📄 dvbsub.c
字号:
i_id = bs_read( s, 16 ); i_version = bs_read( s, 4 ); i_coding_method = bs_read( s, 2 ); if( i_coding_method > 1 ) { msg_Dbg( p_dec, "DVB subtitling method is not handled!" ); bs_skip( s, 8 * (i_segment_length - 2) - 6 ); return; } /* Check if the object needs to be rendered in at least one * of the regions */ for( p_region = p_sys->p_regions; p_region != NULL; p_region = p_region->p_next ) { for( i = 0; i < p_region->i_object_defs; i++ ) if( p_region->p_object_defs[i].i_id == i_id ) break; if( i != p_region->i_object_defs ) break; } if( !p_region ) { bs_skip( s, 8 * (i_segment_length - 2) - 6 ); return; }#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "new object: %i", i_id );#endif b_non_modify_color = bs_read( s, 1 ); bs_skip( s, 1 ); /* Reserved */ if( i_coding_method == 0x00 ) { int i_topfield, i_bottomfield; uint8_t *p_topfield, *p_bottomfield; i_topfield = bs_read( s, 16 ); i_bottomfield = bs_read( s, 16 ); p_topfield = s->p_start + bs_pos( s ) / 8; p_bottomfield = p_topfield + i_topfield; bs_skip( s, 8 * (i_segment_length - 7) ); /* Sanity check */ if( i_segment_length < i_topfield + i_bottomfield + 7 || p_topfield + i_topfield + i_bottomfield > s->p_end ) { msg_Dbg( p_dec, "corrupted object data" ); return; } for( p_region = p_sys->p_regions; p_region != NULL; p_region = p_region->p_next ) { for( i = 0; i < p_region->i_object_defs; i++ ) { if( p_region->p_object_defs[i].i_id != i_id ) continue; dvbsub_render_pdata( p_dec, p_region, p_region->p_object_defs[i].i_x, p_region->p_object_defs[i].i_y, p_topfield, i_topfield ); if( i_bottomfield ) { dvbsub_render_pdata( p_dec, p_region, p_region->p_object_defs[i].i_x, p_region->p_object_defs[i].i_y + 1, p_bottomfield, i_bottomfield ); } else { /* Duplicate the top field */ dvbsub_render_pdata( p_dec, p_region, p_region->p_object_defs[i].i_x, p_region->p_object_defs[i].i_y + 1, p_topfield, i_topfield ); } } } } else { /* DVB subtitling as characters */ int i_number_of_codes = bs_read( s, 8 ); uint8_t* p_start = s->p_start + bs_pos( s ) / 8; /* Sanity check */ if( i_segment_length < i_number_of_codes*2 + 4 || p_start + i_number_of_codes*2 > s->p_end ) { msg_Dbg( p_dec, "corrupted object data" ); return; } for( p_region = p_sys->p_regions; p_region != NULL; p_region = p_region->p_next ) { for( i = 0; i < p_region->i_object_defs; i++ ) { int j; if( p_region->p_object_defs[i].i_id != i_id ) continue; p_region->p_object_defs[i].psz_text = realloc( p_region->p_object_defs[i].psz_text, i_number_of_codes + 1 ); for( j = 0; j < i_number_of_codes; j++ ) { p_region->p_object_defs[i].psz_text[j] = bs_read( s, 16 ); } p_region->p_object_defs[i].psz_text[j] = 0; } } }#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "end object: %i", i_id );#endif}static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region, int i_x, int i_y, uint8_t *p_field, int i_field ){ uint8_t *p_pixbuf; int i_offset = 0; bs_t bs; /* Sanity check */ if( !p_region->p_pixbuf ) { msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id ); return; } if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height || i_x >= p_region->i_width ) { msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y ); return; } p_pixbuf = p_region->p_pixbuf + i_y * p_region->i_width; bs_init( &bs, p_field, i_field ); while( !bs_eof( &bs ) ) { /* Sanity check */ if( i_y >= p_region->i_height ) return; switch( bs_read( &bs, 8 ) ) { case 0x10: dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x, &i_offset ); break; case 0x11: dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x, &i_offset ); break; case 0x12: dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x, &i_offset ); break; case 0x20: case 0x21: case 0x22: /* We don't use map tables */ break; case 0xf0: /* End of line code */ p_pixbuf += 2*p_region->i_width; i_offset = 0; i_y += 2; break; } }}static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ){ vlc_bool_t b_stop = 0; while( !b_stop && !bs_eof( s ) ) { int i_count = 0, i_color = 0; if( (i_color = bs_read( s, 2 )) != 0x00 ) { i_count = 1; } else { if( bs_read( s, 1 ) == 0x01 ) // Switch1 { i_count = 3 + bs_read( s, 3 ); i_color = bs_read( s, 2 ); } else { if( bs_read( s, 1 ) == 0x00 ) //Switch2 { switch( bs_read( s, 2 ) ) //Switch3 { case 0x00: b_stop = 1; break; case 0x01: i_count = 2; break; case 0x02: i_count = 12 + bs_read( s, 4 ); i_color = bs_read( s, 2 ); break; case 0x03: i_count = 29 + bs_read( s, 8 ); i_color = bs_read( s, 2 ); break; default: break; } } else { /* 1 pixel color 0 */ i_count = 1; } } } if( !i_count ) continue; /* Sanity check */ if( i_count + *pi_off > i_width ) break; if( i_count == 1 ) p[*pi_off] = i_color; else memset( p + *pi_off, i_color, i_count ); (*pi_off) += i_count; } bs_align( s );}static void dvbsub_pdata4bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ){ vlc_bool_t b_stop = 0; while( !b_stop && !bs_eof( s ) ) { int i_count = 0, i_color = 0; if( (i_color = bs_read( s, 4 )) != 0x00 ) { /* Add 1 pixel */ i_count = 1; } else { if( bs_read( s, 1 ) == 0x00 ) // Switch1 { if( bs_show( s, 3 ) != 0x00 ) { i_count = 2 + bs_read( s, 3 ); } else { bs_skip( s, 3 ); b_stop = 1; } } else { if( bs_read( s, 1 ) == 0x00) //Switch2 { i_count = 4 + bs_read( s, 2 ); i_color = bs_read( s, 4 ); } else { switch ( bs_read( s, 2 ) ) //Switch3 { case 0x0: i_count = 1; break; case 0x1: i_count = 2; break; case 0x2: i_count = 9 + bs_read( s, 4 ); i_color = bs_read( s, 4 ); break; case 0x3: i_count= 25 + bs_read( s, 8 ); i_color = bs_read( s, 4 ); break; } } } } if( !i_count ) continue; /* Sanity check */ if( i_count + *pi_off > i_width ) break; if( i_count == 1 ) p[*pi_off] = i_color; else memset( p + *pi_off, i_color, i_count ); (*pi_off) += i_count; } bs_align( s );}static void dvbsub_pdata8bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ){ vlc_bool_t b_stop = 0; while( !b_stop && !bs_eof( s ) ) { int i_count = 0, i_color = 0; if( (i_color = bs_read( s, 8 )) != 0x00 ) { /* Add 1 pixel */ i_count = 1; } else { if( bs_read( s, 1 ) == 0x00 ) // Switch1 { if( bs_show( s, 7 ) != 0x00 ) { i_count = bs_read( s, 7 ); } else { bs_skip( s, 7 ); b_stop = 1; } } else { i_count = bs_read( s, 7 ); i_color = bs_read( s, 8 ); } } if( !i_count ) continue; /* Sanity check */ if( i_count + *pi_off > i_width ) break; if( i_count == 1 ) p[*pi_off] = i_color; else memset( p + *pi_off, i_color, i_count ); (*pi_off) += i_count; } bs_align( s );}static void free_all( decoder_t *p_dec ){ decoder_sys_t *p_sys = p_dec->p_sys; dvbsub_region_t *p_reg, *p_reg_next; dvbsub_clut_t *p_clut, *p_clut_next; for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut_next ) { p_clut_next = p_clut->p_next; free( p_clut ); } p_sys->p_cluts = NULL; for( p_reg = p_sys->p_regions; p_reg != NULL; p_reg = p_reg_next ) { int i; p_reg_next = p_reg->p_next; for( i = 0; i < p_reg->i_object_defs; i++ ) if( p_reg->p_object_defs[i].psz_text ) free( p_reg->p_object_defs[i].psz_text ); if( p_reg->i_object_defs ) free( p_reg->p_object_defs ); if( p_reg->p_pixbuf ) free( p_reg->p_pixbuf ); free( p_reg ); } p_sys->p_regions = NULL; if( p_sys->p_page ) { if( p_sys->p_page->i_region_defs ) free( p_sys->p_page->p_region_defs ); free( p_sys->p_page ); } p_sys->p_page = NULL;}static subpicture_t *render( decoder_t *p_dec ){ decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu; subpicture_region_t **pp_spu_region; int i, j, i_timeout = 0; /* Allocate the subpicture internal data. */ p_spu = p_dec->pf_spu_buffer_new( p_dec ); if( !p_spu ) return NULL; pp_spu_region = &p_spu->p_region; /* Loop on region definitions */#ifdef DEBUG_DVBSUB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -