feat: Use ByteBuffer
for much faster toArrayBuffer()
⚡
This commit is contained in:
parent
862e05b64f
commit
521d7c8ccf
@ -98,28 +98,29 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
||||
const jsi::Value& thisArg,
|
||||
const jsi::Value* args,
|
||||
size_t count) -> jsi::Value {
|
||||
auto buffer = this->frame->toByteArray();
|
||||
auto arraySize = buffer->size();
|
||||
auto buffer = this->frame->toByteBuffer();
|
||||
if (!buffer->isDirect()) {
|
||||
throw std::runtime_error("Failed to get byte content of Frame - array is not direct ByteBuffer!");
|
||||
}
|
||||
auto size = buffer->getDirectSize();
|
||||
|
||||
static constexpr auto ARRAYBUFFER_CACHE_PROP_NAME = "__frameArrayBufferCache";
|
||||
if (!runtime.global().hasProperty(runtime, ARRAYBUFFER_CACHE_PROP_NAME)) {
|
||||
vision::TypedArray<vision::TypedArrayKind::Uint8ClampedArray> arrayBuffer(runtime, arraySize);
|
||||
vision::TypedArray<vision::TypedArrayKind::Uint8ClampedArray> arrayBuffer(runtime, size);
|
||||
runtime.global().setProperty(runtime, ARRAYBUFFER_CACHE_PROP_NAME, arrayBuffer);
|
||||
}
|
||||
|
||||
// Get from global JS cache
|
||||
auto arrayBufferCache = runtime.global().getPropertyAsObject(runtime, ARRAYBUFFER_CACHE_PROP_NAME);
|
||||
auto arrayBuffer = vision::getTypedArray(runtime, arrayBufferCache).get<vision::TypedArrayKind::Uint8ClampedArray>(runtime);
|
||||
if (arrayBuffer.size(runtime) != arraySize) {
|
||||
arrayBuffer = vision::TypedArray<vision::TypedArrayKind::Uint8ClampedArray>(runtime, arraySize);
|
||||
if (arrayBuffer.size(runtime) != size) {
|
||||
arrayBuffer = vision::TypedArray<vision::TypedArrayKind::Uint8ClampedArray>(runtime, size);
|
||||
runtime.global().setProperty(runtime, ARRAYBUFFER_CACHE_PROP_NAME, arrayBuffer);
|
||||
}
|
||||
|
||||
// directly write to C++ JSI ArrayBuffer
|
||||
auto destinationBuffer = arrayBuffer.data(runtime);
|
||||
buffer->getRegion(0,
|
||||
static_cast<jint>(arraySize),
|
||||
reinterpret_cast<jbyte*>(destinationBuffer));
|
||||
memcpy(destinationBuffer, buffer->getDirectAddress(), sizeof(uint8_t) * size);
|
||||
|
||||
return arrayBuffer;
|
||||
};
|
||||
|
@ -57,9 +57,10 @@ int JFrame::getBytesPerRow() const {
|
||||
return getBytesPerRowMethod(self());
|
||||
}
|
||||
|
||||
local_ref<JArrayByte> JFrame::toByteArray() const {
|
||||
static const auto toByteArrayMethod = getClass()->getMethod<JArrayByte()>("toByteArray");
|
||||
return toByteArrayMethod(self());
|
||||
local_ref<JByteBuffer> JFrame::toByteBuffer() const {
|
||||
static const auto toByteBufferMethod = getClass()->getMethod<JByteBuffer()>("toByteBuffer");
|
||||
return toByteBufferMethod(self());
|
||||
}
|
||||
}
|
||||
|
||||
void JFrame::incrementRefCount() {
|
||||
|
@ -25,7 +25,7 @@ struct JFrame : public JavaClass<JFrame> {
|
||||
jlong getTimestamp() const;
|
||||
local_ref<JString> getOrientation() const;
|
||||
local_ref<JString> getPixelFormat() const;
|
||||
local_ref<JArrayByte> toByteArray() const;
|
||||
local_ref<JByteBuffer> toByteBuffer() const;
|
||||
void incrementRefCount();
|
||||
void decrementRefCount();
|
||||
void close();
|
||||
|
@ -89,36 +89,31 @@ public class Frame {
|
||||
return image.getPlanes()[0].getRowStride();
|
||||
}
|
||||
|
||||
private static byte[] byteArrayCache;
|
||||
private static ByteBuffer byteArrayCache;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@DoNotStrip
|
||||
public byte[] toByteArray() {
|
||||
public ByteBuffer toByteBuffer() {
|
||||
switch (image.getFormat()) {
|
||||
case ImageFormat.YUV_420_888:
|
||||
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
|
||||
ByteBuffer vuBuffer = image.getPlanes()[2].getBuffer();
|
||||
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
|
||||
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
|
||||
int ySize = yBuffer.remaining();
|
||||
int vuSize = vuBuffer.remaining();
|
||||
int uSize = uBuffer.remaining();
|
||||
int vSize = vBuffer.remaining();
|
||||
int totalSize = ySize + uSize + vSize;
|
||||
|
||||
if (byteArrayCache == null || byteArrayCache.length != ySize + vuSize) {
|
||||
byteArrayCache = new byte[ySize + vuSize];
|
||||
if (byteArrayCache == null) {
|
||||
byteArrayCache = ByteBuffer.allocate(totalSize);
|
||||
}
|
||||
|
||||
yBuffer.get(byteArrayCache, 0, ySize);
|
||||
vuBuffer.get(byteArrayCache, ySize, vuSize);
|
||||
byteArrayCache.rewind();
|
||||
byteArrayCache.put(yBuffer).put(uBuffer).put(vBuffer);
|
||||
|
||||
return byteArrayCache;
|
||||
case ImageFormat.JPEG:
|
||||
ByteBuffer rgbBuffer = image.getPlanes()[0].getBuffer();
|
||||
int size = rgbBuffer.remaining();
|
||||
|
||||
if (byteArrayCache == null || byteArrayCache.length != size) {
|
||||
byteArrayCache = new byte[size];
|
||||
}
|
||||
rgbBuffer.get(byteArrayCache);
|
||||
|
||||
return byteArrayCache;
|
||||
return image.getPlanes()[0].getBuffer();
|
||||
default:
|
||||
throw new RuntimeException("Cannot convert Frame with Format " + image.getFormat() + " to byte array!");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user