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 ¶ms) {
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 ¤tWidth, ¤tHeight, ¤tFormat);
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