ffmpeg C API - 创建帧队列
ffmpeg C API - creating queue of frames
我使用 ffmpeg 的 C API 创建了一个 C++ 应用程序,该应用程序从文件中读取帧并将其写入新文件。一切正常,只要我立即将帧写入输出即可。换句话说,程序的以下结构输出正确的结果(我现在只放置伪代码,如果需要,我也可以发布一些真实的片段,但我为处理 ffmpeg 功能而创建的类非常大):
AVFrame* frame = av_frame_alloc();
int got_frame;
// readFrame returns 0 if file is ended, got frame = 1 if
// a complete frame has been extracted
while(readFrame(inputfile,frame, &got_frame)) {
if (got_frame) {
// I actually do some processing here
writeFrame(outputfile,frame);
}
}
av_frame_free(&frame);
下一步是并行化应用程序,因此,帧在读取后不会立即写入(我不想详细介绍并行化)。在这种情况下会出现问题:输出中有一些闪烁,就好像某些帧随机重复一样。但是,输出视频的帧数和持续时间仍然正确。
我现在要做的是在串行实现中将读取与写入完全分开,以便了解正在发生的事情。我正在创建一个指向框架的指针队列:
std::queue<AVFrame*> queue;
int ret = 1, got_frame;
while (ret) {
AVFrame* frame = av_frame_alloc();
ret = readFrame(inputfile,frame,&got_frame);
if (got_frame)
queue.push(frame);
}
要将帧写入输出文件,我这样做:
while (!queue.empty()) {
frame = queue.front();
queue.pop();
writeFrame(outputFile,frame);
av_frame_free(&frame);
}
在这种情况下,结果是具有正确持续时间和帧数的输出视频,该视频仅重复视频的最后 3 帧(我认为)。
我的猜测是可能会出现问题,因为在第一种情况下,我总是使用相同的内存位置来读取帧,而在第二种情况下,我分配了许多不同的帧。
关于可能是什么问题的任何建议?
啊,所以我假设readFrame()
是libavformat的av_read_frame()
和libavcodec的avcodec_decode_video2()
的包装器,对吗?
从文档中:
当
AVCodecContext.refcounted_frames
设置为 1 时,帧为 引用计数,返回的引用属于调用方。 调用方必须在以下情况下使用av_frame_unref()
释放帧 不再需要框架。
和:
什么时候
AVCodecContext.refcounted_frames
设置为 0,返回的引用 属于解码器,仅在下次调用此 函数或直到关闭或刷新解码器。
显然,由此可以得出您需要将AVCodecContext.refcounted_frames
设置为 1。默认值为 0,所以我的直觉是您需要将其设置为 1,这将解决您的问题。使用后不要忘记在图片上使用av_fame_unref()
以防止内存泄漏,如果got_frame = 0
,也不要忘记在此循环中释放AVFrame
- 再次防止内存泄漏:
while (ret) { AVFrame* frame = av_frame_alloc(); ret = readFrame(inputfile,frame,&got_frame); if (got_frame) queue.push(frame); else av_frame_free(frame); }
(或者,您也可以为frame
实现一些缓存,以便仅在前一个对象被推送到队列中时才重新分配它。
你的伪代码没有明显的问题。 问题几乎肯定在于如何在线程之间锁定队列。
你的内存分配对我来说似乎是一样的。在阅读和写入帧之间,您是否可能会做其他事情?
queue
读取和写入帧的例程中是否为同一队列?
- 在C++中创建队列 - 什么是 malloc 错误?
- 避免使用 boost::进程间::消息队列创建文件
- 是否可以使用简单队列创建优先级队列
- C++ Poco - 如何创建通知队列的向量?
- 如何在 c++ 中创建对的优先级队列.这会弹出具有最小值的元素.默认的弹出最大值
- 如何使用用户输入创建字符串队列?
- 使用加速进程间创建消息队列 - 内存访问冲突
- 为什么我不能在 Windows 中的 rabbitmq 中创建队列?
- 为队列创建C 全局变量
- 创建多类队列C++
- C 在标题文件中创建具有结构定义的结构的队列
- 我有一个问题,创建了C 中阻塞队列的向量
- 无法创建支持传输队列的 VkDevice
- 关于使用我自己创建的类使用优先级队列的问题
- 从调度队列块 [ swift / c++ ] 创建线程
- 在.c文件接收函数中使用Linux中的MSGGET创建消息队列未实现错误
- 尝试使用堆栈创建队列.为什么我会遇到int转换错误的空白
- 用管道在C++中创建调度队列/线程处理程序:FIFO溢出
- 从 STL 优先级队列创建最小堆
- boost::进程间消息队列创建时的竞争条件