diff --git a/camera/common/1.0/default/Exif.cpp b/camera/common/1.0/default/Exif.cpp index 3e894f92a6..6054999a07 100644 --- a/camera/common/1.0/default/Exif.cpp +++ b/camera/common/1.0/default/Exif.cpp @@ -983,15 +983,15 @@ bool ExifUtilsImpl::setFromMetadata(const CameraMetadata& metadata, camera_metadata_ro_entry entry = metadata.find(ANDROID_LENS_FOCAL_LENGTH); if (entry.count) { focal_length = entry.data.f[0]; + + if (!setFocalLength( + static_cast(focal_length * kRationalPrecision), + kRationalPrecision)) { + ALOGE("%s: setting focal length failed.", __FUNCTION__); + return false; + } } else { - ALOGE("%s: Cannot find focal length in metadata.", __FUNCTION__); - return false; - } - if (!setFocalLength( - static_cast(focal_length * kRationalPrecision), - kRationalPrecision)) { - ALOGE("%s: setting focal length failed.", __FUNCTION__); - return false; + ALOGV("%s: Cannot find focal length in metadata.", __FUNCTION__); } if (metadata.exists(ANDROID_JPEG_GPS_COORDINATES)) { diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index 9a02ce86b4..6b05d4a5b1 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -284,13 +284,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( const int32_t jpegMaxSize = mCfg.maxJpegBufSize; UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1); - const uint8_t jpegQuality = 90; - UPDATE(ANDROID_JPEG_QUALITY, &jpegQuality, 1); - UPDATE(ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1); - - const int32_t jpegOrientation = 0; - UPDATE(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1); - // android.lens const uint8_t focusDistanceCalibration = ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED; @@ -322,7 +315,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( // This means pipeline latency of X frame intervals. The maximum number is 4. const uint8_t requestPipelineMaxDepth = 4; UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1); - UPDATE(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1); // Three numbers represent the maximum numbers of different types of output // streams simultaneously. The types are raw sensor, processed (but not @@ -355,7 +347,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( ANDROID_SENSOR_TEST_PATTERN_MODE_OFF}; UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes, ARRAY_SIZE(testPatternModes)); - UPDATE(ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes[0], 1); const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN; UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, ×tampSource, 1); @@ -576,7 +567,6 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, std::vector streamConfigurations; std::vector minFrameDurations; std::vector stallDurations; - int64_t maxFrameDuration = 0; int32_t maxFps = std::numeric_limits::min(); int32_t minFps = std::numeric_limits::max(); std::set framerates; @@ -604,9 +594,6 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, if (frameDuration < minFrameDuration) { minFrameDuration = frameDuration; } - if (frameDuration > maxFrameDuration) { - maxFrameDuration = frameDuration; - } int32_t frameRateInt = static_cast(fr.getDouble()); if (minFps > frameRateInt) { minFps = frameRateInt; @@ -639,14 +626,15 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, } std::vector fpsRanges; - // Variable range - fpsRanges.push_back(minFps); - fpsRanges.push_back(maxFps); - // Fixed ranges + // FPS ranges for (const auto& framerate : framerates) { - fpsRanges.push_back(framerate); + // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range + fpsRanges.push_back(framerate / 2); fpsRanges.push_back(framerate); } + minFps /= 2; + int64_t maxFrameDuration = 1000000000LL / minFps; + UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(), fpsRanges.size()); diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index 55694398e7..7015bcb444 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -47,6 +47,9 @@ static constexpr size_t kMetadataMsgQueueSize = 1 << 18 /* 256kB */; const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get rid of some initial // bad frames. TODO: develop a better bad frame detection // method +constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some + // webcam showing temporarily ioctl failures. +constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds bool tryLock(Mutex& mutex) { @@ -1480,6 +1483,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( int jpegQuality, thumbQuality; Size thumbSize; + bool outputThumbnail = true; if (req->setting.exists(ANDROID_JPEG_QUALITY)) { camera_metadata_entry entry = @@ -1505,6 +1509,9 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( thumbSize = Size { static_cast(entry.data.i32[0]), static_cast(entry.data.i32[1]) }; + if (thumbSize.width == 0 && thumbSize.height == 0) { + outputThumbnail = false; + } } else { return lfail( "%s: ANDROID_JPEG_THUMBNAIL_SIZE not set", __FUNCTION__); @@ -1532,14 +1539,16 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( /* Hold actual thumbnail and main image code sizes */ size_t thumbCodeSize = 0, jpegCodeSize = 0; /* Temporary thumbnail code buffer */ - std::vector thumbCode(maxThumbCodeSize); + std::vector thumbCode(outputThumbnail ? maxThumbCodeSize : 0); YCbCrLayout yu12Thumb; - ret = cropAndScaleThumbLocked(mYu12Frame, thumbSize, &yu12Thumb); + if (outputThumbnail) { + ret = cropAndScaleThumbLocked(mYu12Frame, thumbSize, &yu12Thumb); - if (ret != 0) { - return lfail( - "%s: crop and scale thumbnail failed!", __FUNCTION__); + if (ret != 0) { + return lfail( + "%s: crop and scale thumbnail failed!", __FUNCTION__); + } } /* Scale and crop main jpeg */ @@ -1550,12 +1559,14 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( } /* Encode the thumbnail image */ - ret = encodeJpegYU12(thumbSize, yu12Thumb, - thumbQuality, 0, 0, - &thumbCode[0], maxThumbCodeSize, thumbCodeSize); + if (outputThumbnail) { + ret = encodeJpegYU12(thumbSize, yu12Thumb, + thumbQuality, 0, 0, + &thumbCode[0], maxThumbCodeSize, thumbCodeSize); - if (ret != 0) { - return lfail("%s: encodeJpegYU12 failed with %d",__FUNCTION__, ret); + if (ret != 0) { + return lfail("%s: thumbnail encodeJpegYU12 failed with %d",__FUNCTION__, ret); + } } /* Combine camera characteristics with request settings to form EXIF @@ -1570,11 +1581,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( utils->setFromMetadata(meta, jpegSize.width, jpegSize.height); - /* Check if we made a non-zero-sized thumbnail. Currently not possible - * that we got this far and the code is size 0, but if this code moves - * around it might become relevant again */ - - ret = utils->generateApp1(thumbCodeSize ? &thumbCode[0] : 0, thumbCodeSize); + ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize); if (!ret) { return lfail("%s: generating APP1 failed", __FUNCTION__); @@ -2109,8 +2116,20 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked( fmt.fmt.pix.pixelformat = v4l2Fmt.fourcc; ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); if (ret < 0) { - ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno)); - return -errno; + int numAttempt = 0; + while (ret < 0) { + ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__); + usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again + ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt)); + if (numAttempt == MAX_RETRY) { + break; + } + numAttempt++; + } + if (ret < 0) { + ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno)); + return -errno; + } } if (v4l2Fmt.width != fmt.fmt.pix.width || v4l2Fmt.height != fmt.fmt.pix.height || @@ -2199,9 +2218,22 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked( // VIDIOC_STREAMON: start streaming v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)) < 0) { - ALOGE("%s: VIDIOC_STREAMON failed: %s", __FUNCTION__, strerror(errno)); - return -errno; + ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)); + if (ret < 0) { + int numAttempt = 0; + while (ret < 0) { + ALOGW("%s: VIDIOC_STREAMON failed, wait 33ms and try again", __FUNCTION__); + usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again + ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)); + if (numAttempt == MAX_RETRY) { + break; + } + numAttempt++; + } + if (ret < 0) { + ALOGE("%s: VIDIOC_STREAMON ioctl failed: %s", __FUNCTION__, strerror(errno)); + return -errno; + } } // Swallow first few frames after streamOn to account for bad frames from some devices @@ -2220,6 +2252,8 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked( } } + ALOGI("%s: start V4L2 streaming %dx%d@%ffps", + __FUNCTION__, v4l2Fmt.width, v4l2Fmt.height, fps); mV4l2StreamingFmt = v4l2Fmt; mV4l2Streaming = true; return OK; @@ -2388,6 +2422,7 @@ Status ExternalCameraDeviceSession::configureStreams( uint32_t maxDim = 0; for (const auto& stream : config.streams) { float aspectRatio = ASPECT_RATIO(stream); + ALOGI("%s: request stream %dx%d", __FUNCTION__, stream.width, stream.height); if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) || (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) { desiredAr = aspectRatio; @@ -2572,6 +2607,9 @@ status_t ExternalCameraDeviceSession::initDefaultRequests() { const uint8_t nrMode = ANDROID_NOISE_REDUCTION_MODE_OFF; UPDATE(md, ANDROID_NOISE_REDUCTION_MODE, &nrMode, 1); + const int32_t testPatternModes = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF; + UPDATE(md, ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes, 1); + const uint8_t fdMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; UPDATE(md, ANDROID_STATISTICS_FACE_DETECT_MODE, &fdMode, 1); @@ -2596,7 +2634,7 @@ status_t ExternalCameraDeviceSession::initDefaultRequests() { } } int32_t defaultFramerate = support30Fps ? 30 : maxFps; - int32_t defaultFpsRange[] = {defaultFramerate, defaultFramerate}; + int32_t defaultFpsRange[] = {defaultFramerate / 2, defaultFramerate}; UPDATE(md, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, defaultFpsRange, ARRAY_SIZE(defaultFpsRange)); uint8_t antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO; @@ -2691,6 +2729,10 @@ status_t ExternalCameraDeviceSession::fillCaptureResult( const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE; UPDATE(md, ANDROID_FLASH_STATE, &flashState, 1); + // This means pipeline latency of X frame intervals. The maximum number is 4. + const uint8_t requestPipelineMaxDepth = 4; + UPDATE(md, ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1); + // android.scaler const int32_t crop_region[] = { active_array_size.data.i32[0], active_array_size.data.i32[1], diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp index d28a4dd46a..2e2f73b362 100644 --- a/camera/device/3.4/default/ExternalCameraUtils.cpp +++ b/camera/device/3.4/default/ExternalCameraUtils.cpp @@ -283,9 +283,8 @@ ExternalCameraConfig::ExternalCameraConfig() : numVideoBuffers(kDefaultNumVideoBuffer), numStillBuffers(kDefaultNumStillBuffer) { fpsLimits.push_back({/*Size*/{ 640, 480}, /*FPS upper bound*/30.0}); - fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/15.0}); - fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/10.0}); - fpsLimits.push_back({/*Size*/{4096, 3072}, /*FPS upper bound*/5.0}); + fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/7.5}); + fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0}); }