Commit ad21283f authored by Tristan Matthews's avatar Tristan Matthews
Browse files

* #13731: video: request key frame on error and before probing stream info

parent be2b649d
...@@ -1214,21 +1214,6 @@ void sendSIPInfo(const SIPCall &call, const char *const body, const char *const ...@@ -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); 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 void
dtmfSend(SIPCall &call, char code, const std::string &dtmf) dtmfSend(SIPCall &call, char code, const std::string &dtmf)
{ {
...@@ -1247,6 +1232,29 @@ 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 void
SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code) SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code)
{ {
......
...@@ -253,6 +253,10 @@ class SIPVoIPLink : public VoIPLink { ...@@ -253,6 +253,10 @@ class SIPVoIPLink : public VoIPLink {
SipTransport sipTransport; SipTransport sipTransport;
#ifdef SFL_VIDEO
static void requestFastPictureUpdate(const std::string &callID);
#endif
private: private:
NON_COPYABLE(SIPVoIPLink); NON_COPYABLE(SIPVoIPLink);
......
...@@ -141,6 +141,8 @@ void VideoReceiveThread::setup() ...@@ -141,6 +141,8 @@ void VideoReceiveThread::setup()
EXIT_IF_FAIL(ret == 0, "Could not open input \"%s\"", input.c_str()); EXIT_IF_FAIL(ret == 0, "Could not open input \"%s\"", input.c_str());
DEBUG("Finding stream info"); DEBUG("Finding stream info");
if (requestKeyFrameCallback_)
requestKeyFrameCallback_(id_);
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0) #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0)
ret = av_find_stream_info(inputCtx_); ret = av_find_stream_info(inputCtx_);
#else #else
...@@ -178,8 +180,6 @@ void VideoReceiveThread::setup() ...@@ -178,8 +180,6 @@ void VideoReceiveThread::setup()
dstHeight_ = decoderCtx_->height; dstHeight_ = decoderCtx_->height;
} }
// allocate video frame
rawFrame_ = avcodec_alloc_frame();
// determine required buffer size and allocate buffer // determine required buffer size and allocate buffer
bufferSize_ = getBufferSize(dstWidth_, dstHeight_, VIDEO_RGB_FORMAT); bufferSize_ = getBufferSize(dstWidth_, dstHeight_, VIDEO_RGB_FORMAT);
...@@ -210,7 +210,7 @@ VideoReceiveThread::VideoReceiveThread(const std::string &id, const std::map<str ...@@ -210,7 +210,7 @@ VideoReceiveThread::VideoReceiveThread(const std::string &id, const std::map<str
args_(args), frameNumber_(0), decoderCtx_(0), rawFrame_(0), args_(args), frameNumber_(0), decoderCtx_(0), rawFrame_(0),
scaledPicture_(0), streamIndex_(-1), inputCtx_(0), imgConvertCtx_(0), scaledPicture_(0), streamIndex_(-1), inputCtx_(0), imgConvertCtx_(0),
dstWidth_(0), dstHeight_(0), sink_(), receiving_(false), sdpFilename_(), dstWidth_(0), dstHeight_(0), sink_(), receiving_(false), sdpFilename_(),
bufferSize_(0), id_(id), interruptCb_() bufferSize_(0), id_(id), interruptCb_(), requestKeyFrameCallback_(0)
{ {
interruptCb_.callback = interruptCb; interruptCb_.callback = interruptCb;
interruptCb_.opaque = this; interruptCb_.opaque = this;
...@@ -241,22 +241,28 @@ void VideoReceiveThread::run() ...@@ -241,22 +241,28 @@ void VideoReceiveThread::run()
createScalingContext(); createScalingContext();
const Callback cb(&VideoReceiveThread::fill_buffer); const Callback cb(&VideoReceiveThread::fill_buffer);
AVFrame rawFrame;
rawFrame_ = &rawFrame;
while (receiving_) { while (receiving_) {
AVPacket inpacket; AVPacket inpacket;
int ret = 0; int ret = 0;
if ((ret = av_read_frame(inputCtx_, &inpacket)) < 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; break;
} }
// Guarantee that we free the packet every iteration // Guarantee that we free the packet every iteration
PacketHandle inpacket_handle(inpacket); PacketHandle inpacket_handle(inpacket);
avcodec_get_frame_defaults(rawFrame_);
// is this a packet from the video stream? // is this a packet from the video stream?
if (inpacket.stream_index == streamIndex_) { if (inpacket.stream_index == streamIndex_) {
int frameFinished = 0; int frameFinished = 0;
avcodec_decode_video2(decoderCtx_, rawFrame_, &frameFinished, const int len = avcodec_decode_video2(decoderCtx_, rawFrame_, &frameFinished,
&inpacket); &inpacket);
if (len <= 0 and requestKeyFrameCallback_)
requestKeyFrameCallback_(id_);
// we want our rendering code to be called by the shm_sink, // we want our rendering code to be called by the shm_sink,
// because it manages the shared memory synchronization // because it manages the shared memory synchronization
...@@ -279,9 +285,6 @@ VideoReceiveThread::~VideoReceiveThread() ...@@ -279,9 +285,6 @@ VideoReceiveThread::~VideoReceiveThread()
if (scaledPicture_) if (scaledPicture_)
av_free(scaledPicture_); av_free(scaledPicture_);
if (rawFrame_)
av_free(rawFrame_);
if (decoderCtx_) if (decoderCtx_)
avcodec_close(decoderCtx_); avcodec_close(decoderCtx_);
...@@ -293,4 +296,9 @@ VideoReceiveThread::~VideoReceiveThread() ...@@ -293,4 +296,9 @@ VideoReceiveThread::~VideoReceiveThread()
#endif #endif
} }
} }
void VideoReceiveThread::setRequestKeyFrameCallback(void (*cb)(const std::string &))
{
requestKeyFrameCallback_ = cb;
}
} // end namespace sfl_video } // end namespace sfl_video
...@@ -81,11 +81,13 @@ class VideoReceiveThread : public ost::Thread { ...@@ -81,11 +81,13 @@ class VideoReceiveThread : public ost::Thread {
void fill_buffer(void *data); void fill_buffer(void *data);
static int interruptCb(void *ctx); static int interruptCb(void *ctx);
AVIOInterruptCB interruptCb_; AVIOInterruptCB interruptCb_;
void (* requestKeyFrameCallback_)(const std::string &);
public: public:
VideoReceiveThread(const std::string &id, const std::map<std::string, std::string> &args); VideoReceiveThread(const std::string &id, const std::map<std::string, std::string> &args);
virtual ~VideoReceiveThread(); virtual ~VideoReceiveThread();
virtual void run(); virtual void run();
void setRequestKeyFrameCallback(void (*)(const std::string &));
}; };
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "video_send_thread.h" #include "video_send_thread.h"
#include "video_receive_thread.h" #include "video_receive_thread.h"
#include "sip/sdp.h" #include "sip/sdp.h"
#include "sip/sipvoiplink.h"
#include "libav_utils.h" #include "libav_utils.h"
#include "manager.h" #include "manager.h"
#include "logger.h" #include "logger.h"
...@@ -133,21 +134,19 @@ void VideoRtpSession::start() ...@@ -133,21 +134,19 @@ void VideoRtpSession::start()
WARN("Restarting video sender"); WARN("Restarting video sender");
sendThread_.reset(new VideoSendThread(txArgs_)); sendThread_.reset(new VideoSendThread(txArgs_));
sendThread_->start(); sendThread_->start();
} } else {
else
DEBUG("Video sending disabled"); DEBUG("Video sending disabled");
}
if (receiving_) { if (receiving_) {
if (receiveThread_.get()) { if (receiveThread_.get())
// FIXME: this is just until we fix onhold/offhold WARN("restarting video receiver");
WARN("Not restarting video receiver"); receiveThread_.reset(new VideoReceiveThread(callID_, rxArgs_));
} else { receiveThread_->setRequestKeyFrameCallback(&SIPVoIPLink::requestFastPictureUpdate);
receiveThread_.reset(new VideoReceiveThread(callID_, rxArgs_)); receiveThread_->start();
receiveThread_->start(); } else {
}
}
else
DEBUG("Video receiving disabled"); DEBUG("Video receiving disabled");
}
} }
void VideoRtpSession::stop() void VideoRtpSession::stop()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment