Loading core/java/android/hardware/camera2/legacy/BurstHolder.java +7 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.util.Log; import android.view.Surface; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** Loading @@ -38,14 +39,16 @@ public class BurstHolder { * * @param requestId id of the burst request. * @param repeating true if this burst is repeating. * @param requests a {@link java.util.List} of {@link CaptureRequest}s in this burst. * @param requests a {@link List} of {@link CaptureRequest}s in this burst. * @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs. */ public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests) { mRequestBuilders = new ArrayList<RequestHolder.Builder>(); public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests, Collection<Long> jpegSurfaceIds) { mRequestBuilders = new ArrayList<>(); int i = 0; for (CaptureRequest r : requests) { mRequestBuilders.add(new RequestHolder.Builder(requestId, /*subsequenceId*/i, /*request*/r, repeating)); /*request*/r, repeating, jpegSurfaceIds)); ++i; } mRepeating = repeating; Loading core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +1 −1 Original line number Diff line number Diff line Loading @@ -522,7 +522,7 @@ public class LegacyCameraDevice implements AutoCloseable { return surfaceIds; } static boolean containsSurfaceId(Surface s, List<Long> ids) { static boolean containsSurfaceId(Surface s, Collection<Long> ids) { long id = getSurfaceId(s); return ids.contains(id); } Loading core/java/android/hardware/camera2/legacy/RequestHolder.java +66 −66 Original line number Diff line number Diff line Loading @@ -42,16 +42,52 @@ public class RequestHolder { private final int mNumPreviewTargets; private volatile boolean mFailed = false; /** * A builder class for {@link RequestHolder} objects. * * <p> * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects. * </p> */ public final static class Builder { private final int mRequestId; private final int mSubsequenceId; private final CaptureRequest mRequest; private final boolean mRepeating; private final int mNumJpegTargets; private final int mNumPreviewTargets; private final Collection<Long> mJpegSurfaceIds; /** * Construct a new {@link Builder} to generate {@link RequestHolder} objects. * * @param requestId the ID to set in {@link RequestHolder} objects. * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects. * @param request the original {@link CaptureRequest} to set in {@link RequestHolder} * objects. * @param repeating {@code true} if the request is repeating. */ public Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, Collection<Long> jpegSurfaceIds) { checkNotNull(request, "request must not be null"); mRequestId = requestId; mSubsequenceId = subsequenceId; mRequest = request; mRepeating = repeating; mJpegSurfaceIds = jpegSurfaceIds; mNumJpegTargets = numJpegTargets(mRequest); mNumPreviewTargets = numPreviewTargets(mRequest); } /** * Returns true if the given surface requires jpeg buffers. * * @param s a {@link android.view.Surface} to check. * @return true if the surface requires a jpeg buffer. */ public static boolean jpegType(Surface s) private boolean jpegType(Surface s) throws LegacyExceptionUtils.BufferQueueAbandonedException { return LegacyCameraDevice.detectSurfaceType(s) == CameraMetadataNative.NATIVE_JPEG_FORMAT; return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds); } /** Loading @@ -67,16 +103,15 @@ public class RequestHolder { * @param s a {@link android.view.Surface} to check. * @return true if the surface requires a non-jpeg buffer type. */ public static boolean previewType(Surface s) private boolean previewType(Surface s) throws LegacyExceptionUtils.BufferQueueAbandonedException { return LegacyCameraDevice.detectSurfaceType(s) != CameraMetadataNative.NATIVE_JPEG_FORMAT; return !jpegType(s); } /** * Returns the number of surfaces targeted by the request that require jpeg buffers. */ private static int numJpegTargets(CaptureRequest request) { private int numJpegTargets(CaptureRequest request) { int count = 0; for (Surface s : request.getTargets()) { try { Loading @@ -84,7 +119,7 @@ public class RequestHolder { ++count; } } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { Log.w(TAG, "Surface abandoned, skipping...", e); Log.d(TAG, "Surface abandoned, skipping...", e); } } return count; Loading @@ -93,7 +128,7 @@ public class RequestHolder { /** * Returns the number of surfaces targeted by the request that require non-jpeg buffers. */ private static int numPreviewTargets(CaptureRequest request) { private int numPreviewTargets(CaptureRequest request) { int count = 0; for (Surface s : request.getTargets()) { try { Loading @@ -101,47 +136,12 @@ public class RequestHolder { ++count; } } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { Log.w(TAG, "Surface abandoned, skipping...", e); Log.d(TAG, "Surface abandoned, skipping...", e); } } return count; } /** * A builder class for {@link RequestHolder} objects. * * <p> * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects. * </p> */ public final static class Builder { private final int mRequestId; private final int mSubsequenceId; private final CaptureRequest mRequest; private final boolean mRepeating; private final int mNumJpegTargets; private final int mNumPreviewTargets; /** * Construct a new {@link Builder} to generate {@link RequestHolder} objects. * * @param requestId the ID to set in {@link RequestHolder} objects. * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects. * @param request the original {@link CaptureRequest} to set in {@link RequestHolder} * objects. * @param repeating {@code true} if the request is repeating. */ public Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating) { checkNotNull(request, "request must not be null"); mRequestId = requestId; mSubsequenceId = subsequenceId; mRequest = request; mRepeating = repeating; mNumJpegTargets = numJpegTargets(mRequest); mNumPreviewTargets = numPreviewTargets(mRequest); } /** * Build a new {@link RequestHolder} using with parameters generated from this * {@link Builder}. Loading core/java/android/hardware/camera2/legacy/RequestQueue.java +5 −2 Original line number Diff line number Diff line Loading @@ -39,8 +39,11 @@ public class RequestQueue { private long mCurrentFrameNumber = 0; private long mCurrentRepeatingFrameNumber = INVALID_FRAME; private int mCurrentRequestId = 0; private final List<Long> mJpegSurfaceIds; public RequestQueue() {} public RequestQueue(List<Long> jpegSurfaceIds) { mJpegSurfaceIds = jpegSurfaceIds; } /** * Return and remove the next burst on the queue. Loading Loading @@ -117,7 +120,7 @@ public class RequestQueue { public synchronized int submit(List<CaptureRequest> requests, boolean repeating, /*out*/LongParcelable frameNumber) { int requestId = mCurrentRequestId++; BurstHolder burst = new BurstHolder(requestId, repeating, requests); BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds); long ret = INVALID_FRAME; if (burst.isRepeating()) { Log.i(TAG, "Repeating capture request set."); Loading core/java/android/hardware/camera2/legacy/RequestThreadManager.java +35 −8 Original line number Diff line number Diff line Loading @@ -91,9 +91,11 @@ public class RequestThreadManager { private SurfaceTexture mPreviewTexture; private Camera.Parameters mParams; private final List<Long> mJpegSurfaceIds = new ArrayList<>(); private Size mIntermediateBufferSize; private final RequestQueue mRequestQueue = new RequestQueue(); private final RequestQueue mRequestQueue = new RequestQueue(mJpegSurfaceIds); private LegacyRequest mLastRequest = null; private SurfaceTexture mDummyTexture; private Surface mDummySurface; Loading @@ -102,6 +104,10 @@ public class RequestThreadManager { private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write // limitations for (b/17379185). private static final boolean USE_BLOB_FORMAT_OVERRIDE = true; /** * Container object for Configure messages. */ Loading Loading @@ -197,10 +203,13 @@ public class RequestThreadManager { } for (Surface s : holder.getHolderTargets()) { try { if (RequestHolder.jpegType(s)) { if (LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds)) { Log.i(TAG, "Producing jpeg buffer..."); LegacyCameraDevice.setSurfaceDimens(s, data.length + LegacyCameraDevice.nativeGetJpegFooterSize(), /*height*/1); int totalSize = data.length + LegacyCameraDevice.nativeGetJpegFooterSize(); totalSize += ((totalSize - 1) & ~0x3) + 4; // align to next octonibble LegacyCameraDevice.setSurfaceDimens(s, totalSize, /*height*/1); LegacyCameraDevice.setNextTimestamp(s, timestamp); LegacyCameraDevice.produceFrame(s, data, data.length, /*height*/1, CameraMetadataNative.NATIVE_JPEG_FORMAT); Loading Loading @@ -316,6 +325,7 @@ public class RequestThreadManager { mGLThreadManager.ignoreNewFrames(); mGLThreadManager.waitUntilIdle(); } resetJpegSurfaceFormats(mCallbackOutputs); mPreviewOutputs.clear(); mCallbackOutputs.clear(); mPreviewTexture = null; Loading @@ -329,6 +339,12 @@ public class RequestThreadManager { LegacyCameraDevice.setSurfaceOrientation(s, facing, orientation); switch (format) { case CameraMetadataNative.NATIVE_JPEG_FORMAT: if (USE_BLOB_FORMAT_OVERRIDE) { // Override to RGBA_8888 format. LegacyCameraDevice.setSurfaceFormat(s, LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888); } mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s)); mCallbackOutputs.add(s); break; default: Loading Loading @@ -426,8 +442,19 @@ public class RequestThreadManager { } mCamera.setParameters(mParams); // TODO: configure the JPEG surface with some arbitrary size // using LegacyCameraDevice.nativeConfigureSurface } private void resetJpegSurfaceFormats(Collection<Surface> surfaces) { if (!USE_BLOB_FORMAT_OVERRIDE || surfaces == null) { return; } for(Surface s : surfaces) { try { LegacyCameraDevice.setSurfaceFormat(s, LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB); } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { Log.w(TAG, "Surface abandoned, skipping...", e); } } } /** Loading Loading @@ -459,9 +486,8 @@ public class RequestThreadManager { List<Size> configuredJpegSizes = new ArrayList<Size>(); for (Surface callbackSurface : callbackOutputs) { try { int format = LegacyCameraDevice.detectSurfaceType(callbackSurface); if (format != CameraMetadataNative.NATIVE_JPEG_FORMAT) { if (!LegacyCameraDevice.containsSurfaceId(callbackSurface, mJpegSurfaceIds)) { continue; // Ignore non-JPEG callback formats } Loading Loading @@ -821,6 +847,7 @@ public class RequestThreadManager { if (mCamera != null) { mCamera.release(); } resetJpegSurfaceFormats(mCallbackOutputs); break; default: throw new AssertionError("Unhandled message " + msg.what + Loading Loading
core/java/android/hardware/camera2/legacy/BurstHolder.java +7 −4 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.util.Log; import android.view.Surface; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** Loading @@ -38,14 +39,16 @@ public class BurstHolder { * * @param requestId id of the burst request. * @param repeating true if this burst is repeating. * @param requests a {@link java.util.List} of {@link CaptureRequest}s in this burst. * @param requests a {@link List} of {@link CaptureRequest}s in this burst. * @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs. */ public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests) { mRequestBuilders = new ArrayList<RequestHolder.Builder>(); public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests, Collection<Long> jpegSurfaceIds) { mRequestBuilders = new ArrayList<>(); int i = 0; for (CaptureRequest r : requests) { mRequestBuilders.add(new RequestHolder.Builder(requestId, /*subsequenceId*/i, /*request*/r, repeating)); /*request*/r, repeating, jpegSurfaceIds)); ++i; } mRepeating = repeating; Loading
core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +1 −1 Original line number Diff line number Diff line Loading @@ -522,7 +522,7 @@ public class LegacyCameraDevice implements AutoCloseable { return surfaceIds; } static boolean containsSurfaceId(Surface s, List<Long> ids) { static boolean containsSurfaceId(Surface s, Collection<Long> ids) { long id = getSurfaceId(s); return ids.contains(id); } Loading
core/java/android/hardware/camera2/legacy/RequestHolder.java +66 −66 Original line number Diff line number Diff line Loading @@ -42,16 +42,52 @@ public class RequestHolder { private final int mNumPreviewTargets; private volatile boolean mFailed = false; /** * A builder class for {@link RequestHolder} objects. * * <p> * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects. * </p> */ public final static class Builder { private final int mRequestId; private final int mSubsequenceId; private final CaptureRequest mRequest; private final boolean mRepeating; private final int mNumJpegTargets; private final int mNumPreviewTargets; private final Collection<Long> mJpegSurfaceIds; /** * Construct a new {@link Builder} to generate {@link RequestHolder} objects. * * @param requestId the ID to set in {@link RequestHolder} objects. * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects. * @param request the original {@link CaptureRequest} to set in {@link RequestHolder} * objects. * @param repeating {@code true} if the request is repeating. */ public Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, Collection<Long> jpegSurfaceIds) { checkNotNull(request, "request must not be null"); mRequestId = requestId; mSubsequenceId = subsequenceId; mRequest = request; mRepeating = repeating; mJpegSurfaceIds = jpegSurfaceIds; mNumJpegTargets = numJpegTargets(mRequest); mNumPreviewTargets = numPreviewTargets(mRequest); } /** * Returns true if the given surface requires jpeg buffers. * * @param s a {@link android.view.Surface} to check. * @return true if the surface requires a jpeg buffer. */ public static boolean jpegType(Surface s) private boolean jpegType(Surface s) throws LegacyExceptionUtils.BufferQueueAbandonedException { return LegacyCameraDevice.detectSurfaceType(s) == CameraMetadataNative.NATIVE_JPEG_FORMAT; return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds); } /** Loading @@ -67,16 +103,15 @@ public class RequestHolder { * @param s a {@link android.view.Surface} to check. * @return true if the surface requires a non-jpeg buffer type. */ public static boolean previewType(Surface s) private boolean previewType(Surface s) throws LegacyExceptionUtils.BufferQueueAbandonedException { return LegacyCameraDevice.detectSurfaceType(s) != CameraMetadataNative.NATIVE_JPEG_FORMAT; return !jpegType(s); } /** * Returns the number of surfaces targeted by the request that require jpeg buffers. */ private static int numJpegTargets(CaptureRequest request) { private int numJpegTargets(CaptureRequest request) { int count = 0; for (Surface s : request.getTargets()) { try { Loading @@ -84,7 +119,7 @@ public class RequestHolder { ++count; } } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { Log.w(TAG, "Surface abandoned, skipping...", e); Log.d(TAG, "Surface abandoned, skipping...", e); } } return count; Loading @@ -93,7 +128,7 @@ public class RequestHolder { /** * Returns the number of surfaces targeted by the request that require non-jpeg buffers. */ private static int numPreviewTargets(CaptureRequest request) { private int numPreviewTargets(CaptureRequest request) { int count = 0; for (Surface s : request.getTargets()) { try { Loading @@ -101,47 +136,12 @@ public class RequestHolder { ++count; } } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { Log.w(TAG, "Surface abandoned, skipping...", e); Log.d(TAG, "Surface abandoned, skipping...", e); } } return count; } /** * A builder class for {@link RequestHolder} objects. * * <p> * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects. * </p> */ public final static class Builder { private final int mRequestId; private final int mSubsequenceId; private final CaptureRequest mRequest; private final boolean mRepeating; private final int mNumJpegTargets; private final int mNumPreviewTargets; /** * Construct a new {@link Builder} to generate {@link RequestHolder} objects. * * @param requestId the ID to set in {@link RequestHolder} objects. * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects. * @param request the original {@link CaptureRequest} to set in {@link RequestHolder} * objects. * @param repeating {@code true} if the request is repeating. */ public Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating) { checkNotNull(request, "request must not be null"); mRequestId = requestId; mSubsequenceId = subsequenceId; mRequest = request; mRepeating = repeating; mNumJpegTargets = numJpegTargets(mRequest); mNumPreviewTargets = numPreviewTargets(mRequest); } /** * Build a new {@link RequestHolder} using with parameters generated from this * {@link Builder}. Loading
core/java/android/hardware/camera2/legacy/RequestQueue.java +5 −2 Original line number Diff line number Diff line Loading @@ -39,8 +39,11 @@ public class RequestQueue { private long mCurrentFrameNumber = 0; private long mCurrentRepeatingFrameNumber = INVALID_FRAME; private int mCurrentRequestId = 0; private final List<Long> mJpegSurfaceIds; public RequestQueue() {} public RequestQueue(List<Long> jpegSurfaceIds) { mJpegSurfaceIds = jpegSurfaceIds; } /** * Return and remove the next burst on the queue. Loading Loading @@ -117,7 +120,7 @@ public class RequestQueue { public synchronized int submit(List<CaptureRequest> requests, boolean repeating, /*out*/LongParcelable frameNumber) { int requestId = mCurrentRequestId++; BurstHolder burst = new BurstHolder(requestId, repeating, requests); BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds); long ret = INVALID_FRAME; if (burst.isRepeating()) { Log.i(TAG, "Repeating capture request set."); Loading
core/java/android/hardware/camera2/legacy/RequestThreadManager.java +35 −8 Original line number Diff line number Diff line Loading @@ -91,9 +91,11 @@ public class RequestThreadManager { private SurfaceTexture mPreviewTexture; private Camera.Parameters mParams; private final List<Long> mJpegSurfaceIds = new ArrayList<>(); private Size mIntermediateBufferSize; private final RequestQueue mRequestQueue = new RequestQueue(); private final RequestQueue mRequestQueue = new RequestQueue(mJpegSurfaceIds); private LegacyRequest mLastRequest = null; private SurfaceTexture mDummyTexture; private Surface mDummySurface; Loading @@ -102,6 +104,10 @@ public class RequestThreadManager { private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write // limitations for (b/17379185). private static final boolean USE_BLOB_FORMAT_OVERRIDE = true; /** * Container object for Configure messages. */ Loading Loading @@ -197,10 +203,13 @@ public class RequestThreadManager { } for (Surface s : holder.getHolderTargets()) { try { if (RequestHolder.jpegType(s)) { if (LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds)) { Log.i(TAG, "Producing jpeg buffer..."); LegacyCameraDevice.setSurfaceDimens(s, data.length + LegacyCameraDevice.nativeGetJpegFooterSize(), /*height*/1); int totalSize = data.length + LegacyCameraDevice.nativeGetJpegFooterSize(); totalSize += ((totalSize - 1) & ~0x3) + 4; // align to next octonibble LegacyCameraDevice.setSurfaceDimens(s, totalSize, /*height*/1); LegacyCameraDevice.setNextTimestamp(s, timestamp); LegacyCameraDevice.produceFrame(s, data, data.length, /*height*/1, CameraMetadataNative.NATIVE_JPEG_FORMAT); Loading Loading @@ -316,6 +325,7 @@ public class RequestThreadManager { mGLThreadManager.ignoreNewFrames(); mGLThreadManager.waitUntilIdle(); } resetJpegSurfaceFormats(mCallbackOutputs); mPreviewOutputs.clear(); mCallbackOutputs.clear(); mPreviewTexture = null; Loading @@ -329,6 +339,12 @@ public class RequestThreadManager { LegacyCameraDevice.setSurfaceOrientation(s, facing, orientation); switch (format) { case CameraMetadataNative.NATIVE_JPEG_FORMAT: if (USE_BLOB_FORMAT_OVERRIDE) { // Override to RGBA_8888 format. LegacyCameraDevice.setSurfaceFormat(s, LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888); } mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s)); mCallbackOutputs.add(s); break; default: Loading Loading @@ -426,8 +442,19 @@ public class RequestThreadManager { } mCamera.setParameters(mParams); // TODO: configure the JPEG surface with some arbitrary size // using LegacyCameraDevice.nativeConfigureSurface } private void resetJpegSurfaceFormats(Collection<Surface> surfaces) { if (!USE_BLOB_FORMAT_OVERRIDE || surfaces == null) { return; } for(Surface s : surfaces) { try { LegacyCameraDevice.setSurfaceFormat(s, LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB); } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { Log.w(TAG, "Surface abandoned, skipping...", e); } } } /** Loading Loading @@ -459,9 +486,8 @@ public class RequestThreadManager { List<Size> configuredJpegSizes = new ArrayList<Size>(); for (Surface callbackSurface : callbackOutputs) { try { int format = LegacyCameraDevice.detectSurfaceType(callbackSurface); if (format != CameraMetadataNative.NATIVE_JPEG_FORMAT) { if (!LegacyCameraDevice.containsSurfaceId(callbackSurface, mJpegSurfaceIds)) { continue; // Ignore non-JPEG callback formats } Loading Loading @@ -821,6 +847,7 @@ public class RequestThreadManager { if (mCamera != null) { mCamera.release(); } resetJpegSurfaceFormats(mCallbackOutputs); break; default: throw new AssertionError("Unhandled message " + msg.what + Loading