• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 namespace android {
32 namespace camera2 {
33 
CallbackProcessor(sp<Camera2Client> client)34 CallbackProcessor::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 
~CallbackProcessor()44 CallbackProcessor::~CallbackProcessor() {
45     ALOGV("%s: Exit", __FUNCTION__);
46     deleteStream();
47 }
48 
onFrameAvailable(const BufferItem &)49 void CallbackProcessor::onFrameAvailable(const BufferItem& /*item*/) {
50     Mutex::Autolock l(mInputMutex);
51     if (!mCallbackAvailable) {
52         mCallbackAvailable = true;
53         mCallbackAvailableSignal.signal();
54     }
55 }
56 
setCallbackWindow(const sp<Surface> & callbackWindow)57 status_t CallbackProcessor::setCallbackWindow(
58         const sp<Surface>& 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 
updateStream(const Parameters & params)86 status_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<IGraphicBufferProducer> producer;
114         sp<IGraphicBufferConsumer> consumer;
115         BufferQueue::createBufferQueue(&producer, &consumer);
116         mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount);
117         mCallbackConsumer->setFrameAvailableListener(this);
118         mCallbackConsumer->setName(String8("Camera2-CallbackConsumer"));
119         mCallbackWindow = new Surface(producer);
120     }
121 
122     if (mCallbackStreamId != NO_STREAM) {
123         // Check if stream parameters have to change
124         CameraDeviceBase::StreamInfo streamInfo;
125         res = device->getStreamInfo(mCallbackStreamId, &streamInfo);
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 (streamInfo.width != (uint32_t)params.previewWidth ||
133                 streamInfo.height != (uint32_t)params.previewHeight ||
134                 !streamInfo.matchFormat((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, callbackFormat,
157                 HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_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 
deleteStream()169 status_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 
getStreamId() const211 int CallbackProcessor::getStreamId() const {
212     Mutex::Autolock l(mInputMutex);
213     return mCallbackStreamId;
214 }
215 
dump(int,const Vector<String16> &) const216 void CallbackProcessor::dump(int /*fd*/, const Vector<String16>& /*args*/) const {
217 }
218 
threadLoop()219 bool 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 
discardNewCallback()244 status_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 
processNewCallback(sp<Camera2Client> & client)260 status_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         if (imgBuffer.width != static_cast<uint32_t>(l.mParameters.previewWidth) ||
317                 imgBuffer.height != static_cast<uint32_t>(l.mParameters.previewHeight)) {
318             ALOGW("%s: The preview size has changed to %d x %d from %d x %d, this buffer is"
319                     " no longer valid, dropping",__FUNCTION__,
320                     l.mParameters.previewWidth, l.mParameters.previewHeight,
321                     imgBuffer.width, imgBuffer.height);
322             mCallbackConsumer->unlockBuffer(imgBuffer);
323             return OK;
324         }
325 
326         previewFormat = l.mParameters.previewFormat;
327         useFlexibleYuv = l.mParameters.fastInfo.useFlexibleYuv &&
328                 (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
329                  previewFormat == HAL_PIXEL_FORMAT_YV12);
330 
331         int32_t expectedFormat = useFlexibleYuv ?
332                 HAL_PIXEL_FORMAT_YCbCr_420_888 : previewFormat;
333 
334         if (imgBuffer.format != expectedFormat) {
335             ALOGE("%s: Camera %d: Unexpected format for callback: "
336                     "0x%x, expected 0x%x", __FUNCTION__, mId,
337                     imgBuffer.format, expectedFormat);
338             mCallbackConsumer->unlockBuffer(imgBuffer);
339             return INVALID_OPERATION;
340         }
341 
342         // In one-shot mode, stop sending callbacks after the first one
343         if (l.mParameters.previewCallbackFlags &
344                 CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
345             ALOGV("%s: clearing oneshot", __FUNCTION__);
346             l.mParameters.previewCallbackOneShot = false;
347         }
348 
349         uint32_t destYStride = 0;
350         uint32_t destCStride = 0;
351         if (useFlexibleYuv) {
352             if (previewFormat == HAL_PIXEL_FORMAT_YV12) {
353                 // Strides must align to 16 for YV12
354                 destYStride = ALIGN(imgBuffer.width, 16);
355                 destCStride = ALIGN(destYStride / 2, 16);
356             } else {
357                 // No padding for NV21
358                 ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP,
359                         "Unexpected preview format 0x%x", previewFormat);
360                 destYStride = imgBuffer.width;
361                 destCStride = destYStride / 2;
362             }
363         } else {
364             destYStride = imgBuffer.stride;
365             // don't care about cStride
366         }
367 
368         size_t bufferSize = Camera2Client::calculateBufferSize(
369                 imgBuffer.width, imgBuffer.height,
370                 previewFormat, destYStride);
371         size_t currentBufferSize = (mCallbackHeap == 0) ?
372                 0 : (mCallbackHeap->mHeap->getSize() / kCallbackHeapCount);
373         if (bufferSize != currentBufferSize) {
374             mCallbackHeap.clear();
375             mCallbackHeap = new Camera2Heap(bufferSize, kCallbackHeapCount,
376                     "Camera2Client::CallbackHeap");
377             if (mCallbackHeap->mHeap->getSize() == 0) {
378                 ALOGE("%s: Camera %d: Unable to allocate memory for callbacks",
379                         __FUNCTION__, mId);
380                 mCallbackConsumer->unlockBuffer(imgBuffer);
381                 return INVALID_OPERATION;
382             }
383 
384             mCallbackHeapHead = 0;
385             mCallbackHeapFree = kCallbackHeapCount;
386         }
387 
388         if (mCallbackHeapFree == 0) {
389             ALOGE("%s: Camera %d: No free callback buffers, dropping frame",
390                     __FUNCTION__, mId);
391             mCallbackConsumer->unlockBuffer(imgBuffer);
392             return OK;
393         }
394 
395         heapIdx = mCallbackHeapHead;
396 
397         mCallbackHeapHead = (mCallbackHeapHead + 1) % kCallbackHeapCount;
398         mCallbackHeapFree--;
399 
400         // TODO: Get rid of this copy by passing the gralloc queue all the way
401         // to app
402 
403         ssize_t offset;
404         size_t size;
405         sp<IMemoryHeap> heap =
406                 mCallbackHeap->mBuffers[heapIdx]->getMemory(&offset,
407                         &size);
408         uint8_t *data = (uint8_t*)heap->getBase() + offset;
409 
410         if (!useFlexibleYuv) {
411             // Can just memcpy when HAL format matches API format
412             memcpy(data, imgBuffer.data, bufferSize);
413         } else {
414             res = convertFromFlexibleYuv(previewFormat, data, imgBuffer,
415                     destYStride, destCStride);
416             if (res != OK) {
417                 ALOGE("%s: Camera %d: Can't convert between 0x%x and 0x%x formats!",
418                         __FUNCTION__, mId, imgBuffer.format, previewFormat);
419                 mCallbackConsumer->unlockBuffer(imgBuffer);
420                 return BAD_VALUE;
421             }
422         }
423 
424         ALOGV("%s: Freeing buffer", __FUNCTION__);
425         mCallbackConsumer->unlockBuffer(imgBuffer);
426 
427         // mCallbackHeap may get freed up once input mutex is released
428         callbackHeap = mCallbackHeap;
429     }
430 
431     // Call outside parameter lock to allow re-entrancy from notification
432     {
433         Camera2Client::SharedCameraCallbacks::Lock
434             l(client->mSharedCameraCallbacks);
435         if (l.mRemoteCallback != 0) {
436             ALOGV("%s: Camera %d: Invoking client data callback",
437                     __FUNCTION__, mId);
438             l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
439                     callbackHeap->mBuffers[heapIdx], NULL);
440         }
441     }
442 
443     // Only increment free if we're still using the same heap
444     mCallbackHeapFree++;
445 
446     ALOGV("%s: exit", __FUNCTION__);
447 
448     return OK;
449 }
450 
convertFromFlexibleYuv(int32_t previewFormat,uint8_t * dst,const CpuConsumer::LockedBuffer & src,uint32_t dstYStride,uint32_t dstCStride) const451 status_t CallbackProcessor::convertFromFlexibleYuv(int32_t previewFormat,
452         uint8_t *dst,
453         const CpuConsumer::LockedBuffer &src,
454         uint32_t dstYStride,
455         uint32_t dstCStride) const {
456 
457     if (previewFormat != HAL_PIXEL_FORMAT_YCrCb_420_SP &&
458             previewFormat != HAL_PIXEL_FORMAT_YV12) {
459         ALOGE("%s: Camera %d: Unexpected preview format when using "
460                 "flexible YUV: 0x%x", __FUNCTION__, mId, previewFormat);
461         return INVALID_OPERATION;
462     }
463 
464     // Copy Y plane, adjusting for stride
465     const uint8_t *ySrc = src.data;
466     uint8_t *yDst = dst;
467     for (size_t row = 0; row < src.height; row++) {
468         memcpy(yDst, ySrc, src.width);
469         ySrc += src.stride;
470         yDst += dstYStride;
471     }
472 
473     // Copy/swizzle chroma planes, 4:2:0 subsampling
474     const uint8_t *cbSrc = src.dataCb;
475     const uint8_t *crSrc = src.dataCr;
476     size_t chromaHeight = src.height / 2;
477     size_t chromaWidth = src.width / 2;
478     ssize_t chromaGap = src.chromaStride -
479             (chromaWidth * src.chromaStep);
480     size_t dstChromaGap = dstCStride - chromaWidth;
481 
482     if (previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
483         // Flexible YUV chroma to NV21 chroma
484         uint8_t *crcbDst = yDst;
485         // Check for shortcuts
486         if (cbSrc == crSrc + 1 && src.chromaStep == 2) {
487             ALOGV("%s: Fast NV21->NV21", __FUNCTION__);
488             // Source has semiplanar CrCb chroma layout, can copy by rows
489             for (size_t row = 0; row < chromaHeight; row++) {
490                 memcpy(crcbDst, crSrc, src.width);
491                 crcbDst += src.width;
492                 crSrc += src.chromaStride;
493             }
494         } else {
495             ALOGV("%s: Generic->NV21", __FUNCTION__);
496             // Generic copy, always works but not very efficient
497             for (size_t row = 0; row < chromaHeight; row++) {
498                 for (size_t col = 0; col < chromaWidth; col++) {
499                     *(crcbDst++) = *crSrc;
500                     *(crcbDst++) = *cbSrc;
501                     crSrc += src.chromaStep;
502                     cbSrc += src.chromaStep;
503                 }
504                 crSrc += chromaGap;
505                 cbSrc += chromaGap;
506             }
507         }
508     } else {
509         // flexible YUV chroma to YV12 chroma
510         ALOG_ASSERT(previewFormat == HAL_PIXEL_FORMAT_YV12,
511                 "Unexpected preview format 0x%x", previewFormat);
512         uint8_t *crDst = yDst;
513         uint8_t *cbDst = yDst + chromaHeight * dstCStride;
514         if (src.chromaStep == 1) {
515             ALOGV("%s: Fast YV12->YV12", __FUNCTION__);
516             // Source has planar chroma layout, can copy by row
517             for (size_t row = 0; row < chromaHeight; row++) {
518                 memcpy(crDst, crSrc, chromaWidth);
519                 crDst += dstCStride;
520                 crSrc += src.chromaStride;
521             }
522             for (size_t row = 0; row < chromaHeight; row++) {
523                 memcpy(cbDst, cbSrc, chromaWidth);
524                 cbDst += dstCStride;
525                 cbSrc += src.chromaStride;
526             }
527         } else {
528             ALOGV("%s: Generic->YV12", __FUNCTION__);
529             // Generic copy, always works but not very efficient
530             for (size_t row = 0; row < chromaHeight; row++) {
531                 for (size_t col = 0; col < chromaWidth; col++) {
532                     *(crDst++) = *crSrc;
533                     *(cbDst++) = *cbSrc;
534                     crSrc += src.chromaStep;
535                     cbSrc += src.chromaStep;
536                 }
537                 crSrc += chromaGap;
538                 cbSrc += chromaGap;
539                 crDst += dstChromaGap;
540                 cbDst += dstChromaGap;
541             }
542         }
543     }
544 
545     return OK;
546 }
547 
548 }; // namespace camera2
549 }; // namespace android
550