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