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
This commit is contained in:
parent
f896831d4a
commit
ae75e22fc0
@ -15,6 +15,8 @@
|
|||||||
#include <android/hardware_buffer.h>
|
#include <android/hardware_buffer.h>
|
||||||
#include <android/hardware_buffer_jni.h>
|
#include <android/hardware_buffer_jni.h>
|
||||||
|
|
||||||
|
#include "FinalAction.h"
|
||||||
|
|
||||||
namespace vision {
|
namespace vision {
|
||||||
|
|
||||||
using namespace facebook;
|
using namespace facebook;
|
||||||
@ -92,11 +94,13 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
|||||||
jsi::HostFunctionType toArrayBuffer = JSI_FUNC {
|
jsi::HostFunctionType toArrayBuffer = JSI_FUNC {
|
||||||
#if __ANDROID_API__ >= 26
|
#if __ANDROID_API__ >= 26
|
||||||
AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer();
|
AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer();
|
||||||
|
AHardwareBuffer_acquire(hardwareBuffer);
|
||||||
|
finally([&]() { AHardwareBuffer_release(hardwareBuffer); });
|
||||||
|
|
||||||
AHardwareBuffer_Desc bufferDescription;
|
AHardwareBuffer_Desc bufferDescription;
|
||||||
AHardwareBuffer_describe(hardwareBuffer, &bufferDescription);
|
AHardwareBuffer_describe(hardwareBuffer, &bufferDescription);
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Frame", "Buffer %i x %i @ %i", bufferDescription.width, bufferDescription.height,
|
__android_log_print(ANDROID_LOG_INFO, "Frame", "Converting %i x %i @ %i HardwareBuffer...", bufferDescription.width,
|
||||||
bufferDescription.stride);
|
bufferDescription.height, bufferDescription.stride);
|
||||||
size_t size = bufferDescription.height * bufferDescription.stride;
|
size_t size = bufferDescription.height * bufferDescription.stride;
|
||||||
|
|
||||||
static constexpr auto ARRAYBUFFER_CACHE_PROP_NAME = "__frameArrayBufferCache";
|
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)
|
// Get CPU access to the HardwareBuffer (&buffer is a virtual temporary address)
|
||||||
void* buffer;
|
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
|
// directly write to C++ JSI ArrayBuffer
|
||||||
auto destinationBuffer = arrayBuffer.data(runtime);
|
auto destinationBuffer = arrayBuffer.data(runtime);
|
||||||
memcpy(destinationBuffer, buffer, sizeof(uint8_t) * size);
|
memcpy(destinationBuffer, buffer, sizeof(uint8_t) * size);
|
||||||
|
|
||||||
// Release HardwareBuffer again
|
|
||||||
AHardwareBuffer_unlock(hardwareBuffer, nullptr);
|
|
||||||
AHardwareBuffer_release(hardwareBuffer);
|
|
||||||
|
|
||||||
return arrayBuffer;
|
return arrayBuffer;
|
||||||
#else
|
#else
|
||||||
throw jsi::JSError(runtime, "Frame.toArrayBuffer() is only available if minSdkVersion is set to 26 or higher!");
|
throw jsi::JSError(runtime, "Frame.toArrayBuffer() is only available if minSdkVersion is set to 26 or higher!");
|
||||||
|
34
package/cpp/FinalAction.h
Normal file
34
package/cpp/FinalAction.h
Normal file
@ -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 <typename F> 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 <typename F> vision::FinalAction<F> finally(F f) {
|
||||||
|
return vision::FinalAction<F>(std::move(f));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user