From 134093a43fa3430c913eb3b48726c42510a1e6ad Mon Sep 17 00:00:00 2001 From: Yin-Chia Yeh Date: Mon, 12 Feb 2018 14:05:48 -0800 Subject: [PATCH] Camera: use rational/double for external camera framerate For better precision. Ex: minFrameDuration of 30fps 333333334->333333333 Bug: 72261912 Change-Id: I830d694d34eb01426e46279c4c986d8879b9d847 --- .../3.4/default/ExternalCameraDevice.cpp | 29 +++++++++++-------- .../default/ExternalCameraDeviceSession.cpp | 7 +++-- .../3.4/default/ExternalCameraUtils.cpp | 6 +++- .../ExternalCameraUtils.h | 9 ++++-- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index 61b892124d..b6470f5e75 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp @@ -595,16 +595,19 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT); } - int64_t min_frame_duration = std::numeric_limits::max(); - for (const auto& frameRate : supportedFormat.frameRates) { - int64_t frame_duration = 1000000000LL / frameRate; - if (frame_duration < min_frame_duration) { - min_frame_duration = frame_duration; + int64_t minFrameDuration = std::numeric_limits::max(); + for (const auto& fr : supportedFormat.frameRates) { + // 1000000000LL < (2^32 - 1) and + // fr.durationNumerator is uint32_t, so no overflow here + int64_t frameDuration = 1000000000LL * fr.durationNumerator / + fr.durationDenominator; + if (frameDuration < minFrameDuration) { + minFrameDuration = frameDuration; } - if (frame_duration > maxFrameDuration) { - maxFrameDuration = frame_duration; + if (frameDuration > maxFrameDuration) { + maxFrameDuration = frameDuration; } - int32_t frameRateInt = static_cast(frameRate); + int32_t frameRateInt = static_cast(fr.getDouble()); if (minFps > frameRateInt) { minFps = frameRateInt; } @@ -618,7 +621,7 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd, minFrameDurations.push_back(format); minFrameDurations.push_back(supportedFormat.width); minFrameDurations.push_back(supportedFormat.height); - minFrameDurations.push_back(min_frame_duration); + minFrameDurations.push_back(minFrameDuration); } // The stall duration is 0 for non-jpeg formats. For JPEG format, stall @@ -705,8 +708,10 @@ void ExternalCameraDevice::getFrameRateList( ++frameInterval.index) { if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) { if (frameInterval.discrete.numerator != 0) { - float framerate = frameInterval.discrete.denominator / - static_cast(frameInterval.discrete.numerator); + SupportedV4L2Format::FrameRate fr = { + frameInterval.discrete.numerator, + frameInterval.discrete.denominator}; + double framerate = fr.getDouble(); if (framerate > fpsUpperBound) { continue; } @@ -717,7 +722,7 @@ void ExternalCameraDevice::getFrameRateList( (frameInterval.pixel_format >> 16) & 0xFF, (frameInterval.pixel_format >> 24) & 0xFF, frameInterval.width, frameInterval.height, framerate); - format->frameRates.push_back(framerate); + format->frameRates.push_back(fr); } } } diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index 74fd7f4cb1..5de1442b72 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp @@ -1904,7 +1904,8 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(const SupportedV4L2Fo float fps = 1000.f; const float kDefaultFps = 30.f; // Try to pick the slowest fps that is at least 30 - for (const auto& f : v4l2Fmt.frameRates) { + for (const auto& fr : v4l2Fmt.frameRates) { + double f = fr.getDouble(); if (maxFps < f) { maxFps = f; } @@ -2346,8 +2347,8 @@ status_t ExternalCameraDeviceSession::initDefaultRequests() { bool support30Fps = false; int32_t maxFps = std::numeric_limits::min(); for (const auto& supportedFormat : mSupportedFormats) { - for (const auto& frameRate : supportedFormat.frameRates) { - int32_t framerateInt = static_cast(frameRate); + for (const auto& fr : supportedFormat.frameRates) { + int32_t framerateInt = static_cast(fr.getDouble()); if (maxFps < framerateInt) { maxFps = framerateInt; } diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp index 80f296c6ad..d28a4dd46a 100644 --- a/camera/device/3.4/default/ExternalCameraUtils.cpp +++ b/camera/device/3.4/default/ExternalCameraUtils.cpp @@ -147,6 +147,10 @@ bool isAspectRatioClose(float ar1, float ar2) { return (std::abs(ar1 - ar2) < kAspectRatioMatchThres); } +double SupportedV4L2Format::FrameRate::getDouble() const { + return durationDenominator / static_cast(durationNumerator); +} + } // namespace implementation } // namespace V3_4 } // namespace device @@ -247,7 +251,7 @@ ExternalCameraConfig ExternalCameraConfig::loadFromCfg(const char* cfgPath) { limit.size = { row->UnsignedAttribute("width", /*Default*/0), row->UnsignedAttribute("height", /*Default*/0)}; - limit.fpsUpperBound = row->FloatAttribute("fpsBound", /*Default*/1000.0); + limit.fpsUpperBound = row->DoubleAttribute("fpsBound", /*Default*/1000.0); if (limit.size.width <= prevLimit.size.width || limit.size.height <= prevLimit.size.height || limit.fpsUpperBound >= prevLimit.fpsUpperBound) { diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h index e56160a8d8..37e7cfb32e 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h @@ -73,7 +73,7 @@ struct ExternalCameraConfig { struct FpsLimitation { Size size; - float fpsUpperBound; + double fpsUpperBound; }; std::vector fpsLimits; @@ -93,7 +93,12 @@ struct SupportedV4L2Format { uint32_t height; uint32_t fourcc; // All supported frame rate for this w/h/fourcc combination - std::vector frameRates; + struct FrameRate { + uint32_t durationNumerator; // frame duration numerator. Ex: 1 + uint32_t durationDenominator; // frame duration denominator. Ex: 30 + double getDouble() const; // FrameRate in double. Ex: 30.0 + }; + std::vector frameRates; }; // A class provide access to a dequeued V4L2 frame buffer (mostly in MJPG format)