blob: 6d2cf9491e19cfebb024a11bc9552ec1f8d25242 [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-Stream"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <utils/Trace.h>
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -070023#include "device3/Camera3Stream.h"
24#include "device3/StatusTracker.h"
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080025
26namespace android {
27
28namespace camera3 {
29
30Camera3Stream::~Camera3Stream() {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -070031 sp<StatusTracker> statusTracker = mStatusTracker.promote();
32 if (statusTracker != 0 && mStatusId != StatusTracker::NO_STATUS_ID) {
33 statusTracker->removeComponent(mStatusId);
34 }
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080035}
36
37Camera3Stream* Camera3Stream::cast(camera3_stream *stream) {
38 return static_cast<Camera3Stream*>(stream);
39}
40
41const Camera3Stream* Camera3Stream::cast(const camera3_stream *stream) {
42 return static_cast<const Camera3Stream*>(stream);
43}
44
45Camera3Stream::Camera3Stream(int id,
46 camera3_stream_type type,
47 uint32_t width, uint32_t height, size_t maxSize, int format) :
48 camera3_stream(),
49 mId(id),
50 mName(String8::format("Camera3Stream[%d]", id)),
51 mMaxSize(maxSize),
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -070052 mState(STATE_CONSTRUCTED),
53 mStatusId(StatusTracker::NO_STATUS_ID) {
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080054
55 camera3_stream::stream_type = type;
56 camera3_stream::width = width;
57 camera3_stream::height = height;
58 camera3_stream::format = format;
59 camera3_stream::usage = 0;
60 camera3_stream::max_buffers = 0;
61 camera3_stream::priv = NULL;
62
63 if (format == HAL_PIXEL_FORMAT_BLOB && maxSize == 0) {
64 ALOGE("%s: BLOB format with size == 0", __FUNCTION__);
65 mState = STATE_ERROR;
66 }
67}
68
69int Camera3Stream::getId() const {
70 return mId;
71}
72
73uint32_t Camera3Stream::getWidth() const {
74 return camera3_stream::width;
75}
76
77uint32_t Camera3Stream::getHeight() const {
78 return camera3_stream::height;
79}
80
81int Camera3Stream::getFormat() const {
82 return camera3_stream::format;
83}
84
85camera3_stream* Camera3Stream::startConfiguration() {
Eino-Ville Talvalab2f5b192013-07-30 14:36:03 -070086 ATRACE_CALL();
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080087 Mutex::Autolock l(mLock);
Eino-Ville Talvalab2f5b192013-07-30 14:36:03 -070088 status_t res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -080089
90 switch (mState) {
91 case STATE_ERROR:
92 ALOGE("%s: In error state", __FUNCTION__);
93 return NULL;
94 case STATE_CONSTRUCTED:
95 // OK
96 break;
97 case STATE_IN_CONFIG:
98 case STATE_IN_RECONFIG:
99 // Can start config again with no trouble; but don't redo
100 // oldUsage/oldMaxBuffers
101 return this;
102 case STATE_CONFIGURED:
103 if (stream_type == CAMERA3_STREAM_INPUT) {
104 ALOGE("%s: Cannot configure an input stream twice",
105 __FUNCTION__);
106 return NULL;
107 } else if (hasOutstandingBuffersLocked()) {
108 ALOGE("%s: Cannot configure stream; has outstanding buffers",
109 __FUNCTION__);
110 return NULL;
111 }
112 break;
113 default:
114 ALOGE("%s: Unknown state %d", __FUNCTION__, mState);
115 return NULL;
116 }
117
Eino-Ville Talvalab2f5b192013-07-30 14:36:03 -0700118 oldUsage = camera3_stream::usage;
119 oldMaxBuffers = camera3_stream::max_buffers;
120
121 res = getEndpointUsage(&(camera3_stream::usage));
122 if (res != OK) {
123 ALOGE("%s: Cannot query consumer endpoint usage!",
124 __FUNCTION__);
125 return NULL;
126 }
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800127
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700128 // Stop tracking if currently doing so
129 if (mStatusId != StatusTracker::NO_STATUS_ID) {
130 sp<StatusTracker> statusTracker = mStatusTracker.promote();
131 if (statusTracker != 0) {
132 statusTracker->removeComponent(mStatusId);
133 }
134 mStatusId = StatusTracker::NO_STATUS_ID;
135 }
136
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800137 if (mState == STATE_CONSTRUCTED) {
138 mState = STATE_IN_CONFIG;
139 } else { // mState == STATE_CONFIGURED
140 mState = STATE_IN_RECONFIG;
141 }
142
143 return this;
144}
145
146bool Camera3Stream::isConfiguring() const {
147 Mutex::Autolock l(mLock);
148 return (mState == STATE_IN_CONFIG) || (mState == STATE_IN_RECONFIG);
149}
150
151status_t Camera3Stream::finishConfiguration(camera3_device *hal3Device) {
Eino-Ville Talvalab2f5b192013-07-30 14:36:03 -0700152 ATRACE_CALL();
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800153 Mutex::Autolock l(mLock);
154 switch (mState) {
155 case STATE_ERROR:
156 ALOGE("%s: In error state", __FUNCTION__);
157 return INVALID_OPERATION;
158 case STATE_IN_CONFIG:
159 case STATE_IN_RECONFIG:
160 // OK
161 break;
162 case STATE_CONSTRUCTED:
163 case STATE_CONFIGURED:
164 ALOGE("%s: Cannot finish configuration that hasn't been started",
165 __FUNCTION__);
166 return INVALID_OPERATION;
167 default:
168 ALOGE("%s: Unknown state", __FUNCTION__);
169 return INVALID_OPERATION;
170 }
171
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700172 // Register for idle tracking
173 sp<StatusTracker> statusTracker = mStatusTracker.promote();
174 if (statusTracker != 0) {
175 mStatusId = statusTracker->addComponent();
176 }
177
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800178 // Check if the stream configuration is unchanged, and skip reallocation if
179 // so. As documented in hardware/camera3.h:configure_streams().
180 if (mState == STATE_IN_RECONFIG &&
Eino-Ville Talvalab2f5b192013-07-30 14:36:03 -0700181 oldUsage == camera3_stream::usage &&
182 oldMaxBuffers == camera3_stream::max_buffers) {
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800183 mState = STATE_CONFIGURED;
184 return OK;
185 }
186
187 status_t res;
188 res = configureQueueLocked();
189 if (res != OK) {
190 ALOGE("%s: Unable to configure stream %d queue: %s (%d)",
191 __FUNCTION__, mId, strerror(-res), res);
192 mState = STATE_ERROR;
193 return res;
194 }
195
196 res = registerBuffersLocked(hal3Device);
197 if (res != OK) {
198 ALOGE("%s: Unable to register stream buffers with HAL: %s (%d)",
199 __FUNCTION__, strerror(-res), res);
200 mState = STATE_ERROR;
201 return res;
202 }
203
204 mState = STATE_CONFIGURED;
205
206 return res;
207}
208
209status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer) {
210 ATRACE_CALL();
211 Mutex::Autolock l(mLock);
Igor Murashkin2fba5842013-04-22 14:03:54 -0700212
213 status_t res = getBufferLocked(buffer);
214 if (res == OK) {
215 fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/true);
216 }
217
218 return res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800219}
220
221status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
222 nsecs_t timestamp) {
223 ATRACE_CALL();
224 Mutex::Autolock l(mLock);
Igor Murashkin2fba5842013-04-22 14:03:54 -0700225
226 status_t res = returnBufferLocked(buffer, timestamp);
227 if (res == OK) {
228 fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true);
229 }
230
231 return res;
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800232}
233
Igor Murashkin5a269fa2013-04-15 14:59:22 -0700234status_t Camera3Stream::getInputBuffer(camera3_stream_buffer *buffer) {
235 ATRACE_CALL();
236 Mutex::Autolock l(mLock);
Igor Murashkin2fba5842013-04-22 14:03:54 -0700237
238 status_t res = getInputBufferLocked(buffer);
239 if (res == OK) {
240 fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false);
241 }
242
243 return res;
Igor Murashkin5a269fa2013-04-15 14:59:22 -0700244}
245
246status_t Camera3Stream::returnInputBuffer(const camera3_stream_buffer &buffer) {
247 ATRACE_CALL();
248 Mutex::Autolock l(mLock);
Igor Murashkin2fba5842013-04-22 14:03:54 -0700249
250 status_t res = returnInputBufferLocked(buffer);
251 if (res == OK) {
252 fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/false);
253 }
254 return res;
255}
256
257void Camera3Stream::fireBufferListenersLocked(
258 const camera3_stream_buffer& /*buffer*/, bool acquired, bool output) {
259 List<wp<Camera3StreamBufferListener> >::iterator it, end;
260
261 // TODO: finish implementing
262
263 Camera3StreamBufferListener::BufferInfo info =
264 Camera3StreamBufferListener::BufferInfo();
265 info.mOutput = output;
266 // TODO: rest of fields
267
268 for (it = mBufferListenerList.begin(), end = mBufferListenerList.end();
269 it != end;
270 ++it) {
271
272 sp<Camera3StreamBufferListener> listener = it->promote();
273 if (listener != 0) {
274 if (acquired) {
275 listener->onBufferAcquired(info);
276 } else {
277 listener->onBufferReleased(info);
278 }
279 }
280 }
Igor Murashkin5a269fa2013-04-15 14:59:22 -0700281}
282
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800283bool Camera3Stream::hasOutstandingBuffers() const {
284 ATRACE_CALL();
285 Mutex::Autolock l(mLock);
286 return hasOutstandingBuffersLocked();
287}
288
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700289status_t Camera3Stream::setStatusTracker(sp<StatusTracker> statusTracker) {
290 Mutex::Autolock l(mLock);
291 sp<StatusTracker> oldTracker = mStatusTracker.promote();
292 if (oldTracker != 0 && mStatusId != StatusTracker::NO_STATUS_ID) {
293 oldTracker->removeComponent(mStatusId);
294 }
295 mStatusId = StatusTracker::NO_STATUS_ID;
296 mStatusTracker = statusTracker;
297
298 return OK;
299}
300
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800301status_t Camera3Stream::disconnect() {
302 ATRACE_CALL();
303 Mutex::Autolock l(mLock);
Igor Murashkine2172be2013-05-28 15:31:39 -0700304 ALOGV("%s: Stream %d: Disconnecting...", __FUNCTION__, mId);
305 status_t res = disconnectLocked();
306
307 if (res == -ENOTCONN) {
308 // "Already disconnected" -- not an error
309 return OK;
310 } else {
311 return res;
312 }
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800313}
314
315status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) {
316 ATRACE_CALL();
317 status_t res;
318
319 size_t bufferCount = getBufferCountLocked();
320
321 Vector<buffer_handle_t*> buffers;
322 buffers.insertAt(NULL, 0, bufferCount);
323
324 camera3_stream_buffer_set bufferSet = camera3_stream_buffer_set();
325 bufferSet.stream = this;
326 bufferSet.num_buffers = bufferCount;
327 bufferSet.buffers = buffers.editArray();
328
329 Vector<camera3_stream_buffer_t> streamBuffers;
330 streamBuffers.insertAt(camera3_stream_buffer_t(), 0, bufferCount);
331
332 // Register all buffers with the HAL. This means getting all the buffers
333 // from the stream, providing them to the HAL with the
334 // register_stream_buffers() method, and then returning them back to the
335 // stream in the error state, since they won't have valid data.
336 //
337 // Only registered buffers can be sent to the HAL.
338
339 uint32_t bufferIdx = 0;
340 for (; bufferIdx < bufferCount; bufferIdx++) {
341 res = getBufferLocked( &streamBuffers.editItemAt(bufferIdx) );
342 if (res != OK) {
343 ALOGE("%s: Unable to get buffer %d for registration with HAL",
344 __FUNCTION__, bufferIdx);
345 // Skip registering, go straight to cleanup
346 break;
347 }
348
349 sp<Fence> fence = new Fence(streamBuffers[bufferIdx].acquire_fence);
Mathias Agopiand7644242013-05-16 18:07:35 -0700350 fence->waitForever("Camera3Stream::registerBuffers");
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800351
352 buffers.editItemAt(bufferIdx) = streamBuffers[bufferIdx].buffer;
353 }
354 if (bufferIdx == bufferCount) {
355 // Got all buffers, register with HAL
356 ALOGV("%s: Registering %d buffers with camera HAL",
357 __FUNCTION__, bufferCount);
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -0700358 ATRACE_BEGIN("camera3->register_stream_buffers");
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800359 res = hal3Device->ops->register_stream_buffers(hal3Device,
360 &bufferSet);
Eino-Ville Talvala17a61ad2013-06-03 16:53:32 -0700361 ATRACE_END();
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800362 }
363
364 // Return all valid buffers to stream, in ERROR state to indicate
365 // they weren't filled.
366 for (size_t i = 0; i < bufferIdx; i++) {
367 streamBuffers.editItemAt(i).release_fence = -1;
368 streamBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
369 returnBufferLocked(streamBuffers[i], 0);
370 }
371
372 return res;
373}
374
Igor Murashkin5a269fa2013-04-15 14:59:22 -0700375status_t Camera3Stream::getBufferLocked(camera3_stream_buffer *) {
376 ALOGE("%s: This type of stream does not support output", __FUNCTION__);
377 return INVALID_OPERATION;
378}
379status_t Camera3Stream::returnBufferLocked(const camera3_stream_buffer &,
380 nsecs_t) {
381 ALOGE("%s: This type of stream does not support output", __FUNCTION__);
382 return INVALID_OPERATION;
383}
384status_t Camera3Stream::getInputBufferLocked(camera3_stream_buffer *) {
385 ALOGE("%s: This type of stream does not support input", __FUNCTION__);
386 return INVALID_OPERATION;
387}
388status_t Camera3Stream::returnInputBufferLocked(
389 const camera3_stream_buffer &) {
390 ALOGE("%s: This type of stream does not support input", __FUNCTION__);
391 return INVALID_OPERATION;
392}
393
Igor Murashkin2fba5842013-04-22 14:03:54 -0700394void Camera3Stream::addBufferListener(
395 wp<Camera3StreamBufferListener> listener) {
396 Mutex::Autolock l(mLock);
397 mBufferListenerList.push_back(listener);
398}
399
400void Camera3Stream::removeBufferListener(
401 const sp<Camera3StreamBufferListener>& listener) {
402 Mutex::Autolock l(mLock);
403
404 bool erased = true;
405 List<wp<Camera3StreamBufferListener> >::iterator it, end;
406 for (it = mBufferListenerList.begin(), end = mBufferListenerList.end();
407 it != end;
408 ) {
409
410 if (*it == listener) {
411 it = mBufferListenerList.erase(it);
412 erased = true;
413 } else {
414 ++it;
415 }
416 }
417
418 if (!erased) {
419 ALOGW("%s: Could not find listener to remove, already removed",
420 __FUNCTION__);
421 }
422}
423
Eino-Ville Talvalafd58f1a2013-03-06 16:20:06 -0800424}; // namespace camera3
425
426}; // namespace android