From 0981604c0e13a9856cb3e0dea6a0ffd19fa635b6 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Mon, 24 Nov 2003 02:35:50 +0000 Subject: [PATCH] * all: ported/cleaned up/renabled dvb subtitle decoder. But it is untested. (I have no sample at all) --- configure.ac | 4 +- include/vlc_es.h | 7 +- modules/codec/Modules.am | 1 + modules/codec/dvbsub.c | 1102 +++++++++++++++++++------------------- src/input/input_dec.c | 28 +- 5 files changed, 564 insertions(+), 578 deletions(-) diff --git a/configure.ac b/configure.ac index 193c6816e7..d4a6513f7b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Autoconf settings for vlc -dnl $Id: configure.ac,v 1.119 2003/11/23 18:40:09 fenrir Exp $ +dnl $Id: configure.ac,v 1.120 2003/11/24 02:35:50 fenrir Exp $ AC_INIT(vlc,0.6.3-cvs) @@ -867,7 +867,7 @@ dnl default modules dnl AX_ADD_PLUGINS([dummy rc logger gestures memcpy hotkeys]) AX_ADD_PLUGINS([mpgv mpga m4v mpeg_system ps ts avi asf aac mp4 rawdv]) -AX_ADD_PLUGINS([spudec mpeg_audio lpcm a52 dts cinepak]) +AX_ADD_PLUGINS([spudec dvbsub mpeg_audio lpcm a52 dts cinepak]) AX_ADD_PLUGINS([deinterlace invert adjust wall transform distort clone crop motionblur]) AX_ADD_PLUGINS([float32tos16 float32tos8 float32tou16 float32tou8 a52tospdif dtstospdif fixed32tofloat32 fixed32tos16 s16tofixed32 s16tofloat32 s16tofloat32swab s8tofloat32 u8tofixed32 u8tofloat32]) AX_ADD_PLUGINS([trivial_resampler ugly_resampler linear_resampler bandlimited_resampler]) diff --git a/include/vlc_es.h b/include/vlc_es.h index b204c07612..740fa25075 100644 --- a/include/vlc_es.h +++ b/include/vlc_es.h @@ -2,7 +2,7 @@ * vlc_es.h ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: vlc_es.h,v 1.4 2003/11/24 00:39:00 fenrir Exp $ + * $Id: vlc_es.h,v 1.5 2003/11/24 02:35:50 fenrir Exp $ * * Authors: Laurent Aimar * @@ -92,6 +92,11 @@ struct subs_format_t /* FIXME */ uint32_t palette[16+1]; } spu; + + struct + { + int i_id; + } dvb; }; /** diff --git a/modules/codec/Modules.am b/modules/codec/Modules.am index db1a327735..297363f985 100644 --- a/modules/codec/Modules.am +++ b/modules/codec/Modules.am @@ -16,3 +16,4 @@ SOURCES_rawvideo = rawvideo.c SOURCES_quicktime = quicktime.c SOURCES_subsdec = subsdec.c SOURCES_faad = faad.c +SOURCES_dvbsub = dvbsub.c diff --git a/modules/codec/dvbsub.c b/modules/codec/dvbsub.c index 1b8ff2bc65..6c2b3b47a0 100644 --- a/modules/codec/dvbsub.c +++ b/modules/codec/dvbsub.c @@ -3,9 +3,10 @@ ***************************************************************************** * 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 + * Laurent Aimar * * 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 @@ -185,6 +186,10 @@ typedef struct 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; @@ -202,9 +207,10 @@ struct subpicture_sys_t struct decoder_sys_t { vout_thread_t *p_vout; - mtime_t i_pts; bs_t bs; + + dvbsub_all_t dvbsub; }; @@ -238,36 +244,10 @@ static void Decode ( decoder_t *, block_t ** ); 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 * ); /***************************************************************************** @@ -286,11 +266,12 @@ static int Open( vlc_object_t *p_this ) 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' ) ); @@ -313,86 +294,73 @@ static void Close( vlc_object_t *p_this ) { 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 */ @@ -418,416 +386,414 @@ static vout_thread_t *FindVout( decoder_t *p_dec ) } } -/***************************************************************************** - * 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; kbit_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; kbit_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; kp_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; kp_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_lengthbit_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"); @@ -847,23 +813,28 @@ static dvbsub_image_t* dvbsub_parse_pdata ( dvbsub_thread_t* p_spudec, 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)); @@ -872,97 +843,90 @@ static void add_rle_code (dvbsub_image_t* p, uint16_t num, uint8_t color) 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) @@ -1021,7 +985,10 @@ static void free_objects (dvbsub_object_t* p_o) } } -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) { @@ -1050,53 +1017,10 @@ static void free_all ( dvbsub_all_t* p_a ) 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; @@ -1162,8 +1086,8 @@ static void RenderYUY2 ( vout_thread_t *p_vout, picture_t *p_pic, } -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; @@ -1224,12 +1148,59 @@ static void RenderI42x ( vout_thread_t *p_vout, picture_t *p_pic, } } +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; @@ -1240,88 +1211,91 @@ static void dvbsub_render( dvbsub_thread_t *p_dec, dvbsub_all_t* dvbsub) 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++; + } } } + diff --git a/src/input/input_dec.c b/src/input/input_dec.c index 6cea6ab5fd..042aaa1bea 100644 --- a/src/input/input_dec.c +++ b/src/input/input_dec.c @@ -2,7 +2,7 @@ * input_dec.c: Functions for the management of decoders ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: input_dec.c,v 1.76 2003/11/24 00:39:02 fenrir Exp $ + * $Id: input_dec.c,v 1.77 2003/11/24 02:35:50 fenrir Exp $ * * Authors: Christophe Massiot * Gildas Bazin @@ -407,17 +407,25 @@ static decoder_t * CreateDecoder( input_thread_t * p_input, p_dec->fmt_in.video.i_width = p_bih->biWidth; p_dec->fmt_in.video.i_height = p_bih->biHeight; } + /* FIXME * - 1: beurk - * - 2: I'm not sure there isn't any endian problem here ... */ - if( p_es->i_cat == SPU_ES && - ( p_es->i_fourcc == VLC_FOURCC( 's', 'p', 'u', ' ' ) || - p_es->i_fourcc == VLC_FOURCC( 's', 'p', 'u', 'b' ) ) && - p_es->p_demux_data && - *((uint32_t*)p_es->p_demux_data) == 0xBeef ) + * - 2: I'm not sure there isn't any endian problem here (spu)... */ + if( p_es->i_cat == SPU_ES && p_es->p_demux_data ) { - memcpy( p_dec->fmt_in.subs.spu.palette, - p_es->p_demux_data, 17 * 4 ); + if( ( p_es->i_fourcc == VLC_FOURCC( 's', 'p', 'u', ' ' ) || + p_es->i_fourcc == VLC_FOURCC( 's', 'p', 'u', 'b' ) ) && + *((uint32_t*)p_es->p_demux_data) == 0xBeef ) + { + memcpy( p_dec->fmt_in.subs.spu.palette, + p_es->p_demux_data, 17 * 4 ); + } + else if( p_es->i_fourcc == VLC_FOURCC( 'd', 'v', 'b', 's' ) ) + { + dvb_spuinfo_t *p_dvbs = (dvb_spuinfo_t*)p_es->p_demux_data; + + p_dec->fmt_in.subs.dvb.i_id = p_dvbs->i_id; + } } p_dec->fmt_in.i_cat = p_es->i_cat; @@ -464,8 +472,6 @@ static int DecoderThread( decoder_t * p_dec ) /* The decoder's main loop */ while( !p_dec->b_die && !p_dec->b_error ) { - int i_size; - if( ( p_block = block_FifoGet( p_dec->p_owner->p_fifo ) ) == NULL ) { p_dec->b_error = 1; -- 2.39.2