[FFmpeg-devel] libavfilter/af_atempo: offset output frames' pts by first_frame_pts / tempo

Submitted by Paweł Wegner on Jan. 24, 2019, 12:42 p.m.

Details

Message ID 20190124124203.19345-1-pawel.wegner95@gmail.com
State New
Headers show

Commit Message

Paweł Wegner Jan. 24, 2019, 12:42 p.m.
Signed-off-by: Paweł Wegner <pawel.wegner95@gmail.com>
---
 libavfilter/af_atempo.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Paul B Mahol Jan. 24, 2019, 1:46 p.m.
On 1/24/19, Paweł Wegner <pawel.wegner95@gmail.com> wrote:
> Signed-off-by: Paweł Wegner <pawel.wegner95@gmail.com>
> ---
>  libavfilter/af_atempo.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c
> index bfdad7d76b..1245eae8c1 100644
> --- a/libavfilter/af_atempo.c
> +++ b/libavfilter/af_atempo.c
> @@ -147,6 +147,8 @@ typedef struct ATempoContext {
>      uint8_t *dst_end;
>      uint64_t nsamples_in;
>      uint64_t nsamples_out;
> +
> +    int64_t first_frame_pts;
>  } ATempoContext;
>
>  #define YAE_ATEMPO_MIN 0.5
> @@ -994,6 +996,7 @@ static av_cold int init(AVFilterContext *ctx)
>      ATempoContext *atempo = ctx->priv;
>      atempo->format = AV_SAMPLE_FMT_NONE;
>      atempo->state  = YAE_LOAD_FRAGMENT;
> +    atempo->first_frame_pts = AV_NOPTS_VALUE;
>      return 0;
>  }
>
> @@ -1069,6 +1072,7 @@ static int push_samples(ATempoContext *atempo,
>
>      // adjust the PTS:
>      atempo->dst_buffer->pts =
> +        (atempo->first_frame_pts == AV_NOPTS_VALUE ? 0 :
> atempo->first_frame_pts / atempo->tempo) +
>          av_rescale_q(atempo->nsamples_out,
>                       (AVRational){ 1, outlink->sample_rate },
>                       outlink->time_base);
> @@ -1108,6 +1112,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *src_buffer)
>
>              atempo->dst = atempo->dst_buffer->data[0];
>              atempo->dst_end = atempo->dst + n_out * atempo->stride;
> +
> +            if (atempo->first_frame_pts == AV_NOPTS_VALUE)
> +                atempo->first_frame_pts =
> av_rescale_q(atempo->dst_buffer->pts,
> +                                                       inlink->time_base,
> +                                                       outlink->time_base);
>          }
>
>          yae_apply(atempo, &src, src_end, &atempo->dst, atempo->dst_end);
> --
> 2.17.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

lgtm
Pavel Koshevoy Jan. 24, 2019, 2:36 p.m.
On Thu, Jan 24, 2019 at 5:49 AM Paweł Wegner <pawel.wegner95@gmail.com> wrote:
>
> Signed-off-by: Paweł Wegner <pawel.wegner95@gmail.com>
> ---
>  libavfilter/af_atempo.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c
> index bfdad7d76b..1245eae8c1 100644
> --- a/libavfilter/af_atempo.c
> +++ b/libavfilter/af_atempo.c
> @@ -147,6 +147,8 @@ typedef struct ATempoContext {
>      uint8_t *dst_end;
>      uint64_t nsamples_in;
>      uint64_t nsamples_out;
> +
> +    int64_t first_frame_pts;
>  } ATempoContext;
>
>  #define YAE_ATEMPO_MIN 0.5
> @@ -994,6 +996,7 @@ static av_cold int init(AVFilterContext *ctx)
>      ATempoContext *atempo = ctx->priv;
>      atempo->format = AV_SAMPLE_FMT_NONE;
>      atempo->state  = YAE_LOAD_FRAGMENT;
> +    atempo->first_frame_pts = AV_NOPTS_VALUE;
>      return 0;
>  }
>
> @@ -1069,6 +1072,7 @@ static int push_samples(ATempoContext *atempo,
>
>      // adjust the PTS:
>      atempo->dst_buffer->pts =
> +        (atempo->first_frame_pts == AV_NOPTS_VALUE ? 0 : atempo->first_frame_pts / atempo->tempo) +
>          av_rescale_q(atempo->nsamples_out,
>                       (AVRational){ 1, outlink->sample_rate },
>                       outlink->time_base);
> @@ -1108,6 +1112,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *src_buffer)
>
>              atempo->dst = atempo->dst_buffer->data[0];
>              atempo->dst_end = atempo->dst + n_out * atempo->stride;
> +
> +            if (atempo->first_frame_pts == AV_NOPTS_VALUE)
> +                atempo->first_frame_pts = av_rescale_q(atempo->dst_buffer->pts,
> +                                                       inlink->time_base,
> +                                                       outlink->time_base);
>          }
>
>          yae_apply(atempo, &src, src_end, &atempo->dst, atempo->dst_end);
> --
> 2.17.1
>


