|
|
@ -66,7 +66,6 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { |
|
|
|
private boolean mHasOverlay; |
|
|
|
private boolean mHasOverlay; |
|
|
|
|
|
|
|
|
|
|
|
private int mTextureId; |
|
|
|
private int mTextureId; |
|
|
|
private SurfaceTexture mSurfaceTexture; |
|
|
|
|
|
|
|
private float[] mTransform; |
|
|
|
private float[] mTransform; |
|
|
|
|
|
|
|
|
|
|
|
private int mOverlayTextureId = 0; |
|
|
|
private int mOverlayTextureId = 0; |
|
|
@ -104,7 +103,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onRendererFrame(@NonNull SurfaceTexture surfaceTexture, final float scaleX, final float scaleY) { |
|
|
|
public void onRendererFrame(@NonNull SurfaceTexture surfaceTexture, final float scaleX, final float scaleY) { |
|
|
|
mPreview.removeRendererFrameCallback(this); |
|
|
|
mPreview.removeRendererFrameCallback(this); |
|
|
|
SnapshotGlPictureRecorder.this.onRendererFrame(scaleX, scaleY); |
|
|
|
SnapshotGlPictureRecorder.this.onRendererFrame(surfaceTexture, scaleX, scaleY); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -114,12 +113,11 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { |
|
|
|
private void onRendererTextureCreated(int textureId) { |
|
|
|
private void onRendererTextureCreated(int textureId) { |
|
|
|
mTextureId = textureId; |
|
|
|
mTextureId = textureId; |
|
|
|
mViewport = new EglViewport(); |
|
|
|
mViewport = new EglViewport(); |
|
|
|
mSurfaceTexture = new SurfaceTexture(mTextureId, true); |
|
|
|
|
|
|
|
// Need to crop the size.
|
|
|
|
// Need to crop the size.
|
|
|
|
Rect crop = CropHelper.computeCrop(mResult.size, mOutputRatio); |
|
|
|
Rect crop = CropHelper.computeCrop(mResult.size, mOutputRatio); |
|
|
|
mResult.size = new Size(crop.width(), crop.height()); |
|
|
|
mResult.size = new Size(crop.width(), crop.height()); |
|
|
|
mSurfaceTexture.setDefaultBufferSize(mResult.size.getWidth(), mResult.size.getHeight()); |
|
|
|
|
|
|
|
mTransform = new float[16]; |
|
|
|
mTransform = new float[16]; |
|
|
|
|
|
|
|
Matrix.setIdentityM(mTransform, 0); |
|
|
|
|
|
|
|
|
|
|
|
if (mHasOverlay) { |
|
|
|
if (mHasOverlay) { |
|
|
|
mOverlayTextureId = mViewport.createTexture(); |
|
|
|
mOverlayTextureId = mViewport.createTexture(); |
|
|
@ -155,23 +153,27 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@RendererThread |
|
|
|
@RendererThread |
|
|
|
@TargetApi(Build.VERSION_CODES.KITKAT) |
|
|
|
@TargetApi(Build.VERSION_CODES.KITKAT) |
|
|
|
private void onRendererFrame(final float scaleX, final float scaleY) { |
|
|
|
private void onRendererFrame(final @NonNull SurfaceTexture surfaceTexture, final float scaleX, final float scaleY) { |
|
|
|
// Get egl context from the RendererThread, which is the one in which we have created
|
|
|
|
// Get egl context from the RendererThread, which is the one in which we have created
|
|
|
|
// the textureId and the overlayTextureId, managed by the GlSurfaceView.
|
|
|
|
// the textureId and the overlayTextureId, managed by the GlSurfaceView.
|
|
|
|
// Next operations can then be performed on different threads using this handle.
|
|
|
|
// Next operations can then be performed on different threads using this handle.
|
|
|
|
final EGLContext eglContext = EGL14.eglGetCurrentContext(); |
|
|
|
final EGLContext eglContext = EGL14.eglGetCurrentContext(); |
|
|
|
final EglCore core = new EglCore(eglContext, EglCore.FLAG_RECORDABLE); |
|
|
|
// Calling this invalidates the rotation/scale logic below:
|
|
|
|
|
|
|
|
// surfaceTexture.getTransformMatrix(mTransform); // TODO activate and fix the logic.
|
|
|
|
WorkerHandler.execute(new Runnable() { |
|
|
|
WorkerHandler.execute(new Runnable() { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void run() { |
|
|
|
public void run() { |
|
|
|
// 0. Create an EGL surface
|
|
|
|
// 0. EGL window will need an output.
|
|
|
|
EglBaseSurface eglSurface = new EglWindowSurface(core, mSurfaceTexture); |
|
|
|
// We create a fake one as explained in javadocs.
|
|
|
|
|
|
|
|
final int fakeOutputTextureId = 9999; |
|
|
|
|
|
|
|
SurfaceTexture fakeOutputSurface = new SurfaceTexture(fakeOutputTextureId); |
|
|
|
|
|
|
|
fakeOutputSurface.setDefaultBufferSize(mResult.size.getWidth(), mResult.size.getHeight()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1. Create an EGL surface
|
|
|
|
|
|
|
|
final EglCore core = new EglCore(eglContext, EglCore.FLAG_RECORDABLE); |
|
|
|
|
|
|
|
final EglBaseSurface eglSurface = new EglWindowSurface(core, fakeOutputSurface); |
|
|
|
eglSurface.makeCurrent(); |
|
|
|
eglSurface.makeCurrent(); |
|
|
|
|
|
|
|
|
|
|
|
// 1. Get latest texture
|
|
|
|
|
|
|
|
mSurfaceTexture.updateTexImage(); |
|
|
|
|
|
|
|
mSurfaceTexture.getTransformMatrix(mTransform); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Apply scale and crop
|
|
|
|
// 2. Apply scale and crop
|
|
|
|
boolean flip = mEngine.getAngles().flip(Reference.VIEW, Reference.SENSOR); |
|
|
|
boolean flip = mEngine.getAngles().flip(Reference.VIEW, Reference.SENSOR); |
|
|
|
float realScaleX = flip ? scaleY : scaleX; |
|
|
|
float realScaleX = flip ? scaleY : scaleX; |
|
|
@ -181,22 +183,16 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { |
|
|
|
Matrix.translateM(mTransform, 0, scaleTranslX, scaleTranslY, 0); |
|
|
|
Matrix.translateM(mTransform, 0, scaleTranslX, scaleTranslY, 0); |
|
|
|
Matrix.scaleM(mTransform, 0, realScaleX, realScaleY, 1); |
|
|
|
Matrix.scaleM(mTransform, 0, realScaleX, realScaleY, 1); |
|
|
|
|
|
|
|
|
|
|
|
// 3. Go back to 0,0 so that rotate and flip work well
|
|
|
|
// 3. Apply rotation and flip
|
|
|
|
Matrix.translateM(mTransform, 0, 0.5F, 0.5F, 0); |
|
|
|
Matrix.translateM(mTransform, 0, 0.5F, 0.5F, 0); // Go back to 0,0
|
|
|
|
|
|
|
|
Matrix.rotateM(mTransform, 0, -mResult.rotation, 0, 0, 1); // Rotate (not sure why we need the minus)
|
|
|
|
// 4. Apply rotation (not sure why we need the minus here)
|
|
|
|
|
|
|
|
Matrix.rotateM(mTransform, 0, -mResult.rotation, 0, 0, 1); |
|
|
|
|
|
|
|
mResult.rotation = 0; |
|
|
|
mResult.rotation = 0; |
|
|
|
|
|
|
|
if (mResult.facing == Facing.FRONT) { // 5. Flip horizontally for front camera
|
|
|
|
// 5. Flip horizontally for front camera
|
|
|
|
|
|
|
|
if (mResult.facing == Facing.FRONT) { |
|
|
|
|
|
|
|
Matrix.scaleM(mTransform, 0, -1, 1, 1); |
|
|
|
Matrix.scaleM(mTransform, 0, -1, 1, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Matrix.translateM(mTransform, 0, -0.5F, -0.5F, 0); // Go back to old position
|
|
|
|
|
|
|
|
|
|
|
|
// 6. Go back to old position
|
|
|
|
// 4. Do pretty much the same for overlays
|
|
|
|
Matrix.translateM(mTransform, 0, -0.5F, -0.5F, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 7. Do pretty much the same for overlays
|
|
|
|
|
|
|
|
if (mHasOverlay) { |
|
|
|
if (mHasOverlay) { |
|
|
|
// 1. First we must draw on the texture and get latest image
|
|
|
|
// 1. First we must draw on the texture and get latest image
|
|
|
|
try { |
|
|
|
try { |
|
|
@ -219,17 +215,16 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { |
|
|
|
Matrix.translateM(mOverlayTransform, 0, -0.5F, -0.5F, 0); |
|
|
|
Matrix.translateM(mOverlayTransform, 0, -0.5F, -0.5F, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 8. Draw and save
|
|
|
|
// 5. Draw and save
|
|
|
|
mViewport.drawFrame(mTextureId, mTransform); |
|
|
|
mViewport.drawFrame(mTextureId, mTransform); |
|
|
|
if (mHasOverlay) mViewport.drawFrame(mOverlayTextureId, mOverlayTransform); |
|
|
|
if (mHasOverlay) mViewport.drawFrame(mOverlayTextureId, mOverlayTransform); |
|
|
|
mResult.format = PictureResult.FORMAT_JPEG; |
|
|
|
mResult.format = PictureResult.FORMAT_JPEG; |
|
|
|
mResult.data = eglSurface.saveFrameTo(Bitmap.CompressFormat.JPEG); |
|
|
|
mResult.data = eglSurface.saveFrameTo(Bitmap.CompressFormat.JPEG); |
|
|
|
|
|
|
|
|
|
|
|
// 9. Cleanup
|
|
|
|
// 6. Cleanup
|
|
|
|
mSurfaceTexture.releaseTexImage(); |
|
|
|
|
|
|
|
eglSurface.releaseEglSurface(); |
|
|
|
eglSurface.releaseEglSurface(); |
|
|
|
mViewport.release(); |
|
|
|
mViewport.release(); |
|
|
|
mSurfaceTexture.release(); |
|
|
|
fakeOutputSurface.release(); |
|
|
|
if (mHasOverlay) { |
|
|
|
if (mHasOverlay) { |
|
|
|
mOverlaySurfaceTexture.releaseTexImage(); |
|
|
|
mOverlaySurfaceTexture.releaseTexImage(); |
|
|
|
mOverlaySurface.release(); |
|
|
|
mOverlaySurface.release(); |
|
|
|