| Eino-Ville Talvala | 69230df | 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 | 852c381 | 2012-09-24 09:46:53 -0700 | [diff] [blame] | 17 | #define LOG_TAG "Camera2-CaptureSequencer" | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 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" | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 26 | #include "BurstCapture.h" | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 27 | #include "../Camera2Device.h" | 
 | 28 | #include "../Camera2Client.h" | 
 | 29 | #include "Parameters.h" | 
 | 30 |  | 
 | 31 | namespace android { | 
 | 32 | namespace camera2 { | 
 | 33 |  | 
 | 34 | /** Public members */ | 
 | 35 |  | 
 | 36 | CaptureSequencer::CaptureSequencer(wp<Camera2Client> client): | 
 | 37 |         Thread(false), | 
 | 38 |         mStartCapture(false), | 
 | 39 |         mBusy(false), | 
 | 40 |         mNewAEState(false), | 
 | 41 |         mNewFrameReceived(false), | 
 | 42 |         mNewCaptureReceived(false), | 
 | 43 |         mClient(client), | 
 | 44 |         mCaptureState(IDLE), | 
 | 45 |         mTriggerId(0), | 
 | 46 |         mTimeoutCount(0), | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 47 |         mCaptureId(Camera2Client::kCaptureRequestIdStart) { | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 48 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 49 | } | 
 | 50 |  | 
 | 51 | CaptureSequencer::~CaptureSequencer() { | 
 | 52 |     ALOGV("%s: Exit", __FUNCTION__); | 
 | 53 | } | 
 | 54 |  | 
 | 55 | void CaptureSequencer::setZslProcessor(wp<ZslProcessor> processor) { | 
 | 56 |     Mutex::Autolock l(mInputMutex); | 
 | 57 |     mZslProcessor = processor; | 
 | 58 | } | 
 | 59 |  | 
 | 60 | status_t CaptureSequencer::startCapture() { | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 61 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 62 |     ATRACE_CALL(); | 
 | 63 |     Mutex::Autolock l(mInputMutex); | 
 | 64 |     if (mBusy) { | 
 | 65 |         ALOGE("%s: Already busy capturing!", __FUNCTION__); | 
 | 66 |         return INVALID_OPERATION; | 
 | 67 |     } | 
 | 68 |     if (!mStartCapture) { | 
 | 69 |         mStartCapture = true; | 
 | 70 |         mStartCaptureSignal.signal(); | 
 | 71 |     } | 
 | 72 |     return OK; | 
 | 73 | } | 
 | 74 |  | 
| Eino-Ville Talvala | e049384 | 2012-10-05 12:03:10 -0700 | [diff] [blame^] | 75 | status_t CaptureSequencer::waitUntilIdle(nsecs_t timeout) { | 
 | 76 |     ATRACE_CALL(); | 
 | 77 |     ALOGV("%s: Waiting for idle", __FUNCTION__); | 
 | 78 |     Mutex::Autolock l(mStateMutex); | 
 | 79 |     status_t res = -1; | 
 | 80 |     while (mCaptureState != IDLE) { | 
 | 81 |         nsecs_t startTime = systemTime(); | 
 | 82 |  | 
 | 83 |         res = mStateChanged.waitRelative(mStateMutex, timeout); | 
 | 84 |         if (res != OK) return res; | 
 | 85 |  | 
 | 86 |         timeout -= (systemTime() - startTime); | 
 | 87 |     } | 
 | 88 |     ALOGV("%s: Now idle", __FUNCTION__); | 
 | 89 |     return OK; | 
 | 90 | } | 
 | 91 |  | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 92 | void CaptureSequencer::notifyAutoExposure(uint8_t newState, int triggerId) { | 
 | 93 |     ATRACE_CALL(); | 
 | 94 |     Mutex::Autolock l(mInputMutex); | 
 | 95 |     mAEState = newState; | 
 | 96 |     mAETriggerId = triggerId; | 
 | 97 |     if (!mNewAEState) { | 
 | 98 |         mNewAEState = true; | 
 | 99 |         mNewNotifySignal.signal(); | 
 | 100 |     } | 
 | 101 | } | 
 | 102 |  | 
 | 103 | void CaptureSequencer::onFrameAvailable(int32_t frameId, | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 104 |         const CameraMetadata &frame) { | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 105 |     ALOGV("%s: Listener found new frame", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 106 |     ATRACE_CALL(); | 
 | 107 |     Mutex::Autolock l(mInputMutex); | 
 | 108 |     mNewFrameId = frameId; | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 109 |     mNewFrame = frame; | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 110 |     if (!mNewFrameReceived) { | 
 | 111 |         mNewFrameReceived = true; | 
 | 112 |         mNewFrameSignal.signal(); | 
 | 113 |     } | 
 | 114 | } | 
 | 115 |  | 
| Eino-Ville Talvala | 52e9ad4 | 2012-09-19 17:09:15 -0700 | [diff] [blame] | 116 | void CaptureSequencer::onCaptureAvailable(nsecs_t timestamp, | 
 | 117 |         sp<MemoryBase> captureBuffer) { | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 118 |     ATRACE_CALL(); | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 119 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 120 |     Mutex::Autolock l(mInputMutex); | 
 | 121 |     mCaptureTimestamp = timestamp; | 
| Eino-Ville Talvala | 52e9ad4 | 2012-09-19 17:09:15 -0700 | [diff] [blame] | 122 |     mCaptureBuffer = captureBuffer; | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 123 |     if (!mNewCaptureReceived) { | 
 | 124 |         mNewCaptureReceived = true; | 
 | 125 |         mNewCaptureSignal.signal(); | 
 | 126 |     } | 
 | 127 | } | 
 | 128 |  | 
 | 129 |  | 
 | 130 | void CaptureSequencer::dump(int fd, const Vector<String16>& args) { | 
 | 131 |     String8 result; | 
 | 132 |     if (mCaptureRequest.entryCount() != 0) { | 
 | 133 |         result = "    Capture request:\n"; | 
 | 134 |         write(fd, result.string(), result.size()); | 
 | 135 |         mCaptureRequest.dump(fd, 2, 6); | 
 | 136 |     } else { | 
 | 137 |         result = "    Capture request: undefined\n"; | 
 | 138 |         write(fd, result.string(), result.size()); | 
 | 139 |     } | 
 | 140 |     result = String8::format("    Current capture state: %s\n", | 
 | 141 |             kStateNames[mCaptureState]); | 
 | 142 |     result.append("    Latest captured frame:\n"); | 
 | 143 |     write(fd, result.string(), result.size()); | 
 | 144 |     mNewFrame.dump(fd, 2, 6); | 
 | 145 | } | 
 | 146 |  | 
 | 147 | /** Private members */ | 
 | 148 |  | 
 | 149 | const char* CaptureSequencer::kStateNames[CaptureSequencer::NUM_CAPTURE_STATES+1] = | 
 | 150 | { | 
 | 151 |     "IDLE", | 
 | 152 |     "START", | 
 | 153 |     "ZSL_START", | 
 | 154 |     "ZSL_WAITING", | 
 | 155 |     "ZSL_REPROCESSING", | 
 | 156 |     "STANDARD_START", | 
| Eino-Ville Talvala | e049384 | 2012-10-05 12:03:10 -0700 | [diff] [blame^] | 157 |     "STANDARD_PRECAPTURE_WAIT", | 
 | 158 |     "STANDARD_CAPTURE", | 
 | 159 |     "STANDARD_CAPTURE_WAIT", | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 160 |     "BURST_CAPTURE_START", | 
 | 161 |     "BURST_CAPTURE_WAIT", | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 162 |     "DONE", | 
 | 163 |     "ERROR", | 
 | 164 |     "UNKNOWN" | 
 | 165 | }; | 
 | 166 |  | 
 | 167 | const CaptureSequencer::StateManager | 
 | 168 |         CaptureSequencer::kStateManagers[CaptureSequencer::NUM_CAPTURE_STATES-1] = { | 
 | 169 |     &CaptureSequencer::manageIdle, | 
 | 170 |     &CaptureSequencer::manageStart, | 
 | 171 |     &CaptureSequencer::manageZslStart, | 
 | 172 |     &CaptureSequencer::manageZslWaiting, | 
 | 173 |     &CaptureSequencer::manageZslReprocessing, | 
 | 174 |     &CaptureSequencer::manageStandardStart, | 
 | 175 |     &CaptureSequencer::manageStandardPrecaptureWait, | 
 | 176 |     &CaptureSequencer::manageStandardCapture, | 
 | 177 |     &CaptureSequencer::manageStandardCaptureWait, | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 178 |     &CaptureSequencer::manageBurstCaptureStart, | 
 | 179 |     &CaptureSequencer::manageBurstCaptureWait, | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 180 |     &CaptureSequencer::manageDone, | 
 | 181 | }; | 
 | 182 |  | 
 | 183 | bool CaptureSequencer::threadLoop() { | 
 | 184 |     status_t res; | 
 | 185 |  | 
 | 186 |     sp<Camera2Client> client = mClient.promote(); | 
 | 187 |     if (client == 0) return false; | 
 | 188 |  | 
| Eino-Ville Talvala | e049384 | 2012-10-05 12:03:10 -0700 | [diff] [blame^] | 189 |     CaptureState currentState; | 
 | 190 |     { | 
 | 191 |         Mutex::Autolock l(mStateMutex); | 
 | 192 |         currentState = mCaptureState; | 
 | 193 |     } | 
 | 194 |  | 
 | 195 |     currentState = (this->*kStateManagers[currentState])(client); | 
 | 196 |  | 
 | 197 |     Mutex::Autolock l(mStateMutex); | 
 | 198 |     if (currentState != mCaptureState) { | 
 | 199 |         mCaptureState = currentState; | 
 | 200 |         ATRACE_INT("cam2_capt_state", mCaptureState); | 
 | 201 |         ALOGV("Camera %d: New capture state %s", | 
 | 202 |                 client->getCameraId(), kStateNames[mCaptureState]); | 
 | 203 |         mStateChanged.signal(); | 
 | 204 |     } | 
 | 205 |  | 
 | 206 |     if (mCaptureState == ERROR) { | 
 | 207 |         ALOGE("Camera %d: Stopping capture sequencer due to error", | 
 | 208 |                 client->getCameraId()); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 209 |         return false; | 
 | 210 |     } | 
 | 211 |  | 
 | 212 |     return true; | 
 | 213 | } | 
 | 214 |  | 
 | 215 | CaptureSequencer::CaptureState CaptureSequencer::manageIdle(sp<Camera2Client> &client) { | 
 | 216 |     status_t res; | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 217 |     Mutex::Autolock l(mInputMutex); | 
 | 218 |     while (!mStartCapture) { | 
 | 219 |         res = mStartCaptureSignal.waitRelative(mInputMutex, | 
 | 220 |                 kWaitDuration); | 
 | 221 |         if (res == TIMED_OUT) break; | 
 | 222 |     } | 
 | 223 |     if (mStartCapture) { | 
 | 224 |         mStartCapture = false; | 
 | 225 |         mBusy = true; | 
 | 226 |         return START; | 
 | 227 |     } | 
 | 228 |     return IDLE; | 
 | 229 | } | 
 | 230 |  | 
 | 231 | CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &client) { | 
| Eino-Ville Talvala | 52e9ad4 | 2012-09-19 17:09:15 -0700 | [diff] [blame] | 232 |     status_t res = OK; | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 233 |     ATRACE_CALL(); | 
 | 234 |     mCaptureId++; | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 235 |     if (mCaptureId >= Camera2Client::kCaptureRequestIdEnd) { | 
 | 236 |         mCaptureId = Camera2Client::kCaptureRequestIdStart; | 
 | 237 |     } | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 238 |     { | 
 | 239 |         Mutex::Autolock l(mInputMutex); | 
 | 240 |         mBusy = false; | 
 | 241 |     } | 
 | 242 |  | 
| Eino-Ville Talvala | 52e9ad4 | 2012-09-19 17:09:15 -0700 | [diff] [blame] | 243 |     { | 
 | 244 |         SharedParameters::Lock l(client->getParameters()); | 
 | 245 |         switch (l.mParameters.state) { | 
| Eino-Ville Talvala | e049384 | 2012-10-05 12:03:10 -0700 | [diff] [blame^] | 246 |             case Parameters::DISCONNECTED: | 
 | 247 |                 ALOGW("%s: Camera %d: Discarding image data during shutdown ", | 
 | 248 |                         __FUNCTION__, client->getCameraId()); | 
 | 249 |                 res = INVALID_OPERATION; | 
 | 250 |                 break; | 
| Eino-Ville Talvala | 52e9ad4 | 2012-09-19 17:09:15 -0700 | [diff] [blame] | 251 |             case Parameters::STILL_CAPTURE: | 
 | 252 |                 l.mParameters.state = Parameters::STOPPED; | 
 | 253 |                 break; | 
 | 254 |             case Parameters::VIDEO_SNAPSHOT: | 
 | 255 |                 l.mParameters.state = Parameters::RECORD; | 
 | 256 |                 break; | 
 | 257 |             default: | 
 | 258 |                 ALOGE("%s: Camera %d: Still image produced unexpectedly " | 
 | 259 |                         "in state %s!", | 
 | 260 |                         __FUNCTION__, client->getCameraId(), | 
 | 261 |                         Parameters::getStateName(l.mParameters.state)); | 
 | 262 |                 res = INVALID_OPERATION; | 
 | 263 |         } | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 264 |     } | 
| Eino-Ville Talvala | 5a8fed0 | 2012-09-19 17:11:04 -0700 | [diff] [blame] | 265 |     sp<ZslProcessor> processor = mZslProcessor.promote(); | 
 | 266 |     if (processor != 0) { | 
 | 267 |         processor->clearZslQueue(); | 
 | 268 |     } | 
 | 269 |  | 
| Eino-Ville Talvala | 52e9ad4 | 2012-09-19 17:09:15 -0700 | [diff] [blame] | 270 |     if (mCaptureBuffer != 0 && res == OK) { | 
 | 271 |         Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); | 
 | 272 |         ALOGV("%s: Sending still image to client", __FUNCTION__); | 
 | 273 |         if (l.mCameraClient != 0) { | 
 | 274 |             l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, | 
 | 275 |                     mCaptureBuffer, NULL); | 
 | 276 |         } else { | 
 | 277 |             ALOGV("%s: No client!", __FUNCTION__); | 
 | 278 |         } | 
 | 279 |     } | 
 | 280 |     mCaptureBuffer.clear(); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 281 |  | 
 | 282 |     return IDLE; | 
 | 283 | } | 
 | 284 |  | 
 | 285 | CaptureSequencer::CaptureState CaptureSequencer::manageStart( | 
 | 286 |         sp<Camera2Client> &client) { | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 287 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 288 |     status_t res; | 
 | 289 |     ATRACE_CALL(); | 
 | 290 |     SharedParameters::Lock l(client->getParameters()); | 
 | 291 |     CaptureState nextState = DONE; | 
 | 292 |  | 
 | 293 |     res = updateCaptureRequest(l.mParameters, client); | 
 | 294 |     if (res != OK ) { | 
 | 295 |         ALOGE("%s: Camera %d: Can't update still image capture request: %s (%d)", | 
 | 296 |                 __FUNCTION__, client->getCameraId(), strerror(-res), res); | 
 | 297 |         return DONE; | 
 | 298 |     } | 
 | 299 |  | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 300 |     if(l.mParameters.lightFx != Parameters::LIGHTFX_NONE && | 
 | 301 |             l.mParameters.state == Parameters::STILL_CAPTURE) { | 
 | 302 |         nextState = BURST_CAPTURE_START; | 
 | 303 |     } | 
 | 304 |     else if (l.mParameters.zslMode && | 
| Eino-Ville Talvala | 5a07a62 | 2012-09-21 16:30:42 -0700 | [diff] [blame] | 305 |             l.mParameters.state == Parameters::STILL_CAPTURE && | 
 | 306 |             l.mParameters.flashMode != Parameters::FLASH_MODE_ON) { | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 307 |         nextState = ZSL_START; | 
 | 308 |     } else { | 
 | 309 |         nextState = STANDARD_START; | 
 | 310 |     } | 
 | 311 |  | 
 | 312 |     return nextState; | 
 | 313 | } | 
 | 314 |  | 
 | 315 | CaptureSequencer::CaptureState CaptureSequencer::manageZslStart( | 
 | 316 |         sp<Camera2Client> &client) { | 
| Eino-Ville Talvala | 2954fe9 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 317 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 318 |     status_t res; | 
 | 319 |     sp<ZslProcessor> processor = mZslProcessor.promote(); | 
 | 320 |     if (processor == 0) { | 
 | 321 |         ALOGE("%s: No ZSL queue to use!", __FUNCTION__); | 
 | 322 |         return DONE; | 
 | 323 |     } | 
 | 324 |  | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 325 |     client->registerFrameListener(mCaptureId, mCaptureId + 1, | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 326 |             this); | 
 | 327 |  | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 328 |     // TODO: Actually select the right thing here. | 
| Eino-Ville Talvala | 2954fe9 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 329 |     res = processor->pushToReprocess(mCaptureId); | 
 | 330 |     if (res != OK) { | 
| Eino-Ville Talvala | 2274549 | 2012-09-17 17:55:07 -0700 | [diff] [blame] | 331 |         if (res == NOT_ENOUGH_DATA) { | 
 | 332 |             ALOGV("%s: Camera %d: ZSL queue doesn't have good frame, " | 
 | 333 |                     "falling back to normal capture", __FUNCTION__, | 
 | 334 |                     client->getCameraId()); | 
 | 335 |         } else { | 
 | 336 |             ALOGE("%s: Camera %d: Error in ZSL queue: %s (%d)", | 
 | 337 |                     __FUNCTION__, client->getCameraId(), strerror(-res), res); | 
 | 338 |         } | 
| Eino-Ville Talvala | 2954fe9 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 339 |         return STANDARD_START; | 
 | 340 |     } | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 341 |  | 
| Eino-Ville Talvala | a4247b8 | 2012-09-19 17:12:50 -0700 | [diff] [blame] | 342 |     SharedParameters::Lock l(client->getParameters()); | 
| Igor Murashkin | 707c3e3 | 2012-09-20 15:18:50 -0700 | [diff] [blame] | 343 |     /* warning: this also locks a SharedCameraClient */ | 
 | 344 |     shutterNotifyLocked(l.mParameters, client); | 
| Eino-Ville Talvala | a4247b8 | 2012-09-19 17:12:50 -0700 | [diff] [blame] | 345 |  | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 346 |     mTimeoutCount = kMaxTimeoutsForCaptureEnd; | 
 | 347 |     return STANDARD_CAPTURE_WAIT; | 
 | 348 | } | 
 | 349 |  | 
 | 350 | CaptureSequencer::CaptureState CaptureSequencer::manageZslWaiting( | 
 | 351 |         sp<Camera2Client> &client) { | 
| Eino-Ville Talvala | 2954fe9 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 352 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 353 |     return DONE; | 
 | 354 | } | 
 | 355 |  | 
 | 356 | CaptureSequencer::CaptureState CaptureSequencer::manageZslReprocessing( | 
 | 357 |         sp<Camera2Client> &client) { | 
| Eino-Ville Talvala | 2954fe9 | 2012-09-12 10:42:10 -0700 | [diff] [blame] | 358 |     ALOGV("%s", __FUNCTION__); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 359 |     return START; | 
 | 360 | } | 
 | 361 |  | 
 | 362 | CaptureSequencer::CaptureState CaptureSequencer::manageStandardStart( | 
 | 363 |         sp<Camera2Client> &client) { | 
 | 364 |     ATRACE_CALL(); | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 365 |     client->registerFrameListener(mCaptureId, mCaptureId + 1, | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 366 |             this); | 
 | 367 |     { | 
 | 368 |         SharedParameters::Lock l(client->getParameters()); | 
 | 369 |         mTriggerId = l.mParameters.precaptureTriggerCounter++; | 
 | 370 |     } | 
 | 371 |     client->getCameraDevice()->triggerPrecaptureMetering(mTriggerId); | 
 | 372 |  | 
 | 373 |     mAeInPrecapture = false; | 
 | 374 |     mTimeoutCount = kMaxTimeoutsForPrecaptureStart; | 
 | 375 |     return STANDARD_PRECAPTURE_WAIT; | 
 | 376 | } | 
 | 377 |  | 
 | 378 | CaptureSequencer::CaptureState CaptureSequencer::manageStandardPrecaptureWait( | 
 | 379 |         sp<Camera2Client> &client) { | 
 | 380 |     status_t res; | 
 | 381 |     ATRACE_CALL(); | 
 | 382 |     Mutex::Autolock l(mInputMutex); | 
 | 383 |     while (!mNewAEState) { | 
 | 384 |         res = mNewNotifySignal.waitRelative(mInputMutex, kWaitDuration); | 
 | 385 |         if (res == TIMED_OUT) { | 
 | 386 |             mTimeoutCount--; | 
 | 387 |             break; | 
 | 388 |         } | 
 | 389 |     } | 
 | 390 |     if (mTimeoutCount <= 0) { | 
 | 391 |         ALOGW("Timed out waiting for precapture %s", | 
 | 392 |                 mAeInPrecapture ? "end" : "start"); | 
 | 393 |         return STANDARD_CAPTURE; | 
 | 394 |     } | 
 | 395 |     if (mNewAEState) { | 
 | 396 |         if (!mAeInPrecapture) { | 
 | 397 |             // Waiting to see PRECAPTURE state | 
 | 398 |             if (mAETriggerId == mTriggerId && | 
 | 399 |                     mAEState == ANDROID_CONTROL_AE_STATE_PRECAPTURE) { | 
 | 400 |                 ALOGV("%s: Got precapture start", __FUNCTION__); | 
 | 401 |                 mAeInPrecapture = true; | 
 | 402 |                 mTimeoutCount = kMaxTimeoutsForPrecaptureEnd; | 
 | 403 |             } | 
 | 404 |         } else { | 
 | 405 |             // Waiting to see PRECAPTURE state end | 
 | 406 |             if (mAETriggerId == mTriggerId && | 
 | 407 |                     mAEState != ANDROID_CONTROL_AE_STATE_PRECAPTURE) { | 
 | 408 |                 ALOGV("%s: Got precapture end", __FUNCTION__); | 
 | 409 |                 return STANDARD_CAPTURE; | 
 | 410 |             } | 
 | 411 |         } | 
 | 412 |         mNewAEState = false; | 
 | 413 |     } | 
 | 414 |     return STANDARD_PRECAPTURE_WAIT; | 
 | 415 | } | 
 | 416 |  | 
 | 417 | CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture( | 
 | 418 |         sp<Camera2Client> &client) { | 
 | 419 |     status_t res; | 
 | 420 |     ATRACE_CALL(); | 
 | 421 |     SharedParameters::Lock l(client->getParameters()); | 
 | 422 |     Vector<uint8_t> outputStreams; | 
 | 423 |  | 
 | 424 |     outputStreams.push(client->getPreviewStreamId()); | 
 | 425 |     outputStreams.push(client->getCaptureStreamId()); | 
 | 426 |  | 
 | 427 |     if (l.mParameters.previewCallbackFlags & | 
 | 428 |             CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) { | 
 | 429 |         outputStreams.push(client->getCallbackStreamId()); | 
 | 430 |     } | 
 | 431 |  | 
 | 432 |     if (l.mParameters.state == Parameters::VIDEO_SNAPSHOT) { | 
 | 433 |         outputStreams.push(client->getRecordingStreamId()); | 
 | 434 |     } | 
 | 435 |  | 
 | 436 |     res = mCaptureRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, | 
 | 437 |             outputStreams); | 
 | 438 |     if (res == OK) { | 
 | 439 |         res = mCaptureRequest.update(ANDROID_REQUEST_ID, | 
 | 440 |                 &mCaptureId, 1); | 
 | 441 |     } | 
 | 442 |     if (res == OK) { | 
 | 443 |         res = mCaptureRequest.sort(); | 
 | 444 |     } | 
 | 445 |  | 
 | 446 |     if (res != OK) { | 
 | 447 |         ALOGE("%s: Camera %d: Unable to set up still capture request: %s (%d)", | 
 | 448 |                 __FUNCTION__, client->getCameraId(), strerror(-res), res); | 
 | 449 |         return DONE; | 
 | 450 |     } | 
 | 451 |  | 
 | 452 |     CameraMetadata captureCopy = mCaptureRequest; | 
 | 453 |     if (captureCopy.entryCount() == 0) { | 
 | 454 |         ALOGE("%s: Camera %d: Unable to copy capture request for HAL device", | 
 | 455 |                 __FUNCTION__, client->getCameraId()); | 
 | 456 |         return DONE; | 
 | 457 |     } | 
 | 458 |  | 
 | 459 |     if (l.mParameters.state == Parameters::STILL_CAPTURE) { | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 460 |         res = client->stopStream(); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 461 |         if (res != OK) { | 
 | 462 |             ALOGE("%s: Camera %d: Unable to stop preview for still capture: " | 
 | 463 |                     "%s (%d)", | 
 | 464 |                     __FUNCTION__, client->getCameraId(), strerror(-res), res); | 
 | 465 |             return DONE; | 
 | 466 |         } | 
 | 467 |     } | 
 | 468 |     // TODO: Capture should be atomic with setStreamingRequest here | 
 | 469 |     res = client->getCameraDevice()->capture(captureCopy); | 
 | 470 |     if (res != OK) { | 
 | 471 |         ALOGE("%s: Camera %d: Unable to submit still image capture request: " | 
 | 472 |                 "%s (%d)", | 
 | 473 |                 __FUNCTION__, client->getCameraId(), strerror(-res), res); | 
 | 474 |         return DONE; | 
 | 475 |     } | 
 | 476 |  | 
