diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index 342961d83fb1ba5314813b77465921800c970dab..7cae03e239fc57e8ff71358a604db75517354d79 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -368,57 +368,62 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe, int64_t frame_number) #ifdef RING_ACCEL auto desc = av_pix_fmt_desc_get(static_cast<AVPixelFormat>(input.format())); bool isHardware = desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL); + try { #if defined(TARGET_OS_IOS) && TARGET_OS_IOS - if (accel_) { - auto pix = accel_->getSoftwareFormat(); - if (input.format() != pix) { - std::unique_ptr<VideoFrame> framePtr; - framePtr = scaler_.convertFormat(input, pix); - frame = framePtr->pointer(); + if (accel_) { + auto pix = accel_->getSoftwareFormat(); + if (input.format() != pix) { + std::unique_ptr<VideoFrame> framePtr; + framePtr = scaler_.convertFormat(input, pix); + frame = framePtr->pointer(); + } else { + frame = input.pointer(); + } } else { - frame = input.pointer(); - } - } else { #elif !defined(__APPLE__) - std::unique_ptr<VideoFrame> framePtr; - if (accel_ && accel_->isLinked() && isHardware) { - // Fully accelerated pipeline, skip main memory - // We have to check if the frame is hardware even if - // we are using linked HW encoder and decoder because after - // conference mixing the frame become software (prevent crashes) - frame = input.pointer(); - } else if (isHardware) { - // Hardware decoded frame, transfer back to main memory - // Transfer to GPU if we have a hardware encoder - // Hardware decoders decode to NV12, but Jami's supported software encoders want YUV420P - AVPixelFormat pix = (accel_ ? accel_->getSoftwareFormat() : AV_PIX_FMT_NV12); - framePtr = video::HardwareAccel::transferToMainMemory(input, pix); - if (!accel_) - framePtr = scaler_.convertFormat(*framePtr, AV_PIX_FMT_YUV420P); - else - framePtr = accel_->transfer(*framePtr); - frame = framePtr->pointer(); - } else if (accel_) { - // Software decoded frame with a hardware encoder, convert to accepted format first - auto pix = accel_->getSoftwareFormat(); - if (input.format() != pix) { - framePtr = scaler_.convertFormat(input, pix); - framePtr = accel_->transfer(*framePtr); + std::unique_ptr<VideoFrame> framePtr; + if (accel_ && accel_->isLinked() && isHardware) { + // Fully accelerated pipeline, skip main memory + // We have to check if the frame is hardware even if + // we are using linked HW encoder and decoder because after + // conference mixing the frame become software (prevent crashes) + frame = input.pointer(); + } else if (isHardware) { + // Hardware decoded frame, transfer back to main memory + // Transfer to GPU if we have a hardware encoder + // Hardware decoders decode to NV12, but Jami's supported software encoders want YUV420P + AVPixelFormat pix = (accel_ ? accel_->getSoftwareFormat() : AV_PIX_FMT_NV12); + framePtr = video::HardwareAccel::transferToMainMemory(input, pix); + if (!accel_) + framePtr = scaler_.convertFormat(*framePtr, AV_PIX_FMT_YUV420P); + else + framePtr = accel_->transfer(*framePtr); + frame = framePtr->pointer(); + } else if (accel_) { + // Software decoded frame with a hardware encoder, convert to accepted format first + auto pix = accel_->getSoftwareFormat(); + if (input.format() != pix) { + framePtr = scaler_.convertFormat(input, pix); + framePtr = accel_->transfer(*framePtr); + } else { + framePtr = accel_->transfer(input); + } + frame = framePtr->pointer(); } else { - framePtr = accel_->transfer(input); - } - frame = framePtr->pointer(); - } else { #else - { + { #endif // defined(TARGET_OS_IOS) && TARGET_OS_IOS #endif - libav_utils::fillWithBlack(scaledFrame_.pointer()); - scaler_.scale_with_aspect(input, scaledFrame_); - frame = scaledFrame_.pointer(); + libav_utils::fillWithBlack(scaledFrame_.pointer()); + scaler_.scale_with_aspect(input, scaledFrame_); + frame = scaledFrame_.pointer(); #ifdef RING_ACCEL - } + } #endif + } catch (const std::runtime_error& e) { + JAMI_ERR("Accel failure: %s", e.what()); + return -1; + } AVCodecContext* enc = encoders_[currentStreamIdx_]; frame->pts = frame_number; diff --git a/src/media/media_recorder.cpp b/src/media/media_recorder.cpp index a5ac873e51953f4f205b36aff658cd988d369591..77a0c020ceff5287b42c92205df18037833bad8c 100644 --- a/src/media/media_recorder.cpp +++ b/src/media/media_recorder.cpp @@ -77,9 +77,15 @@ struct MediaRecorder::StreamObserver : public Observer<std::shared_ptr<MediaFram #ifdef RING_ACCEL auto desc = av_pix_fmt_desc_get( (AVPixelFormat)(std::static_pointer_cast<VideoFrame>(m))->format()); - if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) - framePtr = jami::video::HardwareAccel::transferToMainMemory( - *std::static_pointer_cast<VideoFrame>(m), AV_PIX_FMT_NV12); + if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { + try { + framePtr = jami::video::HardwareAccel::transferToMainMemory( + *std::static_pointer_cast<VideoFrame>(m), AV_PIX_FMT_NV12); + } catch (const std::runtime_error& e) { + JAMI_ERR("Accel failure: %s", e.what()); + return; + } + } else #endif framePtr = std::static_pointer_cast<VideoFrame>(m); @@ -257,10 +263,15 @@ MediaRecorder::onFrame(const std::string& name, const std::shared_ptr<MediaFrame auto desc = av_pix_fmt_desc_get( (AVPixelFormat)(std::static_pointer_cast<VideoFrame>(frame))->format()); if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { - clone = video::HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>( - frame), - static_cast<AVPixelFormat>( - ms.format)); + try { + clone = video::HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>( + frame), + static_cast<AVPixelFormat>( + ms.format)); + } catch (const std::runtime_error& e) { + JAMI_ERR("Accel failure: %s", e.what()); + return; + } } else { clone = std::make_unique<MediaFrame>(); clone->copyFrom(*frame); diff --git a/src/media/video/accel.cpp b/src/media/video/accel.cpp index 08d0ce1b72c4666626ca634699a66c7317c5daa1..caf9ff09a1319d42217bf5022e7865292001f10a 100644 --- a/src/media/video/accel.cpp +++ b/src/media/video/accel.cpp @@ -387,8 +387,7 @@ HardwareAccel::transferToMainMemory(const VideoFrame& frame, AVPixelFormat desir int ret = av_hwframe_transfer_data(output, input, 0); if (ret < 0) { - out->copyFrom(frame); - return out; + throw std::runtime_error("Cannot transfer the frame from GPU"); } output->pts = input->pts; diff --git a/src/media/video/sinkclient.cpp b/src/media/video/sinkclient.cpp index 9d3539bba1a4438de278923fc7ff83704c3918e9..f9210e14f6a60e2f9d7dadce68561b8fce7f75e5 100644 --- a/src/media/video/sinkclient.cpp +++ b/src/media/video/sinkclient.cpp @@ -356,10 +356,16 @@ SinkClient::update(Observable<std::shared_ptr<MediaFrame>>* /*obs*/, #ifdef RING_ACCEL auto desc = av_pix_fmt_desc_get( (AVPixelFormat)(std::static_pointer_cast<VideoFrame>(frame_p))->format()); - if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) - frame = HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>( - frame_p), - AV_PIX_FMT_NV12); + if (desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { + try { + frame = HardwareAccel::transferToMainMemory(*std::static_pointer_cast<VideoFrame>( + frame_p), + AV_PIX_FMT_NV12); + } catch (const std::runtime_error& e) { + JAMI_ERR("Accel failure: %s", e.what()); + return; + } + } else #endif frame = std::static_pointer_cast<VideoFrame>(frame_p); diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp index ed1d3df9079d17fc41b05338cf3a7e9d99d5e78a..53613f29094171d08df64a232fb8af313241820c 100644 --- a/src/media/video/video_mixer.cpp +++ b/src/media/video/video_mixer.cpp @@ -337,7 +337,13 @@ VideoMixer::render_frame(VideoFrame& output, return false; #ifdef RING_ACCEL - std::shared_ptr<VideoFrame> frame {HardwareAccel::transferToMainMemory(input, AV_PIX_FMT_NV12)}; + std::shared_ptr<VideoFrame> frame; + try { + frame = HardwareAccel::transferToMainMemory(input, AV_PIX_FMT_NV12); + } catch (const std::runtime_error& e) { + JAMI_ERR("Accel failure: %s", e.what()); + return false; + } #else std::shared_ptr<VideoFrame> frame = input; #endif