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