Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 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 | |
Eino-Ville Talvala | 4bb8118 | 2012-09-24 09:46:53 -0700 | [diff] [blame] | 17 | #define LOG_TAG "Camera2-ZslProcessor" |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 18 | #define ATRACE_TAG ATRACE_TAG_CAMERA |
| 19 | //#define LOG_NDEBUG 0 |
| 20 | //#define LOG_NNDEBUG 0 |
| 21 | |
| 22 | #ifdef LOG_NNDEBUG |
| 23 | #define ALOGVV(...) ALOGV(__VA_ARGS__) |
| 24 | #else |
| 25 | #define ALOGVV(...) ((void)0) |
| 26 | #endif |
| 27 | |
| 28 | #include <utils/Log.h> |
| 29 | #include <utils/Trace.h> |
| 30 | |
| 31 | #include "ZslProcessor.h" |
Mathias Agopian | 1a2952a | 2013-02-14 17:11:27 -0800 | [diff] [blame] | 32 | #include <gui/Surface.h> |
Eino-Ville Talvala | b99c5b8 | 2013-02-06 17:20:07 -0800 | [diff] [blame] | 33 | #include "../CameraDeviceBase.h" |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 34 | #include "../Camera2Client.h" |
| 35 | |
| 36 | |
| 37 | namespace android { |
| 38 | namespace camera2 { |
| 39 | |
| 40 | ZslProcessor::ZslProcessor( |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 41 | sp<Camera2Client> client, |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 42 | wp<CaptureSequencer> sequencer): |
| 43 | Thread(false), |
| 44 | mState(RUNNING), |
| 45 | mClient(client), |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 46 | mDevice(client->getCameraDevice()), |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 47 | mSequencer(sequencer), |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 48 | mId(client->getCameraId()), |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 49 | mZslBufferAvailable(false), |
| 50 | mZslStreamId(NO_STREAM), |
| 51 | mZslReprocessStreamId(NO_STREAM), |
| 52 | mFrameListHead(0), |
| 53 | mZslQueueHead(0), |
| 54 | mZslQueueTail(0) { |
| 55 | mZslQueue.insertAt(0, kZslBufferDepth); |
| 56 | mFrameList.insertAt(0, kFrameListDepth); |
| 57 | sp<CaptureSequencer> captureSequencer = mSequencer.promote(); |
| 58 | if (captureSequencer != 0) captureSequencer->setZslProcessor(this); |
| 59 | } |
| 60 | |
| 61 | ZslProcessor::~ZslProcessor() { |
| 62 | ALOGV("%s: Exit", __FUNCTION__); |
Eino-Ville Talvala | cf70d34 | 2012-09-05 19:02:43 -0700 | [diff] [blame] | 63 | deleteStream(); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | void ZslProcessor::onFrameAvailable() { |
| 67 | Mutex::Autolock l(mInputMutex); |
| 68 | if (!mZslBufferAvailable) { |
| 69 | mZslBufferAvailable = true; |
| 70 | mZslBufferAvailableSignal.signal(); |
| 71 | } |
| 72 | } |
| 73 | |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 74 | void ZslProcessor::onFrameAvailable(int32_t /*frameId*/, |
| 75 | const CameraMetadata &frame) { |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 76 | Mutex::Autolock l(mInputMutex); |
Eino-Ville Talvala | 4865c52 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 77 | camera_metadata_ro_entry_t entry; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 78 | entry = frame.find(ANDROID_SENSOR_TIMESTAMP); |
| 79 | nsecs_t timestamp = entry.data.i64[0]; |
Igor Murashkin | ddf3c50 | 2012-10-12 16:56:11 -0700 | [diff] [blame] | 80 | (void)timestamp; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 81 | ALOGVV("Got preview frame for timestamp %lld", timestamp); |
| 82 | |
| 83 | if (mState != RUNNING) return; |
| 84 | |
Eino-Ville Talvala | 4865c52 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 85 | mFrameList.editItemAt(mFrameListHead) = frame; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 86 | mFrameListHead = (mFrameListHead + 1) % kFrameListDepth; |
| 87 | |
| 88 | findMatchesLocked(); |
| 89 | } |
| 90 | |
| 91 | void ZslProcessor::onBufferReleased(buffer_handle_t *handle) { |
| 92 | Mutex::Autolock l(mInputMutex); |
| 93 | |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 94 | // Verify that the buffer is in our queue |
| 95 | size_t i = 0; |
| 96 | for (; i < mZslQueue.size(); i++) { |
| 97 | if (&(mZslQueue[i].buffer.mGraphicBuffer->handle) == handle) break; |
| 98 | } |
| 99 | if (i == mZslQueue.size()) { |
| 100 | ALOGW("%s: Released buffer %p not found in queue", |
| 101 | __FUNCTION__, handle); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 102 | } |
| 103 | |
Eino-Ville Talvala | 768cf09 | 2012-09-19 17:11:04 -0700 | [diff] [blame] | 104 | // Erase entire ZSL queue since we've now completed the capture and preview |
| 105 | // is stopped. |
| 106 | clearZslQueueLocked(); |
| 107 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 108 | mState = RUNNING; |
| 109 | } |
| 110 | |
| 111 | status_t ZslProcessor::updateStream(const Parameters ¶ms) { |
| 112 | ATRACE_CALL(); |
| 113 | ALOGV("%s: Configuring ZSL streams", __FUNCTION__); |
| 114 | status_t res; |
| 115 | |
| 116 | Mutex::Autolock l(mInputMutex); |
| 117 | |
| 118 | sp<Camera2Client> client = mClient.promote(); |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 119 | if (client == 0) { |
| 120 | ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId); |
| 121 | return INVALID_OPERATION; |
| 122 | } |
| 123 | sp<CameraDeviceBase> device = mDevice.promote(); |
| 124 | if (device == 0) { |
| 125 | ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId); |
| 126 | return INVALID_OPERATION; |
| 127 | } |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 128 | |
| 129 | if (mZslConsumer == 0) { |
| 130 | // Create CPU buffer queue endpoint |
| 131 | mZslConsumer = new BufferItemConsumer( |
| 132 | GRALLOC_USAGE_HW_CAMERA_ZSL, |
| 133 | kZslBufferDepth, |
| 134 | true); |
| 135 | mZslConsumer->setFrameAvailableListener(this); |
| 136 | mZslConsumer->setName(String8("Camera2Client::ZslConsumer")); |
Mathias Agopian | 1a2952a | 2013-02-14 17:11:27 -0800 | [diff] [blame] | 137 | mZslWindow = new Surface( |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 138 | mZslConsumer->getProducerInterface()); |
| 139 | } |
| 140 | |
| 141 | if (mZslStreamId != NO_STREAM) { |
| 142 | // Check if stream parameters have to change |
| 143 | uint32_t currentWidth, currentHeight; |
| 144 | res = device->getStreamInfo(mZslStreamId, |
| 145 | ¤tWidth, ¤tHeight, 0); |
| 146 | if (res != OK) { |
| 147 | ALOGE("%s: Camera %d: Error querying capture output stream info: " |
| 148 | "%s (%d)", __FUNCTION__, |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 149 | mId, strerror(-res), res); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 150 | return res; |
| 151 | } |
Eino-Ville Talvala | 6e4db89 | 2012-09-11 17:23:48 -0700 | [diff] [blame] | 152 | if (currentWidth != (uint32_t)params.fastInfo.arrayWidth || |
| 153 | currentHeight != (uint32_t)params.fastInfo.arrayHeight) { |
Eino-Ville Talvala | 47512a7 | 2012-09-10 13:30:43 -0700 | [diff] [blame] | 154 | res = device->deleteReprocessStream(mZslReprocessStreamId); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 155 | if (res != OK) { |
| 156 | ALOGE("%s: Camera %d: Unable to delete old reprocess stream " |
| 157 | "for ZSL: %s (%d)", __FUNCTION__, |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 158 | mId, strerror(-res), res); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 159 | return res; |
| 160 | } |
Igor Murashkin | ecf17e8 | 2012-10-02 16:05:11 -0700 | [diff] [blame] | 161 | ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed", |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 162 | __FUNCTION__, mId, mZslStreamId); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 163 | res = device->deleteStream(mZslStreamId); |
| 164 | if (res != OK) { |
| 165 | ALOGE("%s: Camera %d: Unable to delete old output stream " |
| 166 | "for ZSL: %s (%d)", __FUNCTION__, |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 167 | mId, strerror(-res), res); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 168 | return res; |
| 169 | } |
| 170 | mZslStreamId = NO_STREAM; |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | if (mZslStreamId == NO_STREAM) { |
| 175 | // Create stream for HAL production |
Eino-Ville Talvala | 6e4db89 | 2012-09-11 17:23:48 -0700 | [diff] [blame] | 176 | // TODO: Sort out better way to select resolution for ZSL |
Eino-Ville Talvala | e382ee2 | 2012-10-02 18:14:49 -0700 | [diff] [blame] | 177 | int streamType = params.quirks.useZslFormat ? |
| 178 | (int)CAMERA2_HAL_PIXEL_FORMAT_ZSL : |
| 179 | (int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 180 | res = device->createStream(mZslWindow, |
Eino-Ville Talvala | 6e4db89 | 2012-09-11 17:23:48 -0700 | [diff] [blame] | 181 | params.fastInfo.arrayWidth, params.fastInfo.arrayHeight, |
Eino-Ville Talvala | e382ee2 | 2012-10-02 18:14:49 -0700 | [diff] [blame] | 182 | streamType, 0, |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 183 | &mZslStreamId); |
| 184 | if (res != OK) { |
| 185 | ALOGE("%s: Camera %d: Can't create output stream for ZSL: " |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 186 | "%s (%d)", __FUNCTION__, mId, |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 187 | strerror(-res), res); |
| 188 | return res; |
| 189 | } |
| 190 | res = device->createReprocessStreamFromStream(mZslStreamId, |
| 191 | &mZslReprocessStreamId); |
| 192 | if (res != OK) { |
| 193 | ALOGE("%s: Camera %d: Can't create reprocess stream for ZSL: " |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 194 | "%s (%d)", __FUNCTION__, mId, |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 195 | strerror(-res), res); |
| 196 | return res; |
| 197 | } |
| 198 | } |
Eino-Ville Talvala | 4865c52 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 199 | client->registerFrameListener(Camera2Client::kPreviewRequestIdStart, |
| 200 | Camera2Client::kPreviewRequestIdEnd, |
| 201 | this); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 202 | |
| 203 | return OK; |
| 204 | } |
| 205 | |
| 206 | status_t ZslProcessor::deleteStream() { |
| 207 | ATRACE_CALL(); |
| 208 | status_t res; |
| 209 | |
| 210 | Mutex::Autolock l(mInputMutex); |
| 211 | |
| 212 | if (mZslStreamId != NO_STREAM) { |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 213 | sp<CameraDeviceBase> device = mDevice.promote(); |
| 214 | if (device == 0) { |
| 215 | ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId); |
| 216 | return INVALID_OPERATION; |
| 217 | } |
| 218 | |
| 219 | clearZslQueueLocked(); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 220 | |
Eino-Ville Talvala | 47512a7 | 2012-09-10 13:30:43 -0700 | [diff] [blame] | 221 | res = device->deleteReprocessStream(mZslReprocessStreamId); |
| 222 | if (res != OK) { |
| 223 | ALOGE("%s: Camera %d: Cannot delete ZSL reprocessing stream %d: " |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 224 | "%s (%d)", __FUNCTION__, mId, |
Eino-Ville Talvala | 47512a7 | 2012-09-10 13:30:43 -0700 | [diff] [blame] | 225 | mZslReprocessStreamId, strerror(-res), res); |
| 226 | return res; |
| 227 | } |
| 228 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 229 | mZslReprocessStreamId = NO_STREAM; |
Eino-Ville Talvala | 47512a7 | 2012-09-10 13:30:43 -0700 | [diff] [blame] | 230 | res = device->deleteStream(mZslStreamId); |
| 231 | if (res != OK) { |
| 232 | ALOGE("%s: Camera %d: Cannot delete ZSL output stream %d: " |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 233 | "%s (%d)", __FUNCTION__, mId, |
Eino-Ville Talvala | 47512a7 | 2012-09-10 13:30:43 -0700 | [diff] [blame] | 234 | mZslStreamId, strerror(-res), res); |
| 235 | return res; |
| 236 | } |
Eino-Ville Talvala | cf70d34 | 2012-09-05 19:02:43 -0700 | [diff] [blame] | 237 | |
| 238 | mZslWindow.clear(); |
| 239 | mZslConsumer.clear(); |
| 240 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 241 | mZslStreamId = NO_STREAM; |
| 242 | } |
| 243 | return OK; |
| 244 | } |
| 245 | |
| 246 | int ZslProcessor::getStreamId() const { |
| 247 | Mutex::Autolock l(mInputMutex); |
| 248 | return mZslStreamId; |
| 249 | } |
| 250 | |
| 251 | int ZslProcessor::getReprocessStreamId() const { |
| 252 | Mutex::Autolock l(mInputMutex); |
| 253 | return mZslReprocessStreamId; |
| 254 | } |
| 255 | |
| 256 | status_t ZslProcessor::pushToReprocess(int32_t requestId) { |
| 257 | ALOGV("%s: Send in reprocess request with id %d", |
| 258 | __FUNCTION__, requestId); |
| 259 | Mutex::Autolock l(mInputMutex); |
| 260 | status_t res; |
| 261 | sp<Camera2Client> client = mClient.promote(); |
| 262 | |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 263 | if (client == 0) { |
| 264 | ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId); |
| 265 | return INVALID_OPERATION; |
| 266 | } |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 267 | |
| 268 | IF_ALOGV() { |
| 269 | dumpZslQueue(-1); |
| 270 | } |
| 271 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 272 | if (mZslQueueTail != mZslQueueHead) { |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 273 | CameraMetadata request; |
| 274 | size_t index = mZslQueueTail; |
Eino-Ville Talvala | 4d410ed | 2012-10-06 13:50:31 -0700 | [diff] [blame] | 275 | while (index != mZslQueueHead) { |
| 276 | if (!mZslQueue[index].frame.isEmpty()) { |
| 277 | request = mZslQueue[index].frame; |
| 278 | break; |
| 279 | } |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 280 | index = (index + 1) % kZslBufferDepth; |
| 281 | } |
Eino-Ville Talvala | 4d410ed | 2012-10-06 13:50:31 -0700 | [diff] [blame] | 282 | if (index == mZslQueueHead) { |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 283 | ALOGV("%s: ZSL queue has no valid frames to send yet.", |
| 284 | __FUNCTION__); |
| 285 | return NOT_ENOUGH_DATA; |
| 286 | } |
| 287 | // Verify that the frame is reasonable for reprocessing |
| 288 | |
| 289 | camera_metadata_entry_t entry; |
| 290 | entry = request.find(ANDROID_CONTROL_AE_STATE); |
| 291 | if (entry.count == 0) { |
| 292 | ALOGE("%s: ZSL queue frame has no AE state field!", |
| 293 | __FUNCTION__); |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 294 | return BAD_VALUE; |
| 295 | } |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 296 | if (entry.data.u8[0] != ANDROID_CONTROL_AE_STATE_CONVERGED && |
| 297 | entry.data.u8[0] != ANDROID_CONTROL_AE_STATE_LOCKED) { |
| 298 | ALOGV("%s: ZSL queue frame AE state is %d, need full capture", |
| 299 | __FUNCTION__, entry.data.u8[0]); |
| 300 | return NOT_ENOUGH_DATA; |
| 301 | } |
| 302 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 303 | buffer_handle_t *handle = |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 304 | &(mZslQueue[index].buffer.mGraphicBuffer->handle); |
| 305 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 306 | uint8_t requestType = ANDROID_REQUEST_TYPE_REPROCESS; |
| 307 | res = request.update(ANDROID_REQUEST_TYPE, |
| 308 | &requestType, 1); |
Eino-Ville Talvala | b99c5b8 | 2013-02-06 17:20:07 -0800 | [diff] [blame] | 309 | uint8_t inputStreams[1] = |
| 310 | { static_cast<uint8_t>(mZslReprocessStreamId) }; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 311 | if (res == OK) request.update(ANDROID_REQUEST_INPUT_STREAMS, |
| 312 | inputStreams, 1); |
Eino-Ville Talvala | b99c5b8 | 2013-02-06 17:20:07 -0800 | [diff] [blame] | 313 | uint8_t outputStreams[1] = |
| 314 | { static_cast<uint8_t>(client->getCaptureStreamId()) }; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 315 | if (res == OK) request.update(ANDROID_REQUEST_OUTPUT_STREAMS, |
| 316 | outputStreams, 1); |
| 317 | res = request.update(ANDROID_REQUEST_ID, |
| 318 | &requestId, 1); |
| 319 | |
| 320 | if (res != OK ) { |
| 321 | ALOGE("%s: Unable to update frame to a reprocess request", __FUNCTION__); |
| 322 | return INVALID_OPERATION; |
| 323 | } |
| 324 | |
Eino-Ville Talvala | 4865c52 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 325 | res = client->stopStream(); |
Alex Ray | c206305 | 2012-10-02 23:30:07 -0700 | [diff] [blame] | 326 | if (res != OK) { |
| 327 | ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: " |
| 328 | "%s (%d)", |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 329 | __FUNCTION__, mId, strerror(-res), res); |
Alex Ray | c206305 | 2012-10-02 23:30:07 -0700 | [diff] [blame] | 330 | return INVALID_OPERATION; |
| 331 | } |
| 332 | // TODO: have push-and-clear be atomic |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 333 | res = client->getCameraDevice()->pushReprocessBuffer(mZslReprocessStreamId, |
| 334 | handle, this); |
| 335 | if (res != OK) { |
| 336 | ALOGE("%s: Unable to push buffer for reprocessing: %s (%d)", |
| 337 | __FUNCTION__, strerror(-res), res); |
| 338 | return res; |
| 339 | } |
| 340 | |
Eino-Ville Talvala | ec77108 | 2012-10-04 13:21:08 -0700 | [diff] [blame] | 341 | // Update JPEG settings |
| 342 | { |
| 343 | SharedParameters::Lock l(client->getParameters()); |
| 344 | res = l.mParameters.updateRequestJpeg(&request); |
| 345 | if (res != OK) { |
| 346 | ALOGE("%s: Camera %d: Unable to update JPEG entries of ZSL " |
| 347 | "capture request: %s (%d)", __FUNCTION__, |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 348 | mId, |
Eino-Ville Talvala | ec77108 | 2012-10-04 13:21:08 -0700 | [diff] [blame] | 349 | strerror(-res), res); |
| 350 | return res; |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | mLatestCapturedRequest = request; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 355 | res = client->getCameraDevice()->capture(request); |
| 356 | if (res != OK ) { |
| 357 | ALOGE("%s: Unable to send ZSL reprocess request to capture: %s (%d)", |
| 358 | __FUNCTION__, strerror(-res), res); |
| 359 | return res; |
| 360 | } |
| 361 | |
| 362 | mState = LOCKED; |
| 363 | } else { |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 364 | ALOGV("%s: No ZSL buffers yet", __FUNCTION__); |
| 365 | return NOT_ENOUGH_DATA; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 366 | } |
| 367 | return OK; |
| 368 | } |
| 369 | |
Eino-Ville Talvala | 768cf09 | 2012-09-19 17:11:04 -0700 | [diff] [blame] | 370 | status_t ZslProcessor::clearZslQueue() { |
| 371 | Mutex::Autolock l(mInputMutex); |
| 372 | // If in middle of capture, can't clear out queue |
| 373 | if (mState == LOCKED) return OK; |
| 374 | |
| 375 | return clearZslQueueLocked(); |
| 376 | } |
| 377 | |
| 378 | status_t ZslProcessor::clearZslQueueLocked() { |
| 379 | for (size_t i = 0; i < mZslQueue.size(); i++) { |
| 380 | if (mZslQueue[i].buffer.mTimestamp != 0) { |
| 381 | mZslConsumer->releaseBuffer(mZslQueue[i].buffer); |
| 382 | } |
| 383 | mZslQueue.replaceAt(i); |
| 384 | } |
| 385 | mZslQueueHead = 0; |
| 386 | mZslQueueTail = 0; |
| 387 | return OK; |
| 388 | } |
| 389 | |
Igor Murashkin | ddf3c50 | 2012-10-12 16:56:11 -0700 | [diff] [blame] | 390 | void ZslProcessor::dump(int fd, const Vector<String16>& /*args*/) const { |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 391 | Mutex::Autolock l(mInputMutex); |
Eino-Ville Talvala | ec77108 | 2012-10-04 13:21:08 -0700 | [diff] [blame] | 392 | if (!mLatestCapturedRequest.isEmpty()) { |
| 393 | String8 result(" Latest ZSL capture request:\n"); |
| 394 | write(fd, result.string(), result.size()); |
| 395 | mLatestCapturedRequest.dump(fd, 2, 6); |
| 396 | } else { |
| 397 | String8 result(" Latest ZSL capture request: none yet\n"); |
| 398 | write(fd, result.string(), result.size()); |
| 399 | } |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 400 | dumpZslQueue(fd); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 401 | } |
| 402 | |
| 403 | bool ZslProcessor::threadLoop() { |
| 404 | status_t res; |
| 405 | |
| 406 | { |
| 407 | Mutex::Autolock l(mInputMutex); |
| 408 | while (!mZslBufferAvailable) { |
| 409 | res = mZslBufferAvailableSignal.waitRelative(mInputMutex, |
| 410 | kWaitDuration); |
| 411 | if (res == TIMED_OUT) return true; |
| 412 | } |
| 413 | mZslBufferAvailable = false; |
| 414 | } |
| 415 | |
| 416 | do { |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 417 | res = processNewZslBuffer(); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 418 | } while (res == OK); |
| 419 | |
| 420 | return true; |
| 421 | } |
| 422 | |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 423 | status_t ZslProcessor::processNewZslBuffer() { |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 424 | ATRACE_CALL(); |
| 425 | status_t res; |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 426 | sp<BufferItemConsumer> zslConsumer; |
| 427 | { |
| 428 | Mutex::Autolock l(mInputMutex); |
| 429 | if (mZslConsumer == 0) return OK; |
| 430 | zslConsumer = mZslConsumer; |
| 431 | } |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 432 | ALOGVV("Trying to get next buffer"); |
| 433 | BufferItemConsumer::BufferItem item; |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 434 | res = zslConsumer->acquireBuffer(&item); |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 435 | if (res != OK) { |
| 436 | if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) { |
| 437 | ALOGE("%s: Camera %d: Error receiving ZSL image buffer: " |
| 438 | "%s (%d)", __FUNCTION__, |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 439 | mId, strerror(-res), res); |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 440 | } else { |
| 441 | ALOGVV(" No buffer"); |
| 442 | } |
| 443 | return res; |
| 444 | } |
| 445 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 446 | Mutex::Autolock l(mInputMutex); |
| 447 | |
| 448 | if (mState == LOCKED) { |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 449 | ALOGVV("In capture, discarding new ZSL buffers"); |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 450 | zslConsumer->releaseBuffer(item); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 451 | return OK; |
| 452 | } |
| 453 | |
| 454 | ALOGVV("Got ZSL buffer: head: %d, tail: %d", mZslQueueHead, mZslQueueTail); |
| 455 | |
| 456 | if ( (mZslQueueHead + 1) % kZslBufferDepth == mZslQueueTail) { |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 457 | ALOGVV("Releasing oldest buffer"); |
Eino-Ville Talvala | d09801b | 2013-04-23 15:16:57 -0700 | [diff] [blame^] | 458 | zslConsumer->releaseBuffer(mZslQueue[mZslQueueTail].buffer); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 459 | mZslQueue.replaceAt(mZslQueueTail); |
| 460 | mZslQueueTail = (mZslQueueTail + 1) % kZslBufferDepth; |
| 461 | } |
| 462 | |
| 463 | ZslPair &queueHead = mZslQueue.editItemAt(mZslQueueHead); |
| 464 | |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 465 | queueHead.buffer = item; |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 466 | queueHead.frame.release(); |
| 467 | |
| 468 | mZslQueueHead = (mZslQueueHead + 1) % kZslBufferDepth; |
| 469 | |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 470 | ALOGVV(" Acquired buffer, timestamp %lld", queueHead.buffer.mTimestamp); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 471 | |
| 472 | findMatchesLocked(); |
| 473 | |
| 474 | return OK; |
| 475 | } |
| 476 | |
| 477 | void ZslProcessor::findMatchesLocked() { |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 478 | ALOGVV("Scanning"); |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 479 | for (size_t i = 0; i < mZslQueue.size(); i++) { |
| 480 | ZslPair &queueEntry = mZslQueue.editItemAt(i); |
| 481 | nsecs_t bufferTimestamp = queueEntry.buffer.mTimestamp; |
Eino-Ville Talvala | bdde5f8 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 482 | IF_ALOGV() { |
| 483 | camera_metadata_entry_t entry; |
| 484 | nsecs_t frameTimestamp = 0; |
| 485 | if (!queueEntry.frame.isEmpty()) { |
| 486 | entry = queueEntry.frame.find(ANDROID_SENSOR_TIMESTAMP); |
| 487 | frameTimestamp = entry.data.i64[0]; |
| 488 | } |
| 489 | ALOGVV(" %d: b: %lld\tf: %lld", i, |
| 490 | bufferTimestamp, frameTimestamp ); |
| 491 | } |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 492 | if (queueEntry.frame.isEmpty() && bufferTimestamp != 0) { |
| 493 | // Have buffer, no matching frame. Look for one |
| 494 | for (size_t j = 0; j < mFrameList.size(); j++) { |
| 495 | bool match = false; |
| 496 | CameraMetadata &frame = mFrameList.editItemAt(j); |
| 497 | if (!frame.isEmpty()) { |
| 498 | camera_metadata_entry_t entry; |
| 499 | entry = frame.find(ANDROID_SENSOR_TIMESTAMP); |
| 500 | if (entry.count == 0) { |
| 501 | ALOGE("%s: Can't find timestamp in frame!", |
| 502 | __FUNCTION__); |
| 503 | continue; |
| 504 | } |
| 505 | nsecs_t frameTimestamp = entry.data.i64[0]; |
| 506 | if (bufferTimestamp == frameTimestamp) { |
| 507 | ALOGVV("%s: Found match %lld", __FUNCTION__, |
| 508 | frameTimestamp); |
| 509 | match = true; |
| 510 | } else { |
| 511 | int64_t delta = abs(bufferTimestamp - frameTimestamp); |
| 512 | if ( delta < 1000000) { |
| 513 | ALOGVV("%s: Found close match %lld (delta %lld)", |
| 514 | __FUNCTION__, bufferTimestamp, delta); |
| 515 | match = true; |
| 516 | } |
| 517 | } |
| 518 | } |
| 519 | if (match) { |
| 520 | queueEntry.frame.acquire(frame); |
| 521 | break; |
| 522 | } |
| 523 | } |
| 524 | } |
| 525 | } |
| 526 | } |
| 527 | |
Eino-Ville Talvala | 97b38a8 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 528 | void ZslProcessor::dumpZslQueue(int fd) const { |
| 529 | String8 header("ZSL queue contents:"); |
| 530 | String8 indent(" "); |
| 531 | ALOGV("%s", header.string()); |
| 532 | if (fd != -1) { |
| 533 | header = indent + header + "\n"; |
| 534 | write(fd, header.string(), header.size()); |
| 535 | } |
| 536 | for (size_t i = 0; i < mZslQueue.size(); i++) { |
| 537 | const ZslPair &queueEntry = mZslQueue[i]; |
| 538 | nsecs_t bufferTimestamp = queueEntry.buffer.mTimestamp; |
| 539 | camera_metadata_ro_entry_t entry; |
| 540 | nsecs_t frameTimestamp = 0; |
| 541 | int frameAeState = -1; |
| 542 | if (!queueEntry.frame.isEmpty()) { |
| 543 | entry = queueEntry.frame.find(ANDROID_SENSOR_TIMESTAMP); |
| 544 | if (entry.count > 0) frameTimestamp = entry.data.i64[0]; |
| 545 | entry = queueEntry.frame.find(ANDROID_CONTROL_AE_STATE); |
| 546 | if (entry.count > 0) frameAeState = entry.data.u8[0]; |
| 547 | } |
| 548 | String8 result = |
| 549 | String8::format(" %d: b: %lld\tf: %lld, AE state: %d", i, |
| 550 | bufferTimestamp, frameTimestamp, frameAeState); |
| 551 | ALOGV("%s", result.string()); |
| 552 | if (fd != -1) { |
| 553 | result = indent + result + "\n"; |
| 554 | write(fd, result.string(), result.size()); |
| 555 | } |
| 556 | |
| 557 | } |
| 558 | } |
| 559 | |
Eino-Ville Talvala | da6665c | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 560 | }; // namespace camera2 |
| 561 | }; // namespace android |