Camera2Device.cpp revision 2c08dc66c2980a50e90befe84f836b7ebf17fe94
1/*
2 * Copyright (C) 2012 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 "Camera2Device"
18//#define LOG_NDEBUG 0
19//#define LOG_NNDEBUG 0  // Per-frame verbose logging
20
21#ifdef LOG_NNDEBUG
22#define ALOGVV(...) ALOGV(__VA_ARGS__)
23#else
24#define ALOGVV(...) ((void)0)
25#endif
26
27#include <utils/Log.h>
28#include "Camera2Device.h"
29
30namespace android {
31
32Camera2Device::Camera2Device(int id):
33        mId(id),
34        mDevice(NULL)
35{
36    ALOGV("%s: E", __FUNCTION__);
37}
38
39Camera2Device::~Camera2Device()
40{
41    ALOGV("%s: E", __FUNCTION__);
42    if (mDevice) {
43        status_t res;
44        res = mDevice->common.close(&mDevice->common);
45        if (res != OK) {
46            ALOGE("%s: Could not close camera %d: %s (%d)",
47                    __FUNCTION__,
48                    mId, strerror(-res), res);
49        }
50        mDevice = NULL;
51    }
52}
53
54status_t Camera2Device::initialize(camera_module_t *module)
55{
56    ALOGV("%s: E", __FUNCTION__);
57
58    status_t res;
59    char name[10];
60    snprintf(name, sizeof(name), "%d", mId);
61
62    res = module->common.methods->open(&module->common, name,
63            reinterpret_cast<hw_device_t**>(&mDevice));
64
65    if (res != OK) {
66        ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
67                mId, strerror(-res), res);
68        return res;
69    }
70
71    if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
72        ALOGE("%s: Could not open camera %d: "
73                "Camera device is not version %x, reports %x instead",
74                __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
75                mDevice->common.version);
76        return BAD_VALUE;
77    }
78
79    camera_info info;
80    res = module->get_camera_info(mId, &info);
81    if (res != OK ) return res;
82
83    if (info.device_version != mDevice->common.version) {
84        ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
85                " and device version (%x).", __FUNCTION__,
86                mDevice->common.version, info.device_version);
87        return BAD_VALUE;
88    }
89
90    mDeviceInfo = info.static_camera_characteristics;
91
92    res = mRequestQueue.setConsumerDevice(mDevice);
93    if (res != OK) {
94        ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
95                __FUNCTION__, mId, strerror(-res), res);
96        return res;
97    }
98    res = mFrameQueue.setProducerDevice(mDevice);
99    if (res != OK) {
100        ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
101                __FUNCTION__, mId, strerror(-res), res);
102        return res;
103    }
104
105    res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
106    if (res != OK ) {
107        ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
108                __FUNCTION__, mId, strerror(-res), res);
109        return res;
110    }
111
112    return OK;
113}
114
115status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
116
117    String8 result;
118
119    result.appendFormat("  Camera2Device[%d] dump:\n", mId);
120
121    result.appendFormat("    Static camera information metadata:\n");
122    write(fd, result.string(), result.size());
123    dump_camera_metadata(mDeviceInfo, fd, 2);
124
125    result = "    Request queue contents:\n";
126    write(fd, result.string(), result.size());
127    mRequestQueue.dump(fd, args);
128
129    result = "    Frame queue contents:\n";
130    write(fd, result.string(), result.size());
131    mFrameQueue.dump(fd, args);
132
133    result = "    Active streams:\n";
134    write(fd, result.string(), result.size());
135    for (StreamList::iterator s = mStreams.begin(); s != mStreams.end(); s++) {
136        (*s)->dump(fd, args);
137    }
138
139    result = "    HAL device dump:\n";
140    write(fd, result.string(), result.size());
141
142    status_t res;
143    res = mDevice->ops->dump(mDevice, fd);
144
145    return res;
146}
147
148camera_metadata_t *Camera2Device::info() {
149    ALOGV("%s: E", __FUNCTION__);
150
151    return mDeviceInfo;
152}
153
154status_t Camera2Device::capture(camera_metadata_t* request) {
155    ALOGV("%s: E", __FUNCTION__);
156
157    mRequestQueue.enqueue(request);
158    return OK;
159}
160
161
162status_t Camera2Device::setStreamingRequest(camera_metadata_t* request) {
163    ALOGV("%s: E", __FUNCTION__);
164
165    mRequestQueue.setStreamSlot(request);
166    return OK;
167}
168
169status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
170        uint32_t width, uint32_t height, int format, size_t size, int *id) {
171    status_t res;
172    ALOGV("%s: E", __FUNCTION__);
173
174    sp<StreamAdapter> stream = new StreamAdapter(mDevice);
175
176    res = stream->connectToDevice(consumer, width, height, format, size);
177    if (res != OK) {
178        ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
179                "%s (%d)",
180                __FUNCTION__, mId, width, height, format, strerror(-res), res);
181        return res;
182    }
183
184    *id = stream->getId();
185
186    mStreams.push_back(stream);
187    return OK;
188}
189
190status_t Camera2Device::getStreamInfo(int id,
191        uint32_t *width, uint32_t *height, uint32_t *format) {
192    ALOGV("%s: E", __FUNCTION__);
193    bool found = false;
194    StreamList::iterator streamI;
195    for (streamI = mStreams.begin();
196         streamI != mStreams.end(); streamI++) {
197        if ((*streamI)->getId() == id) {
198            found = true;
199            break;
200        }
201    }
202    if (!found) {
203        ALOGE("%s: Camera %d: Stream %d does not exist",
204                __FUNCTION__, mId, id);
205        return BAD_VALUE;
206    }
207
208    if (width) *width = (*streamI)->getWidth();
209    if (height) *height = (*streamI)->getHeight();
210    if (format) *format = (*streamI)->getFormat();
211
212    return OK;
213}
214
215status_t Camera2Device::setStreamTransform(int id,
216        int transform) {
217    ALOGV("%s: E", __FUNCTION__);
218    bool found = false;
219    StreamList::iterator streamI;
220    for (streamI = mStreams.begin();
221         streamI != mStreams.end(); streamI++) {
222        if ((*streamI)->getId() == id) {
223            found = true;
224            break;
225        }
226    }
227    if (!found) {
228        ALOGE("%s: Camera %d: Stream %d does not exist",
229                __FUNCTION__, mId, id);
230        return BAD_VALUE;
231    }
232
233    return (*streamI)->setTransform(transform);
234}
235
236status_t Camera2Device::deleteStream(int id) {
237    ALOGV("%s: E", __FUNCTION__);
238    bool found = false;
239    for (StreamList::iterator streamI = mStreams.begin();
240         streamI != mStreams.end(); streamI++) {
241        if ((*streamI)->getId() == id) {
242            status_t res = (*streamI)->disconnect();
243            if (res != OK) {
244                ALOGE("%s: Unable to disconnect stream %d from HAL device: "
245                        "%s (%d)", __FUNCTION__, id, strerror(-res), res);
246                return res;
247            }
248            mStreams.erase(streamI);
249            found = true;
250            break;
251        }
252    }
253    if (!found) {
254        ALOGE("%s: Camera %d: Unable to find stream %d to delete",
255                __FUNCTION__, mId, id);
256        return BAD_VALUE;
257    }
258    return OK;
259}
260
261status_t Camera2Device::createDefaultRequest(int templateId,
262        camera_metadata_t **request) {
263    ALOGV("%s: E", __FUNCTION__);
264    return mDevice->ops->construct_default_request(
265        mDevice, templateId, request);
266}
267
268status_t Camera2Device::waitUntilDrained() {
269    static const uint32_t kSleepTime = 50000; // 50 ms
270    static const uint32_t kMaxSleepTime = 10000000; // 10 s
271
272    if (mRequestQueue.getBufferCount() ==
273            CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
274
275    // TODO: Set up notifications from HAL, instead of sleeping here
276    uint32_t totalTime = 0;
277    while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
278        usleep(kSleepTime);
279        totalTime += kSleepTime;
280        if (totalTime > kMaxSleepTime) {
281            ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
282                    totalTime);
283            return TIMED_OUT;
284        }
285    }
286    return OK;
287}
288
289/**
290 * Camera2Device::MetadataQueue
291 */
292
293Camera2Device::MetadataQueue::MetadataQueue():
294            mDevice(NULL),
295            mFrameCount(0),
296            mCount(0),
297            mStreamSlotCount(0),
298            mSignalConsumer(true)
299{
300    camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
301    camera2_request_queue_src_ops::request_count = consumer_buffer_count;
302    camera2_request_queue_src_ops::free_request = consumer_free;
303
304    camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
305    camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
306    camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
307}
308
309Camera2Device::MetadataQueue::~MetadataQueue() {
310    Mutex::Autolock l(mMutex);
311    freeBuffers(mEntries.begin(), mEntries.end());
312    freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
313}
314
315// Connect to camera2 HAL as consumer (input requests/reprocessing)
316status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
317    status_t res;
318    res = d->ops->set_request_queue_src_ops(d,
319            this);
320    if (res != OK) return res;
321    mDevice = d;
322    return OK;
323}
324
325status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
326    status_t res;
327    res = d->ops->set_frame_queue_dst_ops(d,
328            this);
329    return res;
330}
331
332// Real interfaces
333status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
334    ALOGVV("%s: E", __FUNCTION__);
335    Mutex::Autolock l(mMutex);
336
337    mCount++;
338    mEntries.push_back(buf);
339
340    return signalConsumerLocked();
341}
342
343int Camera2Device::MetadataQueue::getBufferCount() {
344    Mutex::Autolock l(mMutex);
345    if (mStreamSlotCount > 0) {
346        return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
347    }
348    return mCount;
349}
350
351status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
352        bool incrementCount)
353{
354    ALOGVV("%s: E", __FUNCTION__);
355    status_t res;
356    Mutex::Autolock l(mMutex);
357
358    if (mCount == 0) {
359        if (mStreamSlotCount == 0) {
360            ALOGVV("%s: Empty", __FUNCTION__);
361            *buf = NULL;
362            mSignalConsumer = true;
363            return OK;
364        }
365        ALOGVV("%s: Streaming %d frames to queue", __FUNCTION__,
366              mStreamSlotCount);
367
368        for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
369                slotEntry != mStreamSlot.end();
370                slotEntry++ ) {
371            size_t entries = get_camera_metadata_entry_count(*slotEntry);
372            size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
373
374            camera_metadata_t *copy =
375                    allocate_camera_metadata(entries, dataBytes);
376            append_camera_metadata(copy, *slotEntry);
377            mEntries.push_back(copy);
378        }
379        mCount = mStreamSlotCount;
380    }
381    ALOGVV("MetadataQueue: deque (%d buffers)", mCount);
382    camera_metadata_t *b = *(mEntries.begin());
383    mEntries.erase(mEntries.begin());
384
385    if (incrementCount) {
386        camera_metadata_entry_t frameCount;
387        res = find_camera_metadata_entry(b,
388                ANDROID_REQUEST_FRAME_COUNT,
389                &frameCount);
390        if (res != OK) {
391            ALOGE("%s: Unable to add frame count: %s (%d)",
392                    __FUNCTION__, strerror(-res), res);
393        } else {
394            *frameCount.data.i32 = mFrameCount;
395        }
396        mFrameCount++;
397    }
398
399    *buf = b;
400    mCount--;
401
402    return OK;
403}
404
405status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
406{
407    Mutex::Autolock l(mMutex);
408    status_t res;
409    while (mCount == 0) {
410        res = notEmpty.waitRelative(mMutex,timeout);
411        if (res != OK) return res;
412    }
413    return OK;
414}
415
416status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
417{
418    ALOGV("%s: E", __FUNCTION__);
419    Mutex::Autolock l(mMutex);
420    if (buf == NULL) {
421        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
422        mStreamSlotCount = 0;
423        return OK;
424    }
425    camera_metadata_t *buf2 = clone_camera_metadata(buf);
426    if (!buf2) {
427        ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
428        return NO_MEMORY;
429    }
430
431    if (mStreamSlotCount > 1) {
432        List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
433        freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
434        mStreamSlotCount = 1;
435    }
436    if (mStreamSlotCount == 1) {
437        free_camera_metadata( *(mStreamSlot.begin()) );
438        *(mStreamSlot.begin()) = buf2;
439    } else {
440        mStreamSlot.push_front(buf2);
441        mStreamSlotCount = 1;
442    }
443    return signalConsumerLocked();
444}
445
446status_t Camera2Device::MetadataQueue::setStreamSlot(
447        const List<camera_metadata_t*> &bufs)
448{
449    ALOGV("%s: E", __FUNCTION__);
450    Mutex::Autolock l(mMutex);
451    status_t res;
452
453    if (mStreamSlotCount > 0) {
454        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
455    }
456    mStreamSlotCount = 0;
457    for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
458         r != bufs.end(); r++) {
459        camera_metadata_t *r2 = clone_camera_metadata(*r);
460        if (!r2) {
461            ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
462            return NO_MEMORY;
463        }
464        mStreamSlot.push_back(r2);
465        mStreamSlotCount++;
466    }
467    return signalConsumerLocked();
468}
469
470status_t Camera2Device::MetadataQueue::dump(int fd,
471        const Vector<String16>& args) {
472    String8 result;
473    status_t notLocked;
474    notLocked = mMutex.tryLock();
475    if (notLocked) {
476        result.append("    (Unable to lock queue mutex)\n");
477    }
478    result.appendFormat("      Current frame number: %d\n", mFrameCount);
479    if (mStreamSlotCount == 0) {
480        result.append("      Stream slot: Empty\n");
481        write(fd, result.string(), result.size());
482    } else {
483        result.appendFormat("      Stream slot: %d entries\n",
484                mStreamSlot.size());
485        int i = 0;
486        for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
487             r != mStreamSlot.end(); r++) {
488            result = String8::format("       Stream slot buffer %d:\n", i);
489            write(fd, result.string(), result.size());
490            dump_camera_metadata(*r, fd, 2);
491            i++;
492        }
493    }
494    if (mEntries.size() == 0) {
495        result = "      Main queue is empty\n";
496        write(fd, result.string(), result.size());
497    } else {
498        result = String8::format("      Main queue has %d entries:\n",
499                mEntries.size());
500        int i = 0;
501        for (List<camera_metadata_t*>::iterator r = mEntries.begin();
502             r != mEntries.end(); r++) {
503            result = String8::format("       Queue entry %d:\n", i);
504            write(fd, result.string(), result.size());
505            dump_camera_metadata(*r, fd, 2);
506            i++;
507        }
508    }
509
510    if (notLocked == 0) {
511        mMutex.unlock();
512    }
513
514    return OK;
515}
516
517status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
518    status_t res = OK;
519    notEmpty.signal();
520    if (mSignalConsumer && mDevice != NULL) {
521        mSignalConsumer = false;
522
523        mMutex.unlock();
524        ALOGV("%s: Signaling consumer", __FUNCTION__);
525        res = mDevice->ops->notify_request_queue_not_empty(mDevice);
526        mMutex.lock();
527    }
528    return res;
529}
530
531status_t Camera2Device::MetadataQueue::freeBuffers(
532        List<camera_metadata_t*>::iterator start,
533        List<camera_metadata_t*>::iterator end)
534{
535    while (start != end) {
536        free_camera_metadata(*start);
537        start = mStreamSlot.erase(start);
538    }
539    return OK;
540}
541
542Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
543        const camera2_request_queue_src_ops_t *q)
544{
545    const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
546    return const_cast<MetadataQueue*>(cmq);
547}
548
549Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
550        const camera2_frame_queue_dst_ops_t *q)
551{
552    const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
553    return const_cast<MetadataQueue*>(cmq);
554}
555
556int Camera2Device::MetadataQueue::consumer_buffer_count(
557        const camera2_request_queue_src_ops_t *q)
558{
559    MetadataQueue *queue = getInstance(q);
560    return queue->getBufferCount();
561}
562
563int Camera2Device::MetadataQueue::consumer_dequeue(
564        const camera2_request_queue_src_ops_t *q,
565        camera_metadata_t **buffer)
566{
567    MetadataQueue *queue = getInstance(q);
568    return queue->dequeue(buffer, true);
569}
570
571int Camera2Device::MetadataQueue::consumer_free(
572        const camera2_request_queue_src_ops_t *q,
573        camera_metadata_t *old_buffer)
574{
575    MetadataQueue *queue = getInstance(q);
576    free_camera_metadata(old_buffer);
577    return OK;
578}
579
580int Camera2Device::MetadataQueue::producer_dequeue(
581        const camera2_frame_queue_dst_ops_t *q,
582        size_t entries, size_t bytes,
583        camera_metadata_t **buffer)
584{
585    camera_metadata_t *new_buffer =
586            allocate_camera_metadata(entries, bytes);
587    if (new_buffer == NULL) return NO_MEMORY;
588    *buffer = new_buffer;
589        return OK;
590}
591
592int Camera2Device::MetadataQueue::producer_cancel(
593        const camera2_frame_queue_dst_ops_t *q,
594        camera_metadata_t *old_buffer)
595{
596    free_camera_metadata(old_buffer);
597    return OK;
598}
599
600int Camera2Device::MetadataQueue::producer_enqueue(
601        const camera2_frame_queue_dst_ops_t *q,
602        camera_metadata_t *filled_buffer)
603{
604    MetadataQueue *queue = getInstance(q);
605    return queue->enqueue(filled_buffer);
606}
607
608/**
609 * Camera2Device::StreamAdapter
610 */
611
612#ifndef container_of
613#define container_of(ptr, type, member) \
614    (type *)((char*)(ptr) - offsetof(type, member))
615#endif
616
617Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
618        mState(DISCONNECTED),
619        mDevice(d),
620        mId(-1),
621        mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
622        mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
623        mTotalBuffers(0),
624        mFormatRequested(0),
625        mActiveBuffers(0),
626        mFrameCount(0),
627        mLastTimestamp(0)
628{
629    camera2_stream_ops::dequeue_buffer = dequeue_buffer;
630    camera2_stream_ops::enqueue_buffer = enqueue_buffer;
631    camera2_stream_ops::cancel_buffer = cancel_buffer;
632    camera2_stream_ops::set_crop = set_crop;
633}
634
635Camera2Device::StreamAdapter::~StreamAdapter() {
636    disconnect();
637}
638
639status_t Camera2Device::StreamAdapter::connectToDevice(
640        sp<ANativeWindow> consumer,
641        uint32_t width, uint32_t height, int format, size_t size) {
642    status_t res;
643
644    if (mState != DISCONNECTED) return INVALID_OPERATION;
645    if (consumer == NULL) {
646        ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
647        return BAD_VALUE;
648    }
649
650    mConsumerInterface = consumer;
651    mWidth = width;
652    mHeight = height;
653    mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
654    mFormatRequested = format;
655
656    // Allocate device-side stream interface
657
658    uint32_t id;
659    uint32_t formatActual;
660    uint32_t usage;
661    uint32_t maxBuffers = 2;
662    res = mDevice->ops->allocate_stream(mDevice,
663            mWidth, mHeight, mFormatRequested, getStreamOps(),
664            &id, &formatActual, &usage, &maxBuffers);
665    if (res != OK) {
666        ALOGE("%s: Device stream allocation failed: %s (%d)",
667                __FUNCTION__, strerror(-res), res);
668        return res;
669    }
670
671    mId = id;
672    mFormat = formatActual;
673    mUsage = usage;
674    mMaxProducerBuffers = maxBuffers;
675
676    mState = ALLOCATED;
677
678    // Configure consumer-side ANativeWindow interface
679    res = native_window_api_connect(mConsumerInterface.get(),
680            NATIVE_WINDOW_API_CAMERA);
681    if (res != OK) {
682        ALOGE("%s: Unable to connect to native window for stream %d",
683                __FUNCTION__, mId);
684
685        return res;
686    }
687
688    mState = CONNECTED;
689
690    res = native_window_set_usage(mConsumerInterface.get(), mUsage);
691    if (res != OK) {
692        ALOGE("%s: Unable to configure usage %08x for stream %d",
693                __FUNCTION__, mUsage, mId);
694        return res;
695    }
696
697    res = native_window_set_scaling_mode(mConsumerInterface.get(),
698            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
699    if (res != OK) {
700        ALOGE("%s: Unable to configure stream scaling: %s (%d)",
701                __FUNCTION__, strerror(-res), res);
702        return res;
703    }
704
705    res = setTransform(0);
706    if (res != OK) {
707        return res;
708    }
709
710    if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
711        res = native_window_set_buffers_geometry(mConsumerInterface.get(),
712                mSize, 1, mFormat);
713        if (res != OK) {
714            ALOGE("%s: Unable to configure compressed stream buffer geometry"
715                    " %d x %d, size %d for stream %d",
716                    __FUNCTION__, mWidth, mHeight, mSize, mId);
717            return res;
718        }
719    } else {
720        res = native_window_set_buffers_geometry(mConsumerInterface.get(),
721                mWidth, mHeight, mFormat);
722        if (res != OK) {
723            ALOGE("%s: Unable to configure stream buffer geometry"
724                    " %d x %d, format 0x%x for stream %d",
725                    __FUNCTION__, mWidth, mHeight, mFormat, mId);
726            return res;
727        }
728    }
729
730    int maxConsumerBuffers;
731    res = mConsumerInterface->query(mConsumerInterface.get(),
732            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
733    if (res != OK) {
734        ALOGE("%s: Unable to query consumer undequeued"
735                " buffer count for stream %d", __FUNCTION__, mId);
736        return res;
737    }
738    mMaxConsumerBuffers = maxConsumerBuffers;
739
740    ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
741            mMaxProducerBuffers, mMaxConsumerBuffers);
742
743    mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
744    mActiveBuffers = 0;
745    mFrameCount = 0;
746    mLastTimestamp = 0;
747
748    res = native_window_set_buffer_count(mConsumerInterface.get(),
749            mTotalBuffers);
750    if (res != OK) {
751        ALOGE("%s: Unable to set buffer count for stream %d",
752                __FUNCTION__, mId);
753        return res;
754    }
755
756    // Register allocated buffers with HAL device
757    buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
758    ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
759    uint32_t bufferIdx = 0;
760    for (; bufferIdx < mTotalBuffers; bufferIdx++) {
761        res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
762                &anwBuffers[bufferIdx]);
763        if (res != OK) {
764            ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
765                    "stream %d", __FUNCTION__, bufferIdx, mId);
766            goto cleanUpBuffers;
767        }
768
769        res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
770                anwBuffers[bufferIdx]);
771        if (res != OK) {
772            ALOGE("%s: Unable to lock buffer %d for initial registration for"
773                    "stream %d", __FUNCTION__, bufferIdx, mId);
774            bufferIdx++;
775            goto cleanUpBuffers;
776        }
777
778        buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
779    }
780
781    res = mDevice->ops->register_stream_buffers(mDevice,
782            mId,
783            mTotalBuffers,
784            buffers);
785    if (res != OK) {
786        ALOGE("%s: Unable to register buffers with HAL device for stream %d",
787                __FUNCTION__, mId);
788    } else {
789        mState = ACTIVE;
790    }
791
792cleanUpBuffers:
793    for (uint32_t i = 0; i < bufferIdx; i++) {
794        res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
795                anwBuffers[i]);
796        if (res != OK) {
797            ALOGE("%s: Unable to cancel buffer %d after registration",
798                    __FUNCTION__, i);
799        }
800    }
801    delete[] anwBuffers;
802    delete[] buffers;
803
804    return res;
805}
806
807status_t Camera2Device::StreamAdapter::disconnect() {
808    status_t res;
809    if (mState >= ALLOCATED) {
810        res = mDevice->ops->release_stream(mDevice, mId);
811        if (res != OK) {
812            ALOGE("%s: Unable to release stream %d",
813                    __FUNCTION__, mId);
814            return res;
815        }
816    }
817    if (mState >= CONNECTED) {
818        res = native_window_api_disconnect(mConsumerInterface.get(),
819                NATIVE_WINDOW_API_CAMERA);
820        if (res != OK) {
821            ALOGE("%s: Unable to disconnect stream %d from native window",
822                    __FUNCTION__, mId);
823            return res;
824        }
825    }
826    mId = -1;
827    mState = DISCONNECTED;
828    return OK;
829}
830
831status_t Camera2Device::StreamAdapter::setTransform(int transform) {
832    status_t res;
833    if (mState < CONNECTED) {
834        ALOGE("%s: Cannot set transform on unconnected stream", __FUNCTION__);
835        return INVALID_OPERATION;
836    }
837    res = native_window_set_buffers_transform(mConsumerInterface.get(),
838                                              transform);
839    if (res != OK) {
840        ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
841                __FUNCTION__, transform, strerror(-res), res);
842    }
843    return res;
844}
845
846status_t Camera2Device::StreamAdapter::dump(int fd,
847        const Vector<String16>& args) {
848    String8 result = String8::format("      Stream %d: %d x %d, format 0x%x\n",
849            mId, mWidth, mHeight, mFormat);
850    result.appendFormat("        size %d, usage 0x%x, requested format 0x%x\n",
851            mSize, mUsage, mFormatRequested);
852    result.appendFormat("        total buffers: %d, dequeued buffers: %d\n",
853            mTotalBuffers, mActiveBuffers);
854    result.appendFormat("        frame count: %d, last timestamp %lld\n",
855            mFrameCount, mLastTimestamp);
856    write(fd, result.string(), result.size());
857    return OK;
858}
859
860const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
861    return static_cast<camera2_stream_ops *>(this);
862}
863
864ANativeWindow* Camera2Device::StreamAdapter::toANW(
865        const camera2_stream_ops_t *w) {
866    return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
867}
868
869int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
870        buffer_handle_t** buffer) {
871    int res;
872    StreamAdapter* stream =
873            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
874    if (stream->mState != ACTIVE) {
875        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
876        return INVALID_OPERATION;
877    }
878
879    ANativeWindow *a = toANW(w);
880    ANativeWindowBuffer* anb;
881    res = a->dequeueBuffer(a, &anb);
882    if (res != OK) return res;
883    res = a->lockBuffer(a, anb);
884    if (res != OK) return res;
885
886    *buffer = &(anb->handle);
887    stream->mActiveBuffers++;
888
889    ALOGVV("%s: Buffer %p", __FUNCTION__, *buffer);
890    return res;
891}
892
893int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
894        int64_t timestamp,
895        buffer_handle_t* buffer) {
896    StreamAdapter *stream =
897            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
898    ALOGVV("%s: Stream %d: Buffer %p captured at %lld ns",
899            __FUNCTION__, stream->mId, buffer, timestamp);
900    int state = stream->mState;
901    if (state != ACTIVE) {
902        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
903        return INVALID_OPERATION;
904    }
905    ANativeWindow *a = toANW(w);
906    status_t err;
907    err = native_window_set_buffers_timestamp(a, timestamp);
908    if (err != OK) {
909        ALOGE("%s: Error setting timestamp on native window: %s (%d)",
910                __FUNCTION__, strerror(-err), err);
911        return err;
912    }
913    err = a->queueBuffer(a,
914            container_of(buffer, ANativeWindowBuffer, handle));
915    if (err != OK) {
916        ALOGE("%s: Error queueing buffer to native window: %s (%d)",
917                __FUNCTION__, strerror(-err), err);
918    }
919    stream->mActiveBuffers--;
920    stream->mFrameCount++;
921    stream->mLastTimestamp = timestamp;
922    return err;
923}
924
925int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
926        buffer_handle_t* buffer) {
927    StreamAdapter *stream =
928            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
929    if (stream->mState != ACTIVE) {
930        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
931        return INVALID_OPERATION;
932    }
933    stream->mActiveBuffers--;
934    ANativeWindow *a = toANW(w);
935    return a->cancelBuffer(a,
936            container_of(buffer, ANativeWindowBuffer, handle));
937}
938
939int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
940        int left, int top, int right, int bottom) {
941    int state = static_cast<const StreamAdapter*>(w)->mState;
942    if (state != ACTIVE) {
943        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
944        return INVALID_OPERATION;
945    }
946    ANativeWindow *a = toANW(w);
947    android_native_rect_t crop = { left, top, right, bottom };
948    return native_window_set_crop(a, &crop);
949}
950
951
952}; // namespace android
953