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

fix fallback from hardware decoding to software

Fixes certain cases where the fallback to software decoding was
not done.

Change-Id: Ie0276a79f3d7434795876a7f417e7b0c6a0b8851
Reviewed-by : Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 56dd525c
No related branches found
No related tags found
No related merge requests found
......@@ -363,19 +363,33 @@ MediaDecoder::decode(VideoFrame& result)
int frameFinished = 0;
#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
ret = avcodec_send_packet(decoderCtx_, &inpacket);
if (ret < 0)
if (ret < 0) {
#ifdef RING_ACCEL
if (accel_->hasFailed())
return Status::RestartRequired;
#endif
return ret == AVERROR_EOF ? Status::Success : Status::DecodeError;
}
ret = avcodec_receive_frame(decoderCtx_, frame);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
#ifdef RING_ACCEL
if (accel_->hasFailed())
return Status::RestartRequired;
#endif
return Status::DecodeError;
}
if (ret >= 0)
frameFinished = 1;
#else
ret = avcodec_decode_video2(decoderCtx_, frame,
&frameFinished, &inpacket);
if (ret <= 0)
if (ret <= 0) {
#ifdef RING_ACCEL
if (accel_->hasFailed())
return Status::RestartRequired;
#endif
return Status::DecodeError;
}
#endif
av_packet_unref(&inpacket);
......
......@@ -81,11 +81,11 @@ allocateBufferCb(AVCodecContext* codecCtx, AVFrame* frame, int flags)
{
if (auto accel = static_cast<HardwareAccel*>(codecCtx->opaque)) {
if (!accel->hasFailed() && accel->allocateBuffer(frame, flags) == 0) {
accel->succeed();
accel->succeedAllocation();
return 0;
}
accel->fail(false);
accel->failAllocation();
}
return avcodec_default_get_buffer2(codecCtx, frame, flags);
......@@ -96,14 +96,28 @@ HardwareAccel::HardwareAccel(const std::string& name, const AVPixelFormat format
, format_(format)
{}
void
HardwareAccel::failAllocation()
{
++allocationFails_;
fail(false);
}
void
HardwareAccel::failExtraction()
{
++extractionFails_;
fail(false);
}
void
HardwareAccel::fail(bool forceFallback)
{
++failCount_;
if (failCount_ >= MAX_ACCEL_FAILURES || forceFallback) {
if (allocationFails_ >= MAX_ACCEL_FAILURES || extractionFails_ >= MAX_ACCEL_FAILURES || forceFallback) {
RING_ERR("Hardware acceleration failure");
fallback_ = true;
failCount_ = 0;
allocationFails_ = 0;
extractionFails_ = 0;
codecCtx_->get_format = avcodec_default_get_format;
codecCtx_->get_buffer2 = avcodec_default_get_buffer2;
}
......@@ -135,12 +149,12 @@ HardwareAccel::extractData(VideoFrame& input)
av_frame_unref(inFrame);
av_frame_move_ref(inFrame, outFrame);
} catch (const std::runtime_error& e) {
fail(false);
failExtraction();
RING_ERR("%s", e.what());
return false;
}
succeed();
succeedExtraction();
return true;
}
......
......@@ -43,8 +43,11 @@ class HardwareAccel {
void setHeight(int height) { height_ = height; }
void setProfile(int profile) { profile_ = profile; }
void failAllocation();
void failExtraction();
void fail(bool forceFallback);
void succeed() { failCount_ = 0; } // call on success of allocateBuffer or extractData
void succeedAllocation() { allocationFails_ = 0; }
void succeedExtraction() { extractionFails_ = 0; }
// wrapper to take care of boilerplate before calling the derived class's implementation
bool extractData(VideoFrame& input);
......@@ -59,8 +62,9 @@ class HardwareAccel {
AVCodecContext* codecCtx_ = nullptr;
std::string name_;
AVPixelFormat format_;
unsigned failCount_ = 0; // how many failures in a row, reset on success
bool fallback_ = false; // true when failCount_ exceeds a certain number
unsigned allocationFails_ = 0; // how many times in a row allocateBuffer has failed
unsigned extractionFails_ = 0; // how many times in a row extractData has failed
bool fallback_ = false; // set to true when successive failures exceeds MAX_ACCEL_FAILURES
int width_ = -1;
int height_ = -1;
int profile_ = -1;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment