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 &params,
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            &params.jpegThumbQuality, 1);
474    if (res != OK) return res;
475    res = mCaptureRequest.update(ANDROID_JPEG_QUALITY,
476            &params.jpegQuality, 1);
477    if (res != OK) return res;
478    res = mCaptureRequest.update(
479            ANDROID_JPEG_ORIENTATION,
480            &params.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                &params.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