基于 ffmpeg 的多线程 C++ 应用程序解码失败

Posted

技术标签:

【中文标题】基于 ffmpeg 的多线程 C++ 应用程序解码失败【英文标题】:ffmpeg based multi threaded c++ application fails on decoding 【发布时间】:2016-04-28 16:28:12 【问题描述】:

我使用来自 ffmpeg 源的 remuxing 示例作为参考。我编写了一个基于 boost 线程的多线程应用程序,以使用 ffmpeg API 执行编解码器复制和 remux。这很好用。当我尝试解码帧时出现问题

"

 ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &pkt);
            if (ret < 0) 
                av_log(NULL, AV_LOG_ERROR, "Error decoding video %s\n",av_make_error_string(errorBuff,80,ret));
                return -1;
            "

我需要解码帧将其转换为 Opencv Mat 对象。对于单个实例,此代码可以正常工作。但是一旦我运行多个线程,我就会开始收到类似这样的解码错误

   left block unavailable for requested intra mode at 0 0
[h264 @ 0x7f9a48115100] error while decoding MB 0 0, bytestream 1479
[h264 @ 0x7f9a480825e0] number of reference frames (0+2) exceeds max (1; probably corrupt input), discarding one
[h264 @ 0x7f9a480ae680] error while decoding MB 13 5, bytestream -20
[h264 @ 0x7f9a48007700] number of reference frames (0+2) exceeds max (1; probably corrupt input), discarding one
[h264 @ 0x7f9a48110340] top block unavailable for requested intra4x4 mode -1 at 31 0
[h264 @ 0x7f9a48110340] error while decoding MB 31 0, bytestream 1226
[h264 @ 0x7f9a48115100] number of reference frames (0+2) exceeds max (1; probably corrupt input), discarding one
[h264 @ 0x7f9a480825e0] top block unavailable for requested intra4x4 mode -1 at 4 0
[h264 @ 0x7f9a480825e0] error while decoding MB 4 0, bytestream 1292
[h264 @ 0x7f9a480ae680] number of reference frames (0+2) exceeds max (1; probably corrupt input), discarding one

ffmpeg api 使用的所有变量都声明为线程函数的本地变量。我不确定 ffmpeg 框架分配或上下文分配是如何工作的。

在使解码过程多线程方面有什么帮助吗?

更新: 我已经包含了 ff_lockmgr

static int ff_lockmgr(void **mutex, enum AVLockOp op)

   pthread_mutex_t** pmutex = (pthread_mutex_t**) mutex;
   switch (op) 
   case AV_LOCK_CREATE:
      *pmutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
       pthread_mutex_init(*pmutex, NULL);
       break;
   case AV_LOCK_OBTAIN:
       pthread_mutex_lock(*pmutex);
       break;
   case AV_LOCK_RELEASE:
       pthread_mutex_unlock(*pmutex);
       break;
   case AV_LOCK_DESTROY:
       pthread_mutex_destroy(*pmutex);
       free(*pmutex);
       break;
   
   return 0;

并初始化它“av_lockmgr_register(ff_lockmgr);” 现在视频正在所有线程中解码,但使用 FFMPEG AVFrame 从解码帧保存的图像到 OpenCv Mat 转换和 imwrite 导致乱码(混合)帧。部分帧来自一台相机,其余部分来自另一台相机,否则图像根本没有任何意义。

【问题讨论】:

代码中有问题。根据发布指南提取一个最小示例以获得帮助(并帮助自己)。 您是否建议您自己设置“增强线程”并同时从多个线程在同一个 AVCodecContext 上调用 avcodec_decode_video2()?这不是 ffmpeg 多线程的工作方式,它不能那样工作,因为您需要调整线程锁定,以便从帧到帧的帧间预测工作。让 ffmpeg 处理它(它会自动处理),不要自己进行任何额外的线程设置。 不,我没有在同一个 AVCodecContext 上调用 avcodec_decode_video2()。我有多个 boost 线程,每个线程都有本地化变量,用于 AV* 库使用 AVCodecContext n 等。线程之间不共享任何数据。每个都有一个单独的视频输入和一个单独的视频输出。 【参考方案1】:

并非每个格式解码器都支持多线程,即使对于支持它的解码器,特定文件也可能不支持它。

例如,假设一个 MPEG4 文件的开头只有一个关键帧,然后是 P 帧。在这种情况下,每个下一帧都依赖于前一帧,并且使用多个线程可能不会产生任何好处。

因此,在我的应用中,我不得不禁用多线程编码器。

【讨论】:

我担心 H264 使用 (libx264) 并且我有多个线程,每个线程都有自己的 CodecContext 可以处理。 他们是在同一个流上工作,还是在不同的流上工作? 他们正在处理不同的流。基本上,ffmpeg 源代码中的整个 remuxing 示例已将其全局变量移至本地。以及由这些本地化函数组成的线程。所以他们之间不共享任何变量。每个线程都使用来自不同文件的自己的输入源。 这将假定 x264 编解码器内部是线程安全的,但情况可能并非如此。我会问 x264 编解码器的作者。

以上是关于基于 ffmpeg 的多线程 C++ 应用程序解码失败的主要内容,如果未能解决你的问题,请参考以下文章

C++使用ffmpeg硬解码

c++ 中的多线程线程安全动画建议

[音视频处理] FFmpeg使用指北1-视频解码

QT软件开发-基于FFMPEG设计视频播放器-支持软解与硬解

基于ffmpeg开发的多音频文件音量均衡程序

基于ffmpeg开发的多音频文件音量均衡程序