| Igor Murashkin | 707c3e3 | 2012-09-20 15:18:50 -0700 | [diff] [blame] | 477 |     /* warning: this also locks a SharedCameraClient */ | 
 | 478 |     shutterNotifyLocked(l.mParameters, client); | 
| Eino-Ville Talvala | 3357883 | 2012-09-06 18:26:58 -0700 | [diff] [blame] | 479 |  | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 480 |     mTimeoutCount = kMaxTimeoutsForCaptureEnd; | 
 | 481 |     return STANDARD_CAPTURE_WAIT; | 
 | 482 | } | 
 | 483 |  | 
 | 484 | CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait( | 
 | 485 |         sp<Camera2Client> &client) { | 
 | 486 |     status_t res; | 
 | 487 |     ATRACE_CALL(); | 
 | 488 |     Mutex::Autolock l(mInputMutex); | 
 | 489 |     while (!mNewFrameReceived) { | 
 | 490 |         res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration); | 
 | 491 |         if (res == TIMED_OUT) { | 
 | 492 |             mTimeoutCount--; | 
 | 493 |             break; | 
 | 494 |         } | 
 | 495 |     } | 
 | 496 |     while (!mNewCaptureReceived) { | 
 | 497 |         res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration); | 
 | 498 |         if (res == TIMED_OUT) { | 
 | 499 |             mTimeoutCount--; | 
 | 500 |             break; | 
 | 501 |         } | 
 | 502 |     } | 
 | 503 |     if (mTimeoutCount <= 0) { | 
 | 504 |         ALOGW("Timed out waiting for capture to complete"); | 
 | 505 |         return DONE; | 
 | 506 |     } | 
 | 507 |     if (mNewFrameReceived && mNewCaptureReceived) { | 
 | 508 |         if (mNewFrameId != mCaptureId) { | 
 | 509 |             ALOGW("Mismatched capture frame IDs: Expected %d, got %d", | 
 | 510 |                     mCaptureId, mNewFrameId); | 
 | 511 |         } | 
 | 512 |         camera_metadata_entry_t entry; | 
 | 513 |         entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP); | 
 | 514 |         if (entry.count == 0) { | 
 | 515 |             ALOGE("No timestamp field in capture frame!"); | 
 | 516 |         } | 
 | 517 |         if (entry.data.i64[0] != mCaptureTimestamp) { | 
 | 518 |             ALOGW("Mismatched capture timestamps: Metadata frame %lld," | 
 | 519 |                     " captured buffer %lld", entry.data.i64[0], mCaptureTimestamp); | 
 | 520 |         } | 
