Thread Safety of LibAv/FFMpeg?

Thread Safety of LibAv/FFMpeg?

本文关键字:FFMpeg LibAv Safety of Thread      更新时间:2023-10-16

LibAV/FFMpeg 线程安全吗?例如。我可以在一个线程中使用 AVFormatContext* 从文件中读取文件,并通过简单添加互斥锁在另一个线程中解码读取数据包,还是库的线程安全性是"不知道不在乎"类型的交易?我知道 libav 对编码器线程有基本的支持,但我正在尝试更多的黑盒类型方法,将其分解为多个线程(源 -> 解码器 -> 过滤器 -> 编码器 -> 接收器)并试图了解这种复杂性。

任何对 ffmpeg 和线程有任何经验并希望提供与此相关的任何其他信息的人也将不胜感激。

您可以注册自己的锁管理器。ffmpeg 库将控制线程安全。

例:

::av_lockmgr_register(&my_lockmgr_cb);
 
 //// ..........
int my_lockmgr_cb(void **mutex, enum AVLockOp op)
{
  if (NULL == mutex)
    return -1;
  switch(op)
  {
   case AV_LOCK_CREATE:
   {
    *mutex = NULL;
    boost::mutex * m = new boost::mutex();
    *mutex = static_cast<void*>(m);
    break;
   }
   case AV_LOCK_OBTAIN:
   {
    boost::mutex * m =  static_cast<boost::mutex*>(*mutex);
    m->lock();
    break;
   }
   case AV_LOCK_RELEASE:
   {
    boost::mutex * m = static_cast<boost::mutex*>(*mutex);
    m->unlock();
    break;
   }
   case AV_LOCK_DESTROY:
   {
    boost::mutex * m = static_cast<boost::mutex*>(*mutex);
    delete m;
    break;
   }
   default:
   break;
  }
  return 0;
}

要扩展现有答案:

FFMPEG的av_lockmgr_register()是处理锁定的方法。

带有线程的 ffmpeg 构建(以及比 LIBAVCODEC_VERSION_MAJOR 55LIBAVCODEC_VERSION_MINOR 38LIBAVCODEC_VERSION_MICRO 100 更高的版本 - 大约在 2013 年 10 月,请参阅 ffmpeg 提交添加默认 lockmgr)将有一个您可以使用的默认锁管理器。

如果您需要与 libav 兼容,那么(在撰写本文时,2016 年 9 月)它还没有默认的锁管理器,您需要提供自己的锁管理器。

下面是一个纯 C pthread 的实现:

static int ffmpeg_lockmgr_cb(void **arg, enum AVLockOp op)
{
    pthread_mutex_t *mutex = *arg;
    int err;
    switch (op) {
    case AV_LOCK_CREATE:
        mutex = malloc(sizeof(*mutex));
        if (!mutex)
            return AVERROR(ENOMEM);
        if ((err = pthread_mutex_init(mutex, NULL))) {
            free(mutex);
            return AVERROR(err);
        }
        *arg = mutex;
        return 0;
    case AV_LOCK_OBTAIN:
        if ((err = pthread_mutex_lock(mutex)))
            return AVERROR(err);
        return 0;
    case AV_LOCK_RELEASE:
        if ((err = pthread_mutex_unlock(mutex)))
            return AVERROR(err);
        return 0;
    case AV_LOCK_DESTROY:
        if (mutex)
            pthread_mutex_destroy(mutex);
        free(mutex);
        *arg = NULL;
        return 0;
    }
    return 1;
}

注册方式如下:

ret = av_lockmgr_register(ffmpeg_lockmgr_cb);
if (ret < 0)
{
    fprintf(stderr, "av_lockmgr_register failed (%d)n", ret);
    abort();
}