From d93fba5044e5688df377b8f1087d22b0357c36ba Mon Sep 17 00:00:00 2001 From: chenhb3487 Date: Tue, 11 Jan 2022 10:24:26 +0800 Subject: [PATCH] libcamera: add framerate for request pad src. --- .../0010-add-framerate-from-v4l2.patch | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 package/libcamera/0010-add-framerate-from-v4l2.patch diff --git a/package/libcamera/0010-add-framerate-from-v4l2.patch b/package/libcamera/0010-add-framerate-from-v4l2.patch new file mode 100644 index 00000000..b2a558aa --- /dev/null +++ b/package/libcamera/0010-add-framerate-from-v4l2.patch @@ -0,0 +1,234 @@ +diff -Naur a/include/libcamera/internal/v4l2_videodevice.h libcamera-d6f4abeead1e86d89dc376e8a303849bdb98d5fd/include/libcamera/internal/v4l2_videodevice.h +--- a/include/libcamera/internal/v4l2_videodevice.h 2022-01-10 22:03:08.131869823 +0800 ++++ b/include/libcamera/internal/v4l2_videodevice.h 2022-01-11 10:12:46.551963256 +0800 +@@ -35,6 +35,11 @@ + class MediaDevice; + class MediaEntity; + ++struct V4L2Framerate { ++ uint32_t num = 0; ++ uint32_t denom = 0; ++}; ++ + struct V4L2Capability final : v4l2_capability { + const char *driver() const + { +@@ -215,7 +220,7 @@ + + static std::unique_ptr + fromEntityName(const MediaDevice *media, const std::string &entity); +- ++ std::vector getFramerates(uint32_t pixelformat, uint32_t width, uint32_t height); + protected: + std::string logPrefix() const override; + +diff -Naur a/include/libcamera/stream.h b/include/libcamera/stream.h +--- a/include/libcamera/stream.h 2022-01-10 22:03:08.131869823 +0800 ++++ b/include/libcamera/stream.h 2022-01-11 10:12:56.020027708 +0800 +@@ -36,6 +36,11 @@ + std::map> formats_; + }; + ++struct Framerate { ++ uint32_t num = 0; ++ uint32_t denom = 0; ++}; ++ + struct StreamConfiguration { + StreamConfiguration(); + StreamConfiguration(const StreamFormats &formats); +@@ -51,11 +56,15 @@ + void setStream(Stream *stream) { stream_ = stream; } + const StreamFormats &formats() const { return formats_; } + ++ void setframeRates(std::vector framerates) { rates = framerates; } ++ const std::vector getframeRates() const { return rates; } ++ + std::string toString() const; + + private: + Stream *stream_; + StreamFormats formats_; ++ std::vector rates; + }; + + enum StreamRole { +diff -Naur a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp +--- a/src/gstreamer/gstlibcamera-utils.cpp 2022-01-10 22:03:08.135869864 +0800 ++++ b/src/gstreamer/gstlibcamera-utils.cpp 2022-01-11 10:13:11.952135908 +0800 +@@ -140,10 +140,18 @@ + "height", G_TYPE_INT, stream_cfg.size.height, + nullptr); + +- // Add framerate negotiation support +- // the range will be [ 0/1, 2147483647/1 ] as there is not any args +- // required from driver for the time being. +- gst_structure_set(s, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); ++ std::vector rates = stream_cfg.getframeRates(); ++ guint index = 0; ++ for (libcamera::Framerate it : rates) { ++ libcamera::Framerate rate = it; ++ gst_structure_set (s, "framerate", GST_TYPE_FRACTION, rate.denom, rate.num, NULL); ++ //truncate rates. only remain the first one. ++ if ( index == 0) ++ { ++ break; ++ } ++ index++; ++ } + + gst_caps_append_structure(caps, s); + +diff -Naur a/src/libcamera/pipeline/starfive/starfive.cpp b/src/libcamera/pipeline/starfive/starfive.cpp +--- a/src/libcamera/pipeline/starfive/starfive.cpp 2022-01-10 22:03:08.139869906 +0800 ++++ b/src/libcamera/pipeline/starfive/starfive.cpp 2022-01-11 10:13:31.200266219 +0800 +@@ -44,6 +44,9 @@ + + #define PIPELINE_CONFIG_FILENAME "/etc/starfive/sensors_pipeline.yaml" + ++#define DEFAULT_FRAMERATE_NUM 25; ++#define DEFAULT_FRAMERATE_DENOM 1; ++ + namespace { + + typedef enum { +@@ -226,6 +229,8 @@ + std::vector sensorSizes() const; + std::vector sensorFormats() const; + std::vector videoFormats() const; ++ std::vector videoFrameRates(unsigned int pixelformat, unsigned int width, unsigned int height) const; ++ + void paramsFilled(unsigned int id){} + int ispLoadFW(const char *filename); + +@@ -270,6 +275,24 @@ + return formats; + } + ++std::vector StarFiveCameraData::videoFrameRates(unsigned int pixelformat, unsigned int width, unsigned int height) const ++{ ++ if (!video_) ++ return {}; ++ ++ std::vector framerates; ++ for (auto it : video_->getFramerates(pixelformat, width, height)) { ++ V4L2Framerate v4l2_framerate = (V4L2Framerate)it; ++ libcamera::Framerate rate; ++ rate.num = v4l2_framerate.num; ++ rate.denom = v4l2_framerate.denom; ++ LOG(STARFIVE, Debug) << "videoFrameRates framerate: rate.num=" << rate.num << " rate.denom= " << rate.denom; ++ framerates.push_back(rate); ++ } ++ ++ return framerates; ++} ++ + std::vector StarFiveCameraData::sensorFormats() const + { + if (!sensor_) +@@ -481,6 +504,20 @@ + cfg.size.height = std::max(OUTPUT_MIN_SIZE.height, + std::min(OUTPUT_MAX_SIZE.height, cfg.size.height)); + ++ std::vector rates; ++ rates = data_->videoFrameRates(cfg.pixelFormat,size.width, size.height); ++ if (rates.size() > 0){ ++ cfg.setframeRates(rates); ++ } else { ++ LOG(STARFIVE, Debug) ++ << "fail to obtian framerate, use default one "; ++ Framerate rate; ++ rate.num = DEFAULT_FRAMERATE_NUM; ++ rate.denom = DEFAULT_FRAMERATE_DENOM; ++ rates.emplace_back(rate); ++ cfg.setframeRates(rates); ++ } ++ + if (cfg.size != size) { + LOG(STARFIVE, Debug) + << "Adjusting size to " << cfg.size.toString(); +diff -Naur a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp +--- a/src/libcamera/v4l2_videodevice.cpp 2022-01-10 22:03:08.135869864 +0800 ++++ b/src/libcamera/v4l2_videodevice.cpp 2022-01-11 10:13:42.444342141 +0800 +@@ -31,6 +31,7 @@ + #include "libcamera/internal/framebuffer.h" + #include "libcamera/internal/media_device.h" + #include "libcamera/internal/media_object.h" ++#include + + /** + * \file v4l2_videodevice.h +@@ -1847,6 +1848,73 @@ + return std::make_unique(mediaEntity); + } + ++std::vector V4L2VideoDevice::getFramerates(uint32_t pixelformat, uint32_t width, uint32_t height) ++{ ++ struct v4l2_frmivalenum ival; ++ uint32_t num, denom; ++ ++ memset (&ival, 0, sizeof (struct v4l2_frmivalenum)); ++ ival.index = 0; ++ ival.pixel_format = pixelformat; ++ ival.width = width; ++ ival.height = height; ++ std::vector rates; ++ LOG(V4L2, Debug) << "getFramerates: width: " << width << " height: " << height << " pixelformat " << pixelformat; ++ ++ if (ioctl (VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0){ ++ LOG(V4L2, Error) << "fail to ioctl: VIDIOC_ENUM_FRAMEINTERVALS"; ++ goto enum_frameintervals_failed; ++ } ++ ++ if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { ++ struct V4L2Framerate rate; ++ do { ++ num = ival.discrete.numerator; ++ denom = ival.discrete.denominator; ++ ++ if (num > INT_MAX || denom > INT_MAX) { ++ /* let us hope we don't get here... */ ++ LOG(V4L2, Error) << "num or denom is beyond INT_MAX"; ++ goto enum_frameintervals_failed; ++ } ++ ++ // /* swap to get the framerate */ ++ // gst_value_set_fraction (&rate, denom, num); ++ rate.denom = denom; ++ rate.num = num; ++ LOG(V4L2, Debug) << "gstFramerates adding discrete framerate: " << denom << "/" << num; ++ rates.emplace_back(rate); ++ ival.index++; ++ } while (ioctl (VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0); ++ } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE){ ++ //TODO ++ goto enum_frameintervals_unimplemented; ++ } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { ++ num = ival.stepwise.min.numerator; ++ denom = ival.stepwise.min.denominator; ++ if (num > INT_MAX || denom > INT_MAX) { ++ LOG(V4L2, Error) << "continuous frame interval: num or denom is beyond INT_MAX"; ++ goto enum_frameintervals_failed; ++ } ++ ++ struct V4L2Framerate rate; ++ rate.denom = denom; ++ rate.num = num; ++ LOG(V4L2, Debug) << "gstFramerates continuous frame interval: " << denom << "/" <