blob: 0345d5b27ccdcc426193d876b0a30203dc30adf1 [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 }
211 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
212 res = mConsumer->cancelBuffer(mConsumer.get(),
213 container_of(buffer.buffer, ANativeWindowBuffer, handle),
214 buffer.release_fence);
215 if (res != OK) {
216 ALOGE("%s: Stream %d: Error cancelling buffer to native window:"
217 " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
218 return res;
219 }
220 } else {
221 res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
222 if (res != OK) {
223 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
224 __FUNCTION__, mId, strerror(-res), res);
225 return res;
226 }
227
228 sp<Fence> releaseFence = new Fence(buffer.release_fence);
229 int anwReleaseFence = releaseFence->dup();
230
231 res = mConsumer->queueBuffer(mConsumer.get(),
232 container_of(buffer.buffer, ANativeWindowBuffer, handle),
233 anwReleaseFence);
234 if (res != OK) {
235 ALOGE("%s: Stream %d: Error queueing buffer to native window: %s (%d)",
236 __FUNCTION__, mId, strerror(-res), res);
237 close(anwReleaseFence);
238 return res;
239 }
240
241 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
242 }
243
244 mDequeuedBufferCount--;
245 mBufferReturnedSignal.signal();
246 mLastTimestamp = timestamp;
247
248 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800249}
250
251bool Camera3ZslStream::hasOutstandingBuffersLocked() const {
Igor Murashkinae500e52013-04-22 14:03:54 -0700252 // same as output stream
253 nsecs_t signalTime = mCombinedFence->getSignalTime();
254 ALOGV("%s: Stream %d: Has %d outstanding buffers,"
255 " buffer signal time is %lld",
256 __FUNCTION__, mId, mDequeuedBufferCount, signalTime);
257 if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) {
258 return true;
259 }
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800260 return false;
261}
262
263status_t Camera3ZslStream::waitUntilIdle(nsecs_t timeout) {
Igor Murashkinae500e52013-04-22 14:03:54 -0700264 // same as output stream
265 status_t res;
266 {
267 Mutex::Autolock l(mLock);
268 while (mDequeuedBufferCount > 0) {
269 if (timeout != TIMEOUT_NEVER) {
270 nsecs_t startTime = systemTime();
271 res = mBufferReturnedSignal.waitRelative(mLock, timeout);
272 if (res == TIMED_OUT) {
273 return res;
274 } else if (res != OK) {
275 ALOGE("%s: Error waiting for outstanding buffers: %s (%d)",
276 __FUNCTION__, strerror(-res), res);
277 return res;
278 }
279 nsecs_t deltaTime = systemTime() - startTime;
280 if (timeout <= deltaTime) {
281 timeout = 0;
282 } else {
283 timeout -= deltaTime;
284 }
285 } else {
286 res = mBufferReturnedSignal.wait(mLock);
287 if (res != OK) {
288 ALOGE("%s: Error waiting for outstanding buffers: %s (%d)",
289 __FUNCTION__, strerror(-res), res);
290 return res;
291 }
292 }
293 }
294 }
295
296 // No lock
297
298 unsigned int timeoutMs;
299 if (timeout == TIMEOUT_NEVER) {
300 timeoutMs = Fence::TIMEOUT_NEVER;
301 } else if (timeout == 0) {
302 timeoutMs = 0;
303 } else {
304 // Round up to wait at least 1 ms
305 timeoutMs = (timeout + 999999) / 1000000;
306 }
307
308 return mCombinedFence->wait(timeoutMs);
309}
310
311status_t Camera3ZslStream::configureQueueLocked() {
312 status_t res;
313
314 switch (mState) {
315 case STATE_IN_RECONFIG:
316 res = disconnectLocked();
317 if (res != OK) {
318 return res;
319 }
320 break;
321 case STATE_IN_CONFIG:
322 // OK
323 break;
324 default:
325 ALOGE("%s: Bad state: %d", __FUNCTION__, mState);
326 return INVALID_OPERATION;
327 }
328
329 // Configure consumer-side ANativeWindow interface
330 res = native_window_api_connect(mConsumer.get(),
331 NATIVE_WINDOW_API_CAMERA);
332 if (res != OK) {
333 ALOGE("%s: Unable to connect to native window for stream %d",
334 __FUNCTION__, mId);
335 return res;
336 }
337
338 res = native_window_set_usage(mConsumer.get(), camera3_stream::usage);
339 if (res != OK) {
340 ALOGE("%s: Unable to configure usage %08x for stream %d",
341 __FUNCTION__, camera3_stream::usage, mId);
342 return res;
343 }
344
345 res = native_window_set_scaling_mode(mConsumer.get(),
346 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
347 if (res != OK) {
348 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
349 __FUNCTION__, strerror(-res), res);
350 return res;
351 }
352
353 if (mMaxSize == 0) {
354 // For buffers of known size
355 res = native_window_set_buffers_geometry(mConsumer.get(),
356 camera3_stream::width, camera3_stream::height,
357 camera3_stream::format);
358 } else {
359 // For buffers with bounded size
360 res = native_window_set_buffers_geometry(mConsumer.get(),
361 mMaxSize, 1,
362 camera3_stream::format);
363 }
364 if (res != OK) {
365 ALOGE("%s: Unable to configure stream buffer geometry"
366 " %d x %d, format %x for stream %d",
367 __FUNCTION__, camera3_stream::width, camera3_stream::height,
368 camera3_stream::format, mId);
369 return res;
370 }
371
372 int maxConsumerBuffers;
373 res = mConsumer->query(mConsumer.get(),
374 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
375 if (res != OK) {
376 ALOGE("%s: Unable to query consumer undequeued"
377 " buffer count for stream %d", __FUNCTION__, mId);
378 return res;
379 }
380
381 ALOGV("%s: Consumer wants %d buffers", __FUNCTION__,
382 maxConsumerBuffers);
383
384 mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers;
385 mDequeuedBufferCount = 0;
386 mFrameCount = 0;
387 mLastTimestamp = 0;
388
389 res = native_window_set_buffer_count(mConsumer.get(),
390 mTotalBufferCount);
391 if (res != OK) {
392 ALOGE("%s: Unable to set buffer count for stream %d",
393 __FUNCTION__, mId);
394 return res;
395 }
396
397 return OK;
398}
399
400size_t Camera3ZslStream::getBufferCountLocked() {
401 return mTotalBufferCount;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800402}
403
404status_t Camera3ZslStream::disconnectLocked() {
Igor Murashkinae500e52013-04-22 14:03:54 -0700405 status_t res;
406
407 switch (mState) {
408 case STATE_IN_RECONFIG:
409 case STATE_CONFIGURED:
410 // OK
411 break;
412 default:
413 // No connection, nothing to do
414 return OK;
415 }
416
417 if (mDequeuedBufferCount > 0) {
418 ALOGE("%s: Can't disconnect with %d buffers still dequeued!",
419 __FUNCTION__, mDequeuedBufferCount);
420 return INVALID_OPERATION;
421 }
422
423 res = native_window_api_disconnect(mConsumer.get(), NATIVE_WINDOW_API_CAMERA);
424
425 /**
426 * This is not an error. if client calling process dies, the window will
427 * also die and all calls to it will return DEAD_OBJECT, thus it's already
428 * "disconnected"
429 */
430 if (res == DEAD_OBJECT) {
431 ALOGW("%s: While disconnecting stream %d from native window, the"
432 " native window died from under us", __FUNCTION__, mId);
433 }
434 else if (res != OK) {
435 ALOGE("%s: Unable to disconnect stream %d from native window (error %d %s)",
436 __FUNCTION__, mId, res, strerror(-res));
437 mState = STATE_ERROR;
438 return res;
439 }
440
441 mState = (mState == STATE_IN_RECONFIG) ? STATE_IN_CONFIG : STATE_CONSTRUCTED;
442 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800443}
444
Igor Murashkinae500e52013-04-22 14:03:54 -0700445status_t Camera3ZslStream::getInputBufferLocked(camera3_stream_buffer *buffer) {
446 ATRACE_CALL();
447
448 // TODO: potentially register from inputBufferLocked
449 // this should be ok, registerBuffersLocked only calls getBuffer for now
450 // register in output mode instead of input mode for ZSL streams.
451 if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) {
452 ALOGE("%s: Stream %d: Buffer registration for input streams"
453 " not implemented (state %d)",
454 __FUNCTION__, mId, mState);
455 return INVALID_OPERATION;
456 }
457
458 // Allow dequeue during IN_[RE]CONFIG for registration
459 if (mState != STATE_CONFIGURED &&
460 mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) {
461 ALOGE("%s: Stream %d: Can't get buffers in unconfigured state %d",
462 __FUNCTION__, mId, mState);
463 return INVALID_OPERATION;
464 }
465
466 // Only limit dequeue amount when fully configured
467 if (mState == STATE_CONFIGURED &&
468 mDequeuedBufferCount == camera3_stream::max_buffers) {
469 ALOGE("%s: Stream %d: Already dequeued maximum number of simultaneous"
470 " buffers (%d)", __FUNCTION__, mId,
471 camera3_stream::max_buffers);
472 return INVALID_OPERATION;
473 }
474
475 ANativeWindowBuffer* anb;
476 int fenceFd;
477
478 assert(mProducer != 0);
479
480 sp<PinnedBufferItem> bufferItem;
481 {
482 List<sp<RingBufferConsumer::PinnedBufferItem> >::iterator it, end;
483 it = mInputBufferQueue.begin();
484 end = mInputBufferQueue.end();
485
486 // Need to call enqueueInputBufferByTimestamp as a prerequisite
487 if (it == end) {
488 ALOGE("%s: Stream %d: No input buffer was queued",
489 __FUNCTION__, mId);
490 return INVALID_OPERATION;
491 }
492 bufferItem = *it;
493 mInputBufferQueue.erase(it);
494 }
495
496 anb = bufferItem->getBufferItem().mGraphicBuffer->getNativeBuffer();
497 assert(anb != NULL);
498 fenceFd = bufferItem->getBufferItem().mFence->dup();
499
500 /**
501 * FenceFD now owned by HAL except in case of error,
502 * in which case we reassign it to acquire_fence
503 */
504
505 // Handing out a raw pointer to this object. Increment internal refcount.
506 incStrong(this);
507 buffer->stream = this;
508 buffer->buffer = &(anb->handle);
509 buffer->acquire_fence = fenceFd;
510 buffer->release_fence = -1;
511 buffer->status = CAMERA3_BUFFER_STATUS_OK;
512
513 mDequeuedBufferCount++;
514
515 mBuffersInFlight.push_back(bufferItem);
516
517 return OK;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800518}
519
Igor Murashkinae500e52013-04-22 14:03:54 -0700520status_t Camera3ZslStream::returnInputBufferLocked(
521 const camera3_stream_buffer &buffer) {
522 ATRACE_CALL();
523
524 // returnBuffer may be called from a raw pointer, not a sp<>, and we'll be
525 // decrementing the internal refcount next. In case this is the last ref, we
526 // might get destructed on the decStrong(), so keep an sp around until the
527 // end of the call - otherwise have to sprinkle the decStrong on all exit
528 // points.
529 sp<Camera3ZslStream> keepAlive(this);
530 decStrong(this);
531
532 // Allow buffers to be returned in the error state, to allow for disconnect
533 // and in the in-config states for registration
534 if (mState == STATE_CONSTRUCTED) {
535 ALOGE("%s: Stream %d: Can't return buffers in unconfigured state %d",
536 __FUNCTION__, mId, mState);
537 return INVALID_OPERATION;
538 }
539 if (mDequeuedBufferCount == 0) {
540 ALOGE("%s: Stream %d: No buffers outstanding to return", __FUNCTION__,
541 mId);
542 return INVALID_OPERATION;
543 }
544
545 bool bufferFound = false;
546 sp<PinnedBufferItem> bufferItem;
547 {
548 // Find the buffer we are returning
549 Vector<sp<PinnedBufferItem> >::iterator it, end;
550 for (it = mBuffersInFlight.begin(), end = mBuffersInFlight.end();
551 it != end;
552 ++it) {
553
554 const sp<PinnedBufferItem>& tmp = *it;
555 ANativeWindowBuffer *anb =
556 tmp->getBufferItem().mGraphicBuffer->getNativeBuffer();
557 if (anb != NULL && &(anb->handle) == buffer.buffer) {
558 bufferFound = true;
559 bufferItem = tmp;
560 mBuffersInFlight.erase(it);
561 mDequeuedBufferCount--;
562 }
563 }
564 }
565 if (!bufferFound) {
566 ALOGE("%s: Stream %d: Can't return buffer that wasn't sent to HAL",
567 __FUNCTION__, mId);
568 return INVALID_OPERATION;
569 }
570
571 int releaseFenceFd = buffer.release_fence;
572
573 if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
574 if (buffer.release_fence != -1) {
575 ALOGE("%s: Stream %d: HAL should not set release_fence(%d) when "
576 "there is an error", __FUNCTION__, mId, buffer.release_fence);
577 close(buffer.release_fence);
578 }
579
580 /**
581 * Reassign release fence as the acquire fence incase of error
582 */
583 releaseFenceFd = buffer.acquire_fence;
584 }
585
586 /**
587 * Unconditionally return buffer to the buffer queue.
588 * - Fwk takes over the release_fence ownership
589 */
590 sp<Fence> releaseFence = new Fence(releaseFenceFd);
591 bufferItem->getBufferItem().mFence = releaseFence;
592 bufferItem.clear(); // dropping last reference unpins buffer
593
594 mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
595
596 mBufferReturnedSignal.signal();
597
598 return OK;
599
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800600}
601
602void Camera3ZslStream::dump(int fd, const Vector<String16> &args) const {
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800603 (void) args;
Igor Murashkinae500e52013-04-22 14:03:54 -0700604
605 String8 lines;
606 lines.appendFormat(" Stream[%d]: ZSL\n", mId);
607 lines.appendFormat(" State: %d\n", mState);
608 lines.appendFormat(" Dims: %d x %d, format 0x%x\n",
609 camera3_stream::width, camera3_stream::height,
610 camera3_stream::format);
611 lines.appendFormat(" Usage: %d, max HAL buffers: %d\n",
612 camera3_stream::usage, camera3_stream::max_buffers);
613 lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n",
614 mFrameCount, mLastTimestamp);
615 lines.appendFormat(" Total buffers: %d, currently dequeued: %d\n",
616 mTotalBufferCount, mDequeuedBufferCount);
617 lines.appendFormat(" Input buffers pending: %d, in flight %d\n",
618 mInputBufferQueue.size(), mBuffersInFlight.size());
619 write(fd, lines.string(), lines.size());
620}
621
622status_t Camera3ZslStream::enqueueInputBufferByTimestamp(
623 nsecs_t timestamp,
624 nsecs_t* actualTimestamp) {
625
626 Mutex::Autolock l(mLock);
627
628 TimestampFinder timestampFinder = TimestampFinder(timestamp);
629
630 sp<RingBufferConsumer::PinnedBufferItem> pinnedBuffer =
631 mProducer->pinSelectedBuffer(timestampFinder,
632 /*waitForFence*/false);
633
634 if (pinnedBuffer == 0) {
635 ALOGE("%s: No ZSL buffers were available yet", __FUNCTION__);
636 return NO_BUFFER_AVAILABLE;
637 }
638
639 nsecs_t actual = pinnedBuffer->getBufferItem().mTimestamp;
640
641 if (actual != timestamp) {
642 ALOGW("%s: ZSL buffer candidate search didn't find an exact match --"
643 " requested timestamp = %lld, actual timestamp = %lld",
644 __FUNCTION__, timestamp, actual);
645 }
646
647 mInputBufferQueue.push_back(pinnedBuffer);
648
649 if (actualTimestamp != NULL) {
650 *actualTimestamp = actual;
651 }
652
653 return OK;
654}
655
656status_t Camera3ZslStream::clearInputRingBuffer() {
657 Mutex::Autolock l(mLock);
658
659 mInputBufferQueue.clear();
660
661 return mProducer->clear();
662}
663
664status_t Camera3ZslStream::setTransform(int /*transform*/) {
665 ALOGV("%s: Not implemented", __FUNCTION__);
666 return INVALID_OPERATION;
Eino-Ville Talvala8be20f52013-03-06 16:20:06 -0800667}
668
669}; // namespace camera3
670
671}; // namespace android