From c95781a42572e4fa2432a2fb39f890d99511478f Mon Sep 17 00:00:00 2001
From: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
Date: Thu, 2 Aug 2012 11:28:21 -0400
Subject: [PATCH] * #14176: sip/video: register video threads with pjsip before
 calling its functions

---
 daemon/src/sip/Makefile.am                |  4 +-
 daemon/src/sip/sip_thread_client.cpp      | 48 ++++++++++++++++++++++
 daemon/src/sip/sip_thread_client.h        | 50 +++++++++++++++++++++++
 daemon/src/video/video_receive_thread.cpp |  9 +++-
 daemon/src/video/video_receive_thread.h   |  9 +++-
 5 files changed, 115 insertions(+), 5 deletions(-)
 create mode 100644 daemon/src/sip/sip_thread_client.cpp
 create mode 100644 daemon/src/sip/sip_thread_client.h

diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am
index 8841259fd5..16c87391cf 100644
--- a/daemon/src/sip/Makefile.am
+++ b/daemon/src/sip/Makefile.am
@@ -14,7 +14,9 @@ libsiplink_la_SOURCES = \
 		sipvoiplink.h \
 		siptransport.h \
 		sip_utils.cpp \
-		sip_utils.h
+		sip_utils.h \
+		sip_thread_client.h \
+		sip_thread_client.cpp
 
 if BUILD_SDES
 libsiplink_la_SOURCES+= sdes_negotiator.cpp \
diff --git a/daemon/src/sip/sip_thread_client.cpp b/daemon/src/sip/sip_thread_client.cpp
new file mode 100644
index 0000000000..76e4977972
--- /dev/null
+++ b/daemon/src/sip/sip_thread_client.cpp
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (C) 2012 Savoir-Faire Linux Inc.
+ *  Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#include "sip_thread_client.h"
+#include "logger.h"
+
+SIPThreadClient::SIPThreadClient() : thread_(0)
+{
+    // We have to register the external thread so it can access the pjsip frameworks
+    if (pj_thread_register(NULL, desc_, &thread_) != PJ_SUCCESS)
+        ERROR("Could not register thread");
+}
+
+SIPThreadClient::~SIPThreadClient()
+{
+    if (thread_) {
+        WARN("Destroying thread handle");
+        pj_thread_join(thread_);
+        pj_thread_destroy(thread_);
+    }
+}
diff --git a/daemon/src/sip/sip_thread_client.h b/daemon/src/sip/sip_thread_client.h
new file mode 100644
index 0000000000..e1aa36317f
--- /dev/null
+++ b/daemon/src/sip/sip_thread_client.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (C) 2011 Savoir-Faire Linux Inc.
+ *  Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#ifndef SIP_THREAD_CLIENT_H_
+#define SIP_THREAD_CLIENT_H_
+
+#include "pj/os.h"
+#include "noncopyable.h"
+
+class pj_thread_t;
+
+class SIPThreadClient {
+    private:
+        NON_COPYABLE(SIPThreadClient);
+        pj_thread_t *thread_;
+        pj_thread_desc desc_;
+
+    public:
+        SIPThreadClient();
+        ~SIPThreadClient();
+};
+
+#endif // SIP_THREAD_CLIENT_H_
diff --git a/daemon/src/video/video_receive_thread.cpp b/daemon/src/video/video_receive_thread.cpp
index 39b12a9475..953a457e95 100644
--- a/daemon/src/video/video_receive_thread.cpp
+++ b/daemon/src/video/video_receive_thread.cpp
@@ -32,6 +32,7 @@
 #include "video_receive_thread.h"
 #include "dbus/video_controls.h"
 #include "packet_handle.h"
+#include "sip/sip_thread_client.h"
 #include "check.h"
 
 // libav includes
@@ -153,8 +154,10 @@ void VideoReceiveThread::setup()
     EXIT_IF_FAIL(ret == 0, "Could not open input \"%s\"", input.c_str());
 
     DEBUG("Finding stream info");
-    if (requestKeyFrameCallback_)
+    if (requestKeyFrameCallback_) {
+        sipThreadClient_.reset(new SIPThreadClient);
         requestKeyFrameCallback_(id_);
+    }
 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0)
     ret = av_find_stream_info(inputCtx_);
 #else
@@ -217,7 +220,8 @@ VideoReceiveThread::VideoReceiveThread(const std::string &id, const std::map<str
     args_(args), frameNumber_(0), inputDecoder_(0), decoderCtx_(0), rawFrame_(0),
     scaledPicture_(0), streamIndex_(-1), inputCtx_(0), imgConvertCtx_(0),
     dstWidth_(0), dstHeight_(0), sink_(), receiving_(false), sdpFilename_(),
-    bufferSize_(0), id_(id), interruptCb_(), requestKeyFrameCallback_(0)
+    bufferSize_(0), id_(id), interruptCb_(), requestKeyFrameCallback_(0),
+    sipThreadClient_(0)
 {
     interruptCb_.callback = interruptCb;
     interruptCb_.opaque = this;
@@ -281,6 +285,7 @@ void VideoReceiveThread::run()
         }
         yield();
     }
+    sipThreadClient_.reset();
 }
 
 VideoReceiveThread::~VideoReceiveThread()
diff --git a/daemon/src/video/video_receive_thread.h b/daemon/src/video/video_receive_thread.h
index ac9efa098b..fccacf04ec 100644
--- a/daemon/src/video/video_receive_thread.h
+++ b/daemon/src/video/video_receive_thread.h
@@ -35,6 +35,7 @@
 #include <map>
 #include <string>
 #include <climits>
+#include <memory>
 #include "shm_sink.h"
 #include "noncopyable.h"
 
@@ -47,6 +48,7 @@ class AVCodecContext;
 class AVStream;
 class AVFormatContext;
 class AVFrame;
+class SIPThreadClient;
 
 namespace sfl_video {
 
@@ -76,14 +78,17 @@ class VideoReceiveThread : public ost::Thread {
         std::string sdpFilename_;
         size_t bufferSize_;
         const std::string id_;
+        AVIOInterruptCB interruptCb_;
+        void (* requestKeyFrameCallback_)(const std::string &);
+        // XXX: This must be allocated in the video thread, not the main thread
+        std::auto_ptr<SIPThreadClient> sipThreadClient_;
+
         void setup();
         void openDecoder();
         void createScalingContext();
         void loadSDP();
         void fill_buffer(void *data);
         static int interruptCb(void *ctx);
-        AVIOInterruptCB interruptCb_;
-        void (* requestKeyFrameCallback_)(const std::string &);
 
     public:
         VideoReceiveThread(const std::string &id, const std::map<std::string, std::string> &args);
-- 
GitLab