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