blob: 2bb9ff7a3fd908cb1cb2ee760286d9dc085fc64f [file] [log] [blame]
Shuzhen Wang0129d522016-10-30 22:43:41 -07001/*
Shuzhen Wangc28189a2017-11-27 23:05:10 -08002 * Copyright (C) 2016-2018 The Android Open Source Project
Shuzhen Wang0129d522016-10-30 22:43:41 -07003 *
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 "Camera3SharedOutputStream.h"
18
19namespace android {
20
21namespace camera3 {
22
Emilian Peev40ead602017-09-26 15:46:36 +010023const size_t Camera3SharedOutputStream::kMaxOutputs;
24
Shuzhen Wang0129d522016-10-30 22:43:41 -070025Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
26 const std::vector<sp<Surface>>& surfaces,
Shuzhen Wang0129d522016-10-30 22:43:41 -070027 uint32_t width, uint32_t height, int format,
Emilian Peev050f5dc2017-05-18 14:43:56 +010028 uint64_t consumerUsage, android_dataspace dataSpace,
Shuzhen Wang0129d522016-10-30 22:43:41 -070029 camera3_stream_rotation_t rotation,
Shuzhen Wangc28189a2017-11-27 23:05:10 -080030 nsecs_t timestampOffset, const String8& physicalCameraId,
31 int setId) :
Shuzhen Wang0129d522016-10-30 22:43:41 -070032 Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
Shuzhen Wangc28189a2017-11-27 23:05:10 -080033 format, dataSpace, rotation, physicalCameraId,
34 consumerUsage, timestampOffset, setId) {
Emilian Peev40ead602017-09-26 15:46:36 +010035 size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
36 if (surfaces.size() > consumerCount) {
37 ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
38 }
39 for (size_t i = 0; i < consumerCount; i++) {
40 mSurfaces[i] = surfaces[i];
41 }
Shuzhen Wang0129d522016-10-30 22:43:41 -070042}
43
44Camera3SharedOutputStream::~Camera3SharedOutputStream() {
45 disconnectLocked();
46}
47
48status_t Camera3SharedOutputStream::connectStreamSplitterLocked() {
49 status_t res = OK;
50
51 mStreamSplitter = new Camera3StreamSplitter();
52
Emilian Peev050f5dc2017-05-18 14:43:56 +010053 uint64_t usage;
Shuzhen Wang0129d522016-10-30 22:43:41 -070054 getEndpointUsage(&usage);
55
Emilian Peev40ead602017-09-26 15:46:36 +010056 std::unordered_map<size_t, sp<Surface>> initialSurfaces;
57 for (size_t i = 0; i < kMaxOutputs; i++) {
58 if (mSurfaces[i] != nullptr) {
59 initialSurfaces.emplace(i, mSurfaces[i]);
60 }
61 }
62
63 android::PixelFormat format = isFormatOverridden() ? getOriginalFormat() : getFormat();
64 res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera3_stream::max_buffers,
65 getWidth(), getHeight(), format, &mConsumer);
Shuzhen Wang0129d522016-10-30 22:43:41 -070066 if (res != OK) {
67 ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
68 __FUNCTION__, strerror(-res), res);
69 return res;
70 }
71
72 return res;
73}
74
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080075status_t Camera3SharedOutputStream::notifyBufferReleased(ANativeWindowBuffer *anwBuffer) {
Shuzhen Wang0129d522016-10-30 22:43:41 -070076 Mutex::Autolock l(mLock);
77 status_t res = OK;
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080078 const sp<GraphicBuffer> buffer(static_cast<GraphicBuffer*>(anwBuffer));
Shuzhen Wang0129d522016-10-30 22:43:41 -070079
80 if (mStreamSplitter != nullptr) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080081 res = mStreamSplitter->notifyBufferReleased(buffer);
Shuzhen Wang0129d522016-10-30 22:43:41 -070082 }
83
84 return res;
85}
86
87bool Camera3SharedOutputStream::isConsumerConfigurationDeferred(size_t surface_id) const {
88 Mutex::Autolock l(mLock);
Emilian Peev40ead602017-09-26 15:46:36 +010089 if (surface_id >= kMaxOutputs) {
90 return true;
91 }
92
93 return (mSurfaces[surface_id] == nullptr);
Shuzhen Wang0129d522016-10-30 22:43:41 -070094}
95
Shuzhen Wang758c2152017-01-10 18:26:18 -080096status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) {
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -080097 Mutex::Autolock l(mLock);
Shuzhen Wang758c2152017-01-10 18:26:18 -080098 if (surfaces.size() == 0) {
99 ALOGE("%s: it's illegal to set zero consumer surfaces!", __FUNCTION__);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700100 return INVALID_OPERATION;
101 }
102
Shuzhen Wang758c2152017-01-10 18:26:18 -0800103 status_t ret = OK;
104 for (auto& surface : surfaces) {
105 if (surface == nullptr) {
106 ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
107 return INVALID_OPERATION;
108 }
109
Emilian Peev40ead602017-09-26 15:46:36 +0100110 ssize_t id = getNextSurfaceIdLocked();
111 if (id < 0) {
112 ALOGE("%s: No surface ids available!", __func__);
113 return NO_MEMORY;
114 }
115
116 mSurfaces[id] = surface;
Shuzhen Wang758c2152017-01-10 18:26:18 -0800117
118 // Only call addOutput if the splitter has been connected.
119 if (mStreamSplitter != nullptr) {
Emilian Peev40ead602017-09-26 15:46:36 +0100120 ret = mStreamSplitter->addOutput(id, surface);
Shuzhen Wang758c2152017-01-10 18:26:18 -0800121 if (ret != OK) {
122 ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret);
123 return ret;
124
125 }
126 }
Shuzhen Wang0129d522016-10-30 22:43:41 -0700127 }
Shuzhen Wang758c2152017-01-10 18:26:18 -0800128 return ret;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700129}
130
Shuzhen Wangbee0f0a2017-01-24 14:51:37 -0800131status_t Camera3SharedOutputStream::getBufferLocked(camera3_stream_buffer *buffer,
132 const std::vector<size_t>& surface_ids) {
133 ANativeWindowBuffer* anb;
134 int fenceFd = -1;
135
136 status_t res;
137 res = getBufferLockedCommon(&anb, &fenceFd);
138 if (res != OK) {
139 return res;
140 }
141
142 // Attach the buffer to the splitter output queues. This could block if
143 // the output queue doesn't have any empty slot. So unlock during the course
144 // of attachBufferToOutputs.
145 sp<Camera3StreamSplitter> splitter = mStreamSplitter;
146 mLock.unlock();
147 res = splitter->attachBufferToOutputs(anb, surface_ids);
148 mLock.lock();
149 if (res != OK) {
150 ALOGE("%s: Stream %d: Cannot attach stream splitter buffer to outputs: %s (%d)",
151 __FUNCTION__, mId, strerror(-res), res);
152 // Only transition to STATE_ABANDONED from STATE_CONFIGURED. (If it is STATE_PREPARING,
153 // let prepareNextBuffer handle the error.)
154 if (res == NO_INIT && mState == STATE_CONFIGURED) {
155 mState = STATE_ABANDONED;
156 }
157
158 return res;
159 }
160
161 /**
162 * FenceFD now owned by HAL except in case of error,
163 * in which case we reassign it to acquire_fence
164 */
165 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
166 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
167
168 return OK;
169}
170
171status_t Camera3SharedOutputStream::queueBufferToConsumer(sp<ANativeWindow>& consumer,
172 ANativeWindowBuffer* buffer, int anwReleaseFence) {
173 status_t res = consumer->queueBuffer(consumer.get(), buffer, anwReleaseFence);
174
175 // After queuing buffer to the internal consumer queue, check whether the buffer is
176 // successfully queued to the output queues.
177 if (res == OK) {
178 res = mStreamSplitter->getOnFrameAvailableResult();
179 if (res != OK) {
180 ALOGE("%s: getOnFrameAvailable returns %d", __FUNCTION__, res);
181 }
182 } else {
183 ALOGE("%s: queueBufer failed %d", __FUNCTION__, res);
184 }
185
186 return res;
187}
188
Shuzhen Wang0129d522016-10-30 22:43:41 -0700189status_t Camera3SharedOutputStream::configureQueueLocked() {
190 status_t res;
191
192 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
193 return res;
194 }
195
196 res = connectStreamSplitterLocked();
197 if (res != OK) {
198 ALOGE("Cannot connect to stream splitter: %s(%d)", strerror(-res), res);
199 return res;
200 }
201
202 res = configureConsumerQueueLocked();
203 if (res != OK) {
204 ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res);
205 return res;
206 }
207
208 return OK;
209}
210
211status_t Camera3SharedOutputStream::disconnectLocked() {
212 status_t res;
213 res = Camera3OutputStream::disconnectLocked();
214
215 if (mStreamSplitter != nullptr) {
216 mStreamSplitter->disconnect();
217 }
218
219 return res;
220}
221
Emilian Peev050f5dc2017-05-18 14:43:56 +0100222status_t Camera3SharedOutputStream::getEndpointUsage(uint64_t *usage) const {
Shuzhen Wang0129d522016-10-30 22:43:41 -0700223
Shuzhen Wang758c2152017-01-10 18:26:18 -0800224 status_t res = OK;
Emilian Peev050f5dc2017-05-18 14:43:56 +0100225 uint64_t u = 0;
Shuzhen Wang0129d522016-10-30 22:43:41 -0700226
227 if (mConsumer == nullptr) {
228 // Called before shared buffer queue is constructed.
229 *usage = getPresetConsumerUsage();
230
Emilian Peev40ead602017-09-26 15:46:36 +0100231 for (size_t id = 0; id < kMaxOutputs; id++) {
232 if (mSurfaces[id] != nullptr) {
233 res = getEndpointUsageForSurface(&u, mSurfaces[id]);
Shuzhen Wang0129d522016-10-30 22:43:41 -0700234 *usage |= u;
235 }
236 }
237 } else {
238 // Called after shared buffer queue is constructed.
239 res = getEndpointUsageForSurface(&u, mConsumer);
240 *usage |= u;
241 }
242
243 return res;
244}
245
Emilian Peev40ead602017-09-26 15:46:36 +0100246ssize_t Camera3SharedOutputStream::getNextSurfaceIdLocked() {
247 ssize_t id = -1;
248 for (size_t i = 0; i < kMaxOutputs; i++) {
249 if (mSurfaces[i] == nullptr) {
250 id = i;
251 break;
252 }
253 }
254
255 return id;
256}
257
258ssize_t Camera3SharedOutputStream::getSurfaceId(const sp<Surface> &surface) {
259 Mutex::Autolock l(mLock);
260 ssize_t id = -1;
261 for (size_t i = 0; i < kMaxOutputs; i++) {
262 if (mSurfaces[i] == surface) {
263 id = i;
264 break;
265 }
266 }
267
268 return id;
269}
270
271status_t Camera3SharedOutputStream::revertPartialUpdateLocked(
272 const KeyedVector<sp<Surface>, size_t> &removedSurfaces,
273 const KeyedVector<sp<Surface>, size_t> &attachedSurfaces) {
274 status_t ret = OK;
275
276 for (size_t i = 0; i < attachedSurfaces.size(); i++) {
277 size_t index = attachedSurfaces.valueAt(i);
278 if (mStreamSplitter != nullptr) {
279 ret = mStreamSplitter->removeOutput(index);
280 if (ret != OK) {
281 return UNKNOWN_ERROR;
282 }
283 }
284 mSurfaces[index] = nullptr;
285 }
286
287 for (size_t i = 0; i < removedSurfaces.size(); i++) {
288 size_t index = removedSurfaces.valueAt(i);
289 if (mStreamSplitter != nullptr) {
290 ret = mStreamSplitter->addOutput(index, removedSurfaces.keyAt(i));
291 if (ret != OK) {
292 return UNKNOWN_ERROR;
293 }
294 }
295 mSurfaces[index] = removedSurfaces.keyAt(i);
296 }
297
298 return ret;
299}
300
301status_t Camera3SharedOutputStream::updateStream(const std::vector<sp<Surface>> &outputSurfaces,
302 const std::vector<OutputStreamInfo> &outputInfo,
303 const std::vector<size_t> &removedSurfaceIds,
304 KeyedVector<sp<Surface>, size_t> *outputMap) {
305 status_t ret = OK;
306 Mutex::Autolock l(mLock);
307
308 if ((outputMap == nullptr) || (outputInfo.size() != outputSurfaces.size()) ||
309 (outputSurfaces.size() > kMaxOutputs)) {
310 return BAD_VALUE;
311 }
312
313 uint64_t usage;
314 getEndpointUsage(&usage);
315 KeyedVector<sp<Surface>, size_t> removedSurfaces;
316 //Check whether the new surfaces are compatible.
317 for (const auto &infoIt : outputInfo) {
318 bool imgReaderUsage = (infoIt.consumerUsage & GRALLOC_USAGE_SW_READ_OFTEN) ? true : false;
319 bool sizeMismatch = ((static_cast<uint32_t>(infoIt.width) != getWidth()) ||
320 (static_cast<uint32_t> (infoIt.height) != getHeight())) ?
321 true : false;
322 if ((imgReaderUsage && sizeMismatch) ||
323 (infoIt.format != getOriginalFormat() && infoIt.format != getFormat()) ||
324 (infoIt.dataSpace != getDataSpace() &&
325 infoIt.dataSpace != getOriginalDataSpace())) {
326 ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x "
327 " don't match source stream format: 0x%x dataSpace: 0x%x", __FUNCTION__,
328 infoIt.format, infoIt.dataSpace, getFormat(), getDataSpace());
329 return BAD_VALUE;
330 }
331 }
332
333 //First remove all absent outputs
334 for (const auto &it : removedSurfaceIds) {
335 if (mStreamSplitter != nullptr) {
336 ret = mStreamSplitter->removeOutput(it);
337 if (ret != OK) {
338 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
339 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
340 if (res != OK) {
341 return res;
342 }
343 return ret;
344
345 }
346 }
347 mSurfaces[it] = nullptr;
348 removedSurfaces.add(mSurfaces[it], it);
349 }
350
351 //Next add the new outputs
352 for (const auto &it : outputSurfaces) {
353 ssize_t surfaceId = getNextSurfaceIdLocked();
354 if (surfaceId < 0) {
355 ALOGE("%s: No more available output slots!", __FUNCTION__);
356 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
357 if (res != OK) {
358 return res;
359 }
360 return NO_MEMORY;
361 }
362 if (mStreamSplitter != nullptr) {
363 ret = mStreamSplitter->addOutput(surfaceId, it);
364 if (ret != OK) {
365 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
366 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
367 if (res != OK) {
368 return res;
369 }
370 return ret;
371 }
372 }
373 mSurfaces[surfaceId] = it;
374 outputMap->add(it, surfaceId);
375 }
376
377 return ret;
378}
379
Shuzhen Wang0129d522016-10-30 22:43:41 -0700380} // namespace camera3
381
382} // namespace android