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