• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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