CaptureSequencer.cpp revision 609acc0c96bc2aedd42246862b537e045f5184b6
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::CaptureSequencer" 18#define ATRACE_TAG ATRACE_TAG_CAMERA 19//#define LOG_NDEBUG 0 20 21#include <utils/Log.h> 22#include <utils/Trace.h> 23#include <utils/Vector.h> 24 25#include "CaptureSequencer.h" 26#include "../Camera2Device.h" 27#include "../Camera2Client.h" 28#include "Parameters.h" 29 30namespace android { 31namespace camera2 { 32 33/** Public members */ 34 35CaptureSequencer::CaptureSequencer(wp<Camera2Client> client): 36 Thread(false), 37 mStartCapture(false), 38 mBusy(false), 39 mNewAEState(false), 40 mNewFrameReceived(false), 41 mNewCaptureReceived(false), 42 mClient(client), 43 mCaptureState(IDLE), 44 mTriggerId(0), 45 mTimeoutCount(0), 46 mCaptureId(Camera2Client::kFirstCaptureRequestId) { 47} 48 49CaptureSequencer::~CaptureSequencer() { 50 ALOGV("%s: Exit", __FUNCTION__); 51} 52 53void CaptureSequencer::setZslProcessor(wp<ZslProcessor> processor) { 54 Mutex::Autolock l(mInputMutex); 55 mZslProcessor = processor; 56} 57 58status_t CaptureSequencer::startCapture() { 59 ATRACE_CALL(); 60 Mutex::Autolock l(mInputMutex); 61 if (mBusy) { 62 ALOGE("%s: Already busy capturing!", __FUNCTION__); 63 return INVALID_OPERATION; 64 } 65 if (!mStartCapture) { 66 mStartCapture = true; 67 mStartCaptureSignal.signal(); 68 } 69 return OK; 70} 71 72void CaptureSequencer::notifyAutoExposure(uint8_t newState, int triggerId) { 73 ATRACE_CALL(); 74 Mutex::Autolock l(mInputMutex); 75 mAEState = newState; 76 mAETriggerId = triggerId; 77 if (!mNewAEState) { 78 mNewAEState = true; 79 mNewNotifySignal.signal(); 80 } 81} 82 83void CaptureSequencer::onFrameAvailable(int32_t frameId, 84 CameraMetadata &frame) { 85 ATRACE_CALL(); 86 Mutex::Autolock l(mInputMutex); 87 mNewFrameId = frameId; 88 mNewFrame.acquire(frame); 89 if (!mNewFrameReceived) { 90 mNewFrameReceived = true; 91 mNewFrameSignal.signal(); 92 } 93} 94 95void CaptureSequencer::onCaptureAvailable(nsecs_t timestamp) { 96 ATRACE_CALL(); 97 Mutex::Autolock l(mInputMutex); 98 mCaptureTimestamp = timestamp; 99 if (!mNewCaptureReceived) { 100 mNewCaptureReceived = true; 101 mNewCaptureSignal.signal(); 102 } 103} 104 105 106void CaptureSequencer::dump(int fd, const Vector<String16>& args) { 107 String8 result; 108 if (mCaptureRequest.entryCount() != 0) { 109 result = " Capture request:\n"; 110 write(fd, result.string(), result.size()); 111 mCaptureRequest.dump(fd, 2, 6); 112 } else { 113 result = " Capture request: undefined\n"; 114 write(fd, result.string(), result.size()); 115 } 116 result = String8::format(" Current capture state: %s\n", 117 kStateNames[mCaptureState]); 118 result.append(" Latest captured frame:\n"); 119 write(fd, result.string(), result.size()); 120 mNewFrame.dump(fd, 2, 6); 121} 122 123/** Private members */ 124 125const char* CaptureSequencer::kStateNames[CaptureSequencer::NUM_CAPTURE_STATES+1] = 126{ 127 "IDLE", 128 "START", 129 "ZSL_START", 130 "ZSL_WAITING", 131 "ZSL_REPROCESSING", 132 "STANDARD_START", 133 "STANDARD_PRECAPTURE", 134 "STANDARD_CAPTURING", 135 "DONE", 136 "ERROR", 137 "UNKNOWN" 138}; 139 140const CaptureSequencer::StateManager 141 CaptureSequencer::kStateManagers[CaptureSequencer::NUM_CAPTURE_STATES-1] = { 142 &CaptureSequencer::manageIdle, 143 &CaptureSequencer::manageStart, 144 &CaptureSequencer::manageZslStart, 145 &CaptureSequencer::manageZslWaiting, 146 &CaptureSequencer::manageZslReprocessing, 147 &CaptureSequencer::manageStandardStart, 148 &CaptureSequencer::manageStandardPrecaptureWait, 149 &CaptureSequencer::manageStandardCapture, 150 &CaptureSequencer::manageStandardCaptureWait, 151 &CaptureSequencer::manageDone, 152}; 153 154bool CaptureSequencer::threadLoop() { 155 status_t res; 156 157 sp<Camera2Client> client = mClient.promote(); 158 if (client == 0) return false; 159 160 if (mCaptureState < ERROR) { 161 mCaptureState = (this->*kStateManagers[mCaptureState])(client); 162 } else { 163 ALOGE("%s: Bad capture state: %s", 164 __FUNCTION__, kStateNames[mCaptureState]); 165 return false; 166 } 167 168 return true; 169} 170 171CaptureSequencer::CaptureState CaptureSequencer::manageIdle(sp<Camera2Client> &client) { 172 status_t res; 173 ATRACE_CALL(); 174 Mutex::Autolock l(mInputMutex); 175 while (!mStartCapture) { 176 res = mStartCaptureSignal.waitRelative(mInputMutex, 177 kWaitDuration); 178 if (res == TIMED_OUT) break; 179 } 180 if (mStartCapture) { 181 mStartCapture = false; 182 mBusy = true; 183 return START; 184 } 185 return IDLE; 186} 187 188CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &client) { 189 status_t res; 190 ATRACE_CALL(); 191 mCaptureId++; 192 193 { 194 Mutex::Autolock l(mInputMutex); 195 mBusy = false; 196 } 197 198 SharedParameters::Lock l(client->getParameters()); 199 switch (l.mParameters.state) { 200 case Parameters::STILL_CAPTURE: 201 l.mParameters.state = Parameters::STOPPED; 202 break; 203 case Parameters::VIDEO_SNAPSHOT: 204 l.mParameters.state = Parameters::RECORD; 205 break; 206 default: 207 ALOGE("%s: Camera %d: Still image produced unexpectedly " 208 "in state %s!", 209 __FUNCTION__, client->getCameraId(), 210 Parameters::getStateName(l.mParameters.state)); 211 } 212 213 return IDLE; 214} 215 216CaptureSequencer::CaptureState CaptureSequencer::manageStart( 217 sp<Camera2Client> &client) { 218 status_t res; 219 ATRACE_CALL(); 220 SharedParameters::Lock l(client->getParameters()); 221 CaptureState nextState = DONE; 222 223 res = updateCaptureRequest(l.mParameters, client); 224 if (res != OK ) { 225 ALOGE("%s: Camera %d: Can't update still image capture request: %s (%d)", 226 __FUNCTION__, client->getCameraId(), strerror(-res), res); 227 return DONE; 228 } 229 230 if (l.mParameters.zslMode && 231 l.mParameters.state == Parameters::STILL_CAPTURE) { 232 nextState = ZSL_START; 233 } else { 234 nextState = STANDARD_START; 235 } 236 237 return nextState; 238} 239 240CaptureSequencer::CaptureState CaptureSequencer::manageZslStart( 241 sp<Camera2Client> &client) { 242 status_t res; 243 sp<ZslProcessor> processor = mZslProcessor.promote(); 244 if (processor == 0) { 245 ALOGE("%s: No ZSL queue to use!", __FUNCTION__); 246 return DONE; 247 } 248 249 client->registerFrameListener(mCaptureId, 250 this); 251 252 res = client->getCameraDevice()->clearStreamingRequest(); 253 if (res != OK) { 254 ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: " 255 "%s (%d)", 256 __FUNCTION__, client->getCameraId(), strerror(-res), res); 257 return DONE; 258 } 259 // TODO: Actually select the right thing here. 260 processor->pushToReprocess(mCaptureId); 261 262 mTimeoutCount = kMaxTimeoutsForCaptureEnd; 263 return STANDARD_CAPTURE_WAIT; 264} 265 266CaptureSequencer::CaptureState CaptureSequencer::manageZslWaiting( 267 sp<Camera2Client> &client) { 268 return DONE; 269} 270 271CaptureSequencer::CaptureState CaptureSequencer::manageZslReprocessing( 272 sp<Camera2Client> &client) { 273 return START; 274} 275 276CaptureSequencer::CaptureState CaptureSequencer::manageStandardStart( 277 sp<Camera2Client> &client) { 278 ATRACE_CALL(); 279 client->registerFrameListener(mCaptureId, 280 this); 281 { 282 SharedParameters::Lock l(client->getParameters()); 283 mTriggerId = l.mParameters.precaptureTriggerCounter++; 284 } 285 client->getCameraDevice()->triggerPrecaptureMetering(mTriggerId); 286 287 mAeInPrecapture = false; 288 mTimeoutCount = kMaxTimeoutsForPrecaptureStart; 289 return STANDARD_PRECAPTURE_WAIT; 290} 291 292CaptureSequencer::CaptureState CaptureSequencer::manageStandardPrecaptureWait( 293 sp<Camera2Client> &client) { 294 status_t res; 295 ATRACE_CALL(); 296 Mutex::Autolock l(mInputMutex); 297 while (!mNewAEState) { 298 res = mNewNotifySignal.waitRelative(mInputMutex, kWaitDuration); 299 if (res == TIMED_OUT) { 300 mTimeoutCount--; 301 break; 302 } 303 } 304 if (mTimeoutCount <= 0) { 305 ALOGW("Timed out waiting for precapture %s", 306 mAeInPrecapture ? "end" : "start"); 307 return STANDARD_CAPTURE; 308 } 309 if (mNewAEState) { 310 if (!mAeInPrecapture) { 311 // Waiting to see PRECAPTURE state 312 if (mAETriggerId == mTriggerId && 313 mAEState == ANDROID_CONTROL_AE_STATE_PRECAPTURE) { 314 ALOGV("%s: Got precapture start", __FUNCTION__); 315 mAeInPrecapture = true; 316 mTimeoutCount = kMaxTimeoutsForPrecaptureEnd; 317 } 318 } else { 319 // Waiting to see PRECAPTURE state end 320 if (mAETriggerId == mTriggerId && 321 mAEState != ANDROID_CONTROL_AE_STATE_PRECAPTURE) { 322 ALOGV("%s: Got precapture end", __FUNCTION__); 323 return STANDARD_CAPTURE; 324 } 325 } 326 mNewAEState = false; 327 } 328 return STANDARD_PRECAPTURE_WAIT; 329} 330 331CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture( 332 sp<Camera2Client> &client) { 333 status_t res; 334 ATRACE_CALL(); 335 SharedParameters::Lock l(client->getParameters()); 336 Vector<uint8_t> outputStreams; 337 338 outputStreams.push(client->getPreviewStreamId()); 339 outputStreams.push(client->getCaptureStreamId()); 340 341 if (l.mParameters.previewCallbackFlags & 342 CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) { 343 outputStreams.push(client->getCallbackStreamId()); 344 } 345 346 if (l.mParameters.state == Parameters::VIDEO_SNAPSHOT) { 347 outputStreams.push(client->getRecordingStreamId()); 348 } 349 350 res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, 351 outputStreams); 352 if (res == OK) { 353 res = mCaptureRequest.update(ANDROID_REQUEST_ID, 354 &mCaptureId, 1); 355 } 356 if (res == OK) { 357 res = mCaptureRequest.sort(); 358 } 359 360 if (res != OK) { 361 ALOGE("%s: Camera %d: Unable to set up still capture request: %s (%d)", 362 __FUNCTION__, client->getCameraId(), strerror(-res), res); 363 return DONE; 364 } 365 366 CameraMetadata captureCopy = mCaptureRequest; 367 if (captureCopy.entryCount() == 0) { 368 ALOGE("%s: Camera %d: Unable to copy capture request for HAL device", 369 __FUNCTION__, client->getCameraId()); 370 return DONE; 371 } 372 373 if (l.mParameters.state == Parameters::STILL_CAPTURE) { 374 res = client->getCameraDevice()->clearStreamingRequest(); 375 if (res != OK) { 376 ALOGE("%s: Camera %d: Unable to stop preview for still capture: " 377 "%s (%d)", 378 __FUNCTION__, client->getCameraId(), strerror(-res), res); 379 return DONE; 380 } 381 } 382 // TODO: Capture should be atomic with setStreamingRequest here 383 res = client->getCameraDevice()->capture(captureCopy); 384 if (res != OK) { 385 ALOGE("%s: Camera %d: Unable to submit still image capture request: " 386 "%s (%d)", 387 __FUNCTION__, client->getCameraId(), strerror(-res), res); 388 return DONE; 389 } 390 391 if (l.mParameters.playShutterSound) { 392 client->getCameraService()->playSound(CameraService::SOUND_SHUTTER); 393 } 394 395 mTimeoutCount = kMaxTimeoutsForCaptureEnd; 396 return STANDARD_CAPTURE_WAIT; 397} 398 399CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait( 400 sp<Camera2Client> &client) { 401 status_t res; 402 ATRACE_CALL(); 403 Mutex::Autolock l(mInputMutex); 404 while (!mNewFrameReceived) { 405 res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration); 406 if (res == TIMED_OUT) { 407 mTimeoutCount--; 408 break; 409 } 410 } 411 while (!mNewCaptureReceived) { 412 res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration); 413 if (res == TIMED_OUT) { 414 mTimeoutCount--; 415 break; 416 } 417 } 418 if (mTimeoutCount <= 0) { 419 ALOGW("Timed out waiting for capture to complete"); 420 return DONE; 421 } 422 if (mNewFrameReceived && mNewCaptureReceived) { 423 if (mNewFrameId != mCaptureId) { 424 ALOGW("Mismatched capture frame IDs: Expected %d, got %d", 425 mCaptureId, mNewFrameId); 426 } 427 camera_metadata_entry_t entry; 428 entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP); 429 if (entry.count == 0) { 430 ALOGE("No timestamp field in capture frame!"); 431 } 432 if (entry.data.i64[0] != mCaptureTimestamp) { 433 ALOGW("Mismatched capture timestamps: Metadata frame %lld," 434 " captured buffer %lld", entry.data.i64[0], mCaptureTimestamp); 435 } 436 client->removeFrameListener(mCaptureId); 437 438 mNewFrameReceived = false; 439 mNewCaptureReceived = false; 440 return DONE; 441 } 442 return STANDARD_CAPTURE_WAIT; 443} 444 445status_t CaptureSequencer::updateCaptureRequest(const Parameters ¶ms, 446 sp<Camera2Client> &client) { 447 ATRACE_CALL(); 448 status_t res; 449 if (mCaptureRequest.entryCount() == 0) { 450 res = client->getCameraDevice()->createDefaultRequest( 451 CAMERA2_TEMPLATE_STILL_CAPTURE, 452 &mCaptureRequest); 453 if (res != OK) { 454 ALOGE("%s: Camera %d: Unable to create default still image request:" 455 " %s (%d)", __FUNCTION__, client->getCameraId(), 456 strerror(-res), res); 457 return res; 458 } 459 } 460 461 res = params.updateRequest(&mCaptureRequest); 462 if (res != OK) { 463 ALOGE("%s: Camera %d: Unable to update common entries of capture " 464 "request: %s (%d)", __FUNCTION__, client->getCameraId(), 465 strerror(-res), res); 466 return res; 467 } 468 469 res = mCaptureRequest.update(ANDROID_JPEG_THUMBNAIL_SIZE, 470 params.jpegThumbSize, 2); 471 if (res != OK) return res; 472 res = mCaptureRequest.update(ANDROID_JPEG_THUMBNAIL_QUALITY, 473 ¶ms.jpegThumbQuality, 1); 474 if (res != OK) return res; 475 res = mCaptureRequest.update(ANDROID_JPEG_QUALITY, 476 ¶ms.jpegQuality, 1); 477 if (res != OK) return res; 478 res = mCaptureRequest.update( 479 ANDROID_JPEG_ORIENTATION, 480 ¶ms.jpegRotation, 1); 481 if (res != OK) return res; 482 483 if (params.gpsEnabled) { 484 res = mCaptureRequest.update( 485 ANDROID_JPEG_GPS_COORDINATES, 486 params.gpsCoordinates, 3); 487 if (res != OK) return res; 488 res = mCaptureRequest.update( 489 ANDROID_JPEG_GPS_TIMESTAMP, 490 ¶ms.gpsTimestamp, 1); 491 if (res != OK) return res; 492 res = mCaptureRequest.update( 493 ANDROID_JPEG_GPS_PROCESSING_METHOD, 494 params.gpsProcessingMethod); 495 if (res != OK) return res; 496 } else { 497 res = mCaptureRequest.erase(ANDROID_JPEG_GPS_COORDINATES); 498 if (res != OK) return res; 499 res = mCaptureRequest.erase(ANDROID_JPEG_GPS_TIMESTAMP); 500 if (res != OK) return res; 501 res = mCaptureRequest.erase(ANDROID_JPEG_GPS_PROCESSING_METHOD); 502 if (res != OK) return res; 503 } 504 505 return OK; 506} 507 508 509}; // namespace camera2 510}; // namespace android 511