[FFmpeg-devel] [PATCH 3/3] avfilter/yadif_common: fix timestamps with very small timebases

Marton Balint cus at passwd.hu
Sat Feb 3 21:23:43 EET 2024



On Thu, 1 Feb 2024, Marton Balint wrote:

>
> On Thu, 1 Feb 2024, Michael Niedermayer wrote:
>
>>  On Wed, Jan 31, 2024 at 03:42:46AM +0100, Marton Balint wrote:
>>> 
>>>
>>>  On Wed, 31 Jan 2024, Michael Niedermayer wrote:
>>>
>>>>  On Sun, Jan 28, 2024 at 04:01:36AM +0100, Marton Balint wrote:
>>>>>  Yadif filter assumed that the output timebase is always half of the
>>>>>  input
>>>>>  timebase. This is not true if halving the input time base is not
>>>>>  representable
>>>>>  as an AVRational causing the output timestamps to be invalidly scaled
>>>>>  in such a
>>>>>  case.
>>>>>
>>>>>  So let's use av_reduce instead of av_mul_q when calculating the output
>>>>>  time
>>>>>  base and if the conversion is inexact then let's fall back to the
>>>>>  original
>>>>>  timebase which probably makes more parctical sense than using
>>>>>  x/INT_MAX.
>>>>>
>>>>>  Fixes invalidly scaled pts_time values in this command line:
>>>>>  ffmpeg -f lavfi -i testsrc -vf settb=tb=1/2000000000,yadif,showinfo -f
>>>>>  null none
>>>>>
>>>>>  Signed-off-by: Marton Balint <cus at passwd.hu>
>>>>>  ---
>>>>>   libavfilter/yadif.h        |  2 ++
>>>>>   libavfilter/yadif_common.c | 20 ++++++++++++++------
>>>>>   2 files changed, 16 insertions(+), 6 deletions(-)
>>>>>
>>>>>  diff --git a/libavfilter/yadif.h b/libavfilter/yadif.h
>>>>>  index 2c4fed62d2..c144568242 100644
>>>>>  --- a/libavfilter/yadif.h
>>>>>  +++ b/libavfilter/yadif.h
>>>>>  @@ -86,6 +86,8 @@ typedef struct YADIFContext {
>>>>>        * the first field.
>>>>>        */
>>>>>       int current_field;  ///< YADIFCurrentField
>>>>>  +
>>>>>  +    int pts_divisor;
>>>>>   } YADIFContext;
>>>>>
>>>>>  void ff_yadif_init_x86(YADIFContext *yadif);
>>>>>  diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c
>>>>>  index 933372529e..90a5cffc2d 100644
>>>>>  --- a/libavfilter/yadif_common.c
>>>>>  +++ b/libavfilter/yadif_common.c
>>>>>  @@ -61,7 +61,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
>>>>>           int64_t next_pts = yadif->next->pts;
>>>>>
>>>>>           if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
>>>>>  -            yadif->out->pts = cur_pts + next_pts;
>>>>>  +            yadif->out->pts = (cur_pts + next_pts) /
>>>>>  yadif->pts_divisor;
>>>>>           } else {
>>>>>               yadif->out->pts = AV_NOPTS_VALUE;
>>>>>           }
>>>>>  @@ -150,8 +150,8 @@ int ff_yadif_filter_frame(AVFilterLink *link,
>>>>>  AVFrame *frame)
>>>>>           ff_ccfifo_inject(&yadif->cc_fifo, yadif->out);
>>>>>           av_frame_free(&yadif->prev);
>>>>>           if (yadif->out->pts != AV_NOPTS_VALUE)
>>>>>  -            yadif->out->pts *= 2;
>>>>>  -        yadif->out->duration *= 2;
>>>>>  +            yadif->out->pts *= 2 / yadif->pts_divisor;
>>>>>  +        yadif->out->duration *= 2 / yadif->pts_divisor;
>>>>>           return ff_filter_frame(ctx->outputs[0], yadif->out);
>>>>>       }
>>>>>
>>>>>  @@ -168,9 +168,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
>>>>>       yadif->out->flags &= ~AV_FRAME_FLAG_INTERLACED;
>>>>>
>>>>>       if (yadif->out->pts != AV_NOPTS_VALUE)
>>>>>  -        yadif->out->pts *= 2;
>>>>>  +        yadif->out->pts *= 2 / yadif->pts_divisor;
>>>>>       if (!(yadif->mode & 1))
>>>>>  -        yadif->out->duration *= 2;
>>>>>  +        yadif->out->duration *= 2 / yadif->pts_divisor;
>>>>
>>>>  you can use >> instead of division for all above
>>>
>>>  Even for the first case? Because the right shift would be implementation
>>>  defined for negative timestamps.
>>
>>  we are only supporting twos-complement systems
>>  i thought that was somewhete in teh docs
>
> Ok, I will change the /= 2 divisions to >>= 1 shifts in v2 patch then.

Will apply the series.

Regards,
Marton


More information about the ffmpeg-devel mailing list