📄 dvbsub.c
字号:
} 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_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) ); 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->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) ); } p_sys->p_page->i_version = i_version; p_sys->p_page->i_timeout = i_timeout; p_sys->b_page = VLC_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) ); 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; vlc_bool_t 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; } /* Check version number */ if( p_region && p_region->i_version == i_version ) { bs_skip( s, 8 * (i_segment_length - 1) - 4 ); return; } if( !p_region ) {#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "new region: %i", i_id );#endif p_region = *pp_region = malloc( sizeof(dvbsub_region_t) ); memset( p_region, 0, sizeof(dvbsub_region_t) ); p_region->p_object_defs = NULL; p_region->p_pixbuf = NULL; p_region->p_next = NULL; } /* Region attributes */ p_region->i_id = i_id; p_region->i_version = i_version; b_fill = bs_read( s, 1 ); bs_skip( s, 3 ); /* Reserved */ i_width = bs_read( s, 16 ); i_height = bs_read( s, 16 ); i_level_comp = bs_read( s, 3 ); i_depth = bs_read( s, 3 ); bs_skip( s, 2 ); /* Reserved */ i_clut = bs_read( s, 8 ); i_8_bg = bs_read( s, 8 ); i_4_bg = bs_read( s, 4 ); i_2_bg = bs_read( s, 2 ); bs_skip( s, 2 ); /* Reserved */ /* Free old object defs */ while( p_region->i_object_defs ) { int i = p_region->i_object_defs - 1; if( p_region->p_object_defs[i].psz_text ) free( p_region->p_object_defs[i].psz_text ); if( !i ) free( p_region->p_object_defs ); p_region->i_object_defs--; } p_region->p_object_defs = NULL; /* Extra sanity checks */ if( p_region->i_width != i_width || p_region->i_height != i_height ) { if( p_region->p_pixbuf ) { msg_Dbg( p_dec, "region size changed (not allowed)" ); free( p_region->p_pixbuf ); } p_region->p_pixbuf = malloc( i_height * i_width ); p_region->i_depth = 0; b_fill = VLC_TRUE; } if( p_region->i_depth && (p_region->i_depth != i_depth || p_region->i_level_comp != i_level_comp || p_region->i_clut != i_clut) ) { msg_Dbg( p_dec, "region parameters changed (not allowed)" ); } /* Erase background of region */ if( b_fill ) { int i_background = (p_region->i_depth == 1) ? i_2_bg : (p_region->i_depth == 2) ? i_4_bg : i_8_bg; memset( p_region->p_pixbuf, i_background, i_width * i_height ); } p_region->i_width = i_width; p_region->i_height = i_height; p_region->i_level_comp = i_level_comp; p_region->i_depth = i_depth; p_region->i_clut = i_clut; /* List of objects in the region */ i_processed_length = 10; while( i_processed_length < i_segment_length ) { dvbsub_objectdef_t *p_obj; /* We create a new object */ p_region->i_object_defs++; p_region->p_object_defs = realloc( p_region->p_object_defs, sizeof(dvbsub_objectdef_t) * p_region->i_object_defs ); /* We parse object properties */ p_obj = &p_region->p_object_defs[p_region->i_object_defs - 1]; p_obj->i_id = bs_read( s, 16 ); p_obj->i_type = bs_read( s, 2 ); bs_skip( s, 2 ); /* Provider */ p_obj->i_x = bs_read( s, 12 ); bs_skip( s, 4 ); /* Reserved */ p_obj->i_y = bs_read( s, 12 ); p_obj->psz_text = 0; 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; } }}static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int, uint8_t *, int );static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * );static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * );static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * );static void decode_object( decoder_t *p_dec, bs_t *s ){ decoder_sys_t *p_sys = p_dec->p_sys; dvbsub_region_t *p_region; int i_segment_length, i_coding_method, i_version, i_id, i; vlc_bool_t b_non_modify_color; i_segment_length = bs_read( s, 16 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -