Skip to content

Commit

Permalink
accel: refactor and speed up fallback
Browse files Browse the repository at this point in the history
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
  • Loading branch information
philippegorley committed Jan 15, 2018
1 parent cbff7d9 commit ecf3e90
Show file tree
Hide file tree
Showing 12 changed files with 16 additions and 96 deletions.
2 changes: 0 additions & 2 deletions src/call.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 0 additions & 11 deletions src/media/audio/audio_rtp_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
1 change: 0 additions & 1 deletion src/media/audio/audio_rtp_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
9 changes: 6 additions & 3 deletions src/media/media_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down Expand Up @@ -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;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/media/media_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down
1 change: 0 additions & 1 deletion src/media/rtp_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class RtpSession {
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,
Expand Down
19 changes: 5 additions & 14 deletions src/media/video/video_receive_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_()
Expand All @@ -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),
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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()
{
Expand Down
5 changes: 1 addition & 4 deletions src/media/video/video_receive_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include <climits>
#include <sstream>
#include <memory>
#include <atomic>

namespace ring {
class SocketPair;
Expand All @@ -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();

Expand All @@ -60,7 +59,6 @@ class VideoReceiveThread : public VideoGenerator {
int getWidth() const;
int getHeight() const;
int getPixelFormat() const;
bool restartDecoder() const;
void triggerKeyFrameRequest();

private:
Expand All @@ -79,7 +77,6 @@ class VideoReceiveThread : public VideoGenerator {
MediaIOHandle sdpContext_;
std::unique_ptr<MediaIOHandle> demuxContext_;
std::shared_ptr<SinkClient> sink_;
std::atomic_bool restartDecoder_;
bool isReset_;
uint16_t mtu_;

Expand Down
45 changes: 2 additions & 43 deletions src/media/video/video_rtp_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ VideoRtpSession::VideoRtpSession(const string &callID,
, rtcpCheckerThread_([] { return true; },
[this]{ processRtcpChecker(); },
[]{})
, receiverRestartThread_([]{ return true; },
[this]{ processReceiverRestart(); },
[]{})
, packetLossThread_([] { return true; },
[this]{ processPacketLoss(); },
[]{})
Expand Down Expand Up @@ -151,43 +148,26 @@ 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();
packetLossThread_.join();
}
}

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)
{
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -565,33 +544,13 @@ 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()
{
adaptQualityAndBitrate();
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()
{
Expand Down
6 changes: 0 additions & 6 deletions src/media/video/video_rtp_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ class VideoRtpSession : 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 forceKeyFrame();
Expand Down Expand Up @@ -121,8 +120,6 @@ class VideoRtpSession : public RtpSession {
// 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};
Expand All @@ -133,9 +130,6 @@ class VideoRtpSession : public RtpSession {
InterruptedThreadLoop rtcpCheckerThread_;
void processRtcpChecker();

InterruptedThreadLoop receiverRestartThread_;
void processReceiverRestart();

InterruptedThreadLoop packetLossThread_;
void processPacketLoss();
};
Expand Down
10 changes: 0 additions & 10 deletions src/sip/sipcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
1 change: 0 additions & 1 deletion src/sip/sipcall.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ class SIPCall : public Call
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;

Expand Down

0 comments on commit ecf3e90

Please sign in to comment.