FrameProcessorBase.cpp revision 954d248e02e19f8ecd165804b7d063d346154f4c
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 27namespace android { 28namespace camera2 { 29 30FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) : 31 Thread(/*canCallJava*/false), 32 mDevice(device) { 33} 34 35FrameProcessorBase::~FrameProcessorBase() { 36 ALOGV("%s: Exit", __FUNCTION__); 37} 38 39status_t FrameProcessorBase::registerListener(int32_t minId, 40 int32_t maxId, wp<FilteredListener> listener, bool sendPartials) { 41 Mutex::Autolock l(mInputMutex); 42 List<RangeListener>::iterator item = mRangeListeners.begin(); 43 while (item != mRangeListeners.end()) { 44 if (item->minId == minId && 45 item->maxId == maxId && 46 item->listener == listener) { 47 // already registered, just return 48 ALOGV("%s: Attempt to register the same client twice, ignoring", 49 __FUNCTION__); 50 return OK; 51 } 52 item++; 53 } 54 ALOGV("%s: Registering listener for frame id range %d - %d", 55 __FUNCTION__, minId, maxId); 56 RangeListener rListener = { minId, maxId, listener, sendPartials }; 57 mRangeListeners.push_back(rListener); 58 return OK; 59} 60 61status_t FrameProcessorBase::removeListener(int32_t minId, 62 int32_t maxId, 63 wp<FilteredListener> listener) { 64 Mutex::Autolock l(mInputMutex); 65 List<RangeListener>::iterator item = mRangeListeners.begin(); 66 while (item != mRangeListeners.end()) { 67 if (item->minId == minId && 68 item->maxId == maxId && 69 item->listener == listener) { 70 item = mRangeListeners.erase(item); 71 } else { 72 item++; 73 } 74 } 75 return OK; 76} 77 78void FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) { 79 String8 result(" Latest received frame:\n"); 80 write(fd, result.string(), result.size()); 81 82 CameraMetadata lastFrame; 83 { 84 // Don't race while dumping metadata 85 Mutex::Autolock al(mLastFrameMutex); 86 lastFrame = CameraMetadata(mLastFrame); 87 } 88 lastFrame.dump(fd, 2, 6); 89} 90 91bool FrameProcessorBase::threadLoop() { 92 status_t res; 93 94 sp<CameraDeviceBase> device; 95 { 96 device = mDevice.promote(); 97 if (device == 0) return false; 98 } 99 100 res = device->waitForNextFrame(kWaitDuration); 101 if (res == OK) { 102 processNewFrames(device); 103 } else if (res != TIMED_OUT) { 104 ALOGE("FrameProcessorBase: Error waiting for new " 105 "frames: %s (%d)", strerror(-res), res); 106 } 107 108 return true; 109} 110 111void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) { 112 status_t res; 113 ATRACE_CALL(); 114 CaptureResult result; 115 116 ALOGV("%s: Camera %d: Process new frames", __FUNCTION__, device->getId()); 117 118 while ( (res = device->getNextResult(&result)) == OK) { 119 120 // TODO: instead of getting frame number from metadata, we should read 121 // this from result.mResultExtras when CameraDeviceBase interface is fixed. 122 camera_metadata_entry_t entry; 123 124 entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT); 125 if (entry.count == 0) { 126 ALOGE("%s: Camera %d: Error reading frame number", 127 __FUNCTION__, device->getId()); 128 break; 129 } 130 ATRACE_INT("cam2_frame", entry.data.i32[0]); 131 132 if (!processSingleFrame(result, device)) { 133 break; 134 } 135 136 if (!result.mMetadata.isEmpty()) { 137 Mutex::Autolock al(mLastFrameMutex); 138 mLastFrame.acquire(result.mMetadata); 139 } 140 } 141 if (res != NOT_ENOUGH_DATA) { 142 ALOGE("%s: Camera %d: Error getting next frame: %s (%d)", 143 __FUNCTION__, device->getId(), strerror(-res), res); 144 return; 145 } 146 147 return; 148} 149 150bool FrameProcessorBase::processSingleFrame(CaptureResult &result, 151 const sp<CameraDeviceBase> &device) { 152 ALOGV("%s: Camera %d: Process single frame (is empty? %d)", 153 __FUNCTION__, device->getId(), result.mMetadata.isEmpty()); 154 return processListeners(result, device) == OK; 155} 156 157status_t FrameProcessorBase::processListeners(const CaptureResult &result, 158 const sp<CameraDeviceBase> &device) { 159 ATRACE_CALL(); 160 161 camera_metadata_ro_entry_t entry; 162 163 // Quirks: Don't deliver partial results to listeners that don't want them 164 bool quirkIsPartial = false; 165 entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT); 166 if (entry.count != 0 && 167 entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) { 168 ALOGV("%s: Camera %d: Not forwarding partial result to listeners", 169 __FUNCTION__, device->getId()); 170 quirkIsPartial = true; 171 } 172 173 // TODO: instead of getting requestID from CameraMetadata, we should get it 174 // from CaptureResultExtras. This will require changing Camera2Device. 175 // Currently Camera2Device uses MetadataQueue to store results, which does not 176 // include CaptureResultExtras. 177 entry = result.mMetadata.find(ANDROID_REQUEST_ID); 178 if (entry.count == 0) { 179 ALOGE("%s: Camera %d: Error reading frame id", __FUNCTION__, device->getId()); 180 return BAD_VALUE; 181 } 182 int32_t requestId = entry.data.i32[0]; 183 184 List<sp<FilteredListener> > listeners; 185 { 186 Mutex::Autolock l(mInputMutex); 187 188 List<RangeListener>::iterator item = mRangeListeners.begin(); 189 while (item != mRangeListeners.end()) { 190 if (requestId >= item->minId && requestId < item->maxId && 191 (!quirkIsPartial || item->sendPartials)) { 192 sp<FilteredListener> listener = item->listener.promote(); 193 if (listener == 0) { 194 item = mRangeListeners.erase(item); 195 continue; 196 } else { 197 listeners.push_back(listener); 198 } 199 } 200 item++; 201 } 202 } 203 ALOGV("%s: Camera %d: Got %zu range listeners out of %zu", __FUNCTION__, 204 device->getId(), listeners.size(), mRangeListeners.size()); 205 206 List<sp<FilteredListener> >::iterator item = listeners.begin(); 207 for (; item != listeners.end(); item++) { 208 (*item)->onResultAvailable(result); 209 } 210 return OK; 211} 212 213}; // namespace camera2 214}; // namespace android 215