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