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