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