📄 dvbsub.c
字号:
} if( bs_read( &p_sys->bs, 8 ) != 0xff ) /* End marker */ { msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" ); block_Release( p_block ); return NULL; } /* Check if the page is to be displayed */ if( p_sys->p_page && p_sys->b_page ) p_spu = render( p_dec ); block_Release( p_block ); return p_spu;}/* following functions are local *//***************************************************************************** * default_clut_init: default clut as defined in EN 300-743 section 10 *****************************************************************************/static void default_clut_init( decoder_t *p_dec ){ decoder_sys_t *p_sys = p_dec->p_sys; uint8_t i;#define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256;#define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256;#define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256; /* 4 entries CLUT */ for( i = 0; i < 4; i++ ) { uint8_t R = 0, G = 0, B = 0, T = 0; if( !(i & 0x2) && !(i & 0x1) ) T = 0xFF; else if( !(i & 0x2) && (i & 0x1) ) R = G = B = 0xFF; else if( (i & 0x2) && !(i & 0x1) ) R = G = B = 0; else R = G = B = 0x7F; p_sys->default_clut.c_2b[i].Y = RGB_TO_Y(R,G,B); p_sys->default_clut.c_2b[i].Cb = RGB_TO_V(R,G,B); p_sys->default_clut.c_2b[i].Cr = RGB_TO_U(R,G,B); p_sys->default_clut.c_2b[i].T = T; } /* 16 entries CLUT */ for( i = 0; i < 16; i++ ) { uint8_t R = 0, G = 0, B = 0, T = 0; if( !(i & 0x8) ) { if( !(i & 0x4) && !(i & 0x2) && !(i & 0x1) ) { T = 0xFF; } else { R = (i & 0x1) ? 0xFF : 0; G = (i & 0x2) ? 0xFF : 0; B = (i & 0x4) ? 0xFF : 0; } } else { R = (i & 0x1) ? 0x7F : 0; G = (i & 0x2) ? 0x7F : 0; B = (i & 0x4) ? 0x7F : 0; } p_sys->default_clut.c_4b[i].Y = RGB_TO_Y(R,G,B); p_sys->default_clut.c_4b[i].Cr = RGB_TO_V(R,G,B); p_sys->default_clut.c_4b[i].Cb = RGB_TO_U(R,G,B); p_sys->default_clut.c_4b[i].T = T; } /* 256 entries CLUT */ memset( p_sys->default_clut.c_8b, 0xFF, 256 * sizeof(dvbsub_color_t) );}static void decode_segment( decoder_t *p_dec, bs_t *s ){ decoder_sys_t *p_sys = p_dec->p_sys; int i_type; int i_page_id; int i_size; /* sync_byte (already checked) */ 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_sys->i_id ) && ( i_page_id != p_sys->i_ancillary_id ) ) {#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "subtitle skipped (page id: %i, %i)", i_page_id, p_sys->i_id );#endif bs_skip( s, 8 * ( 2 + i_size ) ); return; } if( ( p_sys->i_ancillary_id != p_sys->i_id ) && ( i_type == DVBSUB_ST_PAGE_COMPOSITION ) && ( i_page_id == p_sys->i_ancillary_id ) ) {#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "skipped invalid ancillary subtitle packet" );#endif bs_skip( s, 8 * ( 2 + i_size ) ); return; }#ifdef DEBUG_DVBSUB if( i_page_id == p_sys->i_id ) msg_Dbg( p_dec, "segment (id: %i)", i_page_id ); else msg_Dbg( p_dec, "ancillary segment (id: %i)", i_page_id );#endif switch( i_type ) { case DVBSUB_ST_PAGE_COMPOSITION:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "decode_page_composition" );#endif decode_page_composition( p_dec, s ); break; case DVBSUB_ST_REGION_COMPOSITION:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "decode_region_composition" );#endif decode_region_composition( p_dec, s ); break; case DVBSUB_ST_CLUT_DEFINITION:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "decode_clut" );#endif decode_clut( p_dec, s ); break; case DVBSUB_ST_OBJECT_DATA:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "decode_object" );#endif decode_object( p_dec, s ); break; case DVBSUB_ST_DISPLAY_DEFINITION:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "decode_display_definition" );#endif decode_display_definition( p_dec, s ); break; case DVBSUB_ST_ENDOFDISPLAY:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "end of display" );#endif bs_skip( s, 8 * ( 2 + i_size ) ); break; case DVBSUB_ST_STUFFING:#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "skip stuffing" );#endif bs_skip( s, 8 * ( 2 + i_size ) ); break; default: msg_Warn( p_dec, "unsupported segment type: (%04x)", i_type ); bs_skip( s, 8 * ( 2 + i_size ) ); break; }}static void decode_clut( decoder_t *p_dec, bs_t *s ){ decoder_sys_t *p_sys = p_dec->p_sys; uint16_t i_segment_length; uint16_t i_processed_length; dvbsub_clut_t *p_clut, *p_next; int i_id, i_version; i_segment_length = bs_read( s, 16 ); i_id = bs_read( s, 8 ); i_version = bs_read( s, 4 ); /* Check if we already have this clut */ for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next ) { if( p_clut->i_id == i_id ) break; } /* Check version number */ if( p_clut && ( p_clut->i_version == i_version ) ) { /* Nothing to do */ bs_skip( s, 8 * i_segment_length - 12 ); return; } if( !p_clut ) {#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "new clut: %i", i_id );#endif p_clut = malloc( sizeof( dvbsub_clut_t ) ); if( !p_clut ) return; p_clut->p_next = p_sys->p_cluts; p_sys->p_cluts = p_clut; } /* Initialize to default clut */ p_next = p_clut->p_next; *p_clut = p_sys->default_clut; p_clut->p_next = p_next; /* We don't have this version of the CLUT: Parse it */ p_clut->i_version = i_version; p_clut->i_id = i_id; bs_skip( s, 4 ); /* Reserved bits */ i_processed_length = 2; while( i_processed_length < i_segment_length ) { 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 = 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 = bs_read( s, 6 ) << 2; cr = bs_read( s, 4 ) << 4; cb = bs_read( s, 4 ) << 4; t = bs_read( s, 2 ) << 6; i_processed_length += 4; } /* We are not entirely compliant here as full transparency is indicated * with a luma value of zero, not a transparency value of 0xff * (full transparency would actually be 0xff + 1). */ if( y == 0 ) { cr = cb = 0; t = 0xff; } /* According to EN 300-743 section 7.2.3 note 1, type should * not have more than 1 bit set to one, but some streams don't * respect this note. */ if( ( i_type & 0x04 ) && ( i_id < 4 ) ) { p_clut->c_2b[i_id].Y = y; p_clut->c_2b[i_id].Cr = cr; p_clut->c_2b[i_id].Cb = cb; p_clut->c_2b[i_id].T = t; } if( ( i_type & 0x02 ) && ( i_id < 16 ) ) { p_clut->c_4b[i_id].Y = y; p_clut->c_4b[i_id].Cr = cr; p_clut->c_4b[i_id].Cb = cb; p_clut->c_4b[i_id].T = t; } if( i_type & 0x01 ) { p_clut->c_8b[i_id].Y = y; p_clut->c_8b[i_id].Cr = cr; p_clut->c_8b[i_id].Cb = cb; p_clut->c_8b[i_id].T = t; } }}static void decode_page_composition( decoder_t *p_dec, bs_t *s ){ decoder_sys_t *p_sys = p_dec->p_sys; int i_version, i_state, i_segment_length, i_timeout, i; /* A page is composed by 0 or more region */ i_segment_length = bs_read( s, 16 ); i_timeout = bs_read( s, 8 ); i_version = bs_read( s, 4 ); i_state = bs_read( s, 2 ); bs_skip( s, 2 ); /* Reserved */ if( i_state == DVBSUB_PCS_STATE_CHANGE ) { /* End of an epoch, reset decoder buffer */#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "page composition mode change" );#endif free_all( p_dec ); } else if( !p_sys->p_page && ( i_state != DVBSUB_PCS_STATE_ACQUISITION ) && ( i_state != DVBSUB_PCS_STATE_CHANGE ) ) { /* Not a full PCS, we need to wait for one */ msg_Dbg( p_dec, "didn't receive an acquisition page yet" );#if 0 /* Try to start decoding even without an acquisition page */ bs_skip( s, 8 * (i_segment_length - 2) ); return;#endif }#ifdef DEBUG_DVBSUB if( i_state == DVBSUB_PCS_STATE_ACQUISITION ) msg_Dbg( p_dec, "acquisition page composition" );#endif /* Check version number */ if( p_sys->p_page && ( p_sys->p_page->i_version == i_version ) ) { bs_skip( s, 8 * (i_segment_length - 2) ); return; } else if( p_sys->p_page ) { if( p_sys->p_page->i_region_defs ) free( p_sys->p_page->p_region_defs ); p_sys->p_page->p_region_defs = NULL; p_sys->p_page->i_region_defs = 0; } if( !p_sys->p_page ) {#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "new page" );#endif /* Allocate a new page */ p_sys->p_page = malloc( sizeof(dvbsub_page_t) ); if( !p_sys->p_page ) return; } p_sys->p_page->i_version = i_version; p_sys->p_page->i_timeout = i_timeout; p_sys->b_page = true; /* Number of regions */ p_sys->p_page->i_region_defs = (i_segment_length - 2) / 6; if( p_sys->p_page->i_region_defs == 0 ) return; p_sys->p_page->p_region_defs = malloc( p_sys->p_page->i_region_defs * sizeof(dvbsub_region_t) ); if( p_sys->p_page->p_region_defs ) { for( i = 0; i < p_sys->p_page->i_region_defs; i++ ) { p_sys->p_page->p_region_defs[i].i_id = bs_read( s, 8 ); bs_skip( s, 8 ); /* Reserved */ p_sys->p_page->p_region_defs[i].i_x = bs_read( s, 16 ); p_sys->p_page->p_region_defs[i].i_y = bs_read( s, 16 );#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "page_composition, region %i (%i,%i)", i, p_sys->p_page->p_region_defs[i].i_x, p_sys->p_page->p_region_defs[i].i_y );#endif } }}static void decode_region_composition( decoder_t *p_dec, bs_t *s ){ decoder_sys_t *p_sys = p_dec->p_sys; dvbsub_region_t *p_region, **pp_region = &p_sys->p_regions; int i_segment_length, i_processed_length, i_id, i_version; int i_width, i_height, i_level_comp, i_depth, i_clut; int i_8_bg, i_4_bg, i_2_bg; bool b_fill; i_segment_length = bs_read( s, 16 ); i_id = bs_read( s, 8 ); i_version = bs_read( s, 4 ); /* Check if we already have this region */ for( p_region = p_sys->p_regions; p_region != NULL; p_region = p_region->p_next ) { pp_region = &p_region->p_next; if( p_region->i_id == i_id ) break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -