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