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