Probably okay. The reason I didn't do this to begin with is because
this is an audio stream filter... and how the timeline of the stream
was transformed up to the 1st frame is unknown.  You are making the
assumption that it should have been transformed using the same tempo
parameter as current tempo, but (video) tempo can be varied at runtime
prior to 1st audio frame, so pts_0' = pts_0 / tempo could be wrong.

Anyway, I don't have a use case where this change would break
something, so if this fixes something for you then it's fine.

    Pavel.
Paweł Wegner Jan. 24, 2019, 2:48 p.m.
On Thu, Jan 24, 2019 at 3:43 PM Pavel Koshevoy <pkoshevoy@gmail.com> wrote:

> On Thu, Jan 24, 2019 at 5:49 AM Paweł Wegner <pawel.wegner95@gmail.com>
> wrote:
> >
> > Signed-off-by: Paweł Wegner <pawel.wegner95@gmail.com>
> > ---
> >  libavfilter/af_atempo.c | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> >
> > diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c
> > index bfdad7d76b..1245eae8c1 100644
> > --- a/libavfilter/af_atempo.c
> > +++ b/libavfilter/af_atempo.c
> > @@ -147,6 +147,8 @@ typedef struct ATempoContext {
> >      uint8_t *dst_end;
> >      uint64_t nsamples_in;
> >      uint64_t nsamples_out;
> > +
> > +    int64_t first_frame_pts;
> >  } ATempoContext;
> >
> >  #define YAE_ATEMPO_MIN 0.5
> > @@ -994,6 +996,7 @@ static av_cold int init(AVFilterContext *ctx)
> >      ATempoContext *atempo = ctx->priv;
> >      atempo->format = AV_SAMPLE_FMT_NONE;
> >      atempo->state  = YAE_LOAD_FRAGMENT;
> > +    atempo->first_frame_pts = AV_NOPTS_VALUE;
> >      return 0;
> >  }
> >
> > @@ -1069,6 +1072,7 @@ static int push_samples(ATempoContext *atempo,
> >
> >      // adjust the PTS:
> >      atempo->dst_buffer->pts =
> > +        (atempo->first_frame_pts == AV_NOPTS_VALUE ? 0 :
> atempo->first_frame_pts / atempo->tempo) +
> >          av_rescale_q(atempo->nsamples_out,
> >                       (AVRational){ 1, outlink->sample_rate },
> >                       outlink->time_base);
> > @@ -1108,6 +1112,11 @@ static int filter_frame(AVFilterLink *inlink,
> AVFrame *src_buffer)
> >
> >              atempo->dst = atempo->dst_buffer->data[0];
> >              atempo->dst_end = atempo->dst + n_out * atempo->stride;
> > +
> > +            if (atempo->first_frame_pts == AV_NOPTS_VALUE)
> > +                atempo->first_frame_pts =
> av_rescale_q(atempo->dst_buffer->pts,
> > +
>  inlink->time_base,
> > +
>  outlink->time_base);
> >          }
> >
> >          yae_apply(atempo, &src, src_end, &atempo->dst, atempo->dst_end);
> > --
> > 2.17.1
> >
>
>
> Probably okay. The reason I didn't do this to begin with is because
> this is an audio stream filter... and how the timeline of the stream
> was transformed up to the 1st frame is unknown.  You are making the
> assumption that it should have been transformed using the same tempo
> parameter as current tempo, but (video) tempo can be varied at runtime
> prior to 1st audio frame, so pts_0' = pts_0 / tempo could be wrong.
>
> Anyway, I don't have a use case where this change would break
> something, so if this fixes something for you then it's fine.

