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