From b5a5a4f040cc8a60967723fbef1719506f71960b Mon Sep 17 00:00:00 2001 From: Bartlomiej Moskal Date: Tue, 23 Apr 2024 10:19:21 +0200 Subject: FFmpeg-Android: Set the configured FPS on Camera Add implementation for setting up FPS on Android Camera. [0]QCameraFormat (beyond the pixel format and resolution) contains also max/min frame rate. Those parameters were not passed and set on Android Camera. After this commit, the whole configuration kept in QCameraFormat is set on device during camera activation. [0]https://doc.qt.io/qt-6/qcameraformat.html Task-number: QTBUG-113399 Pick-to: 6.7 6.5 Change-Id: Iba4f4c0c8ac4bbdaf3488a0a9005bff42390c428 Reviewed-by: Artem Dyomin --- .../qtproject/qt/android/multimedia/QtCamera2.java | 22 +++++++++++++++++++--- src/plugins/multimedia/ffmpeg/qandroidcamera.cpp | 22 +++++++++++----------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java index 98af64c31..ac8140197 100644 --- a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java +++ b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java @@ -24,6 +24,7 @@ import android.graphics.ImageFormat; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; +import android.util.Range; import android.view.Surface; import android.media.MediaCodec; import android.media.MediaCodecInfo; @@ -62,6 +63,7 @@ public class QtCamera2 { private int mTorchMode = CameraMetadata.FLASH_MODE_OFF; private int mAFMode = CaptureRequest.CONTROL_AF_MODE_OFF; private float mZoomFactor = 1.0f; + private Range mFpsRange = null; private QtExifDataHandler mExifDataHandler = null; native void onCameraOpened(String cameraId); @@ -261,7 +263,14 @@ public class QtCamera2 { } }; - public boolean addImageReader(int width, int height, int format) { + + public void prepareCamera(int width, int height, int format, int minFps, int maxFps) { + + addImageReader(width, height, format); + setFrameRate(minFps, maxFps); + } + + private void addImageReader(int width, int height, int format) { if (mImageReader != null) removeSurface(mImageReader.getSurface()); @@ -276,8 +285,14 @@ public class QtCamera2 { mCapturedPhotoReader = ImageReader.newInstance(width, height, format, MaxNumberFrames); mCapturedPhotoReader.setOnImageAvailableListener(mOnPhotoAvailableListener, mBackgroundHandler); addSurface(mCapturedPhotoReader.getSurface()); + } + + private void setFrameRate(int minFrameRate, int maxFrameRate) { - return true; + if (minFrameRate <= 0 || maxFrameRate <= 0) + mFpsRange = null; + else + mFpsRange = new Range<>(minFrameRate, maxFrameRate); } public boolean addSurface(Surface surface) { @@ -335,7 +350,8 @@ public class QtCamera2 { mPreviewRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_VIDEO_RECORD); if (mZoomFactor != 1.0f) mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, getScalerCropRegion()); - + if (mFpsRange != null) + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mFpsRange); mPreviewRequest = mPreviewRequestBuilder.build(); mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler); mIsStarted = true; diff --git a/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp b/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp index 97448c707..bf01a4e30 100644 --- a/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp +++ b/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp @@ -55,8 +55,8 @@ QCameraFormat getDefaultCameraFormat() QCameraFormatPrivate *defaultFormat = new QCameraFormatPrivate{ .pixelFormat = QVideoFrameFormat::Format_YUV420P, .resolution = { 1920, 1080 }, - .minFrameRate = 30, - .maxFrameRate = 60, + .minFrameRate = 12, + .maxFrameRate = 30, }; return defaultFormat->create(); } @@ -273,6 +273,15 @@ void QAndroidCamera::setActive(bool active) setState(State::WaitingOpen); g_qcameras->insert(m_cameraDevice.id(), this); + // this should use the camera format. + // but there is only 2 fully supported formats on android - JPG and YUV420P + // and JPEG is not supported for encoding in FFmpeg, so it's locked for YUV for now. + const static int imageFormat = + QJniObject::getStaticField("YUV_420_888"); + m_jniCamera.callMethod("prepareCamera", jint(width), jint(height), + jint(imageFormat), jint(m_cameraFormat.minFrameRate()), + jint(m_cameraFormat.maxFrameRate())); + bool canOpen = m_jniCamera.callMethod( "open", QJniObject::fromString(m_cameraDevice.id()).object()); @@ -282,15 +291,6 @@ void QAndroidCamera::setActive(bool active) emit error(QCamera::CameraError, QString("Failed to start camera: ").append(m_cameraDevice.description())); } - - // this should use the camera format. - // but there is only 2 fully supported formats on android - JPG and YUV420P - // and JPEG is not supported for encoding in FFmpeg, so it's locked for YUV for now. - const static int imageFormat = - QJniObject::getStaticField("YUV_420_888"); - m_jniCamera.callMethod("addImageReader", jint(width), jint(height), - jint(imageFormat)); - } else { m_jniCamera.callMethod("stopAndClose"); m_jniCamera.callMethod("clearSurfaces"); -- cgit v1.2.3