FrameProcessorBase.cpp revision 7b82efe7a376c882f8f938e1c41b8311a8cdda4a
1/*
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 "Camera2-FrameProcessorBase"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <utils/Trace.h>
23
24#include "common/FrameProcessorBase.h"
25#include "common/CameraDeviceBase.h"
26
27namespace android {
28namespace camera2 {
29
30FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) :
31    Thread(/*canCallJava*/false),
32    mDevice(device) {
33}
34
35FrameProcessorBase::~FrameProcessorBase() {
36    ALOGV("%s: Exit", __FUNCTION__);
37}
38
39status_t FrameProcessorBase::registerListener(int32_t minId,
40        int32_t maxId, wp<FilteredListener> listener) {
41    Mutex::Autolock l(mInputMutex);
42    ALOGV("%s: Registering listener for frame id range %d - %d",
43            __FUNCTION__, minId, maxId);
44    RangeListener rListener = { minId, maxId, listener };
45    mRangeListeners.push_back(rListener);
46    return OK;
47}
48
49status_t FrameProcessorBase::removeListener(int32_t minId,
50                                           int32_t maxId,
51                                           wp<FilteredListener> listener) {
52    Mutex::Autolock l(mInputMutex);
53    List<RangeListener>::iterator item = mRangeListeners.begin();
54    while (item != mRangeListeners.end()) {
55        if (item->minId == minId &&
56                item->maxId == maxId &&
57                item->listener == listener) {
58            item = mRangeListeners.erase(item);
59        } else {
60            item++;
61        }
62    }
63    return OK;
64}
65
66void FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) {
67    String8 result("    Latest received frame:\n");
68    write(fd, result.string(), result.size());
69    mLastFrame.dump(fd, 2, 6);
70}
71
72bool FrameProcessorBase::threadLoop() {
73    status_t res;
74
75    sp<CameraDeviceBase> device;
76    {
77        device = mDevice.promote();
78        if (device == 0) return false;
79    }
80
81    res = device->waitForNextFrame(kWaitDuration);
82    if (res == OK) {
83        processNewFrames(device);
84    } else if (res != TIMED_OUT) {
85        ALOGE("FrameProcessorBase: Error waiting for new "
86                "frames: %s (%d)", strerror(-res), res);
87    }
88
89    return true;
90}
91
92void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
93    status_t res;
94    ATRACE_CALL();
95    CameraMetadata frame;
96
97    ALOGV("%s: Camera %d: Process new frames", __FUNCTION__, device->getId());
98
99    while ( (res = device->getNextFrame(&frame)) == OK) {
100
101        camera_metadata_entry_t entry;
102
103        entry = frame.find(ANDROID_REQUEST_FRAME_COUNT);
104        if (entry.count == 0) {
105            ALOGE("%s: Camera %d: Error reading frame number",
106                    __FUNCTION__, device->getId());
107            break;
108        }
109        ATRACE_INT("cam2_frame", entry.data.i32[0]);
110
111        if (!processSingleFrame(frame, device)) {
112            break;
113        }
114
115        if (!frame.isEmpty()) {
116            mLastFrame.acquire(frame);
117        }
118    }
119    if (res != NOT_ENOUGH_DATA) {
120        ALOGE("%s: Camera %d: Error getting next frame: %s (%d)",
121                __FUNCTION__, device->getId(), strerror(-res), res);
122        return;
123    }
124
125    return;
126}
127
128bool FrameProcessorBase::processSingleFrame(CameraMetadata &frame,
129                                           const sp<CameraDeviceBase> &device) {
130    ALOGV("%s: Camera %d: Process single frame (is empty? %d)",
131          __FUNCTION__, device->getId(), frame.isEmpty());
132    return processListeners(frame, device) == OK;
133}
134
135status_t FrameProcessorBase::processListeners(const CameraMetadata &frame,
136        const sp<CameraDeviceBase> &device) {
137    ATRACE_CALL();
138    camera_metadata_ro_entry_t entry;
139
140    entry = frame.find(ANDROID_REQUEST_ID);
141    if (entry.count == 0) {
142        ALOGE("%s: Camera %d: Error reading frame id",
143                __FUNCTION__, device->getId());
144        return BAD_VALUE;
145    }
146    int32_t frameId = entry.data.i32[0];
147
148    List<sp<FilteredListener> > listeners;
149    {
150        Mutex::Autolock l(mInputMutex);
151
152        List<RangeListener>::iterator item = mRangeListeners.begin();
153        while (item != mRangeListeners.end()) {
154            if (frameId >= item->minId &&
155                    frameId < item->maxId) {
156                sp<FilteredListener> listener = item->listener.promote();
157                if (listener == 0) {
158                    item = mRangeListeners.erase(item);
159                    continue;
160                } else {
161                    listeners.push_back(listener);
162                }
163            }
164            item++;
165        }
166    }
167    ALOGV("Got %d range listeners out of %d", listeners.size(), mRangeListeners.size());
168    List<sp<FilteredListener> >::iterator item = listeners.begin();
169    for (; item != listeners.end(); item++) {
170        (*item)->onFrameAvailable(frameId, frame);
171    }
172    return OK;
173}
174
175}; // namespace camera2
176}; // namespace android
177