Browse Source

vf_fps: when reading EOF, using current_pts to duplicate the last frame if needed.

Fix ticket #2674
Tested with examples from ticket 2674.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
tags/n3.4
Thierry Foucu Michael Niedermayer 7 years ago
parent
commit
eea64ef4cf
5 changed files with 49 additions and 7 deletions
  1. +39
    -5
      libavfilter/vf_fps.c
  2. +6
    -0
      tests/ref/fate/filter-fps
  3. +4
    -0
      tests/ref/fate/filter-fps-r
  4. +0
    -1
      tests/ref/fate/filter-mpdecimate
  5. +0
    -1
      tests/ref/fate/m4v-cfr

+ 39
- 5
libavfilter/vf_fps.c View File

@@ -34,6 +34,8 @@
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"


#define FF_INTERNAL_FIELDS 1
#include "framequeue.h"
#include "avfilter.h" #include "avfilter.h"
#include "internal.h" #include "internal.h"
#include "video.h" #include "video.h"
@@ -137,13 +139,45 @@ static int request_frame(AVFilterLink *outlink)
AVFrame *buf; AVFrame *buf;


av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL); av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
outlink->time_base) + s->frames_out;
if (av_fifo_size(s->fifo)) {
buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
outlink->time_base) + s->frames_out;


if ((ret = ff_filter_frame(outlink, buf)) < 0)
return ret;
if ((ret = ff_filter_frame(outlink, buf)) < 0)
return ret;


s->frames_out++;
s->frames_out++;
} else {
/* This is the last frame, we may have to duplicate it to match
* the last frame duration */
int j;
int delta = av_rescale_q_rnd(ctx->inputs[0]->current_pts - s->first_pts,
ctx->inputs[0]->time_base,
outlink->time_base, s->rounding) - s->frames_out ;
/* if the delta is equal to 1, it means we just need to output
* the last frame. Greater than 1 means we will need duplicate
* delta-1 frames */
if (delta > 0 ) {
for (j = 0; j < delta; j++) {
AVFrame *dup = av_frame_clone(buf);

av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n");
dup->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
outlink->time_base) + s->frames_out;

if ((ret = ff_filter_frame(outlink, dup)) < 0)
return ret;

s->frames_out++;
if (j > 0) s->dup++;
}
} else {
/* for delta less or equal to 0, we should drop the frame,
* otherwise, we will have one or more extra frames */
av_frame_free(&buf);
s->drop++;
}
}
} }
return 0; return 0;
} }


+ 6
- 0
tests/ref/fate/filter-fps View File

@@ -85,3 +85,9 @@
0, 79, 79, 1, 30576, 0xa2fcd06f 0, 79, 79, 1, 30576, 0xa2fcd06f
0, 80, 80, 1, 30576, 0xa2fcd06f 0, 80, 80, 1, 30576, 0xa2fcd06f
0, 81, 81, 1, 30576, 0xd4150aad 0, 81, 81, 1, 30576, 0xd4150aad
0, 82, 82, 1, 30576, 0xd4150aad
0, 83, 83, 1, 30576, 0xd4150aad
0, 84, 84, 1, 30576, 0xd4150aad
0, 85, 85, 1, 30576, 0xd4150aad
0, 86, 86, 1, 30576, 0xd4150aad
0, 87, 87, 1, 30576, 0xd4150aad

+ 4
- 0
tests/ref/fate/filter-fps-r View File

@@ -72,3 +72,7 @@
0, 79, 79, 1, 30576, 0xa2fcd06f 0, 79, 79, 1, 30576, 0xa2fcd06f
0, 80, 80, 1, 30576, 0xa2fcd06f 0, 80, 80, 1, 30576, 0xa2fcd06f
0, 82, 82, 1, 30576, 0xd4150aad 0, 82, 82, 1, 30576, 0xd4150aad
0, 83, 83, 1, 30576, 0xd4150aad
0, 84, 84, 1, 30576, 0xd4150aad
0, 85, 85, 1, 30576, 0xd4150aad
0, 86, 86, 1, 30576, 0xd4150aad

+ 0
- 1
tests/ref/fate/filter-mpdecimate View File

@@ -22,4 +22,3 @@
0, 24, 24, 1, 115200, 0x056d40ca 0, 24, 24, 1, 115200, 0x056d40ca
0, 26, 26, 1, 115200, 0xa4374737 0, 26, 26, 1, 115200, 0xa4374737
0, 27, 27, 1, 115200, 0x3eaa3ae8 0, 27, 27, 1, 115200, 0x3eaa3ae8
0, 29, 29, 1, 115200, 0x7551e9ee

+ 0
- 1
tests/ref/fate/m4v-cfr View File

@@ -44,4 +44,3 @@
0, 38, 38, 1, 115200, 0xf30825d5 0, 38, 38, 1, 115200, 0xf30825d5
0, 39, 39, 1, 115200, 0xe3c944a1 0, 39, 39, 1, 115200, 0xe3c944a1
0, 40, 40, 1, 115200, 0x8fec4420 0, 40, 40, 1, 115200, 0x8fec4420
0, 41, 41, 1, 115200, 0x9381fdab

Loading…
Cancel
Save