• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016-2018 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 #include "Camera3SharedOutputStream.h"
18 
19 namespace android {
20 
21 namespace camera3 {
22 
23 const size_t Camera3SharedOutputStream::kMaxOutputs;
24 
Camera3SharedOutputStream(int id,const std::vector<sp<Surface>> & surfaces,uint32_t width,uint32_t height,int format,uint64_t consumerUsage,android_dataspace dataSpace,camera3_stream_rotation_t rotation,nsecs_t timestampOffset,const String8 & physicalCameraId,int setId)25 Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
26         const std::vector<sp<Surface>>& surfaces,
27         uint32_t width, uint32_t height, int format,
28         uint64_t consumerUsage, android_dataspace dataSpace,
29         camera3_stream_rotation_t rotation,
30         nsecs_t timestampOffset, const String8& physicalCameraId,
31         int setId) :
32         Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
33                             format, dataSpace, rotation, physicalCameraId,
34                             consumerUsage, timestampOffset, setId) {
35     size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
36     if (surfaces.size() > consumerCount) {
37         ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
38     }
39     for (size_t i = 0; i < consumerCount; i++) {
40         mSurfaces[i] = surfaces[i];
41     }
42 }
43 
~Camera3SharedOutputStream()44 Camera3SharedOutputStream::~Camera3SharedOutputStream() {
45     disconnectLocked();
46 }
47 
connectStreamSplitterLocked()48 status_t Camera3SharedOutputStream::connectStreamSplitterLocked() {
49     status_t res = OK;
50 
51     mStreamSplitter = new Camera3StreamSplitter();
52 
53     uint64_t usage;
54     getEndpointUsage(&usage);
55 
56     std::unordered_map<size_t, sp<Surface>> initialSurfaces;
57     for (size_t i = 0; i < kMaxOutputs; i++) {
58         if (mSurfaces[i] != nullptr) {
59             initialSurfaces.emplace(i, mSurfaces[i]);
60         }
61     }
62 
63     android::PixelFormat format = isFormatOverridden() ? getOriginalFormat() : getFormat();
64     res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera3_stream::max_buffers,
65             getWidth(), getHeight(), format, &mConsumer);
66     if (res != OK) {
67         ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
68                 __FUNCTION__, strerror(-res), res);
69         return res;
70     }
71 
72     return res;
73 }
74 
notifyBufferReleased(ANativeWindowBuffer * anwBuffer)75 status_t Camera3SharedOutputStream::notifyBufferReleased(ANativeWindowBuffer *anwBuffer) {
76     Mutex::Autolock l(mLock);
77     status_t res = OK;
78     const sp<GraphicBuffer> buffer(static_cast<GraphicBuffer*>(anwBuffer));
79 
80     if (mStreamSplitter != nullptr) {
81         res = mStreamSplitter->notifyBufferReleased(buffer);
82     }
83 
84     return res;
85 }
86 
isConsumerConfigurationDeferred(size_t surface_id) const87 bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const {
88     Mutex::Autolock l(mLock);
89     if (surface_id >= kMaxOutputs) {
90         return true;
91     }
92 
93     return (mSurfaces[surface_id] == nullptr);
94 }
95 
setConsumers(const std::vector<sp<Surface>> & surfaces)96 status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) {
97     Mutex::Autolock l(mLock);
98     if (surfaces.size() == 0) {
99         ALOGE("%s: it's illegal to set zero consumer surfaces!", __FUNCTION__);
100         return INVALID_OPERATION;
101     }
102 
103     status_t ret = OK;
104     for (auto& surface : surfaces) {
105         if (surface == nullptr) {
106             ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
107             return INVALID_OPERATION;
108         }
109 
110         ssize_t id = getNextSurfaceIdLocked();
111         if (id < 0) {
112             ALOGE("%s: No surface ids available!", __func__);
113             return NO_MEMORY;
114         }
115 
116         mSurfaces[id] = surface;
117 
118         // Only call addOutput if the splitter has been connected.
119         if (mStreamSplitter != nullptr) {
120             ret = mStreamSplitter->addOutput(id, surface);
121             if (ret != OK) {
122                 ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret);
123                 return ret;
124 
125             }
126         }
127     }
128     return ret;
129 }
130 
getBufferLocked(camera3_stream_buffer * buffer,const std::vector<size_t> & surface_ids)131 status_t Camera3SharedOutputStream::getBufferLocked(camera3_stream_buffer *buffer,
132         const std::vector<size_t>& surface_ids) {
133     ANativeWindowBuffer* anb;
134     int fenceFd = -1;
135 
136     status_t res;
137     res = getBufferLockedCommon(&anb, &fenceFd);
138     if (res != OK) {
139         return res;
140     }
141 
142     // Attach the buffer to the splitter output queues. This could block if
143     // the output queue doesn't have any empty slot. So unlock during the course
144     // of attachBufferToOutputs.
145     sp<Camera3StreamSplitter> splitter = mStreamSplitter;
146     mLock.unlock();
147     res = splitter->attachBufferToOutputs(anb, surface_ids);
148     mLock.lock();
149     if (res != OK) {
150         ALOGE("%s: Stream %d: Cannot attach stream splitter buffer to outputs: %s (%d)",
151                 __FUNCTION__, mId, strerror(-res), res);
152         // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING,
153         // let prepareNextBuffer handle the error.)
154         if (res == NO_INIT && mState == STATE_CONFIGURED) {
155             mState = STATE_ABANDONED;
156         }
157 
158         return res;
159     }
160 
161     /**
162      * FenceFD now owned by HAL except in case of error,
163      * in which case we reassign it to acquire_fence
164      */
165     handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
166                         /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
167 
168     return OK;
169 }
170 
queueBufferToConsumer(sp<ANativeWindow> & consumer,ANativeWindowBuffer * buffer,int anwReleaseFence)171 status_t Camera3SharedOutputStream::queueBufferToConsumer(sp<ANativeWindow>& consumer,
172             ANativeWindowBuffer* buffer, int anwReleaseFence) {
173     status_t res = consumer->queueBuffer(consumer.get(), buffer, anwReleaseFence);
174 
175     // After queuing buffer to the internal consumer queue, check whether the buffer is
176     // successfully queued to the output queues.
177     if (res == OK) {
178         res = mStreamSplitter->getOnFrameAvailableResult();
179         if (res != OK) {
180             ALOGE("%s: getOnFrameAvailable returns %d", __FUNCTION__, res);
181         }
182     } else {
183         ALOGE("%s: queueBufer failed %d", __FUNCTION__, res);
184     }
185 
186     return res;
187 }
188 
configureQueueLocked()189 status_t Camera3SharedOutputStream::configureQueueLocked() {
190     status_t res;
191 
192     if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
193         return res;
194     }
195 
196     res = connectStreamSplitterLocked();
197     if (res != OK) {
198         ALOGE("Cannot connect to stream splitter: %s(%d)", strerror(-res), res);
199         return res;
200     }
201 
202     res = configureConsumerQueueLocked();
203     if (res != OK) {
204         ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res);
205         return res;
206     }
207 
208     return OK;
209 }
210 
disconnectLocked()211 status_t Camera3SharedOutputStream::disconnectLocked() {
212     status_t res;
213     res = Camera3OutputStream::disconnectLocked();
214 
215     if (mStreamSplitter != nullptr) {
216         mStreamSplitter->disconnect();
217     }
218 
219     return res;
220 }
221 
getEndpointUsage(uint64_t * usage) const222 status_t Camera3SharedOutputStream::getEndpointUsage(uint64_t *usage) const {
223 
224     status_t res = OK;
225     uint64_t u = 0;
226 
227     if (mConsumer == nullptr) {
228         // Called before shared buffer queue is constructed.
229         *usage = getPresetConsumerUsage();
230 
231         for (size_t id = 0; id < kMaxOutputs; id++) {
232             if (mSurfaces[id] != nullptr) {
233                 res = getEndpointUsageForSurface(&u, mSurfaces[id]);
234                 *usage |= u;
235             }
236         }
237     } else {
238         // Called after shared buffer queue is constructed.
239         res = getEndpointUsageForSurface(&u, mConsumer);
240         *usage |= u;
241     }
242 
243     return res;
244 }
245 
getNextSurfaceIdLocked()246 ssize_t Camera3SharedOutputStream::getNextSurfaceIdLocked() {
247     ssize_t id = -1;
248     for (size_t i = 0; i < kMaxOutputs; i++) {
249         if (mSurfaces[i] == nullptr) {
250             id = i;
251             break;
252         }
253     }
254 
255     return id;
256 }
257 
getSurfaceId(const sp<Surface> & surface)258 ssize_t Camera3SharedOutputStream::getSurfaceId(const sp<Surface> &surface) {
259     Mutex::Autolock l(mLock);
260     ssize_t id = -1;
261     for (size_t i = 0; i < kMaxOutputs; i++) {
262         if (mSurfaces[i] == surface) {
263             id = i;
264             break;
265         }
266     }
267 
268     return id;
269 }
270 
revertPartialUpdateLocked(const KeyedVector<sp<Surface>,size_t> & removedSurfaces,const KeyedVector<sp<Surface>,size_t> & attachedSurfaces)271 status_t Camera3SharedOutputStream::revertPartialUpdateLocked(
272         const KeyedVector<sp<Surface>, size_t> &removedSurfaces,
273         const KeyedVector<sp<Surface>, size_t> &attachedSurfaces) {
274     status_t ret = OK;
275 
276     for (size_t i = 0; i < attachedSurfaces.size(); i++) {
277         size_t index = attachedSurfaces.valueAt(i);
278         if (mStreamSplitter != nullptr) {
279             ret = mStreamSplitter->removeOutput(index);
280             if (ret != OK) {
281                 return UNKNOWN_ERROR;
282             }
283         }
284         mSurfaces[index] = nullptr;
285     }
286 
287     for (size_t i = 0; i < removedSurfaces.size(); i++) {
288         size_t index = removedSurfaces.valueAt(i);
289         if (mStreamSplitter != nullptr) {
290             ret = mStreamSplitter->addOutput(index, removedSurfaces.keyAt(i));
291             if (ret != OK) {
292                 return UNKNOWN_ERROR;
293             }
294         }
295         mSurfaces[index] = removedSurfaces.keyAt(i);
296     }
297 
298     return ret;
299 }
300 
updateStream(const std::vector<sp<Surface>> & outputSurfaces,const std::vector<OutputStreamInfo> & outputInfo,const std::vector<size_t> & removedSurfaceIds,KeyedVector<sp<Surface>,size_t> * outputMap)301 status_t Camera3SharedOutputStream::updateStream(const std::vector<sp<Surface>> &outputSurfaces,
302         const std::vector<OutputStreamInfo> &outputInfo,
303         const std::vector<size_t> &removedSurfaceIds,
304         KeyedVector<sp<Surface>, size_t> *outputMap) {
305     status_t ret = OK;
306     Mutex::Autolock l(mLock);
307 
308     if ((outputMap == nullptr) || (outputInfo.size() != outputSurfaces.size()) ||
309             (outputSurfaces.size() > kMaxOutputs)) {
310         return BAD_VALUE;
311     }
312 
313     uint64_t usage;
314     getEndpointUsage(&usage);
315     KeyedVector<sp<Surface>, size_t> removedSurfaces;
316     //Check whether the new surfaces are compatible.
317     for (const auto &infoIt : outputInfo) {
318         bool imgReaderUsage = (infoIt.consumerUsage & GRALLOC_USAGE_SW_READ_OFTEN) ? true : false;
319         bool sizeMismatch = ((static_cast<uint32_t>(infoIt.width) != getWidth()) ||
320                                 (static_cast<uint32_t> (infoIt.height) != getHeight())) ?
321                                 true : false;
322         if ((imgReaderUsage && sizeMismatch) ||
323                 (infoIt.format != getOriginalFormat() && infoIt.format != getFormat()) ||
324                 (infoIt.dataSpace != getDataSpace() &&
325                  infoIt.dataSpace != getOriginalDataSpace())) {
326             ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x "
327                     " don't match source stream format: 0x%x  dataSpace: 0x%x", __FUNCTION__,
328                     infoIt.format, infoIt.dataSpace, getFormat(), getDataSpace());
329             return BAD_VALUE;
330         }
331     }
332 
333     //First remove all absent outputs
334     for (const auto &it : removedSurfaceIds) {
335         if (mStreamSplitter != nullptr) {
336             ret = mStreamSplitter->removeOutput(it);
337             if (ret != OK) {
338                 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
339                 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
340                 if (res != OK) {
341                     return res;
342                 }
343                 return ret;
344 
345             }
346         }
347         mSurfaces[it] = nullptr;
348         removedSurfaces.add(mSurfaces[it], it);
349     }
350 
351     //Next add the new outputs
352     for (const auto &it : outputSurfaces) {
353         ssize_t surfaceId = getNextSurfaceIdLocked();
354         if (surfaceId < 0) {
355             ALOGE("%s: No more available output slots!", __FUNCTION__);
356             status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
357             if (res != OK) {
358                 return res;
359             }
360             return NO_MEMORY;
361         }
362         if (mStreamSplitter != nullptr) {
363             ret = mStreamSplitter->addOutput(surfaceId, it);
364             if (ret != OK) {
365                 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
366                 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
367                 if (res != OK) {
368                     return res;
369                 }
370                 return ret;
371             }
372         }
373         mSurfaces[surfaceId] = it;
374         outputMap->add(it, surfaceId);
375     }
376 
377     return ret;
378 }
379 
380 } // namespace camera3
381 
382 } // namespace android
383