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