From ae75e22fc08148abceed674671eb8dff6828834e Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Wed, 31 Jan 2024 20:32:02 +0100 Subject: [PATCH] fix: Fix crash in `toArrayBuffer()` by properly acquiring a reference on `AHardwareBuffer*` (#2490) * fix: Fix crash in `toArrayBuffer()` by properly acquiring a reference on `AHardwareBuffer*` * Format * Update Podfile.lock --- .../cpp/frameprocessor/FrameHostObject.cpp | 23 +++++++++---- package/cpp/FinalAction.h | 34 +++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 package/cpp/FinalAction.h diff --git a/package/android/src/main/cpp/frameprocessor/FrameHostObject.cpp b/package/android/src/main/cpp/frameprocessor/FrameHostObject.cpp index 773cde6..9ce99f9 100644 --- a/package/android/src/main/cpp/frameprocessor/FrameHostObject.cpp +++ b/package/android/src/main/cpp/frameprocessor/FrameHostObject.cpp @@ -15,6 +15,8 @@ #include #include +#include "FinalAction.h" + namespace vision { using namespace facebook; @@ -92,11 +94,13 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr jsi::HostFunctionType toArrayBuffer = JSI_FUNC { #if __ANDROID_API__ >= 26 AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer(); + AHardwareBuffer_acquire(hardwareBuffer); + finally([&]() { AHardwareBuffer_release(hardwareBuffer); }); AHardwareBuffer_Desc bufferDescription; AHardwareBuffer_describe(hardwareBuffer, &bufferDescription); - __android_log_print(ANDROID_LOG_INFO, "Frame", "Buffer %i x %i @ %i", bufferDescription.width, bufferDescription.height, - bufferDescription.stride); + __android_log_print(ANDROID_LOG_INFO, "Frame", "Converting %i x %i @ %i HardwareBuffer...", bufferDescription.width, + bufferDescription.height, bufferDescription.stride); size_t size = bufferDescription.height * bufferDescription.stride; static constexpr auto ARRAYBUFFER_CACHE_PROP_NAME = "__frameArrayBufferCache"; @@ -118,16 +122,21 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr // Get CPU access to the HardwareBuffer (&buffer is a virtual temporary address) void* buffer; - AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_MASK, -1, nullptr, &buffer); + int result = AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_MASK, -1, nullptr, &buffer); + if (result != 0) { + throw jsi::JSError(runtime, "Failed to lock HardwareBuffer for reading!"); + } + finally([&]() { + int result = AHardwareBuffer_unlock(hardwareBuffer, nullptr); + if (result != 0) { + throw jsi::JSError(runtime, "Failed to lock HardwareBuffer for reading!"); + } + }); // directly write to C++ JSI ArrayBuffer auto destinationBuffer = arrayBuffer.data(runtime); memcpy(destinationBuffer, buffer, sizeof(uint8_t) * size); - // Release HardwareBuffer again - AHardwareBuffer_unlock(hardwareBuffer, nullptr); - AHardwareBuffer_release(hardwareBuffer); - return arrayBuffer; #else throw jsi::JSError(runtime, "Frame.toArrayBuffer() is only available if minSdkVersion is set to 26 or higher!"); diff --git a/package/cpp/FinalAction.h b/package/cpp/FinalAction.h new file mode 100644 index 0000000..083e671 --- /dev/null +++ b/package/cpp/FinalAction.h @@ -0,0 +1,34 @@ +// +// MutableRawBuffer.h +// VisionCamera +// +// Created by Marc Rousavy on 17.01.24. +// Copyright © 2024 mrousavy. All rights reserved. +// + +#pragma once + +namespace vision { + +template struct FinalAction { + +public: + FinalAction(F f) : clean_{f} {} + ~FinalAction() { + if (enabled_) + clean_(); + } + void disable() { + enabled_ = false; + }; + +private: + F clean_; + bool enabled_ = true; +}; + +} // namespace vision + +template vision::FinalAction finally(F f) { + return vision::FinalAction(std::move(f)); +} \ No newline at end of file