summaryrefslogtreecommitdiff
path: root/ffmpeg.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-11-19 12:41:16 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-04-03 19:09:31 +0200
commit98c7729c133e801889adc3f6527ff271b2df73b5 (patch)
tree33b1963b243b0c65babee41711e5f1df5d814739 /ffmpeg.c
parentaf5fec9538d88540af5bb2dd0e4b91162ce6fa13 (diff)
ffmpeg: last frame duplication heuristic
This improves the last frames duration with CFR and when the input durations are inaccurate or missing Fixes Ticket4119 Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'ffmpeg.c')
-rw-r--r--ffmpeg.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index 8bf507a30e..84ad3092d2 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 "libavfilter/avcodec.h"
@@ -914,6 +915,12 @@ static void do_video_out(AVFormatContext *s,
duration = lrintf(av_frame_get_pkt_duration(next_picture) * av_q2d(ist->st->time_base) / 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 {
delta0 = sync_ipts - ost->sync_opts;
delta = delta0 + duration;
@@ -985,9 +992,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,
@@ -1003,7 +1017,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++) {
@@ -1156,6 +1170,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);
}
@@ -1219,7 +1234,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;
@@ -1249,6 +1264,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, AV_NOPTS_VALUE);
}
break;
}
@@ -3741,10 +3759,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;
@@ -3810,10 +3828,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);
}
/*