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