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