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