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
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)
{
......
......@@ -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);
......
......@@ -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
......@@ -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 &));
};
}
......
......@@ -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()
......
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