blob: a360abfed9339f5a058a46a4a08b0488aa774c40 [file] [log] [blame]
Shuzhen Wang0129d522016-10-30 22:43:41 -07001/*
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
Shuzhen Wang0129d522016-10-30 22:43:41 -070017#define LOG_TAG "Camera3StreamSplitter"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
Jim Shargobdc46fa2024-07-01 16:46:49 +000021#include <binder/ProcessState.h>
Jim Shargo2e0202f2024-07-30 19:54:43 +000022#include <camera/StringUtils.h>
23#include <com_android_graphics_libgui_flags.h>
Shuzhen Wang0129d522016-10-30 22:43:41 -070024#include <gui/BufferItem.h>
Jim Shargobdc46fa2024-07-01 16:46:49 +000025#include <gui/BufferItemConsumer.h>
Jim Shargo2e0202f2024-07-30 19:54:43 +000026#include <gui/BufferQueue.h>
Shuzhen Wang0129d522016-10-30 22:43:41 -070027#include <gui/IGraphicBufferConsumer.h>
28#include <gui/IGraphicBufferProducer.h>
Shuzhen Wang0129d522016-10-30 22:43:41 -070029#include <gui/Surface.h>
Jim Shargobdc46fa2024-07-01 16:46:49 +000030#include <system/window.h>
Shuzhen Wang0129d522016-10-30 22:43:41 -070031#include <ui/GraphicBuffer.h>
Shuzhen Wang0129d522016-10-30 22:43:41 -070032#include <utils/Trace.h>
33
Mathias Agopian05d19b02017-02-28 16:28:19 -080034#include <cutils/atomic.h>
Jim Shargobdc46fa2024-07-01 16:46:49 +000035#include <inttypes.h>
36#include <algorithm>
37#include <cstdint>
38#include <memory>
Mathias Agopian05d19b02017-02-28 16:28:19 -080039
Emilian Peev2295df72021-11-12 18:14:10 -080040#include "Camera3Stream.h"
Jim Shargobdc46fa2024-07-01 16:46:49 +000041#include "Flags.h"
Emilian Peev2295df72021-11-12 18:14:10 -080042
Shuzhen Wang0129d522016-10-30 22:43:41 -070043#include "Camera3StreamSplitter.h"
44
Jim Shargobdc46fa2024-07-01 16:46:49 +000045// 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
Shuzhen Wang0129d522016-10-30 22:43:41 -070050namespace android {
51
Emilian Peev40ead602017-09-26 15:46:36 +010052status_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,
Emilian Peev2295df72021-11-12 18:14:10 -080054 uint32_t height, android::PixelFormat format, sp<Surface>* consumer,
Emilian Peevc81a7592022-02-14 17:38:18 -080055 int64_t dynamicRangeProfile) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080056 ATRACE_CALL();
57 if (consumer == nullptr) {
58 SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
Shuzhen Wang0129d522016-10-30 22:43:41 -070059 return BAD_VALUE;
60 }
61
62 Mutex::Autolock lock(mMutex);
63 status_t res = OK;
64
Jim Shargobdc46fa2024-07-01 16:46:49 +000065 if (mOutputSurfaces.size() > 0 || mBufferItemConsumer != nullptr) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080066 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());
Shuzhen Wang0129d522016-10-30 22:43:41 -070071 return BAD_VALUE;
72 }
73
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080074 mMaxHalBuffers = halMaxBuffers;
75 mConsumerName = getUniqueConsumerName();
Emilian Peev2295df72021-11-12 18:14:10 -080076 mDynamicRangeProfile = dynamicRangeProfile;
Shuzhen Wang0129d522016-10-30 22:43:41 -070077 // Add output surfaces. This has to be before creating internal buffer queue
78 // in order to get max consumer side buffers.
Emilian Peev40ead602017-09-26 15:46:36 +010079 for (auto &it : surfaces) {
80 if (it.second == nullptr) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080081 SP_LOGE("%s: Fatal: surface is NULL", __FUNCTION__);
Shuzhen Wang758c2152017-01-10 18:26:18 -080082 return BAD_VALUE;
83 }
Emilian Peev40ead602017-09-26 15:46:36 +010084 res = addOutputLocked(it.first, it.second);
Shuzhen Wang758c2152017-01-10 18:26:18 -080085 if (res != OK) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080086 SP_LOGE("%s: Failed to add output surface: %s(%d)",
Shuzhen Wang758c2152017-01-10 18:26:18 -080087 __FUNCTION__, strerror(-res), res);
88 return res;
Shuzhen Wang0129d522016-10-30 22:43:41 -070089 }
90 }
91
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080092 // 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().
Emilian Peevf130ad72018-10-11 11:03:07 +010096 mMaxConsumerBuffers++;
Jim Shargobdc46fa2024-07-01 16:46:49 +000097
Jim Shargo2e0202f2024-07-30 19:54:43 +000098#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
Jim Shargobdc46fa2024-07-01 16:46:49 +000099 mBufferItemConsumer = sp<BufferItemConsumer>::make(consumerUsage, mMaxConsumerBuffers);
100 mSurface = mBufferItemConsumer->getSurface();
Jim Shargo2e0202f2024-07-30 19:54:43 +0000101#else
Jim Shargobdc46fa2024-07-01 16:46:49 +0000102 // 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);
Jim Shargo2e0202f2024-07-30 19:54:43 +0000109#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
Jim Shargobdc46fa2024-07-01 16:46:49 +0000110
Shuzhen Wang0129d522016-10-30 22:43:41 -0700111 if (mBufferItemConsumer == nullptr) {
112 return NO_MEMORY;
113 }
Jim Shargobdc46fa2024-07-01 16:46:49 +0000114 mBufferItemConsumer->setName(toString8(mConsumerName));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700115
Jim Shargobdc46fa2024-07-01 16:46:49 +0000116 *consumer = mSurface;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800117 if (*consumer == nullptr) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700118 return NO_MEMORY;
119 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700120
Jim Shargobdc46fa2024-07-01 16:46:49 +0000121 res = mSurface->setAsyncMode(true);
Emilian Peev40ead602017-09-26 15:46:36 +0100122 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
Jim Shargobdc46fa2024-07-01 16:46:49 +0000128 mBufferItemConsumer->setFrameAvailableListener(this);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700129
Emilian Peev40ead602017-09-26 15:46:36 +0100130 mWidth = width;
131 mHeight = height;
132 mFormat = format;
133 mProducerUsage = producerUsage;
Emilian Peevf130ad72018-10-11 11:03:07 +0100134 mAcquiredInputBuffers = 0;
Emilian Peev40ead602017-09-26 15:46:36 +0100135
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800136 SP_LOGV("%s: connected", __FUNCTION__);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700137 return res;
138}
139
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800140status_t Camera3StreamSplitter::getOnFrameAvailableResult() {
141 ATRACE_CALL();
142 return mOnFrameAvailableRes.load();
143}
144
Shuzhen Wang0129d522016-10-30 22:43:41 -0700145void Camera3StreamSplitter::disconnect() {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800146 ATRACE_CALL();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700147 Mutex::Autolock lock(mMutex);
148
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800149 mNotifiers.clear();
150
Jim Shargobdc46fa2024-07-01 16:46:49 +0000151 for (auto& output : mOutputSurfaces) {
Emilian Peev40ead602017-09-26 15:46:36 +0100152 if (output.second != nullptr) {
153 output.second->disconnect(NATIVE_WINDOW_API_CAMERA);
154 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700155 }
Emilian Peev2295df72021-11-12 18:14:10 -0800156 mOutputSurfaces.clear();
Jim Shargobdc46fa2024-07-01 16:46:49 +0000157 mHeldBuffers.clear();
Emilian Peev40ead602017-09-26 15:46:36 +0100158 mConsumerBufferCount.clear();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700159
Jim Shargobdc46fa2024-07-01 16:46:49 +0000160 if (mBufferItemConsumer != nullptr) {
161 mBufferItemConsumer->abandon();
Emilian Peev359adca2019-10-30 10:12:46 -0700162 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700163
164 if (mBuffers.size() > 0) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800165 SP_LOGW("%zu buffers still being tracked", mBuffers.size());
166 mBuffers.clear();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700167 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800168
169 mMaxHalBuffers = 0;
170 mMaxConsumerBuffers = 0;
Emilian Peevf130ad72018-10-11 11:03:07 +0100171 mAcquiredInputBuffers = 0;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800172 SP_LOGV("%s: Disconnected", __FUNCTION__);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700173}
174
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700175Camera3StreamSplitter::Camera3StreamSplitter(bool useHalBufManager) :
176 mUseHalBufManager(useHalBufManager) {}
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800177
Shuzhen Wang0129d522016-10-30 22:43:41 -0700178Camera3StreamSplitter::~Camera3StreamSplitter() {
179 disconnect();
180}
181
Emilian Peev40ead602017-09-26 15:46:36 +0100182status_t Camera3StreamSplitter::addOutput(size_t surfaceId, const sp<Surface>& outputQueue) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800183 ATRACE_CALL();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700184 Mutex::Autolock lock(mMutex);
Emilian Peev40ead602017-09-26 15:46:36 +0100185 status_t res = addOutputLocked(surfaceId, outputQueue);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800186
187 if (res != OK) {
188 SP_LOGE("%s: addOutputLocked failed %d", __FUNCTION__, res);
189 return res;
190 }
191
Emilian Peevf130ad72018-10-11 11:03:07 +0100192 if (mMaxConsumerBuffers > mAcquiredInputBuffers) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000193 res = mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers);
Emilian Peevf130ad72018-10-11 11:03:07 +0100194 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800195
196 return res;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700197}
198
Jayant Chowdhary9d3a6492023-11-22 07:23:59 +0000199void Camera3StreamSplitter::setHalBufferManager(bool enabled) {
200 Mutex::Autolock lock(mMutex);
201 mUseHalBufManager = enabled;
202}
203
Shuzhen Wang38df0ca2024-10-09 11:33:44 -0700204status_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
Emilian Peev40ead602017-09-26 15:46:36 +0100215status_t Camera3StreamSplitter::addOutputLocked(size_t surfaceId, const sp<Surface>& outputQueue) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800216 ATRACE_CALL();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700217 if (outputQueue == nullptr) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800218 SP_LOGE("addOutput: outputQueue must not be NULL");
Shuzhen Wang0129d522016-10-30 22:43:41 -0700219 return BAD_VALUE;
220 }
221
Jim Shargobdc46fa2024-07-01 16:46:49 +0000222 if (mOutputSurfaces[surfaceId] != nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100223 SP_LOGE("%s: surfaceId: %u already taken!", __FUNCTION__, (unsigned) surfaceId);
224 return BAD_VALUE;
225 }
226
Shuzhen Wang9d5c9362018-08-27 11:39:53 -0700227 status_t res = native_window_set_buffers_dimensions(outputQueue.get(),
Emilian Peev40ead602017-09-26 15:46:36 +0100228 mWidth, mHeight);
229 if (res != NO_ERROR) {
230 SP_LOGE("addOutput: failed to set buffer dimensions (%d)", res);
231 return res;
232 }
Shuzhen Wang9d5c9362018-08-27 11:39:53 -0700233 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 }
Emilian Peev40ead602017-09-26 15:46:36 +0100240
Shuzhen Wang0129d522016-10-30 22:43:41 -0700241 // Connect to the buffer producer
Jim Shargobdc46fa2024-07-01 16:46:49 +0000242 sp<OutputListener> listener = sp<OutputListener>::make(this, outputQueue);
243 res = outputQueue->connect(NATIVE_WINDOW_API_CAMERA, listener, /* reportBufferRemoval */ false);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800244 if (res != NO_ERROR) {
245 SP_LOGE("addOutput: failed to connect (%d)", res);
246 return res;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700247 }
248
249 // Query consumer side buffer count, and update overall buffer count
250 int maxConsumerBuffers = 0;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800251 res = static_cast<ANativeWindow*>(outputQueue.get())->query(
Shuzhen Wang0129d522016-10-30 22:43:41 -0700252 outputQueue.get(),
253 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800254 if (res != OK) {
255 SP_LOGE("%s: Unable to query consumer undequeued buffer count"
Shuzhen Wang0129d522016-10-30 22:43:41 -0700256 " for surface", __FUNCTION__);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800257 return res;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700258 }
259
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800260 SP_LOGV("%s: Consumer wants %d buffers, Producer wants %zu", __FUNCTION__,
261 maxConsumerBuffers, mMaxHalBuffers);
Emilian Peev18e3f372018-05-22 18:55:01 +0100262 // 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;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800267 res = native_window_set_buffer_count(outputQueue.get(),
Shuzhen Wang0129d522016-10-30 22:43:41 -0700268 totalBufferCount);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800269 if (res != OK) {
270 SP_LOGE("%s: Unable to set buffer count for surface %p",
Shuzhen Wang0129d522016-10-30 22:43:41 -0700271 __FUNCTION__, outputQueue.get());
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800272 return res;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700273 }
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.
Emilian Peev050f5dc2017-05-18 14:43:56 +0100277 uint64_t usage = 0;
278 res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(outputQueue.get()), &usage);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700279 if (!(usage & (GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_TEXTURE))) {
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700280 nsecs_t timeout = mUseHalBufManager ?
281 kHalBufMgrDequeueBufferTimeout : kNormalDequeueBufferTimeout;
282 outputQueue->setDequeueTimeout(timeout);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700283 }
284
Jim Shargobdc46fa2024-07-01 16:46:49 +0000285 res = outputQueue->allowAllocation(false);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800286 if (res != OK) {
287 SP_LOGE("%s: Failed to turn off allocation for outputQueue", __FUNCTION__);
288 return res;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700289 }
290
291 // Add new entry into mOutputs
Emilian Peev2295df72021-11-12 18:14:10 -0800292 mOutputSurfaces[surfaceId] = outputQueue;
Emilian Peev40ead602017-09-26 15:46:36 +0100293 mConsumerBufferCount[surfaceId] = maxConsumerBuffers;
Emilian Peevf63f1d92018-11-06 16:33:29 +0000294 if (mConsumerBufferCount[surfaceId] > mMaxHalBuffers) {
295 SP_LOGW("%s: Consumer buffer count %zu larger than max. Hal buffers: %zu", __FUNCTION__,
296 mConsumerBufferCount[surfaceId], mMaxHalBuffers);
297 }
Jim Shargobdc46fa2024-07-01 16:46:49 +0000298 mNotifiers[outputQueue] = listener;
299 mHeldBuffers[outputQueue] = std::make_unique<HeldBuffers>(totalBufferCount);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800300
301 mMaxConsumerBuffers += maxConsumerBuffers;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700302 return NO_ERROR;
303}
304
Emilian Peev40ead602017-09-26 15:46:36 +0100305status_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
Emilian Peevf130ad72018-10-11 11:03:07 +0100315 if (mAcquiredInputBuffers < mMaxConsumerBuffers) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000316 res = mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers);
Emilian Peevf130ad72018-10-11 11:03:07 +0100317 if (res != OK) {
318 SP_LOGE("%s: setMaxAcquiredBufferCount failed %d", __FUNCTION__, res);
319 return res;
320 }
Emilian Peev40ead602017-09-26 15:46:36 +0100321 }
322
323 return res;
324}
325
326status_t Camera3StreamSplitter::removeOutputLocked(size_t surfaceId) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000327 if (mOutputSurfaces[surfaceId] == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100328 SP_LOGE("%s: output surface is not present!", __FUNCTION__);
329 return BAD_VALUE;
330 }
331
Jim Shargobdc46fa2024-07-01 16:46:49 +0000332 sp<Surface> surface = mOutputSurfaces[surfaceId];
Emilian Peev40ead602017-09-26 15:46:36 +0100333 //Search and decrement the ref. count of any buffers that are
334 //still attached to the removed surface.
335 std::vector<uint64_t> pendingBufferIds;
Jim Shargobdc46fa2024-07-01 16:46:49 +0000336
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());
Emilian Peev40ead602017-09-26 15:46:36 +0100347 }
348 }
Emilian Peev2295df72021-11-12 18:14:10 -0800349 mOutputSurfaces[surfaceId] = nullptr;
Jim Shargobdc46fa2024-07-01 16:46:49 +0000350 mHeldBuffers[surface] = nullptr;
Emilian Peev40ead602017-09-26 15:46:36 +0100351 for (const auto &id : pendingBufferIds) {
352 decrementBufRefCountLocked(id, surfaceId);
353 }
354
Jim Shargobdc46fa2024-07-01 16:46:49 +0000355 status_t res = surface->disconnect(NATIVE_WINDOW_API_CAMERA);
Emilian Peev40ead602017-09-26 15:46:36 +0100356 if (res != OK) {
357 SP_LOGE("%s: Unable disconnect from producer interface: %d ", __FUNCTION__, res);
358 return res;
359 }
360
Jim Shargobdc46fa2024-07-01 16:46:49 +0000361 mNotifiers[surface] = nullptr;
Emilian Peevf63f1d92018-11-06 16:33:29 +0000362 mMaxConsumerBuffers -= mConsumerBufferCount[surfaceId];
Emilian Peev40ead602017-09-26 15:46:36 +0100363 mConsumerBufferCount[surfaceId] = 0;
364
365 return res;
366}
367
Jim Shargobdc46fa2024-07-01 16:46:49 +0000368status_t Camera3StreamSplitter::outputBufferLocked(const sp<Surface>& output,
Emilian Peev40ead602017-09-26 15:46:36 +0100369 const BufferItem& bufferItem, size_t surfaceId) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800370 ATRACE_CALL();
371 status_t res;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800372
373 uint64_t bufferId = bufferItem.mGraphicBuffer->getId();
374 const BufferTracker& tracker = *(mBuffers[bufferId]);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800375
Emilian Peev2295df72021-11-12 18:14:10 -0800376 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
Jim Shargobdc46fa2024-07-01 16:46:49 +0000384 output->setBuffersTimestamp(bufferItem.mTimestamp);
385 output->setBuffersDataSpace(static_cast<ui::Dataspace>(bufferItem.mDataSpace));
386 output->setCrop(&bufferItem.mCrop);
387 output->setScalingMode(bufferItem.mScalingMode);
Shuzhen Wang38df0ca2024-10-09 11:33:44 -0700388
389 int transform = bufferItem.mTransform;
390 if (mOutputTransforms.contains(surfaceId)) {
391 transform = mOutputTransforms[surfaceId];
392 }
393 output->setBuffersTransform(transform);
Jim Shargobdc46fa2024-07-01 16:46:49 +0000394
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800395 // 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();
Jim Shargobdc46fa2024-07-01 16:46:49 +0000400 SurfaceQueueBufferOutput queueBufferOutput;
401 res = output->queueBuffer(bufferItem.mGraphicBuffer, bufferItem.mFence, &queueBufferOutput);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800402 mMutex.lock();
403
Jim Shargobdc46fa2024-07-01 16:46:49 +0000404 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) {
Emilian Peev40ead602017-09-26 15:46:36 +0100409 return res;
410 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800411 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();
Emilian Peev40ead602017-09-26 15:46:36 +0100419 decrementBufRefCountLocked(bufferItem.mGraphicBuffer->getId(), surfaceId);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800420 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.
Jim Shargobdc46fa2024-07-01 16:46:49 +0000426 if (queueBufferOutput.bufferReplaced) {
Emilian Peev703e4992018-02-27 11:42:09 +0000427 onBufferReplacedLocked(output, surfaceId);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800428 }
429
430 return res;
431}
432
Austin Borger1c1bee02023-06-01 16:51:35 -0700433std::string Camera3StreamSplitter::getUniqueConsumerName() {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700434 static volatile int32_t counter = 0;
Austin Borger1c1bee02023-06-01 16:51:35 -0700435 return fmt::sprintf("Camera3StreamSplitter-%d", android_atomic_inc(&counter));
Shuzhen Wang0129d522016-10-30 22:43:41 -0700436}
437
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800438status_t Camera3StreamSplitter::notifyBufferReleased(const sp<GraphicBuffer>& buffer) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700439 ATRACE_CALL();
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800440
Shuzhen Wang0129d522016-10-30 22:43:41 -0700441 Mutex::Autolock lock(mMutex);
442
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800443 uint64_t bufferId = buffer->getId();
444 std::unique_ptr<BufferTracker> tracker_ptr = std::move(mBuffers[bufferId]);
445 mBuffers.erase(bufferId);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700446
Emilian Peev40ead602017-09-26 15:46:36 +0100447 return OK;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800448}
449
450status_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) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000464 sp<Surface>& surface = mOutputSurfaces[surface_id];
465 if (surface.get() == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100466 //Output surface got likely removed by client.
467 continue;
468 }
Jim Shargobdc46fa2024-07-01 16:46:49 +0000469
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800470 //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();
Jim Shargobdc46fa2024-07-01 16:46:49 +0000475 res = surface->attachBuffer(anb);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800476 mMutex.lock();
477 if (res != OK) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000478 SP_LOGE("%s: Cannot attachBuffer from GraphicBufferProducer %p: %s (%d)", __FUNCTION__,
479 surface.get(), strerror(-res), res);
Yin-Chia Yeh58b1b4e2018-10-15 12:18:36 -0700480 // TODO: might need to detach/cleanup the already attached buffers before return?
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800481 return res;
482 }
Emilian Peev40ead602017-09-26 15:46:36 +0100483 //During buffer attach 'mMutex' is not held which makes the removal of
484 //"gbp" possible. Check whether this is the case and continue.
Jim Shargobdc46fa2024-07-01 16:46:49 +0000485 if (mHeldBuffers[surface] == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100486 continue;
487 }
Jim Shargobdc46fa2024-07-01 16:46:49 +0000488 mHeldBuffers[surface]->insert(gb);
489 SP_LOGV("%s: Attached buffer %p on output %p.", __FUNCTION__, gb.get(), surface.get());
Shuzhen Wang0129d522016-10-30 22:43:41 -0700490 }
491
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800492 mBuffers[bufferId] = std::move(tracker);
493
494 return res;
495}
496
497void Camera3StreamSplitter::onFrameAvailable(const BufferItem& /*item*/) {
498 ATRACE_CALL();
499 Mutex::Autolock lock(mMutex);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700500
501 // Acquire and detach the buffer from the input
502 BufferItem bufferItem;
Jim Shargobdc46fa2024-07-01 16:46:49 +0000503 status_t res = mBufferItemConsumer->acquireBuffer(&bufferItem, /* presentWhen */ 0);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800504 if (res != NO_ERROR) {
505 SP_LOGE("%s: Acquiring buffer from input failed (%d)", __FUNCTION__, res);
506 mOnFrameAvailableRes.store(res);
507 return;
508 }
Emilian Peev40ead602017-09-26 15:46:36 +0100509
Jim Shargobdc46fa2024-07-01 16:46:49 +0000510 uint64_t bufferId = bufferItem.mGraphicBuffer->getId();
Emilian Peev40ead602017-09-26 15:46:36 +0100511
512 if (mBuffers.find(bufferId) == mBuffers.end()) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800513 SP_LOGE("%s: Acquired buffer doesn't exist in attached buffer map",
514 __FUNCTION__);
515 mOnFrameAvailableRes.store(INVALID_OPERATION);
516 return;
517 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700518
Emilian Peevf130ad72018-10-11 11:03:07 +0100519 mAcquiredInputBuffers++;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800520 SP_LOGV("acquired buffer %" PRId64 " from input at slot %d",
521 bufferItem.mGraphicBuffer->getId(), bufferItem.mSlot);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700522
Emilian Peev3bdcdff2018-06-25 14:37:29 +0100523 if (bufferItem.mTransformToDisplayInverse) {
524 bufferItem.mTransform |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
525 }
526
Shuzhen Wang0129d522016-10-30 22:43:41 -0700527 // Attach and queue the buffer to each of the outputs
Emilian Peev40ead602017-09-26 15:46:36 +0100528 BufferTracker& tracker = *(mBuffers[bufferId]);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700529
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800530 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()) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000533 if (mOutputSurfaces[id] == nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100534 //Output surface got likely removed by client.
535 continue;
536 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700537
Jim Shargobdc46fa2024-07-01 16:46:49 +0000538 res = outputBufferLocked(mOutputSurfaces[id], bufferItem, id);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800539 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;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700545 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800546 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700547
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800548 mOnFrameAvailableRes.store(res);
549}
550
Yin-Chia Yehda208452019-08-26 15:35:57 -0700551void Camera3StreamSplitter::onFrameReplaced(const BufferItem& item) {
552 ATRACE_CALL();
553 onFrameAvailable(item);
554}
555
Emilian Peev40ead602017-09-26 15:46:36 +0100556void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfaceId) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800557 ATRACE_CALL();
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800558
Emilian Peev40ead602017-09-26 15:46:36 +0100559 if (mBuffers[id] == nullptr) {
560 return;
561 }
562
563 size_t referenceCount = mBuffers[id]->decrementReferenceCountLocked(surfaceId);
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800564 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
Emilian Peev40ead602017-09-26 15:46:36 +0100576 uint64_t bufferId = tracker_ptr->getBuffer()->getId();
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800577
Emilian Peev6f823722017-12-07 18:05:49 +0000578 auto detachBuffer = mDetachedBuffers.find(bufferId);
579 bool detach = (detachBuffer != mDetachedBuffers.end());
580 if (detach) {
581 mDetachedBuffers.erase(detachBuffer);
Emilian Peev6f823722017-12-07 18:05:49 +0000582 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800583 // 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.
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800590 mMutex.unlock();
Emilian Peev40ead602017-09-26 15:46:36 +0100591 int res = NO_ERROR;
Jim Shargobdc46fa2024-07-01 16:46:49 +0000592 if (mBufferItemConsumer != nullptr) {
Emilian Peev6f823722017-12-07 18:05:49 +0000593 if (detach) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000594 res = mBufferItemConsumer->detachBuffer(tracker_ptr->getBuffer());
Emilian Peev6f823722017-12-07 18:05:49 +0000595 } else {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000596 res = mBufferItemConsumer->releaseBuffer(tracker_ptr->getBuffer(),
597 tracker_ptr->getMergedFence());
Emilian Peev6f823722017-12-07 18:05:49 +0000598 }
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800599 } else {
600 SP_LOGE("%s: consumer has become null!", __FUNCTION__);
601 }
602 mMutex.lock();
Emilian Peev6f823722017-12-07 18:05:49 +0000603
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800604 if (res != NO_ERROR) {
Emilian Peev6f823722017-12-07 18:05:49 +0000605 if (detach) {
606 SP_LOGE("%s: detachBuffer returns %d", __FUNCTION__, res);
607 } else {
608 SP_LOGE("%s: releaseBuffer returns %d", __FUNCTION__, res);
609 }
Emilian Peevf130ad72018-10-11 11:03:07 +0100610 } else {
611 if (mAcquiredInputBuffers == 0) {
612 ALOGW("%s: Acquired input buffer count already at zero!", __FUNCTION__);
613 } else {
614 mAcquiredInputBuffers--;
615 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700616 }
617}
618
Jim Shargobdc46fa2024-07-01 16:46:49 +0000619void Camera3StreamSplitter::onBufferReleasedByOutput(const sp<Surface>& from) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700620 ATRACE_CALL();
Emilian Peev703e4992018-02-27 11:42:09 +0000621
Jim Shargobdc46fa2024-07-01 16:46:49 +0000622 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);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700629 Mutex::Autolock lock(mMutex);
Jim Shargobdc46fa2024-07-01 16:46:49 +0000630 handleOutputDequeueStatusLocked(res, buffer);
Emilian Peev703e4992018-02-27 11:42:09 +0000631 if (res != OK) {
632 return;
633 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700634
Emilian Peev40ead602017-09-26 15:46:36 +0100635 size_t surfaceId = 0;
636 bool found = false;
Jim Shargobdc46fa2024-07-01 16:46:49 +0000637 for (const auto& it : mOutputSurfaces) {
Emilian Peev40ead602017-09-26 15:46:36 +0100638 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
Jim Shargobdc46fa2024-07-01 16:46:49 +0000649 returnOutputBufferLocked(fence, from, surfaceId, buffer);
Shuzhen Wanga141c5f2017-01-24 14:51:37 -0800650}
651
Jim Shargobdc46fa2024-07-01 16:46:49 +0000652void Camera3StreamSplitter::onBufferReplacedLocked(const sp<Surface>& from, size_t surfaceId) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800653 ATRACE_CALL();
Emilian Peev40ead602017-09-26 15:46:36 +0100654
Jim Shargobdc46fa2024-07-01 16:46:49 +0000655 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);
Emilian Peev703e4992018-02-27 11:42:09 +0000663 if (res != OK) {
Shuzhen Wangafa8a912017-03-15 10:51:27 -0700664 return;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700665 }
666
Jim Shargobdc46fa2024-07-01 16:46:49 +0000667 returnOutputBufferLocked(fence, from, surfaceId, buffer);
Emilian Peev703e4992018-02-27 11:42:09 +0000668}
669
670void Camera3StreamSplitter::returnOutputBufferLocked(const sp<Fence>& fence,
Jim Shargobdc46fa2024-07-01 16:46:49 +0000671 const sp<Surface>& from, size_t surfaceId, const sp<GraphicBuffer>& buffer) {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700672 BufferTracker& tracker = *(mBuffers[buffer->getId()]);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700673 // 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
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800675 if (fence != nullptr && fence->isValid()) {
676 tracker.mergeFence(fence);
677 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700678
Emilian Peev6f823722017-12-07 18:05:49 +0000679 auto detachBuffer = mDetachedBuffers.find(buffer->getId());
680 bool detach = (detachBuffer != mDetachedBuffers.end());
681 if (detach) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000682 auto res = from->detachBuffer(buffer);
Emilian Peev6f823722017-12-07 18:05:49 +0000683 if (res == NO_ERROR) {
Jim Shargobdc46fa2024-07-01 16:46:49 +0000684 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 }
Emilian Peev6f823722017-12-07 18:05:49 +0000692 } else {
693 SP_LOGE("%s: detach buffer from output failed (%d)", __FUNCTION__, res);
694 }
695 }
696
Shuzhen Wang0129d522016-10-30 22:43:41 -0700697 // Check to see if this is the last outstanding reference to this buffer
Emilian Peev40ead602017-09-26 15:46:36 +0100698 decrementBufRefCountLocked(buffer->getId(), surfaceId);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700699}
700
Jim Shargobdc46fa2024-07-01 16:46:49 +0000701void Camera3StreamSplitter::handleOutputDequeueStatusLocked(status_t res,
702 const sp<GraphicBuffer>& buffer) {
Emilian Peev703e4992018-02-27 11:42:09 +0000703 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();
Emilian Peev703e4992018-02-27 11:42:09 +0000707 } 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__);
Jim Shargobdc46fa2024-07-01 16:46:49 +0000711 } else if (res != OK || buffer == nullptr) {
Emilian Peev703e4992018-02-27 11:42:09 +0000712 SP_LOGE("%s: dequeue buffer from output failed (%d)", __FUNCTION__, res);
713 }
714}
715
Shuzhen Wang0129d522016-10-30 22:43:41 -0700716void Camera3StreamSplitter::onAbandonedLocked() {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800717 // 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
Jim Shargobdc46fa2024-07-01 16:46:49 +0000730Camera3StreamSplitter::OutputListener::OutputListener(wp<Camera3StreamSplitter> splitter,
731 wp<Surface> output)
732 : mSplitter(splitter), mOutput(output) {}
Shuzhen Wang0129d522016-10-30 22:43:41 -0700733
734void Camera3StreamSplitter::OutputListener::onBufferReleased() {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800735 ATRACE_CALL();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700736 sp<Camera3StreamSplitter> splitter = mSplitter.promote();
Jim Shargobdc46fa2024-07-01 16:46:49 +0000737 sp<Surface> output = mOutput.promote();
Shuzhen Wang0129d522016-10-30 22:43:41 -0700738 if (splitter != nullptr && output != nullptr) {
739 splitter->onBufferReleasedByOutput(output);
740 }
741}
742
Jim Shargobdc46fa2024-07-01 16:46:49 +0000743void Camera3StreamSplitter::OutputListener::onRemoteDied() {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700744 sp<Camera3StreamSplitter> splitter = mSplitter.promote();
745 if (splitter != nullptr) {
746 Mutex::Autolock lock(splitter->mMutex);
747 splitter->onAbandonedLocked();
748 }
749}
750
751Camera3StreamSplitter::BufferTracker::BufferTracker(
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800752 const sp<GraphicBuffer>& buffer, const std::vector<size_t>& requestedSurfaces)
753 : mBuffer(buffer), mMergedFence(Fence::NO_FENCE), mRequestedSurfaces(requestedSurfaces),
754 mReferenceCount(requestedSurfaces.size()) {}
Shuzhen Wang0129d522016-10-30 22:43:41 -0700755
756void Camera3StreamSplitter::BufferTracker::mergeFence(const sp<Fence>& with) {
757 mMergedFence = Fence::merge(String8("Camera3StreamSplitter"), mMergedFence, with);
758}
759
Emilian Peev40ead602017-09-26 15:46:36 +0100760size_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
Shuzhen Wang0129d522016-10-30 22:43:41 -0700768 if (mReferenceCount > 0)
769 --mReferenceCount;
770 return mReferenceCount;
771}
772
773} // namespace android
Jim Shargobdc46fa2024-07-01 16:46:49 +0000774
775#endif // USE_NEW_STREAM_SPLITTER