StreamingProcessor.cpp revision 22d58d37db6b5f48a10b3a19f69ffda09943c125
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-StreamingProcessor" 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/SurfaceTextureClient.h> 24#include <media/hardware/MetadataBufferType.h> 25 26#include "StreamingProcessor.h" 27#include "Camera2Heap.h" 28#include "../Camera2Client.h" 29#include "../Camera2Device.h" 30 31namespace android { 32namespace camera2 { 33 34StreamingProcessor::StreamingProcessor(wp<Camera2Client> client): 35 mClient(client), 36 mPreviewStreamId(NO_STREAM), 37 mRecordingStreamId(NO_STREAM), 38 mRecordingHeapCount(kDefaultRecordingHeapCount) 39{ 40 41} 42 43StreamingProcessor::~StreamingProcessor() { 44 deletePreviewStream(); 45 deleteRecordingStream(); 46} 47 48status_t StreamingProcessor::setPreviewWindow(sp<ANativeWindow> window) { 49 ATRACE_CALL(); 50 status_t res; 51 52 res = deletePreviewStream(); 53 if (res != OK) return res; 54 55 Mutex::Autolock m(mMutex); 56 57 mPreviewWindow = window; 58 59 return OK; 60} 61 62bool StreamingProcessor::haveValidPreviewWindow() const { 63 Mutex::Autolock m(mMutex); 64 return mPreviewWindow != 0; 65} 66 67status_t StreamingProcessor::updatePreviewRequest(const Parameters ¶ms) { 68 ATRACE_CALL(); 69 status_t res; 70 sp<Camera2Client> client = mClient.promote(); 71 if (client == 0) return INVALID_OPERATION; 72 73 Mutex::Autolock m(mMutex); 74 if (mPreviewRequest.entryCount() == 0) { 75 res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, 76 &mPreviewRequest); 77 if (res != OK) { 78 ALOGE("%s: Camera %d: Unable to create default preview request: " 79 "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res); 80 return res; 81 } 82 } 83 84 res = params.updateRequest(&mPreviewRequest); 85 if (res != OK) { 86 ALOGE("%s: Camera %d: Unable to update common entries of preview " 87 "request: %s (%d)", __FUNCTION__, client->getCameraId(), 88 strerror(-res), res); 89 return res; 90 } 91 92 res = mPreviewRequest.update(ANDROID_REQUEST_ID, 93 &Camera2Client::kPreviewRequestId, 1); 94 95 return OK; 96} 97 98status_t StreamingProcessor::updatePreviewStream(const Parameters ¶ms) { 99 ATRACE_CALL(); 100 Mutex::Autolock m(mMutex); 101 102 status_t res; 103 sp<Camera2Client> client = mClient.promote(); 104 if (client == 0) return INVALID_OPERATION; 105 sp<Camera2Device> device = client->getCameraDevice(); 106 107 if (mPreviewStreamId != NO_STREAM) { 108 // Check if stream parameters have to change 109 uint32_t currentWidth, currentHeight; 110 res = device->getStreamInfo(mPreviewStreamId, 111 ¤tWidth, ¤tHeight, 0); 112 if (res != OK) { 113 ALOGE("%s: Camera %d: Error querying preview stream info: " 114 "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res); 115 return res; 116 } 117 if (currentWidth != (uint32_t)params.previewWidth || 118 currentHeight != (uint32_t)params.previewHeight) { 119 ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d", 120 __FUNCTION__, client->getCameraId(), currentWidth, currentHeight, 121 params.previewWidth, params.previewHeight); 122 res = device->waitUntilDrained(); 123 if (res != OK) { 124 ALOGE("%s: Camera %d: Error waiting for preview to drain: " 125 "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res); 126 return res; 127 } 128 res = device->deleteStream(mPreviewStreamId); 129 if (res != OK) { 130 ALOGE("%s: Camera %d: Unable to delete old output stream " 131 "for preview: %s (%d)", __FUNCTION__, client->getCameraId(), 132 strerror(-res), res); 133 return res; 134 } 135 mPreviewStreamId = NO_STREAM; 136 } 137 } 138 139 if (mPreviewStreamId == NO_STREAM) { 140 res = device->createStream(mPreviewWindow, 141 params.previewWidth, params.previewHeight, 142 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, 143 &mPreviewStreamId); 144 if (res != OK) { 145 ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)", 146 __FUNCTION__, client->getCameraId(), strerror(-res), res); 147 return res; 148 } 149 } 150 151 res = device->setStreamTransform(mPreviewStreamId, 152 params.previewTransform); 153 if (res != OK) { 154 ALOGE("%s: Camera %d: Unable to set preview stream transform: " 155 "%s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res); 156 return res; 157 } 158 159 return OK; 160} 161 162status_t StreamingProcessor::deletePreviewStream() { 163 ATRACE_CALL(); 164 status_t res; 165 166 Mutex::Autolock m(mMutex); 167 168 if (mPreviewStreamId != NO_STREAM) { 169 sp<Camera2Client> client = mClient.promote(); 170 if (client == 0) return INVALID_OPERATION; 171 sp<Camera2Device> device = client->getCameraDevice(); 172 173 res = device->waitUntilDrained(); 174 if (res != OK) { 175 ALOGE("%s: Error waiting for preview to drain: %s (%d)", 176 __FUNCTION__, strerror(-res), res); 177 return res; 178 } 179 res = device->deleteStream(mPreviewStreamId); 180 if (res != OK) { 181 ALOGE("%s: Unable to delete old preview stream: %s (%d)", 182 __FUNCTION__, strerror(-res), res); 183 return res; 184 } 185 mPreviewStreamId = NO_STREAM; 186 } 187 return OK; 188} 189 190status_t StreamingProcessor::getPreviewStreamId() const { 191 Mutex::Autolock m(mMutex); 192 return mPreviewStreamId; 193} 194 195status_t StreamingProcessor::setRecordingBufferCount(size_t count) { 196 ATRACE_CALL(); 197 // 32 is the current upper limit on the video buffer count for BufferQueue 198 sp<Camera2Client> client = mClient.promote(); 199 if (client == 0) return INVALID_OPERATION; 200 if (count > 32) { 201 ALOGE("%s: Camera %d: Error setting %d as video buffer count value", 202 __FUNCTION__, client->getCameraId(), count); 203 return BAD_VALUE; 204 } 205 206 Mutex::Autolock m(mMutex); 207 208 // Need to reallocate memory for heap 209 if (mRecordingHeapCount != count) { 210 if (mRecordingHeap != 0) { 211 mRecordingHeap.clear(); 212 mRecordingHeap = NULL; 213 } 214 mRecordingHeapCount = count; 215 } 216 217 return OK; 218} 219 220status_t StreamingProcessor::updateRecordingRequest(const Parameters ¶ms) { 221 ATRACE_CALL(); 222 status_t res; 223 Mutex::Autolock m(mMutex); 224 225 sp<Camera2Client> client = mClient.promote(); 226 if (client == 0) return INVALID_OPERATION; 227 228 if (mRecordingRequest.entryCount() == 0) { 229 res = client->getCameraDevice()->createDefaultRequest(CAMERA2_TEMPLATE_VIDEO_RECORD, 230 &mRecordingRequest); 231 if (res != OK) { 232 ALOGE("%s: Camera %d: Unable to create default recording request:" 233 " %s (%d)", __FUNCTION__, client->getCameraId(), strerror(-res), res); 234 return res; 235 } 236 } 237 238 res = params.updateRequest(&mRecordingRequest); 239 if (res != OK) { 240 ALOGE("%s: Camera %d: Unable to update common entries of recording " 241 "request: %s (%d)", __FUNCTION__, client->getCameraId(), 242 strerror(-res), res); 243 return res; 244 } 245 246 return OK; 247} 248 249status_t StreamingProcessor::updateRecordingStream(const Parameters ¶ms) { 250 ATRACE_CALL(); 251 status_t res; 252 Mutex::Autolock m(mMutex); 253 254 sp<Camera2Client> client = mClient.promote(); 255 if (client == 0) return INVALID_OPERATION; 256 sp<Camera2Device> device = client->getCameraDevice(); 257 258 if (mRecordingConsumer == 0) { 259 // Create CPU buffer queue endpoint. We need one more buffer here so that we can 260 // always acquire and free a buffer when the heap is full; otherwise the consumer 261 // will have buffers in flight we'll never clear out. 262 mRecordingConsumer = new BufferItemConsumer( 263 GRALLOC_USAGE_HW_VIDEO_ENCODER, 264 mRecordingHeapCount + 1, 265 true); 266 mRecordingConsumer->setFrameAvailableListener(this); 267 mRecordingConsumer->setName(String8("Camera2-RecordingConsumer")); 268 mRecordingWindow = new SurfaceTextureClient( 269 mRecordingConsumer->getProducerInterface()); 270 // Allocate memory later, since we don't know buffer size until receipt 271 } 272 273 if (mRecordingStreamId != NO_STREAM) { 274 // Check if stream parameters have to change 275 uint32_t currentWidth, currentHeight; 276 res = device->getStreamInfo(mRecordingStreamId, 277 ¤tWidth, ¤tHeight, 0); 278 if (res != OK) { 279 ALOGE("%s: Camera %d: Error querying recording output stream info: " 280 "%s (%d)", __FUNCTION__, client->getCameraId(), 281 strerror(-res), res); 282 return res; 283 } 284 if (currentWidth != (uint32_t)params.videoWidth || 285 currentHeight != (uint32_t)params.videoHeight) { 286 // TODO: Should wait to be sure previous recording has finished 287 res = device->deleteStream(mRecordingStreamId); 288 if (res != OK) { 289 ALOGE("%s: Camera %d: Unable to delete old output stream " 290 "for recording: %s (%d)", __FUNCTION__, 291 client->getCameraId(), strerror(-res), res); 292 return res; 293 } 294 mRecordingStreamId = NO_STREAM; 295 } 296 } 297 298 if (mRecordingStreamId == NO_STREAM) { 299 mRecordingFrameCount = 0; 300 res = device->createStream(mRecordingWindow, 301 params.videoWidth, params.videoHeight, 302 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mRecordingStreamId); 303 if (res != OK) { 304 ALOGE("%s: Camera %d: Can't create output stream for recording: " 305 "%s (%d)", __FUNCTION__, client->getCameraId(), 306 strerror(-res), res); 307 return res; 308 } 309 } 310 311 return OK; 312} 313 314status_t StreamingProcessor::deleteRecordingStream() { 315 ATRACE_CALL(); 316 status_t res; 317 318 Mutex::Autolock m(mMutex); 319 320 if (mRecordingStreamId != NO_STREAM) { 321 sp<Camera2Client> client = mClient.promote(); 322 if (client == 0) return INVALID_OPERATION; 323 sp<Camera2Device> device = client->getCameraDevice(); 324 325 res = device->waitUntilDrained(); 326 if (res != OK) { 327 ALOGE("%s: Error waiting for HAL to drain: %s (%d)", 328 __FUNCTION__, strerror(-res), res); 329 return res; 330 } 331 res = device->deleteStream(mRecordingStreamId); 332 if (res != OK) { 333 ALOGE("%s: Unable to delete recording stream: %s (%d)", 334 __FUNCTION__, strerror(-res), res); 335 return res; 336 } 337 mRecordingStreamId = NO_STREAM; 338 } 339 return OK; 340} 341 342status_t StreamingProcessor::getRecordingStreamId() const { 343 return mRecordingStreamId; 344} 345 346status_t StreamingProcessor::startStream(StreamType type, 347 const Vector<uint8_t> &outputStreams) { 348 ATRACE_CALL(); 349 status_t res; 350 351 sp<Camera2Client> client = mClient.promote(); 352 if (client == 0) return INVALID_OPERATION; 353 354 ALOGV("%s: Camera %d: type = %d", __FUNCTION__, client->getCameraId(), type); 355 356 Mutex::Autolock m(mMutex); 357 358 CameraMetadata &request = (type == PREVIEW) ? 359 mPreviewRequest : mRecordingRequest; 360 361 res = request.update( 362 ANDROID_REQUEST_OUTPUT_STREAMS, 363 outputStreams); 364 if (res != OK) { 365 ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)", 366 __FUNCTION__, client->getCameraId(), strerror(-res), res); 367 return res; 368 } 369 370 res = request.sort(); 371 if (res != OK) { 372 ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)", 373 __FUNCTION__, client->getCameraId(), strerror(-res), res); 374 return res; 375 } 376 377 res = client->getCameraDevice()->setStreamingRequest(request); 378 if (res != OK) { 379 ALOGE("%s: Camera %d: Unable to set preview request to start preview: " 380 "%s (%d)", 381 __FUNCTION__, client->getCameraId(), strerror(-res), res); 382 return res; 383 } 384 385 return OK; 386} 387 388status_t StreamingProcessor::stopStream() { 389 ATRACE_CALL(); 390 status_t res; 391 392 sp<Camera2Client> client = mClient.promote(); 393 if (client == 0) return INVALID_OPERATION; 394 sp<Camera2Device> device = client->getCameraDevice(); 395 396 res = device->clearStreamingRequest(); 397 if (res != OK) { 398 ALOGE("%s: Camera %d: Can't clear stream request: %s (%d)", 399 __FUNCTION__, client->getCameraId(), strerror(-res), res); 400 return res; 401 } 402 res = device->waitUntilDrained(); 403 if (res != OK) { 404 ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)", 405 __FUNCTION__, client->getCameraId(), strerror(-res), res); 406 return res; 407 } 408 return OK; 409} 410 411void StreamingProcessor::onFrameAvailable() { 412 ATRACE_CALL(); 413 status_t res; 414 sp<Camera2Heap> recordingHeap; 415 size_t heapIdx = 0; 416 nsecs_t timestamp; 417 418 sp<Camera2Client> client = mClient.promote(); 419 if (client == 0) return; 420 421 { 422 Mutex::Autolock m(mMutex); 423 BufferItemConsumer::BufferItem imgBuffer; 424 res = mRecordingConsumer->acquireBuffer(&imgBuffer); 425 if (res != OK) { 426 ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)", 427 __FUNCTION__, client->getCameraId(), strerror(-res), res); 428 return; 429 } 430 timestamp = imgBuffer.mTimestamp; 431 432 mRecordingFrameCount++; 433 ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount); 434 435 { 436 SharedParameters::Lock l(client->getParameters()); 437 // TODO: Signal errors here upstream 438 if (l.mParameters.state != Parameters::RECORD && 439 l.mParameters.state != Parameters::VIDEO_SNAPSHOT) { 440 ALOGV("%s: Camera %d: Discarding recording image buffers " 441 "received after recording done", __FUNCTION__, 442 client->getCameraId()); 443 mRecordingConsumer->releaseBuffer(imgBuffer); 444 return; 445 } 446 } 447 448 if (mRecordingHeap == 0) { 449 const size_t bufferSize = 4 + sizeof(buffer_handle_t); 450 ALOGV("%s: Camera %d: Creating recording heap with %d buffers of " 451 "size %d bytes", __FUNCTION__, client->getCameraId(), 452 mRecordingHeapCount, bufferSize); 453 454 mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount, 455 "Camera2Client::RecordingHeap"); 456 if (mRecordingHeap->mHeap->getSize() == 0) { 457 ALOGE("%s: Camera %d: Unable to allocate memory for recording", 458 __FUNCTION__, client->getCameraId()); 459 mRecordingConsumer->releaseBuffer(imgBuffer); 460 return; 461 } 462 for (size_t i = 0; i < mRecordingBuffers.size(); i++) { 463 if (mRecordingBuffers[i].mBuf != 464 BufferItemConsumer::INVALID_BUFFER_SLOT) { 465 ALOGE("%s: Camera %d: Non-empty recording buffers list!", 466 __FUNCTION__, client->getCameraId()); 467 } 468 } 469 mRecordingBuffers.clear(); 470 mRecordingBuffers.setCapacity(mRecordingHeapCount); 471 mRecordingBuffers.insertAt(0, mRecordingHeapCount); 472 473 mRecordingHeapHead = 0; 474 mRecordingHeapFree = mRecordingHeapCount; 475 } 476 477 if ( mRecordingHeapFree == 0) { 478 ALOGE("%s: Camera %d: No free recording buffers, dropping frame", 479 __FUNCTION__, client->getCameraId()); 480 mRecordingConsumer->releaseBuffer(imgBuffer); 481 return; 482 } 483 484 heapIdx = mRecordingHeapHead; 485 mRecordingHeapHead = (mRecordingHeapHead + 1) % mRecordingHeapCount; 486 mRecordingHeapFree--; 487 488 ALOGV("%s: Camera %d: Timestamp %lld", 489 __FUNCTION__, client->getCameraId(), timestamp); 490 491 ssize_t offset; 492 size_t size; 493 sp<IMemoryHeap> heap = 494 mRecordingHeap->mBuffers[heapIdx]->getMemory(&offset, 495 &size); 496 497 uint8_t *data = (uint8_t*)heap->getBase() + offset; 498 uint32_t type = kMetadataBufferTypeGrallocSource; 499 *((uint32_t*)data) = type; 500 *((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle; 501 ALOGV("%s: Camera %d: Sending out buffer_handle_t %p", 502 __FUNCTION__, client->getCameraId(), 503 imgBuffer.mGraphicBuffer->handle); 504 mRecordingBuffers.replaceAt(imgBuffer, heapIdx); 505 recordingHeap = mRecordingHeap; 506 } 507 508 // Call outside locked parameters to allow re-entrancy from notification 509 Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); 510 if (l.mCameraClient != 0) { 511 l.mCameraClient->dataCallbackTimestamp(timestamp, 512 CAMERA_MSG_VIDEO_FRAME, 513 recordingHeap->mBuffers[heapIdx]); 514 } 515} 516 517void StreamingProcessor::releaseRecordingFrame(const sp<IMemory>& mem) { 518 ATRACE_CALL(); 519 status_t res; 520 521 sp<Camera2Client> client = mClient.promote(); 522 if (client == 0) return; 523 524 Mutex::Autolock m(mMutex); 525 // Make sure this is for the current heap 526 ssize_t offset; 527 size_t size; 528 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); 529 if (heap->getHeapID() != mRecordingHeap->mHeap->getHeapID()) { 530 ALOGW("%s: Camera %d: Mismatched heap ID, ignoring release " 531 "(got %x, expected %x)", __FUNCTION__, client->getCameraId(), 532 heap->getHeapID(), mRecordingHeap->mHeap->getHeapID()); 533 return; 534 } 535 uint8_t *data = (uint8_t*)heap->getBase() + offset; 536 uint32_t type = *(uint32_t*)data; 537 if (type != kMetadataBufferTypeGrallocSource) { 538 ALOGE("%s: Camera %d: Recording frame type invalid (got %x, expected %x)", 539 __FUNCTION__, client->getCameraId(), type, 540 kMetadataBufferTypeGrallocSource); 541 return; 542 } 543 544 // Release the buffer back to the recording queue 545 546 buffer_handle_t imgHandle = *(buffer_handle_t*)(data + 4); 547 548 size_t itemIndex; 549 for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) { 550 const BufferItemConsumer::BufferItem item = 551 mRecordingBuffers[itemIndex]; 552 if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT && 553 item.mGraphicBuffer->handle == imgHandle) { 554 break; 555 } 556 } 557 if (itemIndex == mRecordingBuffers.size()) { 558 ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of " 559 "outstanding buffers", __FUNCTION__, client->getCameraId(), 560 imgHandle); 561 return; 562 } 563 564 ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__, 565 client->getCameraId(), imgHandle); 566 567 res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]); 568 if (res != OK) { 569 ALOGE("%s: Camera %d: Unable to free recording frame " 570 "(buffer_handle_t: %p): %s (%d)", __FUNCTION__, 571 client->getCameraId(), imgHandle, strerror(-res), res); 572 return; 573 } 574 mRecordingBuffers.replaceAt(itemIndex); 575 576 mRecordingHeapFree++; 577} 578 579 580status_t StreamingProcessor::dump(int fd, const Vector<String16>& args) { 581 String8 result; 582 583 result.append(" Current requests:\n"); 584 if (mPreviewRequest.entryCount() != 0) { 585 result.append(" Preview request:\n"); 586 write(fd, result.string(), result.size()); 587 mPreviewRequest.dump(fd, 2, 6); 588 } else { 589 result.append(" Preview request: undefined\n"); 590 write(fd, result.string(), result.size()); 591 } 592 593 if (mRecordingRequest.entryCount() != 0) { 594 result = " Recording request:\n"; 595 write(fd, result.string(), result.size()); 596 mRecordingRequest.dump(fd, 2, 6); 597 } else { 598 result = " Recording request: undefined\n"; 599 write(fd, result.string(), result.size()); 600 } 601 602 return OK; 603} 604 605}; // namespace camera2 606}; // namespace android 607