1 /*
2 * Copyright 2014,2016 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 "Camera3StreamSplitter"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20
21 #include <binder/ProcessState.h>
22 #include <camera/StringUtils.h>
23 #include <com_android_graphics_libgui_flags.h>
24 #include <gui/BufferItem.h>
25 #include <gui/BufferItemConsumer.h>
26 #include <gui/BufferQueue.h>
27 #include <gui/IGraphicBufferConsumer.h>
28 #include <gui/IGraphicBufferProducer.h>
29 #include <gui/Surface.h>
30 #include <system/window.h>
31 #include <ui/GraphicBuffer.h>
32 #include <utils/Trace.h>
33
34 #include <cutils/atomic.h>
35 #include <inttypes.h>
36 #include <algorithm>
37 #include <cstdint>
38 #include <memory>
39
40 #include "Camera3Stream.h"
41 #include "Flags.h"
42
43 #include "Camera3StreamSplitter.h"
44
45 // We're relying on a large number of yet-to-be-fully-launched flag dependencies
46 // here. So instead of flagging each one, we flag the entire implementation to
47 // improve legibility.
48 #if USE_NEW_STREAM_SPLITTER
49
50 namespace android {
51
connect(const std::unordered_map<size_t,sp<Surface>> & surfaces,uint64_t consumerUsage,uint64_t producerUsage,size_t halMaxBuffers,uint32_t width,uint32_t height,android::PixelFormat format,sp<Surface> * consumer,int64_t dynamicRangeProfile)52 status_t Camera3StreamSplitter::connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
53 uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
54 uint32_t height, android::PixelFormat format, sp<Surface>* consumer,
55 int64_t dynamicRangeProfile) {
56 ATRACE_CALL();
57 if (consumer == nullptr) {
58 SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
59 return BAD_VALUE;
60 }
61
62 Mutex::Autolock lock(mMutex);
63 status_t res = OK;
64
65 if (mOutputSurfaces.size() > 0 || mBufferItemConsumer != nullptr) {
66 SP_LOGE("%s: already connected", __FUNCTION__);
67 return BAD_VALUE;
68 }
69 if (mBuffers.size() > 0) {
70 SP_LOGE("%s: still has %zu pending buffers", __FUNCTION__, mBuffers.size());
71 return BAD_VALUE;
72 }
73
74 mMaxHalBuffers = halMaxBuffers;
75 mConsumerName = getUniqueConsumerName();
76 mDynamicRangeProfile = dynamicRangeProfile;
77 // Add output surfaces. This has to be before creating internal buffer queue
78 // in order to get max consumer side buffers.
79 for (auto &it : surfaces) {
80 if (it.second == nullptr) {
81 SP_LOGE("%s: Fatal: surface is NULL", __FUNCTION__);
82 return BAD_VALUE;
83 }
84 res = addOutputLocked(it.first, it.second);
85 if (res != OK) {
86 SP_LOGE("%s: Failed to add output surface: %s(%d)",
87 __FUNCTION__, strerror(-res), res);
88 return res;
89 }
90 }
91
92 // Allocate 1 extra buffer to handle the case where all buffers are detached
93 // from input, and attached to the outputs. In this case, the input queue's
94 // dequeueBuffer can still allocate 1 extra buffer before being blocked by
95 // the output's attachBuffer().
96 mMaxConsumerBuffers++;
97
98 std::tie(mBufferItemConsumer, mSurface) =
99 BufferItemConsumer::create(consumerUsage, mMaxConsumerBuffers);
100
101 if (mBufferItemConsumer == nullptr) {
102 return NO_MEMORY;
103 }
104 mBufferItemConsumer->setName(toString8(mConsumerName));
105
106 *consumer = mSurface;
107 if (*consumer == nullptr) {
108 return NO_MEMORY;
109 }
110
111 res = mSurface->setAsyncMode(true);
112 if (res != OK) {
113 SP_LOGE("%s: Failed to enable input queue async mode: %s(%d)", __FUNCTION__,
114 strerror(-res), res);
115 return res;
116 }
117
118 mBufferItemConsumer->setFrameAvailableListener(this);
119
120 mWidth = width;
121 mHeight = height;
122 mFormat = format;
123 mProducerUsage = producerUsage;
124 mAcquiredInputBuffers = 0;
125
126 SP_LOGV("%s: connected", __FUNCTION__);
127 return res;
128 }
129
getOnFrameAvailableResult()130 status_t Camera3StreamSplitter::getOnFrameAvailableResult() {
131 ATRACE_CALL();
132 return mOnFrameAvailableRes.load();
133 }
134
disconnect()135 void Camera3StreamSplitter::disconnect() {
136 ATRACE_CALL();
137 Mutex::Autolock lock(mMutex);
138
139 mNotifiers.clear();
140
141 for (auto& output : mOutputSurfaces) {
142 if (output.second != nullptr) {
143 output.second->disconnect(NATIVE_WINDOW_API_CAMERA);
144 }
145 }
146 mOutputSurfaces.clear();
147 mHeldBuffers.clear();
148 mConsumerBufferCount.clear();
149
150 if (mBufferItemConsumer != nullptr) {
151 mBufferItemConsumer->abandon();
152 }
153
154 if (mBuffers.size() > 0) {
155 SP_LOGW("%zu buffers still being tracked", mBuffers.size());
156 mBuffers.clear();
157 }
158
159 mMaxHalBuffers = 0;
160 mMaxConsumerBuffers = 0;
161 mAcquiredInputBuffers = 0;
162 SP_LOGV("%s: Disconnected", __FUNCTION__);
163 }
164
Camera3StreamSplitter(bool useHalBufManager)165 Camera3StreamSplitter::Camera3StreamSplitter(bool useHalBufManager) :
166 mUseHalBufManager(useHalBufManager) {}
167
~Camera3StreamSplitter()168 Camera3StreamSplitter::~Camera3StreamSplitter() {
169 disconnect();
170 }
171
addOutput(size_t surfaceId,const sp<Surface> & outputQueue)172 status_t Camera3StreamSplitter::addOutput(size_t surfaceId, const sp<Surface>& outputQueue) {
173 ATRACE_CALL();
174 Mutex::Autolock lock(mMutex);
175 status_t res = addOutputLocked(surfaceId, outputQueue);
176
177 if (res != OK) {
178 SP_LOGE("%s: addOutputLocked failed %d", __FUNCTION__, res);
179 return res;
180 }
181
182 if (mMaxConsumerBuffers > mAcquiredInputBuffers) {
183 res = mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers);
184 }
185
186 return res;
187 }
188
setHalBufferManager(bool enabled)189 void Camera3StreamSplitter::setHalBufferManager(bool enabled) {
190 Mutex::Autolock lock(mMutex);
191 mUseHalBufManager = enabled;
192 }
193
setTransform(size_t surfaceId,int transform)194 status_t Camera3StreamSplitter::setTransform(size_t surfaceId, int transform) {
195 Mutex::Autolock lock(mMutex);
196 if (!mOutputSurfaces.contains(surfaceId) || mOutputSurfaces[surfaceId] == nullptr) {
197 SP_LOGE("%s: No surface at id %zu", __FUNCTION__, surfaceId);
198 return BAD_VALUE;
199 }
200
201 mOutputTransforms[surfaceId] = transform;
202 return OK;
203 }
204
addOutputLocked(size_t surfaceId,const sp<Surface> & outputQueue)205 status_t Camera3StreamSplitter::addOutputLocked(size_t surfaceId, const sp<Surface>& outputQueue) {
206 ATRACE_CALL();
207 if (outputQueue == nullptr) {
208 SP_LOGE("addOutput: outputQueue must not be NULL");
209 return BAD_VALUE;
210 }
211
212 if (mOutputSurfaces[surfaceId] != nullptr) {
213 SP_LOGE("%s: surfaceId: %u already taken!", __FUNCTION__, (unsigned) surfaceId);
214 return BAD_VALUE;
215 }
216
217 status_t res = native_window_set_buffers_dimensions(outputQueue.get(),
218 mWidth, mHeight);
219 if (res != NO_ERROR) {
220 SP_LOGE("addOutput: failed to set buffer dimensions (%d)", res);
221 return res;
222 }
223 res = native_window_set_buffers_format(outputQueue.get(),
224 mFormat);
225 if (res != OK) {
226 ALOGE("%s: Unable to configure stream buffer format %#x for surfaceId %zu",
227 __FUNCTION__, mFormat, surfaceId);
228 return res;
229 }
230
231 // Connect to the buffer producer
232 sp<OutputListener> listener = sp<OutputListener>::make(this, outputQueue);
233 res = outputQueue->connect(NATIVE_WINDOW_API_CAMERA, listener, /* reportBufferRemoval */ false);
234 if (res != NO_ERROR) {
235 SP_LOGE("addOutput: failed to connect (%d)", res);
236 return res;
237 }
238
239 // Query consumer side buffer count, and update overall buffer count
240 int maxConsumerBuffers = 0;
241 res = static_cast<ANativeWindow*>(outputQueue.get())->query(
242 outputQueue.get(),
243 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
244 if (res != OK) {
245 SP_LOGE("%s: Unable to query consumer undequeued buffer count"
246 " for surface", __FUNCTION__);
247 return res;
248 }
249
250 SP_LOGV("%s: Consumer wants %d buffers, Producer wants %zu", __FUNCTION__,
251 maxConsumerBuffers, mMaxHalBuffers);
252 // The output slot count requirement can change depending on the current amount
253 // of outputs and incoming buffer consumption rate. To avoid any issues with
254 // insufficient slots, set their count to the maximum supported. The output
255 // surface buffer allocation is disabled so no real buffers will get allocated.
256 size_t totalBufferCount = BufferQueue::NUM_BUFFER_SLOTS;
257 res = native_window_set_buffer_count(outputQueue.get(),
258 totalBufferCount);
259 if (res != OK) {
260 SP_LOGE("%s: Unable to set buffer count for surface %p",
261 __FUNCTION__, outputQueue.get());
262 return res;
263 }
264
265 // Set dequeueBuffer/attachBuffer timeout if the consumer is not hw composer or hw texture.
266 // We need skip these cases as timeout will disable the non-blocking (async) mode.
267 uint64_t usage = 0;
268 res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(outputQueue.get()), &usage);
269 if (!(usage & (GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_TEXTURE))) {
270 nsecs_t timeout = mUseHalBufManager ?
271 kHalBufMgrDequeueBufferTimeout : kNormalDequeueBufferTimeout;
272 outputQueue->setDequeueTimeout(timeout);
273 }
274
275 res = outputQueue->allowAllocation(false);
276 if (res != OK) {
277 SP_LOGE("%s: Failed to turn off allocation for outputQueue", __FUNCTION__);
278 return res;
279 }
280
281 // Add new entry into mOutputs
282 mOutputSurfaces[surfaceId] = outputQueue;
283 mConsumerBufferCount[surfaceId] = maxConsumerBuffers;
284 if (mConsumerBufferCount[surfaceId] > mMaxHalBuffers) {
285 SP_LOGW("%s: Consumer buffer count %zu larger than max. Hal buffers: %zu", __FUNCTION__,
286 mConsumerBufferCount[surfaceId], mMaxHalBuffers);
287 }
288 mNotifiers[outputQueue] = listener;
289 mHeldBuffers[outputQueue] = std::make_unique<HeldBuffers>(totalBufferCount);
290
291 mMaxConsumerBuffers += maxConsumerBuffers;
292 return NO_ERROR;
293 }
294
removeOutput(size_t surfaceId)295 status_t Camera3StreamSplitter::removeOutput(size_t surfaceId) {
296 ATRACE_CALL();
297 Mutex::Autolock lock(mMutex);
298
299 status_t res = removeOutputLocked(surfaceId);
300 if (res != OK) {
301 SP_LOGE("%s: removeOutputLocked failed %d", __FUNCTION__, res);
302 return res;
303 }
304
305 if (mAcquiredInputBuffers < mMaxConsumerBuffers) {
306 res = mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers);
307 if (res != OK) {
308 SP_LOGE("%s: setMaxAcquiredBufferCount failed %d", __FUNCTION__, res);
309 return res;
310 }
311 }
312
313 return res;
314 }
315
removeOutputLocked(size_t surfaceId)316 status_t Camera3StreamSplitter::removeOutputLocked(size_t surfaceId) {
317 if (mOutputSurfaces[surfaceId] == nullptr) {
318 SP_LOGE("%s: output surface is not present!", __FUNCTION__);
319 return BAD_VALUE;
320 }
321
322 sp<Surface> surface = mOutputSurfaces[surfaceId];
323 //Search and decrement the ref. count of any buffers that are
324 //still attached to the removed surface.
325 std::vector<uint64_t> pendingBufferIds;
326
327 // TODO: can we simplify this to just use the tracker?
328 for (const auto& buffer : (*mHeldBuffers[surface])) {
329 pendingBufferIds.push_back(buffer->getId());
330 auto rc = surface->detachBuffer(buffer);
331 if (rc != NO_ERROR) {
332 // Buffers that fail to detach here will be scheduled for detach in the
333 // input buffer queue and the rest of the registered outputs instead.
334 // This will help ensure that camera stops accessing buffers that still
335 // can get referenced by the disconnected output.
336 mDetachedBuffers.emplace(buffer->getId());
337 }
338 }
339 mOutputSurfaces[surfaceId] = nullptr;
340 mHeldBuffers[surface] = nullptr;
341 for (const auto &id : pendingBufferIds) {
342 decrementBufRefCountLocked(id, surfaceId);
343 }
344
345 status_t res = surface->disconnect(NATIVE_WINDOW_API_CAMERA);
346 if (res != OK) {
347 SP_LOGE("%s: Unable disconnect from producer interface: %d ", __FUNCTION__, res);
348 return res;
349 }
350
351 mNotifiers[surface] = nullptr;
352 mMaxConsumerBuffers -= mConsumerBufferCount[surfaceId];
353 mConsumerBufferCount[surfaceId] = 0;
354
355 return res;
356 }
357
outputBufferLocked(const sp<Surface> & output,const BufferItem & bufferItem,size_t surfaceId)358 status_t Camera3StreamSplitter::outputBufferLocked(const sp<Surface>& output,
359 const BufferItem& bufferItem, size_t surfaceId) {
360 ATRACE_CALL();
361 status_t res;
362
363 uint64_t bufferId = bufferItem.mGraphicBuffer->getId();
364 const BufferTracker& tracker = *(mBuffers[bufferId]);
365
366 if (mOutputSurfaces[surfaceId] != nullptr) {
367 sp<ANativeWindow> anw = mOutputSurfaces[surfaceId];
368 camera3::Camera3Stream::queueHDRMetadata(
369 bufferItem.mGraphicBuffer->getNativeBuffer()->handle, anw, mDynamicRangeProfile);
370 } else {
371 SP_LOGE("%s: Invalid surface id: %zu!", __FUNCTION__, surfaceId);
372 }
373
374 output->setBuffersTimestamp(bufferItem.mTimestamp);
375 output->setBuffersDataSpace(static_cast<ui::Dataspace>(bufferItem.mDataSpace));
376 output->setCrop(&bufferItem.mCrop);
377 output->setScalingMode(bufferItem.mScalingMode);
378
379 int transform = bufferItem.mTransform;
380 if (mOutputTransforms.contains(surfaceId)) {
381 transform = mOutputTransforms[surfaceId];
382 }
383 output->setBuffersTransform(transform);
384
385 // In case the output BufferQueue has its own lock, if we hold splitter lock while calling
386 // queueBuffer (which will try to acquire the output lock), the output could be holding its
387 // own lock calling releaseBuffer (which will try to acquire the splitter lock), running into
388 // circular lock situation.
389 mMutex.unlock();
390 SurfaceQueueBufferOutput queueBufferOutput;
391 res = output->queueBuffer(bufferItem.mGraphicBuffer, bufferItem.mFence, &queueBufferOutput);
392 mMutex.lock();
393
394 SP_LOGV("%s: Queuing buffer to buffer queue %p bufferId %" PRIu64 " returns %d", __FUNCTION__,
395 output.get(), bufferId, res);
396 // During buffer queue 'mMutex' is not held which makes the removal of
397 // "output" possible. Check whether this is the case and return.
398 if (mOutputSurfaces[surfaceId] == nullptr) {
399 return res;
400 }
401 if (res != OK) {
402 if (res != NO_INIT && res != DEAD_OBJECT) {
403 SP_LOGE("Queuing buffer to output failed (%d)", res);
404 }
405 // If we just discovered that this output has been abandoned, note
406 // that, increment the release count so that we still release this
407 // buffer eventually, and move on to the next output
408 onAbandonedLocked();
409 decrementBufRefCountLocked(bufferItem.mGraphicBuffer->getId(), surfaceId);
410 return res;
411 }
412
413 // If the queued buffer replaces a pending buffer in the async
414 // queue, no onBufferReleased is called by the buffer queue.
415 // Proactively trigger the callback to avoid buffer loss.
416 if (queueBufferOutput.bufferReplaced) {
417 onBufferReplacedLocked(output, surfaceId);
418 }
419
420 return res;
421 }
422
getUniqueConsumerName()423 std::string Camera3StreamSplitter::getUniqueConsumerName() {
424 static volatile int32_t counter = 0;
425 return fmt::sprintf("Camera3StreamSplitter-%d", android_atomic_inc(&counter));
426 }
427
notifyBufferReleased(const sp<GraphicBuffer> & buffer)428 status_t Camera3StreamSplitter::notifyBufferReleased(const sp<GraphicBuffer>& buffer) {
429 ATRACE_CALL();
430
431 Mutex::Autolock lock(mMutex);
432
433 uint64_t bufferId = buffer->getId();
434 std::unique_ptr<BufferTracker> tracker_ptr = std::move(mBuffers[bufferId]);
435 mBuffers.erase(bufferId);
436
437 return OK;
438 }
439
attachBufferToOutputs(ANativeWindowBuffer * anb,const std::vector<size_t> & surface_ids)440 status_t Camera3StreamSplitter::attachBufferToOutputs(ANativeWindowBuffer* anb,
441 const std::vector<size_t>& surface_ids) {
442 ATRACE_CALL();
443 status_t res = OK;
444
445 Mutex::Autolock lock(mMutex);
446
447 sp<GraphicBuffer> gb(static_cast<GraphicBuffer*>(anb));
448 uint64_t bufferId = gb->getId();
449
450 // Initialize buffer tracker for this input buffer
451 auto tracker = std::make_unique<BufferTracker>(gb, surface_ids);
452
453 for (auto& surface_id : surface_ids) {
454 sp<Surface>& surface = mOutputSurfaces[surface_id];
455 if (surface.get() == nullptr) {
456 //Output surface got likely removed by client.
457 continue;
458 }
459
460 //Temporarly Unlock the mutex when trying to attachBuffer to the output
461 //queue, because attachBuffer could block in case of a slow consumer. If
462 //we block while holding the lock, onFrameAvailable and onBufferReleased
463 //will block as well because they need to acquire the same lock.
464 mMutex.unlock();
465 res = surface->attachBuffer(anb);
466 mMutex.lock();
467 //During buffer attach 'mMutex' is not held which makes the removal of
468 //"surface" possible. Check whether this is the case and continue.
469 if (surface.get() == nullptr) {
470 res = OK;
471 continue;
472 }
473 if (res != OK) {
474 SP_LOGE("%s: Cannot attachBuffer from GraphicBufferProducer %p: %s (%d)", __FUNCTION__,
475 surface.get(), strerror(-res), res);
476 // TODO: might need to detach/cleanup the already attached buffers before return?
477 return res;
478 }
479 mHeldBuffers[surface]->insert(gb);
480 SP_LOGV("%s: Attached buffer %p on output %p.", __FUNCTION__, gb.get(), surface.get());
481 }
482
483 mBuffers[bufferId] = std::move(tracker);
484
485 return res;
486 }
487
onFrameAvailable(const BufferItem &)488 void Camera3StreamSplitter::onFrameAvailable(const BufferItem& /*item*/) {
489 ATRACE_CALL();
490 Mutex::Autolock lock(mMutex);
491
492 // Acquire and detach the buffer from the input
493 BufferItem bufferItem;
494 status_t res = mBufferItemConsumer->acquireBuffer(&bufferItem, /* presentWhen */ 0);
495 if (res != NO_ERROR) {
496 SP_LOGE("%s: Acquiring buffer from input failed (%d)", __FUNCTION__, res);
497 mOnFrameAvailableRes.store(res);
498 return;
499 }
500
501 uint64_t bufferId = bufferItem.mGraphicBuffer->getId();
502
503 if (mBuffers.find(bufferId) == mBuffers.end()) {
504 SP_LOGE("%s: Acquired buffer doesn't exist in attached buffer map",
505 __FUNCTION__);
506 mOnFrameAvailableRes.store(INVALID_OPERATION);
507 return;
508 }
509
510 mAcquiredInputBuffers++;
511 SP_LOGV("acquired buffer %" PRId64 " from input at slot %d",
512 bufferItem.mGraphicBuffer->getId(), bufferItem.mSlot);
513
514 if (bufferItem.mTransformToDisplayInverse) {
515 bufferItem.mTransform |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
516 }
517
518 // Attach and queue the buffer to each of the outputs
519 BufferTracker& tracker = *(mBuffers[bufferId]);
520
521 SP_LOGV("%s: BufferTracker for buffer %" PRId64 ", number of requests %zu",
522 __FUNCTION__, bufferItem.mGraphicBuffer->getId(), tracker.requestedSurfaces().size());
523 for (const auto id : tracker.requestedSurfaces()) {
524 if (mOutputSurfaces[id] == nullptr) {
525 //Output surface got likely removed by client.
526 continue;
527 }
528
529 res = outputBufferLocked(mOutputSurfaces[id], bufferItem, id);
530 if (res != OK) {
531 SP_LOGE("%s: outputBufferLocked failed %d", __FUNCTION__, res);
532 mOnFrameAvailableRes.store(res);
533 // If we fail to send buffer to certain output, keep sending to
534 // other outputs.
535 continue;
536 }
537 }
538
539 mOnFrameAvailableRes.store(res);
540 }
541
onFrameReplaced(const BufferItem & item)542 void Camera3StreamSplitter::onFrameReplaced(const BufferItem& item) {
543 ATRACE_CALL();
544 onFrameAvailable(item);
545 }
546
decrementBufRefCountLocked(uint64_t id,size_t surfaceId)547 void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfaceId) {
548 ATRACE_CALL();
549
550 if (mBuffers[id] == nullptr) {
551 return;
552 }
553
554 size_t referenceCount = mBuffers[id]->decrementReferenceCountLocked(surfaceId);
555 if (referenceCount > 0) {
556 return;
557 }
558
559 // We no longer need to track the buffer now that it is being returned to the
560 // input. Note that this should happen before we unlock the mutex and call
561 // releaseBuffer, to avoid the case where the same bufferId is acquired in
562 // attachBufferToOutputs resulting in a new BufferTracker with same bufferId
563 // overwrites the current one.
564 std::unique_ptr<BufferTracker> tracker_ptr = std::move(mBuffers[id]);
565 mBuffers.erase(id);
566
567 uint64_t bufferId = tracker_ptr->getBuffer()->getId();
568
569 auto detachBuffer = mDetachedBuffers.find(bufferId);
570 bool detach = (detachBuffer != mDetachedBuffers.end());
571 if (detach) {
572 mDetachedBuffers.erase(detachBuffer);
573 }
574 // Temporarily unlock mutex to avoid circular lock:
575 // 1. This function holds splitter lock, calls releaseBuffer which triggers
576 // onBufferReleased in Camera3OutputStream. onBufferReleased waits on the
577 // OutputStream lock
578 // 2. Camera3SharedOutputStream::getBufferLocked calls
579 // attachBufferToOutputs, which holds the stream lock, and waits for the
580 // splitter lock.
581 mMutex.unlock();
582 int res = NO_ERROR;
583 if (mBufferItemConsumer != nullptr) {
584 if (detach) {
585 res = mBufferItemConsumer->detachBuffer(tracker_ptr->getBuffer());
586 } else {
587 res = mBufferItemConsumer->releaseBuffer(tracker_ptr->getBuffer(),
588 tracker_ptr->getMergedFence());
589 }
590 } else {
591 SP_LOGE("%s: consumer has become null!", __FUNCTION__);
592 }
593 mMutex.lock();
594
595 if (res != NO_ERROR) {
596 if (detach) {
597 SP_LOGE("%s: detachBuffer returns %d", __FUNCTION__, res);
598 } else {
599 SP_LOGE("%s: releaseBuffer returns %d", __FUNCTION__, res);
600 }
601 } else {
602 if (mAcquiredInputBuffers == 0) {
603 ALOGW("%s: Acquired input buffer count already at zero!", __FUNCTION__);
604 } else {
605 mAcquiredInputBuffers--;
606 }
607 }
608 }
609
onBufferReleasedByOutput(const sp<Surface> & from)610 void Camera3StreamSplitter::onBufferReleasedByOutput(const sp<Surface>& from) {
611 ATRACE_CALL();
612
613 from->setBuffersDimensions(mWidth, mHeight);
614 from->setBuffersFormat(mFormat);
615 from->setUsage(mProducerUsage);
616
617 sp<GraphicBuffer> buffer;
618 sp<Fence> fence;
619 auto res = from->dequeueBuffer(&buffer, &fence);
620 Mutex::Autolock lock(mMutex);
621 handleOutputDequeueStatusLocked(res, buffer);
622 if (res != OK) {
623 return;
624 }
625
626 size_t surfaceId = 0;
627 bool found = false;
628 for (const auto& it : mOutputSurfaces) {
629 if (it.second == from) {
630 found = true;
631 surfaceId = it.first;
632 break;
633 }
634 }
635 if (!found) {
636 SP_LOGV("%s: output surface not registered anymore!", __FUNCTION__);
637 return;
638 }
639
640 returnOutputBufferLocked(fence, from, surfaceId, buffer);
641 }
642
onBufferReplacedLocked(const sp<Surface> & from,size_t surfaceId)643 void Camera3StreamSplitter::onBufferReplacedLocked(const sp<Surface>& from, size_t surfaceId) {
644 ATRACE_CALL();
645
646 from->setBuffersDimensions(mWidth, mHeight);
647 from->setBuffersFormat(mFormat);
648 from->setUsage(mProducerUsage);
649
650 sp<GraphicBuffer> buffer;
651 sp<Fence> fence;
652 auto res = from->dequeueBuffer(&buffer, &fence);
653 handleOutputDequeueStatusLocked(res, buffer);
654 if (res != OK) {
655 return;
656 }
657
658 returnOutputBufferLocked(fence, from, surfaceId, buffer);
659 }
660
returnOutputBufferLocked(const sp<Fence> & fence,const sp<Surface> & from,size_t surfaceId,const sp<GraphicBuffer> & buffer)661 void Camera3StreamSplitter::returnOutputBufferLocked(const sp<Fence>& fence,
662 const sp<Surface>& from, size_t surfaceId, const sp<GraphicBuffer>& buffer) {
663 BufferTracker& tracker = *(mBuffers[buffer->getId()]);
664 // Merge the release fence of the incoming buffer so that the fence we send
665 // back to the input includes all of the outputs' fences
666 if (fence != nullptr && fence->isValid()) {
667 tracker.mergeFence(fence);
668 }
669
670 auto detachBuffer = mDetachedBuffers.find(buffer->getId());
671 bool detach = (detachBuffer != mDetachedBuffers.end());
672 if (detach) {
673 auto res = from->detachBuffer(buffer);
674 if (res == NO_ERROR) {
675 if (mHeldBuffers.contains(from)) {
676 mHeldBuffers[from]->erase(buffer);
677 } else {
678 uint64_t surfaceId = 0;
679 from->getUniqueId(&surfaceId);
680 SP_LOGW("%s: buffer %" PRIu64 " not found in held buffers of surface %" PRIu64,
681 __FUNCTION__, buffer->getId(), surfaceId);
682 }
683 } else {
684 SP_LOGE("%s: detach buffer from output failed (%d)", __FUNCTION__, res);
685 }
686 }
687
688 // Check to see if this is the last outstanding reference to this buffer
689 decrementBufRefCountLocked(buffer->getId(), surfaceId);
690 }
691
handleOutputDequeueStatusLocked(status_t res,const sp<GraphicBuffer> & buffer)692 void Camera3StreamSplitter::handleOutputDequeueStatusLocked(status_t res,
693 const sp<GraphicBuffer>& buffer) {
694 if (res == NO_INIT) {
695 // If we just discovered that this output has been abandoned, note that,
696 // but we can't do anything else, since buffer is invalid
697 onAbandonedLocked();
698 } else if (res == NO_MEMORY) {
699 SP_LOGE("%s: No free buffers", __FUNCTION__);
700 } else if (res == WOULD_BLOCK) {
701 SP_LOGE("%s: Dequeue call will block", __FUNCTION__);
702 } else if (res != OK || buffer == nullptr) {
703 SP_LOGE("%s: dequeue buffer from output failed (%d)", __FUNCTION__, res);
704 }
705 }
706
onAbandonedLocked()707 void Camera3StreamSplitter::onAbandonedLocked() {
708 // If this is called from binderDied callback, it means the app process
709 // holding the binder has died. CameraService will be notified of the binder
710 // death, and camera device will be closed, which in turn calls
711 // disconnect().
712 //
713 // If this is called from onBufferReleasedByOutput or onFrameAvailable, one
714 // consumer being abanoned shouldn't impact the other consumer. So we won't
715 // stop the buffer flow.
716 //
717 // In both cases, we don't need to do anything here.
718 SP_LOGV("One of my outputs has abandoned me");
719 }
720
OutputListener(wp<Camera3StreamSplitter> splitter,wp<Surface> output)721 Camera3StreamSplitter::OutputListener::OutputListener(wp<Camera3StreamSplitter> splitter,
722 wp<Surface> output)
723 : mSplitter(splitter), mOutput(output) {}
724
onBufferReleased()725 void Camera3StreamSplitter::OutputListener::onBufferReleased() {
726 ATRACE_CALL();
727 sp<Camera3StreamSplitter> splitter = mSplitter.promote();
728 sp<Surface> output = mOutput.promote();
729 if (splitter != nullptr && output != nullptr) {
730 splitter->onBufferReleasedByOutput(output);
731 }
732 }
733
onRemoteDied()734 void Camera3StreamSplitter::OutputListener::onRemoteDied() {
735 sp<Camera3StreamSplitter> splitter = mSplitter.promote();
736 if (splitter != nullptr) {
737 Mutex::Autolock lock(splitter->mMutex);
738 splitter->onAbandonedLocked();
739 }
740 }
741
BufferTracker(const sp<GraphicBuffer> & buffer,const std::vector<size_t> & requestedSurfaces)742 Camera3StreamSplitter::BufferTracker::BufferTracker(
743 const sp<GraphicBuffer>& buffer, const std::vector<size_t>& requestedSurfaces)
744 : mBuffer(buffer), mMergedFence(Fence::NO_FENCE), mRequestedSurfaces(requestedSurfaces),
745 mReferenceCount(requestedSurfaces.size()) {}
746
mergeFence(const sp<Fence> & with)747 void Camera3StreamSplitter::BufferTracker::mergeFence(const sp<Fence>& with) {
748 mMergedFence = Fence::merge(String8("Camera3StreamSplitter"), mMergedFence, with);
749 }
750
decrementReferenceCountLocked(size_t surfaceId)751 size_t Camera3StreamSplitter::BufferTracker::decrementReferenceCountLocked(size_t surfaceId) {
752 const auto& it = std::find(mRequestedSurfaces.begin(), mRequestedSurfaces.end(), surfaceId);
753 if (it == mRequestedSurfaces.end()) {
754 return mReferenceCount;
755 } else {
756 mRequestedSurfaces.erase(it);
757 }
758
759 if (mReferenceCount > 0)
760 --mReferenceCount;
761 return mReferenceCount;
762 }
763
764 } // namespace android
765
766 #endif // USE_NEW_STREAM_SPLITTER
767