diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index d24de327f2bbb5c0acde7fff637f250cd7f7a9b8..9004fe986f7497355f9a3f37e271d57b435ef335 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -1214,21 +1214,6 @@ void sendSIPInfo(const SIPCall &call, const char *const body, const char *const pjsip_dlg_send_request(call.inv->dlg, tdata, mod_ua_.id, NULL); } -#ifdef SFL_VIDEO -void -requestFastPictureUpdate(const SIPCall &call) -{ - const char * const BODY = - "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" - "<media_control><vc_primitive><to_encoder>" - "<picture_fast_update/>" - "</to_encoder></vc_primitive></media_control>"; - - DEBUG("Sending video keyframe request via SIP INFO"); - sendSIPInfo(call, BODY, "media_control+xml"); -} -#endif - void dtmfSend(SIPCall &call, char code, const std::string &dtmf) { @@ -1247,6 +1232,29 @@ dtmfSend(SIPCall &call, char code, const std::string &dtmf) } } +#ifdef SFL_VIDEO +void +SIPVoIPLink::requestFastPictureUpdate(const std::string &callID) +{ + SIPCall *call; + try { + call = SIPVoIPLink::instance()->getSIPCall(callID); + } catch (const VoipLinkException &e) { + ERROR("%s", e.what()); + return; + } + + const char * const BODY = + "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + "<media_control><vc_primitive><to_encoder>" + "<picture_fast_update/>" + "</to_encoder></vc_primitive></media_control>"; + + DEBUG("Sending video keyframe request via SIP INFO"); + sendSIPInfo(*call, BODY, "media_control+xml"); +} +#endif + void SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code) { diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 47f1c91dc607ad0635468e6bf4937f8047bfbf4a..b4706b411e9e733ce52c5bb729f7cb303ca47945 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -253,6 +253,10 @@ class SIPVoIPLink : public VoIPLink { SipTransport sipTransport; +#ifdef SFL_VIDEO + static void requestFastPictureUpdate(const std::string &callID); +#endif + private: NON_COPYABLE(SIPVoIPLink); diff --git a/daemon/src/video/video_receive_thread.cpp b/daemon/src/video/video_receive_thread.cpp index 9f91482fb2b022b651a9052d0b89fa23f1a16719..48da041d975809b51580d60a9e6457fb72532381 100644 --- a/daemon/src/video/video_receive_thread.cpp +++ b/daemon/src/video/video_receive_thread.cpp @@ -141,6 +141,8 @@ void VideoReceiveThread::setup() EXIT_IF_FAIL(ret == 0, "Could not open input \"%s\"", input.c_str()); DEBUG("Finding stream info"); + if (requestKeyFrameCallback_) + requestKeyFrameCallback_(id_); #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0) ret = av_find_stream_info(inputCtx_); #else @@ -178,8 +180,6 @@ void VideoReceiveThread::setup() dstHeight_ = decoderCtx_->height; } - // allocate video frame - rawFrame_ = avcodec_alloc_frame(); // determine required buffer size and allocate buffer bufferSize_ = getBufferSize(dstWidth_, dstHeight_, VIDEO_RGB_FORMAT); @@ -210,7 +210,7 @@ VideoReceiveThread::VideoReceiveThread(const std::string &id, const std::map<str args_(args), frameNumber_(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_() + bufferSize_(0), id_(id), interruptCb_(), requestKeyFrameCallback_(0) { interruptCb_.callback = interruptCb; interruptCb_.opaque = this; @@ -241,22 +241,28 @@ void VideoReceiveThread::run() createScalingContext(); const Callback cb(&VideoReceiveThread::fill_buffer); + AVFrame rawFrame; + rawFrame_ = &rawFrame; + while (receiving_) { AVPacket inpacket; int ret = 0; if ((ret = av_read_frame(inputCtx_, &inpacket)) < 0) { - ERROR("Couldn't read frame : %s\n", strerror(ret)); + ERROR("Couldn't read frame: %s\n", strerror(ret)); break; } // Guarantee that we free the packet every iteration PacketHandle inpacket_handle(inpacket); + avcodec_get_frame_defaults(rawFrame_); // is this a packet from the video stream? if (inpacket.stream_index == streamIndex_) { int frameFinished = 0; - avcodec_decode_video2(decoderCtx_, rawFrame_, &frameFinished, - &inpacket); + const int len = avcodec_decode_video2(decoderCtx_, rawFrame_, &frameFinished, + &inpacket); + if (len <= 0 and requestKeyFrameCallback_) + requestKeyFrameCallback_(id_); // we want our rendering code to be called by the shm_sink, // because it manages the shared memory synchronization @@ -279,9 +285,6 @@ VideoReceiveThread::~VideoReceiveThread() if (scaledPicture_) av_free(scaledPicture_); - if (rawFrame_) - av_free(rawFrame_); - if (decoderCtx_) avcodec_close(decoderCtx_); @@ -293,4 +296,9 @@ VideoReceiveThread::~VideoReceiveThread() #endif } } + +void VideoReceiveThread::setRequestKeyFrameCallback(void (*cb)(const std::string &)) +{ + requestKeyFrameCallback_ = cb; +} } // end namespace sfl_video diff --git a/daemon/src/video/video_receive_thread.h b/daemon/src/video/video_receive_thread.h index f36126bec6df4d87bfcafe10994559fc17c53959..e0d03a4a7ee73c9998788e6a1f30d21d2a3cfab9 100644 --- a/daemon/src/video/video_receive_thread.h +++ b/daemon/src/video/video_receive_thread.h @@ -81,11 +81,13 @@ class VideoReceiveThread : public ost::Thread { 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); virtual ~VideoReceiveThread(); virtual void run(); + void setRequestKeyFrameCallback(void (*)(const std::string &)); }; } diff --git a/daemon/src/video/video_rtp_session.cpp b/daemon/src/video/video_rtp_session.cpp index e6490cad9339112f666d0cdd30dda47be3b80a56..a1b755bc54f3ef1368790b45b761b989e33cb6b6 100644 --- a/daemon/src/video/video_rtp_session.cpp +++ b/daemon/src/video/video_rtp_session.cpp @@ -35,6 +35,7 @@ #include "video_send_thread.h" #include "video_receive_thread.h" #include "sip/sdp.h" +#include "sip/sipvoiplink.h" #include "libav_utils.h" #include "manager.h" #include "logger.h" @@ -133,21 +134,19 @@ void VideoRtpSession::start() WARN("Restarting video sender"); sendThread_.reset(new VideoSendThread(txArgs_)); sendThread_->start(); - } - else + } else { DEBUG("Video sending disabled"); + } if (receiving_) { - if (receiveThread_.get()) { - // FIXME: this is just until we fix onhold/offhold - WARN("Not restarting video receiver"); - } else { - receiveThread_.reset(new VideoReceiveThread(callID_, rxArgs_)); - receiveThread_->start(); - } - } - else + if (receiveThread_.get()) + WARN("restarting video receiver"); + receiveThread_.reset(new VideoReceiveThread(callID_, rxArgs_)); + receiveThread_->setRequestKeyFrameCallback(&SIPVoIPLink::requestFastPictureUpdate); + receiveThread_->start(); + } else { DEBUG("Video receiving disabled"); + } } void VideoRtpSession::stop()