fix: Fix crash when trying to console.log(frame) (#2335)
				
					
				
			* feat: Override `toJSON` to support `console.log(frame)` * Update FrameHostObject.mm * Also use on Android * Update FrameHostObject.mm
This commit is contained in:
		| @@ -31,30 +31,36 @@ FrameHostObject::~FrameHostObject() { | |||||||
|  |  | ||||||
| std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) { | std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) { | ||||||
|   std::vector<jsi::PropNameID> result; |   std::vector<jsi::PropNameID> result; | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("width"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("bytesPerRow"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("orientation"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isMirrored"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("timestamp"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("pixelFormat"))); |  | ||||||
|   // Conversion |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toArrayBuffer"))); |  | ||||||
|   // Ref Management |   // Ref Management | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); |   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("incrementRefCount"))); |   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("incrementRefCount"))); | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("decrementRefCount"))); |   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("decrementRefCount"))); | ||||||
|  |  | ||||||
|  |   if (frame != nullptr && frame->getIsValid()) { | ||||||
|  |     // Frame Properties | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("width"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("bytesPerRow"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("orientation"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isMirrored"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("timestamp"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("pixelFormat"))); | ||||||
|  |     // Conversion | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toArrayBuffer"))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #define JSI_FUNC [=](jsi::Runtime & runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value | ||||||
|  |  | ||||||
| jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) { | jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) { | ||||||
|   auto name = propName.utf8(runtime); |   auto name = propName.utf8(runtime); | ||||||
|  |  | ||||||
|   if (name == "incrementRefCount") { |   if (name == "incrementRefCount") { | ||||||
|     jsi::HostFunctionType incrementRefCount = [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, |     jsi::HostFunctionType incrementRefCount = JSI_FUNC { | ||||||
|                                                   size_t count) -> jsi::Value { |  | ||||||
|       // Increment retain count by one. |       // Increment retain count by one. | ||||||
|       this->frame->incrementRefCount(); |       this->frame->incrementRefCount(); | ||||||
|       return jsi::Value::undefined(); |       return jsi::Value::undefined(); | ||||||
| @@ -62,7 +68,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||||||
|     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), 0, incrementRefCount); |     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), 0, incrementRefCount); | ||||||
|   } |   } | ||||||
|   if (name == "decrementRefCount") { |   if (name == "decrementRefCount") { | ||||||
|     auto decrementRefCount = [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value { |     auto decrementRefCount = JSI_FUNC { | ||||||
|       // Decrement retain count by one. If the retain count is zero, the Frame gets closed. |       // Decrement retain count by one. If the retain count is zero, the Frame gets closed. | ||||||
|       this->frame->decrementRefCount(); |       this->frame->decrementRefCount(); | ||||||
|       return jsi::Value::undefined(); |       return jsi::Value::undefined(); | ||||||
| @@ -70,8 +76,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||||||
|     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), 0, decrementRefCount); |     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), 0, decrementRefCount); | ||||||
|   } |   } | ||||||
|   if (name == "toString") { |   if (name == "toString") { | ||||||
|     jsi::HostFunctionType toString = [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, |     jsi::HostFunctionType toString = JSI_FUNC { | ||||||
|                                          size_t count) -> jsi::Value { |  | ||||||
|       if (!this->frame) { |       if (!this->frame) { | ||||||
|         return jsi::String::createFromUtf8(runtime, "[closed frame]"); |         return jsi::String::createFromUtf8(runtime, "[closed frame]"); | ||||||
|       } |       } | ||||||
| @@ -85,8 +90,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||||||
|     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString); |     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString); | ||||||
|   } |   } | ||||||
|   if (name == "toArrayBuffer") { |   if (name == "toArrayBuffer") { | ||||||
|     jsi::HostFunctionType toArrayBuffer = [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, |     jsi::HostFunctionType toArrayBuffer = JSI_FUNC { | ||||||
|                                               size_t count) -> jsi::Value { |  | ||||||
| #if __ANDROID_API__ >= 26 | #if __ANDROID_API__ >= 26 | ||||||
|       AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer(); |       AHardwareBuffer* hardwareBuffer = this->frame->getHardwareBuffer(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -90,14 +90,25 @@ data class CameraConfiguration( | |||||||
|     fun difference(left: CameraConfiguration?, right: CameraConfiguration): Difference { |     fun difference(left: CameraConfiguration?, right: CameraConfiguration): Difference { | ||||||
|       val deviceChanged = left?.cameraId != right.cameraId |       val deviceChanged = left?.cameraId != right.cameraId | ||||||
|  |  | ||||||
|       val outputsChanged = deviceChanged || // input device |       val outputsChanged = deviceChanged || | ||||||
|         left?.photo != right.photo || left.video != right.video || left.codeScanner != right.codeScanner || |         // input device | ||||||
|         left.preview != right.preview || // outputs |         left?.photo != right.photo || | ||||||
|         left.videoHdr != right.videoHdr || left.photoHdr != right.photoHdr || left.format != right.format // props that affect the outputs |         left.video != right.video || | ||||||
|  |         left.codeScanner != right.codeScanner || | ||||||
|  |         left.preview != right.preview || | ||||||
|  |         // outputs | ||||||
|  |         left.videoHdr != right.videoHdr || | ||||||
|  |         left.photoHdr != right.photoHdr || | ||||||
|  |         left.format != right.format // props that affect the outputs | ||||||
|  |  | ||||||
|       val sidePropsChanged = outputsChanged || // depend on outputs |       val sidePropsChanged = outputsChanged || | ||||||
|         left?.torch != right.torch || left.enableLowLightBoost != right.enableLowLightBoost || left.fps != right.fps || |         // depend on outputs | ||||||
|         left.zoom != right.zoom || left.videoStabilizationMode != right.videoStabilizationMode || left.isActive != right.isActive || |         left?.torch != right.torch || | ||||||
|  |         left.enableLowLightBoost != right.enableLowLightBoost || | ||||||
|  |         left.fps != right.fps || | ||||||
|  |         left.zoom != right.zoom || | ||||||
|  |         left.videoStabilizationMode != right.videoStabilizationMode || | ||||||
|  |         left.isActive != right.isActive || | ||||||
|         left.exposure != right.exposure |         left.exposure != right.exposure | ||||||
|  |  | ||||||
|       val isActiveChanged = left?.isActive != right.isActive |       val isActiveChanged = left?.isActive != right.isActive | ||||||
|   | |||||||
| @@ -16,28 +16,32 @@ | |||||||
|  |  | ||||||
| std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) { | std::vector<jsi::PropNameID> FrameHostObject::getPropertyNames(jsi::Runtime& rt) { | ||||||
|   std::vector<jsi::PropNameID> result; |   std::vector<jsi::PropNameID> result; | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("width"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("bytesPerRow"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("orientation"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isMirrored"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("timestamp"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("pixelFormat"))); |  | ||||||
|   // Conversion |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); |  | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toArrayBuffer"))); |  | ||||||
|   // Ref Management |   // Ref Management | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); |   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isValid"))); | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("incrementRefCount"))); |   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("incrementRefCount"))); | ||||||
|   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("decrementRefCount"))); |   result.push_back(jsi::PropNameID::forUtf8(rt, std::string("decrementRefCount"))); | ||||||
|  |  | ||||||
|  |   if (frame != nil && frame.isValid) { | ||||||
|  |     // Frame Properties | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("width"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("height"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("bytesPerRow"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("planesCount"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("orientation"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("isMirrored"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("timestamp"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("pixelFormat"))); | ||||||
|  |     // Conversion | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toString"))); | ||||||
|  |     result.push_back(jsi::PropNameID::forUtf8(rt, std::string("toArrayBuffer"))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| Frame* FrameHostObject::getFrame() { | Frame* FrameHostObject::getFrame() { | ||||||
|   Frame* frame = this->frame; |   Frame* frame = this->frame; | ||||||
|   if (frame == nil || !CMSampleBufferIsValid(frame.buffer)) { |   if (frame == nil || !frame.isValid) { | ||||||
|     throw std::runtime_error("Frame is already closed! " |     throw std::runtime_error("Frame is already closed! " | ||||||
|                              "Are you trying to access the Image data outside of a Frame Processor's lifetime?\n" |                              "Are you trying to access the Image data outside of a Frame Processor's lifetime?\n" | ||||||
|                              "- If you want to use `console.log(frame)`, use `console.log(frame.toString())` instead.\n" |                              "- If you want to use `console.log(frame)`, use `console.log(frame.toString())` instead.\n" | ||||||
| @@ -47,11 +51,13 @@ Frame* FrameHostObject::getFrame() { | |||||||
|   return frame; |   return frame; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #define JSI_FUNC [=](jsi::Runtime & runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value | ||||||
|  |  | ||||||
| jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) { | jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) { | ||||||
|   auto name = propName.utf8(runtime); |   auto name = propName.utf8(runtime); | ||||||
|  |  | ||||||
|   if (name == "toString") { |   if (name == "toString") { | ||||||
|     auto toString = [this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { |     auto toString = JSI_FUNC { | ||||||
|       // Lock Frame so it cannot be deallocated while we access it |       // Lock Frame so it cannot be deallocated while we access it | ||||||
|       std::lock_guard lock(this->_mutex); |       std::lock_guard lock(this->_mutex); | ||||||
|  |  | ||||||
| @@ -63,8 +69,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||||||
|     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString); |     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "toString"), 0, toString); | ||||||
|   } |   } | ||||||
|   if (name == "incrementRefCount") { |   if (name == "incrementRefCount") { | ||||||
|     auto incrementRefCount = [this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, |     auto incrementRefCount = JSI_FUNC { | ||||||
|                                     size_t count) -> jsi::Value { |  | ||||||
|       // Lock Frame so it cannot be deallocated while we access it |       // Lock Frame so it cannot be deallocated while we access it | ||||||
|       std::lock_guard lock(this->_mutex); |       std::lock_guard lock(this->_mutex); | ||||||
|  |  | ||||||
| @@ -75,8 +80,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||||||
|     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), 0, incrementRefCount); |     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "incrementRefCount"), 0, incrementRefCount); | ||||||
|   } |   } | ||||||
|   if (name == "decrementRefCount") { |   if (name == "decrementRefCount") { | ||||||
|     auto decrementRefCount = [this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, |     auto decrementRefCount = JSI_FUNC { | ||||||
|                                     size_t count) -> jsi::Value { |  | ||||||
|       // Lock Frame so it cannot be deallocated while we access it |       // Lock Frame so it cannot be deallocated while we access it | ||||||
|       std::lock_guard lock(this->_mutex); |       std::lock_guard lock(this->_mutex); | ||||||
|  |  | ||||||
| @@ -92,8 +96,7 @@ jsi::Value FrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pr | |||||||
|     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), 0, decrementRefCount); |     return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "decrementRefCount"), 0, decrementRefCount); | ||||||
|   } |   } | ||||||
|   if (name == "toArrayBuffer") { |   if (name == "toArrayBuffer") { | ||||||
|     auto toArrayBuffer = [this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, |     auto toArrayBuffer = JSI_FUNC { | ||||||
|                                 size_t count) -> jsi::Value { |  | ||||||
|       // Lock Frame so it cannot be deallocated while we access it |       // Lock Frame so it cannot be deallocated while we access it | ||||||
|       std::lock_guard lock(this->_mutex); |       std::lock_guard lock(this->_mutex); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user