1 /* 2 * Copyright (C) 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 #define LOG_TAG "ExtCamDevSsn (at) 3.4" 17 //#define LOG_NDEBUG 0 18 #define ATRACE_TAG ATRACE_TAG_CAMERA 19 #include <log/log.h> 20 21 #include <inttypes.h> 22 #include "ExternalCameraDeviceSession.h" 23 24 #include "android-base/macros.h" 25 #include <utils/Timers.h> 26 #include <utils/Trace.h> 27 #include <linux/videodev2.h> 28 #include <sync/sync.h> 29 30 #define HAVE_JPEG // required for libyuv.h to export MJPEG decode APIs 31 #include <libyuv.h> 32 33 #include <jpeglib.h> 34 35 36 namespace android { 37 namespace hardware { 38 namespace camera { 39 namespace device { 40 namespace V3_4 { 41 namespace implementation { 42 43 namespace { 44 // Size of request/result metadata fast message queue. Change to 0 to always use hwbinder buffer. 45 static constexpr size_t kMetadataMsgQueueSize = 1 << 18 /* 256kB */; 46 47 const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get rid of some initial 48 // bad frames. TODO: develop a better bad frame detection 49 // method 50 constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some 51 // webcam showing temporarily ioctl failures. 52 constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 0.5 seconds 53 54 // Constants for tryLock during dumpstate 55 static constexpr int kDumpLockRetries = 50; 56 static constexpr int kDumpLockSleep = 60000; 57 58 bool tryLock(Mutex& mutex) 59 { 60 bool locked = false; 61 for (int i = 0; i < kDumpLockRetries; ++i) { 62 if (mutex.tryLock() == NO_ERROR) { 63 locked = true; 64 break; 65 } 66 usleep(kDumpLockSleep); 67 } 68 return locked; 69 } 70 71 bool tryLock(std::mutex& mutex) 72 { 73 bool locked = false; 74 for (int i = 0; i < kDumpLockRetries; ++i) { 75 if (mutex.try_lock()) { 76 locked = true; 77 break; 78 } 79 usleep(kDumpLockSleep); 80 } 81 return locked; 82 } 83 84 } // Anonymous namespace 85 86 // Static instances 87 const int ExternalCameraDeviceSession::kMaxProcessedStream; 88 const int ExternalCameraDeviceSession::kMaxStallStream; 89 HandleImporter ExternalCameraDeviceSession::sHandleImporter; 90 91 ExternalCameraDeviceSession::ExternalCameraDeviceSession( 92 const sp<ICameraDeviceCallback>& callback, 93 const ExternalCameraConfig& cfg, 94 const std::vector<SupportedV4L2Format>& sortedFormats, 95 const CroppingType& croppingType, 96 const common::V1_0::helper::CameraMetadata& chars, 97 const std::string& cameraId, 98 unique_fd v4l2Fd) : 99 mCallback(callback), 100 mCfg(cfg), 101 mCameraCharacteristics(chars), 102 mSupportedFormats(sortedFormats), 103 mCroppingType(croppingType), 104 mCameraId(cameraId), 105 mV4l2Fd(std::move(v4l2Fd)), 106 mOutputThread(new OutputThread(this, mCroppingType)), 107 mMaxThumbResolution(getMaxThumbResolution()), 108 mMaxJpegResolution(getMaxJpegResolution()) { 109 mInitFail = initialize(); 110 } 111 112 bool ExternalCameraDeviceSession::initialize() { 113 if (mV4l2Fd.get() < 0) { 114 ALOGE("%s: invalid v4l2 device fd %d!", __FUNCTION__, mV4l2Fd.get()); 115 return true; 116 } 117 118 struct v4l2_capability capability; 119 int ret = ioctl(mV4l2Fd.get(), VIDIOC_QUERYCAP, &capability); 120 std::string make, model; 121 if (ret < 0) { 122 ALOGW("%s v4l2 QUERYCAP failed", __FUNCTION__); 123 make = "Generic UVC webcam"; 124 model = "Generic UVC webcam"; 125 } else { 126 // capability.card is UTF-8 encoded 127 char card[32]; 128 int j = 0; 129 for (int i = 0; i < 32; i++) { 130 if (capability.card[i] < 128) { 131 card[j++] = capability.card[i]; 132 } 133 if (capability.card[i] == '\0') { 134 break; 135 } 136 } 137 if (j == 0 || card[j - 1] != '\0') { 138 make = "Generic UVC webcam"; 139 model = "Generic UVC webcam"; 140 } else { 141 make = card; 142 model = card; 143 } 144 } 145 mOutputThread->setExifMakeModel(make, model); 146 147 status_t status = initDefaultRequests(); 148 if (status != OK) { 149 ALOGE("%s: init default requests failed!", __FUNCTION__); 150 return true; 151 } 152 153 mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>( 154 kMetadataMsgQueueSize, false /* non blocking */); 155 if (!mRequestMetadataQueue->isValid()) { 156 ALOGE("%s: invalid request fmq", __FUNCTION__); 157 return true; 158 } 159 mResultMetadataQueue = std::make_shared<RequestMetadataQueue>( 160 kMetadataMsgQueueSize, false /* non blocking */); 161 if (!mResultMetadataQueue->isValid()) { 162 ALOGE("%s: invalid result fmq", __FUNCTION__); 163 return true; 164 } 165 166 // TODO: check is PRIORITY_DISPLAY enough? 167 mOutputThread->run("ExtCamOut", PRIORITY_DISPLAY); 168 return false; 169 } 170 171 Status ExternalCameraDeviceSession::initStatus() const { 172 Mutex::Autolock _l(mLock); 173 Status status = Status::OK; 174 if (mInitFail || mClosed) { 175 ALOGI("%s: sesssion initFailed %d closed %d", __FUNCTION__, mInitFail, mClosed); 176 status = Status::INTERNAL_ERROR; 177 } 178 return status; 179 } 180 181 ExternalCameraDeviceSession::~ExternalCameraDeviceSession() { 182 if (!isClosed()) { 183 ALOGE("ExternalCameraDeviceSession deleted before close!"); 184 close(); 185 } 186 } 187 188 189 void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) { 190 if (handle->numFds != 1 || handle->numInts != 0) { 191 ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints", 192 __FUNCTION__, handle->numFds, handle->numInts); 193 return; 194 } 195 int fd = handle->data[0]; 196 197 bool intfLocked = tryLock(mInterfaceLock); 198 if (!intfLocked) { 199 dprintf(fd, "!! ExternalCameraDeviceSession interface may be deadlocked !!\n"); 200 } 201 202 if (isClosed()) { 203 dprintf(fd, "External camera %s is closed\n", mCameraId.c_str()); 204 return; 205 } 206 207 bool streaming = false; 208 size_t v4L2BufferCount = 0; 209 SupportedV4L2Format streamingFmt; 210 { 211 bool sessionLocked = tryLock(mLock); 212 if (!sessionLocked) { 213 dprintf(fd, "!! ExternalCameraDeviceSession mLock may be deadlocked !!\n"); 214 } 215 streaming = mV4l2Streaming; 216 streamingFmt = mV4l2StreamingFmt; 217 v4L2BufferCount = mV4L2BufferCount; 218 219 if (sessionLocked) { 220 mLock.unlock(); 221 } 222 } 223 224 std::unordered_set<uint32_t> inflightFrames; 225 { 226 bool iffLocked = tryLock(mInflightFramesLock); 227 if (!iffLocked) { 228 dprintf(fd, 229 "!! ExternalCameraDeviceSession mInflightFramesLock may be deadlocked !!\n"); 230 } 231 inflightFrames = mInflightFrames; 232 if (iffLocked) { 233 mInflightFramesLock.unlock(); 234 } 235 } 236 237 dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n", 238 mCameraId.c_str(), mV4l2Fd.get(), 239 (mCroppingType == VERTICAL) ? "vertical" : "horizontal", 240 streaming ? "streaming" : "not streaming"); 241 if (streaming) { 242 // TODO: dump fps later 243 dprintf(fd, "Current V4L2 format %c%c%c%c %dx%d @ %ffps\n", 244 streamingFmt.fourcc & 0xFF, 245 (streamingFmt.fourcc >> 8) & 0xFF, 246 (streamingFmt.fourcc >> 16) & 0xFF, 247 (streamingFmt.fourcc >> 24) & 0xFF, 248 streamingFmt.width, streamingFmt.height, 249 mV4l2StreamingFps); 250 251 size_t numDequeuedV4l2Buffers = 0; 252 { 253 std::lock_guard<std::mutex> lk(mV4l2BufferLock); 254 numDequeuedV4l2Buffers = mNumDequeuedV4l2Buffers; 255 } 256 dprintf(fd, "V4L2 buffer queue size %zu, dequeued %zu\n", 257 v4L2BufferCount, numDequeuedV4l2Buffers); 258 } 259 260 dprintf(fd, "In-flight frames (not sorted):"); 261 for (const auto& frameNumber : inflightFrames) { 262 dprintf(fd, "%d, ", frameNumber); 263 } 264 dprintf(fd, "\n"); 265 mOutputThread->dump(fd); 266 dprintf(fd, "\n"); 267 268 if (intfLocked) { 269 mInterfaceLock.unlock(); 270 } 271 272 return; 273 } 274 275 Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings( 276 V3_2::RequestTemplate type, 277 V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) { 278 V3_2::CameraMetadata outMetadata; 279 Status status = constructDefaultRequestSettingsRaw( 280 static_cast<RequestTemplate>(type), &outMetadata); 281 _hidl_cb(status, outMetadata); 282 return Void(); 283 } 284 285 Status ExternalCameraDeviceSession::constructDefaultRequestSettingsRaw(RequestTemplate type, 286 V3_2::CameraMetadata *outMetadata) { 287 CameraMetadata emptyMd; 288 Status status = initStatus(); 289 if (status != Status::OK) { 290 return status; 291 } 292 293 switch (type) { 294 case RequestTemplate::PREVIEW: 295 case RequestTemplate::STILL_CAPTURE: 296 case RequestTemplate::VIDEO_RECORD: 297 case RequestTemplate::VIDEO_SNAPSHOT: { 298 *outMetadata = mDefaultRequests[type]; 299 break; 300 } 301 case RequestTemplate::MANUAL: 302 case RequestTemplate::ZERO_SHUTTER_LAG: 303 // Don't support MANUAL, ZSL templates 304 status = Status::ILLEGAL_ARGUMENT; 305 break; 306 default: 307 ALOGE("%s: unknown request template type %d", __FUNCTION__, static_cast<int>(type)); 308 status = Status::ILLEGAL_ARGUMENT; 309 break; 310 } 311 return status; 312 } 313 314 Return<void> ExternalCameraDeviceSession::configureStreams( 315 const V3_2::StreamConfiguration& streams, 316 ICameraDeviceSession::configureStreams_cb _hidl_cb) { 317 V3_2::HalStreamConfiguration outStreams; 318 V3_3::HalStreamConfiguration outStreams_v33; 319 Mutex::Autolock _il(mInterfaceLock); 320 321 Status status = configureStreams(streams, &outStreams_v33); 322 size_t size = outStreams_v33.streams.size(); 323 outStreams.streams.resize(size); 324 for (size_t i = 0; i < size; i++) { 325 outStreams.streams[i] = outStreams_v33.streams[i].v3_2; 326 } 327 _hidl_cb(status, outStreams); 328 return Void(); 329 } 330 331 Return<void> ExternalCameraDeviceSession::configureStreams_3_3( 332 const V3_2::StreamConfiguration& streams, 333 ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb) { 334 V3_3::HalStreamConfiguration outStreams; 335 Mutex::Autolock _il(mInterfaceLock); 336 337 Status status = configureStreams(streams, &outStreams); 338 _hidl_cb(status, outStreams); 339 return Void(); 340 } 341 342 Return<void> ExternalCameraDeviceSession::configureStreams_3_4( 343 const V3_4::StreamConfiguration& requestedConfiguration, 344 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) { 345 V3_2::StreamConfiguration config_v32; 346 V3_3::HalStreamConfiguration outStreams_v33; 347 Mutex::Autolock _il(mInterfaceLock); 348 349 config_v32.operationMode = requestedConfiguration.operationMode; 350 config_v32.streams.resize(requestedConfiguration.streams.size()); 351 for (size_t i = 0; i < config_v32.streams.size(); i++) { 352 config_v32.streams[i] = requestedConfiguration.streams[i].v3_2; 353 } 354 355 Status status = configureStreams(config_v32, &outStreams_v33); 356 357 V3_4::HalStreamConfiguration outStreams; 358 outStreams.streams.resize(outStreams_v33.streams.size()); 359 for (size_t i = 0; i < outStreams.streams.size(); i++) { 360 outStreams.streams[i].v3_3 = outStreams_v33.streams[i]; 361 } 362 _hidl_cb(status, outStreams); 363 return Void(); 364 } 365 366 Return<void> ExternalCameraDeviceSession::getCaptureRequestMetadataQueue( 367 ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) { 368 Mutex::Autolock _il(mInterfaceLock); 369 _hidl_cb(*mRequestMetadataQueue->getDesc()); 370 return Void(); 371 } 372 373 Return<void> ExternalCameraDeviceSession::getCaptureResultMetadataQueue( 374 ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) { 375 Mutex::Autolock _il(mInterfaceLock); 376 _hidl_cb(*mResultMetadataQueue->getDesc()); 377 return Void(); 378 } 379 380 Return<void> ExternalCameraDeviceSession::processCaptureRequest( 381 const hidl_vec<CaptureRequest>& requests, 382 const hidl_vec<BufferCache>& cachesToRemove, 383 ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) { 384 Mutex::Autolock _il(mInterfaceLock); 385 updateBufferCaches(cachesToRemove); 386 387 uint32_t numRequestProcessed = 0; 388 Status s = Status::OK; 389 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) { 390 s = processOneCaptureRequest(requests[i]); 391 if (s != Status::OK) { 392 break; 393 } 394 } 395 396 _hidl_cb(s, numRequestProcessed); 397 return Void(); 398 } 399 400 Return<void> ExternalCameraDeviceSession::processCaptureRequest_3_4( 401 const hidl_vec<V3_4::CaptureRequest>& requests, 402 const hidl_vec<V3_2::BufferCache>& cachesToRemove, 403 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) { 404 Mutex::Autolock _il(mInterfaceLock); 405 updateBufferCaches(cachesToRemove); 406 407 uint32_t numRequestProcessed = 0; 408 Status s = Status::OK; 409 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) { 410 s = processOneCaptureRequest(requests[i].v3_2); 411 if (s != Status::OK) { 412 break; 413 } 414 } 415 416 _hidl_cb(s, numRequestProcessed); 417 return Void(); 418 } 419 420 Return<Status> ExternalCameraDeviceSession::flush() { 421 ATRACE_CALL(); 422 Mutex::Autolock _il(mInterfaceLock); 423 Status status = initStatus(); 424 if (status != Status::OK) { 425 return status; 426 } 427 mOutputThread->flush(); 428 return Status::OK; 429 } 430 431 Return<void> ExternalCameraDeviceSession::close() { 432 Mutex::Autolock _il(mInterfaceLock); 433 bool closed = isClosed(); 434 if (!closed) { 435 mOutputThread->flush(); 436 mOutputThread->requestExit(); 437 mOutputThread->join(); 438 439 Mutex::Autolock _l(mLock); 440 // free all buffers 441 for(auto pair : mStreamMap) { 442 cleanupBuffersLocked(/*Stream ID*/pair.first); 443 } 444 v4l2StreamOffLocked(); 445 ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get()); 446 mV4l2Fd.reset(); 447 mClosed = true; 448 } 449 return Void(); 450 } 451 452 Status ExternalCameraDeviceSession::importRequest( 453 const CaptureRequest& request, 454 hidl_vec<buffer_handle_t*>& allBufPtrs, 455 hidl_vec<int>& allFences) { 456 size_t numOutputBufs = request.outputBuffers.size(); 457 size_t numBufs = numOutputBufs; 458 // Validate all I/O buffers 459 hidl_vec<buffer_handle_t> allBufs; 460 hidl_vec<uint64_t> allBufIds; 461 allBufs.resize(numBufs); 462 allBufIds.resize(numBufs); 463 allBufPtrs.resize(numBufs); 464 allFences.resize(numBufs); 465 std::vector<int32_t> streamIds(numBufs); 466 467 for (size_t i = 0; i < numOutputBufs; i++) { 468 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle(); 469 allBufIds[i] = request.outputBuffers[i].bufferId; 470 allBufPtrs[i] = &allBufs[i]; 471 streamIds[i] = request.outputBuffers[i].streamId; 472 } 473 474 for (size_t i = 0; i < numBufs; i++) { 475 buffer_handle_t buf = allBufs[i]; 476 uint64_t bufId = allBufIds[i]; 477 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]]; 478 if (cbs.count(bufId) == 0) { 479 if (buf == nullptr) { 480 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); 481 return Status::ILLEGAL_ARGUMENT; 482 } 483 // Register a newly seen buffer 484 buffer_handle_t importedBuf = buf; 485 sHandleImporter.importBuffer(importedBuf); 486 if (importedBuf == nullptr) { 487 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i); 488 return Status::INTERNAL_ERROR; 489 } else { 490 cbs[bufId] = importedBuf; 491 } 492 } 493 allBufPtrs[i] = &cbs[bufId]; 494 } 495 496 // All buffers are imported. Now validate output buffer acquire fences 497 for (size_t i = 0; i < numOutputBufs; i++) { 498 if (!sHandleImporter.importFence( 499 request.outputBuffers[i].acquireFence, allFences[i])) { 500 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i); 501 cleanupInflightFences(allFences, i); 502 return Status::INTERNAL_ERROR; 503 } 504 } 505 return Status::OK; 506 } 507 508 void ExternalCameraDeviceSession::cleanupInflightFences( 509 hidl_vec<int>& allFences, size_t numFences) { 510 for (size_t j = 0; j < numFences; j++) { 511 sHandleImporter.closeFence(allFences[j]); 512 } 513 } 514 515 int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) { 516 ATRACE_CALL(); 517 std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec); 518 mLock.unlock(); 519 auto st = mV4L2BufferReturned.wait_for(lk, timeout); 520 // Here we introduce a order where mV4l2BufferLock is acquired before mLock, while 521 // the normal lock acquisition order is reversed. This is fine because in most of 522 // cases we are protected by mInterfaceLock. The only thread that can cause deadlock 523 // is the OutputThread, where we do need to make sure we don't acquire mLock then 524 // mV4l2BufferLock 525 mLock.lock(); 526 if (st == std::cv_status::timeout) { 527 ALOGE("%s: wait for V4L2 buffer return timeout!", __FUNCTION__); 528 return -1; 529 } 530 return 0; 531 } 532 533 Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) { 534 ATRACE_CALL(); 535 Status status = initStatus(); 536 if (status != Status::OK) { 537 return status; 538 } 539 540 if (request.inputBuffer.streamId != -1) { 541 ALOGE("%s: external camera does not support reprocessing!", __FUNCTION__); 542 return Status::ILLEGAL_ARGUMENT; 543 } 544 545 Mutex::Autolock _l(mLock); 546 if (!mV4l2Streaming) { 547 ALOGE("%s: cannot process request in streamOff state!", __FUNCTION__); 548 return Status::INTERNAL_ERROR; 549 } 550 551 const camera_metadata_t *rawSettings = nullptr; 552 bool converted = true; 553 CameraMetadata settingsFmq; // settings from FMQ 554 if (request.fmqSettingsSize > 0) { 555 // non-blocking read; client must write metadata before calling 556 // processOneCaptureRequest 557 settingsFmq.resize(request.fmqSettingsSize); 558 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize); 559 if (read) { 560 converted = V3_2::implementation::convertFromHidl(settingsFmq, &rawSettings); 561 } else { 562 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__); 563 converted = false; 564 } 565 } else { 566 converted = V3_2::implementation::convertFromHidl(request.settings, &rawSettings); 567 } 568 569 if (converted && rawSettings != nullptr) { 570 mLatestReqSetting = rawSettings; 571 } 572 573 if (!converted) { 574 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__); 575 return Status::ILLEGAL_ARGUMENT; 576 } 577 578 if (mFirstRequest && rawSettings == nullptr) { 579 ALOGE("%s: capture request settings must not be null for first request!", 580 __FUNCTION__); 581 return Status::ILLEGAL_ARGUMENT; 582 } 583 584 hidl_vec<buffer_handle_t*> allBufPtrs; 585 hidl_vec<int> allFences; 586 size_t numOutputBufs = request.outputBuffers.size(); 587 588 if (numOutputBufs == 0) { 589 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__); 590 return Status::ILLEGAL_ARGUMENT; 591 } 592 593 camera_metadata_entry fpsRange = mLatestReqSetting.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE); 594 if (fpsRange.count == 2) { 595 double requestFpsMax = fpsRange.data.i32[1]; 596 double closestFps = 0.0; 597 double fpsError = 1000.0; 598 bool fpsSupported = false; 599 for (const auto& fr : mV4l2StreamingFmt.frameRates) { 600 double f = fr.getDouble(); 601 if (std::fabs(requestFpsMax - f) < 1.0) { 602 fpsSupported = true; 603 break; 604 } 605 if (std::fabs(requestFpsMax - f) < fpsError) { 606 fpsError = std::fabs(requestFpsMax - f); 607 closestFps = f; 608 } 609 } 610 if (!fpsSupported) { 611 /* This can happen in a few scenarios: 612 * 1. The application is sending a FPS range not supported by the configured outputs. 613 * 2. The application is sending a valid FPS range for all cofigured outputs, but 614 * the selected V4L2 size can only run at slower speed. This should be very rare 615 * though: for this to happen a sensor needs to support at least 3 different aspect 616 * ratio outputs, and when (at least) two outputs are both not the main aspect ratio 617 * of the webcam, a third size that's larger might be picked and runs into this 618 * issue. 619 */ 620 ALOGW("%s: cannot reach fps %d! Will do %f instead", 621 __FUNCTION__, fpsRange.data.i32[1], closestFps); 622 requestFpsMax = closestFps; 623 } 624 625 if (requestFpsMax != mV4l2StreamingFps) { 626 { 627 std::unique_lock<std::mutex> lk(mV4l2BufferLock); 628 while (mNumDequeuedV4l2Buffers != 0) { 629 // Wait until pipeline is idle before reconfigure stream 630 int waitRet = waitForV4L2BufferReturnLocked(lk); 631 if (waitRet != 0) { 632 ALOGE("%s: wait for pipeline idle failed!", __FUNCTION__); 633 return Status::INTERNAL_ERROR; 634 } 635 } 636 } 637 configureV4l2StreamLocked(mV4l2StreamingFmt, requestFpsMax); 638 } 639 } 640 641 status = importRequest(request, allBufPtrs, allFences); 642 if (status != Status::OK) { 643 return status; 644 } 645 646 nsecs_t shutterTs = 0; 647 sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked(&shutterTs); 648 if ( frameIn == nullptr) { 649 ALOGE("%s: V4L2 deque frame failed!", __FUNCTION__); 650 return Status::INTERNAL_ERROR; 651 } 652 653 std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>(); 654 halReq->frameNumber = request.frameNumber; 655 halReq->setting = mLatestReqSetting; 656 halReq->frameIn = frameIn; 657 halReq->shutterTs = shutterTs; 658 halReq->buffers.resize(numOutputBufs); 659 for (size_t i = 0; i < numOutputBufs; i++) { 660 HalStreamBuffer& halBuf = halReq->buffers[i]; 661 int streamId = halBuf.streamId = request.outputBuffers[i].streamId; 662 halBuf.bufferId = request.outputBuffers[i].bufferId; 663 const Stream& stream = mStreamMap[streamId]; 664 halBuf.width = stream.width; 665 halBuf.height = stream.height; 666 halBuf.format = stream.format; 667 halBuf.usage = stream.usage; 668 halBuf.bufPtr = allBufPtrs[i]; 669 halBuf.acquireFence = allFences[i]; 670 halBuf.fenceTimeout = false; 671 } 672 { 673 std::lock_guard<std::mutex> lk(mInflightFramesLock); 674 mInflightFrames.insert(halReq->frameNumber); 675 } 676 // Send request to OutputThread for the rest of processing 677 mOutputThread->submitRequest(halReq); 678 mFirstRequest = false; 679 return Status::OK; 680 } 681 682 void ExternalCameraDeviceSession::notifyShutter(uint32_t frameNumber, nsecs_t shutterTs) { 683 NotifyMsg msg; 684 msg.type = MsgType::SHUTTER; 685 msg.msg.shutter.frameNumber = frameNumber; 686 msg.msg.shutter.timestamp = shutterTs; 687 mCallback->notify({msg}); 688 } 689 690 void ExternalCameraDeviceSession::notifyError( 691 uint32_t frameNumber, int32_t streamId, ErrorCode ec) { 692 NotifyMsg msg; 693 msg.type = MsgType::ERROR; 694 msg.msg.error.frameNumber = frameNumber; 695 msg.msg.error.errorStreamId = streamId; 696 msg.msg.error.errorCode = ec; 697 mCallback->notify({msg}); 698 } 699 700 //TODO: refactor with processCaptureResult 701 Status ExternalCameraDeviceSession::processCaptureRequestError( 702 const std::shared_ptr<HalRequest>& req) { 703 ATRACE_CALL(); 704 // Return V4L2 buffer to V4L2 buffer queue 705 enqueueV4l2Frame(req->frameIn); 706 707 // NotifyShutter 708 notifyShutter(req->frameNumber, req->shutterTs); 709 710 notifyError(/*frameNum*/req->frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST); 711 712 // Fill output buffers 713 hidl_vec<CaptureResult> results; 714 results.resize(1); 715 CaptureResult& result = results[0]; 716 result.frameNumber = req->frameNumber; 717 result.partialResult = 1; 718 result.inputBuffer.streamId = -1; 719 result.outputBuffers.resize(req->buffers.size()); 720 for (size_t i = 0; i < req->buffers.size(); i++) { 721 result.outputBuffers[i].streamId = req->buffers[i].streamId; 722 result.outputBuffers[i].bufferId = req->buffers[i].bufferId; 723 result.outputBuffers[i].status = BufferStatus::ERROR; 724 if (req->buffers[i].acquireFence >= 0) { 725 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); 726 handle->data[0] = req->buffers[i].acquireFence; 727 result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); 728 } 729 } 730 731 // update inflight records 732 { 733 std::lock_guard<std::mutex> lk(mInflightFramesLock); 734 mInflightFrames.erase(req->frameNumber); 735 } 736 737 // Callback into framework 738 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true); 739 freeReleaseFences(results); 740 return Status::OK; 741 } 742 743 Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequest>& req) { 744 ATRACE_CALL(); 745 // Return V4L2 buffer to V4L2 buffer queue 746 enqueueV4l2Frame(req->frameIn); 747 748 // NotifyShutter 749 notifyShutter(req->frameNumber, req->shutterTs); 750 751 // Fill output buffers 752 hidl_vec<CaptureResult> results; 753 results.resize(1); 754 CaptureResult& result = results[0]; 755 result.frameNumber = req->frameNumber; 756 result.partialResult = 1; 757 result.inputBuffer.streamId = -1; 758 result.outputBuffers.resize(req->buffers.size()); 759 for (size_t i = 0; i < req->buffers.size(); i++) { 760 result.outputBuffers[i].streamId = req->buffers[i].streamId; 761 result.outputBuffers[i].bufferId = req->buffers[i].bufferId; 762 if (req->buffers[i].fenceTimeout) { 763 result.outputBuffers[i].status = BufferStatus::ERROR; 764 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); 765 handle->data[0] = req->buffers[i].acquireFence; 766 result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); 767 notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER); 768 } else { 769 result.outputBuffers[i].status = BufferStatus::OK; 770 // TODO: refactor 771 if (req->buffers[i].acquireFence > 0) { 772 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); 773 handle->data[0] = req->buffers[i].acquireFence; 774 result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); 775 } 776 } 777 } 778 779 // Fill capture result metadata 780 fillCaptureResult(req->setting, req->shutterTs); 781 const camera_metadata_t *rawResult = req->setting.getAndLock(); 782 V3_2::implementation::convertToHidl(rawResult, &result.result); 783 req->setting.unlock(rawResult); 784 785 // update inflight records 786 { 787 std::lock_guard<std::mutex> lk(mInflightFramesLock); 788 mInflightFrames.erase(req->frameNumber); 789 } 790 791 // Callback into framework 792 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true); 793 freeReleaseFences(results); 794 return Status::OK; 795 } 796 797 void ExternalCameraDeviceSession::invokeProcessCaptureResultCallback( 798 hidl_vec<CaptureResult> &results, bool tryWriteFmq) { 799 if (mProcessCaptureResultLock.tryLock() != OK) { 800 const nsecs_t NS_TO_SECOND = 1000000000; 801 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__); 802 if (mProcessCaptureResultLock.timedLock(/* 1s */NS_TO_SECOND) != OK) { 803 ALOGE("%s: cannot acquire lock in 1s, cannot proceed", 804 __FUNCTION__); 805 return; 806 } 807 } 808 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) { 809 for (CaptureResult &result : results) { 810 if (result.result.size() > 0) { 811 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) { 812 result.fmqResultSize = result.result.size(); 813 result.result.resize(0); 814 } else { 815 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__); 816 result.fmqResultSize = 0; 817 } 818 } else { 819 result.fmqResultSize = 0; 820 } 821 } 822 } 823 auto status = mCallback->processCaptureResult(results); 824 if (!status.isOk()) { 825 ALOGE("%s: processCaptureResult ERROR : %s", __FUNCTION__, 826 status.description().c_str()); 827 } 828 829 mProcessCaptureResultLock.unlock(); 830 } 831 832 void ExternalCameraDeviceSession::freeReleaseFences(hidl_vec<CaptureResult>& results) { 833 for (auto& result : results) { 834 if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) { 835 native_handle_t* handle = const_cast<native_handle_t*>( 836 result.inputBuffer.releaseFence.getNativeHandle()); 837 native_handle_close(handle); 838 native_handle_delete(handle); 839 } 840 for (auto& buf : result.outputBuffers) { 841 if (buf.releaseFence.getNativeHandle() != nullptr) { 842 native_handle_t* handle = const_cast<native_handle_t*>( 843 buf.releaseFence.getNativeHandle()); 844 native_handle_close(handle); 845 native_handle_delete(handle); 846 } 847 } 848 } 849 return; 850 } 851 852 ExternalCameraDeviceSession::OutputThread::OutputThread( 853 wp<ExternalCameraDeviceSession> parent, 854 CroppingType ct) : mParent(parent), mCroppingType(ct) {} 855 856 ExternalCameraDeviceSession::OutputThread::~OutputThread() {} 857 858 void ExternalCameraDeviceSession::OutputThread::setExifMakeModel( 859 const std::string& make, const std::string& model) { 860 mExifMake = make; 861 mExifModel = model; 862 } 863 864 uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout( 865 const YCbCrLayout& layout) { 866 intptr_t cb = reinterpret_cast<intptr_t>(layout.cb); 867 intptr_t cr = reinterpret_cast<intptr_t>(layout.cr); 868 if (std::abs(cb - cr) == 1 && layout.chromaStep == 2) { 869 // Interleaved format 870 if (layout.cb > layout.cr) { 871 return V4L2_PIX_FMT_NV21; 872 } else { 873 return V4L2_PIX_FMT_NV12; 874 } 875 } else if (layout.chromaStep == 1) { 876 // Planar format 877 if (layout.cb > layout.cr) { 878 return V4L2_PIX_FMT_YVU420; // YV12 879 } else { 880 return V4L2_PIX_FMT_YUV420; // YU12 881 } 882 } else { 883 return FLEX_YUV_GENERIC; 884 } 885 } 886 887 int ExternalCameraDeviceSession::OutputThread::getCropRect( 888 CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out) { 889 if (out == nullptr) { 890 ALOGE("%s: out is null", __FUNCTION__); 891 return -1; 892 } 893 894 uint32_t inW = inSize.width; 895 uint32_t inH = inSize.height; 896 uint32_t outW = outSize.width; 897 uint32_t outH = outSize.height; 898 899 // Handle special case where aspect ratio is close to input but scaled 900 // dimension is slightly larger than input 901 float arIn = ASPECT_RATIO(inSize); 902 float arOut = ASPECT_RATIO(outSize); 903 if (isAspectRatioClose(arIn, arOut)) { 904 out->left = 0; 905 out->top = 0; 906 out->width = inW; 907 out->height = inH; 908 return 0; 909 } 910 911 if (ct == VERTICAL) { 912 uint64_t scaledOutH = static_cast<uint64_t>(outH) * inW / outW; 913 if (scaledOutH > inH) { 914 ALOGE("%s: Output size %dx%d cannot be vertically cropped from input size %dx%d", 915 __FUNCTION__, outW, outH, inW, inH); 916 return -1; 917 } 918 scaledOutH = scaledOutH & ~0x1; // make it multiple of 2 919 920 out->left = 0; 921 out->top = ((inH - scaledOutH) / 2) & ~0x1; 922 out->width = inW; 923 out->height = static_cast<int32_t>(scaledOutH); 924 ALOGV("%s: crop %dx%d to %dx%d: top %d, scaledH %d", 925 __FUNCTION__, inW, inH, outW, outH, out->top, static_cast<int32_t>(scaledOutH)); 926 } else { 927 uint64_t scaledOutW = static_cast<uint64_t>(outW) * inH / outH; 928 if (scaledOutW > inW) { 929 ALOGE("%s: Output size %dx%d cannot be horizontally cropped from input size %dx%d", 930 __FUNCTION__, outW, outH, inW, inH); 931 return -1; 932 } 933 scaledOutW = scaledOutW & ~0x1; // make it multiple of 2 934 935 out->left = ((inW - scaledOutW) / 2) & ~0x1; 936 out->top = 0; 937 out->width = static_cast<int32_t>(scaledOutW); 938 out->height = inH; 939 ALOGV("%s: crop %dx%d to %dx%d: top %d, scaledW %d", 940 __FUNCTION__, inW, inH, outW, outH, out->top, static_cast<int32_t>(scaledOutW)); 941 } 942 943 return 0; 944 } 945 946 int ExternalCameraDeviceSession::OutputThread::cropAndScaleLocked( 947 sp<AllocatedFrame>& in, const Size& outSz, YCbCrLayout* out) { 948 Size inSz = {in->mWidth, in->mHeight}; 949 950 int ret; 951 if (inSz == outSz) { 952 ret = in->getLayout(out); 953 if (ret != 0) { 954 ALOGE("%s: failed to get input image layout", __FUNCTION__); 955 return ret; 956 } 957 return ret; 958 } 959 960 // Cropping to output aspect ratio 961 IMapper::Rect inputCrop; 962 ret = getCropRect(mCroppingType, inSz, outSz, &inputCrop); 963 if (ret != 0) { 964 ALOGE("%s: failed to compute crop rect for output size %dx%d", 965 __FUNCTION__, outSz.width, outSz.height); 966 return ret; 967 } 968 969 YCbCrLayout croppedLayout; 970 ret = in->getCroppedLayout(inputCrop, &croppedLayout); 971 if (ret != 0) { 972 ALOGE("%s: failed to crop input image %dx%d to output size %dx%d", 973 __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height); 974 return ret; 975 } 976 977 if ((mCroppingType == VERTICAL && inSz.width == outSz.width) || 978 (mCroppingType == HORIZONTAL && inSz.height == outSz.height)) { 979 // No scale is needed 980 *out = croppedLayout; 981 return 0; 982 } 983 984 auto it = mScaledYu12Frames.find(outSz); 985 sp<AllocatedFrame> scaledYu12Buf; 986 if (it != mScaledYu12Frames.end()) { 987 scaledYu12Buf = it->second; 988 } else { 989 it = mIntermediateBuffers.find(outSz); 990 if (it == mIntermediateBuffers.end()) { 991 ALOGE("%s: failed to find intermediate buffer size %dx%d", 992 __FUNCTION__, outSz.width, outSz.height); 993 return -1; 994 } 995 scaledYu12Buf = it->second; 996 } 997 // Scale 998 YCbCrLayout outLayout; 999 ret = scaledYu12Buf->getLayout(&outLayout); 1000 if (ret != 0) { 1001 ALOGE("%s: failed to get output buffer layout", __FUNCTION__); 1002 return ret; 1003 } 1004 1005 ret = libyuv::I420Scale( 1006 static_cast<uint8_t*>(croppedLayout.y), 1007 croppedLayout.yStride, 1008 static_cast<uint8_t*>(croppedLayout.cb), 1009 croppedLayout.cStride, 1010 static_cast<uint8_t*>(croppedLayout.cr), 1011 croppedLayout.cStride, 1012 inputCrop.width, 1013 inputCrop.height, 1014 static_cast<uint8_t*>(outLayout.y), 1015 outLayout.yStride, 1016 static_cast<uint8_t*>(outLayout.cb), 1017 outLayout.cStride, 1018 static_cast<uint8_t*>(outLayout.cr), 1019 outLayout.cStride, 1020 outSz.width, 1021 outSz.height, 1022 // TODO: b/72261744 see if we can use better filter without losing too much perf 1023 libyuv::FilterMode::kFilterNone); 1024 1025 if (ret != 0) { 1026 ALOGE("%s: failed to scale buffer from %dx%d to %dx%d. Ret %d", 1027 __FUNCTION__, inputCrop.width, inputCrop.height, 1028 outSz.width, outSz.height, ret); 1029 return ret; 1030 } 1031 1032 *out = outLayout; 1033 mScaledYu12Frames.insert({outSz, scaledYu12Buf}); 1034 return 0; 1035 } 1036 1037 1038 int ExternalCameraDeviceSession::OutputThread::cropAndScaleThumbLocked( 1039 sp<AllocatedFrame>& in, const Size &outSz, YCbCrLayout* out) { 1040 Size inSz {in->mWidth, in->mHeight}; 1041 1042 if ((outSz.width * outSz.height) > 1043 (mYu12ThumbFrame->mWidth * mYu12ThumbFrame->mHeight)) { 1044 ALOGE("%s: Requested thumbnail size too big (%d,%d) > (%d,%d)", 1045 __FUNCTION__, outSz.width, outSz.height, 1046 mYu12ThumbFrame->mWidth, mYu12ThumbFrame->mHeight); 1047 return -1; 1048 } 1049 1050 int ret; 1051 1052 /* This will crop-and-zoom the input YUV frame to the thumbnail size 1053 * Based on the following logic: 1054 * 1) Square pixels come in, square pixels come out, therefore single 1055 * scale factor is computed to either make input bigger or smaller 1056 * depending on if we are upscaling or downscaling 1057 * 2) That single scale factor would either make height too tall or width 1058 * too wide so we need to crop the input either horizontally or vertically 1059 * but not both 1060 */ 1061 1062 /* Convert the input and output dimensions into floats for ease of math */ 1063 float fWin = static_cast<float>(inSz.width); 1064 float fHin = static_cast<float>(inSz.height); 1065 float fWout = static_cast<float>(outSz.width); 1066 float fHout = static_cast<float>(outSz.height); 1067 1068 /* Compute the one scale factor from (1) above, it will be the smaller of 1069 * the two possibilities. */ 1070 float scaleFactor = std::min( fHin / fHout, fWin / fWout ); 1071 1072 /* Since we are crop-and-zooming (as opposed to letter/pillar boxing) we can 1073 * simply multiply the output by our scaleFactor to get the cropped input 1074 * size. Note that at least one of {fWcrop, fHcrop} is going to wind up 1075 * being {fWin, fHin} respectively because fHout or fWout cancels out the 1076 * scaleFactor calculation above. 1077 * 1078 * Specifically: 1079 * if ( fHin / fHout ) < ( fWin / fWout ) we crop the sides off 1080 * input, in which case 1081 * scaleFactor = fHin / fHout 1082 * fWcrop = fHin / fHout * fWout 1083 * fHcrop = fHin 1084 * 1085 * Note that fWcrop <= fWin ( because ( fHin / fHout ) * fWout < fWin, which 1086 * is just the inequality above with both sides multiplied by fWout 1087 * 1088 * on the other hand if ( fWin / fWout ) < ( fHin / fHout) we crop the top 1089 * and the bottom off of input, and 1090 * scaleFactor = fWin / fWout 1091 * fWcrop = fWin 1092 * fHCrop = fWin / fWout * fHout 1093 */ 1094 float fWcrop = scaleFactor * fWout; 1095 float fHcrop = scaleFactor * fHout; 1096 1097 /* Convert to integer and truncate to an even number */ 1098 Size cropSz = { 2*static_cast<uint32_t>(fWcrop/2.0f), 1099 2*static_cast<uint32_t>(fHcrop/2.0f) }; 1100 1101 /* Convert to a centered rectange with even top/left */ 1102 IMapper::Rect inputCrop { 1103 2*static_cast<int32_t>((inSz.width - cropSz.width)/4), 1104 2*static_cast<int32_t>((inSz.height - cropSz.height)/4), 1105 static_cast<int32_t>(cropSz.width), 1106 static_cast<int32_t>(cropSz.height) }; 1107 1108 if ((inputCrop.top < 0) || 1109 (inputCrop.top >= static_cast<int32_t>(inSz.height)) || 1110 (inputCrop.left < 0) || 1111 (inputCrop.left >= static_cast<int32_t>(inSz.width)) || 1112 (inputCrop.width <= 0) || 1113 (inputCrop.width + inputCrop.left > static_cast<int32_t>(inSz.width)) || 1114 (inputCrop.height <= 0) || 1115 (inputCrop.height + inputCrop.top > static_cast<int32_t>(inSz.height))) 1116 { 1117 ALOGE("%s: came up with really wrong crop rectangle",__FUNCTION__); 1118 ALOGE("%s: input layout %dx%d to for output size %dx%d", 1119 __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height); 1120 ALOGE("%s: computed input crop +%d,+%d %dx%d", 1121 __FUNCTION__, inputCrop.left, inputCrop.top, 1122 inputCrop.width, inputCrop.height); 1123 return -1; 1124 } 1125 1126 YCbCrLayout inputLayout; 1127 ret = in->getCroppedLayout(inputCrop, &inputLayout); 1128 if (ret != 0) { 1129 ALOGE("%s: failed to crop input layout %dx%d to for output size %dx%d", 1130 __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height); 1131 ALOGE("%s: computed input crop +%d,+%d %dx%d", 1132 __FUNCTION__, inputCrop.left, inputCrop.top, 1133 inputCrop.width, inputCrop.height); 1134 return ret; 1135 } 1136 ALOGV("%s: crop input layout %dx%d to for output size %dx%d", 1137 __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height); 1138 ALOGV("%s: computed input crop +%d,+%d %dx%d", 1139 __FUNCTION__, inputCrop.left, inputCrop.top, 1140 inputCrop.width, inputCrop.height); 1141 1142 1143 // Scale 1144 YCbCrLayout outFullLayout; 1145 1146 ret = mYu12ThumbFrame->getLayout(&outFullLayout); 1147 if (ret != 0) { 1148 ALOGE("%s: failed to get output buffer layout", __FUNCTION__); 1149 return ret; 1150 } 1151 1152 1153 ret = libyuv::I420Scale( 1154 static_cast<uint8_t*>(inputLayout.y), 1155 inputLayout.yStride, 1156 static_cast<uint8_t*>(inputLayout.cb), 1157 inputLayout.cStride, 1158 static_cast<uint8_t*>(inputLayout.cr), 1159 inputLayout.cStride, 1160 inputCrop.width, 1161 inputCrop.height, 1162 static_cast<uint8_t*>(outFullLayout.y), 1163 outFullLayout.yStride, 1164 static_cast<uint8_t*>(outFullLayout.cb), 1165 outFullLayout.cStride, 1166 static_cast<uint8_t*>(outFullLayout.cr), 1167 outFullLayout.cStride, 1168 outSz.width, 1169 outSz.height, 1170 libyuv::FilterMode::kFilterNone); 1171 1172 if (ret != 0) { 1173 ALOGE("%s: failed to scale buffer from %dx%d to %dx%d. Ret %d", 1174 __FUNCTION__, inputCrop.width, inputCrop.height, 1175 outSz.width, outSz.height, ret); 1176 return ret; 1177 } 1178 1179 *out = outFullLayout; 1180 return 0; 1181 } 1182 1183 int ExternalCameraDeviceSession::OutputThread::formatConvertLocked( 1184 const YCbCrLayout& in, const YCbCrLayout& out, Size sz, uint32_t format) { 1185 int ret = 0; 1186 switch (format) { 1187 case V4L2_PIX_FMT_NV21: 1188 ret = libyuv::I420ToNV21( 1189 static_cast<uint8_t*>(in.y), 1190 in.yStride, 1191 static_cast<uint8_t*>(in.cb), 1192 in.cStride, 1193 static_cast<uint8_t*>(in.cr), 1194 in.cStride, 1195 static_cast<uint8_t*>(out.y), 1196 out.yStride, 1197 static_cast<uint8_t*>(out.cr), 1198 out.cStride, 1199 sz.width, 1200 sz.height); 1201 if (ret != 0) { 1202 ALOGE("%s: convert to NV21 buffer failed! ret %d", 1203 __FUNCTION__, ret); 1204 return ret; 1205 } 1206 break; 1207 case V4L2_PIX_FMT_NV12: 1208 ret = libyuv::I420ToNV12( 1209 static_cast<uint8_t*>(in.y), 1210 in.yStride, 1211 static_cast<uint8_t*>(in.cb), 1212 in.cStride, 1213 static_cast<uint8_t*>(in.cr), 1214 in.cStride, 1215 static_cast<uint8_t*>(out.y), 1216 out.yStride, 1217 static_cast<uint8_t*>(out.cb), 1218 out.cStride, 1219 sz.width, 1220 sz.height); 1221 if (ret != 0) { 1222 ALOGE("%s: convert to NV12 buffer failed! ret %d", 1223 __FUNCTION__, ret); 1224 return ret; 1225 } 1226 break; 1227 case V4L2_PIX_FMT_YVU420: // YV12 1228 case V4L2_PIX_FMT_YUV420: // YU12 1229 // TODO: maybe we can speed up here by somehow save this copy? 1230 ret = libyuv::I420Copy( 1231 static_cast<uint8_t*>(in.y), 1232 in.yStride, 1233 static_cast<uint8_t*>(in.cb), 1234 in.cStride, 1235 static_cast<uint8_t*>(in.cr), 1236 in.cStride, 1237 static_cast<uint8_t*>(out.y), 1238 out.yStride, 1239 static_cast<uint8_t*>(out.cb), 1240 out.cStride, 1241 static_cast<uint8_t*>(out.cr), 1242 out.cStride, 1243 sz.width, 1244 sz.height); 1245 if (ret != 0) { 1246 ALOGE("%s: copy to YV12 or YU12 buffer failed! ret %d", 1247 __FUNCTION__, ret); 1248 return ret; 1249 } 1250 break; 1251 case FLEX_YUV_GENERIC: 1252 // TODO: b/72261744 write to arbitrary flexible YUV layout. Slow. 1253 ALOGE("%s: unsupported flexible yuv layout" 1254 " y %p cb %p cr %p y_str %d c_str %d c_step %d", 1255 __FUNCTION__, out.y, out.cb, out.cr, 1256 out.yStride, out.cStride, out.chromaStep); 1257 return -1; 1258 default: 1259 ALOGE("%s: unknown YUV format 0x%x!", __FUNCTION__, format); 1260 return -1; 1261 } 1262 return 0; 1263 } 1264 1265 int ExternalCameraDeviceSession::OutputThread::encodeJpegYU12( 1266 const Size & inSz, const YCbCrLayout& inLayout, 1267 int jpegQuality, const void *app1Buffer, size_t app1Size, 1268 void *out, const size_t maxOutSize, size_t &actualCodeSize) 1269 { 1270 /* libjpeg is a C library so we use C-style "inheritance" by 1271 * putting libjpeg's jpeg_destination_mgr first in our custom 1272 * struct. This allows us to cast jpeg_destination_mgr* to 1273 * CustomJpegDestMgr* when we get it passed to us in a callback */ 1274 struct CustomJpegDestMgr { 1275 struct jpeg_destination_mgr mgr; 1276 JOCTET *mBuffer; 1277 size_t mBufferSize; 1278 size_t mEncodedSize; 1279 bool mSuccess; 1280 } dmgr; 1281 1282 jpeg_compress_struct cinfo = {}; 1283 jpeg_error_mgr jerr; 1284 1285 /* Initialize error handling with standard callbacks, but 1286 * then override output_message (to print to ALOG) and 1287 * error_exit to set a flag and print a message instead 1288 * of killing the whole process */ 1289 cinfo.err = jpeg_std_error(&jerr); 1290 1291 cinfo.err->output_message = [](j_common_ptr cinfo) { 1292 char buffer[JMSG_LENGTH_MAX]; 1293 1294 /* Create the message */ 1295 (*cinfo->err->format_message)(cinfo, buffer); 1296 ALOGE("libjpeg error: %s", buffer); 1297 }; 1298 cinfo.err->error_exit = [](j_common_ptr cinfo) { 1299 (*cinfo->err->output_message)(cinfo); 1300 if(cinfo->client_data) { 1301 auto & dmgr = 1302 *reinterpret_cast<CustomJpegDestMgr*>(cinfo->client_data); 1303 dmgr.mSuccess = false; 1304 } 1305 }; 1306 /* Now that we initialized some callbacks, let's create our compressor */ 1307 jpeg_create_compress(&cinfo); 1308 1309 /* Initialize our destination manager */ 1310 dmgr.mBuffer = static_cast<JOCTET*>(out); 1311 dmgr.mBufferSize = maxOutSize; 1312 dmgr.mEncodedSize = 0; 1313 dmgr.mSuccess = true; 1314 cinfo.client_data = static_cast<void*>(&dmgr); 1315 1316 /* These lambdas become C-style function pointers and as per C++11 spec 1317 * may not capture anything */ 1318 dmgr.mgr.init_destination = [](j_compress_ptr cinfo) { 1319 auto & dmgr = reinterpret_cast<CustomJpegDestMgr&>(*cinfo->dest); 1320 dmgr.mgr.next_output_byte = dmgr.mBuffer; 1321 dmgr.mgr.free_in_buffer = dmgr.mBufferSize; 1322 ALOGV("%s:%d jpeg start: %p [%zu]", 1323 __FUNCTION__, __LINE__, dmgr.mBuffer, dmgr.mBufferSize); 1324 }; 1325 1326 dmgr.mgr.empty_output_buffer = [](j_compress_ptr cinfo __unused) { 1327 ALOGV("%s:%d Out of buffer", __FUNCTION__, __LINE__); 1328 return 0; 1329 }; 1330 1331 dmgr.mgr.term_destination = [](j_compress_ptr cinfo) { 1332 auto & dmgr = reinterpret_cast<CustomJpegDestMgr&>(*cinfo->dest); 1333 dmgr.mEncodedSize = dmgr.mBufferSize - dmgr.mgr.free_in_buffer; 1334 ALOGV("%s:%d Done with jpeg: %zu", __FUNCTION__, __LINE__, dmgr.mEncodedSize); 1335 }; 1336 cinfo.dest = reinterpret_cast<struct jpeg_destination_mgr*>(&dmgr); 1337 1338 /* We are going to be using JPEG in raw data mode, so we are passing 1339 * straight subsampled planar YCbCr and it will not touch our pixel 1340 * data or do any scaling or anything */ 1341 cinfo.image_width = inSz.width; 1342 cinfo.image_height = inSz.height; 1343 cinfo.input_components = 3; 1344 cinfo.in_color_space = JCS_YCbCr; 1345 1346 /* Initialize defaults and then override what we want */ 1347 jpeg_set_defaults(&cinfo); 1348 1349 jpeg_set_quality(&cinfo, jpegQuality, 1); 1350 jpeg_set_colorspace(&cinfo, JCS_YCbCr); 1351 cinfo.raw_data_in = 1; 1352 cinfo.dct_method = JDCT_IFAST; 1353 1354 /* Configure sampling factors. The sampling factor is JPEG subsampling 420 1355 * because the source format is YUV420. Note that libjpeg sampling factors 1356 * are... a little weird. Sampling of Y=2,U=1,V=1 means there is 1 U and 1357 * 1 V value for each 2 Y values */ 1358 cinfo.comp_info[0].h_samp_factor = 2; 1359 cinfo.comp_info[0].v_samp_factor = 2; 1360 cinfo.comp_info[1].h_samp_factor = 1; 1361 cinfo.comp_info[1].v_samp_factor = 1; 1362 cinfo.comp_info[2].h_samp_factor = 1; 1363 cinfo.comp_info[2].v_samp_factor = 1; 1364 1365 /* Let's not hardcode YUV420 in 6 places... 5 was enough */ 1366 int maxVSampFactor = std::max( { 1367 cinfo.comp_info[0].v_samp_factor, 1368 cinfo.comp_info[1].v_samp_factor, 1369 cinfo.comp_info[2].v_samp_factor 1370 }); 1371 int cVSubSampling = cinfo.comp_info[0].v_samp_factor / 1372 cinfo.comp_info[1].v_samp_factor; 1373 1374 /* Start the compressor */ 1375 jpeg_start_compress(&cinfo, TRUE); 1376 1377 /* Compute our macroblock height, so we can pad our input to be vertically 1378 * macroblock aligned. 1379 * TODO: Does it need to be horizontally MCU aligned too? */ 1380 1381 size_t mcuV = DCTSIZE*maxVSampFactor; 1382 size_t paddedHeight = mcuV * ((inSz.height + mcuV - 1) / mcuV); 1383 1384 /* libjpeg uses arrays of row pointers, which makes it really easy to pad 1385 * data vertically (unfortunately doesn't help horizontally) */ 1386 std::vector<JSAMPROW> yLines (paddedHeight); 1387 std::vector<JSAMPROW> cbLines(paddedHeight/cVSubSampling); 1388 std::vector<JSAMPROW> crLines(paddedHeight/cVSubSampling); 1389 1390 uint8_t *py = static_cast<uint8_t*>(inLayout.y); 1391 uint8_t *pcr = static_cast<uint8_t*>(inLayout.cr); 1392 uint8_t *pcb = static_cast<uint8_t*>(inLayout.cb); 1393 1394 for(uint32_t i = 0; i < paddedHeight; i++) 1395 { 1396 /* Once we are in the padding territory we still point to the last line 1397 * effectively replicating it several times ~ CLAMP_TO_EDGE */ 1398 int li = std::min(i, inSz.height - 1); 1399 yLines[i] = static_cast<JSAMPROW>(py + li * inLayout.yStride); 1400 if(i < paddedHeight / cVSubSampling) 1401 { 1402 crLines[i] = static_cast<JSAMPROW>(pcr + li * inLayout.cStride); 1403 cbLines[i] = static_cast<JSAMPROW>(pcb + li * inLayout.cStride); 1404 } 1405 } 1406 1407 /* If APP1 data was passed in, use it */ 1408 if(app1Buffer && app1Size) 1409 { 1410 jpeg_write_marker(&cinfo, JPEG_APP0 + 1, 1411 static_cast<const JOCTET*>(app1Buffer), app1Size); 1412 } 1413 1414 /* While we still have padded height left to go, keep giving it one 1415 * macroblock at a time. */ 1416 while (cinfo.next_scanline < cinfo.image_height) { 1417 const uint32_t batchSize = DCTSIZE * maxVSampFactor; 1418 const uint32_t nl = cinfo.next_scanline; 1419 JSAMPARRAY planes[3]{ &yLines[nl], 1420 &cbLines[nl/cVSubSampling], 1421 &crLines[nl/cVSubSampling] }; 1422 1423 uint32_t done = jpeg_write_raw_data(&cinfo, planes, batchSize); 1424 1425 if (done != batchSize) { 1426 ALOGE("%s: compressed %u lines, expected %u (total %u/%u)", 1427 __FUNCTION__, done, batchSize, cinfo.next_scanline, 1428 cinfo.image_height); 1429 return -1; 1430 } 1431 } 1432 1433 /* This will flush everything */ 1434 jpeg_finish_compress(&cinfo); 1435 1436 /* Grab the actual code size and set it */ 1437 actualCodeSize = dmgr.mEncodedSize; 1438 1439 return 0; 1440 } 1441 1442 /* 1443 * TODO: There needs to be a mechanism to discover allocated buffer size 1444 * in the HAL. 1445 * 1446 * This is very fragile because it is duplicated computation from: 1447 * frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp 1448 * 1449 */ 1450 1451 /* This assumes mSupportedFormats have all been declared as supporting 1452 * HAL_PIXEL_FORMAT_BLOB to the framework */ 1453 Size ExternalCameraDeviceSession::getMaxJpegResolution() const { 1454 Size ret { 0, 0 }; 1455 for(auto & fmt : mSupportedFormats) { 1456 if(fmt.width * fmt.height > ret.width * ret.height) { 1457 ret = Size { fmt.width, fmt.height }; 1458 } 1459 } 1460 return ret; 1461 } 1462 1463 Size ExternalCameraDeviceSession::getMaxThumbResolution() const { 1464 Size thumbSize { 0, 0 }; 1465 camera_metadata_ro_entry entry = 1466 mCameraCharacteristics.find(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES); 1467 for(uint32_t i = 0; i < entry.count; i += 2) { 1468 Size sz { static_cast<uint32_t>(entry.data.i32[i]), 1469 static_cast<uint32_t>(entry.data.i32[i+1]) }; 1470 if(sz.width * sz.height > thumbSize.width * thumbSize.height) { 1471 thumbSize = sz; 1472 } 1473 } 1474 1475 if (thumbSize.width * thumbSize.height == 0) { 1476 ALOGW("%s: non-zero thumbnail size not available", __FUNCTION__); 1477 } 1478 1479 return thumbSize; 1480 } 1481 1482 1483 ssize_t ExternalCameraDeviceSession::getJpegBufferSize( 1484 uint32_t width, uint32_t height) const { 1485 // Constant from camera3.h 1486 const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(CameraBlob); 1487 // Get max jpeg size (area-wise). 1488 if (mMaxJpegResolution.width == 0) { 1489 ALOGE("%s: Do not have a single supported JPEG stream", 1490 __FUNCTION__); 1491 return BAD_VALUE; 1492 } 1493 1494 // Get max jpeg buffer size 1495 ssize_t maxJpegBufferSize = 0; 1496 camera_metadata_ro_entry jpegBufMaxSize = 1497 mCameraCharacteristics.find(ANDROID_JPEG_MAX_SIZE); 1498 if (jpegBufMaxSize.count == 0) { 1499 ALOGE("%s: Can't find maximum JPEG size in static metadata!", 1500 __FUNCTION__); 1501 return BAD_VALUE; 1502 } 1503 maxJpegBufferSize = jpegBufMaxSize.data.i32[0]; 1504 1505 if (maxJpegBufferSize <= kMinJpegBufferSize) { 1506 ALOGE("%s: ANDROID_JPEG_MAX_SIZE (%zd) <= kMinJpegBufferSize (%zd)", 1507 __FUNCTION__, maxJpegBufferSize, kMinJpegBufferSize); 1508 return BAD_VALUE; 1509 } 1510 1511 // Calculate final jpeg buffer size for the given resolution. 1512 float scaleFactor = ((float) (width * height)) / 1513 (mMaxJpegResolution.width * mMaxJpegResolution.height); 1514 ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) + 1515 kMinJpegBufferSize; 1516 if (jpegBufferSize > maxJpegBufferSize) { 1517 jpegBufferSize = maxJpegBufferSize; 1518 } 1519 1520 return jpegBufferSize; 1521 } 1522 1523 int ExternalCameraDeviceSession::OutputThread::createJpegLocked( 1524 HalStreamBuffer &halBuf, 1525 const std::shared_ptr<HalRequest>& req) 1526 { 1527 ATRACE_CALL(); 1528 int ret; 1529 auto lfail = [&](auto... args) { 1530 ALOGE(args...); 1531 1532 return 1; 1533 }; 1534 auto parent = mParent.promote(); 1535 if (parent == nullptr) { 1536 ALOGE("%s: session has been disconnected!", __FUNCTION__); 1537 return 1; 1538 } 1539 1540 ALOGV("%s: HAL buffer sid: %d bid: %" PRIu64 " w: %u h: %u", 1541 __FUNCTION__, halBuf.streamId, static_cast<uint64_t>(halBuf.bufferId), 1542 halBuf.width, halBuf.height); 1543 ALOGV("%s: HAL buffer fmt: %x usage: %" PRIx64 " ptr: %p", 1544 __FUNCTION__, halBuf.format, static_cast<uint64_t>(halBuf.usage), 1545 halBuf.bufPtr); 1546 ALOGV("%s: YV12 buffer %d x %d", 1547 __FUNCTION__, 1548 mYu12Frame->mWidth, mYu12Frame->mHeight); 1549 1550 int jpegQuality, thumbQuality; 1551 Size thumbSize; 1552 bool outputThumbnail = true; 1553 1554 if (req->setting.exists(ANDROID_JPEG_QUALITY)) { 1555 camera_metadata_entry entry = 1556 req->setting.find(ANDROID_JPEG_QUALITY); 1557 jpegQuality = entry.data.u8[0]; 1558 } else { 1559 return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__); 1560 } 1561 1562 if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) { 1563 camera_metadata_entry entry = 1564 req->setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY); 1565 thumbQuality = entry.data.u8[0]; 1566 } else { 1567 return lfail( 1568 "%s: ANDROID_JPEG_THUMBNAIL_QUALITY not set", 1569 __FUNCTION__); 1570 } 1571 1572 if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) { 1573 camera_metadata_entry entry = 1574 req->setting.find(ANDROID_JPEG_THUMBNAIL_SIZE); 1575 thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]), 1576 static_cast<uint32_t>(entry.data.i32[1]) 1577 }; 1578 if (thumbSize.width == 0 && thumbSize.height == 0) { 1579 outputThumbnail = false; 1580 } 1581 } else { 1582 return lfail( 1583 "%s: ANDROID_JPEG_THUMBNAIL_SIZE not set", __FUNCTION__); 1584 } 1585 1586 /* Cropped and scaled YU12 buffer for main and thumbnail */ 1587 YCbCrLayout yu12Main; 1588 Size jpegSize { halBuf.width, halBuf.height }; 1589 1590 /* Compute temporary buffer sizes accounting for the following: 1591 * thumbnail can't exceed APP1 size of 64K 1592 * main image needs to hold APP1, headers, and at most a poorly 1593 * compressed image */ 1594 const ssize_t maxThumbCodeSize = 64 * 1024; 1595 const ssize_t maxJpegCodeSize = parent->getJpegBufferSize(jpegSize.width, 1596 jpegSize.height); 1597 1598 /* Check that getJpegBufferSize did not return an error */ 1599 if (maxJpegCodeSize < 0) { 1600 return lfail( 1601 "%s: getJpegBufferSize returned %zd",__FUNCTION__,maxJpegCodeSize); 1602 } 1603 1604 1605 /* Hold actual thumbnail and main image code sizes */ 1606 size_t thumbCodeSize = 0, jpegCodeSize = 0; 1607 /* Temporary thumbnail code buffer */ 1608 std::vector<uint8_t> thumbCode(outputThumbnail ? maxThumbCodeSize : 0); 1609 1610 YCbCrLayout yu12Thumb; 1611 if (outputThumbnail) { 1612 ret = cropAndScaleThumbLocked(mYu12Frame, thumbSize, &yu12Thumb); 1613 1614 if (ret != 0) { 1615 return lfail( 1616 "%s: crop and scale thumbnail failed!", __FUNCTION__); 1617 } 1618 } 1619 1620 /* Scale and crop main jpeg */ 1621 ret = cropAndScaleLocked(mYu12Frame, jpegSize, &yu12Main); 1622 1623 if (ret != 0) { 1624 return lfail("%s: crop and scale main failed!", __FUNCTION__); 1625 } 1626 1627 /* Encode the thumbnail image */ 1628 if (outputThumbnail) { 1629 ret = encodeJpegYU12(thumbSize, yu12Thumb, 1630 thumbQuality, 0, 0, 1631 &thumbCode[0], maxThumbCodeSize, thumbCodeSize); 1632 1633 if (ret != 0) { 1634 return lfail("%s: thumbnail encodeJpegYU12 failed with %d",__FUNCTION__, ret); 1635 } 1636 } 1637 1638 /* Combine camera characteristics with request settings to form EXIF 1639 * metadata */ 1640 common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics); 1641 meta.append(req->setting); 1642 1643 /* Generate EXIF object */ 1644 std::unique_ptr<ExifUtils> utils(ExifUtils::create()); 1645 /* Make sure it's initialized */ 1646 utils->initialize(); 1647 1648 utils->setFromMetadata(meta, jpegSize.width, jpegSize.height); 1649 utils->setMake(mExifMake); 1650 utils->setModel(mExifModel); 1651 1652 ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize); 1653 1654 if (!ret) { 1655 return lfail("%s: generating APP1 failed", __FUNCTION__); 1656 } 1657 1658 /* Get internal buffer */ 1659 size_t exifDataSize = utils->getApp1Length(); 1660 const uint8_t* exifData = utils->getApp1Buffer(); 1661 1662 /* Lock the HAL jpeg code buffer */ 1663 void *bufPtr = sHandleImporter.lock( 1664 *(halBuf.bufPtr), halBuf.usage, maxJpegCodeSize); 1665 1666 if (!bufPtr) { 1667 return lfail("%s: could not lock %zu bytes", __FUNCTION__, maxJpegCodeSize); 1668 } 1669 1670 /* Encode the main jpeg image */ 1671 ret = encodeJpegYU12(jpegSize, yu12Main, 1672 jpegQuality, exifData, exifDataSize, 1673 bufPtr, maxJpegCodeSize, jpegCodeSize); 1674 1675 /* TODO: Not sure this belongs here, maybe better to pass jpegCodeSize out 1676 * and do this when returning buffer to parent */ 1677 CameraBlob blob { CameraBlobId::JPEG, static_cast<uint32_t>(jpegCodeSize) }; 1678 void *blobDst = 1679 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(bufPtr) + 1680 maxJpegCodeSize - 1681 sizeof(CameraBlob)); 1682 memcpy(blobDst, &blob, sizeof(CameraBlob)); 1683 1684 /* Unlock the HAL jpeg code buffer */ 1685 int relFence = sHandleImporter.unlock(*(halBuf.bufPtr)); 1686 if (relFence > 0) { 1687 halBuf.acquireFence = relFence; 1688 } 1689 1690 /* Check if our JPEG actually succeeded */ 1691 if (ret != 0) { 1692 return lfail( 1693 "%s: encodeJpegYU12 failed with %d",__FUNCTION__, ret); 1694 } 1695 1696 ALOGV("%s: encoded JPEG (ret:%d) with Q:%d max size: %zu", 1697 __FUNCTION__, ret, jpegQuality, maxJpegCodeSize); 1698 1699 return 0; 1700 } 1701 1702 bool ExternalCameraDeviceSession::OutputThread::threadLoop() { 1703 std::shared_ptr<HalRequest> req; 1704 auto parent = mParent.promote(); 1705 if (parent == nullptr) { 1706 ALOGE("%s: session has been disconnected!", __FUNCTION__); 1707 return false; 1708 } 1709 1710 // TODO: maybe we need to setup a sensor thread to dq/enq v4l frames 1711 // regularly to prevent v4l buffer queue filled with stale buffers 1712 // when app doesn't program a preveiw request 1713 waitForNextRequest(&req); 1714 if (req == nullptr) { 1715 // No new request, wait again 1716 return true; 1717 } 1718 1719 auto onDeviceError = [&](auto... args) { 1720 ALOGE(args...); 1721 parent->notifyError( 1722 req->frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE); 1723 signalRequestDone(); 1724 return false; 1725 }; 1726 1727 if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) { 1728 return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__, 1729 req->frameIn->mFourcc & 0xFF, 1730 (req->frameIn->mFourcc >> 8) & 0xFF, 1731 (req->frameIn->mFourcc >> 16) & 0xFF, 1732 (req->frameIn->mFourcc >> 24) & 0xFF); 1733 } 1734 1735 std::unique_lock<std::mutex> lk(mBufferLock); 1736 // Convert input V4L2 frame to YU12 of the same size 1737 // TODO: see if we can save some computation by converting to YV12 here 1738 uint8_t* inData; 1739 size_t inDataSize; 1740 req->frameIn->map(&inData, &inDataSize); 1741 // TODO: in some special case maybe we can decode jpg directly to gralloc output? 1742 ATRACE_BEGIN("MJPGtoI420"); 1743 int res = libyuv::MJPGToI420( 1744 inData, inDataSize, 1745 static_cast<uint8_t*>(mYu12FrameLayout.y), 1746 mYu12FrameLayout.yStride, 1747 static_cast<uint8_t*>(mYu12FrameLayout.cb), 1748 mYu12FrameLayout.cStride, 1749 static_cast<uint8_t*>(mYu12FrameLayout.cr), 1750 mYu12FrameLayout.cStride, 1751 mYu12Frame->mWidth, mYu12Frame->mHeight, 1752 mYu12Frame->mWidth, mYu12Frame->mHeight); 1753 ATRACE_END(); 1754 1755 if (res != 0) { 1756 // For some webcam, the first few V4L2 frames might be malformed... 1757 ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res); 1758 lk.unlock(); 1759 Status st = parent->processCaptureRequestError(req); 1760 if (st != Status::OK) { 1761 return onDeviceError("%s: failed to process capture request error!", __FUNCTION__); 1762 } 1763 signalRequestDone(); 1764 return true; 1765 } 1766 1767 ALOGV("%s processing new request", __FUNCTION__); 1768 const int kSyncWaitTimeoutMs = 500; 1769 for (auto& halBuf : req->buffers) { 1770 if (halBuf.acquireFence != -1) { 1771 int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); 1772 if (ret) { 1773 halBuf.fenceTimeout = true; 1774 } else { 1775 ::close(halBuf.acquireFence); 1776 halBuf.acquireFence = -1; 1777 } 1778 } 1779 1780 if (halBuf.fenceTimeout) { 1781 continue; 1782 } 1783 1784 // Gralloc lockYCbCr the buffer 1785 switch (halBuf.format) { 1786 case PixelFormat::BLOB: { 1787 int ret = createJpegLocked(halBuf, req); 1788 1789 if(ret != 0) { 1790 lk.unlock(); 1791 return onDeviceError("%s: createJpegLocked failed with %d", 1792 __FUNCTION__, ret); 1793 } 1794 } break; 1795 case PixelFormat::YCBCR_420_888: 1796 case PixelFormat::YV12: { 1797 IMapper::Rect outRect {0, 0, 1798 static_cast<int32_t>(halBuf.width), 1799 static_cast<int32_t>(halBuf.height)}; 1800 YCbCrLayout outLayout = sHandleImporter.lockYCbCr( 1801 *(halBuf.bufPtr), halBuf.usage, outRect); 1802 ALOGV("%s: outLayout y %p cb %p cr %p y_str %d c_str %d c_step %d", 1803 __FUNCTION__, outLayout.y, outLayout.cb, outLayout.cr, 1804 outLayout.yStride, outLayout.cStride, outLayout.chromaStep); 1805 1806 // Convert to output buffer size/format 1807 uint32_t outputFourcc = getFourCcFromLayout(outLayout); 1808 ALOGV("%s: converting to format %c%c%c%c", __FUNCTION__, 1809 outputFourcc & 0xFF, 1810 (outputFourcc >> 8) & 0xFF, 1811 (outputFourcc >> 16) & 0xFF, 1812 (outputFourcc >> 24) & 0xFF); 1813 1814 YCbCrLayout cropAndScaled; 1815 ATRACE_BEGIN("cropAndScaleLocked"); 1816 int ret = cropAndScaleLocked( 1817 mYu12Frame, 1818 Size { halBuf.width, halBuf.height }, 1819 &cropAndScaled); 1820 ATRACE_END(); 1821 if (ret != 0) { 1822 lk.unlock(); 1823 return onDeviceError("%s: crop and scale failed!", __FUNCTION__); 1824 } 1825 1826 Size sz {halBuf.width, halBuf.height}; 1827 ATRACE_BEGIN("formatConvertLocked"); 1828 ret = formatConvertLocked(cropAndScaled, outLayout, sz, outputFourcc); 1829 ATRACE_END(); 1830 if (ret != 0) { 1831 lk.unlock(); 1832 return onDeviceError("%s: format coversion failed!", __FUNCTION__); 1833 } 1834 int relFence = sHandleImporter.unlock(*(halBuf.bufPtr)); 1835 if (relFence > 0) { 1836 halBuf.acquireFence = relFence; 1837 } 1838 } break; 1839 default: 1840 lk.unlock(); 1841 return onDeviceError("%s: unknown output format %x", __FUNCTION__, halBuf.format); 1842 } 1843 } // for each buffer 1844 mScaledYu12Frames.clear(); 1845 1846 // Don't hold the lock while calling back to parent 1847 lk.unlock(); 1848 Status st = parent->processCaptureResult(req); 1849 if (st != Status::OK) { 1850 return onDeviceError("%s: failed to process capture result!", __FUNCTION__); 1851 } 1852 signalRequestDone(); 1853 return true; 1854 } 1855 1856 Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers( 1857 const Size& v4lSize, const Size& thumbSize, 1858 const hidl_vec<Stream>& streams) { 1859 std::lock_guard<std::mutex> lk(mBufferLock); 1860 if (mScaledYu12Frames.size() != 0) { 1861 ALOGE("%s: intermediate buffer pool has %zu inflight buffers! (expect 0)", 1862 __FUNCTION__, mScaledYu12Frames.size()); 1863 return Status::INTERNAL_ERROR; 1864 } 1865 1866 // Allocating intermediate YU12 frame 1867 if (mYu12Frame == nullptr || mYu12Frame->mWidth != v4lSize.width || 1868 mYu12Frame->mHeight != v4lSize.height) { 1869 mYu12Frame.clear(); 1870 mYu12Frame = new AllocatedFrame(v4lSize.width, v4lSize.height); 1871 int ret = mYu12Frame->allocate(&mYu12FrameLayout); 1872 if (ret != 0) { 1873 ALOGE("%s: allocating YU12 frame failed!", __FUNCTION__); 1874 return Status::INTERNAL_ERROR; 1875 } 1876 } 1877 1878 // Allocating intermediate YU12 thumbnail frame 1879 if (mYu12ThumbFrame == nullptr || 1880 mYu12ThumbFrame->mWidth != thumbSize.width || 1881 mYu12ThumbFrame->mHeight != thumbSize.height) { 1882 mYu12ThumbFrame.clear(); 1883 mYu12ThumbFrame = new AllocatedFrame(thumbSize.width, thumbSize.height); 1884 int ret = mYu12ThumbFrame->allocate(&mYu12ThumbFrameLayout); 1885 if (ret != 0) { 1886 ALOGE("%s: allocating YU12 thumb frame failed!", __FUNCTION__); 1887 return Status::INTERNAL_ERROR; 1888 } 1889 } 1890 1891 // Allocating scaled buffers 1892 for (const auto& stream : streams) { 1893 Size sz = {stream.width, stream.height}; 1894 if (sz == v4lSize) { 1895 continue; // Don't need an intermediate buffer same size as v4lBuffer 1896 } 1897 if (mIntermediateBuffers.count(sz) == 0) { 1898 // Create new intermediate buffer 1899 sp<AllocatedFrame> buf = new AllocatedFrame(stream.width, stream.height); 1900 int ret = buf->allocate(); 1901 if (ret != 0) { 1902 ALOGE("%s: allocating intermediate YU12 frame %dx%d failed!", 1903 __FUNCTION__, stream.width, stream.height); 1904 return Status::INTERNAL_ERROR; 1905 } 1906 mIntermediateBuffers[sz] = buf; 1907 } 1908 } 1909 1910 // Remove unconfigured buffers 1911 auto it = mIntermediateBuffers.begin(); 1912 while (it != mIntermediateBuffers.end()) { 1913 bool configured = false; 1914 auto sz = it->first; 1915 for (const auto& stream : streams) { 1916 if (stream.width == sz.width && stream.height == sz.height) { 1917 configured = true; 1918 break; 1919 } 1920 } 1921 if (configured) { 1922 it++; 1923 } else { 1924 it = mIntermediateBuffers.erase(it); 1925 } 1926 } 1927 return Status::OK; 1928 } 1929 1930 Status ExternalCameraDeviceSession::OutputThread::submitRequest( 1931 const std::shared_ptr<HalRequest>& req) { 1932 std::unique_lock<std::mutex> lk(mRequestListLock); 1933 mRequestList.push_back(req); 1934 lk.unlock(); 1935 mRequestCond.notify_one(); 1936 return Status::OK; 1937 } 1938 1939 void ExternalCameraDeviceSession::OutputThread::flush() { 1940 ATRACE_CALL(); 1941 auto parent = mParent.promote(); 1942 if (parent == nullptr) { 1943 ALOGE("%s: session has been disconnected!", __FUNCTION__); 1944 return; 1945 } 1946 1947 std::unique_lock<std::mutex> lk(mRequestListLock); 1948 std::list<std::shared_ptr<HalRequest>> reqs = std::move(mRequestList); 1949 mRequestList.clear(); 1950 if (mProcessingRequest) { 1951 std::chrono::seconds timeout = std::chrono::seconds(kFlushWaitTimeoutSec); 1952 auto st = mRequestDoneCond.wait_for(lk, timeout); 1953 if (st == std::cv_status::timeout) { 1954 ALOGE("%s: wait for inflight request finish timeout!", __FUNCTION__); 1955 } 1956 } 1957 1958 ALOGV("%s: flusing inflight requests", __FUNCTION__); 1959 lk.unlock(); 1960 for (const auto& req : reqs) { 1961 parent->processCaptureRequestError(req); 1962 } 1963 } 1964 1965 void ExternalCameraDeviceSession::OutputThread::waitForNextRequest( 1966 std::shared_ptr<HalRequest>* out) { 1967 ATRACE_CALL(); 1968 if (out == nullptr) { 1969 ALOGE("%s: out is null", __FUNCTION__); 1970 return; 1971 } 1972 1973 std::unique_lock<std::mutex> lk(mRequestListLock); 1974 int waitTimes = 0; 1975 while (mRequestList.empty()) { 1976 if (exitPending()) { 1977 return; 1978 } 1979 std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs); 1980 auto st = mRequestCond.wait_for(lk, timeout); 1981 if (st == std::cv_status::timeout) { 1982 waitTimes++; 1983 if (waitTimes == kReqWaitTimesMax) { 1984 // no new request, return 1985 return; 1986 } 1987 } 1988 } 1989 *out = mRequestList.front(); 1990 mRequestList.pop_front(); 1991 mProcessingRequest = true; 1992 mProcessingFrameNumer = (*out)->frameNumber; 1993 } 1994 1995 void ExternalCameraDeviceSession::OutputThread::signalRequestDone() { 1996 std::unique_lock<std::mutex> lk(mRequestListLock); 1997 mProcessingRequest = false; 1998 mProcessingFrameNumer = 0; 1999 lk.unlock(); 2000 mRequestDoneCond.notify_one(); 2001 } 2002 2003 void ExternalCameraDeviceSession::OutputThread::dump(int fd) { 2004 std::lock_guard<std::mutex> lk(mRequestListLock); 2005 if (mProcessingRequest) { 2006 dprintf(fd, "OutputThread processing frame %d\n", mProcessingFrameNumer); 2007 } else { 2008 dprintf(fd, "OutputThread not processing any frames\n"); 2009 } 2010 dprintf(fd, "OutputThread request list contains frame: "); 2011 for (const auto& req : mRequestList) { 2012 dprintf(fd, "%d, ", req->frameNumber); 2013 } 2014 dprintf(fd, "\n"); 2015 } 2016 2017 void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) { 2018 for (auto& pair : mCirculatingBuffers.at(id)) { 2019 sHandleImporter.freeBuffer(pair.second); 2020 } 2021 mCirculatingBuffers[id].clear(); 2022 mCirculatingBuffers.erase(id); 2023 } 2024 2025 void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) { 2026 Mutex::Autolock _l(mLock); 2027 for (auto& cache : cachesToRemove) { 2028 auto cbsIt = mCirculatingBuffers.find(cache.streamId); 2029 if (cbsIt == mCirculatingBuffers.end()) { 2030 // The stream could have been removed 2031 continue; 2032 } 2033 CirculatingBuffers& cbs = cbsIt->second; 2034 auto it = cbs.find(cache.bufferId); 2035 if (it != cbs.end()) { 2036 sHandleImporter.freeBuffer(it->second); 2037 cbs.erase(it); 2038 } else { 2039 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached", 2040 __FUNCTION__, cache.streamId, cache.bufferId); 2041 } 2042 } 2043 } 2044 2045 bool ExternalCameraDeviceSession::isSupported(const Stream& stream) { 2046 int32_t ds = static_cast<int32_t>(stream.dataSpace); 2047 PixelFormat fmt = stream.format; 2048 uint32_t width = stream.width; 2049 uint32_t height = stream.height; 2050 // TODO: check usage flags 2051 2052 if (stream.streamType != StreamType::OUTPUT) { 2053 ALOGE("%s: does not support non-output stream type", __FUNCTION__); 2054 return false; 2055 } 2056 2057 if (stream.rotation != StreamRotation::ROTATION_0) { 2058 ALOGE("%s: does not support stream rotation", __FUNCTION__); 2059 return false; 2060 } 2061 2062 if (ds & Dataspace::DEPTH) { 2063 ALOGI("%s: does not support depth output", __FUNCTION__); 2064 return false; 2065 } 2066 2067 switch (fmt) { 2068 case PixelFormat::BLOB: 2069 if (ds != static_cast<int32_t>(Dataspace::V0_JFIF)) { 2070 ALOGI("%s: BLOB format does not support dataSpace %x", __FUNCTION__, ds); 2071 return false; 2072 } 2073 case PixelFormat::IMPLEMENTATION_DEFINED: 2074 case PixelFormat::YCBCR_420_888: 2075 case PixelFormat::YV12: 2076 // TODO: check what dataspace we can support here. 2077 // intentional no-ops. 2078 break; 2079 default: 2080 ALOGI("%s: does not support format %x", __FUNCTION__, fmt); 2081 return false; 2082 } 2083 2084 // Assume we can convert any V4L2 format to any of supported output format for now, i.e, 2085 // ignoring v4l2Fmt.fourcc for now. Might need more subtle check if we support more v4l format 2086 // in the futrue. 2087 for (const auto& v4l2Fmt : mSupportedFormats) { 2088 if (width == v4l2Fmt.width && height == v4l2Fmt.height) { 2089 return true; 2090 } 2091 } 2092 ALOGI("%s: resolution %dx%d is not supported", __FUNCTION__, width, height); 2093 return false; 2094 } 2095 2096 int ExternalCameraDeviceSession::v4l2StreamOffLocked() { 2097 if (!mV4l2Streaming) { 2098 return OK; 2099 } 2100 2101 { 2102 std::lock_guard<std::mutex> lk(mV4l2BufferLock); 2103 if (mNumDequeuedV4l2Buffers != 0) { 2104 ALOGE("%s: there are %zu inflight V4L buffers", 2105 __FUNCTION__, mNumDequeuedV4l2Buffers); 2106 return -1; 2107 } 2108 } 2109 mV4L2BufferCount = 0; 2110 2111 // VIDIOC_STREAMOFF 2112 v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2113 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMOFF, &capture_type)) < 0) { 2114 ALOGE("%s: STREAMOFF failed: %s", __FUNCTION__, strerror(errno)); 2115 return -errno; 2116 } 2117 2118 // VIDIOC_REQBUFS: clear buffers 2119 v4l2_requestbuffers req_buffers{}; 2120 req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2121 req_buffers.memory = V4L2_MEMORY_MMAP; 2122 req_buffers.count = 0; 2123 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) { 2124 ALOGE("%s: REQBUFS failed: %s", __FUNCTION__, strerror(errno)); 2125 return -errno; 2126 } 2127 2128 mV4l2Streaming = false; 2129 return OK; 2130 } 2131 2132 int ExternalCameraDeviceSession::setV4l2FpsLocked(double fps) { 2133 // VIDIOC_G_PARM/VIDIOC_S_PARM: set fps 2134 v4l2_streamparm streamparm = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; 2135 // The following line checks that the driver knows about framerate get/set. 2136 int ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_G_PARM, &streamparm)); 2137 if (ret != 0) { 2138 if (errno == -EINVAL) { 2139 ALOGW("%s: device does not support VIDIOC_G_PARM", __FUNCTION__); 2140 } 2141 return -errno; 2142 } 2143 // Now check if the device is able to accept a capture framerate set. 2144 if (!(streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) { 2145 ALOGW("%s: device does not support V4L2_CAP_TIMEPERFRAME", __FUNCTION__); 2146 return -EINVAL; 2147 } 2148 2149 // fps is float, approximate by a fraction. 2150 const int kFrameRatePrecision = 10000; 2151 streamparm.parm.capture.timeperframe.numerator = kFrameRatePrecision; 2152 streamparm.parm.capture.timeperframe.denominator = 2153 (fps * kFrameRatePrecision); 2154 2155 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_PARM, &streamparm)) < 0) { 2156 ALOGE("%s: failed to set framerate to %f: %s", __FUNCTION__, fps, strerror(errno)); 2157 return -1; 2158 } 2159 2160 double retFps = streamparm.parm.capture.timeperframe.denominator / 2161 static_cast<double>(streamparm.parm.capture.timeperframe.numerator); 2162 if (std::fabs(fps - retFps) > 1.0) { 2163 ALOGE("%s: expect fps %f, got %f instead", __FUNCTION__, fps, retFps); 2164 return -1; 2165 } 2166 mV4l2StreamingFps = fps; 2167 return 0; 2168 } 2169 2170 int ExternalCameraDeviceSession::configureV4l2StreamLocked( 2171 const SupportedV4L2Format& v4l2Fmt, double requestFps) { 2172 ATRACE_CALL(); 2173 int ret = v4l2StreamOffLocked(); 2174 if (ret != OK) { 2175 ALOGE("%s: stop v4l2 streaming failed: ret %d", __FUNCTION__, ret); 2176 return ret; 2177 } 2178 2179 // VIDIOC_S_FMT w/h/fmt 2180 v4l2_format fmt; 2181 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2182 fmt.fmt.pix.width = v4l2Fmt.width; 2183 fmt.fmt.pix.height = v4l2Fmt.height; 2184 fmt.fmt.pix.pixelformat = v4l2Fmt.fourcc; 2185 ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); 2186 if (ret < 0) { 2187 int numAttempt = 0; 2188 while (ret < 0) { 2189 ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__); 2190 usleep(IOCTL_RETRY_SLEEP_US); // sleep and try again 2191 ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); 2192 if (numAttempt == MAX_RETRY) { 2193 break; 2194 } 2195 numAttempt++; 2196 } 2197 if (ret < 0) { 2198 ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno)); 2199 return -errno; 2200 } 2201 } 2202 2203 if (v4l2Fmt.width != fmt.fmt.pix.width || v4l2Fmt.height != fmt.fmt.pix.height || 2204 v4l2Fmt.fourcc != fmt.fmt.pix.pixelformat) { 2205 ALOGE("%s: S_FMT expect %c%c%c%c %dx%d, got %c%c%c%c %dx%d instead!", __FUNCTION__, 2206 v4l2Fmt.fourcc & 0xFF, 2207 (v4l2Fmt.fourcc >> 8) & 0xFF, 2208 (v4l2Fmt.fourcc >> 16) & 0xFF, 2209 (v4l2Fmt.fourcc >> 24) & 0xFF, 2210 v4l2Fmt.width, v4l2Fmt.height, 2211 fmt.fmt.pix.pixelformat & 0xFF, 2212 (fmt.fmt.pix.pixelformat >> 8) & 0xFF, 2213 (fmt.fmt.pix.pixelformat >> 16) & 0xFF, 2214 (fmt.fmt.pix.pixelformat >> 24) & 0xFF, 2215 fmt.fmt.pix.width, fmt.fmt.pix.height); 2216 return -EINVAL; 2217 } 2218 uint32_t bufferSize = fmt.fmt.pix.sizeimage; 2219 ALOGI("%s: V4L2 buffer size is %d", __FUNCTION__, bufferSize); 2220 uint32_t expectedMaxBufferSize = kMaxBytesPerPixel * fmt.fmt.pix.width * fmt.fmt.pix.height; 2221 if ((bufferSize == 0) || (bufferSize > expectedMaxBufferSize)) { 2222 ALOGE("%s: V4L2 buffer size: %u looks invalid. Expected maximum size: %u", __FUNCTION__, 2223 bufferSize, expectedMaxBufferSize); 2224 return -EINVAL; 2225 } 2226 mMaxV4L2BufferSize = bufferSize; 2227 2228 const double kDefaultFps = 30.0; 2229 double fps = 1000.0; 2230 if (requestFps != 0.0) { 2231 fps = requestFps; 2232 } else { 2233 double maxFps = -1.0; 2234 // Try to pick the slowest fps that is at least 30 2235 for (const auto& fr : v4l2Fmt.frameRates) { 2236 double f = fr.getDouble(); 2237 if (maxFps < f) { 2238 maxFps = f; 2239 } 2240 if (f >= kDefaultFps && f < fps) { 2241 fps = f; 2242 } 2243 } 2244 if (fps == 1000.0) { 2245 fps = maxFps; 2246 } 2247 } 2248 2249 int fpsRet = setV4l2FpsLocked(fps); 2250 if (fpsRet != 0 && fpsRet != -EINVAL) { 2251 ALOGE("%s: set fps failed: %s", __FUNCTION__, strerror(fpsRet)); 2252 return fpsRet; 2253 } 2254 2255 uint32_t v4lBufferCount = (fps >= kDefaultFps) ? 2256 mCfg.numVideoBuffers : mCfg.numStillBuffers; 2257 // VIDIOC_REQBUFS: create buffers 2258 v4l2_requestbuffers req_buffers{}; 2259 req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2260 req_buffers.memory = V4L2_MEMORY_MMAP; 2261 req_buffers.count = v4lBufferCount; 2262 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) { 2263 ALOGE("%s: VIDIOC_REQBUFS failed: %s", __FUNCTION__, strerror(errno)); 2264 return -errno; 2265 } 2266 2267 // Driver can indeed return more buffer if it needs more to operate 2268 if (req_buffers.count < v4lBufferCount) { 2269 ALOGE("%s: VIDIOC_REQBUFS expected %d buffers, got %d instead", 2270 __FUNCTION__, v4lBufferCount, req_buffers.count); 2271 return NO_MEMORY; 2272 } 2273 2274 // VIDIOC_QUERYBUF: get buffer offset in the V4L2 fd 2275 // VIDIOC_QBUF: send buffer to driver 2276 mV4L2BufferCount = req_buffers.count; 2277 for (uint32_t i = 0; i < req_buffers.count; i++) { 2278 v4l2_buffer buffer = { 2279 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 2280 .index = i, 2281 .memory = V4L2_MEMORY_MMAP}; 2282 2283 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QUERYBUF, &buffer)) < 0) { 2284 ALOGE("%s: QUERYBUF %d failed: %s", __FUNCTION__, i, strerror(errno)); 2285 return -errno; 2286 } 2287 2288 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) { 2289 ALOGE("%s: QBUF %d failed: %s", __FUNCTION__, i, strerror(errno)); 2290 return -errno; 2291 } 2292 } 2293 2294 // VIDIOC_STREAMON: start streaming 2295 v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2296 ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)); 2297 if (ret < 0) { 2298 int numAttempt = 0; 2299 while (ret < 0) { 2300 ALOGW("%s: VIDIOC_STREAMON failed, wait 33ms and try again", __FUNCTION__); 2301 usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again 2302 ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)); 2303 if (numAttempt == MAX_RETRY) { 2304 break; 2305 } 2306 numAttempt++; 2307 } 2308 if (ret < 0) { 2309 ALOGE("%s: VIDIOC_STREAMON ioctl failed: %s", __FUNCTION__, strerror(errno)); 2310 return -errno; 2311 } 2312 } 2313 2314 // Swallow first few frames after streamOn to account for bad frames from some devices 2315 for (int i = 0; i < kBadFramesAfterStreamOn; i++) { 2316 v4l2_buffer buffer{}; 2317 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2318 buffer.memory = V4L2_MEMORY_MMAP; 2319 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) { 2320 ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno)); 2321 return -errno; 2322 } 2323 2324 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) { 2325 ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, buffer.index, strerror(errno)); 2326 return -errno; 2327 } 2328 } 2329 2330 ALOGI("%s: start V4L2 streaming %dx%d@%ffps", 2331 __FUNCTION__, v4l2Fmt.width, v4l2Fmt.height, fps); 2332 mV4l2StreamingFmt = v4l2Fmt; 2333 mV4l2Streaming = true; 2334 return OK; 2335 } 2336 2337 sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs) { 2338 ATRACE_CALL(); 2339 sp<V4L2Frame> ret = nullptr; 2340 2341 if (shutterTs == nullptr) { 2342 ALOGE("%s: shutterTs must not be null!", __FUNCTION__); 2343 return ret; 2344 } 2345 2346 { 2347 std::unique_lock<std::mutex> lk(mV4l2BufferLock); 2348 if (mNumDequeuedV4l2Buffers == mV4L2BufferCount) { 2349 int waitRet = waitForV4L2BufferReturnLocked(lk); 2350 if (waitRet != 0) { 2351 return ret; 2352 } 2353 } 2354 } 2355 2356 ATRACE_BEGIN("VIDIOC_DQBUF"); 2357 v4l2_buffer buffer{}; 2358 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2359 buffer.memory = V4L2_MEMORY_MMAP; 2360 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) { 2361 ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno)); 2362 return ret; 2363 } 2364 ATRACE_END(); 2365 2366 if (buffer.index >= mV4L2BufferCount) { 2367 ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index); 2368 return ret; 2369 } 2370 2371 if (buffer.flags & V4L2_BUF_FLAG_ERROR) { 2372 ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags); 2373 // TODO: try to dequeue again 2374 } 2375 2376 if (buffer.bytesused > mMaxV4L2BufferSize) { 2377 ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused, 2378 mMaxV4L2BufferSize); 2379 return ret; 2380 } 2381 2382 if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) { 2383 // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but 2384 // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now 2385 *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec)*1000000000LL + 2386 buffer.timestamp.tv_usec * 1000LL; 2387 } else { 2388 *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC); 2389 } 2390 2391 { 2392 std::lock_guard<std::mutex> lk(mV4l2BufferLock); 2393 mNumDequeuedV4l2Buffers++; 2394 } 2395 return new V4L2Frame( 2396 mV4l2StreamingFmt.width, mV4l2StreamingFmt.height, mV4l2StreamingFmt.fourcc, 2397 buffer.index, mV4l2Fd.get(), buffer.bytesused, buffer.m.offset); 2398 } 2399 2400 void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { 2401 ATRACE_CALL(); 2402 frame->unmap(); 2403 ATRACE_BEGIN("VIDIOC_QBUF"); 2404 v4l2_buffer buffer{}; 2405 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2406 buffer.memory = V4L2_MEMORY_MMAP; 2407 buffer.index = frame->mBufferIndex; 2408 if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) { 2409 ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, 2410 frame->mBufferIndex, strerror(errno)); 2411 return; 2412 } 2413 ATRACE_END(); 2414 2415 { 2416 std::lock_guard<std::mutex> lk(mV4l2BufferLock); 2417 mNumDequeuedV4l2Buffers--; 2418 } 2419 mV4L2BufferReturned.notify_one(); 2420 } 2421 2422 Status ExternalCameraDeviceSession::configureStreams( 2423 const V3_2::StreamConfiguration& config, V3_3::HalStreamConfiguration* out) { 2424 ATRACE_CALL(); 2425 if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) { 2426 ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode); 2427 return Status::ILLEGAL_ARGUMENT; 2428 } 2429 2430 if (config.streams.size() == 0) { 2431 ALOGE("%s: cannot configure zero stream", __FUNCTION__); 2432 return Status::ILLEGAL_ARGUMENT; 2433 } 2434 2435 int numProcessedStream = 0; 2436 int numStallStream = 0; 2437 for (const auto& stream : config.streams) { 2438 // Check if the format/width/height combo is supported 2439 if (!isSupported(stream)) { 2440 return Status::ILLEGAL_ARGUMENT; 2441 } 2442 if (stream.format == PixelFormat::BLOB) { 2443 numStallStream++; 2444 } else { 2445 numProcessedStream++; 2446 } 2447 } 2448 2449 if (numProcessedStream > kMaxProcessedStream) { 2450 ALOGE("%s: too many processed streams (expect <= %d, got %d)", __FUNCTION__, 2451 kMaxProcessedStream, numProcessedStream); 2452 return Status::ILLEGAL_ARGUMENT; 2453 } 2454 2455 if (numStallStream > kMaxStallStream) { 2456 ALOGE("%s: too many stall streams (expect <= %d, got %d)", __FUNCTION__, 2457 kMaxStallStream, numStallStream); 2458 return Status::ILLEGAL_ARGUMENT; 2459 } 2460 2461 Status status = initStatus(); 2462 if (status != Status::OK) { 2463 return status; 2464 } 2465 2466 2467 { 2468 std::lock_guard<std::mutex> lk(mInflightFramesLock); 2469 if (!mInflightFrames.empty()) { 2470 ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!", 2471 __FUNCTION__, mInflightFrames.size()); 2472 return Status::INTERNAL_ERROR; 2473 } 2474 } 2475 2476 Mutex::Autolock _l(mLock); 2477 // Add new streams 2478 for (const auto& stream : config.streams) { 2479 if (mStreamMap.count(stream.id) == 0) { 2480 mStreamMap[stream.id] = stream; 2481 mCirculatingBuffers.emplace(stream.id, CirculatingBuffers{}); 2482 } 2483 } 2484 2485 // Cleanup removed streams 2486 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) { 2487 int id = it->first; 2488 bool found = false; 2489 for (const auto& stream : config.streams) { 2490 if (id == stream.id) { 2491 found = true; 2492 break; 2493 } 2494 } 2495 if (!found) { 2496 // Unmap all buffers of deleted stream 2497 cleanupBuffersLocked(id); 2498 it = mStreamMap.erase(it); 2499 } else { 2500 ++it; 2501 } 2502 } 2503 2504 // Now select a V4L2 format to produce all output streams 2505 float desiredAr = (mCroppingType == VERTICAL) ? kMaxAspectRatio : kMinAspectRatio; 2506 uint32_t maxDim = 0; 2507 for (const auto& stream : config.streams) { 2508 float aspectRatio = ASPECT_RATIO(stream); 2509 ALOGI("%s: request stream %dx%d", __FUNCTION__, stream.width, stream.height); 2510 if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) || 2511 (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) { 2512 desiredAr = aspectRatio; 2513 } 2514 2515 // The dimension that's not cropped 2516 uint32_t dim = (mCroppingType == VERTICAL) ? stream.width : stream.height; 2517 if (dim > maxDim) { 2518 maxDim = dim; 2519 } 2520 } 2521 // Find the smallest format that matches the desired aspect ratio and is wide/high enough 2522 SupportedV4L2Format v4l2Fmt {.width = 0, .height = 0}; 2523 for (const auto& fmt : mSupportedFormats) { 2524 uint32_t dim = (mCroppingType == VERTICAL) ? fmt.width : fmt.height; 2525 if (dim >= maxDim) { 2526 float aspectRatio = ASPECT_RATIO(fmt); 2527 if (isAspectRatioClose(aspectRatio, desiredAr)) { 2528 v4l2Fmt = fmt; 2529 // since mSupportedFormats is sorted by width then height, the first matching fmt 2530 // will be the smallest one with matching aspect ratio 2531 break; 2532 } 2533 } 2534 } 2535 if (v4l2Fmt.width == 0) { 2536 // Cannot find exact good aspect ratio candidate, try to find a close one 2537 for (const auto& fmt : mSupportedFormats) { 2538 uint32_t dim = (mCroppingType == VERTICAL) ? fmt.width : fmt.height; 2539 if (dim >= maxDim) { 2540 float aspectRatio = ASPECT_RATIO(fmt); 2541 if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) || 2542 (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) { 2543 v4l2Fmt = fmt; 2544 break; 2545 } 2546 } 2547 } 2548 } 2549 2550 if (v4l2Fmt.width == 0) { 2551 ALOGE("%s: unable to find a resolution matching (%s at least %d, aspect ratio %f)" 2552 , __FUNCTION__, (mCroppingType == VERTICAL) ? "width" : "height", 2553 maxDim, desiredAr); 2554 return Status::ILLEGAL_ARGUMENT; 2555 } 2556 2557 if (configureV4l2StreamLocked(v4l2Fmt) != 0) { 2558 ALOGE("V4L configuration failed!, format:%c%c%c%c, w %d, h %d", 2559 v4l2Fmt.fourcc & 0xFF, 2560 (v4l2Fmt.fourcc >> 8) & 0xFF, 2561 (v4l2Fmt.fourcc >> 16) & 0xFF, 2562 (v4l2Fmt.fourcc >> 24) & 0xFF, 2563 v4l2Fmt.width, v4l2Fmt.height); 2564 return Status::INTERNAL_ERROR; 2565 } 2566 2567 Size v4lSize = {v4l2Fmt.width, v4l2Fmt.height}; 2568 Size thumbSize { 0, 0 }; 2569 camera_metadata_ro_entry entry = 2570 mCameraCharacteristics.find(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES); 2571 for(uint32_t i = 0; i < entry.count; i += 2) { 2572 Size sz { static_cast<uint32_t>(entry.data.i32[i]), 2573 static_cast<uint32_t>(entry.data.i32[i+1]) }; 2574 if(sz.width * sz.height > thumbSize.width * thumbSize.height) { 2575 thumbSize = sz; 2576 } 2577 } 2578 2579 if (thumbSize.width * thumbSize.height == 0) { 2580 ALOGE("%s: non-zero thumbnail size not available", __FUNCTION__); 2581 return Status::INTERNAL_ERROR; 2582 } 2583 2584 status = mOutputThread->allocateIntermediateBuffers(v4lSize, 2585 mMaxThumbResolution, config.streams); 2586 if (status != Status::OK) { 2587 ALOGE("%s: allocating intermediate buffers failed!", __FUNCTION__); 2588 return status; 2589 } 2590 2591 out->streams.resize(config.streams.size()); 2592 for (size_t i = 0; i < config.streams.size(); i++) { 2593 out->streams[i].overrideDataSpace = config.streams[i].dataSpace; 2594 out->streams[i].v3_2.id = config.streams[i].id; 2595 // TODO: double check should we add those CAMERA flags 2596 mStreamMap[config.streams[i].id].usage = 2597 out->streams[i].v3_2.producerUsage = config.streams[i].usage | 2598 BufferUsage::CPU_WRITE_OFTEN | 2599 BufferUsage::CAMERA_OUTPUT; 2600 out->streams[i].v3_2.consumerUsage = 0; 2601 out->streams[i].v3_2.maxBuffers = mV4L2BufferCount; 2602 2603 switch (config.streams[i].format) { 2604 case PixelFormat::BLOB: 2605 case PixelFormat::YCBCR_420_888: 2606 case PixelFormat::YV12: // Used by SurfaceTexture 2607 // No override 2608 out->streams[i].v3_2.overrideFormat = config.streams[i].format; 2609 break; 2610 case PixelFormat::IMPLEMENTATION_DEFINED: 2611 // Override based on VIDEO or not 2612 out->streams[i].v3_2.overrideFormat = 2613 (config.streams[i].usage & BufferUsage::VIDEO_ENCODER) ? 2614 PixelFormat::YCBCR_420_888 : PixelFormat::YV12; 2615 // Save overridden formt in mStreamMap 2616 mStreamMap[config.streams[i].id].format = out->streams[i].v3_2.overrideFormat; 2617 break; 2618 default: 2619 ALOGE("%s: unsupported format 0x%x", __FUNCTION__, config.streams[i].format); 2620 return Status::ILLEGAL_ARGUMENT; 2621 } 2622 } 2623 2624 mFirstRequest = true; 2625 return Status::OK; 2626 } 2627 2628 bool ExternalCameraDeviceSession::isClosed() { 2629 Mutex::Autolock _l(mLock); 2630 return mClosed; 2631 } 2632 2633 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 2634 #define UPDATE(md, tag, data, size) \ 2635 do { \ 2636 if ((md).update((tag), (data), (size))) { \ 2637 ALOGE("Update " #tag " failed!"); \ 2638 return BAD_VALUE; \ 2639 } \ 2640 } while (0) 2641 2642 status_t ExternalCameraDeviceSession::initDefaultRequests() { 2643 ::android::hardware::camera::common::V1_0::helper::CameraMetadata md; 2644 2645 const uint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF; 2646 UPDATE(md, ANDROID_COLOR_CORRECTION_ABERRATION_MODE, &aberrationMode, 1); 2647 2648 const int32_t exposureCompensation = 0; 2649 UPDATE(md, ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &exposureCompensation, 1); 2650 2651 const uint8_t videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF; 2652 UPDATE(md, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &videoStabilizationMode, 1); 2653 2654 const uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO; 2655 UPDATE(md, ANDROID_CONTROL_AWB_MODE, &awbMode, 1); 2656 2657 const uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON; 2658 UPDATE(md, ANDROID_CONTROL_AE_MODE, &aeMode, 1); 2659 2660 const uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE; 2661 UPDATE(md, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &aePrecaptureTrigger, 1); 2662 2663 const uint8_t afMode = ANDROID_CONTROL_AF_MODE_AUTO; 2664 UPDATE(md, ANDROID_CONTROL_AF_MODE, &afMode, 1); 2665 2666 const uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE; 2667 UPDATE(md, ANDROID_CONTROL_AF_TRIGGER, &afTrigger, 1); 2668 2669 const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED; 2670 UPDATE(md, ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1); 2671 2672 const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF; 2673 UPDATE(md, ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1); 2674 2675 const uint8_t flashMode = ANDROID_FLASH_MODE_OFF; 2676 UPDATE(md, ANDROID_FLASH_MODE, &flashMode, 1); 2677 2678 const int32_t thumbnailSize[] = {240, 180}; 2679 UPDATE(md, ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2); 2680 2681 const uint8_t jpegQuality = 90; 2682 UPDATE(md, ANDROID_JPEG_QUALITY, &jpegQuality, 1); 2683 UPDATE(md, ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1); 2684 2685 const int32_t jpegOrientation = 0; 2686 UPDATE(md, ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1); 2687 2688 const uint8_t oisMode = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF; 2689 UPDATE(md, ANDROID_LENS_OPTICAL_STABILIZATION_MODE, &oisMode, 1); 2690 2691 const uint8_t nrMode = ANDROID_NOISE_REDUCTION_MODE_OFF; 2692 UPDATE(md, ANDROID_NOISE_REDUCTION_MODE, &nrMode, 1); 2693 2694 const int32_t testPatternModes = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF; 2695 UPDATE(md, ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes, 1); 2696 2697 const uint8_t fdMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; 2698 UPDATE(md, ANDROID_STATISTICS_FACE_DETECT_MODE, &fdMode, 1); 2699 2700 const uint8_t hotpixelMode = ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF; 2701 UPDATE(md, ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, &hotpixelMode, 1); 2702 2703 bool support30Fps = false; 2704 int32_t maxFps = std::numeric_limits<int32_t>::min(); 2705 for (const auto& supportedFormat : mSupportedFormats) { 2706 for (const auto& fr : supportedFormat.frameRates) { 2707 int32_t framerateInt = static_cast<int32_t>(fr.getDouble()); 2708 if (maxFps < framerateInt) { 2709 maxFps = framerateInt; 2710 } 2711 if (framerateInt == 30) { 2712 support30Fps = true; 2713 break; 2714 } 2715 } 2716 if (support30Fps) { 2717 break; 2718 } 2719 } 2720 int32_t defaultFramerate = support30Fps ? 30 : maxFps; 2721 int32_t defaultFpsRange[] = {defaultFramerate / 2, defaultFramerate}; 2722 UPDATE(md, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, defaultFpsRange, ARRAY_SIZE(defaultFpsRange)); 2723 2724 uint8_t antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO; 2725 UPDATE(md, ANDROID_CONTROL_AE_ANTIBANDING_MODE, &antibandingMode, 1); 2726 2727 const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO; 2728 UPDATE(md, ANDROID_CONTROL_MODE, &controlMode, 1); 2729 2730 auto requestTemplates = hidl_enum_iterator<RequestTemplate>(); 2731 for (RequestTemplate type : requestTemplates) { 2732 ::android::hardware::camera::common::V1_0::helper::CameraMetadata mdCopy = md; 2733 uint8_t intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; 2734 switch (type) { 2735 case RequestTemplate::PREVIEW: 2736 intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; 2737 break; 2738 case RequestTemplate::STILL_CAPTURE: 2739 intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE; 2740 break; 2741 case RequestTemplate::VIDEO_RECORD: 2742 intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD; 2743 break; 2744 case RequestTemplate::VIDEO_SNAPSHOT: 2745 intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT; 2746 break; 2747 default: 2748 ALOGV("%s: unsupported RequestTemplate type %d", __FUNCTION__, type); 2749 continue; 2750 } 2751 UPDATE(mdCopy, ANDROID_CONTROL_CAPTURE_INTENT, &intent, 1); 2752 2753 camera_metadata_t* rawMd = mdCopy.release(); 2754 CameraMetadata hidlMd; 2755 hidlMd.setToExternal( 2756 (uint8_t*) rawMd, get_camera_metadata_size(rawMd)); 2757 mDefaultRequests[type] = hidlMd; 2758 free_camera_metadata(rawMd); 2759 } 2760 2761 return OK; 2762 } 2763 2764 status_t ExternalCameraDeviceSession::fillCaptureResult( 2765 common::V1_0::helper::CameraMetadata &md, nsecs_t timestamp) { 2766 // android.control 2767 // For USB camera, we don't know the AE state. Set the state to converged to 2768 // indicate the frame should be good to use. Then apps don't have to wait the 2769 // AE state. 2770 const uint8_t aeState = ANDROID_CONTROL_AE_STATE_CONVERGED; 2771 UPDATE(md, ANDROID_CONTROL_AE_STATE, &aeState, 1); 2772 2773 const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF; 2774 UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1); 2775 2776 bool afTrigger = false; 2777 { 2778 std::lock_guard<std::mutex> lk(mAfTriggerLock); 2779 afTrigger = mAfTrigger; 2780 if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) { 2781 camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER); 2782 if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) { 2783 mAfTrigger = afTrigger = true; 2784 } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) { 2785 mAfTrigger = afTrigger = false; 2786 } 2787 } 2788 } 2789 2790 // For USB camera, the USB camera handles everything and we don't have control 2791 // over AF. We only simply fake the AF metadata based on the request 2792 // received here. 2793 uint8_t afState; 2794 if (afTrigger) { 2795 afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED; 2796 } else { 2797 afState = ANDROID_CONTROL_AF_STATE_INACTIVE; 2798 } 2799 UPDATE(md, ANDROID_CONTROL_AF_STATE, &afState, 1); 2800 2801 // Set AWB state to converged to indicate the frame should be good to use. 2802 const uint8_t awbState = ANDROID_CONTROL_AWB_STATE_CONVERGED; 2803 UPDATE(md, ANDROID_CONTROL_AWB_STATE, &awbState, 1); 2804 2805 const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF; 2806 UPDATE(md, ANDROID_CONTROL_AWB_LOCK, &awbLock, 1); 2807 2808 camera_metadata_ro_entry active_array_size = 2809 mCameraCharacteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE); 2810 2811 if (active_array_size.count == 0) { 2812 ALOGE("%s: cannot find active array size!", __FUNCTION__); 2813 return -EINVAL; 2814 } 2815 2816 const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE; 2817 UPDATE(md, ANDROID_FLASH_STATE, &flashState, 1); 2818 2819 // This means pipeline latency of X frame intervals. The maximum number is 4. 2820 const uint8_t requestPipelineMaxDepth = 4; 2821 UPDATE(md, ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1); 2822 2823 // android.scaler 2824 const int32_t crop_region[] = { 2825 active_array_size.data.i32[0], active_array_size.data.i32[1], 2826 active_array_size.data.i32[2], active_array_size.data.i32[3], 2827 }; 2828 UPDATE(md, ANDROID_SCALER_CROP_REGION, crop_region, ARRAY_SIZE(crop_region)); 2829 2830 // android.sensor 2831 UPDATE(md, ANDROID_SENSOR_TIMESTAMP, ×tamp, 1); 2832 2833 // android.statistics 2834 const uint8_t lensShadingMapMode = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF; 2835 UPDATE(md, ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &lensShadingMapMode, 1); 2836 2837 const uint8_t sceneFlicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE; 2838 UPDATE(md, ANDROID_STATISTICS_SCENE_FLICKER, &sceneFlicker, 1); 2839 2840 return OK; 2841 } 2842 2843 #undef ARRAY_SIZE 2844 #undef UPDATE 2845 2846 } // namespace implementation 2847 } // namespace V3_4 2848 } // namespace device 2849 } // namespace camera 2850 } // namespace hardware 2851 } // namespace android 2852