backends/camera_api: set preview resolution with given fps 63/315363/3
authorInki Dae <inki.dae@samsung.com>
Fri, 29 Nov 2024 02:02:40 +0000 (11:02 +0900)
committerInki Dae <inki.dae@samsung.com>
Wed, 4 Dec 2024 06:26:37 +0000 (06:26 +0000)
Set preview resoultion with given fps.

Preview resolution has supported fps so find a proper resolution
which supports the user-given fps and set it.

In addition, this patch adds YUYV pixel format support.

Change-Id: Ie45053c099441463061976fbf6faf1830ee676d9
Signed-off-by: Inki Dae <inki.dae@samsung.com>
input/backends/camera_api/include/CameraApiBackend.h
input/backends/camera_api/src/CameraApiBackend.cpp

index 5e73758e172154f92c56b023c73a4ceca4d633ed..5fc6d8935a3ace41e38786f79c44ff9fbd89c555 100644 (file)
@@ -42,8 +42,10 @@ private:
        bool _isCaptured { false };
        IInputObserver *_observer {};
        cv::Mat _cvCaptureImage;
-       camera_pixel_format_e _defaultPreviewPixelFormat { CAMERA_PIXEL_FORMAT_I420 };
-       camera_pixel_format_e _defaultCapturePixelFormat { CAMERA_PIXEL_FORMAT_I420 };
+       std::vector<camera_pixel_format_e> _defaultPreviewPixelFormats = { CAMERA_PIXEL_FORMAT_YUYV,
+                                                                                                                                          CAMERA_PIXEL_FORMAT_I420 };
+       std::vector<camera_pixel_format_e> _defaultCapturePixelFormats = { CAMERA_PIXEL_FORMAT_I420,
+                                                                                                                                          CAMERA_PIXEL_FORMAT_YUYV };
        std::vector<camera_pixel_format_e> _validPreviewPixelFormat;
        std::vector<camera_pixel_format_e> _validCapturePixelFormat;
        std::vector<cv::Size> _validPreviewResolution;
@@ -88,6 +90,7 @@ private:
        static void captureCompletedCb(void *user_data);
        static bool previewFpsCb(camera_attr_fps_e fps, void *user_data);
        static bool compareSizesDescending(const cv::Size &a, const cv::Size &b);
