blob: 532d2aaac396d29ffbb7c3cbeb1fca790ccb2bce [file] [log] [blame]
Eino-Ville Talvala69230df2012-08-29 17:37:16 -07001/*
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 mTimeoutCount = kMaxTimeoutsForCaptureEnd;
392 return STANDARD_CAPTURE_WAIT;
393}
394
395CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(
396 sp<Camera2Client> &client) {
397 status_t res;
398 ATRACE_CALL();
399 Mutex::Autolock l(mInputMutex);
400 while (!mNewFrameReceived) {
401 res = mNewFrameSignal.waitRelative(mInputMutex, kWaitDuration);
402 if (res == TIMED_OUT) {
403 mTimeoutCount--;
404 break;
405 }
406 }
407 while (!mNewCaptureReceived) {
408 res = mNewCaptureSignal.waitRelative(mInputMutex, kWaitDuration);
409 if (res == TIMED_OUT) {
410 mTimeoutCount--;
411 break;
412 }
413 }
414 if (mTimeoutCount <= 0) {
415 ALOGW("Timed out waiting for capture to complete");
416 return DONE;
417 }
418 if (mNewFrameReceived && mNewCaptureReceived) {
419 if (mNewFrameId != mCaptureId) {
420 ALOGW("Mismatched capture frame IDs: Expected %d, got %d",
421 mCaptureId, mNewFrameId);
422 }
423 camera_metadata_entry_t entry;
424 entry = mNewFrame.find(ANDROID_SENSOR_TIMESTAMP);
425 if (entry.count == 0) {
426 ALOGE("No timestamp field in capture frame!");
427 }
428 if (entry.data.i64[0] != mCaptureTimestamp) {
429 ALOGW("Mismatched capture timestamps: Metadata frame %lld,"
430 " captured buffer %lld", entry.data.i64[0], mCaptureTimestamp);
431 }
432 client->removeFrameListener(mCaptureId);
433
434 mNewFrameReceived = false;
435 mNewCaptureReceived = false;
436 return DONE;
437 }
438 return STANDARD_CAPTURE_WAIT;
439}
440
441status_t CaptureSequencer::updateCaptureRequest(const Parameters &params,
442 sp<Camera2Client> &client) {
443 ATRACE_CALL();
444 status_t res;
445 if (mCaptureRequest.entryCount() == 0) {
446 res = client->getCameraDevice()->createDefaultRequest(
447 CAMERA2_TEMPLATE_STILL_CAPTURE,
448 &mCaptureRequest);
449 if (res != OK) {
450 ALOGE("%s: Camera %d: Unable to create default still image request:"
451 " %s (%d)", __FUNCTION__, client->getCameraId(),
452 strerror(-res), res);
453 return res;
454 }
455 }
456
457 res = params.updateRequest(&mCaptureRequest);
458 if (res != OK) {
459 ALOGE("%s: Camera %d: Unable to update common entries of capture "
460 "request: %s (%d)", __FUNCTION__, client->getCameraId(),
461 strerror(-res), res);
462 return res;
463 }
464
465 res = mCaptureRequest.update(ANDROID_JPEG_THUMBNAIL_SIZE,
466 params.jpegThumbSize, 2);
467 if (res != OK) return res;
468 res = mCaptureRequest.update(ANDROID_JPEG_THUMBNAIL_QUALITY,
469 &params.jpegThumbQuality, 1);
470 if (res != OK) return res;
471 res = mCaptureRequest.update(ANDROID_JPEG_QUALITY,
472 &params.jpegQuality, 1);
473 if (res != OK) return res;
474 res = mCaptureRequest.update(
475 ANDROID_JPEG_ORIENTATION,
476 &params.jpegRotation, 1);
477 if (res != OK) return res;
478
479 if (params.gpsEnabled) {
480 res = mCaptureRequest.update(
481 ANDROID_JPEG_GPS_COORDINATES,
482 params.gpsCoordinates, 3);
483 if (res != OK) return res;
484 res = mCaptureRequest.update(
485 ANDROID_JPEG_GPS_TIMESTAMP,
486 &params.gpsTimestamp, 1);
487 if (res != OK) return res;
488 res = mCaptureRequest.update(
489 ANDROID_JPEG_GPS_PROCESSING_METHOD,
490 params.gpsProcessingMethod);
491 if (res != OK) return res;
492 } else {
493 res = mCaptureRequest.erase(ANDROID_JPEG_GPS_COORDINATES);
494 if (res != OK) return res;
495 res = mCaptureRequest.erase(ANDROID_JPEG_GPS_TIMESTAMP);
496 if (res != OK) return res;
497 res = mCaptureRequest.erase(ANDROID_JPEG_GPS_PROCESSING_METHOD);
498 if (res != OK) return res;
499 }
500
501 return OK;
502}
503
504
505}; // namespace camera2
506}; // namespace android