diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am index 16c87391cfc9abf537a8eba9435850323bdd7f72..8841259fd579ca989d7c225108683c126f1adc59 100644 --- a/daemon/src/sip/Makefile.am +++ b/daemon/src/sip/Makefile.am @@ -14,9 +14,7 @@ libsiplink_la_SOURCES = \ sipvoiplink.h \ siptransport.h \ sip_utils.cpp \ - sip_utils.h \ - sip_thread_client.h \ - sip_thread_client.cpp + sip_utils.h 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 deleted file mode 100644 index e657e9efd9e0fc89c9f08102a4e25e4e30aacca0..0000000000000000000000000000000000000000 --- a/daemon/src/sip/sip_thread_client.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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" -#include <cstring> - -SIPThreadClient::SIPThreadClient() : thread_(0), desc_() -{ - memset(desc_, 0, sizeof(desc_)); - // 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"); - if (pj_thread_join(thread_) != PJ_SUCCESS) { - ERROR("Error on thread join"); - } else if (pj_thread_destroy(thread_) != PJ_SUCCESS) { - ERROR("Error on thread destroy"); - } - thread_ = 0; - } -} diff --git a/daemon/src/sip/sip_thread_client.h b/daemon/src/sip/sip_thread_client.h deleted file mode 100644 index e1aa36317fcc237ccf47270af1e8c9df96a91d29..0000000000000000000000000000000000000000 --- a/daemon/src/sip/sip_thread_client.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index cb4cf0ed41e1a202965b74c8837005bd3ec17c4e..b9028fb11aa49e77f36cd0edaeae292a6c37c629 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -415,6 +415,10 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), sipAccountMap_(), sipCallMapMutex_(), sipCallMap_(), evThread_(this) +#ifdef SFL_VIDEO + , keyframeRequestsMutex_() + , keyframeRequests_() +#endif { #define TRY(ret) do { \ if (ret != PJ_SUCCESS) \ @@ -561,6 +565,9 @@ bool SIPVoIPLink::getEvent() static const pj_time_val timeout = {0, 10}; pjsip_endpt_handle_events(endpt_, &timeout); +#ifdef SFL_VIDEO + dequeKeyframeRequests(); +#endif return handlingEvents_; } @@ -1084,10 +1091,11 @@ SIPVoIPLink::getSipCall(const std::string& id) } SIPCall* -SIPVoIPLink::tryGetSipCall(const std::string &id) +SIPVoIPLink::tryGetSIPCall(const std::string &id) { if (not sipCallMapMutex_.tryEnterMutex()) { ERROR("Could not lock call map mutex"); + sipCallMapMutex_.leaveMutex(); return 0; } SipCallMap::iterator iter = sipCallMap_.find(id); @@ -1278,13 +1286,35 @@ dtmfSend(SIPCall &call, char code, const std::string &dtmf) } #ifdef SFL_VIDEO +// Called from a video thread +void +SIPVoIPLink::enqueueKeyframeRequest(const std::string &id) +{ + ost::MutexLock m(instance_->keyframeRequestsMutex_); + instance_->keyframeRequests_.push(id); +} + +// Called from SIP event thread +void +SIPVoIPLink::dequeKeyframeRequests() +{ + int max_requests = 20; + while (not keyframeRequests_.empty() and max_requests--) { + ost::MutexLock m(keyframeRequestsMutex_); + const std::string &id(keyframeRequests_.front()); + requestKeyframe(id); + keyframeRequests_.pop(); + } +} + +// Called from SIP event thread void -SIPVoIPLink::requestFastPictureUpdate(const std::string &callID) +SIPVoIPLink::requestKeyframe(const std::string &callID) { SIPCall *call = 0; const int tries = 10; for (int i = 0; !call and i < tries; ++i) - call = SIPVoIPLink::instance()->tryGetSipCall(callID); + call = SIPVoIPLink::instance()->tryGetSIPCall(callID); if (!call) return; diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 924915be9ed558784d7bf98040bb62b870b400f5..f261df94206b37fc197cb665d30fa3b75ff8dfd8 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -48,6 +48,9 @@ #include <pjlib-util.h> #include <pjnath.h> #include <pjnath/stun_config.h> +#ifdef SFL_VIDEO +#include <queue> +#endif #include "sipaccount.h" #include "voiplink.h" @@ -283,9 +286,8 @@ class SIPVoIPLink : public VoIPLink { SipTransport sipTransport; #ifdef SFL_VIDEO - static void requestFastPictureUpdate(const std::string &callID); + static void enqueueKeyframeRequest(const std::string &callID); #endif - private: NON_COPYABLE(SIPVoIPLink); @@ -313,6 +315,13 @@ class SIPVoIPLink : public VoIPLink { */ EventThread evThread_; +#ifdef SFL_VIDEO + void dequeKeyframeRequests(); + void requestKeyframe(const std::string &callID); + ost::Mutex keyframeRequestsMutex_; + std::queue<std::string> keyframeRequests_; +#endif + static bool destroyed_; static SIPVoIPLink *instance_; diff --git a/daemon/src/video/video_receive_thread.cpp b/daemon/src/video/video_receive_thread.cpp index 6ecb00d31c5eec2a107fd24c5feafc70d3df9cf2..6abd23b36090c9473fb4b43d7a80463ae0a11acf 100644 --- a/daemon/src/video/video_receive_thread.cpp +++ b/daemon/src/video/video_receive_thread.cpp @@ -32,7 +32,6 @@ #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 @@ -157,10 +156,9 @@ void VideoReceiveThread::setup() ERROR("Could not remove %s", sdpFilename_.c_str()); DEBUG("Finding stream info"); - if (requestKeyFrameCallback_) { - sipThreadClient_.reset(new SIPThreadClient); + if (requestKeyFrameCallback_) requestKeyFrameCallback_(id_); - } + #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0) ret = av_find_stream_info(inputCtx_); #else @@ -223,8 +221,7 @@ 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_(), threadRunning_(false), - sdpFilename_(), bufferSize_(0), id_(id), interruptCb_(), requestKeyFrameCallback_(0), - sipThreadClient_(0) + sdpFilename_(), bufferSize_(0), id_(id), interruptCb_(), requestKeyFrameCallback_(0) { interruptCb_.callback = interruptCb; interruptCb_.opaque = this; @@ -299,7 +296,6 @@ void VideoReceiveThread::run() VideoReceiveThread::~VideoReceiveThread() { threadRunning_ = false; - sipThreadClient_.reset(0); Manager::instance().getVideoControls()->stoppedDecoding(id_, sink_.openedName()); // this calls join, which waits for the run() method (in separate thread) to return ost::Thread::terminate(); diff --git a/daemon/src/video/video_receive_thread.h b/daemon/src/video/video_receive_thread.h index 4dd706ba3fcbddab576d85a4b77f93cc60c98da5..a908972b8d639ea780734ac3def5cd264f6e56f8 100644 --- a/daemon/src/video/video_receive_thread.h +++ b/daemon/src/video/video_receive_thread.h @@ -35,7 +35,6 @@ #include <map> #include <string> #include <climits> -#include <memory> #include "shm_sink.h" #include "noncopyable.h" @@ -48,8 +47,6 @@ class AVCodecContext; class AVStream; class AVFormatContext; class AVFrame; -class SIPThreadClient; - namespace sfl_video { class VideoReceiveThread : public ost::Thread { @@ -84,8 +81,6 @@ class VideoReceiveThread : public ost::Thread { 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(); diff --git a/daemon/src/video/video_rtp_session.cpp b/daemon/src/video/video_rtp_session.cpp index 97c655a5b738b45198be45a790018ce702cccd3a..ceb0c25b7afa4cbc97be74cb73d739a56d420c75 100644 --- a/daemon/src/video/video_rtp_session.cpp +++ b/daemon/src/video/video_rtp_session.cpp @@ -133,7 +133,7 @@ void VideoRtpSession::start() if (receiveThread_.get()) WARN("restarting video receiver"); receiveThread_.reset(new VideoReceiveThread(callID_, rxArgs_)); - receiveThread_->setRequestKeyFrameCallback(&SIPVoIPLink::requestFastPictureUpdate); + receiveThread_->setRequestKeyFrameCallback(&SIPVoIPLink::enqueueKeyframeRequest); receiveThread_->start(); } else { DEBUG("Video receiving disabled");