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