blob: 187bd932e0b81b0960b0659fed5071ca52bbb373 [file] [log] [blame]
Shuzhen Wang0129d522016-10-30 22:43:41 -07001/*
Shuzhen Wangc28189a2017-11-27 23:05:10 -08002 * Copyright (C) 2016-2018 The Android Open Source Project
Shuzhen Wang0129d522016-10-30 22:43:41 -07003 *
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
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -070017#define LOG_TAG "Camera3-SharedOuStrm"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
Jim Shargoc50928e2024-07-03 05:00:43 +000021#include "Flags.h"
22
Shuzhen Wang0129d522016-10-30 22:43:41 -070023#include "Camera3SharedOutputStream.h"
24
25namespace android {
26
27namespace camera3 {
28
Emilian Peev40ead602017-09-26 15:46:36 +010029const size_t Camera3SharedOutputStream::kMaxOutputs;
30
Shuzhen Wang0129d522016-10-30 22:43:41 -070031Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
32 const std::vector<sp<Surface>>& surfaces,
Shuzhen Wang0129d522016-10-30 22:43:41 -070033 uint32_t width, uint32_t height, int format,
Emilian Peev050f5dc2017-05-18 14:43:56 +010034 uint64_t consumerUsage, android_dataspace dataSpace,
Emilian Peevf4816702020-04-03 15:44:51 -070035 camera_stream_rotation_t rotation,
Austin Borger1c1bee02023-06-01 16:51:35 -070036 nsecs_t timestampOffset, const std::string& physicalCameraId,
Jayant Chowdharyc67af1b2022-04-07 18:05:04 +000037 const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
Emilian Peevc81a7592022-02-14 17:38:18 -080038 int setId, bool useHalBufManager, int64_t dynamicProfile,
Shuzhen Wang8ed1e872022-03-08 16:34:33 -080039 int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
Shuzhen Wangbce53db2022-12-03 00:38:20 +000040 int mirrorMode, int32_t colorSpace, bool useReadoutTimestamp) :
Emilian Peevf4816702020-04-03 15:44:51 -070041 Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
Jayant Chowdhary13f9b2f2020-12-02 22:46:15 -080042 format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
Jayant Chowdharyc67af1b2022-04-07 18:05:04 +000043 transport, consumerUsage, timestampOffset, setId,
44 /*isMultiResolution*/false, dynamicProfile, streamUseCase,
Shuzhen Wangbce53db2022-12-03 00:38:20 +000045 deviceTimeBaseIsRealtime, timestampBase, mirrorMode, colorSpace,
46 useReadoutTimestamp),
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -070047 mUseHalBufManager(useHalBufManager) {
Emilian Peev40ead602017-09-26 15:46:36 +010048 size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
49 if (surfaces.size() > consumerCount) {
50 ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
51 }
52 for (size_t i = 0; i < consumerCount; i++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -070053 mSurfaceUniqueIds[i] = std::make_pair(surfaces[i], mNextUniqueSurfaceId++);
Emilian Peev40ead602017-09-26 15:46:36 +010054 }
Shuzhen Wang0129d522016-10-30 22:43:41 -070055}
56
57Camera3SharedOutputStream::~Camera3SharedOutputStream() {
58 disconnectLocked();
59}
60
61status_t Camera3SharedOutputStream::connectStreamSplitterLocked() {
62 status_t res = OK;
63
Jim Shargoc50928e2024-07-03 05:00:43 +000064#if USE_NEW_STREAM_SPLITTER
65 mStreamSplitter = sp<Camera3StreamSplitter>::make(mUseHalBufManager);
66#else
67 mStreamSplitter = sp<DeprecatedCamera3StreamSplitter>::make(mUseHalBufManager);
68#endif // USE_NEW_STREAM_SPLITTER
Shuzhen Wang0129d522016-10-30 22:43:41 -070069
Shuzhen Wang92653952019-05-07 15:11:43 -070070 uint64_t usage = 0;
Shuzhen Wang0129d522016-10-30 22:43:41 -070071 getEndpointUsage(&usage);
72
Emilian Peev40ead602017-09-26 15:46:36 +010073 std::unordered_map<size_t, sp<Surface>> initialSurfaces;
74 for (size_t i = 0; i < kMaxOutputs; i++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -070075 if (mSurfaceUniqueIds[i].first != nullptr) {
76 initialSurfaces.emplace(i, mSurfaceUniqueIds[i].first);
Emilian Peev40ead602017-09-26 15:46:36 +010077 }
78 }
79
Emilian Peevf4816702020-04-03 15:44:51 -070080 res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera_stream::max_buffers,
Emilian Peev2295df72021-11-12 18:14:10 -080081 getWidth(), getHeight(), getFormat(), &mConsumer, camera_stream::dynamic_range_profile);
Shuzhen Wang0129d522016-10-30 22:43:41 -070082 if (res != OK) {
83 ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
84 __FUNCTION__, strerror(-res), res);
85 return res;
86 }
87
88 return res;
89}
90
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -070091status_t Camera3SharedOutputStream::attachBufferToSplitterLocked(
92 ANativeWindowBuffer* anb,
93 const std::vector<size_t>& surface_ids) {
94 status_t res = OK;
95
96 // Attach the buffer to the splitter output queues. This could block if
97 // the output queue doesn't have any empty slot. So unlock during the course
98 // of attachBufferToOutputs.
Jim Shargoc50928e2024-07-03 05:00:43 +000099#if USE_NEW_STREAM_SPLITTER
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700100 sp<Camera3StreamSplitter> splitter = mStreamSplitter;
Jim Shargoc50928e2024-07-03 05:00:43 +0000101#else
102 sp<DeprecatedCamera3StreamSplitter> splitter = mStreamSplitter;
103#endif // USE_NEW_STREAM_SPLITTER
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700104 mLock.unlock();
105 res = splitter->attachBufferToOutputs(anb, surface_ids);
106 mLock.lock();
107 if (res != OK) {
108 ALOGE("%s: Stream %d: Cannot attach stream splitter buffer to outputs: %s (%d)",
109 __FUNCTION__, mId, strerror(-res), res);
110 // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING,
111 // let prepareNextBuffer handle the error.)
112 if (res == NO_INIT && mState == STATE_CONFIGURED) {
113 mState = STATE_ABANDONED;
114 }
115 }
116 return res;
117}
118
Jayant Chowdhary9d3a6492023-11-22 07:23:59 +0000119void Camera3SharedOutputStream::setHalBufferManager(bool enabled) {
120 Mutex::Autolock l(mLock);
121 mUseHalBufManager = enabled;
122 if (mStreamSplitter != nullptr) {
123 mStreamSplitter->setHalBufferManager(enabled);
124 }
125}
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700126
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800127status_t Camera3SharedOutputStream::notifyBufferReleased(ANativeWindowBuffer *anwBuffer) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700128 Mutex::Autolock l(mLock);
129 status_t res = OK;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800130 const sp<GraphicBuffer> buffer(static_cast<GraphicBuffer*>(anwBuffer));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700131
132 if (mStreamSplitter != nullptr) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800133 res = mStreamSplitter->notifyBufferReleased(buffer);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700134 }
135
136 return res;
137}
138
139bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const {
140 Mutex::Autolock l(mLock);
Emilian Peev40ead602017-09-26 15:46:36 +0100141 if (surface_id >= kMaxOutputs) {
142 return true;
143 }
144
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700145 return (mSurfaceUniqueIds[surface_id].first == nullptr);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700146}
147
Shuzhen Wang758c2152017-01-10 18:26:18 -0800148status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800149 Mutex::Autolock l(mLock);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800150 if (surfaces.size() == 0) {
151 ALOGE("%s: it's illegal to set zero consumer surfaces!", __FUNCTION__);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700152 return INVALID_OPERATION;
153 }
154
Shuzhen Wang758c2152017-01-10 18:26:18 -0800155 status_t ret = OK;
156 for (auto& surface : surfaces) {
157 if (surface == nullptr) {
158 ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
159 return INVALID_OPERATION;
160 }
161
Emilian Peev40ead602017-09-26 15:46:36 +0100162 ssize_t id = getNextSurfaceIdLocked();
163 if (id < 0) {
164 ALOGE("%s: No surface ids available!", __func__);
165 return NO_MEMORY;
166 }
167
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700168 mSurfaceUniqueIds[id] = std::make_pair(surface, mNextUniqueSurfaceId++);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800169
170 // Only call addOutput if the splitter has been connected.
171 if (mStreamSplitter != nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100172 ret = mStreamSplitter->addOutput(id, surface);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800173 if (ret != OK) {
174 ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret);
175 return ret;
176
177 }
178 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700179 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800180 return ret;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700181}
182
Emilian Peevf4816702020-04-03 15:44:51 -0700183status_t Camera3SharedOutputStream::getBufferLocked(camera_stream_buffer *buffer,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700184 const std::vector<size_t>& surfaceIds) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800185 ANativeWindowBuffer* anb;
186 int fenceFd = -1;
187
188 status_t res;
189 res = getBufferLockedCommon(&anb, &fenceFd);
190 if (res != OK) {
191 return res;
192 }
193
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700194 if (!mUseHalBufManager) {
195 res = attachBufferToSplitterLocked(anb, surfaceIds);
196 if (res != OK) {
197 return res;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800198 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800199 }
200
201 /**
202 * FenceFD now owned by HAL except in case of error,
203 * in which case we reassign it to acquire_fence
204 */
205 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
Emilian Peevf4816702020-04-03 15:44:51 -0700206 /*releaseFence*/-1, CAMERA_BUFFER_STATUS_OK, /*output*/true);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800207
208 return OK;
209}
210
211status_t Camera3SharedOutputStream::queueBufferToConsumer(sp<ANativeWindow>& consumer,
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700212 ANativeWindowBuffer* buffer, int anwReleaseFence,
213 const std::vector<size_t>& uniqueSurfaceIds) {
214 status_t res = OK;
215 if (mUseHalBufManager) {
216 if (uniqueSurfaceIds.size() == 0) {
217 ALOGE("%s: uniqueSurfaceIds must not be empty!", __FUNCTION__);
218 return BAD_VALUE;
219 }
220 Mutex::Autolock l(mLock);
221 std::vector<size_t> surfaceIds;
222 for (const auto& uniqueId : uniqueSurfaceIds) {
223 bool uniqueIdFound = false;
224 for (size_t i = 0; i < kMaxOutputs; i++) {
225 if (mSurfaceUniqueIds[i].second == uniqueId) {
226 surfaceIds.push_back(i);
227 uniqueIdFound = true;
228 break;
229 }
230 }
231 if (!uniqueIdFound) {
232 ALOGV("%s: unknown unique surface ID %zu for stream %d: "
233 "output might have been removed.",
234 __FUNCTION__, uniqueId, mId);
235 }
236 }
237 res = attachBufferToSplitterLocked(buffer, surfaceIds);
238 if (res != OK) {
239 return res;
240 }
241 }
242
243 res = consumer->queueBuffer(consumer.get(), buffer, anwReleaseFence);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800244
245 // After queuing buffer to the internal consumer queue, check whether the buffer is
246 // successfully queued to the output queues.
247 if (res == OK) {
248 res = mStreamSplitter->getOnFrameAvailableResult();
249 if (res != OK) {
250 ALOGE("%s: getOnFrameAvailable returns %d", __FUNCTION__, res);
251 }
252 } else {
253 ALOGE("%s: queueBufer failed %d", __FUNCTION__, res);
254 }
255
256 return res;
257}
258
Shuzhen Wang0129d522016-10-30 22:43:41 -0700259status_t Camera3SharedOutputStream::configureQueueLocked() {
260 status_t res;
261
262 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
263 return res;
264 }
265
266 res = connectStreamSplitterLocked();
267 if (res != OK) {
268 ALOGE("Cannot connect to stream splitter: %s(%d)", strerror(-res), res);
269 return res;
270 }
271
Shuzhen Wangba92d772022-04-11 11:47:24 -0700272 res = configureConsumerQueueLocked(false/*allowPreviewRespace*/);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700273 if (res != OK) {
274 ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res);
275 return res;
276 }
277
278 return OK;
279}
280
281status_t Camera3SharedOutputStream::disconnectLocked() {
282 status_t res;
283 res = Camera3OutputStream::disconnectLocked();
284
285 if (mStreamSplitter != nullptr) {
286 mStreamSplitter->disconnect();
287 }
288
289 return res;
290}
291
Emilian Peev3b93acb2024-03-11 21:09:48 +0000292status_t Camera3SharedOutputStream::getEndpointUsage(uint64_t *usage) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700293
Shuzhen Wang758c2152017-01-10 18:26:18 -0800294 status_t res = OK;
Emilian Peev050f5dc2017-05-18 14:43:56 +0100295 uint64_t u = 0;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700296
297 if (mConsumer == nullptr) {
298 // Called before shared buffer queue is constructed.
299 *usage = getPresetConsumerUsage();
300
Emilian Peev40ead602017-09-26 15:46:36 +0100301 for (size_t id = 0; id < kMaxOutputs; id++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700302 if (mSurfaceUniqueIds[id].first != nullptr) {
303 res = getEndpointUsageForSurface(&u, mSurfaceUniqueIds[id].first);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700304 *usage |= u;
305 }
306 }
307 } else {
308 // Called after shared buffer queue is constructed.
309 res = getEndpointUsageForSurface(&u, mConsumer);
310 *usage |= u;
311 }
312
313 return res;
314}
315
Emilian Peev40ead602017-09-26 15:46:36 +0100316ssize_t Camera3SharedOutputStream::getNextSurfaceIdLocked() {
317 ssize_t id = -1;
318 for (size_t i = 0; i < kMaxOutputs; i++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700319 if (mSurfaceUniqueIds[i].first == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100320 id = i;
321 break;
322 }
323 }
324
325 return id;
326}
327
328ssize_t Camera3SharedOutputStream::getSurfaceId(const sp<Surface> &surface) {
329 Mutex::Autolock l(mLock);
330 ssize_t id = -1;
331 for (size_t i = 0; i < kMaxOutputs; i++) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700332 if (mSurfaceUniqueIds[i].first == surface) {
Emilian Peev40ead602017-09-26 15:46:36 +0100333 id = i;
334 break;
335 }
336 }
337
338 return id;
339}
340
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700341status_t Camera3SharedOutputStream::getUniqueSurfaceIds(
342 const std::vector<size_t>& surfaceIds,
343 /*out*/std::vector<size_t>* outUniqueIds) {
344 Mutex::Autolock l(mLock);
345 if (outUniqueIds == nullptr || surfaceIds.size() > kMaxOutputs) {
346 return BAD_VALUE;
347 }
348
349 outUniqueIds->clear();
350 outUniqueIds->reserve(surfaceIds.size());
351
352 for (const auto& surfaceId : surfaceIds) {
353 if (surfaceId >= kMaxOutputs) {
354 return BAD_VALUE;
355 }
356 outUniqueIds->push_back(mSurfaceUniqueIds[surfaceId].second);
357 }
358 return OK;
359}
360
Emilian Peev40ead602017-09-26 15:46:36 +0100361status_t Camera3SharedOutputStream::revertPartialUpdateLocked(
362 const KeyedVector<sp<Surface>, size_t> &removedSurfaces,
363 const KeyedVector<sp<Surface>, size_t> &attachedSurfaces) {
364 status_t ret = OK;
365
366 for (size_t i = 0; i < attachedSurfaces.size(); i++) {
367 size_t index = attachedSurfaces.valueAt(i);
368 if (mStreamSplitter != nullptr) {
369 ret = mStreamSplitter->removeOutput(index);
370 if (ret != OK) {
371 return UNKNOWN_ERROR;
372 }
373 }
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700374 mSurfaceUniqueIds[index] = std::make_pair(nullptr, mNextUniqueSurfaceId++);
Emilian Peev40ead602017-09-26 15:46:36 +0100375 }
376
377 for (size_t i = 0; i < removedSurfaces.size(); i++) {
378 size_t index = removedSurfaces.valueAt(i);
379 if (mStreamSplitter != nullptr) {
380 ret = mStreamSplitter->addOutput(index, removedSurfaces.keyAt(i));
381 if (ret != OK) {
382 return UNKNOWN_ERROR;
383 }
384 }
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700385 mSurfaceUniqueIds[index] = std::make_pair(
386 removedSurfaces.keyAt(i), mNextUniqueSurfaceId++);
Emilian Peev40ead602017-09-26 15:46:36 +0100387 }
388
389 return ret;
390}
391
392status_t Camera3SharedOutputStream::updateStream(const std::vector<sp<Surface>> &outputSurfaces,
393 const std::vector<OutputStreamInfo> &outputInfo,
394 const std::vector<size_t> &removedSurfaceIds,
395 KeyedVector<sp<Surface>, size_t> *outputMap) {
396 status_t ret = OK;
397 Mutex::Autolock l(mLock);
398
399 if ((outputMap == nullptr) || (outputInfo.size() != outputSurfaces.size()) ||
400 (outputSurfaces.size() > kMaxOutputs)) {
401 return BAD_VALUE;
402 }
403
404 uint64_t usage;
405 getEndpointUsage(&usage);
406 KeyedVector<sp<Surface>, size_t> removedSurfaces;
407 //Check whether the new surfaces are compatible.
408 for (const auto &infoIt : outputInfo) {
409 bool imgReaderUsage = (infoIt.consumerUsage & GRALLOC_USAGE_SW_READ_OFTEN) ? true : false;
410 bool sizeMismatch = ((static_cast<uint32_t>(infoIt.width) != getWidth()) ||
411 (static_cast<uint32_t> (infoIt.height) != getHeight())) ?
412 true : false;
Emilian Peev2295df72021-11-12 18:14:10 -0800413 bool dynamicRangeMismatch = dynamic_range_profile != infoIt.dynamicRangeProfile;
414 if ((imgReaderUsage && sizeMismatch) || dynamicRangeMismatch ||
Emilian Peev40ead602017-09-26 15:46:36 +0100415 (infoIt.format != getOriginalFormat() && infoIt.format != getFormat()) ||
416 (infoIt.dataSpace != getDataSpace() &&
417 infoIt.dataSpace != getOriginalDataSpace())) {
Emilian Peevc81a7592022-02-14 17:38:18 -0800418 ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x dynamic range 0x%"
419 PRIx64 " don't match source stream format: 0x%x dataSpace: 0x%x dynamic"
420 " range 0x%" PRIx64 , __FUNCTION__, infoIt.format, infoIt.dataSpace,
421 infoIt.dynamicRangeProfile, getFormat(), getDataSpace(), dynamic_range_profile);
Emilian Peev40ead602017-09-26 15:46:36 +0100422 return BAD_VALUE;
423 }
424 }
425
426 //First remove all absent outputs
427 for (const auto &it : removedSurfaceIds) {
428 if (mStreamSplitter != nullptr) {
429 ret = mStreamSplitter->removeOutput(it);
430 if (ret != OK) {
431 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
432 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
433 if (res != OK) {
434 return res;
435 }
436 return ret;
437
438 }
439 }
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700440 removedSurfaces.add(mSurfaceUniqueIds[it].first, it);
441 mSurfaceUniqueIds[it] = std::make_pair(nullptr, mNextUniqueSurfaceId++);
Emilian Peev40ead602017-09-26 15:46:36 +0100442 }
443
444 //Next add the new outputs
445 for (const auto &it : outputSurfaces) {
446 ssize_t surfaceId = getNextSurfaceIdLocked();
447 if (surfaceId < 0) {
448 ALOGE("%s: No more available output slots!", __FUNCTION__);
449 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
450 if (res != OK) {
451 return res;
452 }
453 return NO_MEMORY;
454 }
455 if (mStreamSplitter != nullptr) {
456 ret = mStreamSplitter->addOutput(surfaceId, it);
457 if (ret != OK) {
458 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
459 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
460 if (res != OK) {
461 return res;
462 }
463 return ret;
464 }
465 }
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700466 mSurfaceUniqueIds[surfaceId] = std::make_pair(it, mNextUniqueSurfaceId++);
Emilian Peev40ead602017-09-26 15:46:36 +0100467 outputMap->add(it, surfaceId);
468 }
469
470 return ret;
471}
472
Shuzhen Wang0129d522016-10-30 22:43:41 -0700473} // namespace camera3
474
475} // namespace android