diff options
-rw-r--r-- | src/libcamera/include/v4l2_videodevice.h | 39 | ||||
-rw-r--r-- | src/libcamera/pipeline/uvcvideo.cpp | 4 | ||||
-rw-r--r-- | src/libcamera/v4l2_videodevice.cpp | 91 |
3 files changed, 109 insertions, 25 deletions
diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h index bc1c6a4d..2a380c0e 100644 --- a/src/libcamera/include/v4l2_videodevice.h +++ b/src/libcamera/include/v4l2_videodevice.h @@ -149,10 +149,33 @@ private: unsigned int missCounter_; }; +class V4L2PixelFormat +{ +public: + V4L2PixelFormat() + : fourcc_(0) + { + } + + V4L2PixelFormat(uint32_t fourcc) + : fourcc_(fourcc) + { + } + + bool isValid() const { return fourcc_ != 0; } + uint32_t fourcc() const { return fourcc_; } + operator uint32_t() const { return fourcc_; } + + std::string toString() const; + +private: + uint32_t fourcc_; +}; + class V4L2DeviceFormat { public: - uint32_t fourcc; + V4L2PixelFormat fourcc; Size size; struct { @@ -184,7 +207,7 @@ public: int getFormat(V4L2DeviceFormat *format); int setFormat(V4L2DeviceFormat *format); - ImageFormats formats(); + std::map<V4L2PixelFormat, std::vector<SizeRange>> formats(); int setCrop(Rectangle *rect); int setCompose(Rectangle *rect); @@ -205,10 +228,10 @@ public: static V4L2VideoDevice *fromEntityName(const MediaDevice *media, const std::string &entity); - static PixelFormat toPixelFormat(uint32_t v4l2Fourcc); - uint32_t toV4L2Fourcc(const PixelFormat &pixelFormat); - static uint32_t toV4L2Fourcc(const PixelFormat &pixelFormat, - bool multiplanar); + static PixelFormat toPixelFormat(V4L2PixelFormat v4l2Fourcc); + V4L2PixelFormat toV4L2Fourcc(const PixelFormat &pixelFormat); + static V4L2PixelFormat toV4L2Fourcc(const PixelFormat &pixelFormat, + bool multiplanar); protected: std::string logPrefix() const; @@ -223,8 +246,8 @@ private: int getFormatSingleplane(V4L2DeviceFormat *format); int setFormatSingleplane(V4L2DeviceFormat *format); - std::vector<unsigned int> enumPixelformats(); - std::vector<SizeRange> enumSizes(unsigned int pixelFormat); + std::vector<V4L2PixelFormat> enumPixelformats(); + std::vector<SizeRange> enumSizes(V4L2PixelFormat pixelFormat); int setSelection(unsigned int target, Rectangle *rect); diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 73114975..67750fbc 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -154,8 +154,8 @@ CameraConfiguration *PipelineHandlerUVC::generateConfiguration(Camera *camera, if (roles.empty()) return config; - std::map<unsigned int, std::vector<SizeRange>> v4l2Formats = - data->video_->formats().data(); + std::map<V4L2PixelFormat, std::vector<SizeRange>> v4l2Formats = + data->video_->formats(); std::map<PixelFormat, std::vector<SizeRange>> deviceFormats; std::transform(v4l2Formats.begin(), v4l2Formats.end(), std::inserter(deviceFormats, deviceFormats.begin()), diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 56251a46..1c60014c 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -279,6 +279,65 @@ bool V4L2BufferCache::Entry::operator==(const FrameBuffer &buffer) const } /** + * \class V4L2PixelFormat + * \brief V4L2 pixel format FourCC wrapper + * + * The V4L2PixelFormat class describes the pixel format of a V4L2 buffer. It + * wraps the V4L2 numerical FourCC, and shall be used in all APIs that deal with + * V4L2 pixel formats. Its purpose is to prevent unintentional confusion of + * V4L2 and DRM FourCCs in code by catching implicit conversion attempts at + * compile time. + */ + +/** + * \fn V4L2PixelFormat::V4L2PixelFormat() + * \brief Construct a V4L2PixelFormat with an invalid format + * + * V4L2PixelFormat instances constructed with the default constructor are + * invalid, calling the isValid() function returns false. + */ + +/** + * \fn V4L2PixelFormat::V4L2PixelFormat(uint32_t fourcc) + * \brief Construct a V4L2PixelFormat from a FourCC value + * \param[in] fourcc The pixel format FourCC numerical value + */ + +/** + * \fn bool V4L2PixelFormat::isValid() const + * \brief Check if the pixel format is valid + * + * V4L2PixelFormat instances constructed with the default constructor are + * invalid. Instances constructed with a FourCC defined in the V4L2 API are + * valid. The behaviour is undefined otherwise. + * + * \return True if the pixel format is valid, false otherwise + */ + +/** + * \fn uint32_t V4L2PixelFormat::fourcc() const + * \brief Retrieve the pixel format FourCC numerical value + * \return The pixel format FourCC numerical value + */ + +/** + * \fn V4L2PixelFormat::operator uint32_t() const + * \brief Convert to the pixel format FourCC numerical value + * \return The pixel format FourCC numerical value + */ + +/** + * \brief Assemble and return a string describing the pixel format + * \return A string describing the pixel format + */ +std::string V4L2PixelFormat::toString() const +{ + char str[11]; + snprintf(str, 11, "0x%08x", fourcc_); + return str; +} + +/** * \class V4L2DeviceFormat * \brief The V4L2 video device image format and sizes * @@ -386,7 +445,7 @@ bool V4L2BufferCache::Entry::operator==(const FrameBuffer &buffer) const const std::string V4L2DeviceFormat::toString() const { std::stringstream ss; - ss << size.toString() << "-" << utils::hex(fourcc); + ss << size.toString() << "-" << fourcc.toString(); return ss.str(); } @@ -901,29 +960,31 @@ int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format) * * \return A list of the supported video device formats */ -ImageFormats V4L2VideoDevice::formats() +std::map<V4L2PixelFormat, std::vector<SizeRange>> V4L2VideoDevice::formats() { - ImageFormats formats; + std::map<V4L2PixelFormat, std::vector<SizeRange>> formats; - for (unsigned int pixelformat : enumPixelformats()) { - std::vector<SizeRange> sizes = enumSizes(pixelformat); + for (V4L2PixelFormat pixelFormat : enumPixelformats()) { + std::vector<SizeRange> sizes = enumSizes(pixelFormat); if (sizes.empty()) return {}; - if (formats.addFormat(pixelformat, sizes)) { + if (formats.find(pixelFormat) != formats.end()) { LOG(V4L2, Error) << "Could not add sizes for pixel format " - << pixelformat; + << pixelFormat; return {}; } + + formats.emplace(pixelFormat, sizes); } return formats; } -std::vector<unsigned int> V4L2VideoDevice::enumPixelformats() +std::vector<V4L2PixelFormat> V4L2VideoDevice::enumPixelformats() { - std::vector<unsigned int> formats; + std::vector<V4L2PixelFormat> formats; int ret; for (unsigned int index = 0; ; index++) { @@ -948,7 +1009,7 @@ std::vector<unsigned int> V4L2VideoDevice::enumPixelformats() return formats; } -std::vector<SizeRange> V4L2VideoDevice::enumSizes(unsigned int pixelFormat) +std::vector<SizeRange> V4L2VideoDevice::enumSizes(V4L2PixelFormat pixelFormat) { std::vector<SizeRange> sizes; int ret; @@ -1563,7 +1624,7 @@ V4L2VideoDevice *V4L2VideoDevice::fromEntityName(const MediaDevice *media, * \param[in] v4l2Fourcc The V4L2 pixel format (V4L2_PIX_FORMAT_*) * \return The PixelFormat corresponding to \a v4l2Fourcc */ -PixelFormat V4L2VideoDevice::toPixelFormat(uint32_t v4l2Fourcc) +PixelFormat V4L2VideoDevice::toPixelFormat(V4L2PixelFormat v4l2Fourcc) { switch (v4l2Fourcc) { /* RGB formats. */ @@ -1612,7 +1673,7 @@ PixelFormat V4L2VideoDevice::toPixelFormat(uint32_t v4l2Fourcc) libcamera::_log(__FILE__, __LINE__, _LOG_CATEGORY(V4L2)(), LogError).stream() << "Unsupported V4L2 pixel format " - << utils::hex(v4l2Fourcc); + << v4l2Fourcc.toString(); return PixelFormat(); } } @@ -1628,7 +1689,7 @@ PixelFormat V4L2VideoDevice::toPixelFormat(uint32_t v4l2Fourcc) * * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat */ -uint32_t V4L2VideoDevice::toV4L2Fourcc(const PixelFormat &pixelFormat) +V4L2PixelFormat V4L2VideoDevice::toV4L2Fourcc(const PixelFormat &pixelFormat) { return V4L2VideoDevice::toV4L2Fourcc(pixelFormat, caps_.isMultiplanar()); } @@ -1646,8 +1707,8 @@ uint32_t V4L2VideoDevice::toV4L2Fourcc(const PixelFormat &pixelFormat) * * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat */ -uint32_t V4L2VideoDevice::toV4L2Fourcc(const PixelFormat &pixelFormat, - bool multiplanar) +V4L2PixelFormat V4L2VideoDevice::toV4L2Fourcc(const PixelFormat &pixelFormat, + bool multiplanar) { switch (pixelFormat) { /* RGB formats. */ |