*****************************************************************************
* Copyright (C) 2003 ANEVIA
* Copyright (C) 2003 VideoLAN
- * $Id: dvbsub.c,v 1.5 2003/11/24 00:39:01 fenrir Exp $
+ * $Id: dvbsub.c,v 1.6 2003/11/24 02:35:50 fenrir Exp $
*
* Authors: Damien LUCAS <damien.lucas@anevia.com>
+ * Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
typedef struct
{
+ int i_id;
+
+ mtime_t i_pts;
+
dvbsub_clut_t* p_clut[0xff];
dvbsub_page_t* p_page;
dvbsub_object_t* p_objects;
struct decoder_sys_t
{
vout_thread_t *p_vout;
- mtime_t i_pts;
bs_t bs;
+
+ dvbsub_all_t dvbsub;
};
static vout_thread_t *FindVout( decoder_t * );
-static void RenderI42x( vout_thread_t *, picture_t *, const subpicture_t *,
- vlc_bool_t );
-static void RenderYUY2( vout_thread_t *, picture_t *, const subpicture_t *,
- vlc_bool_t );
-static void dvbsub_clut_add_entry ( dvbsub_clut_t* clut, uint8_t type,
- uint8_t id, uint8_t y, uint8_t cr,
- uint8_t cb, uint8_t t);
-static void dvbsub_add_objectdef_to_region ( dvbsub_objectdef_t* p_obj,
- dvbsub_region_t* p_region );
-static dvbsub_image_t* dvbsub_parse_pdata ( dvbsub_thread_t* ,uint16_t );
-static uint16_t dvbsub_count0x11(dvbsub_thread_t* p_spudec,
- uint16_t* p,
- dvbsub_image_t* p_image);
-static void dvbsub_decode_segment ( dvbsub_thread_t *, dvbsub_all_t* );
-static void dvbsub_decode_page_composition ( dvbsub_thread_t *, dvbsub_all_t* );
-static void dvbsub_decode_region_composition ( dvbsub_thread_t*, dvbsub_all_t*);
-static void dvbsub_decode_object ( dvbsub_thread_t*, dvbsub_all_t* );
-static vlc_bool_t dvbsub_check_page ( dvbsub_all_t* );
-static void dvbsub_render ( dvbsub_thread_t *p_spudec,dvbsub_all_t* );
-static int dvbsub_parse ( dvbsub_thread_t *p_spudec, dvbsub_all_t* dvbsub );
-static void dvbsub_decode_clut ( dvbsub_thread_t*, dvbsub_all_t*);
-static void dvbsub_stop_display ( dvbsub_thread_t* p_dec, dvbsub_all_t* dvbsub);
-
-static void free_image (dvbsub_image_t* p_i);
-static void free_object (dvbsub_object_t* p_o);
-static void free_regions (dvbsub_region_t* p_r, uint8_t nb);
-static void free_objects (dvbsub_object_t* p_o);
-static void free_clut ( dvbsub_clut_t* p_c);
-static void free_page (dvbsub_page_t* p_p);
-static void free_all ( dvbsub_all_t* p_a );
+static int dvbsub_init( dvbsub_all_t *, int );
+static void dvbsub_decode_segment( dvbsub_all_t *p_dvbsub, bs_t *s );
+static void dvbsub_render( dvbsub_all_t *, vout_thread_t * );
+static void dvbsub_clean( dvbsub_all_t * );
/*****************************************************************************
return VLC_EGENERIC;
}
- p_dec->pf_decode_subs = Decode;
+ p_dec->pf_decode_sub = Decode;
p_sys = p_dec->p_sys = malloc( sizeof( decoder_sys_t ) );
p_sys->p_vout = NULL;
- p_sys->i_pts = 0;
+
+ dvbsub_init( &p_sys->dvbsub, p_dec->fmt_in.subs.dvb.i_id );
es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'd','v','b','s' ) );
{
p_subpic = &p_sys->p_vout->p_subpicture[i_subpic];
if( p_subpic != NULL &&
- ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
- || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
+ ( ( p_subpic->i_status == RESERVED_SUBPICTURE ) ||
+ ( p_subpic->i_status == READY_SUBPICTURE ) ) )
{
vout_DestroySubPicture( p_sys->p_vout, p_subpic );
}
}
}
- trox_call();
+ dvbsub_clean( &p_sys->dvbsub );
+
+ free( p_sys );
}
/*****************************************************************************
- * RunDecoder: this function is called just after the thread is created
+ * Decode:
*****************************************************************************/
-static int RunDecoder( decoder_fifo_t * p_fifo )
+static void Decode( decoder_t *p_dec, block_t **pp_block )
{
- dvbsub_thread_t * p_dvbsubdec;
-// vout_thread_t * p_vout_backup = NULL;
- dvbsub_all_t dvbsub;
- unsigned int k;
- /* Allocate the memory needed to store the thread's structure */
- p_dvbsubdec = (dvbsub_thread_t *)trox_malloc( sizeof(dvbsub_thread_t) );
- if ( p_dvbsubdec == NULL )
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ block_t *p_block;
+
+ if( pp_block == NULL || *pp_block == NULL )
{
- msg_Err( p_fifo, "out of memory" );
- DecoderError( p_fifo );
- return( -1 );
+ return;
}
- /*
- * Initialize the thread properties
- */
- p_dvbsubdec->p_vout = NULL;
- p_dvbsubdec->p_fifo = p_fifo;
- /*
- * Initialize thread and free configuration
- */
- p_dvbsubdec->p_fifo->b_error = InitThread( p_dvbsubdec );
- dvbsub.p_page=NULL;
- dvbsub.p_objects=NULL;
- for(k=0; k<0xff; k++) dvbsub.p_clut[k] = NULL;
- for(k=0; k<16; k++) dvbsub.p_spu[k] = NULL;
-
- /*
- * Main loop - it is not executed if an error occured during
- * initialization
- */
- while( (!p_dvbsubdec->p_fifo->b_die) && (!p_dvbsubdec->p_fifo->b_error) )
+ p_block = *pp_block;
+ *pp_block = NULL;
+
+ p_sys->dvbsub.i_pts = p_block->i_pts;
+ if( p_sys->dvbsub.i_pts <= 0 )
{
- dvbsub_parse( p_dvbsubdec, &dvbsub );
- p_dvbsubdec->p_vout = FindVout( p_dvbsubdec );
- if( p_dvbsubdec->p_vout )
+ msg_Warn( p_dec, "non dated subtitle" );
+ block_Release( p_block );
+ return;
+ }
+
+ if( ( p_sys->p_vout = FindVout( p_dec ) ) )
+ {
+ int i_data_identifier;
+ int i_subtitle_stream_id;
+ int i_end_data_marker;
+
+ bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer );
+
+ i_data_identifier = bs_read( &p_sys->bs, 8 );
+ i_subtitle_stream_id = bs_read( &p_sys->bs, 8 );
+
+ for( ;; )
{
- // Check if the page is to be displayed
- if(dvbsub_check_page(&dvbsub))
+ if( bs_show( &p_sys->bs, 8 ) != 0x0f )
{
- dvbsub_render(p_dvbsubdec, &dvbsub);
+ break;
}
- vlc_object_release( p_dvbsubdec->p_vout );
+ dvbsub_decode_segment( &p_sys->dvbsub, &p_sys->bs );
}
+ i_end_data_marker = bs_read( &p_sys->bs, 8 );
+
+ /* Check if the page is to be displayed */
+ if( p_sys->dvbsub.p_page && p_sys->dvbsub.p_objects )
+ {
+ dvbsub_render( &p_sys->dvbsub, p_sys->p_vout );
+ }
+
+ vlc_object_release( p_sys->p_vout );
}
- // Free all structures
- //dvbsub.p_objects=NULL;
- //for(k=0; k<16; k++)
- // if(dvbsub.p_spu[k] != NULL)
- // dvbsub.p_spu[k]->p_sys->b_obsolete = 1;
-
- /*
- * Error loop
- */
- if( p_dvbsubdec->p_fifo->b_error )
- {
- DecoderError( p_dvbsubdec->p_fifo );
- /* End of thread */
- EndThread( p_dvbsubdec, &dvbsub );
- return -1;
- }
- /* End of thread */
- EndThread( p_dvbsubdec, &dvbsub );
- free_all(&dvbsub);
- return 0;
+
+ block_Release( p_block );
}
/* following functions are local */
}
}
-/*****************************************************************************
- * EndThread: thread destruction
- *****************************************************************************
- * This function is called when the thread ends after a sucessful
- * initialization.
- *****************************************************************************/
-static void EndThread( dvbsub_thread_t *p_dvbsubdec, dvbsub_all_t* p_dvbsub )
+
+static int dvbsub_init( dvbsub_all_t *p_dvbsub, int i_id )
{
- if( p_dvbsubdec->p_vout != NULL
- && p_dvbsubdec->p_vout->p_subpicture != NULL )
+ int i;
+
+ memset( p_dvbsub, 0, sizeof( dvbsub_all_t ) );
+
+ p_dvbsub->i_pts = 0;
+ p_dvbsub->i_id = i_id;
+ p_dvbsub->p_page = NULL;
+ p_dvbsub->p_objects = NULL;
+ for( i = 0; i < 255; i++ )
{
- subpicture_t * p_subpic;
- int i_subpic;
- for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
- {
- p_subpic = &p_dvbsubdec->p_vout->p_subpicture[i_subpic];
- if( p_subpic != NULL &&
- ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
- || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
- {
- vout_DestroySubPicture( p_dvbsubdec->p_vout, p_subpic );
- }
- }
+ p_dvbsub->p_clut[i] = NULL;
+ }
+ for( i = 0; i < 16; i++ )
+ {
+ p_dvbsub->p_spu[i] = NULL;
}
- CloseBitstream( &p_dvbsubdec->bit_stream );
- trox_free( p_dvbsubdec );
- trox_call();
+ return 0;
}
+static void free_all( dvbsub_all_t * );
-static int dvbsub_parse ( dvbsub_thread_t *p_spudec,
- dvbsub_all_t* dvbsub )
+static void dvbsub_clean( dvbsub_all_t *p_dvbsub )
{
- unsigned int data_identifier;
- unsigned int subtitle_stream_id;
- unsigned int nextbits;
- uint32_t end_data_marker;
- /* Re-align the buffer on an 8-bit boundary */
- RealignBits( &p_spudec->bit_stream );
- data_identifier = GetBits( &p_spudec->bit_stream, 8 );
- subtitle_stream_id = GetBits( &p_spudec->bit_stream, 8 );
- nextbits = ShowBits( &p_spudec->bit_stream, 8 );
- while(nextbits == 0x0f )
- {
- dvbsub_decode_segment( p_spudec, dvbsub );
- nextbits = ShowBits( &p_spudec->bit_stream, 8 );
- }
- end_data_marker = GetBits( &p_spudec->bit_stream, 8 );
- return 0;
+ free_all( p_dvbsub );
+ trox_call() ;
}
+static void dvbsub_decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s );
+static void dvbsub_decode_page_composition( dvbsub_all_t *p_dvbsub, bs_t *s);
+static void dvbsub_decode_region_composition( dvbsub_all_t *p_dvbsub, bs_t *s );
+static void dvbsub_stop_display( dvbsub_all_t* p_dvbsub );
+static void dvbsub_decode_object( dvbsub_all_t *p_dvbsub, bs_t *s );
-static void dvbsub_decode_segment ( dvbsub_thread_t * p_spudec,
- dvbsub_all_t * dvbsub )
+static void free_page (dvbsub_page_t* p_p);
+
+static void dvbsub_decode_segment( dvbsub_all_t *p_dvbspu, bs_t *s )
{
- unsigned int sync_byte;
- unsigned int segment_type;
- uint16_t page_id;
- uint16_t segment_length;
- int k;
- sync_byte = GetBits( &p_spudec->bit_stream, 8 );
- segment_type = GetBits( &p_spudec->bit_stream, 8 );
- page_id = GetBits( &p_spudec->bit_stream, 16 );
- segment_length = ShowBits( &p_spudec->bit_stream, 16 );
- if( page_id != ((dvb_spuinfo_t*)p_spudec->p_fifo->p_spuinfo)->i_id )
+ int i_type;
+ int i_page_id;
+ int i_size;
+
+ /* sync_byte */
+ bs_skip( s, 8 );
+
+ /* segment type */
+ i_type = bs_read( s, 8 );
+
+ /* page id */
+ i_page_id = bs_read( s, 16 );
+
+ /* segment size */
+ i_size = bs_show( s, 16 );
+
+ if( i_page_id != p_dvbspu->i_id )
{
- //TODO should use GetChunk
- for(k=0; k<segment_length+2; k++) GetBits( &p_spudec->bit_stream, 8 );
+ bs_skip( s, 8 * ( 2 + i_size ) );
return;
}
- switch( segment_type )
+
+ switch( i_type )
{
case DVBSUB_ST_CLUT_DEFINITION:
- dvbsub_decode_clut ( p_spudec, dvbsub );
+ dvbsub_decode_clut( p_dvbspu, s );
break;
case DVBSUB_ST_PAGE_COMPOSITION:
- dvbsub_decode_page_composition ( p_spudec, dvbsub );
+ dvbsub_decode_page_composition( p_dvbspu, s );
break;
case DVBSUB_ST_REGION_COMPOSITION:
- dvbsub_decode_region_composition ( p_spudec, dvbsub );
+ dvbsub_decode_region_composition( p_dvbspu, s );
break;
case DVBSUB_ST_OBJECT_DATA:
- dvbsub_decode_object ( p_spudec, dvbsub );
+ dvbsub_decode_object( p_dvbspu, s );
break;
case DVBSUB_ST_ENDOFDISPLAY:
- dvbsub_stop_display ( p_spudec, dvbsub);
+ dvbsub_stop_display( p_dvbspu );
break;
case DVBSUB_ST_STUFFING:
default:
- fprintf(stderr, "*** DVBSUB - Unsupported segment type ! (%04x)\n",
- segment_type );
- GetBits( &p_spudec->bit_stream, 16 );
- for(k=0; k<segment_length; k++)
- GetBits( &p_spudec->bit_stream, 8 );
+ fprintf( stderr, "*** DVBSUB - Unsupported segment type ! (%04x)",
+ i_type );
+ bs_skip( s, 8 * ( 2 + i_size ) );
break;
}
- return;
-}
-
-
-static void dvbsub_decode_page_composition (dvbsub_thread_t *p_spudec,
- dvbsub_all_t *dvbsub)
-{
- unsigned int i_version_number;
- unsigned int i_state;
- unsigned int i_segment_length;
- uint8_t i_timeout;
- unsigned int k;
- i_segment_length = GetBits( &p_spudec->bit_stream, 16 );
- //A page is composed by one or more region:
- i_timeout = GetBits( &p_spudec->bit_stream, 8 );
- i_version_number = GetBits( &p_spudec->bit_stream, 4 );
- i_state = GetBits( &p_spudec->bit_stream, 2 );
- // TODO We assume it is a new page (i_state)
- if (dvbsub->p_page) free_page(dvbsub->p_page);
-
- GetBits( &p_spudec->bit_stream, 2 ); /* Reserved */
- //Allocate a new page
- dvbsub->p_page = trox_malloc (sizeof(dvbsub_page_t));
- dvbsub->p_page->i_timeout = i_timeout;
- // Number of regions:
- dvbsub->p_page->i_regions_number = (i_segment_length-2) / 6;
-
-/* Special workaround for CAVENA encoders
- * a page with no regions is sent instead of a 0x80 packet (End Of Display) */
- if( dvbsub->p_page->i_regions_number == 0 )
- {
- dvbsub_stop_display(p_spudec, dvbsub );
- }
-/* /Special workaround */
-
- dvbsub->p_page->regions =
- trox_malloc(dvbsub->p_page->i_regions_number*sizeof(dvbsub_region_t));
- for(k=0; k<dvbsub->p_page->i_regions_number ; k++)
- {
- dvbsub->p_page->regions[k].i_id = GetBits( &p_spudec->bit_stream, 8 );
- GetBits( &p_spudec->bit_stream, 8 ); /* Reserved */
- dvbsub->p_page->regions[k].i_x = GetBits( &p_spudec->bit_stream, 16 );
- dvbsub->p_page->regions[k].i_y = GetBits( &p_spudec->bit_stream, 16 );
- dvbsub->p_page->regions[k].p_object = NULL;
- }
}
-
-static void dvbsub_decode_region_composition (dvbsub_thread_t *p_spudec,
- dvbsub_all_t *dvbsub)
+static void dvbsub_stop_display( dvbsub_all_t *p_dvbsub )
{
- unsigned int i_segment_length;
- unsigned int i_processed_length;
- unsigned int i_region_id;
- dvbsub_region_t* p_region;
- unsigned int k;
- p_region = NULL;
- i_segment_length = GetBits( &p_spudec->bit_stream, 16 );
- // Get region id:
- i_region_id = GetBits( &p_spudec->bit_stream, 8 );
- for(k=0; k<dvbsub->p_page->i_regions_number; k++)
- {
- if ( dvbsub->p_page->regions[k].i_id == i_region_id )
- p_region = &(dvbsub->p_page->regions[k]);
- }
- if(p_region == NULL)
- {
- // TODO
- // The region has never been declared before
- // Internal error
- fprintf (stderr, "Decoding of undeclared region N/A...\n");
- return;
- }
- // Skip version number and fill flag
- if (ShowBits( &p_spudec->bit_stream, 4 ) == p_region->i_version_number)
- {
- fprintf(stderr, "Skipping already known region N/A ...\n");
- // TODO Skip the right number of bits
- }
- // Region attributes
- p_region->i_version_number = GetBits( &p_spudec->bit_stream, 4 );
- p_region->b_fill = GetBits( &p_spudec->bit_stream, 1 );
- GetBits( &p_spudec->bit_stream, 3 ); /* Reserved */
- p_region->i_width = GetBits( &p_spudec->bit_stream, 16 );
- p_region->i_height = GetBits( &p_spudec->bit_stream, 16 );
- p_region->i_level_comp = GetBits( &p_spudec->bit_stream, 3 );
- p_region->i_depth = GetBits( &p_spudec->bit_stream, 3 );
- GetBits( &p_spudec->bit_stream, 2 ); /* Reserved */
- p_region->i_clut = GetBits( &p_spudec->bit_stream, 8 );
- p_region->i_8bp_code = GetBits( &p_spudec->bit_stream, 8 );
- p_region->i_4bp_code = GetBits( &p_spudec->bit_stream, 4 );
- p_region->i_2bp_code = GetBits( &p_spudec->bit_stream, 2 );
- GetBits( &p_spudec->bit_stream, 2 ); /* Reserved */
- // List of objects in the region:
- // We already skipped 10 bytes
- i_processed_length = 10;
- while ( i_processed_length < i_segment_length )
- {
- // We create a new object
- dvbsub_objectdef_t* p_obj;
- p_obj = trox_malloc(sizeof(dvbsub_objectdef_t));
- // We parse object properties
- p_obj->i_id = GetBits( &p_spudec->bit_stream, 16 );
- p_obj->i_type = GetBits( &p_spudec->bit_stream, 2 );
- p_obj->i_provider = GetBits( &p_spudec->bit_stream, 2 );
- p_obj->i_xoffset = GetBits( &p_spudec->bit_stream, 12 );
- GetBits( &p_spudec->bit_stream, 4 ); /* Reserved */
- p_obj->i_yoffset = GetBits( &p_spudec->bit_stream, 12 );
- i_processed_length += 6;
- if ( p_obj->i_type == DVBSUB_OT_BASIC_CHAR
- || p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING )
- {
- p_obj->i_fg_pc = GetBits( &p_spudec->bit_stream, 8 );
- p_obj->i_bg_pc = GetBits( &p_spudec->bit_stream, 8 );
- i_processed_length += 2;
- }
- p_obj->p_next = NULL;
- dvbsub_add_objectdef_to_region(p_obj, p_region);
- }
-}
+ int i;
-
-static void dvbsub_decode_object (dvbsub_thread_t* p_spudec,
- dvbsub_all_t* dvbsub)
-{
- dvbsub_object_t* p_obj;
- dvbsub_object_t* p_o;
- uint16_t i_segment_length;
- uint16_t i_topfield_length;
- uint16_t i_bottomfield_length;
- // Memory Allocation
- p_obj = trox_malloc ( sizeof ( dvbsub_object_t ) );
- p_obj->p_next=NULL;
- i_segment_length = GetBits( &p_spudec->bit_stream, 16 );
- p_obj->i_id = GetBits( &p_spudec->bit_stream, 16 );
- p_obj->i_version_number = GetBits( &p_spudec->bit_stream, 4 );
- // TODO Check we don't already have this object / this version
- p_obj->i_coding_method = GetBits( &p_spudec->bit_stream, 2 );
- p_obj->b_non_modify_color = GetBits( &p_spudec->bit_stream, 1 );
- GetBits( &p_spudec->bit_stream, 1 ); /* Reserved */
- if(p_obj->i_coding_method == 0x00)
- {
- i_topfield_length = GetBits( &p_spudec->bit_stream, 16 );
- i_bottomfield_length = GetBits( &p_spudec->bit_stream, 16 );
- p_obj->topfield = dvbsub_parse_pdata (p_spudec, i_topfield_length);
- p_obj->bottomfield =
- dvbsub_parse_pdata (p_spudec, i_bottomfield_length);
- }
- else
+ for( i = 0; p_dvbsub->p_spu[i] != NULL; i++ )
{
- GetBits(&p_spudec->bit_stream, (i_segment_length -3) *8);
- //TODO
- // DVB subtitling as characters
+ p_dvbsub->p_spu[i]->i_stop = p_dvbsub->i_pts;
}
- // Add this object to the list of the page
- p_o = dvbsub->p_objects;
- dvbsub->p_objects = p_obj;
- p_obj->p_next = p_o;
- return;
}
-static void dvbsub_stop_display ( dvbsub_thread_t* p_dec,
- dvbsub_all_t* dvbsub)
-{
- unsigned int j;
-
- for(j = 0; dvbsub->p_spu[j] != NULL; j++)
- dvbsub->p_spu[j]->i_stop = p_dec->bit_stream.p_pes->i_pts;
- return;
-}
-
-static void dvbsub_decode_clut ( dvbsub_thread_t* p_dec,
- dvbsub_all_t* dvbsub)
+static void dvbsub_decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s )
{
uint16_t i_segment_length;
uint16_t i_processed_length;
- uint8_t i_entry_id;
- uint8_t i_entry_type;
dvbsub_clut_t* clut;
uint8_t i_clut_id;
uint8_t i_version_number;
- uint8_t y;
- uint8_t cr;
- uint8_t cb;
- uint8_t t;
- i_segment_length = GetBits( &p_dec->bit_stream, 16 );
- i_clut_id = GetBits( &p_dec->bit_stream, 8 );
- i_version_number = GetBits( &p_dec->bit_stream, 4 );
+
+ i_segment_length = bs_read( s, 16 );
+ i_clut_id = bs_read( s, 8 );
+ i_version_number = bs_read( s, 4 );
+
// Check that this id doesn't not already exist
// with the same version number
// And allocate memory if necessary
- if( dvbsub->p_clut[i_clut_id] != NULL)
+ if( p_dvbsub->p_clut[i_clut_id] != NULL)
{
- if ( dvbsub->p_clut[i_clut_id]->i_version_number == i_version_number )
+ if( p_dvbsub->p_clut[i_clut_id]->i_version_number == i_version_number )
{
//TODO skip the right number of bits
return;
}
else
{
- memset(dvbsub->p_clut[i_clut_id], 0, sizeof(dvbsub_clut_t));
+ memset( p_dvbsub->p_clut[i_clut_id], 0, sizeof(dvbsub_clut_t) );
}
}
else
{
- dvbsub->p_clut[i_clut_id] = trox_malloc(sizeof(dvbsub_clut_t));
+ p_dvbsub->p_clut[i_clut_id] = trox_malloc( sizeof(dvbsub_clut_t) );
}
- clut = dvbsub->p_clut[i_clut_id];
+ clut = p_dvbsub->p_clut[i_clut_id];
+
/* We don't have this version of the CLUT:
* Parse it */
clut->i_version_number = i_version_number;
- GetBits( &p_dec->bit_stream, 4 ); /* Reserved bits */
- i_processed_length=2;
- while(i_processed_length<i_segment_length)
+ bs_skip( s, 4 ); /* Reserved bits */
+ i_processed_length = 2;
+ while( i_processed_length < i_segment_length )
{
- i_entry_id = GetBits( &p_dec->bit_stream, 8 );
- i_entry_type = GetBits( &p_dec->bit_stream, 3 );
- GetBits( &p_dec->bit_stream, 4 );
- if ( GetBits( &p_dec->bit_stream, 1 )==0x01 )
+ uint8_t y, cb, cr, t;
+ uint8_t i_id;
+ uint8_t i_type;
+
+ i_id = bs_read( s, 8 );
+ i_type = bs_read( s, 3 );
+
+ bs_skip( s, 4 );
+
+ if( bs_read( s, 1 ) )
{
- y = GetBits( &p_dec->bit_stream, 8 );
- cr = GetBits( &p_dec->bit_stream, 8 );
- cb = GetBits( &p_dec->bit_stream, 8 );
- t = GetBits( &p_dec->bit_stream, 8 );
- i_processed_length += 6;
+ y = bs_read( s, 8 );
+ cr = bs_read( s, 8 );
+ cb = bs_read( s, 8 );
+ t = bs_read( s, 8 );
+ i_processed_length += 6;
}
else
{
- y = GetBits( &p_dec->bit_stream, 6 );
- cr = GetBits( &p_dec->bit_stream, 4 );
- cb = GetBits( &p_dec->bit_stream, 4 );
- t = GetBits( &p_dec->bit_stream, 2 );
- i_processed_length += 4;
+ y = bs_read( s, 6 );
+ cr = bs_read( s, 4 );
+ cb = bs_read( s, 4 );
+ t = bs_read( s, 2 );
+ i_processed_length += 4;
+ }
+
+ /* According to EN 300-743 section 7.2.3 note 1, type should
+ * not have more than 1 bit set to one
+ But, some strams don't respect this note. */
+
+ if( i_type&0x04)
+ {
+ clut->c_2b[i_id].Y = y;
+ clut->c_2b[i_id].Cr = cr;
+ clut->c_2b[i_id].Cb = cb;
+ clut->c_2b[i_id].T = t;
+ }
+ if( i_type&0x02)
+ {
+ clut->c_4b[i_id].Y = y;
+ clut->c_4b[i_id].Cr = cr;
+ clut->c_4b[i_id].Cb = cb;
+ clut->c_4b[i_id].T = t;
+ }
+ if( i_type & 0x01)
+ {
+ clut->c_8b[i_id].Y = y;
+ clut->c_8b[i_id].Cr = cr;
+ clut->c_8b[i_id].Cb = cb;
+ clut->c_8b[i_id].T = t;
}
- dvbsub_clut_add_entry(clut, i_entry_type, i_entry_id, y, cr, cb, t);
+ }
+}
+
+static void dvbsub_decode_page_composition( dvbsub_all_t *p_dvbsub, bs_t *s )
+{
+ unsigned int i_version_number;
+ unsigned int i_state;
+ unsigned int i_segment_length;
+ uint8_t i_timeout;
+ unsigned int i;
+
+ i_segment_length = bs_read( s, 16 );
+
+ /* A page is composed by one or more region: */
+ i_timeout = bs_read( s, 8 );
+ i_version_number = bs_read( s, 4 );
+ i_state = bs_read( s, 2 );
+
+ /* TODO We assume it is a new page (i_state) */
+ if( p_dvbsub->p_page ) free_page( p_dvbsub->p_page );
+
+ bs_skip( s, 2 ); /* Reserved */
+
+ /* Allocate a new page */
+ p_dvbsub->p_page = trox_malloc( sizeof(dvbsub_page_t) );
+ p_dvbsub->p_page->i_timeout = i_timeout;
+
+ /* Number of regions: */
+ p_dvbsub->p_page->i_regions_number = (i_segment_length-2) / 6;
+
+ /* Special workaround for CAVENA encoders
+ * a page with no regions is sent instead of a 0x80 packet (End Of Display) */
+ if( p_dvbsub->p_page->i_regions_number == 0 )
+ {
+ dvbsub_stop_display( p_dvbsub );
+ }
+ /* /Special workaround */
+
+ p_dvbsub->p_page->regions =
+ trox_malloc(p_dvbsub->p_page->i_regions_number*sizeof(dvbsub_region_t));
+ for( i = 0; i < p_dvbsub->p_page->i_regions_number; i++ )
+ {
+ p_dvbsub->p_page->regions[i].i_id = bs_read( s, 8 );
+ bs_skip( s, 8 ); /* Reserved */
+ p_dvbsub->p_page->regions[i].i_x = bs_read( s, 16 );
+ p_dvbsub->p_page->regions[i].i_y = bs_read( s, 16 );
+ p_dvbsub->p_page->regions[i].p_object = NULL;
}
}
-static void dvbsub_clut_add_entry ( dvbsub_clut_t* clut, uint8_t type,
- uint8_t id, uint8_t y, uint8_t cr,
- uint8_t cb, uint8_t t)
+static void dvbsub_decode_region_composition( dvbsub_all_t *p_dvbsub, bs_t *s )
{
- /* According to EN 300-743 section 7.2.3 note 1, type should
- * not have more than 1 bit set to one
- But, some strams don't respect this note. */
- if( type & 0x04)
+ dvbsub_region_t* p_region = NULL;
+ unsigned int i_segment_length;
+ unsigned int i_processed_length;
+ unsigned int i_region_id;
+ unsigned int i;
+
+ i_segment_length = bs_read( s, 16 );
+
+ /* Get region id: */
+ i_region_id = bs_read( s, 8 );
+ for( i = 0; i < p_dvbsub->p_page->i_regions_number; i++ )
+ {
+ if( p_dvbsub->p_page->regions[i].i_id == i_region_id )
+ {
+ p_region = &(p_dvbsub->p_page->regions[i]);
+ }
+ }
+
+ if( p_region == NULL )
{
- clut->c_2b[id].Y = y;
- clut->c_2b[id].Cr = cr;
- clut->c_2b[id].Cb = cb;
- clut->c_2b[id].T = t;
+ /* TODO
+ * The region has never been declared before
+ * Internal error */
+ fprintf( stderr, "Decoding of undeclared region N/A...\n" );
+ return;
}
- if( type & 0x02)
+
+ /* Skip version number and fill flag */
+ if( bs_show( s, 4 ) == p_region->i_version_number )
{
- clut->c_4b[id].Y = y;
- clut->c_4b[id].Cr = cr;
- clut->c_4b[id].Cb = cb;
- clut->c_4b[id].T = t;
+ fprintf( stderr, "Skipping already known region N/A ...\n" );
+ /* TODO Skip the right number of bits */
}
- if( type & 0x01)
+
+ /* Region attributes */
+ p_region->i_version_number = bs_read( s, 4 );
+ p_region->b_fill = bs_read( s, 1 );
+ bs_skip( s, 3 ); /* Reserved */
+ p_region->i_width = bs_read( s, 16 );
+ p_region->i_height = bs_read( s, 16 );
+ p_region->i_level_comp = bs_read( s, 3 );
+ p_region->i_depth = bs_read( s, 3 );
+ bs_skip( s, 2 ); /* Reserved */
+ p_region->i_clut = bs_read( s, 8 );
+ p_region->i_8bp_code = bs_read( s, 8 );
+ p_region->i_4bp_code = bs_read( s, 4 );
+ p_region->i_2bp_code = bs_read( s, 2 );
+ bs_skip( s, 2 ); /* Reserved */
+
+ /* List of objects in the region: */
+ /* We already skipped 10 bytes */
+
+ i_processed_length = 10;
+ while( i_processed_length < i_segment_length )
{
- clut->c_8b[id].Y = y;
- clut->c_8b[id].Cr = cr;
- clut->c_8b[id].Cb = cb;
- clut->c_8b[id].T = t;
+ /* We create a new object */
+ dvbsub_objectdef_t *p_obj = trox_malloc(sizeof(dvbsub_objectdef_t));
+
+ /* We parse object properties */
+ p_obj->p_next = NULL;
+ p_obj->i_id = bs_read( s, 16 );
+ p_obj->i_type = bs_read( s, 2 );
+ p_obj->i_provider = bs_read( s, 2 );
+ p_obj->i_xoffset = bs_read( s, 12 );
+ bs_skip( s, 4 ); /* Reserved */
+ p_obj->i_yoffset = bs_read( s, 12 );
+
+ i_processed_length += 6;
+
+ if( p_obj->i_type == DVBSUB_OT_BASIC_CHAR ||
+ p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING )
+ {
+ p_obj->i_fg_pc = bs_read( s, 8 );
+ p_obj->i_bg_pc = bs_read( s, 8 );
+ i_processed_length += 2;
+ }
+
+ /* we append it */
+ if( p_region->p_object )
+ {
+ dvbsub_objectdef_t *p_o;
+ for( p_o = p_region->p_object; ; p_o = p_o->p_next )
+ {
+ if( p_o->p_next == NULL )
+ {
+ break;
+ }
+ }
+ p_o->p_next = p_obj;
+ }
+ else
+ {
+ p_region->p_object = p_obj;
+ }
}
- return;
}
+static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s, uint16_t length );
+static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p, dvbsub_image_t* p_image);
-static void dvbsub_add_objectdef_to_region ( dvbsub_objectdef_t* p_obj,
- dvbsub_region_t* p_region )
+static void dvbsub_decode_object( dvbsub_all_t *p_dvbsub, bs_t *s )
{
- dvbsub_objectdef_t* p_o = p_region->p_object;
- // Seek to the last non null element
- if(p_o!=NULL)
+ dvbsub_object_t *p_obj;
+ uint16_t i_segment_length;
+
+ /* Memory Allocation */
+ p_obj = trox_malloc ( sizeof ( dvbsub_object_t ) );
+ p_obj->p_next = NULL;
+
+ i_segment_length = bs_read( s, 16 );
+
+ /* TODO Check we don't already have this object / this version */
+ p_obj->i_id = bs_read( s, 16 );
+ p_obj->i_version_number = bs_read( s, 4 );
+ p_obj->i_coding_method = bs_read( s, 2 );
+ p_obj->b_non_modify_color= bs_read( s, 1 );
+ bs_skip( s, 1 ); /* Reserved */
+
+ if( p_obj->i_coding_method == 0x00 )
{
- for(; p_o->p_next!=NULL; p_o=p_o->p_next);
- p_o->p_next = p_obj;
- p_o->p_next->p_next = NULL;
+ uint16_t i_topfield_length;
+ uint16_t i_bottomfield_length;
+
+ i_topfield_length = bs_read( s, 16 );
+ i_bottomfield_length= bs_read( s, 16 );
+
+ p_obj->topfield = dvbsub_parse_pdata( p_dvbsub, s, i_topfield_length );
+ p_obj->bottomfield = dvbsub_parse_pdata( p_dvbsub, s, i_bottomfield_length );
}
else
{
- p_region->p_object = p_obj;
- p_region->p_object->p_next = NULL;
+ bs_skip( s, (i_segment_length - 3 ) * 8 );
+ /*TODO
+ * DVB subtitling as characters */
}
- return;
-}
+ /* Add this object to the list of the page */
+ p_obj->p_next = p_dvbsub->p_objects;
+ p_dvbsub->p_objects = p_obj;
+}
-static dvbsub_image_t* dvbsub_parse_pdata ( dvbsub_thread_t* p_spudec,
- uint16_t length )
+static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s, uint16_t length )
{
dvbsub_image_t* p_image;
uint16_t i_processed_length=0;
uint16_t i_lines=0;
uint16_t i_cols_last=0;
+
p_image = trox_malloc ( sizeof ( dvbsub_image_t) );
p_image->p_last=NULL;
+
memset(p_image->i_cols, 0, 576*sizeof(uint16_t));
+
/* Let's parse it a first time to determine the size of the buffer */
- while (i_processed_length < length)
+ while( i_processed_length < length)
{
- switch(GetBits( &p_spudec->bit_stream, 8 ))
+ switch( bs_read( s, 8 ) )
{
case 0x10:
fprintf(stderr, "0x10 N/A\n");
break;
case 0x11:
- i_processed_length += 1 + dvbsub_count0x11(p_spudec,
- &(p_image->i_cols[i_lines]),
- p_image);
+ i_processed_length +=
+ 1 + dvbsub_count0x11( s, &(p_image->i_cols[i_lines]),
+ p_image );
break;
case 0x12:
fprintf(stderr, "0x12 N/A\n");
break;
}
}
+
p_image->i_rows = i_lines;
p_image->i_cols[i_lines] = i_cols_last;
- // Check word-aligned bits
- if(ShowBits( &p_spudec->bit_stream, 8 )==0x00)
- GetBits( &p_spudec->bit_stream, 8 );
+
+ /* Check word-aligned bits */
+ if( bs_show( s, 8 ) == 0x00 )
+ {
+ bs_skip( s, 8 );
+ }
+
return p_image;
}
-static void add_rle_code (dvbsub_image_t* p, uint16_t num, uint8_t color)
+static void add_rle_code( dvbsub_image_t *p, uint16_t num, uint8_t color )
{
if(p->p_last != NULL)
{
p->p_last->p_next = trox_malloc (sizeof (dvbsub_rle_t));
p->p_last = p->p_last->p_next;
- }
+ }
else
{
p->p_codes = trox_malloc (sizeof (dvbsub_rle_t));
p->p_last->i_num = num;
p->p_last->i_color_code = color;
p->p_last->p_next = NULL;
- return;
}
-static uint16_t dvbsub_count0x11(dvbsub_thread_t* p_spudec, uint16_t* p, dvbsub_image_t* p_image)
+static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p, dvbsub_image_t* p_image )
{
uint16_t i_processed=0;
vlc_bool_t b_stop=0;
uint16_t i_count = 0;
uint8_t i_color =0;
+
while (!b_stop)
{
- if ( (i_color = GetBits( &p_spudec->bit_stream, 4 )) != 0x00 )
+ if( (i_color = bs_read( s, 4 )) != 0x00 )
{
(*p)++;
i_processed+=4;
- // 1 pixel of color code '0000'
- add_rle_code (p_image, 1, i_color );
+
+ /* 1 pixel of color code '0000' */
+ add_rle_code( p_image, 1, i_color );
}
else
{
- if(GetBits( &p_spudec->bit_stream, 1 ) == 0x00) // Switch1
+ if( bs_read( s, 1 ) == 0x00 ) // Switch1
{
- if( ShowBits( &p_spudec->bit_stream, 3 ) != 0x00 )
+ if( bs_show( s, 3 ) != 0x00 )
{
- i_count = 2 + GetBits( &p_spudec->bit_stream, 3 );
+ i_count = 2 + bs_read( s, 3 );
(*p) += i_count ;
- add_rle_code (p_image, i_count, 0x00);
+ add_rle_code( p_image, i_count, 0x00 );
}
else
{
- GetBits( &p_spudec->bit_stream, 3);
+ bs_skip( s, 3 );
b_stop=1;
}
i_processed += 8;
}
else
{
- if(GetBits( &p_spudec->bit_stream, 1 ) == 0x00) //Switch2
+ if( bs_read( s, 1 ) == 0x00) //Switch2
{
- i_count = 4 + GetBits( &p_spudec->bit_stream, 2 );
- i_color = GetBits( &p_spudec->bit_stream, 4 );
+ i_count = 4 + bs_read( s, 2 );
+ i_color = bs_read( s, 4 );
(*p) += i_count;
i_processed += 12;
- add_rle_code(p_image, i_count, i_color);
+ add_rle_code( p_image, i_count, i_color );
}
else
{
- switch ( GetBits( &p_spudec->bit_stream, 2 ) ) //Switch3
+ switch ( bs_read( s, 2 ) ) //Switch3
{
case 0x0:
(*p)++;
i_processed += 8;
- add_rle_code(p_image, 1, 0x00);
+ add_rle_code( p_image, 1, 0x00 );
break;
case 0x1:
(*p)+=2;
i_processed += 8;
- add_rle_code(p_image, 2, 0x00);
+ add_rle_code( p_image, 2, 0x00 );
break;
case 0x2:
- i_count = 9 + GetBits( &p_spudec->bit_stream, 4 );
- i_color = GetBits( &p_spudec->bit_stream, 4 );
+ i_count = 9 + bs_read( s, 4 );
+ i_color = bs_read( s, 4 );
(*p)+= i_count;
i_processed += 16;
- add_rle_code ( p_image, i_count, i_color );
+ add_rle_code( p_image, i_count, i_color );
break;
case 0x3:
- i_count= 25 + GetBits( &p_spudec->bit_stream, 8 );
- i_color = GetBits( &p_spudec->bit_stream, 4 );
+ i_count= 25 + bs_read( s, 8 );
+ i_color = bs_read( s, 4 );
(*p)+= i_count;
i_processed += 20;
- add_rle_code ( p_image, i_count, i_color );
+ add_rle_code( p_image, i_count, i_color );
break;
}
}
}
}
}
- RealignBits ( &p_spudec->bit_stream );
- return (i_processed+7)/8 ;
-}
-static vlc_bool_t dvbsub_check_page(dvbsub_all_t* dvbsub)
-{
- if(dvbsub->p_page != NULL)
- {
- if(dvbsub->p_objects != NULL)
- return VLC_TRUE;
- }
- return VLC_FALSE;
+ bs_align( s );
+
+ return ( i_processed + 7 ) / 8 ;
}
static void free_image (dvbsub_image_t* p_i)
}
}
-static void free_clut ( dvbsub_clut_t* p_c) { trox_free(p_c); }
+static void free_clut ( dvbsub_clut_t* p_c )
+{
+ trox_free(p_c);
+}
static void free_page (dvbsub_page_t* p_p)
{
for(i=0; i<16; i++) if (p_a->p_spu[i]) free_spu ( p_a->p_spu[i] );
if(p_a->p_page) free_page( p_a->p_page );
free_objects (p_a->p_objects);
-
-}
-
-static void dvbsub_RenderDVBSUB ( vout_thread_t *p_vout, picture_t *p_pic,
- const subpicture_t *p_spu, vlc_bool_t b_crop )
-{
- // If we have changed the language on the fly,
- if(!p_spu->p_sys) return;
-
- if(p_spu->p_sys->b_obsolete) return;
-
- switch (p_vout->output.i_chroma)
- {
- /* I420 target, no scaling */
- case VLC_FOURCC('I','4','2','2'):
- case VLC_FOURCC('I','4','2','0'):
- case VLC_FOURCC('I','Y','U','V'):
- case VLC_FOURCC('Y','V','1','2'):
- // As long as we just use Y info, I422 and YV12 are just equivalent
- // to I420. Remember to change it the day we'll take into account
- // U and V info.
- RenderI42x( p_vout, p_pic, p_spu, VLC_FALSE );
- break;
- /* RV16 target, scaling */
- case VLC_FOURCC('R','V','1','6'):
- fprintf(stderr, "Not implemented chroma ! RV16)\n");
- //RenderRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
- break;
- /* RV32 target, scaling */
- case VLC_FOURCC('R','V','2','4'):
- case VLC_FOURCC('R','V','3','2'):
- fprintf(stderr, "Not implemented chroma ! RV32 \n");
- //RenderRV32( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
- break;
- /* NVidia overlay, no scaling */
- case VLC_FOURCC('Y','U','Y','2'):
- RenderYUY2( p_vout, p_pic, p_spu, VLC_FALSE );
- break;
- default:
- msg_Err( p_vout, "unknown chroma, can't render SPU" );
- break;
- }
}
-
-static void RenderYUY2 ( vout_thread_t *p_vout, picture_t *p_pic,
- const subpicture_t *p_spu, vlc_bool_t b_crop )
+static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
+ const subpicture_t *p_spu )
{
/* Common variables */
uint8_t *p_desty;
}
-static void RenderI42x ( vout_thread_t *p_vout, picture_t *p_pic,
- const subpicture_t *p_spu, vlc_bool_t b_crop )
+static void RenderI42x( vout_thread_t *p_vout, picture_t *p_pic,
+ const subpicture_t *p_spu )
{
/* Common variables */
uint8_t *p_desty;
}
}
+static void dvbsub_RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
+ const subpicture_t *p_spu )
+{
+ /* If we have changed the language on the fly */
+
+ if( p_spu->p_sys == NULL || p_spu->p_sys->b_obsolete )
+ {
+ return;
+ }
+
+ switch( p_vout->output.i_chroma )
+ {
+ /* I420 target, no scaling */
+ case VLC_FOURCC('I','4','2','2'):
+ case VLC_FOURCC('I','4','2','0'):
+ case VLC_FOURCC('I','Y','U','V'):
+ case VLC_FOURCC('Y','V','1','2'):
+ /* As long as we just use Y info, I422 and YV12 are just equivalent
+ * to I420. Remember to change it the day we'll take into account
+ * U and V info. */
+ RenderI42x( p_vout, p_pic, p_spu );
+ break;
+
+ /* RV16 target, scaling */
+ case VLC_FOURCC('R','V','1','6'):
+ fprintf(stderr, "Not implemented chroma ! RV16)\n");
+ /* RenderRV16( p_vout, p_pic, p_spu ); */
+ break;
+
+ /* RV32 target, scaling */
+ case VLC_FOURCC('R','V','2','4'):
+ case VLC_FOURCC('R','V','3','2'):
+ fprintf(stderr, "Not implemented chroma ! RV32 \n");
+ /* RenderRV32( p_vout, p_pic, p_spu ); */
+ break;
+
+ /* NVidia overlay, no scaling */
+ case VLC_FOURCC('Y','U','Y','2'):
+ RenderYUY2( p_vout, p_pic, p_spu );
+ break;
+
+ default:
+ msg_Err( p_vout, "unknown chroma, can't render SPU" );
+ break;
+ }
+}
+
static void dvbsub_Destroy( subpicture_t *p_spu )
{
free_spu( p_spu );
}
-static void dvbsub_render( dvbsub_thread_t *p_dec, dvbsub_all_t* dvbsub)
+static void dvbsub_render( dvbsub_all_t *dvbsub, vout_thread_t *p_vout )
{
dvbsub_region_t* p_region;
dvbsub_objectdef_t* p_objectdef;
dvbsub_rle_t* p_c;
uint8_t i,j;
j=0;
+
/* loop on regions */
- for(i=0; i< dvbsub->p_page->i_regions_number; i++)
+ for( i = 0; i < dvbsub->p_page->i_regions_number; i++ )
{
p_region = &(dvbsub->p_page->regions[i]);
- /* loop on objects */
- for(p_objectdef = p_region->p_object;
- p_objectdef != NULL;
- p_objectdef = p_objectdef->p_next)
- {
- /* Look for the right object */
- p_object = dvbsub->p_objects;
- while((p_object!=NULL) && (p_object->i_id != p_objectdef->i_id))
- {
- p_object = p_object->p_next;
- }
- if(p_object==NULL)
- {
- fprintf(stderr, "Internal DvbSub decoder error\n");
- return;
- }
- /* Allocate the render structure */
- p_render = trox_malloc(sizeof(dvbsub_render_t));
- p_render->i_x = p_region->i_x + p_objectdef->i_xoffset;
- p_render->i_y = p_region->i_y + p_objectdef->i_yoffset;
- p_render->p_rle_top = p_object->topfield;
- p_render->p_rle_bot = p_object->bottomfield;
-
- // if we did not recieved the CLUT yet
- if ( !dvbsub->p_clut[p_region->i_clut] ) return;
-
- /* Compute the color datas according to the appropriate CLUT */
- for(p_c=p_render->p_rle_top->p_codes;p_c->p_next!=NULL; p_c=p_c->p_next)
- {
- //TODO We assume here we are working in 4bp
- p_c->y=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Y;
- p_c->cr=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cr;
- p_c->cb=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cb;
- p_c->t=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].T;
- }
- for(p_c=p_render->p_rle_bot->p_codes;p_c->p_next!=NULL; p_c=p_c->p_next)
+
+ /* loop on objects */
+ for(p_objectdef = p_region->p_object; p_objectdef != NULL; p_objectdef = p_objectdef->p_next )
{
- //TODO We assume here we are working in 4bp
- p_c->y=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Y;
- p_c->cr=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cr;
- p_c->cb=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cb;
- p_c->t=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].T;
- }
+ /* Look for the right object */
+ p_object = dvbsub->p_objects;
+ while((p_object!=NULL) && (p_object->i_id != p_objectdef->i_id))
+ {
+ p_object = p_object->p_next;
+ }
+ if(p_object==NULL)
+ {
+ fprintf(stderr, "Internal DvbSub decoder error\n");
+ return;
+ }
- /* Allocate the subpicture internal data. */
- dvbsub->p_spu[j] = vout_CreateSubPicture( p_dec->p_vout,
- MEMORY_SUBPICTURE );
- if( dvbsub->p_spu[j] == NULL )
- {
- fprintf(stderr, "Unable to allocate memory ... skipping\n");
- return;
- }
- /* Set the pf_render callback */
- dvbsub->p_spu[j]->pf_render = dvbsub_RenderDVBSUB;
- dvbsub->p_spu[j]->p_sys = trox_malloc( sizeof( subpicture_sys_t ));
- dvbsub->p_spu[j]->p_sys->p_data = p_render;
- dvbsub->p_spu[j]->p_sys->b_obsolete=0;
- dvbsub->p_spu[j]->pf_destroy = dvbsub_Destroy;
- dvbsub->p_spu[j]->i_start = p_dec->bit_stream.p_pes->i_pts;
- dvbsub->p_spu[j]->i_stop = dvbsub->p_spu[j]->i_start + dvbsub->p_page->i_timeout*1000000;
- dvbsub->p_spu[j]->b_ephemer = VLC_FALSE;
-
- // At this stage, we have all we need in p_render
- // We need to free the object
- //Remove this object from the list
- p_object_old = p_object;
- if(p_object == dvbsub->p_objects)
- dvbsub->p_objects = p_object->p_next;
- else
- {
- for(p_o = dvbsub->p_objects; p_o->p_next != p_object; p_o=p_o->p_next);
- p_o->p_next = p_object->p_next;
- }
- free_object(p_object_old);
+ /* Allocate the render structure */
+ p_render = trox_malloc(sizeof(dvbsub_render_t));
+ p_render->i_x = p_region->i_x + p_objectdef->i_xoffset;
+ p_render->i_y = p_region->i_y + p_objectdef->i_yoffset;
+ p_render->p_rle_top = p_object->topfield;
+ p_render->p_rle_bot = p_object->bottomfield;
- vout_DisplaySubPicture (p_dec->p_vout, dvbsub->p_spu[j] );
- j++;
- }
+ // if we did not recieved the CLUT yet
+ if ( !dvbsub->p_clut[p_region->i_clut] ) return;
+
+ /* Compute the color datas according to the appropriate CLUT */
+ for(p_c=p_render->p_rle_top->p_codes;p_c->p_next!=NULL; p_c=p_c->p_next)
+ {
+ //TODO We assume here we are working in 4bp
+ p_c->y=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Y;
+ p_c->cr=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cr;
+ p_c->cb=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cb;
+ p_c->t=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].T;
+ }
+ for(p_c=p_render->p_rle_bot->p_codes;p_c->p_next!=NULL; p_c=p_c->p_next)
+ {
+ //TODO We assume here we are working in 4bp
+ p_c->y=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Y;
+ p_c->cr=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cr;
+ p_c->cb=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].Cb;
+ p_c->t=dvbsub->p_clut[p_region->i_clut]->c_4b[p_c->i_color_code].T;
+ }
+
+
+ /* Allocate the subpicture internal data. */
+ dvbsub->p_spu[j] = vout_CreateSubPicture( p_vout, MEMORY_SUBPICTURE );
+ if( dvbsub->p_spu[j] == NULL )
+ {
+ fprintf(stderr, "Unable to allocate memory ... skipping\n");
+ return;
+ }
+ /* Set the pf_render callback */
+ dvbsub->p_spu[j]->pf_render = dvbsub_RenderDVBSUB;
+ dvbsub->p_spu[j]->p_sys = trox_malloc( sizeof( subpicture_sys_t ));
+ dvbsub->p_spu[j]->p_sys->p_data = p_render;
+ dvbsub->p_spu[j]->p_sys->b_obsolete=0;
+ dvbsub->p_spu[j]->pf_destroy = dvbsub_Destroy;
+ dvbsub->p_spu[j]->i_start = dvbsub->i_pts;
+ dvbsub->p_spu[j]->i_stop = dvbsub->p_spu[j]->i_start + dvbsub->p_page->i_timeout*1000000;
+ dvbsub->p_spu[j]->b_ephemer = VLC_FALSE;
+
+ // At this stage, we have all we need in p_render
+ // We need to free the object
+ //Remove this object from the list
+ p_object_old = p_object;
+ if(p_object == dvbsub->p_objects)
+ dvbsub->p_objects = p_object->p_next;
+ else
+ {
+ for(p_o = dvbsub->p_objects; p_o->p_next != p_object; p_o=p_o->p_next);
+ p_o->p_next = p_object->p_next;
+ }
+ free_object(p_object_old);
+
+ vout_DisplaySubPicture( p_vout, dvbsub->p_spu[j] );
+
+ j++;
+ }
}
}
+