OutputConfiguration.cpp revision 0129d52df9794d6fdf06be304722b5cb51a2eab5
1/*
2**
3** Copyright 2015, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "OutputConfiguration"
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22
23#include <camera/camera2/OutputConfiguration.h>
24#include <gui/Surface.h>
25#include <binder/Parcel.h>
26
27namespace android {
28
29
30const int OutputConfiguration::INVALID_ROTATION = -1;
31const int OutputConfiguration::INVALID_SET_ID = -1;
32
33const std::vector<sp<IGraphicBufferProducer>>&
34        OutputConfiguration::getGraphicBufferProducers() const {
35    return mGbps;
36}
37
38int OutputConfiguration::getRotation() const {
39    return mRotation;
40}
41
42int OutputConfiguration::getSurfaceSetID() const {
43    return mSurfaceSetID;
44}
45
46int OutputConfiguration::getSurfaceType() const {
47    return mSurfaceType;
48}
49
50int OutputConfiguration::getWidth() const {
51    return mWidth;
52}
53
54int OutputConfiguration::getHeight() const {
55    return mHeight;
56}
57
58OutputConfiguration::OutputConfiguration() :
59        mRotation(INVALID_ROTATION),
60        mSurfaceSetID(INVALID_SET_ID),
61        mSurfaceType(SURFACE_TYPE_UNKNOWN),
62        mWidth(0),
63        mHeight(0) {
64}
65
66OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
67        mRotation(INVALID_ROTATION),
68        mSurfaceSetID(INVALID_SET_ID) {
69    readFromParcel(&parcel);
70}
71
72status_t OutputConfiguration::readFromParcel(const android::Parcel* parcel) {
73    status_t err = OK;
74    int rotation = 0;
75
76    if (parcel == nullptr) return BAD_VALUE;
77
78    if ((err = parcel->readInt32(&rotation)) != OK) {
79        ALOGE("%s: Failed to read rotation from parcel", __FUNCTION__);
80        return err;
81    }
82
83    int setID = INVALID_SET_ID;
84    if ((err = parcel->readInt32(&setID)) != OK) {
85        ALOGE("%s: Failed to read surface set ID from parcel", __FUNCTION__);
86        return err;
87    }
88
89    int surfaceType = SURFACE_TYPE_UNKNOWN;
90    if ((err = parcel->readInt32(&surfaceType)) != OK) {
91        ALOGE("%s: Failed to read surface type from parcel", __FUNCTION__);
92        return err;
93    }
94
95    int width = 0;
96    if ((err = parcel->readInt32(&width)) != OK) {
97        ALOGE("%s: Failed to read surface width from parcel", __FUNCTION__);
98        return err;
99    }
100
101    int height = 0;
102    if ((err = parcel->readInt32(&height)) != OK) {
103        ALOGE("%s: Failed to read surface height from parcel", __FUNCTION__);
104        return err;
105    }
106
107    // numSurfaces is the total number of surfaces for this OutputConfiguration,
108    // regardless the surface is deferred or not.
109    int numSurfaces = 0;
110    if ((err = parcel->readInt32(&numSurfaces)) != OK) {
111        ALOGE("%s: Failed to read maxSurfaces from parcel", __FUNCTION__);
112        return err;
113    }
114    if (numSurfaces < 1) {
115        ALOGE("%s: there has to be at least 1 surface per"
116              " outputConfiguration", __FUNCTION__);
117        return BAD_VALUE;
118    }
119
120    // Read all surfaces from parcel. If a surface is deferred, readFromPacel
121    // returns error, and a null surface is put into the mGbps. We assume all
122    // deferred surfaces are after non-deferred surfaces in the parcel.
123    // TODO: Need better way to detect deferred surface than using error
124    // return from readFromParcel.
125    std::vector<sp<IGraphicBufferProducer>> gbps;
126    for (int i = 0; i < numSurfaces; i++) {
127        view::Surface surfaceShim;
128        if ((err = surfaceShim.readFromParcel(parcel)) != OK) {
129            // Read surface failure for deferred surface configuration is expected.
130            if ((surfaceType == SURFACE_TYPE_SURFACE_VIEW ||
131                    surfaceType == SURFACE_TYPE_SURFACE_TEXTURE)) {
132                ALOGV("%s: Get null surface from a deferred surface configuration (%dx%d)",
133                        __FUNCTION__, width, height);
134                err = OK;
135            } else {
136                ALOGE("%s: Failed to read surface from parcel", __FUNCTION__);
137                return err;
138            }
139        }
140        gbps.push_back(surfaceShim.graphicBufferProducer);
141        ALOGV("%s: OutputConfiguration: gbps[%d] : %p, name %s", __FUNCTION__,
142                i, gbps[i].get(), String8(surfaceShim.name).string());
143    }
144
145    mRotation = rotation;
146    mSurfaceSetID = setID;
147    mSurfaceType = surfaceType;
148    mWidth = width;
149    mHeight = height;
150    mGbps = std::move(gbps);
151
152    ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d",
153            __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType);
154
155    return err;
156}
157
158OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
159        int surfaceSetID) {
160    mGbps.push_back(gbp);
161    mRotation = rotation;
162    mSurfaceSetID = surfaceSetID;
163}
164
165status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
166
167    if (parcel == nullptr) return BAD_VALUE;
168    status_t err = OK;
169
170    err = parcel->writeInt32(mRotation);
171    if (err != OK) return err;
172
173    err = parcel->writeInt32(mSurfaceSetID);
174    if (err != OK) return err;
175
176    err = parcel->writeInt32(mSurfaceType);
177    if (err != OK) return err;
178
179    err = parcel->writeInt32(mWidth);
180    if (err != OK) return err;
181
182    err = parcel->writeInt32(mHeight);
183    if (err != OK) return err;
184
185    int numSurfaces = mGbps.size();
186    err = parcel->writeInt32(numSurfaces);
187    if (err != OK) return err;
188
189    for (int i = 0; i < numSurfaces; i++) {
190        view::Surface surfaceShim;
191        surfaceShim.name = String16("unknown_name"); // name of surface
192        surfaceShim.graphicBufferProducer = mGbps[i];
193
194        err = surfaceShim.writeToParcel(parcel);
195        if (err != OK) return err;
196    }
197
198    return OK;
199}
200
201bool OutputConfiguration::gbpsEqual(const OutputConfiguration& other) const {
202    const std::vector<sp<IGraphicBufferProducer> >& otherGbps =
203            other.getGraphicBufferProducers();
204
205    if (mGbps.size() != otherGbps.size()) {
206        return false;
207    }
208
209    for (size_t i = 0; i < mGbps.size(); i++) {
210        if (mGbps[i] != otherGbps[i]) {
211            return false;
212        }
213    }
214
215    return true;
216}
217
218bool OutputConfiguration::gbpsLessThan(const OutputConfiguration& other) const {
219    const std::vector<sp<IGraphicBufferProducer> >& otherGbps =
220            other.getGraphicBufferProducers();
221
222    if (mGbps.size() !=  otherGbps.size()) {
223        return mGbps.size() < otherGbps.size();
224    }
225
226    for (size_t i = 0; i < mGbps.size(); i++) {
227        if (mGbps[i] != otherGbps[i]) {
228            return mGbps[i] < otherGbps[i];
229        }
230    }
231
232    return false;
233}
234}; // namespace android
235