Loading core/java/android/hardware/camera2/CaptureRequest.java +115 −20 Original line number Diff line number Diff line Loading @@ -21,15 +21,18 @@ import android.annotation.Nullable; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.PublicKey; import android.hardware.camera2.impl.SyntheticKey; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.TypeReference; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.view.Surface; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; Loading Loading @@ -198,7 +201,24 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> } } private final HashSet<Surface> mSurfaceSet; private final String TAG = "CaptureRequest-JV"; private final ArraySet<Surface> mSurfaceSet = new ArraySet<Surface>(); // Speed up sending CaptureRequest across IPC: // mSurfaceConverted should only be set to true during capture request // submission by {@link #convertSurfaceToStreamId}. The method will convert // surfaces to stream/surface indexes based on passed in stream configuration at that time. // This will save significant unparcel time for remote camera device. // Once the request is submitted, camera device will call {@link #recoverStreamIdToSurface} // to reset the capture request back to its original state. private final Object mSurfacesLock = new Object(); private boolean mSurfaceConverted = false; private int[] mStreamIdxArray; private int[] mSurfaceIdxArray; private static final ArraySet<Surface> mEmptySurfaceSet = new ArraySet<Surface>(); private final CameraMetadataNative mSettings; private boolean mIsReprocess; // If this request is part of constrained high speed request list that was created by Loading @@ -218,7 +238,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private CaptureRequest() { mSettings = new CameraMetadataNative(); setNativeInstance(mSettings); mSurfaceSet = new HashSet<Surface>(); mIsReprocess = false; mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE; } Loading @@ -232,7 +251,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private CaptureRequest(CaptureRequest source) { mSettings = new CameraMetadataNative(source.mSettings); setNativeInstance(mSettings); mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone(); mSurfaceSet.addAll(source.mSurfaceSet); mIsReprocess = source.mIsReprocess; mIsPartOfCHSRequestList = source.mIsPartOfCHSRequestList; mReprocessableSessionId = source.mReprocessableSessionId; Loading Loading @@ -263,7 +282,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> int reprocessableSessionId) { mSettings = CameraMetadataNative.move(settings); setNativeInstance(mSettings); mSurfaceSet = new HashSet<Surface>(); mIsReprocess = isReprocess; if (isReprocess) { if (reprocessableSessionId == CameraCaptureSession.SESSION_ID_NONE) { Loading Loading @@ -463,22 +481,25 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private void readFromParcel(Parcel in) { mSettings.readFromParcel(in); setNativeInstance(mSettings); mIsReprocess = (in.readInt() == 0) ? false : true; mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE; synchronized (mSurfacesLock) { mSurfaceSet.clear(); Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader()); if (parcelableArray == null) { return; } if (parcelableArray != null) { for (Parcelable p : parcelableArray) { Surface s = (Surface) p; mSurfaceSet.add(s); } mIsReprocess = (in.readInt() == 0) ? false : true; mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE; } // Intentionally disallow java side readFromParcel to receive streamIdx/surfaceIdx // Since there is no good way to convert indexes back to Surface int streamSurfaceSize = in.readInt(); if (streamSurfaceSize != 0) { throw new RuntimeException("Reading cached CaptureRequest is not supported"); } } } @Override Loading @@ -489,8 +510,21 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> @Override public void writeToParcel(Parcel dest, int flags) { mSettings.writeToParcel(dest, flags); dest.writeParcelableArray(mSurfaceSet.toArray(new Surface[mSurfaceSet.size()]), flags); dest.writeInt(mIsReprocess ? 1 : 0); synchronized (mSurfacesLock) { final ArraySet<Surface> surfaces = mSurfaceConverted ? mEmptySurfaceSet : mSurfaceSet; dest.writeParcelableArray(surfaces.toArray(new Surface[surfaces.size()]), flags); if (mSurfaceConverted) { dest.writeInt(mStreamIdxArray.length); for (int i = 0; i < mStreamIdxArray.length; i++) { dest.writeInt(mStreamIdxArray[i]); dest.writeInt(mSurfaceIdxArray[i]); } } else { dest.writeInt(0); } } } /** Loading @@ -507,6 +541,67 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> return Collections.unmodifiableCollection(mSurfaceSet); } /** * @hide */ public void convertSurfaceToStreamId( final SparseArray<OutputConfiguration> configuredOutputs) { synchronized (mSurfacesLock) { if (mSurfaceConverted) { Log.v(TAG, "Cannot convert already converted surfaces!"); return; } mStreamIdxArray = new int[mSurfaceSet.size()]; mSurfaceIdxArray = new int[mSurfaceSet.size()]; int i = 0; for (Surface s : mSurfaceSet) { boolean streamFound = false; for (int j = 0; j < configuredOutputs.size(); ++j) { int streamId = configuredOutputs.keyAt(j); OutputConfiguration outConfig = configuredOutputs.valueAt(j); int surfaceId = 0; for (Surface outSurface : outConfig.getSurfaces()) { if (s == outSurface) { streamFound = true; mStreamIdxArray[i] = streamId; mSurfaceIdxArray[i] = surfaceId; i++; break; } surfaceId++; } if (streamFound) { break; } } if (!streamFound) { mStreamIdxArray = null; mSurfaceIdxArray = null; throw new IllegalArgumentException( "CaptureRequest contains unconfigured Input/Output Surface!"); } } mSurfaceConverted = true; } } /** * @hide */ public void recoverStreamIdToSurface() { synchronized (mSurfacesLock) { if (!mSurfaceConverted) { Log.v(TAG, "Cannot convert already converted surfaces!"); return; } mStreamIdxArray = null; mSurfaceIdxArray = null; mSurfaceConverted = false; } } /** * A builder for capture requests. * Loading core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +11 −0 Original line number Diff line number Diff line Loading @@ -779,6 +779,7 @@ public class CameraDeviceImpl extends CameraDevice } mRemoteDevice.updateOutputConfiguration(streamId, config); mConfiguredOutputs.put(streamId, config); } } Loading Loading @@ -828,6 +829,7 @@ public class CameraDeviceImpl extends CameraDevice + " must have at least 1 surface"); } mRemoteDevice.finalizeOutputConfigurations(streamId, config); mConfiguredOutputs.put(streamId, config); } } } Loading Loading @@ -950,11 +952,20 @@ public class CameraDeviceImpl extends CameraDevice SubmitInfo requestInfo; CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]); // Convert Surface to streamIdx and surfaceIdx for (CaptureRequest request : requestArray) { request.convertSurfaceToStreamId(mConfiguredOutputs); } requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating); if (DEBUG) { Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber()); } for (CaptureRequest request : requestArray) { request.recoverStreamIdToSurface(); } if (callback != null) { mCaptureCallbackMap.put(requestInfo.getRequestId(), new CaptureCallbackHolder( Loading Loading
core/java/android/hardware/camera2/CaptureRequest.java +115 −20 Original line number Diff line number Diff line Loading @@ -21,15 +21,18 @@ import android.annotation.Nullable; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.PublicKey; import android.hardware.camera2.impl.SyntheticKey; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.TypeReference; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.view.Surface; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; Loading Loading @@ -198,7 +201,24 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> } } private final HashSet<Surface> mSurfaceSet; private final String TAG = "CaptureRequest-JV"; private final ArraySet<Surface> mSurfaceSet = new ArraySet<Surface>(); // Speed up sending CaptureRequest across IPC: // mSurfaceConverted should only be set to true during capture request // submission by {@link #convertSurfaceToStreamId}. The method will convert // surfaces to stream/surface indexes based on passed in stream configuration at that time. // This will save significant unparcel time for remote camera device. // Once the request is submitted, camera device will call {@link #recoverStreamIdToSurface} // to reset the capture request back to its original state. private final Object mSurfacesLock = new Object(); private boolean mSurfaceConverted = false; private int[] mStreamIdxArray; private int[] mSurfaceIdxArray; private static final ArraySet<Surface> mEmptySurfaceSet = new ArraySet<Surface>(); private final CameraMetadataNative mSettings; private boolean mIsReprocess; // If this request is part of constrained high speed request list that was created by Loading @@ -218,7 +238,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private CaptureRequest() { mSettings = new CameraMetadataNative(); setNativeInstance(mSettings); mSurfaceSet = new HashSet<Surface>(); mIsReprocess = false; mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE; } Loading @@ -232,7 +251,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private CaptureRequest(CaptureRequest source) { mSettings = new CameraMetadataNative(source.mSettings); setNativeInstance(mSettings); mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone(); mSurfaceSet.addAll(source.mSurfaceSet); mIsReprocess = source.mIsReprocess; mIsPartOfCHSRequestList = source.mIsPartOfCHSRequestList; mReprocessableSessionId = source.mReprocessableSessionId; Loading Loading @@ -263,7 +282,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> int reprocessableSessionId) { mSettings = CameraMetadataNative.move(settings); setNativeInstance(mSettings); mSurfaceSet = new HashSet<Surface>(); mIsReprocess = isReprocess; if (isReprocess) { if (reprocessableSessionId == CameraCaptureSession.SESSION_ID_NONE) { Loading Loading @@ -463,22 +481,25 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private void readFromParcel(Parcel in) { mSettings.readFromParcel(in); setNativeInstance(mSettings); mIsReprocess = (in.readInt() == 0) ? false : true; mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE; synchronized (mSurfacesLock) { mSurfaceSet.clear(); Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader()); if (parcelableArray == null) { return; } if (parcelableArray != null) { for (Parcelable p : parcelableArray) { Surface s = (Surface) p; mSurfaceSet.add(s); } mIsReprocess = (in.readInt() == 0) ? false : true; mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE; } // Intentionally disallow java side readFromParcel to receive streamIdx/surfaceIdx // Since there is no good way to convert indexes back to Surface int streamSurfaceSize = in.readInt(); if (streamSurfaceSize != 0) { throw new RuntimeException("Reading cached CaptureRequest is not supported"); } } } @Override Loading @@ -489,8 +510,21 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> @Override public void writeToParcel(Parcel dest, int flags) { mSettings.writeToParcel(dest, flags); dest.writeParcelableArray(mSurfaceSet.toArray(new Surface[mSurfaceSet.size()]), flags); dest.writeInt(mIsReprocess ? 1 : 0); synchronized (mSurfacesLock) { final ArraySet<Surface> surfaces = mSurfaceConverted ? mEmptySurfaceSet : mSurfaceSet; dest.writeParcelableArray(surfaces.toArray(new Surface[surfaces.size()]), flags); if (mSurfaceConverted) { dest.writeInt(mStreamIdxArray.length); for (int i = 0; i < mStreamIdxArray.length; i++) { dest.writeInt(mStreamIdxArray[i]); dest.writeInt(mSurfaceIdxArray[i]); } } else { dest.writeInt(0); } } } /** Loading @@ -507,6 +541,67 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> return Collections.unmodifiableCollection(mSurfaceSet); } /** * @hide */ public void convertSurfaceToStreamId( final SparseArray<OutputConfiguration> configuredOutputs) { synchronized (mSurfacesLock) { if (mSurfaceConverted) { Log.v(TAG, "Cannot convert already converted surfaces!"); return; } mStreamIdxArray = new int[mSurfaceSet.size()]; mSurfaceIdxArray = new int[mSurfaceSet.size()]; int i = 0; for (Surface s : mSurfaceSet) { boolean streamFound = false; for (int j = 0; j < configuredOutputs.size(); ++j) { int streamId = configuredOutputs.keyAt(j); OutputConfiguration outConfig = configuredOutputs.valueAt(j); int surfaceId = 0; for (Surface outSurface : outConfig.getSurfaces()) { if (s == outSurface) { streamFound = true; mStreamIdxArray[i] = streamId; mSurfaceIdxArray[i] = surfaceId; i++; break; } surfaceId++; } if (streamFound) { break; } } if (!streamFound) { mStreamIdxArray = null; mSurfaceIdxArray = null; throw new IllegalArgumentException( "CaptureRequest contains unconfigured Input/Output Surface!"); } } mSurfaceConverted = true; } } /** * @hide */ public void recoverStreamIdToSurface() { synchronized (mSurfacesLock) { if (!mSurfaceConverted) { Log.v(TAG, "Cannot convert already converted surfaces!"); return; } mStreamIdxArray = null; mSurfaceIdxArray = null; mSurfaceConverted = false; } } /** * A builder for capture requests. * Loading
core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +11 −0 Original line number Diff line number Diff line Loading @@ -779,6 +779,7 @@ public class CameraDeviceImpl extends CameraDevice } mRemoteDevice.updateOutputConfiguration(streamId, config); mConfiguredOutputs.put(streamId, config); } } Loading Loading @@ -828,6 +829,7 @@ public class CameraDeviceImpl extends CameraDevice + " must have at least 1 surface"); } mRemoteDevice.finalizeOutputConfigurations(streamId, config); mConfiguredOutputs.put(streamId, config); } } } Loading Loading @@ -950,11 +952,20 @@ public class CameraDeviceImpl extends CameraDevice SubmitInfo requestInfo; CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]); // Convert Surface to streamIdx and surfaceIdx for (CaptureRequest request : requestArray) { request.convertSurfaceToStreamId(mConfiguredOutputs); } requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating); if (DEBUG) { Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber()); } for (CaptureRequest request : requestArray) { request.recoverStreamIdToSurface(); } if (callback != null) { mCaptureCallbackMap.put(requestInfo.getRequestId(), new CaptureCallbackHolder( Loading