From: Laurent Aimar Date: Wed, 29 Apr 2009 18:24:13 +0000 (+0200) Subject: Ensure that VC1 I frame always have a sequence header and an entry point. X-Git-Tag: 1.0.0-rc1~166 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=70729ba3b48d3999a7d4f44610097be640d8c965;p=vlc Ensure that VC1 I frame always have a sequence header and an entry point. --- diff --git a/modules/packetizer/vc1.c b/modules/packetizer/vc1.c index d5f6c63d7b..c422f7a3dc 100644 --- a/modules/packetizer/vc1.c +++ b/modules/packetizer/vc1.c @@ -84,6 +84,8 @@ struct decoder_sys_t bool b_frame; /* Current frame being built */ + mtime_t i_frame_dts; + mtime_t i_frame_pts; block_t *p_frame; block_t **pp_last; @@ -147,11 +149,14 @@ static int Open( vlc_object_t *p_this ) p_sys->b_entry_point = false; p_sys->ep.p_ep = NULL; + p_sys->i_frame_dts = VLC_TS_INVALID; + p_sys->i_frame_pts = VLC_TS_INVALID; + p_sys->b_frame = false; p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; - p_sys->i_interpolated_dts = -1; + p_sys->i_interpolated_dts = VLC_TS_INVALID; p_sys->b_check_startcode = p_dec->fmt_in.b_packetized; if( p_dec->fmt_out.i_extra > 0 ) @@ -241,7 +246,10 @@ static void PacketizeReset( void *p_private, bool b_broken ) p_sys->pp_last = &p_sys->p_frame; p_sys->b_frame = false; } - p_sys->i_interpolated_dts = 0; + + p_sys->i_frame_dts = VLC_TS_INVALID; + p_sys->i_frame_pts = VLC_TS_INVALID; + p_sys->i_interpolated_dts = VLC_TS_INVALID; } static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block ) { @@ -255,7 +263,7 @@ static int PacketizeValidate( void *p_private, block_t *p_au ) decoder_t *p_dec = p_private; decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->i_interpolated_dts < 0 ) + if( p_sys->i_interpolated_dts <= VLC_TS_INVALID ) { msg_Dbg( p_dec, "need a starting pts/dts" ); return VLC_EGENERIC; @@ -339,27 +347,41 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag ) idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA && idu != IDU_TYPE_END_OF_SEQUENCE ) { + /* Prepend SH and EP on I */ + if( p_sys->p_frame->i_flags & BLOCK_FLAG_TYPE_I ) + { + block_t *p_list = block_Duplicate( p_sys->sh.p_sh ); + block_ChainAppend( &p_list, block_Duplicate( p_sys->ep.p_ep ) ); + block_ChainAppend( &p_list, p_sys->p_frame ); + + p_list->i_flags = p_sys->p_frame->i_flags; + + p_sys->p_frame = p_list; + } + /* */ p_pic = block_ChainGather( p_sys->p_frame ); + p_pic->i_dts = p_sys->i_frame_dts; + p_pic->i_pts = p_sys->i_frame_pts; /* */ - if( p_pic->i_dts > 0 ) + if( p_pic->i_dts > VLC_TS_INVALID ) p_sys->i_interpolated_dts = p_pic->i_dts; /* We can interpolate dts/pts only if we have a frame rate */ if( p_dec->fmt_out.video.i_frame_rate != 0 && p_dec->fmt_out.video.i_frame_rate_base != 0 ) { - if( p_sys->i_interpolated_dts > 0 ) + if( p_sys->i_interpolated_dts > VLC_TS_INVALID ) p_sys->i_interpolated_dts += INT64_C(1000000) * p_dec->fmt_out.video.i_frame_rate_base / p_dec->fmt_out.video.i_frame_rate; //msg_Dbg( p_dec, "-------------- XXX0 dts=%"PRId64" pts=%"PRId64" interpolated=%"PRId64, // p_pic->i_dts, p_pic->i_pts, p_sys->i_interpolated_dts ); - if( p_pic->i_dts <= 0 ) + if( p_pic->i_dts <= VLC_TS_INVALID ) p_pic->i_dts = p_sys->i_interpolated_dts; - if( p_pic->i_pts <= 0 ) + if( p_pic->i_pts <= VLC_TS_INVALID ) { if( !p_sys->sh.b_has_bframe || (p_pic->i_flags & BLOCK_FLAG_TYPE_B ) ) p_pic->i_pts = p_pic->i_dts; @@ -371,22 +393,26 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag ) /* Reset context */ p_sys->b_frame = false; + p_sys->i_frame_dts = VLC_TS_INVALID; + p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; } /* */ - if( p_sys->p_frame ) + if( p_sys->i_frame_dts <= VLC_TS_INVALID && p_sys->i_frame_pts <= VLC_TS_INVALID ) { - block_t *p_frame = p_sys->p_frame; - if( p_frame->i_dts <= 0 && p_frame->i_pts <= 0 ) - { - p_frame->i_dts = p_frag->i_dts; - p_frame->i_pts = p_frag->i_pts; - *pb_used_ts = true; - } + p_sys->i_frame_dts = p_frag->i_dts; + p_sys->i_frame_pts = p_frag->i_pts; + *pb_used_ts = true; } - block_ChainLastAppend( &p_sys->pp_last, p_frag ); + + /* We will add back SH and EP on I frames */ + block_t *p_release = NULL; + if( idu != IDU_TYPE_SEQUENCE_HEADER && idu != IDU_TYPE_ENTRY_POINT ) + block_ChainLastAppend( &p_sys->pp_last, p_frag ); + else + p_release = p_frag; /* Parse IDU */ if( idu == IDU_TYPE_SEQUENCE_HEADER ) @@ -648,6 +674,9 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag ) } p_sys->b_frame = true; } + + if( p_release ) + block_Release( p_release ); return p_pic; }