Commit 2a9e7bb9 authored by Adrien Béraud's avatar Adrien Béraud Committed by Denys Vidal

KeyFrameRequest: use callback to request new key frame

Change-Id: Id7c250c83de49d0ae712bb5e1e95d3f11565efe9
parent 12932733
......@@ -238,6 +238,8 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
*/
virtual bool offhold() = 0;
virtual void sendKeyframe() = 0;
/**
* Peer has hung up a call
*/
......
......@@ -21,8 +21,8 @@
#ifndef CALL_FACTORY_H
#define CALL_FACTORY_H
#include <call.h>
#include <account.h>
#include "call.h"
#include "account.h"
#include <map>
#include <memory>
......
......@@ -111,7 +111,7 @@ bool VideoReceiveThread::setup()
}
if (requestKeyFrameCallback_)
requestKeyFrameCallback_(id_);
requestKeyFrameCallback_();
if (videoDecoder_->setupFromVideoData()) {
RING_ERR("decoder IO startup failed");
......@@ -191,7 +191,7 @@ bool VideoReceiveThread::decodeFrame()
case MediaDecoder::Status::DecodeError:
RING_WARN("video decoding failure");
if (requestKeyFrameCallback_)
requestKeyFrameCallback_(id_);
requestKeyFrameCallback_();
break;
case MediaDecoder::Status::ReadError:
......@@ -233,8 +233,7 @@ void VideoReceiveThread::exitConference()
sink_->setFrameSize(dstWidth_, dstHeight_);
}
void VideoReceiveThread::setRequestKeyFrameCallback(
void (*cb)(const std::string &))
void VideoReceiveThread::setRequestKeyFrameCallback(std::function<void (void)> cb)
{ requestKeyFrameCallback_ = cb; }
int VideoReceiveThread::getWidth() const
......@@ -256,7 +255,7 @@ void
VideoReceiveThread::triggerKeyFrameRequest()
{
if (requestKeyFrameCallback_)
requestKeyFrameCallback_(id_);
requestKeyFrameCallback_();
}
}} // namespace ring::video
......@@ -52,7 +52,7 @@ public:
void startLoop();
void addIOContext(SocketPair& socketPair);
void setRequestKeyFrameCallback(void (*)(const std::string &));
void setRequestKeyFrameCallback(std::function<void (void)>);
void enterConference();
void exitConference();
......@@ -82,7 +82,7 @@ private:
bool isReset_;
uint16_t mtu_;
void (*requestKeyFrameCallback_)(const std::string &);
std::function<void(void)> requestKeyFrameCallback_;
void openDecoder();
bool decodeFrame();
static int interruptCb(void *ctx);
......
......@@ -77,6 +77,12 @@ VideoRtpSession::updateMedia(const MediaDescription& send, const MediaDescriptio
setupVideoBitrateInfo();
}
void
VideoRtpSession::setRequestKeyFrameCallback(std::function<void(void)> cb)
{
requestKeyFrameCallback_ = cb;
}
void VideoRtpSession::startSender()
{
if (send_.enabled and not send_.holding) {
......@@ -157,7 +163,7 @@ void VideoRtpSession::startReceiver()
);
// XXX keyframe requests can timeout if unanswered
receiveThread_->setRequestKeyFrameCallback(&SIPVoIPLink::enqueueKeyframeRequest);
receiveThread_->setRequestKeyFrameCallback(requestKeyFrameCallback_);
receiveThread_->addIOContext(*socketPair_);
receiveThread_->startLoop();
packetLossThread_.start();
......@@ -558,7 +564,8 @@ VideoRtpSession::processPacketLoss()
{
if (packetLossThread_.wait_for(RTCP_PACKET_LOSS_INTERVAL,
[this]{return socketPair_->rtcpPacketLossDetected();})) {
receiveThread_->triggerKeyFrameRequest();
if (requestKeyFrameCallback_)
requestKeyFrameCallback_();
}
}
......
......@@ -62,6 +62,8 @@ public:
const DeviceParams& localVideoParams);
~VideoRtpSession();
void setRequestKeyFrameCallback(std::function<void(void)> cb);
void updateMedia(const MediaDescription& send, const MediaDescription& receive) override;
void start(std::unique_ptr<IceSocket> rtp_sock,
......@@ -102,6 +104,8 @@ private:
std::shared_ptr<VideoFrameActiveWriter> videoLocal_;
uint16_t initSeqVal_ = 0;
std::function<void (void)> requestKeyFrameCallback_;
float checkPeerPacketLoss();
unsigned getLowerQuality();
unsigned getLowerBitrate();
......
......@@ -41,6 +41,7 @@
#include "dring/media_const.h"
#include "client/ring_signal.h"
#include "ice_transport.h"
#include "thread_pool.h"
#ifdef RING_VIDEO
#include "client/videomanager.h"
......@@ -268,6 +269,23 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
}
void
SIPCall::requestKeyframe()
{
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>";
RING_DBG("Sending video keyframe request via SIP INFO");
try {
sendSIPInfo(BODY, "media_control+xml");
} catch (const std::exception& e) {
RING_ERR("Error sending video keyframe request: %s", e.what());
}
}
void
SIPCall::updateSDPFromSTUN()
{
......@@ -768,6 +786,19 @@ SIPCall::onAnswered()
}
}
void
SIPCall::sendKeyframe()
{
#ifdef RING_VIDEO
ThreadPool::instance().run([w = weak()] {
if (auto sthis = w.lock()) {
RING_DBG("handling picture fast update request");
sthis->getVideoRtp().forceKeyFrame();
}
});
#endif
}
void
SIPCall::onPeerRinging()
{
......@@ -857,6 +888,15 @@ SIPCall::startAllMedia()
bool peer_holding {true};
int slotN = -1;
#ifdef RING_VIDEO
videortp_->setRequestKeyFrameCallback([wthis = weak()] {
runOnMainThread([wthis] {
if (auto this_ = wthis.lock())
this_->requestKeyframe();
});
});
#endif
for (const auto& slot : slots) {
++slotN;
const auto& local = slot.first;
......
......@@ -103,6 +103,7 @@ public: // overridden
void muteMedia(const std::string& mediaType, bool isMuted) override;
void restartMediaSender() override;
bool useVideoCodec(const AccountVideoCodecInfo* codec) const override;
void sendKeyframe() override;
std::map<std::string, std::string> getDetails() const override;
virtual bool toggleRecording() override; // SIPCall needs to spread recorder to rtp sessions, so override
......@@ -159,6 +160,8 @@ public: // SIP related
void sendSIPInfo(const char *const body, const char *const subtype);
void requestKeyframe();
SIPAccountBase& getSIPAccount() const;
void updateSDPFromSTUN();
......@@ -249,6 +252,19 @@ private:
void merge(Call& call) override; // not public - only called by Call
inline std::shared_ptr<const SIPCall> shared() const {
return std::static_pointer_cast<const SIPCall>(shared_from_this());
}
inline std::shared_ptr<SIPCall> shared() {
return std::static_pointer_cast<SIPCall>(shared_from_this());
}
inline std::weak_ptr<const SIPCall> weak() const {
return std::weak_ptr<const SIPCall>(shared());
}
inline std::weak_ptr<SIPCall> weak() {
return std::weak_ptr<SIPCall>(shared());
}
std::unique_ptr<AudioRtpSession> avformatrtp_;
#ifdef RING_VIDEO
......
......@@ -728,39 +728,6 @@ void SIPVoIPLink::cancelKeepAliveTimer(pj_timer_entry& timer)
pjsip_endpt_cancel_timer(endpt_, &timer);
}
#ifdef RING_VIDEO
// Called from a video thread
void
SIPVoIPLink::enqueueKeyframeRequest(const std::string &id)
{
runOnMainThread([link = getSIPVoIPLink(), id] {
if (link)
link->requestKeyframe(id);
});
}
void
SIPVoIPLink::requestKeyframe(const std::string &callID)
{
auto call = Manager::instance().callFactory.getCall<SIPCall>(callID);
if (!call || call->getState() != Call::CallState::ACTIVE)
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>";
RING_DBG("Sending video keyframe request via SIP INFO");
try {
call->sendSIPInfo(BODY, "media_control+xml");
} catch (const std::exception& e) {
RING_WARN("Error sending video keyframe request: %s", e.what());
}
}
#endif
///////////////////////////////////////////////////////////////////////////////
// Private functions
///////////////////////////////////////////////////////////////////////////////
......@@ -993,10 +960,7 @@ handleMediaControl(SIPCall& call, pjsip_msg_body* body)
const pj_str_t PICT_FAST_UPDATE = CONST_PJ_STR("picture_fast_update");
if (pj_strstr(&control_st, &PICT_FAST_UPDATE)) {
#ifdef RING_VIDEO
RING_DBG("handling picture fast update request");
call.getVideoRtp().forceKeyFrame();
#endif
call.sendKeyframe();
return true;
}
}
......
......@@ -107,10 +107,6 @@ class SIPVoIPLink {
*/
std::unique_ptr<SipTransportBroker> sipTransportBroker;
#ifdef RING_VIDEO
static void enqueueKeyframeRequest(const std::string &callID);
#endif
typedef std::function<void(std::vector<IpAddr>)> SrvResolveCallback;
void resolveSrvName(const std::string &name, pjsip_transport_type_e type, SrvResolveCallback cb);
......
Markdown is supported
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