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