📄 zvbi.c
字号:
if( (pp_block == NULL) || (*pp_block == NULL) ) return NULL; p_block = *pp_block; *pp_block = NULL; p_pos = p_block->p_buffer; i_left = p_block->i_buffer; while( i_left > 0 ) { vbi_sliced p_sliced[MAX_SLICES]; unsigned int i_lines = 0; int64_t i_pts; i_lines = vbi_dvb_demux_cor( p_sys->p_dvb_demux, p_sliced, MAX_SLICES, &i_pts, &p_pos, &i_left ); if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, i_pts / 90000.0 ); } /* */ vlc_mutex_lock( &p_sys->lock ); const int i_align = p_sys->i_align; const unsigned int i_wanted_page = p_sys->i_wanted_page; const bool b_opaque = p_sys->b_opaque; vlc_mutex_unlock( &p_sys->lock ); /* Try to see if the page we want is in the cache yet */ b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page, vbi_dec2bcd( i_wanted_page ), VBI_ANY_SUBNO, VBI_WST_LEVEL_3p5, 25, FALSE ); if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update ) goto error; if( !b_cached ) { if( p_sys->i_last_page != i_wanted_page ) { /* We need to reset the subtitle */ p_spu = Subpicture( p_dec, &fmt, true, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; p_spu->p_region->psz_text = strdup(""); p_sys->b_update = true; p_sys->i_last_page = i_wanted_page; goto exit; } goto error; } p_sys->b_update = false; p_sys->i_last_page = i_wanted_page;#ifdef ZVBI_DEBUG msg_Dbg( p_dec, "we now have page: %d ready for display", i_wanted_page );#endif /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ p_spu = Subpicture( p_dec, &fmt, p_sys->b_text, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; if( p_sys->b_text ) { unsigned int i_textsize = 7000; int i_total; char p_text[i_textsize+1]; i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, 0, p_page.columns, p_page.rows ); p_text[i_total] = '\0'; /* Strip off the pagenumber */ if( i_total <= 40 ) goto error; p_spu->p_region->psz_text = strdup( &p_text[8] );#ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text );#endif } else { picture_t *p_pic = &p_spu->p_region->picture; /* ZVBI is stupid enough to assume pitch == width */ p_pic->p->i_pitch = 4 * fmt.i_width; vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->picture.p->p_pixels, 1, 1 ); OpaquePage( p_pic, p_page, fmt, b_opaque ); }exit: vbi_unref_page( &p_page ); block_Release( p_block ); return p_spu;error: vbi_unref_page( &p_page ); if( p_spu != NULL ) { p_dec->pf_spu_buffer_del( p_dec, p_spu ); p_spu = NULL; } block_Release( p_block ); return NULL;}static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt, bool b_text, int i_columns, int i_rows, int i_align, mtime_t i_pts ){ video_format_t fmt; subpicture_t *p_spu; /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ p_spu = p_dec->pf_spu_buffer_new( p_dec ); if( !p_spu ) { msg_Warn( p_dec, "can't get spu buffer" ); return NULL; } memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = b_text ? VLC_FOURCC('T','E','X','T') : VLC_FOURCC('R','G','B','A'); fmt.i_aspect = b_text ? 0 : VOUT_ASPECT_FACTOR; if( b_text ) { fmt.i_bits_per_pixel = 0; } else { fmt.i_sar_num = fmt.i_sar_den = 1; fmt.i_width = fmt.i_visible_width = i_columns * 12; fmt.i_height = fmt.i_visible_height = i_rows * 10; fmt.i_bits_per_pixel = 32; } fmt.i_x_offset = fmt.i_y_offset = 0; p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt ); if( p_spu->p_region == NULL ) { msg_Err( p_dec, "cannot allocate SPU region" ); p_dec->pf_spu_buffer_del( p_dec, p_spu ); return NULL; } p_spu->p_region->i_x = 0; p_spu->p_region->i_y = 0; p_spu->p_region->i_align = i_align; /* Normal text subs, easy markup */ p_spu->i_flags = SUBPICTURE_ALIGN_BOTTOM; p_spu->i_start = i_pts; p_spu->i_stop = 0; p_spu->b_ephemer = true; p_spu->b_absolute = false; p_spu->b_pausable = true; if( !b_text ) { p_spu->i_width = p_spu->i_original_picture_width = fmt.i_width; p_spu->i_height = p_spu->i_original_picture_height = fmt.i_height; } /* */ *p_fmt = fmt; return p_spu;}static void EventHandler( vbi_event *ev, void *user_data ){ decoder_t *p_dec = (decoder_t *)user_data; decoder_sys_t *p_sys = p_dec->p_sys; if( ev->type == VBI_EVENT_TTX_PAGE ) {#ifdef ZVBI_DEBUG msg_Info( p_dec, "Page %03x.%02x ", ev->ev.ttx_page.pgno, ev->ev.ttx_page.subno & 0xFF);#endif if( p_sys->i_last_page == vbi_bcd2dec( ev->ev.ttx_page.pgno ) ) p_sys->b_update = true; if( ev->ev.ttx_page.clock_update ) msg_Dbg( p_dec, "clock" );#ifdef ZVBI_DEBUG if( ev->ev.ttx_page.header_update ) msg_Dbg( p_dec, "header" );#endif } else if( ev->type == VBI_EVENT_CAPTION ) msg_Dbg( p_dec, "Caption line: %x", ev->ev.caption.pgno ); else if( ev->type == VBI_EVENT_NETWORK ) msg_Dbg( p_dec, "Network change" ); else if( ev->type == VBI_EVENT_ASPECT ) msg_Dbg( p_dec, "Aspect update" ); else if( ev->type == VBI_EVENT_NETWORK ) msg_Dbg( p_dec, "Program info received" );}static int OpaquePage( picture_t *p_src, const vbi_page p_page, const video_format_t fmt, bool b_opaque ){ unsigned int x, y; assert( fmt.i_chroma == VLC_FOURCC('R','G','B','A' ) ); /* Kludge since zvbi doesn't provide an option to specify opacity. */ for( y = 0; y < fmt.i_height; y++ ) { for( x = 0; x < fmt.i_width; x++ ) { const vbi_opacity opacity = p_page.text[ y/10 * p_page.columns + x/12 ].opacity; uint32_t *p_pixel = (uint32_t*)&p_src->p->p_pixels[y * p_src->p->i_pitch + 4*x]; switch( opacity ) { /* Show video instead of this character */ case VBI_TRANSPARENT_SPACE: *p_pixel = 0; break; /* To make the boxed text "closed captioning" transparent * change true to false. */ case VBI_OPAQUE: if( b_opaque ) break; /* Full text transparency. only foreground color is show */ case VBI_TRANSPARENT_FULL: *p_pixel = 0; break; /* Transparency for boxed text */ case VBI_SEMI_TRANSPARENT: if( (*p_pixel) == 0xff000000 && 0 ) /* Disabled until someone implement borders */ *p_pixel = 0; break; } } } /* end of kludge */ return VLC_SUCCESS;}/* Callbacks */static int RequestPage( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ decoder_sys_t *p_sys = p_data; VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); vlc_mutex_lock( &p_sys->lock ); if( newval.i_int > 0 && newval.i_int < 999 ) p_sys->i_wanted_page = newval.i_int; vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS;}static int Opaque( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ decoder_sys_t *p_sys = p_data; VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); vlc_mutex_lock( &p_sys->lock ); p_sys->b_opaque = newval.b_bool; vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS;}static int Position( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ decoder_sys_t *p_sys = p_data; VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); vlc_mutex_lock( &p_sys->lock ); p_sys->i_align = newval.i_int; vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -