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