Camera: update createStream API to add new rotation field
Change-Id: I0f4343a0bfa7bf09ba887c78a1da1c08daa35333
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
package android.hardware.camera2;
|
||||
|
||||
import android.view.Surface;
|
||||
import android.hardware.camera2.params.OutputConfiguration;
|
||||
import android.hardware.camera2.impl.CameraMetadataNative;
|
||||
import android.hardware.camera2.CaptureRequest;
|
||||
|
||||
@@ -66,7 +66,7 @@ interface ICameraDeviceUser
|
||||
int deleteStream(int streamId);
|
||||
|
||||
// non-negative value is the stream ID. negative value is status_t
|
||||
int createStream(in Surface surface);
|
||||
int createStream(in OutputConfiguration outputConfiguration);
|
||||
|
||||
int createDefaultRequest(int templateId, out CameraMetadataNative request);
|
||||
|
||||
|
||||
@@ -79,7 +79,8 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
private int mRepeatingRequestId = REQUEST_ID_NONE;
|
||||
private final ArrayList<Integer> mRepeatingRequestIdDeletedList = new ArrayList<Integer>();
|
||||
// Map stream IDs to Surfaces
|
||||
private final SparseArray<Surface> mConfiguredOutputs = new SparseArray<Surface>();
|
||||
private final SparseArray<OutputConfiguration> mConfiguredOutputs =
|
||||
new SparseArray<OutputConfiguration>();
|
||||
|
||||
private final String mCameraId;
|
||||
private final CameraCharacteristics mCharacteristics;
|
||||
@@ -315,7 +316,11 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
|
||||
public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
|
||||
// Leave this here for backwards compatibility with older code using this directly
|
||||
configureOutputsChecked(outputs);
|
||||
ArrayList<OutputConfiguration> outputConfigs = new ArrayList<>(outputs.size());
|
||||
for (Surface s : outputs) {
|
||||
outputConfigs.add(new OutputConfiguration(s));
|
||||
}
|
||||
configureOutputsChecked(outputConfigs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,28 +339,30 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
*
|
||||
* @throws CameraAccessException if there were any unexpected problems during configuration
|
||||
*/
|
||||
public boolean configureOutputsChecked(List<Surface> outputs) throws CameraAccessException {
|
||||
public boolean configureOutputsChecked(List<OutputConfiguration> outputs)
|
||||
throws CameraAccessException {
|
||||
// Treat a null input the same an empty list
|
||||
if (outputs == null) {
|
||||
outputs = new ArrayList<Surface>();
|
||||
outputs = new ArrayList<OutputConfiguration>();
|
||||
}
|
||||
boolean success = false;
|
||||
|
||||
synchronized(mInterfaceLock) {
|
||||
checkIfCameraClosedOrInError();
|
||||
|
||||
HashSet<Surface> addSet = new HashSet<Surface>(outputs); // Streams to create
|
||||
List<Integer> deleteList = new ArrayList<Integer>(); // Streams to delete
|
||||
// Streams to create
|
||||
HashSet<OutputConfiguration> addSet = new HashSet<OutputConfiguration>(outputs);
|
||||
// Streams to delete
|
||||
List<Integer> deleteList = new ArrayList<Integer>();
|
||||
|
||||
// Determine which streams need to be created, which to be deleted
|
||||
for (int i = 0; i < mConfiguredOutputs.size(); ++i) {
|
||||
int streamId = mConfiguredOutputs.keyAt(i);
|
||||
Surface s = mConfiguredOutputs.valueAt(i);
|
||||
OutputConfiguration outConfig = mConfiguredOutputs.valueAt(i);
|
||||
|
||||
if (!outputs.contains(s)) {
|
||||
if (!outputs.contains(outConfig)) {
|
||||
deleteList.add(streamId);
|
||||
} else {
|
||||
addSet.remove(s); // Don't create a stream previously created
|
||||
addSet.remove(outConfig); // Don't create a stream previously created
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,9 +380,11 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
}
|
||||
|
||||
// Add all new streams
|
||||
for (Surface s : addSet) {
|
||||
int streamId = mRemoteDevice.createStream(s);
|
||||
mConfiguredOutputs.put(streamId, s);
|
||||
for (OutputConfiguration outConfig : outputs) {
|
||||
if (addSet.contains(outConfig)) {
|
||||
int streamId = mRemoteDevice.createStream(outConfig);
|
||||
mConfiguredOutputs.put(streamId, outConfig);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -444,12 +453,9 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
// TODO: dont block for this
|
||||
boolean configureSuccess = true;
|
||||
CameraAccessException pendingException = null;
|
||||
List<Surface> outSurfaces = new ArrayList<>(outputConfigurations.size());
|
||||
for (OutputConfiguration config : outputConfigurations) {
|
||||
outSurfaces.add(config.getSurface());
|
||||
}
|
||||
try {
|
||||
configureSuccess = configureOutputsChecked(outSurfaces); // and then block until IDLE
|
||||
// configure outputs and then block until IDLE
|
||||
configureSuccess = configureOutputsChecked(outputConfigurations);
|
||||
} catch (CameraAccessException e) {
|
||||
configureSuccess = false;
|
||||
pendingException = e;
|
||||
@@ -458,6 +464,10 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
}
|
||||
}
|
||||
|
||||
List<Surface> outSurfaces = new ArrayList<>(outputConfigurations.size());
|
||||
for (OutputConfiguration config : outputConfigurations) {
|
||||
outSurfaces.add(config.getSurface());
|
||||
}
|
||||
// Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
|
||||
CameraCaptureSessionImpl newSession =
|
||||
new CameraCaptureSessionImpl(mNextSessionId++,
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.hardware.camera2.ICameraDeviceUser;
|
||||
import android.hardware.camera2.utils.LongParcelable;
|
||||
import android.hardware.camera2.impl.CameraMetadataNative;
|
||||
import android.hardware.camera2.impl.CaptureResultExtras;
|
||||
import android.hardware.camera2.params.OutputConfiguration;
|
||||
import android.hardware.camera2.utils.CameraBinderDecorator;
|
||||
import android.hardware.camera2.utils.CameraRuntimeException;
|
||||
import android.os.ConditionVariable;
|
||||
@@ -504,7 +505,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int createStream(Surface surface) {
|
||||
public int createStream(OutputConfiguration outputConfiguration) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "createStream called.");
|
||||
}
|
||||
@@ -518,8 +519,12 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
|
||||
Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
|
||||
return CameraBinderDecorator.INVALID_OPERATION;
|
||||
}
|
||||
if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
|
||||
Log.e(TAG, "Cannot create stream, stream rotation is not supported.");
|
||||
return CameraBinderDecorator.INVALID_OPERATION;
|
||||
}
|
||||
int id = ++mSurfaceIdCounter;
|
||||
mSurfaces.put(id, surface);
|
||||
mSurfaces.put(id, outputConfiguration.getSurface());
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.camera2.params;
|
||||
|
||||
/** @hide */
|
||||
parcelable OutputConfiguration;
|
||||
@@ -18,19 +18,22 @@
|
||||
package android.hardware.camera2.params;
|
||||
|
||||
import android.hardware.camera2.CameraDevice;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
|
||||
/**
|
||||
* Immutable class for describing camera output, which contains a {@link Surface} and its specific
|
||||
* A class for describing camera output, which contains a {@link Surface} and its specific
|
||||
* configuration for creating capture session.
|
||||
*
|
||||
* @see CameraDevice#createCaptureSession
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class OutputConfiguration {
|
||||
public final class OutputConfiguration implements Parcelable {
|
||||
|
||||
/**
|
||||
* Rotation constant: 0 degree rotation (no rotation)
|
||||
@@ -92,6 +95,18 @@ public final class OutputConfiguration {
|
||||
mRotation = rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an OutputConfiguration from Parcel.
|
||||
*/
|
||||
private OutputConfiguration(Parcel source) {
|
||||
int rotation = source.readInt();
|
||||
Surface surface = Surface.CREATOR.createFromParcel(source);
|
||||
checkNotNull(surface, "Surface must not be null");
|
||||
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
|
||||
mSurface = surface;
|
||||
mRotation = rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Surface} associated with this {@link OutputConfiguration}.
|
||||
*
|
||||
@@ -111,6 +126,40 @@ public final class OutputConfiguration {
|
||||
return mRotation;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<OutputConfiguration> CREATOR =
|
||||
new Parcelable.Creator<OutputConfiguration>() {
|
||||
@Override
|
||||
public OutputConfiguration createFromParcel(Parcel source) {
|
||||
try {
|
||||
OutputConfiguration outputConfiguration = new OutputConfiguration(source);
|
||||
return outputConfiguration;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Exception creating OutputConfiguration from parcel", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputConfiguration[] newArray(int size) {
|
||||
return new OutputConfiguration[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
if (dest == null) {
|
||||
throw new IllegalArgumentException("dest must not be null");
|
||||
}
|
||||
dest.writeInt(mRotation);
|
||||
mSurface.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
private static final String TAG = "OutputConfiguration";
|
||||
private final Surface mSurface;
|
||||
private final int mRotation;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.hardware.camera2.ICameraDeviceCallbacks;
|
||||
import android.hardware.camera2.ICameraDeviceUser;
|
||||
import android.hardware.camera2.impl.CameraMetadataNative;
|
||||
import android.hardware.camera2.impl.CaptureResultExtras;
|
||||
import android.hardware.camera2.params.OutputConfiguration;
|
||||
import android.hardware.camera2.utils.BinderHolder;
|
||||
import android.media.Image;
|
||||
import android.media.ImageReader;
|
||||
@@ -67,6 +68,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
|
||||
private CameraBinderTestUtils mUtils;
|
||||
private ICameraDeviceCallbacks.Stub mMockCb;
|
||||
private Surface mSurface;
|
||||
private OutputConfiguration mOutputConfiguration;
|
||||
private HandlerThread mHandlerThread;
|
||||
private Handler mHandler;
|
||||
ImageReader mImageReader;
|
||||
@@ -147,6 +149,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
|
||||
MAX_NUM_IMAGES);
|
||||
mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler);
|
||||
mSurface = mImageReader.getSurface();
|
||||
mOutputConfiguration = new OutputConfiguration(mSurface);
|
||||
}
|
||||
|
||||
private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
|
||||
@@ -161,7 +164,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
|
||||
assertFalse(request.isEmpty());
|
||||
assertFalse(metadata.isEmpty());
|
||||
if (needStream) {
|
||||
int streamId = mCameraUser.createStream(mSurface);
|
||||
int streamId = mCameraUser.createStream(mOutputConfiguration);
|
||||
assertEquals(0, streamId);
|
||||
request.addTarget(mSurface);
|
||||
}
|
||||
@@ -234,11 +237,11 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
|
||||
|
||||
@SmallTest
|
||||
public void testCreateStream() throws Exception {
|
||||
int streamId = mCameraUser.createStream(mSurface);
|
||||
int streamId = mCameraUser.createStream(mOutputConfiguration);
|
||||
assertEquals(0, streamId);
|
||||
|
||||
assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
|
||||
mCameraUser.createStream(mSurface));
|
||||
mCameraUser.createStream(mOutputConfiguration));
|
||||
|
||||
assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
|
||||
}
|
||||
@@ -255,18 +258,19 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
|
||||
public void testCreateStreamTwo() throws Exception {
|
||||
|
||||
// Create first stream
|
||||
int streamId = mCameraUser.createStream(mSurface);
|
||||
int streamId = mCameraUser.createStream(mOutputConfiguration);
|
||||
assertEquals(0, streamId);
|
||||
|
||||
assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
|
||||
mCameraUser.createStream(mSurface));
|
||||
mCameraUser.createStream(mOutputConfiguration));
|
||||
|
||||
// Create second stream with a different surface.
|
||||
SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
|
||||
surfaceTexture.setDefaultBufferSize(640, 480);
|
||||
Surface surface2 = new Surface(surfaceTexture);
|
||||
OutputConfiguration output2 = new OutputConfiguration(surface2);
|
||||
|
||||
int streamId2 = mCameraUser.createStream(surface2);
|
||||
int streamId2 = mCameraUser.createStream(output2);
|
||||
assertEquals(1, streamId2);
|
||||
|
||||
// Clean up streams
|
||||
|
||||
Reference in New Issue
Block a user