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
27 namespace android {
28 namespace camera2 {
29
FrameProcessorBase(wp<CameraDeviceBase> device)30 FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) :
31 Thread(/*canCallJava*/false),
32 mDevice(device),
33 mNumPartialResults(1) {
34 sp<CameraDeviceBase> cameraDevice = device.promote();
35 if (cameraDevice != 0 &&
36 cameraDevice->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) {
37 CameraMetadata staticInfo = cameraDevice->info();
38 camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
39 if (entry.count > 0) {
40 mNumPartialResults = entry.data.i32[0];
41 }
42 }
43 }
44
~FrameProcessorBase()45 FrameProcessorBase::~FrameProcessorBase() {
46 ALOGV("%s: Exit", __FUNCTION__);
47 }
48
registerListener(int32_t minId,int32_t maxId,wp<FilteredListener> listener,bool sendPartials)49 status_t FrameProcessorBase::registerListener(int32_t minId,
50 int32_t maxId, wp<FilteredListener> listener, bool sendPartials) {
51 Mutex::Autolock l(mInputMutex);
52 List<RangeListener>::iterator item = mRangeListeners.begin();
53 while (item != mRangeListeners.end()) {
54 if (item->minId == minId &&
55 item->maxId == maxId &&
56 item->listener == listener) {
57 // already registered, just return
58 ALOGV("%s: Attempt to register the same client twice, ignoring",
59 __FUNCTION__);
60 return OK;
61 }
62 item++;
63 }
64 ALOGV("%s: Registering listener for frame id range %d - %d",
65 __FUNCTION__, minId, maxId);
66 RangeListener rListener = { minId, maxId, listener, sendPartials };
67 mRangeListeners.push_back(rListener);
68 return OK;
69 }
70
removeListener(int32_t minId,int32_t maxId,wp<FilteredListener> listener)71 status_t FrameProcessorBase::removeListener(int32_t minId,
72 int32_t maxId,
73 wp<FilteredListener> listener) {
74 Mutex::Autolock l(mInputMutex);
75 List<RangeListener>::iterator item = mRangeListeners.begin();
76 while (item != mRangeListeners.end()) {
77 if (item->minId == minId &&
78 item->maxId == maxId &&
79 item->listener == listener) {
80 item = mRangeListeners.erase(item);
81 } else {
82 item++;
83 }
84 }
85 return OK;
86 }
87
dump(int fd,const Vector<String16> &)88 void FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) {
89 String8 result(" Latest received frame:\n");
90 write(fd, result.string(), result.size());
91
92 CameraMetadata lastFrame;
93 {
94 // Don't race while dumping metadata
95 Mutex::Autolock al(mLastFrameMutex);
96 lastFrame = CameraMetadata(mLastFrame);
97 }
98 lastFrame.dump(fd, 2, 6);
99 }
100
threadLoop()101 bool FrameProcessorBase::threadLoop() {
102 status_t res;
103
104 sp<CameraDeviceBase> device;
105 {
106 device = mDevice.promote();
107 if (device == 0) return false;
108 }
109
110 res = device->waitForNextFrame(kWaitDuration);
111 if (res == OK) {
112 processNewFrames(device);
113 } else if (res != TIMED_OUT) {
114 ALOGE("FrameProcessorBase: Error waiting for new "
115 "frames: %s (%d)", strerror(-res), res);
116 }
117
118 return true;
119 }
120
processNewFrames(const sp<CameraDeviceBase> & device)121 void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
122 status_t res;
123 ATRACE_CALL();
124 CaptureResult result;
125
126 ALOGV("%s: Camera %d: Process new frames", __FUNCTION__, device->getId());
127
128 while ( (res = device->getNextResult(&result)) == OK) {
129
130 // TODO: instead of getting frame number from metadata, we should read
131 // this from result.mResultExtras when CameraDeviceBase interface is fixed.
132 camera_metadata_entry_t entry;
133
134 entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
135 if (entry.count == 0) {
136 ALOGE("%s: Camera %d: Error reading frame number",
137 __FUNCTION__, device->getId());
138 break;
139 }
140 ATRACE_INT("cam2_frame", entry.data.i32[0]);
141
142 if (!processSingleFrame(result, device)) {
143 break;
144 }
145
146 if (!result.mMetadata.isEmpty()) {
147 Mutex::Autolock al(mLastFrameMutex);
148 mLastFrame.acquire(result.mMetadata);
149 }
150 }
151 if (res != NOT_ENOUGH_DATA) {
152 ALOGE("%s: Camera %d: Error getting next frame: %s (%d)",
153 __FUNCTION__, device->getId(), strerror(-res), res);
154 return;
155 }
156
157 return;
158 }
159
processSingleFrame(CaptureResult & result,const sp<CameraDeviceBase> & device)160 bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
161 const sp<CameraDeviceBase> &device) {
162 ALOGV("%s: Camera %d: Process single frame (is empty? %d)",
163 __FUNCTION__, device->getId(), result.mMetadata.isEmpty());
164 return processListeners(result, device) == OK;
165 }
166
processListeners(const CaptureResult & result,const sp<CameraDeviceBase> & device)167 status_t FrameProcessorBase::processListeners(const CaptureResult &result,
168 const sp<CameraDeviceBase> &device) {
169 ATRACE_CALL();
170
171 camera_metadata_ro_entry_t entry;
172
173 // Check if this result is partial.
174 bool isPartialResult = false;
175 if (device->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) {
176 isPartialResult = result.mResultExtras.partialResultCount < mNumPartialResults;
177 } else {
178 entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT);
179 if (entry.count != 0 &&
180 entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) {
181 ALOGV("%s: Camera %d: This is a partial result",
182 __FUNCTION__, device->getId());
183 isPartialResult = true;
184 }
185 }
186
187 // TODO: instead of getting requestID from CameraMetadata, we should get it
188 // from CaptureResultExtras. This will require changing Camera2Device.
189 // Currently Camera2Device uses MetadataQueue to store results, which does not
190 // include CaptureResultExtras.
191 entry = result.mMetadata.find(ANDROID_REQUEST_ID);
192 if (entry.count == 0) {
193 ALOGE("%s: Camera %d: Error reading frame id", __FUNCTION__, device->getId());
194 return BAD_VALUE;
195 }
196 int32_t requestId = entry.data.i32[0];
197
198 List<sp<FilteredListener> > listeners;
199 {
200 Mutex::Autolock l(mInputMutex);
201
202 List<RangeListener>::iterator item = mRangeListeners.begin();
203 // Don't deliver partial results to listeners that don't want them
204 while (item != mRangeListeners.end()) {
205 if (requestId >= item->minId && requestId < item->maxId &&
206 (!isPartialResult || item->sendPartials)) {
207 sp<FilteredListener> listener = item->listener.promote();
208 if (listener == 0) {
209 item = mRangeListeners.erase(item);
210 continue;
211 } else {
212 listeners.push_back(listener);
213 }
214 }
215 item++;
216 }
217 }
218 ALOGV("%s: Camera %d: Got %zu range listeners out of %zu", __FUNCTION__,
219 device->getId(), listeners.size(), mRangeListeners.size());
220
221 List<sp<FilteredListener> >::iterator item = listeners.begin();
222 for (; item != listeners.end(); item++) {
223 (*item)->onResultAvailable(result);
224 }
225 return OK;
226 }
227
228 }; // namespace camera2
229 }; // namespace android
230