CaptureSequencer.cpp revision da6665cbd06ca58d3357c3002b7366d13e23f152
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    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
507