| Eino-Ville Talvala | 4c9eb71 | 2012-10-02 13:30:28 -0700 | [diff] [blame] | 521 |         client->removeFrameListener(mCaptureId, mCaptureId + 1, this); | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 522 |  | 
 | 523 |         mNewFrameReceived = false; | 
 | 524 |         mNewCaptureReceived = false; | 
 | 525 |         return DONE; | 
 | 526 |     } | 
 | 527 |     return STANDARD_CAPTURE_WAIT; | 
 | 528 | } | 
 | 529 |  | 
| James Painter | c3dbf1a | 2012-09-05 18:02:32 -0700 | [diff] [blame] | 530 | CaptureSequencer::CaptureState CaptureSequencer::manageBurstCaptureStart( | 
 | 531 |         sp<Camera2Client> &client) { | 
 | 532 |     ALOGV("%s", __FUNCTION__); | 
 | 533 |     status_t res; | 
 | 534 |     ATRACE_CALL(); | 
 | 535 |  | 
 | 536 |     // check which burst mode is set, create respective burst object | 
 | 537 |     { | 
 | 538 |         SharedParameters::Lock l(client->getParameters()); | 
 | 539 |  | 
 | 540 |         res = updateCaptureRequest(l.mParameters, client); | 
 | 541 |         if(res != OK) { | 
 | 542 |             return DONE; | 
 | 543 |         } | 
 | 544 |  | 
 | 545 |         // | 
 | 546 |         // check for burst mode type in mParameters here | 
 | 547 |         // | 
 | 548 |         mBurstCapture = new BurstCapture(client, this); | 
 | 549 |     } | 
 | 550 |  | 
 | 551 |     res = mCaptureRequest.update(ANDROID_REQUEST_ID, &mCaptureId, 1); | 
 | 552 |     if (res == OK) { | 
 | 553 |         res = mCaptureRequest.sort(); | 
 | 554 |     } | 
 | 555 |     if (res != OK) { | 
 | 556 |         ALOGE("%s: Camera %d: Unable to set up still capture request: %s (%d)", | 
 | 557 |                 __FUNCTION__, client->getCameraId(), strerror(-res), res); | 
 | 558 |         return DONE; | 
 | 559 |     } | 
 | 560 |  | 
 | 561 |     CameraMetadata captureCopy = mCaptureRequest; | 
 | 562 |     if (captureCopy.entryCount() == 0) { | 
 | 563 |         ALOGE("%s: Camera %d: Unable to copy capture request for HAL device", | 
 | 564 |                 __FUNCTION__, client->getCameraId()); | 
 | 565 |         return DONE; | 
 | 566 |     } | 
 | 567 |  | 
 | 568 |     Vector<CameraMetadata> requests; | 
 | 569 |     requests.push(mCaptureRequest); | 
 | 570 |     res = mBurstCapture->start(requests, mCaptureId); | 
 | 571 |     mTimeoutCount = kMaxTimeoutsForCaptureEnd * 10; | 
 | 572 |     return BURST_CAPTURE_WAIT; | 
 | 573 | } | 
 | 574 |  | 
 | 575 | CaptureSequencer::CaptureState CaptureSequencer::manageBurstCaptureWait( | 
 | 576 |         sp<Camera2Client> &client) { | 
 | 577 |     status_t res; | 
 | 578 |     ATRACE_CALL(); | 
 | 579 |  | 
 | 580 |     while (!mNewCaptureReceived) { | 
 | 581 |         res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration); | 
 | 582 |         if (res == TIMED_OUT) { | 
 | 583 |             mTimeoutCount--; | 
 | 584 |             break; | 
 | 585 |         } | 
 | 586 |     } | 
 | 587 |  | 
 | 588 |     if (mTimeoutCount <= 0) { | 
 | 589 |         ALOGW("Timed out waiting for burst capture to complete"); | 
 | 590 |         return DONE; | 
 | 591 |     } | 
 | 592 |     if (mNewCaptureReceived) { | 
 | 593 |         mNewCaptureReceived = false; | 
 | 594 |         // TODO: update mCaptureId to last burst's capture ID + 1? | 
 | 595 |         return DONE; | 
 | 596 |     } | 
 | 597 |  | 
 | 598 |     return BURST_CAPTURE_WAIT; | 
 | 599 | } | 
 | 600 |  | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 601 | status_t CaptureSequencer::updateCaptureRequest(const Parameters ¶ms, | 
 | 602 |         sp<Camera2Client> &client) { | 
 | 603 |     ATRACE_CALL(); | 
 | 604 |     status_t res; | 
 | 605 |     if (mCaptureRequest.entryCount() == 0) { | 
 | 606 |         res = client->getCameraDevice()->createDefaultRequest( | 
 | 607 |                 CAMERA2_TEMPLATE_STILL_CAPTURE, | 
 | 608 |                 &mCaptureRequest); | 
 | 609 |         if (res != OK) { | 
 | 610 |             ALOGE("%s: Camera %d: Unable to create default still image request:" | 
 | 611 |                     " %s (%d)", __FUNCTION__, client->getCameraId(), | 
 | 612 |                     strerror(-res), res); | 
 | 613 |             return res; | 
 | 614 |         } | 
 | 615 |     } | 
 | 616 |  | 
 | 617 |     res = params.updateRequest(&mCaptureRequest); | 
 | 618 |     if (res != OK) { | 
 | 619 |         ALOGE("%s: Camera %d: Unable to update common entries of capture " | 
 | 620 |                 "request: %s (%d)", __FUNCTION__, client->getCameraId(), | 
 | 621 |                 strerror(-res), res); | 
 | 622 |         return res; | 
 | 623 |     } | 
 | 624 |  | 
| Eino-Ville Talvala | db30e68 | 2012-10-04 13:21:08 -0700 | [diff] [blame] | 625 |     res = params.updateRequestJpeg(&mCaptureRequest); | 
 | 626 |     if (res != OK) { | 
 | 627 |         ALOGE("%s: Camera %d: Unable to update JPEG entries of capture " | 
 | 628 |                 "request: %s (%d)", __FUNCTION__, client->getCameraId(), | 
 | 629 |                 strerror(-res), res); | 
 | 630 |         return res; | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 631 |     } | 
 | 632 |  | 
 | 633 |     return OK; | 
 | 634 | } | 
 | 635 |  | 
