vlc | branch: master | Francois Cartegnie <[email protected]> | Thu Sep 26 11:32:56 2019 +0200| [269fc9bc45d3252d11ebfe445eb98801e9eeb860] | committer: Francois Cartegnie
packetizer: mpegvideo: refactor frame output > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=269fc9bc45d3252d11ebfe445eb98801e9eeb860 --- modules/packetizer/mpegvideo.c | 405 ++++++++++++++++++++++------------------- 1 file changed, 213 insertions(+), 192 deletions(-) diff --git a/modules/packetizer/mpegvideo.c b/modules/packetizer/mpegvideo.c index d449e4204b..547a1d337e 100644 --- a/modules/packetizer/mpegvideo.c +++ b/modules/packetizer/mpegvideo.c @@ -349,6 +349,217 @@ static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc ) return p_cc; } +/***************************************************************************** + * OutputFrame: assemble and tag frame + *****************************************************************************/ +static block_t *OutputFrame( decoder_t *p_dec ) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_pic = NULL; + + if( !p_sys->p_frame ) + return NULL; + + p_pic = block_ChainGather( p_sys->p_frame ); + if( p_pic == NULL ) + { + p_sys->p_frame = NULL; + p_sys->pp_last = &p_sys->p_frame; + p_sys->b_frame_slice = false; + return p_pic; + } + + unsigned i_num_fields; + + if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 /* Field Picture */ ) + i_num_fields = 1; + else + i_num_fields = 2; + + if( p_sys->b_seq_progressive ) + { + if( p_sys->i_top_field_first == 0 && + p_sys->i_repeat_first_field == 1 ) + { + i_num_fields *= 2; + } + else if( p_sys->i_top_field_first == 1 && + p_sys->i_repeat_first_field == 1 ) + { + i_num_fields *= 3; + } + } + else + { + if( p_sys->i_picture_structure == 0x03 /* Frame Picture */ ) + { + if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field ) + { + i_num_fields += 1; + } + } + } + + switch ( p_sys->i_picture_type ) + { + case 0x01: + p_pic->i_flags |= BLOCK_FLAG_TYPE_I; + break; + case 0x02: + p_pic->i_flags |= BLOCK_FLAG_TYPE_P; + break; + case 0x03: + p_pic->i_flags |= BLOCK_FLAG_TYPE_B; + break; + } + + if( !p_sys->b_seq_progressive ) + { + if( p_sys->i_picture_structure < 0x03 ) + { + p_pic->i_flags |= BLOCK_FLAG_SINGLE_FIELD; + p_pic->i_flags |= (p_sys->i_picture_structure == 0x01) ? BLOCK_FLAG_TOP_FIELD_FIRST + : BLOCK_FLAG_BOTTOM_FIELD_FIRST; + } + else /* if( p_sys->i_picture_structure == 0x03 ) */ + { + p_pic->i_flags |= (p_sys->i_top_field_first) ? BLOCK_FLAG_TOP_FIELD_FIRST + : BLOCK_FLAG_BOTTOM_FIELD_FIRST; + } + } + + /* Special case for DVR-MS where we need to fully build pts from scratch + * and only use first dts as it does not monotonically increase + * This will NOT work with frame repeats and such, as we would need to fully + * fill the DPB to get accurate pts timings. */ + if( unlikely( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'D','V','R',' ') ) ) + { + const bool b_first_xmited = (p_sys->i_prev_temporal_ref != p_sys->i_temporal_ref ); + + if( ( p_pic->i_flags & BLOCK_FLAG_TYPE_I ) && b_first_xmited ) + { + if( date_Get( &p_sys->prev_iframe_dts ) == VLC_TICK_INVALID ) + { + if( p_sys->i_dts != VLC_TICK_INVALID ) + { + date_Set( &p_sys->dts, p_sys->i_dts ); + } + else + { + if( date_Get( &p_sys->dts ) == VLC_TICK_INVALID ) + { + date_Set( &p_sys->dts, VLC_TICK_0 ); + } + } + } + p_sys->prev_iframe_dts = p_sys->dts; + } + + p_pic->i_dts = date_Get( &p_sys->dts ); + + /* Compute pts from poc */ + date_t datepts = p_sys->prev_iframe_dts; + date_Increment( &datepts, (1 + p_sys->i_temporal_ref) * 2 ); + + /* Field picture second field case */ + if( p_sys->i_picture_structure != 0x03 ) + { + /* first sent is not the first in display order */ + if( (p_sys->i_picture_structure >> 1) != !p_sys->i_top_field_first && + b_first_xmited ) + { + date_Increment( &datepts, 2 ); + } + } + + p_pic->i_pts = date_Get( &datepts ); + + if( date_Get( &p_sys->dts ) != VLC_TICK_INVALID ) + { + date_Increment( &p_sys->dts, i_num_fields ); + + p_pic->i_length = date_Get( &p_sys->dts ) - p_pic->i_dts; + } + p_sys->i_prev_temporal_ref = p_sys->i_temporal_ref; + } + else /* General case, use demuxer's dts/pts when set or interpolate */ + { + if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 ) + { + /* Trivial case (DTS == PTS) */ + /* Correct interpolated dts when we receive a new pts/dts */ + if( p_sys->i_pts != VLC_TICK_INVALID ) + date_Set( &p_sys->dts, p_sys->i_pts ); + if( p_sys->i_dts != VLC_TICK_INVALID ) + date_Set( &p_sys->dts, p_sys->i_dts ); + } + else + { + /* Correct interpolated dts when we receive a new pts/dts */ + if(p_sys->i_last_ref_pts != VLC_TICK_INVALID && !p_sys->b_second_field) + date_Set( &p_sys->dts, p_sys->i_last_ref_pts ); + if( p_sys->i_dts != VLC_TICK_INVALID ) + date_Set( &p_sys->dts, p_sys->i_dts ); + + if( !p_sys->b_second_field ) + p_sys->i_last_ref_pts = p_sys->i_pts; + } + + p_pic->i_dts = date_Get( &p_sys->dts ); + + /* Set PTS only if we have a B frame or if it comes from the stream */ + if( p_sys->i_pts != VLC_TICK_INVALID ) + { + p_pic->i_pts = p_sys->i_pts; + } + else if( p_sys->i_picture_type == 0x03 ) + { + p_pic->i_pts = p_pic->i_dts; + } + else + { + p_pic->i_pts = VLC_TICK_INVALID; + } + + if( date_Get( &p_sys->dts ) != VLC_TICK_INVALID ) + { + date_Increment( &p_sys->dts, i_num_fields ); + + p_pic->i_length = date_Get( &p_sys->dts ) - p_pic->i_dts; + } + } + +#if 0 + msg_Dbg( p_dec, "pic: type=%d ref=%d nf=%d tff=%d dts=%"PRId64" ptsdiff=%"PRId64" len=%"PRId64, + p_sys->i_picture_structure, p_sys->i_temporal_ref, i_num_fields, + p_sys->i_top_field_first, + p_pic->i_dts , (p_pic->i_pts != VLC_TICK_INVALID) ? p_pic->i_pts - p_pic->i_dts : 0, p_pic->i_length ); +#endif + + + /* Reset context */ + p_sys->p_frame = NULL; + p_sys->pp_last = &p_sys->p_frame; + p_sys->b_frame_slice = false; + + if( p_sys->i_picture_structure != 0x03 ) + { + p_sys->b_second_field = !p_sys->b_second_field; + } + else + { + p_sys->b_second_field = 0; + } + + /* CC */ + p_sys->b_cc_reset = true; + p_sys->i_cc_pts = p_pic->i_pts; + p_sys->i_cc_dts = p_pic->i_dts; + p_sys->i_cc_flags = p_pic->i_flags & BLOCK_FLAG_TYPE_MASK; + + return p_pic; +} + /***************************************************************************** * Helpers: *****************************************************************************/ @@ -461,200 +672,10 @@ static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag ) p_frag = NULL; } - p_pic = block_ChainGather( p_sys->p_frame ); - if( p_pic == NULL ) - return p_pic; + p_pic = OutputFrame( p_dec ); - if( b_eos ) + if( p_pic && b_eos ) p_pic->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE; - - unsigned i_num_fields; - - if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 /* Field Picture */ ) - i_num_fields = 1; - else - i_num_fields = 2; - - if( p_sys->b_seq_progressive ) - { - if( p_sys->i_top_field_first == 0 && - p_sys->i_repeat_first_field == 1 ) - { - i_num_fields *= 2; - } - else if( p_sys->i_top_field_first == 1 && - p_sys->i_repeat_first_field == 1 ) - { - i_num_fields *= 3; - } - } - else - { - if( p_sys->i_picture_structure == 0x03 /* Frame Picture */ ) - { - if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field ) - { - i_num_fields += 1; - } - } - } - - switch ( p_sys->i_picture_type ) - { - case 0x01: - p_pic->i_flags |= BLOCK_FLAG_TYPE_I; - break; - case 0x02: - p_pic->i_flags |= BLOCK_FLAG_TYPE_P; - break; - case 0x03: - p_pic->i_flags |= BLOCK_FLAG_TYPE_B; - break; - } - - if( !p_sys->b_seq_progressive ) - { - if( p_sys->i_picture_structure < 0x03 ) - { - p_pic->i_flags |= BLOCK_FLAG_SINGLE_FIELD; - p_pic->i_flags |= (p_sys->i_picture_structure == 0x01) ? BLOCK_FLAG_TOP_FIELD_FIRST - : BLOCK_FLAG_BOTTOM_FIELD_FIRST; - } - else /* if( p_sys->i_picture_structure == 0x03 ) */ - { - p_pic->i_flags |= (p_sys->i_top_field_first) ? BLOCK_FLAG_TOP_FIELD_FIRST - : BLOCK_FLAG_BOTTOM_FIELD_FIRST; - } - } - - /* Special case for DVR-MS where we need to fully build pts from scratch - * and only use first dts as it does not monotonically increase - * This will NOT work with frame repeats and such, as we would need to fully - * fill the DPB to get accurate pts timings. */ - if( unlikely( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'D','V','R',' ') ) ) - { - const bool b_first_xmited = (p_sys->i_prev_temporal_ref != p_sys->i_temporal_ref ); - - if( ( p_pic->i_flags & BLOCK_FLAG_TYPE_I ) && b_first_xmited ) - { - if( date_Get( &p_sys->prev_iframe_dts ) == VLC_TICK_INVALID ) - { - if( p_sys->i_dts != VLC_TICK_INVALID ) - { - date_Set( &p_sys->dts, p_sys->i_dts ); - } - else - { - if( date_Get( &p_sys->dts ) == VLC_TICK_INVALID ) - { - date_Set( &p_sys->dts, VLC_TICK_0 ); - } - } - } - p_sys->prev_iframe_dts = p_sys->dts; - } - - p_pic->i_dts = date_Get( &p_sys->dts ); - - /* Compute pts from poc */ - date_t datepts = p_sys->prev_iframe_dts; - date_Increment( &datepts, (1 + p_sys->i_temporal_ref) * 2 ); - - /* Field picture second field case */ - if( p_sys->i_picture_structure != 0x03 ) - { - /* first sent is not the first in display order */ - if( (p_sys->i_picture_structure >> 1) != !p_sys->i_top_field_first && - b_first_xmited ) - { - date_Increment( &datepts, 2 ); - } - } - - p_pic->i_pts = date_Get( &datepts ); - - if( date_Get( &p_sys->dts ) != VLC_TICK_INVALID ) - { - date_Increment( &p_sys->dts, i_num_fields ); - - p_pic->i_length = date_Get( &p_sys->dts ) - p_pic->i_dts; - } - p_sys->i_prev_temporal_ref = p_sys->i_temporal_ref; - } - else /* General case, use demuxer's dts/pts when set or interpolate */ - { - if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 ) - { - /* Trivial case (DTS == PTS) */ - /* Correct interpolated dts when we receive a new pts/dts */ - if( p_sys->i_pts != VLC_TICK_INVALID ) - date_Set( &p_sys->dts, p_sys->i_pts ); - if( p_sys->i_dts != VLC_TICK_INVALID ) - date_Set( &p_sys->dts, p_sys->i_dts ); - } - else - { - /* Correct interpolated dts when we receive a new pts/dts */ - if(p_sys->i_last_ref_pts != VLC_TICK_INVALID && !p_sys->b_second_field) - date_Set( &p_sys->dts, p_sys->i_last_ref_pts ); - if( p_sys->i_dts != VLC_TICK_INVALID ) - date_Set( &p_sys->dts, p_sys->i_dts ); - - if( !p_sys->b_second_field ) - p_sys->i_last_ref_pts = p_sys->i_pts; - } - - p_pic->i_dts = date_Get( &p_sys->dts ); - - /* Set PTS only if we have a B frame or if it comes from the stream */ - if( p_sys->i_pts != VLC_TICK_INVALID ) - { - p_pic->i_pts = p_sys->i_pts; - } - else if( p_sys->i_picture_type == 0x03 ) - { - p_pic->i_pts = p_pic->i_dts; - } - else - { - p_pic->i_pts = VLC_TICK_INVALID; - } - - if( date_Get( &p_sys->dts ) != VLC_TICK_INVALID ) - { - date_Increment( &p_sys->dts, i_num_fields ); - - p_pic->i_length = date_Get( &p_sys->dts ) - p_pic->i_dts; - } - } - -#if 0 - msg_Dbg( p_dec, "pic: type=%d ref=%d nf=%d tff=%d dts=%"PRId64" ptsdiff=%"PRId64" len=%"PRId64, - p_sys->i_picture_structure, p_sys->i_temporal_ref, i_num_fields, - p_sys->i_top_field_first, - p_pic->i_dts , (p_pic->i_pts != VLC_TICK_INVALID) ? p_pic->i_pts - p_pic->i_dts : 0, p_pic->i_length ); -#endif - - - /* Reset context */ - p_sys->p_frame = NULL; - p_sys->pp_last = &p_sys->p_frame; - p_sys->b_frame_slice = false; - - if( p_sys->i_picture_structure != 0x03 ) - { - p_sys->b_second_field = !p_sys->b_second_field; - } - else - { - p_sys->b_second_field = 0; - } - - /* CC */ - p_sys->b_cc_reset = true; - p_sys->i_cc_pts = p_pic->i_pts; - p_sys->i_cc_dts = p_pic->i_dts; - p_sys->i_cc_flags = p_pic->i_flags & BLOCK_FLAG_TYPE_MASK; } if( !p_pic && p_sys->b_cc_reset ) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
