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