• 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()49 void CallbackProcessor::onFrameAvailable() {
50     Mutex::Autolock l(mInputMutex);
51     if (!mCallbackAvailable) {
52         mCallbackAvailable = true;
53         mCallbackAvailableSignal.signal();
54     }
55 }
56 
setCallbackWindow(sp<ANativeWindow> callbackWindow)57 status_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 
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<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 
deleteStream()168 status_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 
getStreamId() const210 int CallbackProcessor::getStreamId() const {
211     Mutex::Autolock l(mInputMutex);
212     return mCallbackStreamId;
213 }
214 
dump(int,const Vector<String16> &) const215 void CallbackProcessor::dump(int /*fd*/, const Vector<String16>& /*args*/) const {
216 }
217 
threadLoop()218 bool 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 
discardNewCallback()243 status_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 
processNewCallback(sp<Camera2Client> & client)259 status_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 
convertFromFlexibleYuv(int32_t previewFormat,uint8_t * dst,const CpuConsumer::LockedBuffer & src,uint32_t dstYStride,uint32_t dstCStride) const450 status_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