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) ...@@ -363,19 +363,33 @@ MediaDecoder::decode(VideoFrame& result)
int frameFinished = 0; int frameFinished = 0;
#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) #if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101)
ret = avcodec_send_packet(decoderCtx_, &inpacket); 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; return ret == AVERROR_EOF ? Status::Success : Status::DecodeError;
}
ret = avcodec_receive_frame(decoderCtx_, frame); 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; return Status::DecodeError;
}
if (ret >= 0) if (ret >= 0)
frameFinished = 1; frameFinished = 1;
#else #else
ret = avcodec_decode_video2(decoderCtx_, frame, ret = avcodec_decode_video2(decoderCtx_, frame,
&frameFinished, &inpacket); &frameFinished, &inpacket);
if (ret <= 0) if (ret <= 0) {
#ifdef RING_ACCEL
if (accel_->hasFailed())
return Status::RestartRequired;
#endif
return Status::DecodeError; return Status::DecodeError;
}
#endif #endif
av_packet_unref(&inpacket); av_packet_unref(&inpacket);
......
...@@ -81,11 +81,11 @@ allocateBufferCb(AVCodecContext* codecCtx, AVFrame* frame, int flags) ...@@ -81,11 +81,11 @@ allocateBufferCb(AVCodecContext* codecCtx, AVFrame* frame, int flags)
{ {
if (auto accel = static_cast<HardwareAccel*>(codecCtx->opaque)) { if (auto accel = static_cast<HardwareAccel*>(codecCtx->opaque)) {
if (!accel->hasFailed() && accel->allocateBuffer(frame, flags) == 0) { if (!accel->hasFailed() && accel->allocateBuffer(frame, flags) == 0) {
accel->succeed(); accel->succeedAllocation();
return 0; return 0;
} }
accel->fail(false); accel->failAllocation();
} }
return avcodec_default_get_buffer2(codecCtx, frame, flags); return avcodec_default_get_buffer2(codecCtx, frame, flags);
...@@ -96,14 +96,28 @@ HardwareAccel::HardwareAccel(const std::string& name, const AVPixelFormat format ...@@ -96,14 +96,28 @@ HardwareAccel::HardwareAccel(const std::string& name, const AVPixelFormat format
, format_(format) , format_(format)
{} {}
void
HardwareAccel::failAllocation()
{
++allocationFails_;
fail(false);
}
void
HardwareAccel::failExtraction()
{
++extractionFails_;
fail(false);
}
void void
HardwareAccel::fail(bool forceFallback) HardwareAccel::fail(bool forceFallback)
{ {
++failCount_; if (allocationFails_ >= MAX_ACCEL_FAILURES || extractionFails_ >= MAX_ACCEL_FAILURES || forceFallback) {
if (failCount_ >= MAX_ACCEL_FAILURES || forceFallback) {
RING_ERR("Hardware acceleration failure"); RING_ERR("Hardware acceleration failure");
fallback_ = true; fallback_ = true;
failCount_ = 0; allocationFails_ = 0;
extractionFails_ = 0;
codecCtx_->get_format = avcodec_default_get_format; codecCtx_->get_format = avcodec_default_get_format;
codecCtx_->get_buffer2 = avcodec_default_get_buffer2; codecCtx_->get_buffer2 = avcodec_default_get_buffer2;
} }
...@@ -135,12 +149,12 @@ HardwareAccel::extractData(VideoFrame& input) ...@@ -135,12 +149,12 @@ HardwareAccel::extractData(VideoFrame& input)
av_frame_unref(inFrame); av_frame_unref(inFrame);
av_frame_move_ref(inFrame, outFrame); av_frame_move_ref(inFrame, outFrame);
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
fail(false); failExtraction();
RING_ERR("%s", e.what()); RING_ERR("%s", e.what());
return false; return false;
} }
succeed(); succeedExtraction();
return true; return true;
} }
......
...@@ -43,8 +43,11 @@ class HardwareAccel { ...@@ -43,8 +43,11 @@ class HardwareAccel {
void setHeight(int height) { height_ = height; } void setHeight(int height) { height_ = height; }
void setProfile(int profile) { profile_ = profile; } void setProfile(int profile) { profile_ = profile; }
void failAllocation();
void failExtraction();
void fail(bool forceFallback); 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 // wrapper to take care of boilerplate before calling the derived class's implementation
bool extractData(VideoFrame& input); bool extractData(VideoFrame& input);
...@@ -59,8 +62,9 @@ class HardwareAccel { ...@@ -59,8 +62,9 @@ class HardwareAccel {
AVCodecContext* codecCtx_ = nullptr; AVCodecContext* codecCtx_ = nullptr;
std::string name_; std::string name_;
AVPixelFormat format_; AVPixelFormat format_;
unsigned failCount_ = 0; // how many failures in a row, reset on success unsigned allocationFails_ = 0; // how many times in a row allocateBuffer has failed
bool fallback_ = false; // true when failCount_ exceeds a certain number 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 width_ = -1;
int height_ = -1; int height_ = -1;
int profile_ = -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