This fixes seeking when I have video playback sped up in ffplay like this:
ffplay -vf "setpts=0.5 * PTS" -af "atempo=2" input

>
>     Pavel.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Gyan Jan. 24, 2019, 3:01 p.m.
On 24-01-2019 08:18 PM, Paweł Wegner wrote:
>
> This fixes seeking when I have video playback sped up in ffplay like this:
> ffplay -vf "setpts=0.5 * PTS" -af "atempo=2" input

The better way to run this is

     ffplay -vf "setpts=0.5 * (PTS - STARTPTS)" -af "atempo=2" input


Gyan
Pavel Koshevoy Jan. 24, 2019, 3:17 p.m.
On Thu, Jan 24, 2019 at 8:01 AM Gyan <ffmpeg@gyani.pro> wrote:
>
>
>
> On 24-01-2019 08:18 PM, Paweł Wegner wrote:
> >
> > This fixes seeking when I have video playback sped up in ffplay like this:
> > ffplay -vf "setpts=0.5 * PTS" -af "atempo=2" input
>
> The better way to run this is
>
>      ffplay -vf "setpts=0.5 * (PTS - STARTPTS)" -af "atempo=2" input
>
>


yeah, why not just do this... no code changes required.  I'd prefer it
if atempo stayed simple.  This way you can still use a separate pts
transform filter to adjust audio pts if necessary and without
hard-coding an assumption into atempo.

Pavel.
Paweł Wegner Jan. 24, 2019, 5:08 p.m.
On Thu, Jan 24, 2019 at 4:01 PM Gyan <ffmpeg@gyani.pro> wrote:

>
>
> On 24-01-2019 08:18 PM, Paweł Wegner wrote:
> >
> > This fixes seeking when I have video playback sped up in ffplay like
> this:
> > ffplay -vf "setpts=0.5 * PTS" -af "atempo=2" input
>
> The better way to run this is
>
>      ffplay -vf "setpts=0.5 * (PTS - STARTPTS)" -af "atempo=2" input
>
This works fine, thanks; the patch can be discarded.

>
> Gyan
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Patch hide | download patch | download mbox

diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c
index bfdad7d76b..1245eae8c1 100644
--- a/libavfilter/af_atempo.c
+++ b/libavfilter/af_atempo.c
@@ -147,6 +147,8 @@  typedef struct ATempoContext {
     uint8_t *dst_end;
     uint64_t nsamples_in;
     uint64_t nsamples_out;
+
+    int64_t first_frame_pts;
 } ATempoContext;
 
 #define YAE_ATEMPO_MIN 0.5
@@ -994,6 +996,7 @@  static av_cold int init(AVFilterContext *ctx)
     ATempoContext *atempo = ctx->priv;
     atempo->format = AV_SAMPLE_FMT_NONE;
     atempo->state  = YAE_LOAD_FRAGMENT;
+    atempo->first_frame_pts = AV_NOPTS_VALUE;
     return 0;
 }
 
@@ -1069,6 +1072,7 @@  static int push_samples(ATempoContext *atempo,
 
     // adjust the PTS:
     atempo->dst_buffer->pts =
+        (atempo->first_frame_pts == AV_NOPTS_VALUE ? 0 : atempo->first_frame_pts / atempo->tempo) +
         av_rescale_q(atempo->nsamples_out,
                      (AVRational){ 1, outlink->sample_rate },
                      outlink->time_base);
@@ -1108,6 +1112,11 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *src_buffer)
 
             atempo->dst = atempo->dst_buffer->data[0];
             atempo->dst_end = atempo->dst + n_out * atempo->stride;
+
+            if (atempo->first_frame_pts == AV_NOPTS_VALUE)
+                atempo->first_frame_pts = av_rescale_q(atempo->dst_buffer->pts,
+                                                       inlink->time_base,
+                                                       outlink->time_base);
         }
 
         yae_apply(atempo, &src, src_end, &atempo->dst, atempo->dst_end);