From e8a99a821c6f6a34ecc198b2006b1a3926941330 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?=
 <rafael.carre@savoirfairelinux.com>
Date: Thu, 30 Jun 2011 11:46:57 -0400
Subject: [PATCH] * #6277 : prevent concurrent calls to avcodec_{open,close}

---
 sflphone-common/src/managerimpl.h             | 13 +++++++++++++
 .../src/video/video_receive_thread.cpp        | 14 ++++++++++----
 .../src/video/video_send_thread.cpp           | 19 +++++++++++++------
 3 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h
index 043f203849..8eb7d229a8 100644
--- a/sflphone-common/src/managerimpl.h
+++ b/sflphone-common/src/managerimpl.h
@@ -1215,6 +1215,16 @@ class ManagerImpl
          */
         void audioLayerMutexUnlock(void) { _audiolayerMutex.leaveMutex(); }
 
+        /**
+         * Enter the mutex for libavcodec
+         */
+        void avcodecLock(void) { _avcodecMutex.enterMutex(); }
+
+        /**
+         * Leave the mutex for libavcodec
+         */
+        void avcodecUnlock(void) { _avcodecMutex.leaveMutex(); }
+
         /**
          * Helper function that creates an MD5 Hash from the credential
          * information provided as parameters. The hash is computed as
@@ -1288,6 +1298,9 @@ class ManagerImpl
         /** Protected current call access */
         ost::Mutex _currentCallMutex;
 
+        /** Protected libavcodec access */
+        ost::Mutex _avcodecMutex;
+
         /** Audio layer */
         AudioLayer* _audiodriver;
 
diff --git a/sflphone-common/src/video/video_receive_thread.cpp b/sflphone-common/src/video/video_receive_thread.cpp
index 3796500bba..4dc3169f6d 100644
--- a/sflphone-common/src/video/video_receive_thread.cpp
+++ b/sflphone-common/src/video/video_receive_thread.cpp
@@ -53,6 +53,8 @@ extern "C" {
 #include <time.h>
 #include <cstdlib>
 
+#include "manager.h"
+
 namespace sfl_video {
 
 namespace { // anonymouse namespace
@@ -263,8 +265,10 @@ void VideoReceiveThread::setup()
     }
 
     // open codec
-    // FIXME: calls to avcodec_open/close should be protected by a mutex
-    if (avcodec_open(decoderCtx_, inputDecoder) < 0)
+    Manager::instance().avcodecLock();
+    int ret = avcodec_open(decoderCtx_, inputDecoder);
+    Manager::instance().avcodecUnlock();
+    if (ret < 0)
     {
         std::cerr << "Could not open codec!" << std::endl;
         cleanup();
@@ -315,9 +319,11 @@ void VideoReceiveThread::cleanup()
         av_free(rawFrame_);
 
     // doesn't need to be freed, we didn't use avcodec_alloc_context
-    // FIXME: calls to avcodec_open/close should be protected by a mutex
-    if (decoderCtx_)
+    if (decoderCtx_) {
+        Manager::instance().avcodecLock();
         avcodec_close(decoderCtx_);
+        Manager::instance().avcodecUnlock();
+    }
 
     // close the video file
     if (inputCtx_)
diff --git a/sflphone-common/src/video/video_send_thread.cpp b/sflphone-common/src/video/video_send_thread.cpp
index 0b9b0538f6..f7903ff611 100644
--- a/sflphone-common/src/video/video_send_thread.cpp
+++ b/sflphone-common/src/video/video_send_thread.cpp
@@ -41,6 +41,8 @@ extern "C" {
 #include <libswscale/swscale.h>
 }
 
+#include "manager.h"
+
 namespace sfl_video {
 
 void VideoSendThread::print_error(const char *filename, int err)
@@ -132,6 +134,7 @@ void VideoSendThread::prepareEncoderContext()
 
 void VideoSendThread::setup()
 {
+    int ret;
     av_register_all();
     avdevice_register_all();
 
@@ -198,8 +201,10 @@ void VideoSendThread::setup()
     }
 
     // open codec
-    // FIXME: calls to avcodec_open/close should be protected by a mutex
-    if (avcodec_open(inputDecoderCtx_, inputDecoder) < 0)
+    Manager::instance().avcodecLock();
+    ret = avcodec_open(inputDecoderCtx_, inputDecoder);
+    Manager::instance().avcodecUnlock();
+    if (ret < 0)
     {
         std::cerr << "Could not open codec!" << std::endl;
         cleanup();
@@ -236,8 +241,10 @@ void VideoSendThread::setup()
     scaledPicture_ = avcodec_alloc_frame();
 
     // open encoder
-    // FIXME: calls to avcodec_open/close should be protected by a mutex
-    if (avcodec_open(encoderCtx_, encoder) < 0)
+    Manager::instance().avcodecLock();
+    ret = avcodec_open(encoderCtx_, encoder);
+    Manager::instance().avcodecUnlock();
+    if (ret < 0)
     {
         std::cerr << "Could not open encoder" << std::endl;
         cleanup();
@@ -318,7 +325,7 @@ void VideoSendThread::cleanup()
         av_free(rawFrame_);
 
     // close the codecs
-    // FIXME: calls to avcodec_open/close should be protected by a mutex
+    Manager::instance().avcodecLock();
     if (encoderCtx_)
     {
         avcodec_close(encoderCtx_);
@@ -326,9 +333,9 @@ void VideoSendThread::cleanup()
     }
 
     // doesn't need to be freed, we didn't use avcodec_alloc_context
-    // FIXME: calls to avcodec_open/close should be protected by a mutex
     if (inputDecoderCtx_)
         avcodec_close(inputDecoderCtx_);
+    Manager::instance().avcodecUnlock();
 
     // close the video file
     if (inputCtx_)
-- 
GitLab