blob: 96bed0dc7dadfab9a6fe8e57fbb6735e44b9d199 [file] [log] [blame]
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -08001/*
2 * Copyright (C) 2013 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 "Camera3-OutputStream"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080021#include <utils/Log.h>
22#include <utils/Trace.h>
23#include "Camera3OutputStream.h"
24
25#ifndef container_of
26#define container_of(ptr, type, member) \
27 (type *)((char*)(ptr) - offsetof(type, member))
28#endif
29
30namespace android {
31
32namespace camera3 {
33
34Camera3OutputStream::Camera3OutputStream(int id,
35 sp<ANativeWindow> consumer,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -080036 uint32_t width, uint32_t height, int format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070037 android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
Igor Murashkine3a9f962013-05-08 18:03:15 -070038 Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070039 /*maxSize*/0, format, dataSpace, rotation),
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080040 mConsumer(consumer),
Ruchit Sharmae0711f22014-08-18 13:48:24 -040041 mTransform(0),
42 mTraceFirstBuffer(true) {
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080043
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080044 if (mConsumer == NULL) {
45 ALOGE("%s: Consumer is NULL!", __FUNCTION__);
46 mState = STATE_ERROR;
47 }
48}
49
50Camera3OutputStream::Camera3OutputStream(int id,
51 sp<ANativeWindow> consumer,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -080052 uint32_t width, uint32_t height, size_t maxSize, int format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070053 android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
Igor Murashkine3a9f962013-05-08 18:03:15 -070054 Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070055 format, dataSpace, rotation),
Igor Murashkina55b5452013-04-02 16:36:33 -070056 mConsumer(consumer),
Ruchit Sharmae0711f22014-08-18 13:48:24 -040057 mTransform(0),
58 mTraceFirstBuffer(true) {
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080059
60 if (format != HAL_PIXEL_FORMAT_BLOB) {
61 ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__,
62 format);
63 mState = STATE_ERROR;
64 }
65
66 if (mConsumer == NULL) {
67 ALOGE("%s: Consumer is NULL!", __FUNCTION__);
68 mState = STATE_ERROR;
69 }
70}
71
Igor Murashkine3a9f962013-05-08 18:03:15 -070072Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
73 uint32_t width, uint32_t height,
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -080074 int format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070075 android_dataspace dataSpace,
76 camera3_stream_rotation_t rotation) :
Igor Murashkine3a9f962013-05-08 18:03:15 -070077 Camera3IOStreamBase(id, type, width, height,
78 /*maxSize*/0,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070079 format, dataSpace, rotation),
Igor Murashkine3a9f962013-05-08 18:03:15 -070080 mTransform(0) {
81
82 // Subclasses expected to initialize mConsumer themselves
83}
84
85
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080086Camera3OutputStream::~Camera3OutputStream() {
87 disconnectLocked();
88}
89
90status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer) {
91 ATRACE_CALL();
92 status_t res;
93
Igor Murashkine3a9f962013-05-08 18:03:15 -070094 if ((res = getBufferPreconditionCheckLocked()) != OK) {
95 return res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080096 }
97
98 ANativeWindowBuffer* anb;
99 int fenceFd;
100
Zhijun He15ad2472013-10-11 16:21:11 -0700101 /**
102 * Release the lock briefly to avoid deadlock for below scenario:
103 * Thread 1: StreamingProcessor::startStream -> Camera3Stream::isConfiguring().
104 * This thread acquired StreamingProcessor lock and try to lock Camera3Stream lock.
105 * Thread 2: Camera3Stream::returnBuffer->StreamingProcessor::onFrameAvailable().
106 * This thread acquired Camera3Stream lock and bufferQueue lock, and try to lock
107 * StreamingProcessor lock.
108 * Thread 3: Camera3Stream::getBuffer(). This thread acquired Camera3Stream lock
109 * and try to lock bufferQueue lock.
110 * Then there is circular locking dependency.
111 */
112 sp<ANativeWindow> currentConsumer = mConsumer;
113 mLock.unlock();
114
115 res = currentConsumer->dequeueBuffer(currentConsumer.get(), &anb, &fenceFd);
116 mLock.lock();
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800117 if (res != OK) {
118 ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
119 __FUNCTION__, mId, strerror(-res), res);
120 return res;
121 }
122
Igor Murashkine3a9f962013-05-08 18:03:15 -0700123 /**
124 * FenceFD now owned by HAL except in case of error,
125 * in which case we reassign it to acquire_fence
126 */
127 handoutBufferLocked(*buffer, &(anb->handle), /*acquireFence*/fenceFd,
Zhijun He6adc9cc2014-04-15 14:09:55 -0700128 /*releaseFence*/-1, CAMERA3_BUFFER_STATUS_OK, /*output*/true);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800129
130 return OK;
131}
132
133status_t Camera3OutputStream::returnBufferLocked(
134 const camera3_stream_buffer &buffer,
135 nsecs_t timestamp) {
136 ATRACE_CALL();
Igor Murashkine3a9f962013-05-08 18:03:15 -0700137
138 status_t res = returnAnyBufferLocked(buffer, timestamp, /*output*/true);
139
140 if (res != OK) {
141 return res;
142 }
143
144 mLastTimestamp = timestamp;
145
146 return OK;
147}
148
149status_t Camera3OutputStream::returnBufferCheckedLocked(
150 const camera3_stream_buffer &buffer,
151 nsecs_t timestamp,
152 bool output,
153 /*out*/
154 sp<Fence> *releaseFenceOut) {
155
156 (void)output;
157 ALOG_ASSERT(output, "Expected output to be true");
158
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800159 status_t res;
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700160 sp<Fence> releaseFence;
161
162 /**
163 * Fence management - calculate Release Fence
164 */
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800165 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700166 if (buffer.release_fence != -1) {
167 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
168 "there is an error", __FUNCTION__, mId, buffer.release_fence);
169 close(buffer.release_fence);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800170 }
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700171
172 /**
173 * Reassign release fence as the acquire fence in case of error
174 */
175 releaseFence = new Fence(buffer.acquire_fence);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800176 } else {
177 res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
178 if (res != OK) {
179 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
Igor Murashkine3a9f962013-05-08 18:03:15 -0700180 __FUNCTION__, mId, strerror(-res), res);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800181 return res;
182 }
183
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700184 releaseFence = new Fence(buffer.release_fence);
185 }
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800186
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700187 int anwReleaseFence = releaseFence->dup();
188
189 /**
Zhijun He124ccf42013-05-22 14:01:30 -0700190 * Release the lock briefly to avoid deadlock with
191 * StreamingProcessor::startStream -> Camera3Stream::isConfiguring (this
192 * thread will go into StreamingProcessor::onFrameAvailable) during
193 * queueBuffer
194 */
195 sp<ANativeWindow> currentConsumer = mConsumer;
196 mLock.unlock();
197
198 /**
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700199 * Return buffer back to ANativeWindow
200 */
201 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
202 // Cancel buffer
Zhijun He124ccf42013-05-22 14:01:30 -0700203 res = currentConsumer->cancelBuffer(currentConsumer.get(),
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700204 container_of(buffer.buffer, ANativeWindowBuffer, handle),
205 anwReleaseFence);
206 if (res != OK) {
207 ALOGE("%s: Stream %d: Error cancelling buffer to native window:"
Igor Murashkine3a9f962013-05-08 18:03:15 -0700208 " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700209 }
210 } else {
Ruchit Sharmae0711f22014-08-18 13:48:24 -0400211 if (mTraceFirstBuffer && (stream_type == CAMERA3_STREAM_OUTPUT)) {
212 {
213 char traceLog[48];
214 snprintf(traceLog, sizeof(traceLog), "Stream %d: first full buffer\n", mId);
215 ATRACE_NAME(traceLog);
216 }
217 mTraceFirstBuffer = false;
218 }
219
Zhijun He124ccf42013-05-22 14:01:30 -0700220 res = currentConsumer->queueBuffer(currentConsumer.get(),
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800221 container_of(buffer.buffer, ANativeWindowBuffer, handle),
222 anwReleaseFence);
223 if (res != OK) {
Igor Murashkine3a9f962013-05-08 18:03:15 -0700224 ALOGE("%s: Stream %d: Error queueing buffer to native window: "
225 "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800226 }
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800227 }
Zhijun He124ccf42013-05-22 14:01:30 -0700228 mLock.lock();
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700229 if (res != OK) {
230 close(anwReleaseFence);
Igor Murashkin5a1798a2013-05-07 10:58:13 -0700231 }
232
Igor Murashkine3a9f962013-05-08 18:03:15 -0700233 *releaseFenceOut = releaseFence;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800234
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700235 return res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800236}
237
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800238void Camera3OutputStream::dump(int fd, const Vector<String16> &args) const {
239 (void) args;
240 String8 lines;
241 lines.appendFormat(" Stream[%d]: Output\n", mId);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800242 write(fd, lines.string(), lines.size());
Igor Murashkine3a9f962013-05-08 18:03:15 -0700243
244 Camera3IOStreamBase::dump(fd, args);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800245}
246
247status_t Camera3OutputStream::setTransform(int transform) {
248 ATRACE_CALL();
249 Mutex::Autolock l(mLock);
250 return setTransformLocked(transform);
251}
252
253status_t Camera3OutputStream::setTransformLocked(int transform) {
254 status_t res = OK;
255 if (mState == STATE_ERROR) {
256 ALOGE("%s: Stream in error state", __FUNCTION__);
257 return INVALID_OPERATION;
258 }
259
260 mTransform = transform;
261 if (mState == STATE_CONFIGURED) {
262 res = native_window_set_buffers_transform(mConsumer.get(),
263 transform);
264 if (res != OK) {
265 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
266 __FUNCTION__, transform, strerror(-res), res);
267 }
268 }
269 return res;
270}
271
272status_t Camera3OutputStream::configureQueueLocked() {
273 status_t res;
274
Ruchit Sharmae0711f22014-08-18 13:48:24 -0400275 mTraceFirstBuffer = true;
Igor Murashkine3a9f962013-05-08 18:03:15 -0700276 if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) {
277 return res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800278 }
279
Igor Murashkine3a9f962013-05-08 18:03:15 -0700280 ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL");
281
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800282 // Configure consumer-side ANativeWindow interface
283 res = native_window_api_connect(mConsumer.get(),
284 NATIVE_WINDOW_API_CAMERA);
285 if (res != OK) {
286 ALOGE("%s: Unable to connect to native window for stream %d",
287 __FUNCTION__, mId);
288 return res;
289 }
290
291 res = native_window_set_usage(mConsumer.get(), camera3_stream::usage);
292 if (res != OK) {
293 ALOGE("%s: Unable to configure usage %08x for stream %d",
294 __FUNCTION__, camera3_stream::usage, mId);
295 return res;
296 }
297
298 res = native_window_set_scaling_mode(mConsumer.get(),
299 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
300 if (res != OK) {
301 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
302 __FUNCTION__, strerror(-res), res);
303 return res;
304 }
305
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800306 if (mMaxSize == 0) {
307 // For buffers of known size
Eino-Ville Talvala7d70c5e2014-07-24 18:10:23 -0700308 res = native_window_set_buffers_dimensions(mConsumer.get(),
309 camera3_stream::width, camera3_stream::height);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800310 } else {
311 // For buffers with bounded size
Eino-Ville Talvala7d70c5e2014-07-24 18:10:23 -0700312 res = native_window_set_buffers_dimensions(mConsumer.get(),
313 mMaxSize, 1);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800314 }
315 if (res != OK) {
Eino-Ville Talvala7d70c5e2014-07-24 18:10:23 -0700316 ALOGE("%s: Unable to configure stream buffer dimensions"
317 " %d x %d (maxSize %zu) for stream %d",
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800318 __FUNCTION__, camera3_stream::width, camera3_stream::height,
Eino-Ville Talvala7d70c5e2014-07-24 18:10:23 -0700319 mMaxSize, mId);
320 return res;
321 }
322 res = native_window_set_buffers_format(mConsumer.get(),
323 camera3_stream::format);
324 if (res != OK) {
325 ALOGE("%s: Unable to configure stream buffer format %#x for stream %d",
326 __FUNCTION__, camera3_stream::format, mId);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800327 return res;
328 }
329
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800330 res = native_window_set_buffers_data_space(mConsumer.get(),
331 camera3_stream::data_space);
332 if (res != OK) {
333 ALOGE("%s: Unable to configure stream dataspace %#x for stream %d",
334 __FUNCTION__, camera3_stream::data_space, mId);
335 return res;
336 }
337
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800338 int maxConsumerBuffers;
339 res = mConsumer->query(mConsumer.get(),
340 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
341 if (res != OK) {
342 ALOGE("%s: Unable to query consumer undequeued"
343 " buffer count for stream %d", __FUNCTION__, mId);
344 return res;
345 }
346
Alex Ray20cb3002013-05-28 20:18:22 -0700347 ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__,
348 maxConsumerBuffers, camera3_stream::max_buffers);
349 if (camera3_stream::max_buffers == 0) {
Zhijun He2ab500c2013-07-23 08:02:53 -0700350 ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1",
Alex Ray20cb3002013-05-28 20:18:22 -0700351 __FUNCTION__, camera3_stream::max_buffers);
352 return INVALID_OPERATION;
353 }
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800354
355 mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
Zhijun He6adc9cc2014-04-15 14:09:55 -0700356 mHandoutTotalBufferCount = 0;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800357 mFrameCount = 0;
358 mLastTimestamp = 0;
359
360 res = native_window_set_buffer_count(mConsumer.get(),
361 mTotalBufferCount);
362 if (res != OK) {
363 ALOGE("%s: Unable to set buffer count for stream %d",
364 __FUNCTION__, mId);
365 return res;
366 }
367
368 res = native_window_set_buffers_transform(mConsumer.get(),
369 mTransform);
370 if (res != OK) {
371 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
372 __FUNCTION__, mTransform, strerror(-res), res);
373 }
374
375 return OK;
376}
377
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800378status_t Camera3OutputStream::disconnectLocked() {
379 status_t res;
380
Igor Murashkine3a9f962013-05-08 18:03:15 -0700381 if ((res = Camera3IOStreamBase::disconnectLocked()) != OK) {
382 return res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800383 }
384
Igor Murashkine3a9f962013-05-08 18:03:15 -0700385 res = native_window_api_disconnect(mConsumer.get(),
386 NATIVE_WINDOW_API_CAMERA);
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800387
388 /**
389 * This is not an error. if client calling process dies, the window will
390 * also die and all calls to it will return DEAD_OBJECT, thus it's already
391 * "disconnected"
392 */
393 if (res == DEAD_OBJECT) {
394 ALOGW("%s: While disconnecting stream %d from native window, the"
395 " native window died from under us", __FUNCTION__, mId);
396 }
397 else if (res != OK) {
Igor Murashkine3a9f962013-05-08 18:03:15 -0700398 ALOGE("%s: Unable to disconnect stream %d from native window "
399 "(error %d %s)",
400 __FUNCTION__, mId, res, strerror(-res));
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800401 mState = STATE_ERROR;
402 return res;
403 }
404
Igor Murashkine3a9f962013-05-08 18:03:15 -0700405 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG
406 : STATE_CONSTRUCTED;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800407 return OK;
408}
409
Eino-Ville Talvalab2f5b192013-07-30 14:36:03 -0700410status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) {
411
412 status_t res;
413 int32_t u = 0;
414 res = mConsumer->query(mConsumer.get(),
415 NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
416 *usage = u;
417
418 return res;
419}
420
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800421}; // namespace camera3
422
423}; // namespace android