camera2_utils.cpp revision 567b4a24fa9fedf0086af5e0bb8e45bd3294bc9d
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// Utility classes for camera2 HAL testing
18
19#define LOG_TAG "Camera2_test_utils"
20#define LOG_NDEBUG 0
21
22#include "utils/Log.h"
23#include "camera2_utils.h"
24
25namespace android {
26
27/**
28 * MetadataQueue
29 */
30
31MetadataQueue::MetadataQueue():
32            mDevice(NULL),
33            mFrameCount(0),
34            mCount(0),
35            mStreamSlotCount(0),
36            mSignalConsumer(true)
37{
38    camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
39    camera2_request_queue_src_ops::request_count = consumer_buffer_count;
40    camera2_request_queue_src_ops::free_request = consumer_free;
41
42    camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
43    camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
44    camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
45}
46
47MetadataQueue::~MetadataQueue() {
48    freeBuffers(mEntries.begin(), mEntries.end());
49    freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
50}
51
52// Interface to camera2 HAL as consumer (input requests/reprocessing)
53camera2_request_queue_src_ops_t* MetadataQueue::getToConsumerInterface() {
54    return static_cast<camera2_request_queue_src_ops_t*>(this);
55}
56
57void MetadataQueue::setFromConsumerInterface(camera2_device_t *d) {
58    mDevice = d;
59}
60
61camera2_frame_queue_dst_ops_t* MetadataQueue::getToProducerInterface() {
62    return static_cast<camera2_frame_queue_dst_ops_t*>(this);
63}
64
65// Real interfaces
66status_t MetadataQueue::enqueue(camera_metadata_t *buf) {
67    Mutex::Autolock l(mMutex);
68
69    mCount++;
70    mEntries.push_back(buf);
71    notEmpty.signal();
72
73    if (mSignalConsumer && mDevice != NULL) {
74        mSignalConsumer = false;
75
76        mMutex.unlock();
77        ALOGV("%s: Signaling consumer", __FUNCTION__);
78        mDevice->ops->notify_request_queue_not_empty(mDevice);
79        mMutex.lock();
80    }
81    return OK;
82}
83
84int MetadataQueue::getBufferCount() {
85    Mutex::Autolock l(mMutex);
86    if (mStreamSlotCount > 0) {
87        return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
88    }
89    return mCount;
90}
91
92status_t MetadataQueue::dequeue(camera_metadata_t **buf, bool incrementCount) {
93    Mutex::Autolock l(mMutex);
94
95    if (mCount == 0) {
96        if (mStreamSlotCount == 0) {
97            ALOGV("%s: Empty", __FUNCTION__);
98            *buf = NULL;
99            mSignalConsumer = true;
100            return OK;
101        }
102        ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
103              mStreamSlotCount);
104
105        for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
106                slotEntry != mStreamSlot.end();
107                slotEntry++ ) {
108            size_t entries = get_camera_metadata_entry_count(*slotEntry);
109            size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
110
111            camera_metadata_t *copy = allocate_camera_metadata(entries, dataBytes);
112            append_camera_metadata(copy, *slotEntry);
113            mEntries.push_back(copy);
114        }
115        mCount = mStreamSlotCount;
116    }
117    ALOGV("MetadataQueue: deque (%d buffers)", mCount);
118    camera_metadata_t *b = *(mEntries.begin());
119    mEntries.erase(mEntries.begin());
120
121    if (incrementCount) {
122        add_camera_metadata_entry(b,
123                ANDROID_REQUEST_FRAME_COUNT,
124                (void**)&mFrameCount, 1);
125        mFrameCount++;
126    }
127
128    *buf = b;
129    mCount--;
130
131    return OK;
132}
133
134status_t MetadataQueue::waitForBuffer(nsecs_t timeout) {
135    Mutex::Autolock l(mMutex);
136    status_t res;
137    while (mCount == 0) {
138        res = notEmpty.waitRelative(mMutex,timeout);
139        if (res != OK) return res;
140    }
141    return OK;
142}
143
144status_t MetadataQueue::setStreamSlot(camera_metadata_t *buf) {
145    if (buf == NULL) {
146        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
147        mStreamSlotCount = 0;
148        return OK;
149    }
150    if (mStreamSlotCount > 1) {
151        List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
152        freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
153        mStreamSlotCount = 1;
154    }
155    if (mStreamSlotCount == 1) {
156        free_camera_metadata( *(mStreamSlot.begin()) );
157        *(mStreamSlot.begin()) = buf;
158    } else {
159        mStreamSlot.push_front(buf);
160        mStreamSlotCount = 1;
161    }
162    return OK;
163}
164
165status_t MetadataQueue::setStreamSlot(const List<camera_metadata_t*> &bufs) {
166    if (mStreamSlotCount > 0) {
167        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
168    }
169    mStreamSlot = bufs;
170    mStreamSlotCount = mStreamSlot.size();
171
172    return OK;
173}
174
175status_t MetadataQueue::freeBuffers(List<camera_metadata_t*>::iterator start,
176                                    List<camera_metadata_t*>::iterator end) {
177    while (start != end) {
178        free_camera_metadata(*start);
179        start = mStreamSlot.erase(start);
180    }
181    return OK;
182}
183
184int MetadataQueue::consumer_buffer_count(
185        camera2_request_queue_src_ops_t *q) {
186    MetadataQueue *queue = static_cast<MetadataQueue *>(q);
187    return queue->getBufferCount();
188}
189
190int MetadataQueue::consumer_dequeue(camera2_request_queue_src_ops_t *q,
191        camera_metadata_t **buffer) {
192    MetadataQueue *queue = static_cast<MetadataQueue *>(q);
193    return queue->dequeue(buffer, true);
194}
195
196int MetadataQueue::consumer_free(camera2_request_queue_src_ops_t *q,
197        camera_metadata_t *old_buffer) {
198    MetadataQueue *queue = static_cast<MetadataQueue *>(q);
199    free_camera_metadata(old_buffer);
200    return OK;
201}
202
203int MetadataQueue::producer_dequeue(camera2_frame_queue_dst_ops_t *q,
204        size_t entries, size_t bytes,
205        camera_metadata_t **buffer) {
206    camera_metadata_t *new_buffer =
207            allocate_camera_metadata(entries, bytes);
208    if (new_buffer == NULL) return NO_MEMORY;
209    *buffer = new_buffer;
210        return OK;
211}
212
213int MetadataQueue::producer_cancel(camera2_frame_queue_dst_ops_t *q,
214        camera_metadata_t *old_buffer) {
215    free_camera_metadata(old_buffer);
216    return OK;
217}
218
219int MetadataQueue::producer_enqueue(camera2_frame_queue_dst_ops_t *q,
220        camera_metadata_t *filled_buffer) {
221    MetadataQueue *queue = static_cast<MetadataQueue *>(q);
222    return queue->enqueue(filled_buffer);
223}
224
225/**
226 * NotifierListener
227 */
228
229NotifierListener::NotifierListener() {
230}
231
232status_t NotifierListener::getNotificationsFrom(camera2_device *dev) {
233    if (!dev) return BAD_VALUE;
234    status_t err;
235    err = dev->ops->set_notify_callback(dev,
236            notify_callback_dispatch,
237            (void*)this);
238    return err;
239}
240
241status_t NotifierListener::getNextNotification(int32_t *msg_type,
242        int32_t *ext1,
243        int32_t *ext2,
244        int32_t *ext3) {
245    Mutex::Autolock l(mMutex);
246    if (mNotifications.size() == 0) return BAD_VALUE;
247    return getNextNotificationLocked(msg_type, ext1, ext2, ext3);
248}
249
250status_t NotifierListener::waitForNotification(int32_t *msg_type,
251        int32_t *ext1,
252        int32_t *ext2,
253        int32_t *ext3) {
254    Mutex::Autolock l(mMutex);
255    while (mNotifications.size() == 0) {
256        mNewNotification.wait(mMutex);
257    }
258    return getNextNotificationLocked(msg_type, ext1, ext2, ext3);
259}
260
261int NotifierListener::numNotifications() {
262    Mutex::Autolock l(mMutex);
263    return mNotifications.size();
264}
265
266status_t NotifierListener::getNextNotificationLocked(int32_t *msg_type,
267        int32_t *ext1,
268        int32_t *ext2,
269        int32_t *ext3) {
270    *msg_type = mNotifications.begin()->msg_type;
271    *ext1 = mNotifications.begin()->ext1;
272    *ext2 = mNotifications.begin()->ext2;
273    *ext3 = mNotifications.begin()->ext3;
274    mNotifications.erase(mNotifications.begin());
275    return OK;
276}
277
278void NotifierListener::onNotify(int32_t msg_type,
279        int32_t ext1,
280        int32_t ext2,
281        int32_t ext3) {
282    Mutex::Autolock l(mMutex);
283    mNotifications.push_back(Notification(msg_type, ext1, ext2, ext3));
284    mNewNotification.signal();
285}
286
287void NotifierListener::notify_callback_dispatch(int32_t msg_type,
288        int32_t ext1,
289        int32_t ext2,
290        int32_t ext3,
291        void *user) {
292    NotifierListener *me = reinterpret_cast<NotifierListener*>(user);
293    me->onNotify(msg_type, ext1, ext2, ext3);
294}
295
296/**
297 * StreamAdapter
298 */
299
300#ifndef container_of
301#define container_of(ptr, type, member) \
302    (type *)((char*)(ptr) - offsetof(type, member))
303#endif
304
305StreamAdapter::StreamAdapter(sp<ISurfaceTexture> consumer):
306        mState(UNINITIALIZED), mDevice(NULL),
307        mId(-1),
308        mWidth(0), mHeight(0), mFormatRequested(0)
309{
310    mConsumerInterface = new SurfaceTextureClient(consumer);
311    camera2_stream_ops::dequeue_buffer = dequeue_buffer;
312    camera2_stream_ops::enqueue_buffer = enqueue_buffer;
313    camera2_stream_ops::cancel_buffer = cancel_buffer;
314    camera2_stream_ops::set_crop = set_crop;
315}
316
317StreamAdapter::~StreamAdapter() {
318    disconnect();
319}
320
321status_t StreamAdapter::connectToDevice(camera2_device_t *d,
322        uint32_t width, uint32_t height, int format) {
323    if (mState != UNINITIALIZED) return INVALID_OPERATION;
324    if (d == NULL) {
325        ALOGE("%s: Null device passed to stream adapter", __FUNCTION__);
326        return BAD_VALUE;
327    }
328
329    status_t res;
330
331    mWidth = width;
332    mHeight = height;
333    mFormatRequested = format;
334
335    // Allocate device-side stream interface
336
337    uint32_t id;
338    uint32_t formatActual;
339    uint32_t usage;
340    uint32_t maxBuffers = 2;
341    res = d->ops->allocate_stream(d,
342            mWidth, mHeight, mFormatRequested, getStreamOps(),
343            &id, &formatActual, &usage, &maxBuffers);
344    if (res != OK) {
345        ALOGE("%s: Device stream allocation failed: %s (%d)",
346                __FUNCTION__, strerror(-res), res);
347        mState = UNINITIALIZED;
348        return res;
349    }
350    mDevice = d;
351
352    mId = id;
353    mFormat = formatActual;
354    mUsage = usage;
355    mMaxProducerBuffers = maxBuffers;
356
357    // Configure consumer-side ANativeWindow interface
358
359    res = native_window_api_connect(mConsumerInterface.get(),
360            NATIVE_WINDOW_API_CAMERA);
361    if (res != OK) {
362        ALOGE("%s: Unable to connect to native window for stream %d",
363                __FUNCTION__, mId);
364        mState = ALLOCATED;
365        return res;
366    }
367
368    res = native_window_set_usage(mConsumerInterface.get(), mUsage);
369    if (res != OK) {
370        ALOGE("%s: Unable to configure usage %08x for stream %d",
371                __FUNCTION__, mUsage, mId);
372        mState = CONNECTED;
373        return res;
374    }
375
376    res = native_window_set_buffers_geometry(mConsumerInterface.get(),
377            mWidth, mHeight, mFormat);
378    if (res != OK) {
379        ALOGE("%s: Unable to configure buffer geometry"
380                " %d x %d, format 0x%x for stream %d",
381                __FUNCTION__, mWidth, mHeight, mFormat, mId);
382        mState = CONNECTED;
383        return res;
384    }
385
386    int maxConsumerBuffers;
387    res = mConsumerInterface->query(mConsumerInterface.get(),
388            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
389    if (res != OK) {
390        ALOGE("%s: Unable to query consumer undequeued"
391                " buffer count for stream %d", __FUNCTION__, mId);
392        mState = CONNECTED;
393        return res;
394    }
395    mMaxConsumerBuffers = maxConsumerBuffers;
396
397    ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
398            mMaxProducerBuffers, mMaxConsumerBuffers);
399
400    int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
401
402    res = native_window_set_buffer_count(mConsumerInterface.get(),
403            totalBuffers);
404    if (res != OK) {
405        ALOGE("%s: Unable to set buffer count for stream %d",
406                __FUNCTION__, mId);
407        mState = CONNECTED;
408        return res;
409    }
410
411    // Register allocated buffers with HAL device
412    buffer_handle_t *buffers = new buffer_handle_t[totalBuffers];
413    ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers];
414    int bufferIdx = 0;
415    for (; bufferIdx < totalBuffers; bufferIdx++) {
416        res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
417                &anwBuffers[bufferIdx]);
418        if (res != OK) {
419            ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
420                    "stream %d", __FUNCTION__, bufferIdx, mId);
421            mState = CONNECTED;
422            goto cleanUpBuffers;
423        }
424
425        res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
426                anwBuffers[bufferIdx]);
427        if (res != OK) {
428            ALOGE("%s: Unable to lock buffer %d for initial registration for"
429                    "stream %d", __FUNCTION__, bufferIdx, mId);
430            mState = CONNECTED;
431            bufferIdx++;
432            goto cleanUpBuffers;
433        }
434
435        buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
436    }
437
438    res = mDevice->ops->register_stream_buffers(mDevice,
439            mId,
440            totalBuffers,
441            buffers);
442    if (res != OK) {
443        ALOGE("%s: Unable to register buffers with HAL device for stream %d",
444                __FUNCTION__, mId);
445        mState = CONNECTED;
446    } else {
447        mState = ACTIVE;
448    }
449
450cleanUpBuffers:
451    for (int i = 0; i < bufferIdx; i++) {
452        res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
453                anwBuffers[i]);
454    }
455    delete anwBuffers;
456    delete buffers;
457
458    return res;
459}
460
461status_t StreamAdapter::disconnect() {
462    status_t res;
463    if (mState >= ALLOCATED) {
464        res = mDevice->ops->release_stream(mDevice, mId);
465        if (res != OK) {
466            ALOGE("%s: Unable to release stream %d",
467                    __FUNCTION__, mId);
468            return res;
469        }
470    }
471    if (mState >= CONNECTED) {
472        res = native_window_api_disconnect(mConsumerInterface.get(),
473                NATIVE_WINDOW_API_CAMERA);
474        if (res != OK) {
475            ALOGE("%s: Unable to disconnect stream %d from native window",
476                    __FUNCTION__, mId);
477            return res;
478        }
479    }
480    mId = -1;
481    mState = DISCONNECTED;
482    return OK;
483}
484
485int StreamAdapter::getId() {
486    return mId;
487}
488
489camera2_stream_ops *StreamAdapter::getStreamOps() {
490    return static_cast<camera2_stream_ops *>(this);
491}
492
493ANativeWindow* StreamAdapter::toANW(camera2_stream_ops_t *w) {
494    return static_cast<StreamAdapter*>(w)->mConsumerInterface.get();
495}
496
497int StreamAdapter::dequeue_buffer(camera2_stream_ops_t *w,
498        buffer_handle_t** buffer) {
499    int res;
500    int state = static_cast<StreamAdapter*>(w)->mState;
501    if (state != ACTIVE) {
502        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
503        return INVALID_OPERATION;
504    }
505
506    ANativeWindow *a = toANW(w);
507    ANativeWindowBuffer* anb;
508    res = a->dequeueBuffer(a, &anb);
509    if (res != OK) return res;
510    res = a->lockBuffer(a, anb);
511    if (res != OK) return res;
512
513    *buffer = &(anb->handle);
514
515    return res;
516}
517
518int StreamAdapter::enqueue_buffer(camera2_stream_ops_t* w,
519        int64_t timestamp,
520        buffer_handle_t* buffer) {
521    int state = static_cast<StreamAdapter*>(w)->mState;
522    if (state != ACTIVE) {
523        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
524        return INVALID_OPERATION;
525    }
526    ANativeWindow *a = toANW(w);
527    status_t err;
528    err = native_window_set_buffers_timestamp(a, timestamp);
529    if (err != OK) return err;
530    return a->queueBuffer(a,
531            container_of(buffer, ANativeWindowBuffer, handle));
532}
533
534int StreamAdapter::cancel_buffer(camera2_stream_ops_t* w,
535        buffer_handle_t* buffer) {
536    int state = static_cast<StreamAdapter*>(w)->mState;
537    if (state != ACTIVE) {
538        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
539        return INVALID_OPERATION;
540    }
541    ANativeWindow *a = toANW(w);
542    return a->cancelBuffer(a,
543            container_of(buffer, ANativeWindowBuffer, handle));
544}
545
546int StreamAdapter::set_crop(camera2_stream_ops_t* w,
547        int left, int top, int right, int bottom) {
548    int state = static_cast<StreamAdapter*>(w)->mState;
549    if (state != ACTIVE) {
550        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
551        return INVALID_OPERATION;
552    }
553    ANativeWindow *a = toANW(w);
554    android_native_rect_t crop = { left, top, right, bottom };
555    return native_window_set_crop(a, &crop);
556}
557
558/**
559 * FrameWaiter
560 */
561
562FrameWaiter::FrameWaiter():
563        mPendingFrames(0) {
564}
565
566status_t FrameWaiter::waitForFrame(nsecs_t timeout) {
567    status_t res;
568    Mutex::Autolock lock(mMutex);
569    while (mPendingFrames == 0) {
570        res = mCondition.waitRelative(mMutex, timeout);
571        if (res != OK) return res;
572    }
573    mPendingFrames--;
574    return OK;
575}
576
577void FrameWaiter::onFrameAvailable() {
578    Mutex::Autolock lock(mMutex);
579    mPendingFrames++;
580    mCondition.signal();
581}
582
583} // namespace android
584