ZslProcessor.cpp revision 768cf093dade9085e0ad6305d9f7c16ae9ad9e26
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::ZslProcessor"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20//#define LOG_NNDEBUG 0
21
22#ifdef LOG_NNDEBUG
23#define ALOGVV(...) ALOGV(__VA_ARGS__)
24#else
25#define ALOGVV(...) ((void)0)
26#endif
27
28#include <utils/Log.h>
29#include <utils/Trace.h>
30
31#include "ZslProcessor.h"
32#include <gui/SurfaceTextureClient.h>
33#include "../Camera2Device.h"
34#include "../Camera2Client.h"
35
36
37namespace android {
38namespace camera2 {
39
40ZslProcessor::ZslProcessor(
41    wp<Camera2Client> client,
42    wp<CaptureSequencer> sequencer):
43        Thread(false),
44        mState(RUNNING),
45        mClient(client),
46        mSequencer(sequencer),
47        mZslBufferAvailable(false),
48        mZslStreamId(NO_STREAM),
49        mZslReprocessStreamId(NO_STREAM),
50        mFrameListHead(0),
51        mZslQueueHead(0),
52        mZslQueueTail(0) {
53    mZslQueue.insertAt(0, kZslBufferDepth);
54    mFrameList.insertAt(0, kFrameListDepth);
55    sp<CaptureSequencer> captureSequencer = mSequencer.promote();
56    if (captureSequencer != 0) captureSequencer->setZslProcessor(this);
57}
58
59ZslProcessor::~ZslProcessor() {
60    ALOGV("%s: Exit", __FUNCTION__);
61    deleteStream();
62}
63
64void ZslProcessor::onFrameAvailable() {
65    Mutex::Autolock l(mInputMutex);
66    if (!mZslBufferAvailable) {
67        mZslBufferAvailable = true;
68        mZslBufferAvailableSignal.signal();
69    }
70}
71
72void ZslProcessor::onFrameAvailable(int32_t frameId, CameraMetadata &frame) {
73    Mutex::Autolock l(mInputMutex);
74    camera_metadata_entry_t entry;
75    entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
76    nsecs_t timestamp = entry.data.i64[0];
77    ALOGVV("Got preview frame for timestamp %lld", timestamp);
78
79    if (mState != RUNNING) return;
80
81    mFrameList.editItemAt(mFrameListHead).acquire(frame);
82    mFrameListHead = (mFrameListHead + 1) % kFrameListDepth;
83
84    findMatchesLocked();
85}
86
87void ZslProcessor::onBufferReleased(buffer_handle_t *handle) {
88    Mutex::Autolock l(mInputMutex);
89
90    // Verify that the buffer is in our queue
91    size_t i = 0;
92    for (; i < mZslQueue.size(); i++) {
93        if (&(mZslQueue[i].buffer.mGraphicBuffer->handle) == handle) break;
94    }
95    if (i == mZslQueue.size()) {
96        ALOGW("%s: Released buffer %p not found in queue",
97                __FUNCTION__, handle);
98    }
99
100    // Erase entire ZSL queue since we've now completed the capture and preview
101    // is stopped.
102    clearZslQueueLocked();
103
104    mState = RUNNING;
105}
106
107status_t ZslProcessor::updateStream(const Parameters &params) {
108    ATRACE_CALL();
109    ALOGV("%s: Configuring ZSL streams", __FUNCTION__);
110    status_t res;
111
112    Mutex::Autolock l(mInputMutex);
113
114    sp<Camera2Client> client = mClient.promote();
115    if (client == 0) return OK;
116    sp<Camera2Device> device = client->getCameraDevice();
117
118    if (mZslConsumer == 0) {
119        // Create CPU buffer queue endpoint
120        mZslConsumer = new BufferItemConsumer(
121            GRALLOC_USAGE_HW_CAMERA_ZSL,
122            kZslBufferDepth,
123            true);
124        mZslConsumer->setFrameAvailableListener(this);
125        mZslConsumer->setName(String8("Camera2Client::ZslConsumer"));
126        mZslWindow = new SurfaceTextureClient(
127            mZslConsumer->getProducerInterface());
128    }
129
130    if (mZslStreamId != NO_STREAM) {
131        // Check if stream parameters have to change
132        uint32_t currentWidth, currentHeight;
133        res = device->getStreamInfo(mZslStreamId,
134                &currentWidth, &currentHeight, 0);
135        if (res != OK) {
136            ALOGE("%s: Camera %d: Error querying capture output stream info: "
137                    "%s (%d)", __FUNCTION__,
138                    client->getCameraId(), strerror(-res), res);
139            return res;
140        }
141        if (currentWidth != (uint32_t)params.fastInfo.arrayWidth ||
142                currentHeight != (uint32_t)params.fastInfo.arrayHeight) {
143            res = device->deleteReprocessStream(mZslReprocessStreamId);
144            if (res != OK) {
145                ALOGE("%s: Camera %d: Unable to delete old reprocess stream "
146                        "for ZSL: %s (%d)", __FUNCTION__,
147                        client->getCameraId(), strerror(-res), res);
148                return res;
149            }
150            res = device->deleteStream(mZslStreamId);
151            if (res != OK) {
152                ALOGE("%s: Camera %d: Unable to delete old output stream "
153                        "for ZSL: %s (%d)", __FUNCTION__,
154                        client->getCameraId(), strerror(-res), res);
155                return res;
156            }
157            mZslStreamId = NO_STREAM;
158        }
159    }
160
161    if (mZslStreamId == NO_STREAM) {
162        // Create stream for HAL production
163        // TODO: Sort out better way to select resolution for ZSL
164        res = device->createStream(mZslWindow,
165                params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
166                CAMERA2_HAL_PIXEL_FORMAT_ZSL, 0,
167                &mZslStreamId);
168        if (res != OK) {
169            ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
170                    "%s (%d)", __FUNCTION__, client->getCameraId(),
171                    strerror(-res), res);
172            return res;
173        }
174        res = device->createReprocessStreamFromStream(mZslStreamId,
175                &mZslReprocessStreamId);
176        if (res != OK) {
177            ALOGE("%s: Camera %d: Can't create reprocess stream for ZSL: "
178                    "%s (%d)", __FUNCTION__, client->getCameraId(),
179                    strerror(-res), res);
180            return res;
181        }
182    }
183    client->registerFrameListener(Camera2Client::kPreviewRequestId, this);
184
185    return OK;
186}
187
188status_t ZslProcessor::deleteStream() {
189    ATRACE_CALL();
190    status_t res;
191
192    Mutex::Autolock l(mInputMutex);
193
194    if (mZslStreamId != NO_STREAM) {
195        sp<Camera2Client> client = mClient.promote();
196        if (client == 0) return OK;
197        sp<Camera2Device> device = client->getCameraDevice();
198
199        res = device->deleteReprocessStream(mZslReprocessStreamId);
200        if (res != OK) {
201            ALOGE("%s: Camera %d: Cannot delete ZSL reprocessing stream %d: "
202                    "%s (%d)", __FUNCTION__, client->getCameraId(),
203                    mZslReprocessStreamId, strerror(-res), res);
204            return res;
205        }
206
207        mZslReprocessStreamId = NO_STREAM;
208        res = device->deleteStream(mZslStreamId);
209        if (res != OK) {
210            ALOGE("%s: Camera %d: Cannot delete ZSL output stream %d: "
211                    "%s (%d)", __FUNCTION__, client->getCameraId(),
212                    mZslStreamId, strerror(-res), res);
213            return res;
214        }
215
216        mZslWindow.clear();
217        mZslConsumer.clear();
218
219        mZslStreamId = NO_STREAM;
220    }
221    return OK;
222}
223
224int ZslProcessor::getStreamId() const {
225    Mutex::Autolock l(mInputMutex);
226    return mZslStreamId;
227}
228
229int ZslProcessor::getReprocessStreamId() const {
230    Mutex::Autolock l(mInputMutex);
231    return mZslReprocessStreamId;
232}
233
234status_t ZslProcessor::pushToReprocess(int32_t requestId) {
235    ALOGV("%s: Send in reprocess request with id %d",
236            __FUNCTION__, requestId);
237    Mutex::Autolock l(mInputMutex);
238    status_t res;
239    sp<Camera2Client> client = mClient.promote();
240
241    if (client == 0) return INVALID_OPERATION;
242
243    IF_ALOGV() {
244        dumpZslQueue(-1);
245    }
246
247    if (mZslQueueTail != mZslQueueHead) {
248        CameraMetadata request;
249        size_t index = mZslQueueTail;
250        while (request.isEmpty() && index != mZslQueueHead) {
251            request = mZslQueue[index].frame;
252            index = (index + 1) % kZslBufferDepth;
253        }
254        if (request.isEmpty()) {
255            ALOGV("%s: ZSL queue has no valid frames to send yet.",
256                  __FUNCTION__);
257            return NOT_ENOUGH_DATA;
258        }
259        // Verify that the frame is reasonable for reprocessing
260
261        camera_metadata_entry_t entry;
262        entry = request.find(ANDROID_CONTROL_AE_STATE);
263        if (entry.count == 0) {
264            ALOGE("%s: ZSL queue frame has no AE state field!",
265                    __FUNCTION__);
266            return BAD_VALUE;
267        }
268        if (entry.data.u8[0] != ANDROID_CONTROL_AE_STATE_CONVERGED &&
269                entry.data.u8[0] != ANDROID_CONTROL_AE_STATE_LOCKED) {
270            ALOGV("%s: ZSL queue frame AE state is %d, need full capture",
271                    __FUNCTION__, entry.data.u8[0]);
272            return NOT_ENOUGH_DATA;
273        }
274
275        buffer_handle_t *handle =
276            &(mZslQueue[index].buffer.mGraphicBuffer->handle);
277
278        uint8_t requestType = ANDROID_REQUEST_TYPE_REPROCESS;
279        res = request.update(ANDROID_REQUEST_TYPE,
280                &requestType, 1);
281        uint8_t inputStreams[1] = { mZslReprocessStreamId };
282        if (res == OK) request.update(ANDROID_REQUEST_INPUT_STREAMS,
283                inputStreams, 1);
284        uint8_t outputStreams[1] = { client->getCaptureStreamId() };
285        if (res == OK) request.update(ANDROID_REQUEST_OUTPUT_STREAMS,
286                outputStreams, 1);
287        res = request.update(ANDROID_REQUEST_ID,
288                &requestId, 1);
289
290        if (res != OK ) {
291            ALOGE("%s: Unable to update frame to a reprocess request", __FUNCTION__);
292            return INVALID_OPERATION;
293        }
294
295        res = client->getCameraDevice()->pushReprocessBuffer(mZslReprocessStreamId,
296                handle, this);
297        if (res != OK) {
298            ALOGE("%s: Unable to push buffer for reprocessing: %s (%d)",
299                    __FUNCTION__, strerror(-res), res);
300            return res;
301        }
302
303        res = client->getCameraDevice()->capture(request);
304        if (res != OK ) {
305            ALOGE("%s: Unable to send ZSL reprocess request to capture: %s (%d)",
306                    __FUNCTION__, strerror(-res), res);
307            return res;
308        }
309
310        mState = LOCKED;
311    } else {
312        ALOGV("%s: No ZSL buffers yet", __FUNCTION__);
313        return NOT_ENOUGH_DATA;
314    }
315    return OK;
316}
317
318status_t ZslProcessor::clearZslQueue() {
319    Mutex::Autolock l(mInputMutex);
320    // If in middle of capture, can't clear out queue
321    if (mState == LOCKED) return OK;
322
323    return clearZslQueueLocked();
324}
325
326status_t ZslProcessor::clearZslQueueLocked() {
327    for (size_t i = 0; i < mZslQueue.size(); i++) {
328        if (mZslQueue[i].buffer.mTimestamp != 0) {
329            mZslConsumer->releaseBuffer(mZslQueue[i].buffer);
330        }
331        mZslQueue.replaceAt(i);
332    }
333    mZslQueueHead = 0;
334    mZslQueueTail = 0;
335    return OK;
336}
337
338void ZslProcessor::dump(int fd, const Vector<String16>& args) const {
339    Mutex::Autolock l(mInputMutex);
340    dumpZslQueue(fd);
341}
342
343bool ZslProcessor::threadLoop() {
344    status_t res;
345
346    {
347        Mutex::Autolock l(mInputMutex);
348        while (!mZslBufferAvailable) {
349            res = mZslBufferAvailableSignal.waitRelative(mInputMutex,
350                    kWaitDuration);
351            if (res == TIMED_OUT) return true;
352        }
353        mZslBufferAvailable = false;
354    }
355
356    do {
357        sp<Camera2Client> client = mClient.promote();
358        if (client == 0) return false;
359        res = processNewZslBuffer(client);
360    } while (res == OK);
361
362    return true;
363}
364
365status_t ZslProcessor::processNewZslBuffer(sp<Camera2Client> &client) {
366    ATRACE_CALL();
367    status_t res;
368
369    ALOGVV("Trying to get next buffer");
370    BufferItemConsumer::BufferItem item;
371    res = mZslConsumer->acquireBuffer(&item);
372    if (res != OK) {
373        if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
374            ALOGE("%s: Camera %d: Error receiving ZSL image buffer: "
375                    "%s (%d)", __FUNCTION__,
376                    client->getCameraId(), strerror(-res), res);
377        } else {
378            ALOGVV("  No buffer");
379        }
380        return res;
381    }
382
383    Mutex::Autolock l(mInputMutex);
384
385    if (mState == LOCKED) {
386        ALOGVV("In capture, discarding new ZSL buffers");
387        mZslConsumer->releaseBuffer(item);
388        return OK;
389    }
390
391    ALOGVV("Got ZSL buffer: head: %d, tail: %d", mZslQueueHead, mZslQueueTail);
392
393    if ( (mZslQueueHead + 1) % kZslBufferDepth == mZslQueueTail) {
394        ALOGVV("Releasing oldest buffer");
395        mZslConsumer->releaseBuffer(mZslQueue[mZslQueueTail].buffer);
396        mZslQueue.replaceAt(mZslQueueTail);
397        mZslQueueTail = (mZslQueueTail + 1) % kZslBufferDepth;
398    }
399
400    ZslPair &queueHead = mZslQueue.editItemAt(mZslQueueHead);
401
402    queueHead.buffer = item;
403    queueHead.frame.release();
404
405    mZslQueueHead = (mZslQueueHead + 1) % kZslBufferDepth;
406
407    ALOGVV("  Acquired buffer, timestamp %lld", queueHead.buffer.mTimestamp);
408
409    findMatchesLocked();
410
411    return OK;
412}
413
414void ZslProcessor::findMatchesLocked() {
415    ALOGVV("Scanning");
416    for (size_t i = 0; i < mZslQueue.size(); i++) {
417        ZslPair &queueEntry = mZslQueue.editItemAt(i);
418        nsecs_t bufferTimestamp = queueEntry.buffer.mTimestamp;
419        IF_ALOGV() {
420            camera_metadata_entry_t entry;
421            nsecs_t frameTimestamp = 0;
422            if (!queueEntry.frame.isEmpty()) {
423                entry = queueEntry.frame.find(ANDROID_SENSOR_TIMESTAMP);
424                frameTimestamp = entry.data.i64[0];
425            }
426            ALOGVV("   %d: b: %lld\tf: %lld", i,
427                    bufferTimestamp, frameTimestamp );
428        }
429        if (queueEntry.frame.isEmpty() && bufferTimestamp != 0) {
430            // Have buffer, no matching frame. Look for one
431            for (size_t j = 0; j < mFrameList.size(); j++) {
432                bool match = false;
433                CameraMetadata &frame = mFrameList.editItemAt(j);
434                if (!frame.isEmpty()) {
435                    camera_metadata_entry_t entry;
436                    entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
437                    if (entry.count == 0) {
438                        ALOGE("%s: Can't find timestamp in frame!",
439                                __FUNCTION__);
440                        continue;
441                    }
442                    nsecs_t frameTimestamp = entry.data.i64[0];
443                    if (bufferTimestamp == frameTimestamp) {
444                        ALOGVV("%s: Found match %lld", __FUNCTION__,
445                                frameTimestamp);
446                        match = true;
447                    } else {
448                        int64_t delta = abs(bufferTimestamp - frameTimestamp);
449                        if ( delta < 1000000) {
450                            ALOGVV("%s: Found close match %lld (delta %lld)",
451                                    __FUNCTION__, bufferTimestamp, delta);
452                            match = true;
453                        }
454                    }
455                }
456                if (match) {
457                    queueEntry.frame.acquire(frame);
458                    break;
459                }
460            }
461        }
462    }
463}
464
465void ZslProcessor::dumpZslQueue(int fd) const {
466    String8 header("ZSL queue contents:");
467    String8 indent("    ");
468    ALOGV("%s", header.string());
469    if (fd != -1) {
470        header = indent + header + "\n";
471        write(fd, header.string(), header.size());
472    }
473    for (size_t i = 0; i < mZslQueue.size(); i++) {
474        const ZslPair &queueEntry = mZslQueue[i];
475        nsecs_t bufferTimestamp = queueEntry.buffer.mTimestamp;
476        camera_metadata_ro_entry_t entry;
477        nsecs_t frameTimestamp = 0;
478        int frameAeState = -1;
479        if (!queueEntry.frame.isEmpty()) {
480            entry = queueEntry.frame.find(ANDROID_SENSOR_TIMESTAMP);
481            if (entry.count > 0) frameTimestamp = entry.data.i64[0];
482            entry = queueEntry.frame.find(ANDROID_CONTROL_AE_STATE);
483            if (entry.count > 0) frameAeState = entry.data.u8[0];
484        }
485        String8 result =
486                String8::format("   %d: b: %lld\tf: %lld, AE state: %d", i,
487                        bufferTimestamp, frameTimestamp, frameAeState);
488        ALOGV("%s", result.string());
489        if (fd != -1) {
490            result = indent + result + "\n";
491            write(fd, result.string(), result.size());
492        }
493
494    }
495}
496
497}; // namespace camera2
498}; // namespace android
499