CallbackProcessor.cpp revision deeef54487a34034dc0cfaab20b20d557224c07c
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        previewFormat = l.mParameters.previewFormat;
316        useFlexibleYuv = l.mParameters.fastInfo.useFlexibleYuv &&
317                (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
318                 previewFormat == HAL_PIXEL_FORMAT_YV12);
319
320        int32_t expectedFormat = useFlexibleYuv ?
321                HAL_PIXEL_FORMAT_YCbCr_420_888 : previewFormat;
322
323        if (imgBuffer.format != expectedFormat) {
324            ALOGE("%s: Camera %d: Unexpected format for callback: "
325                    "0x%x, expected 0x%x", __FUNCTION__, mId,
326                    imgBuffer.format, expectedFormat);
327            mCallbackConsumer->unlockBuffer(imgBuffer);
328            return INVALID_OPERATION;
329        }
330
331        // In one-shot mode, stop sending callbacks after the first one
332        if (l.mParameters.previewCallbackFlags &
333                CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
334            ALOGV("%s: clearing oneshot", __FUNCTION__);
335            l.mParameters.previewCallbackOneShot = false;
336        }
337
338        uint32_t destYStride = 0;
339        uint32_t destCStride = 0;
340        if (useFlexibleYuv) {
341            if (previewFormat == HAL_PIXEL_FORMAT_YV12) {
342                // Strides must align to 16 for YV12
343                destYStride = ALIGN(imgBuffer.width, 16);
344                destCStride = ALIGN(destYStride / 2, 16);
345            } else {
346                // No padding for NV21
347                ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP,
348                        "Unexpected preview format 0x%x", previewFormat);
349                destYStride = imgBuffer.width;
350                destCStride = destYStride / 2;
351            }
352        } else {
353            destYStride = imgBuffer.stride;
354            // don't care about cStride
355        }
356
357        size_t bufferSize = Camera2Client::calculateBufferSize(
358                imgBuffer.width, imgBuffer.height,
359                previewFormat, destYStride);
360        size_t currentBufferSize = (mCallbackHeap == 0) ?
361                0 : (mCallbackHeap->mHeap->getSize() / kCallbackHeapCount);
362        if (bufferSize != currentBufferSize) {
363            mCallbackHeap.clear();
364            mCallbackHeap = new Camera2Heap(bufferSize, kCallbackHeapCount,
365                    "Camera2Client::CallbackHeap");
366            if (mCallbackHeap->mHeap->getSize() == 0) {
367                ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
368                        __FUNCTION__, mId);
369                mCallbackConsumer->unlockBuffer(imgBuffer);
370                return INVALID_OPERATION;
371            }
372
373            mCallbackHeapHead = 0;
374            mCallbackHeapFree = kCallbackHeapCount;
375        }
376
377        if (mCallbackHeapFree == 0) {
378            ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
379                    __FUNCTION__, mId);
380            mCallbackConsumer->unlockBuffer(imgBuffer);
381            return OK;
382        }
383
384        heapIdx = mCallbackHeapHead;
385
386        mCallbackHeapHead = (mCallbackHeapHead + 1) & kCallbackHeapCount;
387        mCallbackHeapFree--;
388
389        // TODO: Get rid of this copy by passing the gralloc queue all the way
390        // to app
391
392        ssize_t offset;
393        size_t size;
394        sp<IMemoryHeap> heap =
395                mCallbackHeap->mBuffers[heapIdx]->getMemory(&offset,
396                        &size);
397        uint8_t *data = (uint8_t*)heap->getBase() + offset;
398
399        if (!useFlexibleYuv) {
400            // Can just memcpy when HAL format matches API format
401            memcpy(data, imgBuffer.data, bufferSize);
402        } else {
403            res = convertFromFlexibleYuv(previewFormat, data, imgBuffer,
404                    destYStride, destCStride);
405            if (res != OK) {
406                ALOGE("%s: Camera %d: Can't convert between 0x%x and 0x%x formats!",
407                        __FUNCTION__, mId, imgBuffer.format, previewFormat);
408                mCallbackConsumer->unlockBuffer(imgBuffer);
409                return BAD_VALUE;
410            }
411        }
412
413        ALOGV("%s: Freeing buffer", __FUNCTION__);
414        mCallbackConsumer->unlockBuffer(imgBuffer);
415
416        // mCallbackHeap may get freed up once input mutex is released
417        callbackHeap = mCallbackHeap;
418    }
419
420    // Call outside parameter lock to allow re-entrancy from notification
421    {
422        Camera2Client::SharedCameraCallbacks::Lock
423            l(client->mSharedCameraCallbacks);
424        if (l.mRemoteCallback != 0) {
425            ALOGV("%s: Camera %d: Invoking client data callback",
426                    __FUNCTION__, mId);
427            l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
428                    callbackHeap->mBuffers[heapIdx], NULL);
429        }
430    }
431
432    // Only increment free if we're still using the same heap
433    mCallbackHeapFree++;
434
435    ALOGV("%s: exit", __FUNCTION__);
436
437    return OK;
438}
439
440status_t CallbackProcessor::convertFromFlexibleYuv(int32_t previewFormat,
441        uint8_t *dst,
442        const CpuConsumer::LockedBuffer &src,
443        uint32_t dstYStride,
444        uint32_t dstCStride) const {
445
446    if (previewFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
447            previewFormat != HAL_PIXEL_FORMAT_YV12) {
448        ALOGE("%s: Camera %d: Unexpected preview format when using "
449                "flexible YUV: 0x%x", __FUNCTION__, mId, previewFormat);
450        return INVALID_OPERATION;
451    }
452
453    // Copy Y plane, adjusting for stride
454    const uint8_t *ySrc = src.data;
455    uint8_t *yDst = dst;
456    for (size_t row = 0; row < src.height; row++) {
457        memcpy(yDst, ySrc, src.width);
458        ySrc += src.stride;
459        yDst += dstYStride;
460    }
461
462    // Copy/swizzle chroma planes, 4:2:0 subsampling
463    const uint8_t *cbSrc = src.dataCb;
464    const uint8_t *crSrc = src.dataCr;
465    size_t chromaHeight = src.height / 2;
466    size_t chromaWidth = src.width / 2;
467    ssize_t chromaGap = src.chromaStride -
468            (chromaWidth * src.chromaStep);
469    size_t dstChromaGap = dstCStride - chromaWidth;
470
471    if (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
472        // Flexible YUV chroma to NV21 chroma
473        uint8_t *crcbDst = yDst;
474        // Check for shortcuts
475        if (cbSrc == crSrc + 1 && src.chromaStep == 2) {
476            ALOGV("%s: Fast NV21->NV21", __FUNCTION__);
477            // Source has semiplanar CrCb chroma layout, can copy by rows
478            for (size_t row = 0; row < chromaHeight; row++) {
479                memcpy(crcbDst, crSrc, src.width);
480                crcbDst += src.width;
481                crSrc += src.chromaStride;
482            }
483        } else {
484            ALOGV("%s: Generic->NV21", __FUNCTION__);
485            // Generic copy, always works but not very efficient
486            for (size_t row = 0; row < chromaHeight; row++) {
487                for (size_t col = 0; col < chromaWidth; col++) {
488                    *(crcbDst++) = *crSrc;
489                    *(crcbDst++) = *cbSrc;
490                    crSrc += src.chromaStep;
491                    cbSrc += src.chromaStep;
492                }
493                crSrc += chromaGap;
494                cbSrc += chromaGap;
495            }
496        }
497    } else {
498        // flexible YUV chroma to YV12 chroma
499        ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YV12,
500                "Unexpected preview format 0x%x", previewFormat);
501        uint8_t *crDst = yDst;
502        uint8_t *cbDst = yDst + chromaHeight * dstCStride;
503        if (src.chromaStep == 1) {
504            ALOGV("%s: Fast YV12->YV12", __FUNCTION__);
505            // Source has planar chroma layout, can copy by row
506            for (size_t row = 0; row < chromaHeight; row++) {
507                memcpy(crDst, crSrc, chromaWidth);
508                crDst += dstCStride;
509                crSrc += src.chromaStride;
510            }
511            for (size_t row = 0; row < chromaHeight; row++) {
512                memcpy(cbDst, cbSrc, chromaWidth);
513                cbDst += dstCStride;
514                cbSrc += src.chromaStride;
515            }
516        } else {
517            ALOGV("%s: Generic->YV12", __FUNCTION__);
518            // Generic copy, always works but not very efficient
519            for (size_t row = 0; row < chromaHeight; row++) {
520                for (size_t col = 0; col < chromaWidth; col++) {
521                    *(crDst++) = *crSrc;
522                    *(cbDst++) = *cbSrc;
523                    crSrc += src.chromaStep;
524                    cbSrc += src.chromaStep;
525                }
526                crSrc += chromaGap;
527                cbSrc += chromaGap;
528                crDst += dstChromaGap;
529                cbDst += dstChromaGap;
530            }
531        }
532    }
533
534    return OK;
535}
536
537}; // namespace camera2
538}; // namespace android
539