diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index fdc54f795d233fa6e0a3fcfb03fc4236e88efd4c..d939b99a49e961e5f32127a4cd8c820be2924de3 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -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; } diff --git a/src/media/video/accel.cpp b/src/media/video/accel.cpp index 118a28e077586983c07fdefc1f0d73e6444cfd1e..636c5bac20ad1c826c4bf0e8d9c815cdb039ae4d 100644 --- a/src/media/video/accel.cpp +++ b/src/media/video/accel.cpp @@ -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; } } diff --git a/src/media/video/accel.h b/src/media/video/accel.h index f0507b6d22da517e69cd44bd199ef76ee26a9fe5..fd6f9083a2670edc25da2454f97feee7e1116223 100644 --- a/src/media/video/accel.h +++ b/src/media/video/accel.h @@ -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 diff --git a/src/media/video/v4l2/vaapi.cpp b/src/media/video/v4l2/vaapi.cpp index 6139e5abaabfe563341749d2c6806340f04527c9..3d3cec3b8d63584c0f5948031707ac8f66fa93c8 100644 --- a/src/media/video/v4l2/vaapi.cpp +++ b/src/media/video/v4l2/vaapi.cpp @@ -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;