diff options
Diffstat (limited to 'src/spu_dec/spudvb_decoder.c')
-rw-r--r-- | src/spu_dec/spudvb_decoder.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/src/spu_dec/spudvb_decoder.c b/src/spu_dec/spudvb_decoder.c index ee4b0142d..6c3909505 100644 --- a/src/spu_dec/spudvb_decoder.c +++ b/src/spu_dec/spudvb_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 the xine project + * Copyright (C) 2008 the xine project * * This file is part of xine, a free video player. * @@ -48,6 +48,7 @@ typedef struct { } page_t; typedef struct { + int version_number; int width, height; int empty; int depth; @@ -170,20 +171,18 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w lprintf( "can't allocate mem for region %d\n", region_id ); return; } - fill_color = 15; fill = 1; } - + if ( fill ) { memset( reg->img, fill_color, region_width*region_height ); reg->empty = 1; #ifdef LOG - printf("SPUDVB : FILL REGION %d\n", region_id); + printf("SPUDVB : FILL REGION %d\n", region_id); #endif } reg->width = region_width; reg->height = region_height; - page->regions[region_id].is_visible = 1; } @@ -438,8 +437,6 @@ static void process_page_composition_segment (dvb_spu_decoder_t * this) { int segment_length; int region_id, region_x, region_y; - int j; - int r; dvbsub_func_t *dvbsub = this->dvbsub; dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; @@ -447,19 +444,22 @@ static void process_page_composition_segment (dvb_spu_decoder_t * this) segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; - j = dvbsub->i + segment_length; + int j = dvbsub->i + segment_length; dvbsub->page.page_time_out = dvbsub->buf[dvbsub->i++]; + if ( dvbsub->page.page_time_out>6 ) /* some timeout are insane, e.g. 65s ! */ + dvbsub->page.page_time_out = 6; - dvbsub->page.page_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + int version = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + if ( version == dvbsub->page.page_version_number ) + return; + dvbsub->page.page_version_number = version; dvbsub->page.page_state = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; dvbsub->i++; - if (dvbsub->page.page_state==2) { - for (r=0; r<MAX_REGIONS; r++) - dvbsub->page.regions[r].is_visible = 0; - } - else if ( dvbsub->page.page_state!=0 && dvbsub->page.page_state!=1 ) { - return; + + int r; + for (r=0; r<MAX_REGIONS; r++) { /* reset */ + dvbsub->page.regions[r].is_visible = 0; } while (dvbsub->i < j) { @@ -472,6 +472,7 @@ static void process_page_composition_segment (dvb_spu_decoder_t * this) dvbsub->page.regions[region_id].x = region_x; dvbsub->page.regions[region_id].y = region_y; + dvbsub->page.regions[region_id].is_visible = 1; } } @@ -512,6 +513,11 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) if(region_id>=MAX_REGIONS) return; + + if ( dvbsub->regions[region_id].version_number == region_version_number ) + return; + + dvbsub->regions[region_id].version_number = region_version_number; /* Check if region size has changed and fill background. */ update_region (this, region_id, region_width, region_height, region_fill_flag, region_4_bit_pixel_code); @@ -561,7 +567,6 @@ static void process_object_data_segment (dvb_spu_decoder_t * this) dvbsub->i += 2; segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; - j = dvbsub->i + segment_length; object_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; @@ -715,6 +720,9 @@ static void draw_subtitles (dvb_spu_decoder_t * this) printf("SPUDVB: this->vpts=%llu\n",this->vpts); #endif for ( r=0; r<MAX_REGIONS; r++ ) { +#ifdef LOG + printf("SPUDVB : region=%d, visible=%d, osd=%d, empty=%d\n", r, this->dvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); +#endif if ( this->dvbsub->page.regions[r].is_visible && this->dvbsub->regions[r].osd && !this->dvbsub->regions[r].empty ) { this->stream->osd_renderer->set_position( this->dvbsub->regions[r].osd, this->dvbsub->page.regions[r].x, this->dvbsub->page.regions[r].y ); this->stream->osd_renderer->show( this->dvbsub->regions[r].osd, this->vpts ); @@ -808,13 +816,15 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) this->vpts = vpts; } + /* completely ignore pts since it makes a lot of problems with various providers */ + this->vpts = 0; + /* process the pes section */ PES_packet_length = this->pes_pkt_size; this->dvbsub->buf = this->pes_pkt; - PES_header_data_length = 0; this->dvbsub->i = 0; data_identifier = this->dvbsub->buf[this->dvbsub->i++]; @@ -860,7 +870,31 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) this->dvbsub->i = new_i; } - return; + /* verify we've the right segment */ + if(this->dvbsub->page.page_id==this->spu_descriptor->comp_page_id) { + /* SEGMENT_DATA_FIELD */ + switch (segment_type) { + case 0x10: + process_page_composition_segment(this); + break; + case 0x11: + process_region_composition_segment(this); + break; + case 0x12: + process_CLUT_definition_segment(this); + break; + case 0x13: + process_object_data_segment (this); + break; + case 0x80: + draw_subtitles( this ); /* Page is now completely rendered */ + break; + default: + return; + break; + } + } + this->dvbsub->i = new_i; } static void spudec_reset (spu_decoder_t * this_gen) @@ -873,7 +907,9 @@ static void spudec_reset (spu_decoder_t * this_gen) for ( i=0; i<MAX_REGIONS; i++ ) { if ( this->dvbsub->regions[i].osd ) this->stream->osd_renderer->hide(this->dvbsub->regions[i].osd, 0); + this->dvbsub->regions[i].version_number = -1; } + this->dvbsub->page.page_version_number = -1; pthread_mutex_unlock(&this->dvbsub_osd_mutex); } @@ -916,12 +952,8 @@ static void spudec_dispose (spu_decoder_t * this_gen) static spu_decoder_t *dvb_spu_class_open_plugin (spu_decoder_class_t * class_gen, xine_stream_t * stream) { - - int i; - dvb_spu_decoder_t *this; - dvb_spu_class_t *class = (dvb_spu_class_t *) class_gen; - - this = calloc(1, sizeof (dvb_spu_decoder_t)); + dvb_spu_decoder_t *this = calloc(1, sizeof (dvb_spu_decoder_t)); + dvb_spu_class_t *class = (dvb_spu_class_t *)class_gen; this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -938,6 +970,7 @@ static spu_decoder_t *dvb_spu_class_open_plugin (spu_decoder_class_t * class_gen this->dvbsub = calloc(1, sizeof (dvbsub_func_t)); + int i; for (i = 0; i < MAX_REGIONS; i++) { this->dvbsub->page.regions[i].is_visible = 0; this->dvbsub->regions[i].img = NULL; |