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