| Igor Murashkin | 707c3e3 | 2012-09-20 15:18:50 -0700 | [diff] [blame] | 636 | /*static*/ void CaptureSequencer::shutterNotifyLocked(const Parameters ¶ms, | 
 | 637 |             sp<Camera2Client> client) { | 
 | 638 |     ATRACE_CALL(); | 
 | 639 |  | 
 | 640 |     if (params.state == Parameters::STILL_CAPTURE && params.playShutterSound) { | 
 | 641 |         client->getCameraService()->playSound(CameraService::SOUND_SHUTTER); | 
 | 642 |     } | 
 | 643 |  | 
 | 644 |     { | 
 | 645 |         Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); | 
 | 646 |  | 
 | 647 |         ALOGV("%s: Notifying of shutter close to client", __FUNCTION__); | 
 | 648 |         if (l.mCameraClient != 0) { | 
 | 649 |             // ShutterCallback | 
 | 650 |             l.mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, | 
 | 651 |                                             /*ext1*/0, /*ext2*/0); | 
 | 652 |  | 
 | 653 |             // RawCallback with null buffer | 
 | 654 |             l.mCameraClient->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY, | 
 | 655 |                                             /*ext1*/0, /*ext2*/0); | 
 | 656 |         } else { | 
 | 657 |             ALOGV("%s: No client!", __FUNCTION__); | 
 | 658 |         } | 
 | 659 |     } | 
 | 660 | } | 
 | 661 |  | 
| Eino-Ville Talvala | 69230df | 2012-08-29 17:37:16 -0700 | [diff] [blame] | 662 |  | 
 | 663 | }; // namespace camera2 | 
 | 664 | }; // namespace android |