2012-12-15 71 views
4

LibAV/FFMpeg線程安全嗎?例如。我可以在一個線程中使用AVFormatContext *讀取文件,並在另一個線程中解讀讀取的數據包,只需添加一些互斥體,或者是庫的線程安全性「不知道不關心」類型處理?我知道libav對編碼器線程有基本的支持,但我正在嘗試更多的黑盒類型方法,我將它分解爲多個線程(Source - > Decoder - > Filter - > Encoder - > Sink)並嘗試理解這些併發症這樣的。LibAv/FFMpeg的線程安全性?

任何有任何ffmpeg和線程經驗的人都想要和其他任何與此相關的信息參與其中也將不勝感激。

+3

我不能完全肯定,所以我不會做這樣的一個答案,但我認爲基本思想是庫是線程安全的,但調用者必須確保一次只有一個線程訪問單個av對象。 –

回答

6

您可以註冊您自己的鎖定管理器。 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; 

}

+0

如果使用'--enable-pthreads'構建FFmpeg,FFmpeg將自動使用其自己的默認鎖管理器實現,因此不需要調用'av_lockmgr_register()'。 – smokris

0

要擴大現有的答案:

FFmpeg的av_lockmgr_register是對付鎖定的方式。

的ffmpeg的構建與線程(和更高版本比LIBAVCODEC_VERSION_MAJOR 55,LIBAVCODEC_VERSION_MINOR 38和LIBAVCODEC_VERSION_MICRO 100 - 大致佔2013年10月,見ffmpeg commit adding default lockmgr)將有你可以只使用一個默認的鎖管理器。

如果您需要與libav兼容(在寫作時,2016年9月),這還沒有默認鎖定管理器,您需要提供自己的。

這是一個純C並行線程的實現:

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(); 
}