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