feat: Make Frame thread-safe and improve error messages (#2327)

* fix: Fix multi-Thread access on Java

* fix: Thread-lock access on iOS as well

* whoops add missing header impl

* Update Podfile.lock

* fix: Don't use `CFGetRetainCount`

* fix: Lock access on iOS as well

* C++ format

* More detailed error

* chore: Move getters into `Frame`

* Format c++

* Use enum `orientation` again

* format

* fix: Synchronize `isValid` on Java

* Also log pixelformat

* feat: Use Java enums in C++

* Format C++
This commit is contained in:
Marc Rousavy
2023-12-29 14:09:56 +01:00
committed by GitHub
parent e4393cd83a
commit 895f3ec889
14 changed files with 338 additions and 114 deletions

View File

@@ -7,6 +7,7 @@ import com.facebook.proguard.annotations.DoNotStrip;
import com.mrousavy.camera.core.HardwareBuffersNotAvailableError;
import com.mrousavy.camera.types.PixelFormat;
import com.mrousavy.camera.types.Orientation;
import java.lang.IllegalStateException;
public class Frame {
private final Image image;
@@ -24,30 +25,44 @@ public class Frame {
}
public Image getImage() {
return image;
synchronized (this) {
Image img = image;
if (!getIsImageValid(img)) {
throw new RuntimeException("Frame is already closed! " +
"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 do async processing, use `runAsync(...)` instead.\n" +
"- If you want to use runOnJS, increment it's ref-count: `frame.incrementRefCount()`");
}
return img;
}
}
@SuppressWarnings("unused")
@DoNotStrip
public int getWidth() {
return image.getWidth();
return getImage().getWidth();
}
@SuppressWarnings("unused")
@DoNotStrip
public int getHeight() {
return image.getHeight();
return getImage().getHeight();
}
@SuppressWarnings("unused")
@DoNotStrip
public boolean getIsValid() {
return getIsImageValid(getImage());
}
private boolean getIsImageValid(Image image) {
try {
// will throw an exception if the image is already closed
image.getCropRect();
synchronized (this) { image.getFormat(); }
// no exception thrown, image must still be valid.
return true;
} catch (Exception e) {
} catch (IllegalStateException e) {
// exception thrown, image has already been closed.
return false;
}
@@ -67,27 +82,26 @@ public class Frame {
@SuppressWarnings("unused")
@DoNotStrip
public String getOrientation() {
return orientation.getUnionValue();
public Orientation getOrientation() {
return orientation;
}
@SuppressWarnings("unused")
@DoNotStrip
public String getPixelFormat() {
PixelFormat format = PixelFormat.Companion.fromImageFormat(image.getFormat());
return format.getUnionValue();
public PixelFormat getPixelFormat() {
return PixelFormat.Companion.fromImageFormat(getImage().getFormat());
}
@SuppressWarnings("unused")
@DoNotStrip
public int getPlanesCount() {
return image.getPlanes().length;
return getImage().getPlanes().length;
}
@SuppressWarnings("unused")
@DoNotStrip
public int getBytesPerRow() {
return image.getPlanes()[0].getRowStride();
return getImage().getPlanes()[0].getRowStride();
}
@SuppressWarnings("unused")
@@ -101,7 +115,7 @@ public class Frame {
throw new HardwareBuffersNotAvailableError();
}
if (hardwareBuffer == null) {
hardwareBuffer = image.getHardwareBuffer();
hardwareBuffer = getImage().getHardwareBuffer();
}
return hardwareBuffer;
}
@@ -121,17 +135,17 @@ public class Frame {
refCount--;
if (refCount <= 0) {
// If no reference is held on this Image, close it.
image.close();
close();
}
}
}
@SuppressWarnings("unused")
@DoNotStrip
private void close() {
if (hardwareBuffer != null) {
hardwareBuffer.close();
private synchronized void close() {
synchronized (this) {
if (hardwareBuffer != null) {
hardwareBuffer.close();
}
image.close();
}
image.close();
}
}