Commit ecf3e901 authored by Philippe Gorley's avatar Philippe Gorley

accel: refactor and speed up fallback

Falling back from hardware to software decoding requires only a
reinitialization of the AVCodecContext. Hardware decoding failure is no
longer bubbled up to the RTP session, which makes it much faster.

Change-Id: I79fdfcfa41f822b3299d74ac654146789fcfd97b
parent cbff7d98
......@@ -304,8 +304,6 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
virtual void restartMediaSender() = 0;
virtual void restartMediaReceiver() = 0;
/**
* Update call details after creation.
* @param details to update
......
......@@ -438,17 +438,6 @@ AudioRtpSession::startReceiver()
receiveThread_->startLoop();
}
void
AudioRtpSession::restartReceiver()
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
// ensure that start has been called before restart
if (not socketPair_)
return;
startReceiver();
}
void
AudioRtpSession::start(std::unique_ptr<IceSocket> rtp_sock, std::unique_ptr<IceSocket> rtcp_sock)
{
......
......@@ -44,7 +44,6 @@ class AudioRtpSession : public RtpSession {
void start(std::unique_ptr<IceSocket> rtp_sock,
std::unique_ptr<IceSocket> rtcp_sock) override;
void restartSender() override;
void restartReceiver() override;
void stop() override;
void setMuted(bool isMuted);
......
......@@ -244,9 +244,11 @@ int MediaDecoder::setupFromVideoData()
static const unsigned MAX_ANALYZE_DURATION = 30; // time in seconds
inputCtx_->max_analyze_duration = MAX_ANALYZE_DURATION * AV_TIME_BASE;
RING_DBG("Finding stream info");
ret = avformat_find_stream_info(inputCtx_, NULL);
// if fallback from accel, don't check for stream info, it's already done
if (!fallback_) {
RING_DBG("Finding stream info");
ret = avformat_find_stream_info(inputCtx_, NULL);
}
if (ret < 0) {
// workaround for this bug:
// http://patches.libav.org/patch/22541/
......@@ -378,6 +380,7 @@ MediaDecoder::decode(VideoFrame& result)
if (accelFailures_ >= MAX_ACCEL_FAILURES) {
RING_ERR("Hardware decoding failure");
accelFailures_ = 0; // reset error count for next time
fallback_ = true;
return Status::RestartRequired;
}
}
......
......@@ -116,6 +116,8 @@ class MediaDecoder {
void extract(const std::map<std::string, std::string>& map, const std::string& key);
int correctPixFmt(int input_pix_fmt);
bool fallback_ = false;
#ifdef RING_ACCEL
bool enableAccel_ = true;
video::HardwareAccel accel_;
......
......@@ -41,7 +41,6 @@ public:
virtual void start(std::unique_ptr<IceSocket> rtp_sock,
std::unique_ptr<IceSocket> rtcp_sock) = 0;
virtual void restartSender() = 0;
virtual void restartReceiver() = 0;
virtual void stop() = 0;
virtual void updateMedia(const MediaDescription& send,
......
......@@ -38,7 +38,6 @@ using std::string;
VideoReceiveThread::VideoReceiveThread(const std::string& id,
const std::string &sdp,
const bool isReset,
uint16_t mtu) :
VideoGenerator::VideoGenerator()
, args_()
......@@ -48,8 +47,6 @@ VideoReceiveThread::VideoReceiveThread(const std::string& id,
, stream_(sdp)
, sdpContext_(stream_.str().size(), false, &readFunction, 0, 0, this)
, sink_ {Manager::instance().createSinkClient(id)}
, restartDecoder_(false)
, isReset_(isReset)
, mtu_(mtu)
, requestKeyFrameCallback_(0)
, loop_(std::bind(&VideoReceiveThread::setup, this),
......@@ -74,11 +71,6 @@ bool VideoReceiveThread::setup()
{
videoDecoder_.reset(new MediaDecoder());
#ifdef RING_ACCEL
// disable accel if there was a fallback to software decoding
videoDecoder_->enableAccel(!isReset_);
#endif
dstWidth_ = args_.width;
dstHeight_ = args_.height;
......@@ -188,9 +180,12 @@ bool VideoReceiveThread::decodeFrame()
break;
case MediaDecoder::Status::RestartRequired:
restartDecoder_ = true;
// disable accel, reset decoder's AVCodecContext
#ifdef RING_ACCEL
videoDecoder_->enableAccel(false);
#endif
videoDecoder_->setupFromVideoData();
break;
case MediaDecoder::Status::Success:
case MediaDecoder::Status::EOFError:
break;
......@@ -231,10 +226,6 @@ int VideoReceiveThread::getHeight() const
int VideoReceiveThread::getPixelFormat() const
{ return videoDecoder_->getPixelFormat(); }
bool
VideoReceiveThread::restartDecoder() const
{ return restartDecoder_.load(); }
void
VideoReceiveThread::triggerKeyFrameRequest()
{
......
......@@ -34,7 +34,6 @@
#include <climits>
#include <sstream>
#include <memory>
#include <atomic>
namespace ring {
class SocketPair;
......@@ -47,7 +46,7 @@ class SinkClient;
class VideoReceiveThread : public VideoGenerator {
public:
VideoReceiveThread(const std::string &id, const std::string &sdp, const bool isReset, uint16_t mtu);
VideoReceiveThread(const std::string &id, const std::string &sdp, uint16_t mtu);
~VideoReceiveThread();
void startLoop();
......@@ -60,7 +59,6 @@ public:
int getWidth() const;
int getHeight() const;
int getPixelFormat() const;
bool restartDecoder() const;
void triggerKeyFrameRequest();
private:
......@@ -79,7 +77,6 @@ private:
MediaIOHandle sdpContext_;
std::unique_ptr<MediaIOHandle> demuxContext_;
std::shared_ptr<SinkClient> sink_;
std::atomic_bool restartDecoder_;
bool isReset_;
uint16_t mtu_;
......
......@@ -60,9 +60,6 @@ VideoRtpSession::VideoRtpSession(const string &callID,
, rtcpCheckerThread_([] { return true; },
[this]{ processRtcpChecker(); },
[]{})
, receiverRestartThread_([]{ return true; },
[this]{ processReceiverRestart(); },
[]{})
, packetLossThread_([] { return true; },
[this]{ processPacketLoss(); },
[]{})
......@@ -151,24 +148,19 @@ VideoRtpSession::restartSender()
void VideoRtpSession::startReceiver()
{
if (receive_.enabled and not receive_.holding) {
bool isReset = false;
if (receiveThread_) {
if (receiveThread_)
RING_WARN("Restarting video receiver");
isReset = true;
}
receiveThread_.reset(
new VideoReceiveThread(callID_, receive_.receiving_sdp, isReset, mtu_)
new VideoReceiveThread(callID_, receive_.receiving_sdp, mtu_)
);
// XXX keyframe requests can timeout if unanswered
receiveThread_->setRequestKeyFrameCallback(&SIPVoIPLink::enqueueKeyframeRequest);
receiverRestartThread_.start();
receiveThread_->addIOContext(*socketPair_);
receiveThread_->startLoop();
packetLossThread_.start();
} else {
RING_DBG("Video receiving disabled");
receiverRestartThread_.join();
if (receiveThread_)
receiveThread_->detach(videoMixer_.get());
receiveThread_.reset();
......@@ -176,18 +168,6 @@ void VideoRtpSession::startReceiver()
}
}
void
VideoRtpSession::restartReceiver()
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
// ensure that start has been called before restart
if (not socketPair_)
return;
startReceiver();
}
void VideoRtpSession::start(std::unique_ptr<IceSocket> rtp_sock,
std::unique_ptr<IceSocket> rtcp_sock)
{
......@@ -225,7 +205,6 @@ void VideoRtpSession::stop()
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
rtcpCheckerThread_.join();
receiverRestartThread_.join();
packetLossThread_.join();
if (videoLocal_)
videoLocal_->detach(sender_.get());
......@@ -565,19 +544,6 @@ VideoRtpSession::storeVideoBitrateInfo() {
}
}
void
VideoRtpSession::checkReceiver()
{
if (receiveThread_ && receiveThread_->restartDecoder()) {
const auto& cid = callID_;
runOnMainThread([cid]{
if (auto call = Manager::instance().callFactory.getCall(cid)) {
call->restartMediaReceiver();
}
});
}
}
void
VideoRtpSession::processRtcpChecker()
{
......@@ -585,13 +551,6 @@ VideoRtpSession::processRtcpChecker()
rtcpCheckerThread_.wait_for(std::chrono::seconds(RTCP_CHECKING_INTERVAL));
}
void
VideoRtpSession::processReceiverRestart()
{
checkReceiver();
receiverRestartThread_.wait_for(std::chrono::seconds(RECEIVER_RESTART_INTERVAL));
}
void
VideoRtpSession::processPacketLoss()
{
......
......@@ -66,7 +66,6 @@ public:
void start(std::unique_ptr<IceSocket> rtp_sock,
std::unique_ptr<IceSocket> rtcp_sock) override;
void restartSender() override;
void restartReceiver() override;
void stop() override;
void forceKeyFrame();
......@@ -121,8 +120,6 @@ private:
// max size of quality and bitrate historic
static constexpr unsigned MAX_SIZE_HISTO_QUALITY_ {30};
static constexpr unsigned MAX_SIZE_HISTO_BITRATE_ {100};
// how long (in seconds) to wait before rechecking if the receiver needs to restart
const unsigned RECEIVER_RESTART_INTERVAL {4};
// 5 tries in a row
static constexpr unsigned MAX_ADAPTATIVE_BITRATE_ITERATION {5};
......@@ -133,9 +130,6 @@ private:
InterruptedThreadLoop rtcpCheckerThread_;
void processRtcpChecker();
InterruptedThreadLoop receiverRestartThread_;
void processReceiverRestart();
InterruptedThreadLoop packetLossThread_;
void processPacketLoss();
};
......
......@@ -946,16 +946,6 @@ SIPCall::restartMediaSender()
#endif
}
void
SIPCall::restartMediaReceiver()
{
RING_DBG("[call:%s] restarting RX media streams", getCallId().c_str());
avformatrtp_->restartReceiver();
#ifdef RING_VIDEO
videortp_->restartReceiver();
#endif
}
void
SIPCall::stopAllMedia()
{
......
......@@ -102,7 +102,6 @@ public: // overridden
void removeCall() override;
void muteMedia(const std::string& mediaType, bool isMuted) override;
void restartMediaSender() override;
void restartMediaReceiver() override;
bool useVideoCodec(const AccountVideoCodecInfo* codec) const override;
std::map<std::string, std::string> getDetails() const override;
......
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