+       void setPreviewResolutionAndFps(unsigned int fps);
        std::mutex &getMutex()
        {
                return _capture_mutex;
index 69c354b3c1d24d8bc8fe58e43d9975469ea7be4a..aa38e74452dc38098e920a6526b1965b0dd5540b 100644 (file)
@@ -90,17 +90,24 @@ void CameraApiBackend::previewCb(camera_preview_data_s *data, void *user_data)
        if (!context->_observer)
                return;
 
-       if (data->num_of_planes != 3 || data->format != CAMERA_PIXEL_FORMAT_I420) {
+       if (data->format != CAMERA_PIXEL_FORMAT_I420 && data->format != CAMERA_PIXEL_FORMAT_YUYV) {
                SINGLEO_LOGE("Number of planes or pixel format not supported.");
                throw InvalidParameter("Number of planes or pixel format not supported.");
        }
 
        // TODO. consider for other plane type and pixel format support later.
 
-       cv::Mat cv_src(data->height + data->height / 2, data->width, CV_8UC1, data->data.triple_plane.y);
-       cv::Mat cv_dst;
+       SINGLEO_LOGD("width = %d, height = %d, number of planes = %d", data->width, data->height, data->num_of_planes);
 
-       cv::cvtColor(cv_src, cv_dst, cv::COLOR_YUV2BGR_I420);
+       cv::Mat cv_dst {};
+
+       if (data->format == CAMERA_PIXEL_FORMAT_YUYV) {
+               cv::Mat cv_src(data->height, data->width, CV_8UC2, data->data.single_plane.yuv);
+               cv::cvtColor(cv_src, cv_dst, cv::COLOR_YUV2BGR_YUYV);
+       } else {
+               cv::Mat cv_src(data->height + data->height / 2, data->width, CV_8UC1, data->data.triple_plane.y);
+               cv::cvtColor(cv_src, cv_dst, cv::COLOR_YUV2BGR_I420);
+       }
 
        ImageDataType data_type;
 
@@ -175,11 +182,62 @@ bool CameraApiBackend::previewFpsCb(camera_attr_fps_e fps, void *user_data)
        return true;
 }
 
+void CameraApiBackend::setPreviewResolutionAndFps(unsigned int fps)
+{
+       camera_attr_fps_e givenFps = CAMERA_ATTR_FPS_AUTO;
+
+       try {
+               givenFps = _fpsTypeTable.at(fps);
+       } catch (const std::out_of_range &e) {
+               SINGLEO_LOGE("CameraApiBackend: a given fps(%d) is out_of_range.", fps);
+               throw InvalidOperation("CameraApiBackend: a given fps is out_of_range.");
+       }
+
+       auto fps_it = find(_validFps.begin(), _validFps.end(), givenFps);
+       if (fps_it == _validFps.end()) {
+               SINGLEO_LOGE("CameraApiBackend: fps(%d) is not supported.", fps);
+               throw InvalidOperation("CameraApiBackend: fps is not supported.");
+       }
+
+       bool isFpsSupported = false;
+       cv::Size validResolution {};
+
+       for (auto &resolution : _validPreviewResolution) {
+               int ret = camera_set_preview_resolution(_camera, resolution.width, resolution.height);
+               if (ret != CAMERA_ERROR_NONE) {
+                       SINGLEO_LOGE("CameraApiBackend: camera_set_preview_resolution failed. ret: %d", ret);
+                       throw InvalidOperation("CameraApiBackend: camera_set_preview_resolution failed.");
+               }
+
+               ret = camera_attr_set_preview_fps(_camera, givenFps);
+               if (ret == CAMERA_ERROR_NONE) {
+                       isFpsSupported = true;
+                       validResolution = resolution;
+                       break;
+               }
+
+               SINGLEO_LOGW("CameraApiBackend: (%d)fps not supported with %dx%d so retry.", fps, resolution.width,
+                                        resolution.height);
+       }
+
+       if (!isFpsSupported)
+               throw InvalidOperation("CameraApiBackend: fps(%d) is not supported.", fps);
+
+       SINGLEO_LOGD("CameraApiBackend: preview resolution(width: %d, height: %d) has been set with fps(%d)",
+                                validResolution.width, validResolution.height, fps);
+}
+
 void CameraApiBackend::configure(const CameraConfig &config)
 {
        setActiveCameraDevice(config.device_id);
 
-       int ret = camera_foreach_supported_preview_resolution(_camera, previewResolutionCb, this);
+       int ret = camera_attr_foreach_supported_fps(_camera, previewFpsCb, this);
+       if (ret != CAMERA_ERROR_NONE) {
+               SINGLEO_LOGE("CameraApiBackend: camera_attr_foreach_supported_fps failed. ret: %d", ret);
+               throw InvalidOperation("CameraApiBackend: camera_attr_foreach_supported_fps failed.");
+       }
+
+       ret = camera_foreach_supported_preview_resolution(_camera, previewResolutionCb, this);
        if (ret != CAMERA_ERROR_NONE) {
                SINGLEO_LOGE("CameraApiBackend: camera_foreach_supported_preview_resolution failed. ret: %d", ret);
                throw InvalidOperation("CameraApiBackend: camera_foreach_supported_preview_resolution failed.");
@@ -195,14 +253,7 @@ void CameraApiBackend::configure(const CameraConfig &config)
                                 _validPreviewResolution[0].width, _validPreviewResolution[0].height);
 
        // TODO. set user-given resolution with the option string of singleo API later.
-       ret = camera_set_preview_resolution(_camera, _validPreviewResolution[0].width, _validPreviewResolution[0].height);
-       if (ret != CAMERA_ERROR_NONE) {
-               SINGLEO_LOGE("CameraApiBackend: camera_set_preview_resolution failed. ret: %d", ret);
-               throw InvalidOperation("CameraApiBackend: camera_set_preview_resolution failed.");
-       }
-
-       SINGLEO_LOGD("Set camera resolution for capture with width(%d) and height(%d) in default.",
-                                _validCaptureResolution[0].width, _validCaptureResolution[0].height);
+       setPreviewResolutionAndFps(config.fps);
 
        ret = camera_set_capture_resolution(_camera, _validCaptureResolution[0].width, _validCaptureResolution[0].height);
        if (ret != CAMERA_ERROR_NONE) {
@@ -217,14 +268,24 @@ void CameraApiBackend::configure(const CameraConfig &config)
        }
 
        // TODO. read default pixel format from json configuration file later.
-       auto preview_it =
-                       find(_validPreviewPixelFormat.begin(), _validPreviewPixelFormat.end(), _defaultPreviewPixelFormat);
-       if (preview_it == _validPreviewPixelFormat.end()) {
+
+       // Select preview format from the list of supported formats.
+       camera_pixel_format_e previewPixelFormat { CAMERA_PIXEL_FORMAT_INVALID };
+
+       for (auto format : _defaultPreviewPixelFormats) {
+               auto preview_it = find(_validPreviewPixelFormat.begin(), _validPreviewPixelFormat.end(), format);
+               if (preview_it != _validPreviewPixelFormat.end()) {
+                       previewPixelFormat = format;
+                       break;
+               }
+       }
+
+       if (previewPixelFormat == CAMERA_PIXEL_FORMAT_INVALID) {
                SINGLEO_LOGE("Invalid preview pixel format type.");
                throw InvalidOperation("CameraApiBackend: Invalid preview pixel format type.");
        }
 
-       ret = camera_set_preview_format(_camera, _defaultPreviewPixelFormat);
+       ret = camera_set_preview_format(_camera, previewPixelFormat);
        if (ret != CAMERA_ERROR_NONE) {
                SINGLEO_LOGE("CameraApiBackend: camera_set_preview_format failed. ret: %d", ret);
                throw InvalidOperation("CameraApiBackend: camera_set_preview_format failed.");
@@ -237,55 +298,28 @@ void CameraApiBackend::configure(const CameraConfig &config)
        }
 
        // TODO. read default pixel format from json configuration file later.
-       auto capture_it =
-                       find(_validCapturePixelFormat.begin(), _validCapturePixelFormat.end(), _defaultCapturePixelFormat);
-       if (capture_it == _validCapturePixelFormat.end()) {
-               SINGLEO_LOGE("Invalid capture pixel format type.");
-               throw InvalidOperation("CameraApiBackend: Invalid capture pixel format type.");
-       }
-
-       ret = camera_set_capture_format(_camera, _defaultCapturePixelFormat);
-       if (ret != CAMERA_ERROR_NONE) {
-               SINGLEO_LOGE("CameraApiBackend: camera_set_capture_format failed. ret: %d", ret);
-               throw InvalidOperation("CameraApiBackend: camera_set_capture_format failed.");
-       }
 
-       ret = camera_attr_foreach_supported_fps(_camera, previewFpsCb, this);
-       if (ret != CAMERA_ERROR_NONE) {
-               SINGLEO_LOGE("CameraApiBackend: camera_attr_foreach_supported_fps failed. ret: %d", ret);
-               throw InvalidOperation("CameraApiBackend: camera_attr_foreach_supported_fps failed.");
-       }
-
-       camera_attr_fps_e givenFps = CAMERA_ATTR_FPS_AUTO;
+       // Select capture format from the list of supported formats.
+       camera_pixel_format_e capturePixelFormat { CAMERA_PIXEL_FORMAT_INVALID };
 
-       try {
-               givenFps = _fpsTypeTable.at(config.fps);
-       } catch (const std::out_of_range &e) {
-               SINGLEO_LOGE("CameraApiBackend: a given fps(%d) is out_of_range.", config.fps);
-               throw InvalidOperation("CameraApiBackend: a given fps is out_of_range.");
-       }
-
-       auto fps_it = find(_validFps.begin(), _validFps.end(), givenFps);
-       if (fps_it == _validFps.end()) {
-               SINGLEO_LOGE("CameraApiBackend: fps(%d) is not supported.", config.fps);
-               throw InvalidOperation("CameraApiBackend: fps is not supported.");
+       for (auto format : _defaultCapturePixelFormats) {
+               auto preview_it = find(_validCapturePixelFormat.begin(), _validCapturePixelFormat.end(), format);
+               if (preview_it != _validCapturePixelFormat.end()) {
+                       capturePixelFormat = format;
+                       break;
+               }
        }
 
-       ret = camera_attr_set_preview_fps(_camera, givenFps);
-       if (ret != CAMERA_ERROR_NONE) {
-               SINGLEO_LOGE("CameraApiBackend: camera_attr_set_preview_fps failed. ret: %d", ret);
-               throw InvalidOperation("CameraApiBackend: camera_attr_set_preview_fps failed.");
+       if (capturePixelFormat == CAMERA_PIXEL_FORMAT_INVALID) {
+               SINGLEO_LOGE("Invalid capture pixel format type.");
+               throw InvalidOperation("CameraApiBackend: Invalid capture pixel format type.");
        }
 
-       camera_attr_fps_e previewFps;
-
-       ret = camera_attr_get_preview_fps(_camera, &previewFps);
+       ret = camera_set_capture_format(_camera, capturePixelFormat);
        if (ret != CAMERA_ERROR_NONE) {
-               SINGLEO_LOGE("CameraApiBackend: camera_attr_get_preview_fps failed. ret: %d", ret);
-               throw InvalidOperation("CameraApiBackend: camera_attr_get_preview_fps failed.");
+               SINGLEO_LOGE("CameraApiBackend: camera_set_capture_format failed. ret: %d", ret);
+               throw InvalidOperation("CameraApiBackend: camera_set_capture_format failed.");
        }
-
-       SINGLEO_LOGD("CameraApiBackend: previewFps: %d", previewFps);
 }
 
 void CameraApiBackend::captureCb(camera_image_data_s *image, camera_image_data_s *postview,