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 std::map<std::string, CameraMetadata> lastPhysicalFrames;
93 {
94 // Don't race while dumping metadata
95 Mutex::Autolock al(mLastFrameMutex);
96 lastFrame = CameraMetadata(mLastFrame);
97
98 for (const auto& physicalFrame : mLastPhysicalFrames) {
99 lastPhysicalFrames.emplace(String8(physicalFrame.mPhysicalCameraId),
100 physicalFrame.mPhysicalCameraMetadata);
101 }
102 }
103 lastFrame.dump(fd, /*verbosity*/2, /*indentation*/6);
104
105 for (const auto& physicalFrame : lastPhysicalFrames) {
106 result = String8::format(" Latest received frame for physical camera %s:\n",
107 physicalFrame.first.c_str());
108 write(fd, result.string(), result.size());
109 CameraMetadata lastPhysicalMetadata = CameraMetadata(physicalFrame.second);
110 lastPhysicalMetadata.sort();
111 lastPhysicalMetadata.dump(fd, /*verbosity*/2, /*indentation*/6);
112 }
113 }
114
threadLoop()115 bool FrameProcessorBase::threadLoop() {
116 status_t res;
117
118 sp<CameraDeviceBase> device;
119 {
120 device = mDevice.promote();
121 if (device == 0) return false;
122 }
123
124 res = device->waitForNextFrame(kWaitDuration);
125 if (res == OK) {
126 processNewFrames(device);
127 } else if (res != TIMED_OUT) {
128 ALOGE("FrameProcessorBase: Error waiting for new "
129 "frames: %s (%d)", strerror(-res), res);
130 }
131
132 return true;
133 }
134
processNewFrames(const sp<CameraDeviceBase> & device)135 void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
136 status_t res;
137 ATRACE_CALL();
138 CaptureResult result;
139
140 ALOGV("%s: Camera %s: Process new frames", __FUNCTION__, device->getId().string());
141
142 while ( (res = device->getNextResult(&result)) == OK) {
143
144 // TODO: instead of getting frame number from metadata, we should read
145 // this from result.mResultExtras when CameraDeviceBase interface is fixed.
146 camera_metadata_entry_t entry;
147
148 entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
149 if (entry.count == 0) {
150 ALOGE("%s: Camera %s: Error reading frame number",
151 __FUNCTION__, device->getId().string());
152 break;
153 }
154 ATRACE_INT("cam2_frame", entry.data.i32[0]);
155
156 if (!processSingleFrame(result, device)) {
157 break;
158 }
159
160 if (!result.mMetadata.isEmpty()) {
161 Mutex::Autolock al(mLastFrameMutex);
162 mLastFrame.acquire(result.mMetadata);
163
164 mLastPhysicalFrames = std::move(result.mPhysicalMetadatas);
165 }
166 }
167 if (res != NOT_ENOUGH_DATA) {
168 ALOGE("%s: Camera %s: Error getting next frame: %s (%d)",
169 __FUNCTION__, device->getId().string(), strerror(-res), res);
170 return;
171 }
172
173 return;
174 }
175
processSingleFrame(CaptureResult & result,const sp<CameraDeviceBase> & device)176 bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
177 const sp<CameraDeviceBase> &device) {
178 ALOGV("%s: Camera %s: Process single frame (is empty? %d)",
179 __FUNCTION__, device->getId().string(), result.mMetadata.isEmpty());
180 return processListeners(result, device) == OK;
181 }
182
processListeners(const CaptureResult & result,const sp<CameraDeviceBase> & device)183 status_t FrameProcessorBase::processListeners(const CaptureResult &result,
184 const sp<CameraDeviceBase> &device) {
185 ATRACE_CALL();
186
187 camera_metadata_ro_entry_t entry;
188
189 // Check if this result is partial.
190 bool isPartialResult =
191 result.mResultExtras.partialResultCount < mNumPartialResults;
192
193 // TODO: instead of getting requestID from CameraMetadata, we should get it
194 // from CaptureResultExtras. This will require changing Camera2Device.
195 // Currently Camera2Device uses MetadataQueue to store results, which does not
196 // include CaptureResultExtras.
197 entry = result.mMetadata.find(ANDROID_REQUEST_ID);
198 if (entry.count == 0) {
199 ALOGE("%s: Camera %s: Error reading frame id", __FUNCTION__, device->getId().string());
200 return BAD_VALUE;
201 }
202 int32_t requestId = entry.data.i32[0];
203
204 List<sp<FilteredListener> > listeners;
205 {
206 Mutex::Autolock l(mInputMutex);
207
208 List<RangeListener>::iterator item = mRangeListeners.begin();
209 // Don't deliver partial results to listeners that don't want them
210 while (item != mRangeListeners.end()) {
211 if (requestId >= item->minId && requestId < item->maxId &&
212 (!isPartialResult || item->sendPartials)) {
213 sp<FilteredListener> listener = item->listener.promote();
214 if (listener == 0) {
215 item = mRangeListeners.erase(item);
216 continue;
217 } else {
218 listeners.push_back(listener);
219 }
220 }
221 item++;
222 }
223 }
224 ALOGV("%s: Camera %s: Got %zu range listeners out of %zu", __FUNCTION__,
225 device->getId().string(), listeners.size(), mRangeListeners.size());
226
227 List<sp<FilteredListener> >::iterator item = listeners.begin();
228 for (; item != listeners.end(); item++) {
229 (*item)->onResultAvailable(result);
230 }
231 return OK;
232 }
233
234 }; // namespace camera2
235 }; // namespace android
236