当我用ffmpeg转码这个源文件时,ffmpeg可能会吃掉很多东西 记忆大约几十GB直到被杀,为什么?
the report here:
ffmpeg started on 2017-12-19 at 10:59:15
Report written to "ffmpeg-20171219-105915.log"
Command line:
ffmpeg -i memory_error_fifo.mp4 -s 854x480 -vcodec libx264 -x264opts
"keyint=50" -b:v 238k -vf "movie=namei.jpg [watermark]; [vf0] fifo
[vf1];[vf1][watermark] overlay=main_w-overlay_w-0:0[vf2]" -acodec
libfdk_aac -ar 44100 -movflags faststart -f mp4 output.mp4 -y -v trace
-report
ffmpeg version N-89095-gb3c1172 Copyright (c) 2000-2017 the FFmpeg
How to reproduce:
ffmpeg -i "memory_error_fifo.mp4" -s 854x480 -vcodec libx264 -x264opts
keyint=50 -b:v 238k -vf "movie=namei.jpg [watermark]; [vf0] fifo
[vf1];[vf1][watermark] overlay=main_w-overlay_w-0:0[vf2]" -acodec
libfdk_aac -ar 44100 -movflags faststart -f mp4 output.mp4 -y -v trace
-report
当我使用-an来禁用音频时,结果还可以; 当我不使用" fifo"时,结果还可以,但我的项目需要这个" fifo"过滤
n3.5-dev-1292-gce001bb with master commit
ce001bb8fc6677541c401a614e05e5058d58dde1
built on linux
ffmpeg report:https://pan.baidu.com/s/1qYNvTes
attached source file: https://pan.baidu.com/s/1pLzbwbp
答案 0 :(得分:1)
原因:fifo-filter在请求之前不会输出帧。并且ffmpeg仅请求属于具有最小时间戳的流的帧(请参阅choose_output()函数)。因此,当媒体有一些不正常的内容,比如没有音频或一些音频解码错误的短片纯图像时,ffmpeg将继续请求音频帧并在fifo-filter中阻止数千个视频帧占用你的记忆。
<强>解决方案强>: 我遇到了同样的问题并通过在fifo-filter中添加样本限制来解决它。当缓冲帧数超过限制时,它将强制下一个链接过滤器请求帧。代码:
libavfilter/fifo.c:
+ #define NB_SAMPLE_MAX 500 // About 1GB memory
typedef struct Buf {
AVFrame *frame;
struct Buf *next;
AVFrame *out;
int allocated_samples; ///< number of samples out was allocated for
+ int buffered_samples; ///< avoid memory overflow
} FifoContext;
static av_cold int init(AVFilterContext *ctx)
{
FifoContext *fifo = ctx->priv;
fifo->last = &fifo->root;
+ fifo->buffered_samples = 0;
return 0;
}
static int add_to_queue(AVFilterLink *inlink, AVFrame *frame)
{
FifoContext *fifo = inlink->dst->priv;
+ int i;
fifo->last->next = av_mallocz(sizeof(Buf));
if (!fifo->last->next) {
av_frame_free(&frame);
return AVERROR(ENOMEM);
}
fifo->last = fifo->last->next;
fifo->last->frame = frame;
+ fifo->buffered_samples++;
+ if (fifo->buffered_samples > NB_SAMPLE_MAX) {
+ av_log(NULL, AV_LOG_DEBUG, "Too many frames buffered in fifo.\n");
+ for (i = 0; i < inlink->dst->nb_outputs; i++) {
+ inlink->dst->outputs[i]->frame_wanted_out = 1; // it will force the next filter to request frames
+ }
+ }
return 0;
}
static void queue_pop(FifoContext *s)
{
Buf *tmp = s->root.next->next;
if (s->last == s->root.next)
s->last = &s->root;
av_freep(&s->root.next);
s->root.next = tmp;
+ if (s->buffered_samples > 0)
+ s->buffered_samples--;
}
我不确定这些变化是否会导致其他一些问题。如果有人有更好的解决方案,请告诉我。