[vlc-devel] [PATCH] avcodec: repeat the pictures marked as repeating
Steve Lhomme
robux4 at ycbcr.xyz
Mon Nov 16 14:12:45 CET 2020
The libavutil doc for "repeat_pict" says:
When decoding, this signals how much the picture must be delayed.
extra_delay = repeat_pict / (2*fps)
But the one in AVCodecParserContext says:
This field is used for proper frame duration computation in lavf.
It signals, how much longer the frame duration of the current frame is
compared to normal frame duration.
frame_duration = (1 + repeat_pict) * time_base
It is used by codecs like H.264 to display telecined material.
In practice it only sets a few values:
- 0 1 picture in progressive / 1 or 2 fields in interlaced
- 1 2 fields in interlaced + 1 repeated field
- 2 2 pictures in progressive
- 4 3 pictures in progressive
It should make it easier to remux or reencode on containers with a fixed frame
rate that don't handle gaps between pictures. Each picture has the same base
duration.
In addition the interpolate_next_pts() used the repeat_pict incorrectly as the
value is 2 per progressive picture. So every additional picture was counted as
2 ticks.
---
modules/codec/avcodec/video.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 23d1d469394..33b5d2272bb 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -679,7 +679,7 @@ static block_t * filter_earlydropped_blocks( decoder_t *p_dec, block_t *block )
return block;
}
-static vlc_tick_t interpolate_next_pts( decoder_t *p_dec, AVFrame *frame )
+static vlc_tick_t interpolate_next_pts( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
AVCodecContext *p_context = p_sys->p_context;
@@ -693,7 +693,7 @@ static vlc_tick_t interpolate_next_pts( decoder_t *p_dec, AVFrame *frame )
i_tick = 1;
/* interpolate the next PTS */
- return date_Increment( &p_sys->pts, i_tick + frame->repeat_pict );
+ return date_Increment( &p_sys->pts, i_tick );
}
static void update_late_frame_count( decoder_t *p_dec, block_t *p_block,
@@ -1093,7 +1093,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( i_pts != VLC_TICK_INVALID )
date_Set( &p_sys->pts, i_pts );
- const vlc_tick_t i_next_pts = interpolate_next_pts(p_dec, frame);
+ const vlc_tick_t i_next_pts = interpolate_next_pts(p_dec);
if( b_first_output_sequence )
{
@@ -1214,13 +1214,14 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
// interlaced HEVC decoding sends 1 field at a time and isn't signaled by lavc
p_pic->i_nb_fields = 1;
else
- p_pic->i_nb_fields = 2 + frame->repeat_pict;
+ p_pic->i_nb_fields = 2 + frame->repeat_pict % 2;
p_pic->b_progressive = !frame->interlaced_frame;
p_pic->b_top_field_first = frame->top_field_first;
if (DecodeSidedata(p_dec, frame, p_pic))
i_pts = VLC_TICK_INVALID;
+ int repeat_pict = frame->repeat_pict / 2;
av_frame_free(&frame);
/* Send decoded frame to vout */
@@ -1231,6 +1232,13 @@ static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_sys->b_first_frame = false;
vlc_mutex_unlock(&p_sys->lock);
decoder_QueueVideo( p_dec, p_pic );
+ while ( repeat_pict > 0 )
+ {
+ picture_t *p_repeat = picture_Clone( p_pic );
+ p_repeat->date = interpolate_next_pts( p_dec );
+ decoder_QueueVideo( p_dec, p_repeat );
+ repeat_pict --;
+ }
}
else
{
--
2.26.2
More information about the vlc-devel
mailing list