Fix processor bug

pull/431/head
Mattia Iavarone 6 years ago
parent fc4a75a24b
commit 407b2d4e64
  1. 21
      cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java
  2. 8
      cameraview/src/main/java/com/otaliastudios/cameraview/FrameManager.java
  3. 77
      demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java

@ -20,6 +20,18 @@ public class Frame {
mManager = manager; mManager = manager;
} }
boolean isAlive() {
return mData != null;
}
private void ensureAlive() {
if (!isAlive()) {
throw new RuntimeException("You should not access a released frame. " +
"If this frame was passed to a FrameProcessor, you can only use its contents synchronously," +
"for the duration of the process() method.");
}
}
void set(@NonNull byte[] data, long time, int rotation, @NonNull Size size, int format) { void set(@NonNull byte[] data, long time, int rotation, @NonNull Size size, int format) {
this.mData = data; this.mData = data;
this.mTime = time; this.mTime = time;
@ -44,6 +56,7 @@ public class Frame {
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@NonNull @NonNull
public Frame freeze() { public Frame freeze() {
ensureAlive();
byte[] data = new byte[mData.length]; byte[] data = new byte[mData.length];
System.arraycopy(mData, 0, data, 0, mData.length); System.arraycopy(mData, 0, data, 0, mData.length);
Frame other = new Frame(mManager); Frame other = new Frame(mManager);
@ -56,11 +69,12 @@ public class Frame {
* that are not useful anymore. * that are not useful anymore.
*/ */
public void release() { public void release() {
if (!isAlive()) return;
if (mManager != null) { if (mManager != null) {
// If needed, the manager will call releaseManager on us. // If needed, the manager will call releaseManager on us.
mManager.onFrameReleased(this); mManager.onFrameReleased(this);
} }
mData = null; mData = null;
mRotation = 0; mRotation = 0;
mTime = -1; mTime = -1;
@ -79,6 +93,7 @@ public class Frame {
*/ */
@NonNull @NonNull
public byte[] getData() { public byte[] getData() {
ensureAlive();
return mData; return mData;
} }
@ -89,6 +104,7 @@ public class Frame {
* @return time data * @return time data
*/ */
public long getTime() { public long getTime() {
ensureAlive();
return mTime; return mTime;
} }
@ -100,6 +116,7 @@ public class Frame {
* @return clock-wise rotation * @return clock-wise rotation
*/ */
public int getRotation() { public int getRotation() {
ensureAlive();
return mRotation; return mRotation;
} }
@ -110,6 +127,7 @@ public class Frame {
*/ */
@NonNull @NonNull
public Size getSize() { public Size getSize() {
ensureAlive();
return mSize; return mSize;
} }
@ -122,6 +140,7 @@ public class Frame {
* @see android.graphics.ImageFormat * @see android.graphics.ImageFormat
*/ */
public int getFormat() { public int getFormat() {
ensureAlive();
return mFormat; return mFormat;
} }
} }

@ -52,15 +52,17 @@ class FrameManager {
byte[] buffer = frame.getData(); byte[] buffer = frame.getData();
boolean willRecycle = mQueue.offer(frame); boolean willRecycle = mQueue.offer(frame);
if (!willRecycle) { if (!willRecycle) {
// If frame queue is full, let's drop everything.
frame.releaseManager(); frame.releaseManager();
} } else {
if (buffer != null && mCallback != null) { // If frame will be recycled, let's recycle the buffer as well.
int currSize = buffer.length; int currSize = buffer.length;
int reqSize = mBufferSize; int reqSize = mBufferSize;
if (currSize == reqSize) { if (currSize == reqSize && mCallback != null) {
mCallback.onBufferAvailable(buffer); mCallback.onBufferAvailable(buffer);
} }
} }
} }
/** /**

@ -7,6 +7,8 @@ import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetBehavior;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
@ -17,6 +19,8 @@ import com.otaliastudios.cameraview.CameraListener;
import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.CameraOptions; import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.CameraView; import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.Frame;
import com.otaliastudios.cameraview.FrameProcessor;
import com.otaliastudios.cameraview.PictureResult; import com.otaliastudios.cameraview.PictureResult;
import com.otaliastudios.cameraview.Mode; import com.otaliastudios.cameraview.Mode;
import com.otaliastudios.cameraview.VideoResult; import com.otaliastudios.cameraview.VideoResult;
@ -40,14 +44,7 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis
camera = findViewById(R.id.camera); camera = findViewById(R.id.camera);
camera.setLifecycleOwner(this); camera.setLifecycleOwner(this);
camera.addCameraListener(new CameraListener() { camera.addCameraListener(new Listener());
public void onCameraOpened(@NonNull CameraOptions options) { onOpened(options); }
public void onPictureTaken(@NonNull PictureResult result) { onPicture(result); }
public void onVideoTaken(@NonNull VideoResult result) { onVideo(result); }
public void onCameraError(@NonNull CameraException exception) {
onError(exception);
}
});
findViewById(R.id.edit).setOnClickListener(this); findViewById(R.id.edit).setOnClickListener(this);
findViewById(R.id.capturePicture).setOnClickListener(this); findViewById(R.id.capturePicture).setOnClickListener(this);
@ -80,38 +77,48 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis
Toast.makeText(this, content, length).show(); Toast.makeText(this, content, length).show();
} }
private void onOpened(CameraOptions options) { private class Listener extends CameraListener {
ViewGroup group = (ViewGroup) controlPanel.getChildAt(0);
for (int i = 0; i < group.getChildCount(); i++) {
ControlView view = (ControlView) group.getChildAt(i);
view.onCameraOpened(camera, options);
}
}
private void onError(@NonNull CameraException exception) { @Override
message("Got CameraException #" + exception.getReason(), true); public void onCameraOpened(@NonNull CameraOptions options) {
} ViewGroup group = (ViewGroup) controlPanel.getChildAt(0);
for (int i = 0; i < group.getChildCount(); i++) {
ControlView view = (ControlView) group.getChildAt(i);
view.onCameraOpened(camera, options);
}
}
private void onPicture(PictureResult result) { @Override
if (camera.isTakingVideo()) { public void onCameraError(@NonNull CameraException exception) {
message("Captured while taking video. Size=" + result.getSize(), false); super.onCameraError(exception);
return; message("Got CameraException #" + exception.getReason(), true);
} }
// This can happen if picture was taken with a gesture. @Override
long callbackTime = System.currentTimeMillis(); public void onPictureTaken(@NonNull PictureResult result) {
if (mCaptureTime == 0) mCaptureTime = callbackTime - 300; super.onPictureTaken(result);
PicturePreviewActivity.setPictureResult(result); if (camera.isTakingVideo()) {
Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class); message("Captured while taking video. Size=" + result.getSize(), false);
intent.putExtra("delay", callbackTime - mCaptureTime); return;
startActivity(intent); }
mCaptureTime = 0;
} // This can happen if picture was taken with a gesture.
long callbackTime = System.currentTimeMillis();
if (mCaptureTime == 0) mCaptureTime = callbackTime - 300;
PicturePreviewActivity.setPictureResult(result);
Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class);
intent.putExtra("delay", callbackTime - mCaptureTime);
startActivity(intent);
mCaptureTime = 0;
}
private void onVideo(VideoResult video) { @Override
VideoPreviewActivity.setVideoResult(video); public void onVideoTaken(@NonNull VideoResult result) {
Intent intent = new Intent(CameraActivity.this, VideoPreviewActivity.class); super.onVideoTaken(result);
startActivity(intent); VideoPreviewActivity.setVideoResult(result);
Intent intent = new Intent(CameraActivity.this, VideoPreviewActivity.class);
startActivity(intent);
}
} }
@Override @Override

Loading…
Cancel
Save