CallbackProcessor.cpp revision 893068ad0ca0cce8428f5a358c86b81139399c07
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-CallbackProcessor"
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 <gui/Surface.h>
24
25#include "common/CameraDeviceBase.h"
26#include "api1/Camera2Client.h"
27#include "api1/client2/CallbackProcessor.h"
28
29#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
30
31namespace android {
32namespace camera2 {
33
34CallbackProcessor::CallbackProcessor(sp<Camera2Client> client):
35        Thread(false),
36        mClient(client),
37        mDevice(client->getCameraDevice()),
38        mId(client->getCameraId()),
39        mCallbackAvailable(false),
40        mCallbackToApp(false),
41        mCallbackStreamId(NO_STREAM) {
42}
43
44CallbackProcessor::~CallbackProcessor() {
45    ALOGV("%s: Exit", __FUNCTION__);
46    deleteStream();
47}
48
49void CallbackProcessor::onFrameAvailable() {
50    Mutex::Autolock l(mInputMutex);
51    if (!mCallbackAvailable) {
52        mCallbackAvailable = true;
53        mCallbackAvailableSignal.signal();
54    }
55}
56
57status_t CallbackProcessor::setCallbackWindow(
58        sp<ANativeWindow> callbackWindow) {
59    ATRACE_CALL();
60    status_t res;
61
62    Mutex::Autolock l(mInputMutex);
63
64    sp<Camera2Client> client = mClient.promote();
65    if (client == 0) return OK;
66    sp<CameraDeviceBase> device = client->getCameraDevice();
67
68    // If the window is changing, clear out stream if it already exists
69    if (mCallbackWindow != callbackWindow && mCallbackStreamId != NO_STREAM) {
70        res = device->deleteStream(mCallbackStreamId);
71        if (res != OK) {
72            ALOGE("%s: Camera %d: Unable to delete old stream "
73                    "for callbacks: %s (%d)", __FUNCTION__,
74                    client->getCameraId(), strerror(-res), res);
75            return res;
76        }
77        mCallbackStreamId = NO_STREAM;
78        mCallbackConsumer.clear();
79    }
80    mCallbackWindow = callbackWindow;
81    mCallbackToApp = (mCallbackWindow != NULL);
82
83    return OK;
84}
85
86status_t CallbackProcessor::updateStream(const Parameters &params) {
87    ATRACE_CALL();
88    status_t res;
89
90    Mutex::Autolock l(mInputMutex);
91
92    sp<CameraDeviceBase> device = mDevice.promote();
93    if (device == 0) {
94        ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
95        return INVALID_OPERATION;
96    }
97
98    // If possible, use the flexible YUV format
99    int32_t callbackFormat = params.previewFormat;
100    if (mCallbackToApp) {
101        // TODO: etalvala: This should use the flexible YUV format as well, but
102        // need to reconcile HAL2/HAL3 requirements.
103        callbackFormat = HAL_PIXEL_FORMAT_YV12;
104    } else if(params.fastInfo.useFlexibleYuv &&
105            (params.previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
106             params.previewFormat == HAL_PIXEL_FORMAT_YV12) ) {
107        callbackFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
108    }
109
110    if (!mCallbackToApp && mCallbackConsumer == 0) {
111        // Create CPU buffer queue endpoint, since app hasn't given us one
112        // Make it async to avoid disconnect deadlocks
113        sp<BufferQueue> bq = new BufferQueue();
114        mCallbackConsumer = new CpuConsumer(bq, kCallbackHeapCount);
115        mCallbackConsumer->setFrameAvailableListener(this);
116        mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));
117        mCallbackWindow = new Surface(bq);
118    }
119
120    if (mCallbackStreamId != NO_STREAM) {
121        // Check if stream parameters have to change
122        uint32_t currentWidth, currentHeight, currentFormat;
123        res = device->getStreamInfo(mCallbackStreamId,
124                &currentWidth, &currentHeight, &currentFormat);
125        if (res != OK) {
126            ALOGE("%s: Camera %d: Error querying callback output stream info: "
127                    "%s (%d)", __FUNCTION__, mId,
128                    strerror(-res), res);
129            return res;
130        }
131        if (currentWidth != (uint32_t)params.previewWidth ||
132                currentHeight != (uint32_t)params.previewHeight ||
133                currentFormat != (uint32_t)callbackFormat) {
134            // Since size should only change while preview is not running,
135            // assuming that all existing use of old callback stream is
136            // completed.
137            ALOGV("%s: Camera %d: Deleting stream %d since the buffer "
138                    "parameters changed", __FUNCTION__, mId, mCallbackStreamId);
139            res = device->deleteStream(mCallbackStreamId);
140            if (res != OK) {
141                ALOGE("%s: Camera %d: Unable to delete old output stream "
142                        "for callbacks: %s (%d)", __FUNCTION__,
143                        mId, strerror(-res), res);
144                return res;
145            }
146            mCallbackStreamId = NO_STREAM;
147        }
148    }
149
150    if (mCallbackStreamId == NO_STREAM) {
151        ALOGV("Creating callback stream: %d x %d, format 0x%x, API format 0x%x",
152                params.previewWidth, params.previewHeight,
153                callbackFormat, params.previewFormat);
154        res = device->createStream(mCallbackWindow,
155                params.previewWidth, params.previewHeight,
156                callbackFormat, 0, &mCallbackStreamId);
157        if (res != OK) {
158            ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
159                    "%s (%d)", __FUNCTION__, mId,
160                    strerror(-res), res);
161            return res;
162        }
163    }
164
165    return OK;
166}
167
168status_t CallbackProcessor::deleteStream() {
169    ATRACE_CALL();
170    sp<CameraDeviceBase> device;
171    status_t res;
172    {
173        Mutex::Autolock l(mInputMutex);
174
175        if (mCallbackStreamId == NO_STREAM) {
176            return OK;
177        }
178        device = mDevice.promote();
179        if (device == 0) {
180            ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
181            return INVALID_OPERATION;
182        }
183    }
184    res = device->waitUntilDrained();
185    if (res != OK) {
186        ALOGE("%s: Error waiting for HAL to drain: %s (%d)",
187                __FUNCTION__, strerror(-res), res);
188        return res;
189    }
190
191    res = device->deleteStream(mCallbackStreamId);
192    if (res != OK) {
193        ALOGE("%s: Unable to delete callback stream: %s (%d)",
194                __FUNCTION__, strerror(-res), res);
195        return res;
196    }
197
198    {
199        Mutex::Autolock l(mInputMutex);
200
201        mCallbackHeap.clear();
202        mCallbackWindow.clear();
203        mCallbackConsumer.clear();
204
205        mCallbackStreamId = NO_STREAM;
206    }
207    return OK;
208}
209
210int CallbackProcessor::getStreamId() const {
211    Mutex::Autolock l(mInputMutex);
212    return mCallbackStreamId;
213}
214
215void CallbackProcessor::dump(int /*fd*/, const Vector<String16>& /*args*/) const {
216}
217
218bool CallbackProcessor::threadLoop() {
219    status_t res;
220
221    {
222        Mutex::Autolock l(mInputMutex);
223        while (!mCallbackAvailable) {
224            res = mCallbackAvailableSignal.waitRelative(mInputMutex,
225                    kWaitDuration);
226            if (res == TIMED_OUT) return true;
227        }
228        mCallbackAvailable = false;
229    }
230
231    do {
232        sp<Camera2Client> client = mClient.promote();
233        if (client == 0) {
234            res = discardNewCallback();
235        } else {
236            res = processNewCallback(client);
237        }
238    } while (res == OK);
239
240    return true;
241}
242
243status_t CallbackProcessor::discardNewCallback() {
244    ATRACE_CALL();
245    status_t res;
246    CpuConsumer::LockedBuffer imgBuffer;
247    res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
248    if (res != OK) {
249        if (res != BAD_VALUE) {
250            ALOGE("%s: Camera %d: Error receiving next callback buffer: "
251                    "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
252        }
253        return res;
254    }
255    mCallbackConsumer->unlockBuffer(imgBuffer);
256    return OK;
257}
258
259status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
260    ATRACE_CALL();
261    status_t res;
262
263    sp<Camera2Heap> callbackHeap;
264    bool useFlexibleYuv = false;
265    int32_t previewFormat = 0;
266    size_t heapIdx;
267
268    {
269        /* acquire SharedParameters before mMutex so we don't dead lock
270            with Camera2Client code calling into StreamingProcessor */
271        SharedParameters::Lock l(client->getParameters());
272        Mutex::Autolock m(mInputMutex);
273        CpuConsumer::LockedBuffer imgBuffer;
274        if (mCallbackStreamId == NO_STREAM) {
275            ALOGV("%s: Camera %d:No stream is available"
276                    , __FUNCTION__, mId);
277            return INVALID_OPERATION;
278        }
279
280        ALOGV("%s: Getting buffer", __FUNCTION__);
281        res = mCallbackConsumer->lockNextBuffer(&imgBuffer);
282        if (res != OK) {
283            if (res != BAD_VALUE) {
284                ALOGE("%s: Camera %d: Error receiving next callback buffer: "
285                        "%s (%d)", __FUNCTION__, mId, strerror(-res), res);
286            }
287            return res;
288        }
289        ALOGV("%s: Camera %d: Preview callback available", __FUNCTION__,
290                mId);
291
292        if ( l.mParameters.state != Parameters::PREVIEW
293                && l.mParameters.state != Parameters::RECORD
294                && l.mParameters.state != Parameters::VIDEO_SNAPSHOT) {
295            ALOGV("%s: Camera %d: No longer streaming",
296                    __FUNCTION__, mId);
297            mCallbackConsumer->unlockBuffer(imgBuffer);
298            return OK;
299        }
300
301        if (! (l.mParameters.previewCallbackFlags &
302                CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) ) {
303            ALOGV("%s: No longer enabled, dropping", __FUNCTION__);
304            mCallbackConsumer->unlockBuffer(imgBuffer);
305            return OK;
306        }
307        if ((l.mParameters.previewCallbackFlags &
308                        CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) &&
309                !l.mParameters.previewCallbackOneShot) {
310            ALOGV("%s: One shot mode, already sent, dropping", __FUNCTION__);
311            mCallbackConsumer->unlockBuffer(imgBuffer);
312            return OK;
313        }
314
315        if (imgBuffer.width != static_cast<uint32_t>(l.mParameters.previewWidth) ||
316                imgBuffer.height != static_cast<uint32_t>(l.mParameters.previewHeight)) {
317            ALOGW("%s: The preview size has changed to %d x %d from %d x %d, this buffer is"
318                    " no longer valid, dropping",__FUNCTION__,
319                    l.mParameters.previewWidth, l.mParameters.previewHeight,
320                    imgBuffer.width, imgBuffer.height);
321            mCallbackConsumer->unlockBuffer(imgBuffer);
322            return OK;
323        }
324
325        previewFormat = l.mParameters.previewFormat;
326        useFlexibleYuv = l.mParameters.fastInfo.useFlexibleYuv &&
327                (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
328                 previewFormat == HAL_PIXEL_FORMAT_YV12);
329
330        int32_t expectedFormat = useFlexibleYuv ?
331                HAL_PIXEL_FORMAT_YCbCr_420_888 : previewFormat;
332
333        if (imgBuffer.format != expectedFormat) {
334            ALOGE("%s: Camera %d: Unexpected format for callback: "
335                    "0x%x, expected 0x%x", __FUNCTION__, mId,
336                    imgBuffer.format, expectedFormat);
337            mCallbackConsumer->unlockBuffer(imgBuffer);
338            return INVALID_OPERATION;
339        }
340
341        // In one-shot mode, stop sending callbacks after the first one
342        if (l.mParameters.previewCallbackFlags &
343                CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
344            ALOGV("%s: clearing oneshot", __FUNCTION__);
345            l.mParameters.previewCallbackOneShot = false;
346        }
347
348        uint32_t destYStride = 0;
349        uint32_t destCStride = 0;
350        if (useFlexibleYuv) {
351            if (previewFormat == HAL_PIXEL_FORMAT_YV12) {
352                // Strides must align to 16 for YV12
353                destYStride = ALIGN(imgBuffer.width, 16);
354                destCStride = ALIGN(destYStride / 2, 16);
355            } else {
356                // No padding for NV21
357                ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP,
358                        "Unexpected preview format 0x%x", previewFormat);
359                destYStride = imgBuffer.width;
360                destCStride = destYStride / 2;
361            }
362        } else {
363            destYStride = imgBuffer.stride;
364            // don't care about cStride
365        }
366
367        size_t bufferSize = Camera2Client::calculateBufferSize(
368                imgBuffer.width, imgBuffer.height,
369                previewFormat, destYStride);
370        size_t currentBufferSize = (mCallbackHeap == 0) ?
371                0 : (mCallbackHeap->mHeap->getSize() / kCallbackHeapCount);
372        if (bufferSize != currentBufferSize) {
373            mCallbackHeap.clear();
374            mCallbackHeap = new Camera2Heap(bufferSize, kCallbackHeapCount,
375                    "Camera2Client::CallbackHeap");
376            if (mCallbackHeap->mHeap->getSize() == 0) {
377                ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
378                        __FUNCTION__, mId);
379                mCallbackConsumer->unlockBuffer(imgBuffer);
380                return INVALID_OPERATION;
381            }
382
383            mCallbackHeapHead = 0;
384            mCallbackHeapFree = kCallbackHeapCount;
385        }
386
387        if (mCallbackHeapFree == 0) {
388            ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
389                    __FUNCTION__, mId);
390            mCallbackConsumer->unlockBuffer(imgBuffer);
391            return OK;
392        }
393
394        heapIdx = mCallbackHeapHead;
395
396        mCallbackHeapHead = (mCallbackHeapHead + 1) & kCallbackHeapCount;
397        mCallbackHeapFree--;
398
399        // TODO: Get rid of this copy by passing the gralloc queue all the way
400        // to app
401
402        ssize_t offset;
403        size_t size;
404        sp<IMemoryHeap> heap =
405                mCallbackHeap->mBuffers[heapIdx]->getMemory(&offset,
406                        &size);
407        uint8_t *data = (uint8_t*)heap->getBase() + offset;
408
409        if (!useFlexibleYuv) {
410            // Can just memcpy when HAL format matches API format
411            memcpy(data, imgBuffer.data, bufferSize);
412        } else {
413            res = convertFromFlexibleYuv(previewFormat, data, imgBuffer,
414                    destYStride, destCStride);
415            if (res != OK) {
416                ALOGE("%s: Camera %d: Can't convert between 0x%x and 0x%x formats!",
417                        __FUNCTION__, mId, imgBuffer.format, previewFormat);
418                mCallbackConsumer->unlockBuffer(imgBuffer);
419                return BAD_VALUE;
420            }
421        }
422
423        ALOGV("%s: Freeing buffer", __FUNCTION__);
424        mCallbackConsumer->unlockBuffer(imgBuffer);
425
426        // mCallbackHeap may get freed up once input mutex is released
427        callbackHeap = mCallbackHeap;
428    }
429
430    // Call outside parameter lock to allow re-entrancy from notification
431    {
432        Camera2Client::SharedCameraCallbacks::Lock
433            l(client->mSharedCameraCallbacks);
434        if (l.mRemoteCallback != 0) {
435            ALOGV("%s: Camera %d: Invoking client data callback",
436                    __FUNCTION__, mId);
437            l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
438                    callbackHeap->mBuffers[heapIdx], NULL);
439        }
440    }
441
442    // Only increment free if we're still using the same heap
443    mCallbackHeapFree++;
444
445    ALOGV("%s: exit", __FUNCTION__);
446
447    return OK;
448}
449
450status_t CallbackProcessor::convertFromFlexibleYuv(int32_t previewFormat,
451        uint8_t *dst,
452        const CpuConsumer::LockedBuffer &src,
453        uint32_t dstYStride,
454        uint32_t dstCStride) const {
455
456    if (previewFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
457            previewFormat != HAL_PIXEL_FORMAT_YV12) {
458        ALOGE("%s: Camera %d: Unexpected preview format when using "
459                "flexible YUV: 0x%x", __FUNCTION__, mId, previewFormat);
460        return INVALID_OPERATION;
461    }
462
463    // Copy Y plane, adjusting for stride
464    const uint8_t *ySrc = src.data;
465    uint8_t *yDst = dst;
466    for (size_t row = 0; row < src.height; row++) {
467        memcpy(yDst, ySrc, src.width);
468        ySrc += src.stride;
469        yDst += dstYStride;
470    }
471
472    // Copy/swizzle chroma planes, 4:2:0 subsampling
473    const uint8_t *cbSrc = src.dataCb;
474    const uint8_t *crSrc = src.dataCr;
475    size_t chromaHeight = src.height / 2;
476    size_t chromaWidth = src.width / 2;
477    ssize_t chromaGap = src.chromaStride -
478            (chromaWidth * src.chromaStep);
479    size_t dstChromaGap = dstCStride - chromaWidth;
480
481    if (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
482        // Flexible YUV chroma to NV21 chroma
483        uint8_t *crcbDst = yDst;
484        // Check for shortcuts
485        if (cbSrc == crSrc + 1 && src.chromaStep == 2) {
486            ALOGV("%s: Fast NV21->NV21", __FUNCTION__);
487            // Source has semiplanar CrCb chroma layout, can copy by rows
488            for (size_t row = 0; row < chromaHeight; row++) {
489                memcpy(crcbDst, crSrc, src.width);
490                crcbDst += src.width;
491                crSrc += src.chromaStride;
492            }
493        } else {
494            ALOGV("%s: Generic->NV21", __FUNCTION__);
495            // Generic copy, always works but not very efficient
496            for (size_t row = 0; row < chromaHeight; row++) {
497                for (size_t col = 0; col < chromaWidth; col++) {
498                    *(crcbDst++) = *crSrc;
499                    *(crcbDst++) = *cbSrc;
500                    crSrc += src.chromaStep;
501                    cbSrc += src.chromaStep;
502                }
503                crSrc += chromaGap;
504                cbSrc += chromaGap;
505            }
506        }
507    } else {
508        // flexible YUV chroma to YV12 chroma
509        ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YV12,
510                "Unexpected preview format 0x%x", previewFormat);
511        uint8_t *crDst = yDst;
512        uint8_t *cbDst = yDst + chromaHeight * dstCStride;
513        if (src.chromaStep == 1) {
514            ALOGV("%s: Fast YV12->YV12", __FUNCTION__);
515            // Source has planar chroma layout, can copy by row
516            for (size_t row = 0; row < chromaHeight; row++) {
517                memcpy(crDst, crSrc, chromaWidth);
518                crDst += dstCStride;
519                crSrc += src.chromaStride;
520            }
521            for (size_t row = 0; row < chromaHeight; row++) {
522                memcpy(cbDst, cbSrc, chromaWidth);
523                cbDst += dstCStride;
524                cbSrc += src.chromaStride;
525            }
526        } else {
527            ALOGV("%s: Generic->YV12", __FUNCTION__);
528            // Generic copy, always works but not very efficient
529            for (size_t row = 0; row < chromaHeight; row++) {
530                for (size_t col = 0; col < chromaWidth; col++) {
531                    *(crDst++) = *crSrc;
532                    *(cbDst++) = *cbSrc;
533                    crSrc += src.chromaStep;
534                    cbSrc += src.chromaStep;
535                }
536                crSrc += chromaGap;
537                cbSrc += chromaGap;
538                crDst += dstChromaGap;
539                cbDst += dstChromaGap;
540            }
541        }
542    }
543
544    return OK;
545}
546
547}; // namespace camera2
548}; // namespace android
549