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 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 45 FrameProcessorBase::~FrameProcessorBase() { 46 ALOGV("%s: Exit", __FUNCTION__); 47 } 48 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 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 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 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 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 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 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