[FFmpeg-devel] [PATCH 1/2] ffmpeg: last frame duplication heuristic
Michael Niedermayer
michaelni at gmx.at
Wed Nov 19 13:18:41 CET 2014
This improves the last frames duration with CFR and when the input durations
are inaccurate or missing
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
ffmpeg.c | 29 ++++++++++++++++++++++++-----
ffmpeg.h | 1 +
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/ffmpeg.c b/ffmpeg.c
index 0f4b2aa..ab95e13 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -60,6 +60,7 @@
#include "libavutil/bprint.h"
#include "libavutil/time.h"
#include "libavutil/threadmessage.h"
+#include "libavcodec/mathops.h"
#include "libavformat/os_support.h"
#include "libavformat/ffm.h" // not public API
@@ -893,6 +894,12 @@ static void do_video_out(AVFormatContext *s,
if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num)
duration = 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base));
+ if (!next_picture) {
+ //end, flushing
+ nb0_frames = nb_frames = mid_pred(ost->last_nb0_frames[0],
+ ost->last_nb0_frames[1],
+ ost->last_nb0_frames[2]);
+ } else {
sync_ipts = next_picture->pts;
delta0 = sync_ipts - ost->sync_opts;
delta = delta0 + duration;
@@ -949,9 +956,16 @@ static void do_video_out(AVFormatContext *s,
default:
av_assert0(0);
}
+ }
nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
nb0_frames = FFMIN(nb0_frames, nb_frames);
+
+ memmove(ost->last_nb0_frames + 1,
+ ost->last_nb0_frames,
+ sizeof(ost->last_nb0_frames[0]) * (FF_ARRAY_ELEMS(ost->last_nb0_frames) - 1));
+ ost->last_nb0_frames[0] = nb0_frames;
+
if (nb0_frames == 0 && ost->last_droped) {
nb_frames_drop++;
av_log(NULL, AV_LOG_VERBOSE,
@@ -967,7 +981,7 @@ static void do_video_out(AVFormatContext *s,
nb_frames_dup += nb_frames - (nb0_frames && ost->last_droped) - (nb_frames > nb0_frames);
av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
}
- ost->last_droped = nb_frames == nb0_frames;
+ ost->last_droped = nb_frames == nb0_frames && next_picture;
/* duplicates frame if needed */
for (i = 0; i < nb_frames; i++) {
@@ -1122,6 +1136,7 @@ static void do_video_out(AVFormatContext *s,
if (!ost->last_frame)
ost->last_frame = av_frame_alloc();
av_frame_unref(ost->last_frame);
+ if (next_picture)
av_frame_ref(ost->last_frame, next_picture);
}
@@ -1185,7 +1200,7 @@ static void finish_output_stream(OutputStream *ost)
*
* @return 0 for success, <0 for severe errors
*/
-static int reap_filters(void)
+static int reap_filters(int flush)
{
AVFrame *filtered_frame = NULL;
int i;
@@ -1215,6 +1230,9 @@ static int reap_filters(void)
if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
av_log(NULL, AV_LOG_WARNING,
"Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret));
+ } else if (flush) {
+ if (filter->inputs[0]->type == AVMEDIA_TYPE_VIDEO)
+ do_video_out(of->ctx, ost, NULL);
}
break;
}
@@ -3611,10 +3629,10 @@ static int transcode_from_filter(FilterGraph *graph, InputStream **best_ist)
*best_ist = NULL;
ret = avfilter_graph_request_oldest(graph->graph);
if (ret >= 0)
- return reap_filters();
+ return reap_filters(0);
if (ret == AVERROR_EOF) {
- ret = reap_filters();
+ ret = reap_filters(1);
for (i = 0; i < graph->nb_outputs; i++)
close_output_stream(graph->outputs[i]->ost);
return ret;
@@ -3680,10 +3698,11 @@ static int transcode_step(void)
ost->unavailable = 1;
return 0;
}
+
if (ret < 0)
return ret == AVERROR_EOF ? 0 : ret;
- return reap_filters();
+ return reap_filters(0);
}
/*
diff --git a/ffmpeg.h b/ffmpeg.h
index 1ace8be..f62bc9a 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -390,6 +390,7 @@ typedef struct OutputStream {
AVFrame *filtered_frame;
AVFrame *last_frame;
int last_droped;
+ int last_nb0_frames[3];
/* video only */
AVRational frame_rate;
--
1.7.9.5
More information about the ffmpeg-devel
mailing list