OutputConfiguration.java revision 445b316755923565c3b5b8ebb642db10de5d0ab7
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package android.hardware.camera2.params;
19
20import android.annotation.SystemApi;
21import android.hardware.camera2.CameraDevice;
22import android.hardware.camera2.utils.HashCodeHelpers;
23import android.hardware.camera2.utils.SurfaceUtils;
24import android.util.Log;
25import android.util.Size;
26import android.view.Surface;
27import android.os.Parcel;
28import android.os.Parcelable;
29
30import static com.android.internal.util.Preconditions.*;
31
32/**
33 * A class for describing camera output, which contains a {@link Surface} and its specific
34 * configuration for creating capture session.
35 *
36 * @see CameraDevice#createCaptureSessionByOutputConfiguration
37 *
38 */
39public final class OutputConfiguration implements Parcelable {
40
41    /**
42     * Rotation constant: 0 degree rotation (no rotation)
43     *
44     * @hide
45     */
46    @SystemApi
47    public static final int ROTATION_0 = 0;
48
49    /**
50     * Rotation constant: 90 degree counterclockwise rotation.
51     *
52     * @hide
53     */
54    @SystemApi
55    public static final int ROTATION_90 = 1;
56
57    /**
58     * Rotation constant: 180 degree counterclockwise rotation.
59     *
60     * @hide
61     */
62    @SystemApi
63    public static final int ROTATION_180 = 2;
64
65    /**
66     * Rotation constant: 270 degree counterclockwise rotation.
67     *
68     * @hide
69     */
70    @SystemApi
71    public static final int ROTATION_270 = 3;
72
73    /**
74     * Invalid surface set ID.
75     *
76     *<p>An {@link OutputConfiguration} with this value indicates that the included surface
77     *doesn't belong to any surface set.</p>
78     */
79    public static final int SURFACE_SET_ID_INVALID = -1;
80
81    /**
82     * Create a new {@link OutputConfiguration} instance with a {@link Surface}.
83     *
84     * @param surface
85     *          A Surface for camera to output to.
86     *
87     * <p>This constructor creates a default configuration.</p>
88     *
89     */
90    public OutputConfiguration(Surface surface) {
91        this(surface, ROTATION_0);
92    }
93
94    /**
95     * Create a new {@link OutputConfiguration} instance.
96     *
97     * <p>This constructor takes an argument for desired camera rotation</p>
98     *
99     * @param surface
100     *          A Surface for camera to output to.
101     * @param rotation
102     *          The desired rotation to be applied on camera output. Value must be one of
103     *          ROTATION_[0, 90, 180, 270]. Note that when the rotation is 90 or 270 degree,
104     *          application should make sure corresponding surface size has width and height
105     *          transposed corresponding to the width and height without rotation. For example,
106     *          if application needs camera to capture 1280x720 picture and rotate it by 90 degree,
107     *          application should set rotation to {@code ROTATION_90} and make sure the
108     *          corresponding Surface size is 720x1280. Note that {@link CameraDevice} might
109     *          throw {@code IllegalArgumentException} if device cannot perform such rotation.
110     * @hide
111     */
112    @SystemApi
113    public OutputConfiguration(Surface surface, int rotation) {
114        checkNotNull(surface, "Surface must not be null");
115        checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
116        mSurfaceSetId = SURFACE_SET_ID_INVALID;
117        mSurface = surface;
118        mRotation = rotation;
119        mConfiguredSize = SurfaceUtils.getSurfaceSize(surface);
120        mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface);
121        mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface);
122    }
123
124    /**
125     * Create a new {@link OutputConfiguration} instance with another {@link OutputConfiguration}
126     * instance.
127     *
128     * @param other Another {@link OutputConfiguration} instance to be copied.
129     *
130     * @hide
131     */
132    @SystemApi
133    public OutputConfiguration(OutputConfiguration other) {
134        if (other == null) {
135            throw new IllegalArgumentException("OutputConfiguration shouldn't be null");
136        }
137
138        this.mSurface = other.mSurface;
139        this.mRotation = other.mRotation;
140        this.mSurfaceSetId = other.mSurfaceSetId;
141        this.mConfiguredDataspace = other.mConfiguredDataspace;
142        this.mConfiguredFormat = other.mConfiguredFormat;
143        this.mConfiguredSize = other.mConfiguredSize;
144    }
145
146    /**
147     * Create an OutputConfiguration from Parcel.
148     */
149    private OutputConfiguration(Parcel source) {
150        int rotation = source.readInt();
151        int surfaceSetId = source.readInt();
152        Surface surface = Surface.CREATOR.createFromParcel(source);
153        checkNotNull(surface, "Surface must not be null");
154        checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
155        mSurfaceSetId = surfaceSetId;
156        mSurface = surface;
157        mRotation = rotation;
158        mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface);
159        mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface);
160        mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface);
161    }
162
163    /**
164     * Get the {@link Surface} associated with this {@link OutputConfiguration}.
165     *
166     * @return the {@link Surface} associated with this {@link OutputConfiguration}.
167     */
168    public Surface getSurface() {
169        return mSurface;
170    }
171
172    /**
173     * Get the rotation associated with this {@link OutputConfiguration}.
174     *
175     * @return the rotation associated with this {@link OutputConfiguration}.
176     *         Value will be one of ROTATION_[0, 90, 180, 270]
177     *
178     * @hide
179     */
180    @SystemApi
181    public int getRotation() {
182        return mRotation;
183    }
184
185    /**
186     * Set the surface set ID to this {@link OutputConfiguration}.
187     *
188     * <p>
189     * A surface set ID is used to identify which surface set this output surface belongs to. A
190     * surface set is a group of output surfaces that are not intended to receive camera output
191     * buffer streams simultaneously. The {@link CameraDevice} may be able to share the buffers used
192     * by all the surfaces from the same surface set, therefore may save the overall memory
193     * footprint. The application should only set the same set ID for the streams that are not
194     * simultaneously streaming. A negative ID indicates that this surface doesn't belong to any
195     * surface set. The default value will be {@value #SURFACE_SET_ID_INVALID}.
196     * </p>
197     *
198     * @param setId
199     */
200    public void setSurfaceSetId(int setId) {
201        if (setId < 0) {
202            setId = SURFACE_SET_ID_INVALID;
203        }
204        mSurfaceSetId = setId;
205    }
206
207    /**
208     * Get the surface set Id associated with this {@link OutputConfiguration}.
209     *
210     * @return the surface set Id associated with this {@link OutputConfiguration}.
211     *         Value will be one of ROTATION_[0, 90, 180, 270]
212     */
213    public int getSurfaceSetId() {
214        return mSurfaceSetId;
215    }
216
217    public static final Parcelable.Creator<OutputConfiguration> CREATOR =
218            new Parcelable.Creator<OutputConfiguration>() {
219        @Override
220        public OutputConfiguration createFromParcel(Parcel source) {
221            try {
222                OutputConfiguration outputConfiguration = new OutputConfiguration(source);
223                return outputConfiguration;
224            } catch (Exception e) {
225                Log.e(TAG, "Exception creating OutputConfiguration from parcel", e);
226                return null;
227            }
228        }
229
230        @Override
231        public OutputConfiguration[] newArray(int size) {
232            return new OutputConfiguration[size];
233        }
234    };
235
236    @Override
237    public int describeContents() {
238        return 0;
239    }
240
241    @Override
242    public void writeToParcel(Parcel dest, int flags) {
243        if (dest == null) {
244            throw new IllegalArgumentException("dest must not be null");
245        }
246        dest.writeInt(mRotation);
247        dest.writeInt(mSurfaceSetId);
248        mSurface.writeToParcel(dest, flags);
249    }
250
251    /**
252     * Check if this {@link OutputConfiguration} is equal to another {@link OutputConfiguration}.
253     *
254     * <p>Two output configurations are only equal if and only if the underlying surfaces, surface
255     * properties (width, height, format, dataspace) when the output configurations are created,
256     * and all other configuration parameters are equal. </p>
257     *
258     * @return {@code true} if the objects were equal, {@code false} otherwise
259     */
260    @Override
261    public boolean equals(Object obj) {
262        if (obj == null) {
263            return false;
264        } else if (this == obj) {
265            return true;
266        } else if (obj instanceof OutputConfiguration) {
267            final OutputConfiguration other = (OutputConfiguration) obj;
268            return mSurface == other.mSurface &&
269                   mRotation == other.mRotation &&
270                   mConfiguredSize.equals(other.mConfiguredSize) &&
271                   mConfiguredFormat == other.mConfiguredFormat &&
272                   mConfiguredDataspace == other.mConfiguredDataspace &&
273                   mSurfaceSetId == other.mSurfaceSetId;
274        }
275        return false;
276    }
277
278    /**
279     * {@inheritDoc}
280     */
281    @Override
282    public int hashCode() {
283        return HashCodeHelpers.hashCode(mSurface.hashCode(), mRotation);
284    }
285
286    private static final String TAG = "OutputConfiguration";
287    private final Surface mSurface;
288    private final int mRotation;
289    private int mSurfaceSetId;
290
291    // The size, format, and dataspace of the surface when OutputConfiguration is created.
292    private final Size mConfiguredSize;
293    private final int mConfiguredFormat;
294    private final int mConfiguredDataspace;
295}
296