blob: 5a13dded4c6434a19b28f788c7536c8fe13d03aa [file] [log] [blame]
Eino-Ville Talvala8be20f52013-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-ZslStream"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
Igor Murashkinae500e52013-04-22 14:03:54 -070021// This is needed for stdint.h to define INT64_MAX in C++
22#define __STDC_LIMIT_MACROS
23
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -080024#include <utils/Log.h>
25#include <utils/Trace.h>
26#include "Camera3ZslStream.h"
27
Igor Murashkinae500e52013-04-22 14:03:54 -070028#ifndef container_of
29#define container_of(ptr, type, member) \
30 (type *)((char*)(ptr) - offsetof(type, member))
31#endif
32
33typedef android::RingBufferConsumer::PinnedBufferItem PinnedBufferItem;
34
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -080035namespace android {
36
37namespace camera3 {
38
Igor Murashkinae500e52013-04-22 14:03:54 -070039namespace {
40struct TimestampFinder : public RingBufferConsumer::RingBufferComparator {
41 typedef RingBufferConsumer::BufferInfo BufferInfo;
42
43 enum {
44 SELECT_I1 = -1,
45 SELECT_I2 = 1,
46 SELECT_NEITHER = 0,
47 };
48
49 TimestampFinder(nsecs_t timestamp) : mTimestamp(timestamp) {}
50 ~TimestampFinder() {}
51
52 template <typename T>
53 static void swap(T& a, T& b) {
54 T tmp = a;
55 a = b;
56 b = tmp;
57 }
58
59 /**
60 * Try to find the best candidate for a ZSL buffer.
61 * Match priority from best to worst:
62 * 1) Timestamps match.
63 * 2) Timestamp is closest to the needle (and lower).
64 * 3) Timestamp is closest to the needle (and higher).
65 *
66 */
67 virtual int compare(const BufferInfo *i1,
68 const BufferInfo *i2) const {
69 // Try to select non-null object first.
70 if (i1 == NULL) {
71 return SELECT_I2;
72 } else if (i2 == NULL) {
73 return SELECT_I1;
74 }
75
76 // Best result: timestamp is identical
77 if (i1->mTimestamp == mTimestamp) {
78 return SELECT_I1;
79 } else if (i2->mTimestamp == mTimestamp) {
80 return SELECT_I2;
81 }
82
83 const BufferInfo* infoPtrs[2] = {
84 i1,
85 i2
86 };
87 int infoSelectors[2] = {
88 SELECT_I1,
89 SELECT_I2
90 };
91
92 // Order i1,i2 so that always i1.timestamp < i2.timestamp
93 if (i1->mTimestamp > i2->mTimestamp) {
94 swap(infoPtrs[0], infoPtrs[1]);
95 swap(infoSelectors[0], infoSelectors[1]);
96 }
97
98 // Second best: closest (lower) timestamp
99 if (infoPtrs[1]->mTimestamp < mTimestamp) {
100 return infoSelectors[1];
101 } else if (infoPtrs[0]->mTimestamp < mTimestamp) {
102 return infoSelectors[0];
103 }
104
105 // Worst: closest (higher) timestamp
106 return infoSelectors[0];
107
108 /**
109 * The above cases should cover all the possibilities,
110 * and we get an 'empty' result only if the ring buffer
111 * was empty itself
112 */
113 }
114
115 const nsecs_t mTimestamp;
116}; // struct TimestampFinder
117} // namespace anonymous
118
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800119Camera3ZslStream::Camera3ZslStream(int id, uint32_t width, uint32_t height,
120 int depth) :
121 Camera3Stream(id, CAMERA3_STREAM_BIDIRECTIONAL, width, height, 0,
122 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
Igor Murashkinae500e52013-04-22 14:03:54 -0700123 mDepth(depth),
124 mProducer(new RingBufferConsumer(GRALLOC_USAGE_HW_CAMERA_ZSL,
125 depth)),
126 mConsumer(new Surface(mProducer->getProducerInterface())),
127 //mTransform(0),
128 mTotalBufferCount(0),
129 mDequeuedBufferCount(0),
130 mFrameCount(0),
131 mLastTimestamp(0),
132 mCombinedFence(new Fence()) {
133}
134
135Camera3ZslStream::~Camera3ZslStream() {
136 disconnectLocked();
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800137}
138
139status_t Camera3ZslStream::getBufferLocked(camera3_stream_buffer *buffer) {
Igor Murashkinae500e52013-04-22 14:03:54 -0700140 // same as output stream code
141 ATRACE_CALL();
142 status_t res;
143
144 // Allow dequeue during IN_[RE]CONFIG for registration
145 if (mState != STATE_CONFIGURED &&
146 mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) {
147 ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d",
148 __FUNCTION__, mId, mState);
149 return INVALID_OPERATION;
150 }
151
152 // Only limit dequeue amount when fully configured
153 if (mState == STATE_CONFIGURED &&
154 mDequeuedBufferCount == camera3_stream::max_buffers) {
155 ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous"
156 " buffers (%d)", __FUNCTION__, mId,
157 camera3_stream::max_buffers);
158 return INVALID_OPERATION;
159 }
160
161 ANativeWindowBuffer* anb;
162 int fenceFd;
163
164 res = mConsumer->dequeueBuffer(mConsumer.get(), &anb, &fenceFd);
165 if (res != OK) {
166 ALOGE("%s: Stream %d: Can't dequeue next output buffer: %s (%d)",
167 __FUNCTION__, mId, strerror(-res), res);
168 return res;
169 }
170
171 // Handing out a raw pointer to this object. Increment internal refcount.
172 incStrong(this);
173 buffer->stream = this;
174 buffer->buffer = &(anb->handle);
175 buffer->acquire_fence = fenceFd;
176 buffer->release_fence = -1;
177 buffer->status = CAMERA3_BUFFER_STATUS_OK;
178
179 mDequeuedBufferCount++;
180
181 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800182}
183
184status_t Camera3ZslStream::returnBufferLocked(
185 const camera3_stream_buffer &buffer,
186 nsecs_t timestamp) {
Igor Murashkinae500e52013-04-22 14:03:54 -0700187 // same as output stream code
188 ATRACE_CALL();
189 status_t res;
190
191 // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be
192 // decrementing the internal refcount next. In case this is the last ref, we
193 // might get destructed on the decStrong(), so keep an sp around until the
194 // end of the call - otherwise have to sprinkle the decStrong on all exit
195 // points.
196 sp<Camera3ZslStream> keepAlive(this);
197 decStrong(this);
198
199 // Allow buffers to be returned in the error state, to allow for disconnect
200 // and in the in-config states for registration
201 if (mState == STATE_CONSTRUCTED) {
202 ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d",
203 __FUNCTION__, mId, mState);
204 return INVALID_OPERATION;
205 }
206 if (mDequeuedBufferCount == 0) {
207 ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
208 mId);
209 return INVALID_OPERATION;
210 }
Igor Murashkindf2c8bf2013-05-07 10:58:13 -0700211
212 sp<Fence> releaseFence;
213
214 /**
215 * Fence management - calculate Release Fence
216 */
Igor Murashkinae500e52013-04-22 14:03:54 -0700217 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
Igor Murashkindf2c8bf2013-05-07 10:58:13 -0700218 if (buffer.release_fence != -1) {
219 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
220 "there is an error", __FUNCTION__, mId, buffer.release_fence);
221 close(buffer.release_fence);
Igor Murashkinae500e52013-04-22 14:03:54 -0700222 }
Igor Murashkindf2c8bf2013-05-07 10:58:13 -0700223
224 /**
225 * Reassign release fence as the acquire fence in case of error
226 */
227 releaseFence = new Fence(buffer.acquire_fence);
Igor Murashkinae500e52013-04-22 14:03:54 -0700228 } else {
229 res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
230 if (res != OK) {
231 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
232 __FUNCTION__, mId, strerror(-res), res);
233 return res;
234 }
235
Igor Murashkindf2c8bf2013-05-07 10:58:13 -0700236 releaseFence = new Fence(buffer.release_fence);
237 }
Igor Murashkinae500e52013-04-22 14:03:54 -0700238
Igor Murashkindf2c8bf2013-05-07 10:58:13 -0700239 int anwReleaseFence = releaseFence->dup();
240
241 /**
242 * Return buffer back to ANativeWindow
243 */
244 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
245 // Cancel buffer
246 res = mConsumer->cancelBuffer(mConsumer.get(),
247 container_of(buffer.buffer, ANativeWindowBuffer, handle),
248 anwReleaseFence);
249 if (res != OK) {
250 ALOGE("%s: Stream %d: Error cancelling buffer to native window:"
251 " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
252 }
253 } else {
Igor Murashkinae500e52013-04-22 14:03:54 -0700254 res = mConsumer->queueBuffer(mConsumer.get(),
255 container_of(buffer.buffer, ANativeWindowBuffer, handle),
256 anwReleaseFence);
257 if (res != OK) {
258 ALOGE("%s: Stream %d: Error queueing buffer to native window: %s (%d)",
259 __FUNCTION__, mId, strerror(-res), res);
Igor Murashkinae500e52013-04-22 14:03:54 -0700260 }
Igor Murashkinae500e52013-04-22 14:03:54 -0700261 }
262
Igor Murashkindf2c8bf2013-05-07 10:58:13 -0700263 if (res != OK) {
264 close(anwReleaseFence);
265 return res;
266 }
267 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
268
Igor Murashkinae500e52013-04-22 14:03:54 -0700269 mDequeuedBufferCount--;
270 mBufferReturnedSignal.signal();
271 mLastTimestamp = timestamp;
272
273 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800274}
275
276bool Camera3ZslStream::hasOutstandingBuffersLocked() const {
Igor Murashkinae500e52013-04-22 14:03:54 -0700277 // same as output stream
278 nsecs_t signalTime = mCombinedFence->getSignalTime();
279 ALOGV("%s: Stream %d: Has %d outstanding buffers,"
280 " buffer signal time is %lld",
281 __FUNCTION__, mId, mDequeuedBufferCount, signalTime);
282 if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) {
283 return true;
284 }
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800285 return false;
286}
287
288status_t Camera3ZslStream::waitUntilIdle(nsecs_t timeout) {
Igor Murashkinae500e52013-04-22 14:03:54 -0700289 // same as output stream
290 status_t res;
291 {
292 Mutex::Autolock l(mLock);
293 while (mDequeuedBufferCount > 0) {
294 if (timeout != TIMEOUT_NEVER) {
295 nsecs_t startTime = systemTime();
296 res = mBufferReturnedSignal.waitRelative(mLock, timeout);
297 if (res == TIMED_OUT) {
298 return res;
299 } else if (res != OK) {
300 ALOGE("%s: Error waiting for outstanding buffers: %s (%d)",
301 __FUNCTION__, strerror(-res), res);
302 return res;
303 }
304 nsecs_t deltaTime = systemTime() - startTime;
305 if (timeout <= deltaTime) {
306 timeout = 0;
307 } else {
308 timeout -= deltaTime;
309 }
310 } else {
311 res = mBufferReturnedSignal.wait(mLock);
312 if (res != OK) {
313 ALOGE("%s: Error waiting for outstanding buffers: %s (%d)",
314 __FUNCTION__, strerror(-res), res);
315 return res;
316 }
317 }
318 }
319 }
320
321 // No lock
322
323 unsigned int timeoutMs;
324 if (timeout == TIMEOUT_NEVER) {
325 timeoutMs = Fence::TIMEOUT_NEVER;
326 } else if (timeout == 0) {
327 timeoutMs = 0;
328 } else {
329 // Round up to wait at least 1 ms
330 timeoutMs = (timeout + 999999) / 1000000;
331 }
332
333 return mCombinedFence->wait(timeoutMs);
334}
335
336status_t Camera3ZslStream::configureQueueLocked() {
337 status_t res;
338
339 switch (mState) {
340 case STATE_IN_RECONFIG:
341 res = disconnectLocked();
342 if (res != OK) {
343 return res;
344 }
345 break;
346 case STATE_IN_CONFIG:
347 // OK
348 break;
349 default:
350 ALOGE("%s: Bad state: %d", __FUNCTION__, mState);
351 return INVALID_OPERATION;
352 }
353
354 // Configure consumer-side ANativeWindow interface
355 res = native_window_api_connect(mConsumer.get(),
356 NATIVE_WINDOW_API_CAMERA);
357 if (res != OK) {
358 ALOGE("%s: Unable to connect to native window for stream %d",
359 __FUNCTION__, mId);
360 return res;
361 }
362
363 res = native_window_set_usage(mConsumer.get(), camera3_stream::usage);
364 if (res != OK) {
365 ALOGE("%s: Unable to configure usage %08x for stream %d",
366 __FUNCTION__, camera3_stream::usage, mId);
367 return res;
368 }
369
370 res = native_window_set_scaling_mode(mConsumer.get(),
371 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
372 if (res != OK) {
373 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
374 __FUNCTION__, strerror(-res), res);
375 return res;
376 }
377
378 if (mMaxSize == 0) {
379 // For buffers of known size
380 res = native_window_set_buffers_geometry(mConsumer.get(),
381 camera3_stream::width, camera3_stream::height,
382 camera3_stream::format);
383 } else {
384 // For buffers with bounded size
385 res = native_window_set_buffers_geometry(mConsumer.get(),
386 mMaxSize, 1,
387 camera3_stream::format);
388 }
389 if (res != OK) {
390 ALOGE("%s: Unable to configure stream buffer geometry"
391 " %d x %d, format %x for stream %d",
392 __FUNCTION__, camera3_stream::width, camera3_stream::height,
393 camera3_stream::format, mId);
394 return res;
395 }
396
397 int maxConsumerBuffers;
398 res = mConsumer->query(mConsumer.get(),
399 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
400 if (res != OK) {
401 ALOGE("%s: Unable to query consumer undequeued"
402 " buffer count for stream %d", __FUNCTION__, mId);
403 return res;
404 }
405
406 ALOGV("%s: Consumer wants %d buffers", __FUNCTION__,
407 maxConsumerBuffers);
408
409 mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
410 mDequeuedBufferCount = 0;
411 mFrameCount = 0;
412 mLastTimestamp = 0;
413
414 res = native_window_set_buffer_count(mConsumer.get(),
415 mTotalBufferCount);
416 if (res != OK) {
417 ALOGE("%s: Unable to set buffer count for stream %d",
418 __FUNCTION__, mId);
419 return res;
420 }
421
422 return OK;
423}
424
425size_t Camera3ZslStream::getBufferCountLocked() {
426 return mTotalBufferCount;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800427}
428
429status_t Camera3ZslStream::disconnectLocked() {
Igor Murashkinae500e52013-04-22 14:03:54 -0700430 status_t res;
431
432 switch (mState) {
433 case STATE_IN_RECONFIG:
434 case STATE_CONFIGURED:
435 // OK
436 break;
437 default:
438 // No connection, nothing to do
439 return OK;
440 }
441
442 if (mDequeuedBufferCount > 0) {
443 ALOGE("%s: Can't disconnect with %d buffers still dequeued!",
444 __FUNCTION__, mDequeuedBufferCount);
445 return INVALID_OPERATION;
446 }
447
448 res = native_window_api_disconnect(mConsumer.get(), NATIVE_WINDOW_API_CAMERA);
449
450 /**
451 * This is not an error. if client calling process dies, the window will
452 * also die and all calls to it will return DEAD_OBJECT, thus it's already
453 * "disconnected"
454 */
455 if (res == DEAD_OBJECT) {
456 ALOGW("%s: While disconnecting stream %d from native window, the"
457 " native window died from under us", __FUNCTION__, mId);
458 }
459 else if (res != OK) {
460 ALOGE("%s: Unable to disconnect stream %d from native window (error %d %s)",
461 __FUNCTION__, mId, res, strerror(-res));
462 mState = STATE_ERROR;
463 return res;
464 }
465
466 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED;
467 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800468}
469
Igor Murashkinae500e52013-04-22 14:03:54 -0700470status_t Camera3ZslStream::getInputBufferLocked(camera3_stream_buffer *buffer) {
471 ATRACE_CALL();
472
473 // TODO: potentially register from inputBufferLocked
474 // this should be ok, registerBuffersLocked only calls getBuffer for now
475 // register in output mode instead of input mode for ZSL streams.
476 if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) {
477 ALOGE("%s: Stream %d: Buffer registration for input streams"
478 " not implemented (state %d)",
479 __FUNCTION__, mId, mState);
480 return INVALID_OPERATION;
481 }
482
483 // Allow dequeue during IN_[RE]CONFIG for registration
484 if (mState != STATE_CONFIGURED &&
485 mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) {
486 ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d",
487 __FUNCTION__, mId, mState);
488 return INVALID_OPERATION;
489 }
490
491 // Only limit dequeue amount when fully configured
492 if (mState == STATE_CONFIGURED &&
493 mDequeuedBufferCount == camera3_stream::max_buffers) {
494 ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous"
495 " buffers (%d)", __FUNCTION__, mId,
496 camera3_stream::max_buffers);
497 return INVALID_OPERATION;
498 }
499
500 ANativeWindowBuffer* anb;
501 int fenceFd;
502
503 assert(mProducer != 0);
504
505 sp<PinnedBufferItem> bufferItem;
506 {
507 List<sp<RingBufferConsumer::PinnedBufferItem> >::iterator it, end;
508 it = mInputBufferQueue.begin();
509 end = mInputBufferQueue.end();
510
511 // Need to call enqueueInputBufferByTimestamp as a prerequisite
512 if (it == end) {
513 ALOGE("%s: Stream %d: No input buffer was queued",
514 __FUNCTION__, mId);
515 return INVALID_OPERATION;
516 }
517 bufferItem = *it;
518 mInputBufferQueue.erase(it);
519 }
520
521 anb = bufferItem->getBufferItem().mGraphicBuffer->getNativeBuffer();
522 assert(anb != NULL);
523 fenceFd = bufferItem->getBufferItem().mFence->dup();
524
525 /**
526 * FenceFD now owned by HAL except in case of error,
527 * in which case we reassign it to acquire_fence
528 */
529
530 // Handing out a raw pointer to this object. Increment internal refcount.
531 incStrong(this);
532 buffer->stream = this;
533 buffer->buffer = &(anb->handle);
534 buffer->acquire_fence = fenceFd;
535 buffer->release_fence = -1;
536 buffer->status = CAMERA3_BUFFER_STATUS_OK;
537
538 mDequeuedBufferCount++;
539
540 mBuffersInFlight.push_back(bufferItem);
541
542 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800543}
544
Igor Murashkinae500e52013-04-22 14:03:54 -0700545status_t Camera3ZslStream::returnInputBufferLocked(
546 const camera3_stream_buffer &buffer) {
547 ATRACE_CALL();
548
549 // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be
550 // decrementing the internal refcount next. In case this is the last ref, we
551 // might get destructed on the decStrong(), so keep an sp around until the
552 // end of the call - otherwise have to sprinkle the decStrong on all exit
553 // points.
554 sp<Camera3ZslStream> keepAlive(this);
555 decStrong(this);
556
557 // Allow buffers to be returned in the error state, to allow for disconnect
558 // and in the in-config states for registration
559 if (mState == STATE_CONSTRUCTED) {
560 ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d",
561 __FUNCTION__, mId, mState);
562 return INVALID_OPERATION;
563 }
564 if (mDequeuedBufferCount == 0) {
565 ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
566 mId);
567 return INVALID_OPERATION;
568 }
569
570 bool bufferFound = false;
571 sp<PinnedBufferItem> bufferItem;
572 {
573 // Find the buffer we are returning
574 Vector<sp<PinnedBufferItem> >::iterator it, end;
575 for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end();
576 it != end;
577 ++it) {
578
579 const sp<PinnedBufferItem>& tmp = *it;
580 ANativeWindowBuffer *anb =
581 tmp->getBufferItem().mGraphicBuffer->getNativeBuffer();
582 if (anb != NULL && &(anb->handle) == buffer.buffer) {
583 bufferFound = true;
584 bufferItem = tmp;
585 mBuffersInFlight.erase(it);
586 mDequeuedBufferCount--;
587 }
588 }
589 }
590 if (!bufferFound) {
591 ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL",
592 __FUNCTION__, mId);
593 return INVALID_OPERATION;
594 }
595
596 int releaseFenceFd = buffer.release_fence;
597
598 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
599 if (buffer.release_fence != -1) {
600 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
601 "there is an error", __FUNCTION__, mId, buffer.release_fence);
602 close(buffer.release_fence);
603 }
604
605 /**
606 * Reassign release fence as the acquire fence incase of error
607 */
608 releaseFenceFd = buffer.acquire_fence;
609 }
610
611 /**
612 * Unconditionally return buffer to the buffer queue.
613 * - Fwk takes over the release_fence ownership
614 */
615 sp<Fence> releaseFence = new Fence(releaseFenceFd);
616 bufferItem->getBufferItem().mFence = releaseFence;
617 bufferItem.clear(); // dropping last reference unpins buffer
618
619 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
620
621 mBufferReturnedSignal.signal();
622
623 return OK;
624
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800625}
626
627void Camera3ZslStream::dump(int fd, const Vector<String16> &args) const {
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800628 (void) args;
Igor Murashkinae500e52013-04-22 14:03:54 -0700629
630 String8 lines;
631 lines.appendFormat(" Stream[%d]: ZSL\n", mId);
632 lines.appendFormat(" State: %d\n", mState);
633 lines.appendFormat(" Dims: %d x %d, format 0x%x\n",
634 camera3_stream::width, camera3_stream::height,
635 camera3_stream::format);
636 lines.appendFormat(" Usage: %d, max HAL buffers: %d\n",
637 camera3_stream::usage, camera3_stream::max_buffers);
638 lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n",
639 mFrameCount, mLastTimestamp);
640 lines.appendFormat(" Total buffers: %d, currently dequeued: %d\n",
641 mTotalBufferCount, mDequeuedBufferCount);
642 lines.appendFormat(" Input buffers pending: %d, in flight %d\n",
643 mInputBufferQueue.size(), mBuffersInFlight.size());
644 write(fd, lines.string(), lines.size());
645}
646
647status_t Camera3ZslStream::enqueueInputBufferByTimestamp(
648 nsecs_t timestamp,
649 nsecs_t* actualTimestamp) {
650
651 Mutex::Autolock l(mLock);
652
653 TimestampFinder timestampFinder = TimestampFinder(timestamp);
654
655 sp<RingBufferConsumer::PinnedBufferItem> pinnedBuffer =
656 mProducer->pinSelectedBuffer(timestampFinder,
657 /*waitForFence*/false);
658
659 if (pinnedBuffer == 0) {
660 ALOGE("%s: No ZSL buffers were available yet", __FUNCTION__);
661 return NO_BUFFER_AVAILABLE;
662 }
663
664 nsecs_t actual = pinnedBuffer->getBufferItem().mTimestamp;
665
666 if (actual != timestamp) {
667 ALOGW("%s: ZSL buffer candidate search didn't find an exact match --"
668 " requested timestamp = %lld, actual timestamp = %lld",
669 __FUNCTION__, timestamp, actual);
670 }
671
672 mInputBufferQueue.push_back(pinnedBuffer);
673
674 if (actualTimestamp != NULL) {
675 *actualTimestamp = actual;
676 }
677
678 return OK;
679}
680
681status_t Camera3ZslStream::clearInputRingBuffer() {
682 Mutex::Autolock l(mLock);
683
684 mInputBufferQueue.clear();
685
686 return mProducer->clear();
687}
688
689status_t Camera3ZslStream::setTransform(int /*transform*/) {
690 ALOGV("%s: Not implemented", __FUNCTION__);
691 return INVALID_OPERATION;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800692}
693
694}; // namespace camera3
695
696}; // namespace android