Skip to content
Snippets Groups Projects
Commit ecf3e901 authored by Philippe Gorley's avatar Philippe Gorley
Browse files

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