OutputConfiguration.java revision 828adbba24c430b09c48092ce05730a54e50756a
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.hardware.camera2.CameraDevice;
21import android.hardware.camera2.utils.HashCodeHelpers;
22import android.hardware.camera2.utils.SurfaceUtils;
23import android.util.Log;
24import android.util.Size;
25import android.view.Surface;
26import android.os.Parcel;
27import android.os.Parcelable;
28
29import static com.android.internal.util.Preconditions.*;
30
31/**
32 * A class for describing camera output, which contains a {@link Surface} and its specific
33 * configuration for creating capture session.
34 *
35 * @see CameraDevice#createCaptureSession
36 *
37 * @hide
38 */
39public final class OutputConfiguration implements Parcelable {
40
41    /**
42     * Rotation constant: 0 degree rotation (no rotation)
43     */
44    public static final int ROTATION_0 = 0;
45
46    /**
47     * Rotation constant: 90 degree counterclockwise rotation.
48     */
49    public static final int ROTATION_90 = 1;
50
51    /**
52     * Rotation constant: 180 degree counterclockwise rotation.
53     */
54    public static final int ROTATION_180 = 2;
55
56    /**
57     * Rotation constant: 270 degree counterclockwise rotation.
58     */
59    public static final int ROTATION_270 = 3;
60
61    /**
62     * Create a new immutable SurfaceConfiguration instance.
63     *
64     * @param surface
65     *          A Surface for camera to output to.
66     *
67     * <p>This constructor creates a default configuration</p>
68     *
69     */
70    public OutputConfiguration(Surface surface) {
71        this(surface, ROTATION_0);
72    }
73
74    /**
75     * Create a new immutable SurfaceConfiguration instance.
76     *
77     * <p>This constructor takes an argument for desired camera rotation</p>
78     *
79     * @param surface
80     *          A Surface for camera to output to.
81     * @param rotation
82     *          The desired rotation to be applied on camera output. Value must be one of
83     *          ROTATION_[0, 90, 180, 270]. Note that when the rotation is 90 or 270 degree,
84     *          application should make sure corresponding surface size has width and height
85     *          transposed corresponding to the width and height without rotation. For example,
86     *          if application needs camera to capture 1280x720 picture and rotate it by 90 degree,
87     *          application should set rotation to {@code ROTATION_90} and make sure the
88     *          corresponding Surface size is 720x1280. Note that {@link CameraDevice} might
89     *          throw {@code IllegalArgumentException} if device cannot perform such rotation.
90     *
91     */
92    public OutputConfiguration(Surface surface, int rotation) {
93        checkNotNull(surface, "Surface must not be null");
94        checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
95        mSurface = surface;
96        mRotation = rotation;
97        mConfiguredSize = SurfaceUtils.getSurfaceSize(surface);
98        mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface);
99        mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface);
100    }
101
102    /**
103     * Create an OutputConfiguration from Parcel.
104     */
105    private OutputConfiguration(Parcel source) {
106        int rotation = source.readInt();
107        Surface surface = Surface.CREATOR.createFromParcel(source);
108        checkNotNull(surface, "Surface must not be null");
109        checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
110        mSurface = surface;
111        mRotation = rotation;
112        mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface);
113        mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface);
114        mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface);
115    }
116
117    /**
118     * Get the {@link Surface} associated with this {@link OutputConfiguration}.
119     *
120     * @return the {@link Surface} associated with this {@link OutputConfiguration}.
121     */
122    public Surface getSurface() {
123        return mSurface;
124    }
125
126    /**
127     * Get the rotation associated with this {@link OutputConfiguration}.
128     *
129     * @return the rotation associated with this {@link OutputConfiguration}.
130     *         Value will be one of ROTATION_[0, 90, 180, 270]
131     */
132    public int getRotation() {
133        return mRotation;
134    }
135
136    public static final Parcelable.Creator<OutputConfiguration> CREATOR =
137            new Parcelable.Creator<OutputConfiguration>() {
138        @Override
139        public OutputConfiguration createFromParcel(Parcel source) {
140            try {
141                OutputConfiguration outputConfiguration = new OutputConfiguration(source);
142                return outputConfiguration;
143            } catch (Exception e) {
144                Log.e(TAG, "Exception creating OutputConfiguration from parcel", e);
145                return null;
146            }
147        }
148
149        @Override
150        public OutputConfiguration[] newArray(int size) {
151            return new OutputConfiguration[size];
152        }
153    };
154
155    @Override
156    public int describeContents() {
157        return 0;
158    }
159
160    @Override
161    public void writeToParcel(Parcel dest, int flags) {
162        if (dest == null) {
163            throw new IllegalArgumentException("dest must not be null");
164        }
165        dest.writeInt(mRotation);
166        mSurface.writeToParcel(dest, flags);
167    }
168
169    /**
170     * Check if this {@link OutputConfiguration} is equal to another {@link OutputConfiguration}.
171     *
172     * <p>Two output configurations are only equal if and only if the underlying surfaces, surface
173     * properties (width, height, format, dataspace) when the output configurations are created,
174     * and all other configuration parameters are equal. </p>
175     *
176     * @return {@code true} if the objects were equal, {@code false} otherwise
177     */
178    @Override
179    public boolean equals(Object obj) {
180        if (obj == null) {
181            return false;
182        } else if (this == obj) {
183            return true;
184        } else if (obj instanceof OutputConfiguration) {
185            final OutputConfiguration other = (OutputConfiguration) obj;
186            return mSurface == other.mSurface &&
187                   mRotation == other.mRotation &&
188                   mConfiguredSize.equals(other.mConfiguredSize) &&
189                   mConfiguredFormat == other.mConfiguredFormat &&
190                   mConfiguredDataspace == other.mConfiguredDataspace;
191        }
192        return false;
193    }
194
195    /**
196     * {@inheritDoc}
197     */
198    @Override
199    public int hashCode() {
200        return HashCodeHelpers.hashCode(mSurface.hashCode(), mRotation);
201    }
202
203    private static final String TAG = "OutputConfiguration";
204    private final Surface mSurface;
205    private final int mRotation;
206
207    // The size, format, and dataspace of the surface when OutputConfiguration is created.
208    private final Size mConfiguredSize;
209    private final int mConfiguredFormat;
210    private final int mConfiguredDataspace;
211}
212