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