📄 dvbsub.c
字号:
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 if( p_sys->p_page ) msg_Dbg( p_dec, "rendering %i regions", p_sys->p_page->i_region_defs );#endif for( i = 0; p_sys->p_page && i < p_sys->p_page->i_region_defs; i++ ) { dvbsub_region_t *p_region; dvbsub_regiondef_t *p_regiondef; dvbsub_clut_t *p_clut; dvbsub_color_t *p_color; subpicture_region_t *p_spu_region; uint8_t *p_src, *p_dst; video_format_t fmt; int i_pitch; i_timeout = p_sys->p_page->i_timeout; p_regiondef = &p_sys->p_page->p_region_defs[i];#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "rendering region %i (%i,%i)", i, p_regiondef->i_x, p_regiondef->i_y );#endif /* Find associated region */ for( p_region = p_sys->p_regions; p_region != NULL; p_region = p_region->p_next ) { if( p_regiondef->i_id == p_region->i_id ) break; } if( !p_region ) { msg_Dbg( p_dec, "region %i not found", p_regiondef->i_id ); continue; } /* Find associated CLUT */ for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next ) { if( p_region->i_clut == p_clut->i_id ) break; } if( !p_clut ) { msg_Dbg( p_dec, "clut %i not found", p_region->i_clut ); continue; } /* Create new SPU region */ memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = VLC_FOURCC('Y','U','V','P'); fmt.i_aspect = 0; /* 0 means use aspect ratio of background video */ fmt.i_width = fmt.i_visible_width = p_region->i_width; fmt.i_height = fmt.i_visible_height = p_region->i_height; fmt.i_x_offset = fmt.i_y_offset = 0; p_spu_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt ); if( !p_spu_region ) { msg_Err( p_dec, "cannot allocate SPU region" ); continue; } p_spu_region->i_x = p_regiondef->i_x; p_spu_region->i_y = p_regiondef->i_y; *pp_spu_region = p_spu_region; pp_spu_region = &p_spu_region->p_next; /* Build palette */ fmt.p_palette->i_entries = p_region->i_depth == 1 ? 4 : p_region->i_depth == 2 ? 16 : 256; p_color = (p_region->i_depth == 1) ? p_clut->c_2b : (p_region->i_depth == 2) ? p_clut->c_4b : p_clut->c_8b; for( j = 0; j < fmt.p_palette->i_entries; j++ ) { fmt.p_palette->palette[j][0] = p_color[j].Y; fmt.p_palette->palette[j][1] = p_color[j].Cb; /* U == Cb */ fmt.p_palette->palette[j][2] = p_color[j].Cr; /* V == Cr */ fmt.p_palette->palette[j][3] = 0xff - p_color[j].T; } p_src = p_region->p_pixbuf; p_dst = p_spu_region->picture.Y_PIXELS; i_pitch = p_spu_region->picture.Y_PITCH; /* Copy pixel buffer */ for( j = 0; j < p_region->i_height; j++ ) { memcpy( p_dst, p_src, p_region->i_width ); p_src += p_region->i_width; p_dst += i_pitch; } /* Check subtitles encoded as strings of characters * (since there are not rendered in the pixbuffer) */ for( j = 0; j < p_region->i_object_defs; j++ ) { dvbsub_objectdef_t *p_object_def = &p_region->p_object_defs[j]; if( p_object_def->i_type != 1 || !p_object_def->psz_text ) continue; /* Create new SPU region */ memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = VLC_FOURCC('T','E','X','T'); fmt.i_aspect = VOUT_ASPECT_FACTOR; fmt.i_width = fmt.i_visible_width = p_region->i_width; fmt.i_height = fmt.i_visible_height = p_region->i_height; fmt.i_x_offset = fmt.i_y_offset = 0; p_spu_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt ); if( !p_region ) { msg_Err( p_dec, "cannot allocate SPU region" ); continue; } p_spu_region->psz_text = strdup( p_object_def->psz_text ); p_spu_region->i_x = p_regiondef->i_x + p_object_def->i_x; p_spu_region->i_y = p_regiondef->i_y + p_object_def->i_y; *pp_spu_region = p_spu_region; pp_spu_region = &p_spu_region->p_next; } } /* Set the pf_render callback */ p_spu->i_start = p_sys->i_pts; p_spu->i_stop = p_spu->i_start + (mtime_t) (i_timeout * 1000000); p_spu->b_ephemer = VLC_TRUE; p_spu->b_fade = VLC_TRUE; /* Correct positioning of SPU */ p_spu->b_absolute = p_sys->b_absolute; p_spu->i_flags = p_sys->i_spu_position; p_spu->i_x = p_sys->i_spu_x; p_spu->i_y = p_sys->i_spu_y; p_spu->i_original_picture_width = 720; p_spu->i_original_picture_height = 576; return p_spu;}/***************************************************************************** * encoder_sys_t : encoder descriptor *****************************************************************************/typedef struct encoder_region_t{ int i_width; int i_height;} encoder_region_t;struct encoder_sys_t{ unsigned int i_page_ver; unsigned int i_region_ver; unsigned int i_clut_ver; int i_regions; encoder_region_t *p_regions; mtime_t i_pts; /* subpicture positioning */ int i_offset_x; int i_offset_y;};static void encode_page_composition( encoder_t *, bs_t *, subpicture_t * );static void encode_clut( encoder_t *, bs_t *, subpicture_t * );static void encode_region_composition( encoder_t *, bs_t *, subpicture_t * );static void encode_object( encoder_t *, bs_t *, subpicture_t * );/***************************************************************************** * OpenEncoder: probe the encoder and return score *****************************************************************************/static int OpenEncoder( vlc_object_t *p_this ){ encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys; vlc_value_t val; if( p_enc->fmt_out.i_codec != VLC_FOURCC('d','v','b','s') && !p_enc->b_force ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL ) { msg_Err( p_enc, "out of memory" ); return VLC_ENOMEM; } p_enc->p_sys = p_sys; p_enc->pf_encode_sub = Encode; p_enc->fmt_out.i_codec = VLC_FOURCC('d','v','b','s'); p_enc->fmt_out.subs.dvb.i_id = 1 << 16 | 1; sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); p_sys->i_page_ver = 0; p_sys->i_region_ver = 0; p_sys->i_clut_ver = 0; p_sys->i_regions = 0; p_sys->p_regions = 0; var_Create( p_this, ENC_CFG_PREFIX "x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_this, ENC_CFG_PREFIX "x", &val ); p_sys->i_offset_x = val.i_int; var_Create( p_this, ENC_CFG_PREFIX "y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_this, ENC_CFG_PREFIX "y", &val ); p_sys->i_offset_y = val.i_int; return VLC_SUCCESS;}/* FIXME: this routine is a hack to convert VLC_FOURCC('Y','U','V','A') * into VLC_FOURCC('Y','U','V','P') */static subpicture_t *YuvaYuvp( encoder_t *p_enc, subpicture_t *p_subpic ){ subpicture_region_t *p_region = NULL; if( !p_subpic ) return NULL; for( p_region = p_subpic->p_region; p_region; p_region = p_region->p_next ) { video_format_t *p_fmt = &p_region->fmt; int i = 0, j = 0, n = 0, p = 0; int i_max_entries = 256;#ifdef RANDOM_DITHERING int i_seed = 0xdeadbeef; /* random seed */#else int *pi_delta;#endif int i_pixels = p_region->picture.p[0].i_visible_lines * p_region->picture.p[0].i_pitch; int i_iterator = p_region->picture.p[0].i_visible_lines * 3 / 4 * p_region->picture.p[0].i_pitch + p_region->picture.p[0].i_pitch * 1 / 3; int i_tolerance = 0;#if DEBUG_DVBSUB msg_Dbg( p_enc, "YuvaYuvp: i_pixels=%d, i_iterator=%d", i_pixels, i_iterator );#endif p_fmt->i_chroma = VLC_FOURCC('Y','U','V','P'); p_fmt->p_palette = (video_palette_t *) malloc( sizeof( video_palette_t ) ); if( !p_fmt->p_palette ) break; p_fmt->p_palette->i_entries = 0; /* Find best iterator using Euclide’s algorithm */ for( ; i_iterator > 1 ; i_iterator-- ) { int a = i_pixels; int b = i_iterator; int c; while( b ) { c = a % b; a = b; b = c; } if( a == 1 ) { break; } } /* Count colors, build best palette */ for( i_tolerance = 0; i_tolerance < 128; i_tolerance++ ) { vlc_bool_t b_success = VLC_TRUE; p_fmt->p_palette->i_entries = 0; for( i = 0; i < i_pixels ; ) { uint8_t y, u, v, a; y = p_region->picture.p[0].p_pixels[i]; u = p_region->picture.p[1].p_pixels[i]; v = p_region->picture.p[2].p_pixels[i]; a = p_region->picture.p[3].p_pixels[i]; for( j = 0; j < p_fmt->p_palette->i_entries; j++ ) { if( abs((int)p_fmt->p_palette->palette[j][0] - (int)y) <= i_tolerance && abs((int)p_fmt->p_palette->palette[j][1] - (int)u) <= i_tolerance && abs((int)p_fmt->p_palette->palette[j][2] - (int)v) <= i_tolerance && abs((int)p_fmt->p_palette->palette[j][3] - (int)a) <= i_tolerance / 2 ) { break; } } if( j == p_fmt->p_palette->i_entries ) { p_fmt->p_palette->palette[j][0] = y; p_fmt->p_palette->palette[j][1] = u; p_fmt->p_palette->palette[j][2] = v; p_fmt->p_palette->palette[j][3] = a; p_fmt->p_palette->i_entries++; } if( p_fmt->p_palette->i_entries >= i_max_entries ) { b_success = VLC_FALSE; break; } i += i_iterator; if( i > i_pixels ) { i -= i_pixels; } } if( b_success ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -