Skip to content
Snippets Groups Projects
Commit 274049bc authored by Philippe Gorley's avatar Philippe Gorley Committed by gerrit2
Browse files

video: fix hardware acceleration bugs

Now correctly takes into account user setting. Will no longer try
to retrieve data from the GPU buffer if acceleration has failed.
Uses hardware acceleration when flushing the video stream.

Change-Id: Id7787a181b3822e8c7da0e8c2ce2cdfa302a3ddd
(cherry picked from commit c49f1368)
parent bad31c23
Branches
No related tags found
No related merge requests found
......@@ -96,7 +96,7 @@ int MediaDecoder::openInput(const DeviceParams& params)
RING_DBG("Trying to open device %s with format %s, pixel format %s, size %dx%d, rate %lf", params.input.c_str(),
params.format.c_str(), params.pixel_format.c_str(), params.width, params.height, params.framerate.real());
enableAccel_ = (params.enableAccel == "1");
enableAccel_ = (params.enableAccel != "0");
int ret = avformat_open_input(
&inputCtx_,
......@@ -267,8 +267,10 @@ int MediaDecoder::setupFromVideoData()
decoderCtx_->thread_count = std::thread::hardware_concurrency();
#ifdef RING_ACCEL
accel_ = video::makeHardwareAccel(decoderCtx_);
decoderCtx_->opaque = accel_.get();
if (enableAccel_) {
accel_ = video::makeHardwareAccel(decoderCtx_);
decoderCtx_->opaque = accel_.get();
}
#endif // RING_ACCEL
// find the decoder for the video stream
......@@ -334,8 +336,12 @@ MediaDecoder::decode(VideoFrame& result)
if (frameFinished) {
frame->format = (AVPixelFormat) correctPixFmt(frame->format);
#if defined(RING_VIDEO) && defined(RING_ACCEL)
if (accel_ && !accel_->extractData(decoderCtx_, result))
return Status::DecodeError;
if (accel_) {
if (!accel_->hasFailed())
accel_->extractData(decoderCtx_, result);
else
return Status::DecodeError;
}
#endif // RING_ACCEL
if (emulateRate_ and frame->pkt_pts != AV_NOPTS_VALUE) {
auto frame_time = getTimeBase()*(frame->pkt_pts - avStream_->start_time);
......@@ -418,8 +424,15 @@ MediaDecoder::flush(VideoFrame& result)
if (len <= 0)
return Status::DecodeError;
if (frameFinished)
if (frameFinished) {
#ifdef RING_ACCEL
// flush is called when closing the stream
// so don't restart the media decoder
if (accel_ && !accel_->hasFailed())
accel_->extractData(decoderCtx_, result);
#endif // RING_ACCEL
return Status::FrameFinished;
}
return Status::Success;
}
......
......@@ -57,7 +57,7 @@ getFormatCb(AVCodecContext* codecCtx, const AVPixelFormat* formats)
}
}
accel->fail(true);
accel->fail(codecCtx, true);
RING_WARN("Falling back to software decoding");
codecCtx->get_format = avcodec_default_get_format;
codecCtx->get_buffer2 = avcodec_default_get_buffer2;
......@@ -80,7 +80,7 @@ allocateBufferCb(AVCodecContext* codecCtx, AVFrame* frame, int flags)
return 0;
}
accel->fail();
accel->fail(codecCtx, false);
}
return avcodec_default_get_buffer2(codecCtx, frame, flags);
......@@ -140,13 +140,15 @@ HardwareAccel::HardwareAccel(const AccelInfo& info)
}
void
HardwareAccel::fail(bool forceFallback)
HardwareAccel::fail(AVCodecContext* codecCtx, bool forceFallback)
{
++failCount_;
if (failCount_ >= MAX_ACCEL_FAILURES || forceFallback) {
RING_ERR("Hardware acceleration failure");
fallback_ = true;
failCount_ = 0;
// force reinit of media decoder to correctly set thread count
codecCtx->get_format = avcodec_default_get_format;
codecCtx->get_buffer2 = avcodec_default_get_buffer2;
}
}
......
......@@ -60,7 +60,7 @@ class HardwareAccel {
void setHeight(int height) { height_ = height; }
void setProfile(int profile) { profile_ = profile; }
void fail(bool forceFallback = false);
void fail(AVCodecContext* codecCtx, bool forceFallback);
void succeed() { failCount_ = 0; } // call on success of allocateBuffer or extractData
public: // must be implemented by derived classes
......
......@@ -83,7 +83,7 @@ VaapiAccel::extractData(AVCodecContext* codecCtx, VideoFrame& container)
av_frame_unref(input);
av_frame_move_ref(input, output);
} catch (const std::runtime_error& e) {
fail();
fail(codecCtx, false);
RING_ERR("%s", e.what());
return false;
}
......@@ -117,7 +117,7 @@ VaapiAccel::init(AVCodecContext* codecCtx)
{ AV_CODEC_ID_H264, h264 },
{ AV_CODEC_ID_MPEG4, mpeg4 },
{ AV_CODEC_ID_H263, h263 },
{ AV_CODEC_ID_H263P, h263 } // no clue if this'll work, #ffmpeg isn't answering me
{ AV_CODEC_ID_H263P, h263 }
};
VAStatus status;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment