|
@@ -1,41 +1,36 @@
|
|
|
package v4l2
|
|
|
|
|
|
+// #include <linux/videodev2.h>
|
|
|
+import "C"
|
|
|
+
|
|
|
import (
|
|
|
"fmt"
|
|
|
"unsafe"
|
|
|
)
|
|
|
|
|
|
-// FourCCEncoding represents the four character encoding value
|
|
|
-type FourCCEncoding = uint32
|
|
|
+// FourCCType represents the four character encoding value
|
|
|
+type FourCCType = uint32
|
|
|
|
|
|
// Some Predefined pixel format definitions
|
|
|
// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt.html
|
|
|
// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L518
|
|
|
var (
|
|
|
- PixFmtRGB24 = fourcc('R', 'G', 'B', '3') // V4L2_PIX_FMT_RGB24
|
|
|
- PixFmtGrey = fourcc('G', 'R', 'E', 'Y') // V4L2_PIX_FMT_GREY
|
|
|
- PixelFmtYUYV = fourcc('Y', 'U', 'Y', 'V') // V4L2_PIX_FMT_YUYV
|
|
|
- PixelFmtYYUV = fourcc('Y', 'Y', 'U', 'V') // V4L2_PIX_FMT_YYUV
|
|
|
- PixelFmtYVYU = fourcc('Y', 'V', 'Y', 'U') // V4L2_PIX_FMT_YVYU
|
|
|
- PixelFmtUYVY = fourcc('U', 'Y', 'V', 'Y') // V4L2_PIX_FMT_UYVY
|
|
|
- PixelFmtVYUY = fourcc('V', 'Y', 'U', 'Y') // V4L2_PIX_FMT_VYUY
|
|
|
- PixelFmtMJPEG = fourcc('M', 'J', 'P', 'G') // V4L2_PIX_FMT_MJPEG
|
|
|
- PixelFmtJPEG = fourcc('J', 'P', 'E', 'G') // V4L2_PIX_FMT_JPEG
|
|
|
- PixelFmtMPEG = fourcc('M', 'P', 'E', 'G') // V4L2_PIX_FMT_MPEG
|
|
|
- PixelFmtH264 = fourcc('H', '2', '6', '4') // V4L2_PIX_FMT_H264
|
|
|
- PixelFmtMPEG4 = fourcc('M', 'P', 'G', '4') // V4L2_PIX_FMT_MPEG4
|
|
|
+ PixFmtRGB24 FourCCType = C.V4L2_PIX_FMT_RGB24
|
|
|
+ PixFmtGrey FourCCType = C.V4L2_PIX_FMT_GREY
|
|
|
+ PixelFmtYUYV FourCCType = C.V4L2_PIX_FMT_YUYV
|
|
|
+ PixelFmtYYUV FourCCType = C.V4L2_PIX_FMT_YYUV
|
|
|
+ PixelFmtYVYU FourCCType = C.V4L2_PIX_FMT_YVYU
|
|
|
+ PixelFmtUYVY FourCCType = C.V4L2_PIX_FMT_UYVY
|
|
|
+ PixelFmtVYUY FourCCType = C.V4L2_PIX_FMT_VYUY
|
|
|
+ PixelFmtMJPEG FourCCType = C.V4L2_PIX_FMT_MJPEG
|
|
|
+ PixelFmtJPEG FourCCType = C.V4L2_PIX_FMT_JPEG
|
|
|
+ PixelFmtMPEG FourCCType = C.V4L2_PIX_FMT_MPEG
|
|
|
+ PixelFmtH264 FourCCType = C.V4L2_PIX_FMT_H264
|
|
|
+ PixelFmtMPEG4 FourCCType = C.V4L2_PIX_FMT_MPEG4
|
|
|
)
|
|
|
|
|
|
-// fourcc implements the four character code encoding found
|
|
|
-// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L81
|
|
|
-// #define v4l2_fourcc(a, b, c, d)\
|
|
|
-// ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
|
|
|
-func fourcc(a, b, c, d uint32) FourCCEncoding {
|
|
|
- return (a | b<<8) | c<<16 | d<<24
|
|
|
-}
|
|
|
-
|
|
|
-// PixelFormats provides a map of FourCC encoding description
|
|
|
-var PixelFormats = map[FourCCEncoding]string{
|
|
|
+// PixelFormats provides a map of FourCCType encoding description
|
|
|
+var PixelFormats = map[FourCCType]string{
|
|
|
PixFmtRGB24: "24-bit RGB 8-8-8",
|
|
|
PixFmtGrey: "8-bit Greyscale",
|
|
|
PixelFmtYUYV: "YUYV 4:2:2",
|
|
@@ -47,7 +42,7 @@ var PixelFormats = map[FourCCEncoding]string{
|
|
|
}
|
|
|
|
|
|
// IsPixYUVEncoded returns true if the pixel format is a chrome+luminance YUV format
|
|
|
-func IsPixYUVEncoded(pixFmt FourCCEncoding) bool {
|
|
|
+func IsPixYUVEncoded(pixFmt FourCCType) bool {
|
|
|
switch pixFmt {
|
|
|
case
|
|
|
PixelFmtYUYV,
|
|
@@ -66,24 +61,24 @@ func IsPixYUVEncoded(pixFmt FourCCEncoding) bool {
|
|
|
type ColorspaceType = uint32
|
|
|
|
|
|
const (
|
|
|
- ColorspaceTypeDefault ColorspaceType = iota //V4L2_COLORSPACE_DEFAULT
|
|
|
- ColorspaceSMPTE170M //V4L2_COLORSPACE_SMPTE170M
|
|
|
- ColorspaceSMPTE240M // V4L2_COLORSPACE_SMPTE240M
|
|
|
- ColorspaceREC709 // V4L2_COLORSPACE_REC709
|
|
|
- ColorspaceBT878 // V4L2_COLORSPACE_BT878 (absolete)
|
|
|
- Colorspace470SystemM // V4L2_COLORSPACE_470_SYSTEM_M (absolete)
|
|
|
- Colorspace470SystemBG // V4L2_COLORSPACE_470_SYSTEM_BG
|
|
|
- ColorspaceJPEG // V4L2_COLORSPACE_JPEG
|
|
|
- ColorspaceSRGB // V4L2_COLORSPACE_SRGB
|
|
|
- ColorspaceOPRGB // V4L2_COLORSPACE_OPRGB
|
|
|
- ColorspaceBT2020 // V4L2_COLORSPACE_BT2020
|
|
|
- ColorspaceRaw // V4L2_COLORSPACE_RAW
|
|
|
- ColorspaceDCIP3 // V4L2_COLORSPACE_DCI_P3
|
|
|
+ ColorspaceDefault ColorspaceType = C.V4L2_COLORSPACE_DEFAULT
|
|
|
+ ColorspaceSMPTE170M ColorspaceType = C.V4L2_COLORSPACE_SMPTE170M
|
|
|
+ ColorspaceSMPTE240M ColorspaceType = C.V4L2_COLORSPACE_SMPTE240M
|
|
|
+ ColorspaceREC709 ColorspaceType = C.V4L2_COLORSPACE_REC709
|
|
|
+ ColorspaceBT878 ColorspaceType = C.V4L2_COLORSPACE_BT878 //(absolete)
|
|
|
+ Colorspace470SystemM ColorspaceType = C.V4L2_COLORSPACE_470_SYSTEM_M //(absolete)
|
|
|
+ Colorspace470SystemBG ColorspaceType = C.V4L2_COLORSPACE_470_SYSTEM_BG
|
|
|
+ ColorspaceJPEG ColorspaceType = C.V4L2_COLORSPACE_JPEG
|
|
|
+ ColorspaceSRGB ColorspaceType = C.V4L2_COLORSPACE_SRGB
|
|
|
+ ColorspaceOPRGB ColorspaceType = C.V4L2_COLORSPACE_OPRGB
|
|
|
+ ColorspaceBT2020 ColorspaceType = C.V4L2_COLORSPACE_BT2020
|
|
|
+ ColorspaceRaw ColorspaceType = C.V4L2_COLORSPACE_RAW
|
|
|
+ ColorspaceDCIP3 ColorspaceType = C.V4L2_COLORSPACE_DCI_P3
|
|
|
)
|
|
|
|
|
|
// Colorspaces is a map of colorspace to its respective description
|
|
|
var Colorspaces = map[ColorspaceType]string{
|
|
|
- ColorspaceTypeDefault: "Default",
|
|
|
+ ColorspaceDefault: "Default",
|
|
|
ColorspaceREC709: "Rec. 709",
|
|
|
Colorspace470SystemBG: "470 System BG",
|
|
|
ColorspaceJPEG: "JPEG",
|
|
@@ -100,14 +95,14 @@ var Colorspaces = map[ColorspaceType]string{
|
|
|
type YCbCrEncodingType = uint32
|
|
|
|
|
|
const (
|
|
|
- YCbCrEncodingDefault YCbCrEncodingType = iota // V4L2_YCBCR_ENC_DEFAULT
|
|
|
- YCbCrEncoding601 // V4L2_YCBCR_ENC_601
|
|
|
- YCbCrEncoding709 // V4L2_YCBCR_ENC_709
|
|
|
- YCbCrEncodingXV601 // V4L2_YCBCR_ENC_XV601
|
|
|
- YCbCrEncodingXV709 // V4L2_YCBCR_ENC_XV709
|
|
|
- _ // V4L2_YCBCR_ENC_SYCC (absolete)
|
|
|
- YCbCrEncodingBT2020 // V4L2_YCBCR_ENC_BT2020
|
|
|
- YCbCrEncodingBT2020ConstLum // V4L2_YCBCR_ENC_BT2020_CONST_LUM
|
|
|
+ YCbCrEncodingDefault YCbCrEncodingType = C.V4L2_YCBCR_ENC_DEFAULT
|
|
|
+ YCbCrEncoding601 YCbCrEncodingType = C.V4L2_YCBCR_ENC_601
|
|
|
+ YCbCrEncoding709 YCbCrEncodingType = C.V4L2_YCBCR_ENC_709
|
|
|
+ YCbCrEncodingXV601 YCbCrEncodingType = C.V4L2_YCBCR_ENC_XV601
|
|
|
+ YCbCrEncodingXV709 YCbCrEncodingType = C.V4L2_YCBCR_ENC_XV709
|
|
|
+ _ YCbCrEncodingType = C.V4L2_YCBCR_ENC_SYCC //(absolete)
|
|
|
+ YCbCrEncodingBT2020 YCbCrEncodingType = C.V4L2_YCBCR_ENC_BT2020
|
|
|
+ YCbCrEncodingBT2020ConstLum YCbCrEncodingType = C.V4L2_YCBCR_ENC_BT2020_CONST_LUM
|
|
|
)
|
|
|
|
|
|
var YCbCrEncodings = map[YCbCrEncodingType]string{
|
|
@@ -139,8 +134,8 @@ func ColorspaceToYCbCrEnc(cs ColorspaceType) YCbCrEncodingType {
|
|
|
type HSVEncodingType = YCbCrEncodingType
|
|
|
|
|
|
const (
|
|
|
- HSVEncoding180 = HSVEncodingType(128) // V4L2_HSV_ENC_180
|
|
|
- HSVEncoding256 = HSVEncodingType(129) // V4L2_HSV_ENC_256
|
|
|
+ HSVEncoding180 HSVEncodingType = C.V4L2_HSV_ENC_180
|
|
|
+ HSVEncoding256 HSVEncodingType = C.V4L2_HSV_ENC_256
|
|
|
)
|
|
|
|
|
|
// QuantizationType (v4l2_quantization)
|
|
@@ -149,9 +144,9 @@ const (
|
|
|
type QuantizationType = uint32
|
|
|
|
|
|
const (
|
|
|
- QuantizationDefault QuantizationType = iota // V4L2_QUANTIZATION_DEFAULT
|
|
|
- QuantizationFullRange // V4L2_QUANTIZATION_FULL_RANGE
|
|
|
- QuantizationLimitedRange // V4L2_QUANTIZATION_LIM_RANGE
|
|
|
+ QuantizationDefault QuantizationType = C.V4L2_QUANTIZATION_DEFAULT
|
|
|
+ QuantizationFullRange QuantizationType = C.V4L2_QUANTIZATION_FULL_RANGE
|
|
|
+ QuantizationLimitedRange QuantizationType = C.V4L2_QUANTIZATION_LIM_RANGE
|
|
|
)
|
|
|
|
|
|
var Quantizations = map[QuantizationType]string{
|
|
@@ -176,14 +171,14 @@ func ColorspaceToQuantization(cs ColorspaceType) QuantizationType {
|
|
|
type XferFunctionType = uint32
|
|
|
|
|
|
const (
|
|
|
- XferFuncDefault XferFunctionType = iota // V4L2_XFER_FUNC_DEFAULT = 0
|
|
|
- XferFunc709 // V4L2_XFER_FUNC_709 = 1,
|
|
|
- XferFuncSRGB // V4L2_XFER_FUNC_SRGB = 2,
|
|
|
- XferFuncOpRGB // V4L2_XFER_FUNC_OPRGB = 3,
|
|
|
- XferFuncSMPTE240M // V4L2_XFER_FUNC_SMPTE240M = 4,
|
|
|
- XferFuncNone // V4L2_XFER_FUNC_NONE = 5,
|
|
|
- XferFuncDCIP3 // V4L2_XFER_FUNC_DCI_P3 = 6,
|
|
|
- XferFuncSMPTE2084 // V4L2_XFER_FUNC_SMPTE2084 = 7,
|
|
|
+ XferFuncDefault XferFunctionType = C.V4L2_XFER_FUNC_DEFAULT
|
|
|
+ XferFunc709 XferFunctionType = C.V4L2_XFER_FUNC_709
|
|
|
+ XferFuncSRGB XferFunctionType = C.V4L2_XFER_FUNC_SRGB
|
|
|
+ XferFuncOpRGB XferFunctionType = C.V4L2_XFER_FUNC_OPRGB
|
|
|
+ XferFuncSMPTE240M XferFunctionType = C.V4L2_XFER_FUNC_SMPTE240M
|
|
|
+ XferFuncNone XferFunctionType = C.V4L2_XFER_FUNC_NONE
|
|
|
+ XferFuncDCIP3 XferFunctionType = C.V4L2_XFER_FUNC_DCI_P3
|
|
|
+ XferFuncSMPTE2084 XferFunctionType = C.V4L2_XFER_FUNC_SMPTE2084
|
|
|
)
|
|
|
|
|
|
var XferFunctions = map[XferFunctionType]string{
|
|
@@ -223,16 +218,16 @@ func ColorspaceToXferFunc(cs ColorspaceType) XferFunctionType {
|
|
|
type FieldType = uint32
|
|
|
|
|
|
const (
|
|
|
- FieldAny FieldType = iota // V4L2_FIELD_ANY
|
|
|
- FieldNone // V4L2_FIELD_NONE
|
|
|
- FieldTop // V4L2_FIELD_TOP
|
|
|
- FieldBottom // V4L2_FIELD_BOTTOM
|
|
|
- FieldInterlaced // V4L2_FIELD_INTERLACED
|
|
|
- FieldSequentialTopBottom // V4L2_FIELD_SEQ_TB
|
|
|
- FieldSequentialBottomTop // V4L2_FIELD_SEQ_BT
|
|
|
- FieldAlternate // V4L2_FIELD_ALTERNATE
|
|
|
- FieldInterlacedTopBottom // V4L2_FIELD_INTERLACED_TB
|
|
|
- FieldInterlacedBottomTop // V4L2_FIELD_INTERLACED_BT
|
|
|
+ FieldAny FieldType = C.V4L2_FIELD_ANY
|
|
|
+ FieldNone FieldType = C.V4L2_FIELD_NONE
|
|
|
+ FieldTop FieldType = C.V4L2_FIELD_TOP
|
|
|
+ FieldBottom FieldType = C.V4L2_FIELD_BOTTOM
|
|
|
+ FieldInterlaced FieldType = C.V4L2_FIELD_INTERLACED
|
|
|
+ FieldSequentialTopBottom FieldType = C.V4L2_FIELD_SEQ_TB
|
|
|
+ FieldSequentialBottomTop FieldType = C.V4L2_FIELD_SEQ_BT
|
|
|
+ FieldAlternate FieldType = C.V4L2_FIELD_ALTERNATE
|
|
|
+ FieldInterlacedTopBottom FieldType = C.V4L2_FIELD_INTERLACED_TB
|
|
|
+ FieldInterlacedBottomTop FieldType = C.V4L2_FIELD_INTERLACED_BT
|
|
|
)
|
|
|
|
|
|
// Fields is a map of FieldType description
|
|
@@ -249,13 +244,13 @@ var Fields = map[FieldType]string{
|
|
|
FieldInterlacedBottomTop: "interlaced bottom-top",
|
|
|
}
|
|
|
|
|
|
-// PixFormat (v4l2_pix_format)
|
|
|
+// PixFormat contains video image format from v4l2_pix_format.
|
|
|
// https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/pixfmt-002.html?highlight=v4l2_pix_format
|
|
|
// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L496
|
|
|
type PixFormat struct {
|
|
|
Width uint32
|
|
|
Height uint32
|
|
|
- PixelFormat FourCCEncoding
|
|
|
+ PixelFormat FourCCType
|
|
|
Field FieldType
|
|
|
BytesPerLine uint32
|
|
|
SizeImage uint32
|
|
@@ -263,6 +258,7 @@ type PixFormat struct {
|
|
|
Priv uint32
|
|
|
Flags uint32
|
|
|
YcbcrEnc YCbCrEncodingType
|
|
|
+ HSVEnc HSVEncodingType
|
|
|
Quantization QuantizationType
|
|
|
XferFunc XferFunctionType
|
|
|
}
|
|
@@ -282,58 +278,43 @@ func (f PixFormat) String() string {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-// v4l2Format (v4l2_format)
|
|
|
-// https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/vidioc-g-fmt.html?highlight=v4l2_format
|
|
|
-// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L2331
|
|
|
-//
|
|
|
-// field fmt is a union, thus it's constructed as an appropriately sized array:
|
|
|
-//
|
|
|
-// struct v4l2_format {
|
|
|
-// __u32 type;
|
|
|
-// union {
|
|
|
-// struct v4l2_pix_format pix;
|
|
|
-// struct v4l2_pix_format_mplane pix_mp;
|
|
|
-// struct v4l2_window win;
|
|
|
-// struct v4l2_vbi_format vbi;
|
|
|
-// struct v4l2_sliced_vbi_format sliced;
|
|
|
-// struct v4l2_sdr_format sdr;
|
|
|
-// struct v4l2_meta_format meta;
|
|
|
-// __u8 raw_data[200]; /* user-defined */
|
|
|
-// } fmt;
|
|
|
-// };
|
|
|
-type v4l2Format struct {
|
|
|
- StreamType uint32
|
|
|
- fmt [200]byte
|
|
|
-}
|
|
|
-
|
|
|
-// getPixFormat returns the PixFormat by casting the pointer to the union type
|
|
|
-func (f *v4l2Format) getPixFormat() PixFormat {
|
|
|
- pixfmt := (*PixFormat)(unsafe.Pointer(&f.fmt[0]))
|
|
|
- return *pixfmt
|
|
|
-}
|
|
|
-
|
|
|
-// setPixFormat sets the PixFormat by casting the pointer to the fmt union and set its value
|
|
|
-func (f *v4l2Format) setPixFormat(newPix PixFormat) {
|
|
|
- f.fmt = *(*[200]byte)(unsafe.Pointer(&newPix))
|
|
|
-}
|
|
|
-
|
|
|
-// GetPixFormat retrieves pixel information for the specified driver
|
|
|
-// See https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/vidioc-g-fmt.html#ioctl-vidioc-g-fmt-vidioc-s-fmt-vidioc-try-fmt
|
|
|
+// GetPixFormat retrieves pixel information for the specified driver (via v4l2_format and v4l2_pix_format)
|
|
|
+// See https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L2331
|
|
|
+// and https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/vidioc-g-fmt.html#ioctl-vidioc-g-fmt-vidioc-s-fmt-vidioc-try-fmt
|
|
|
func GetPixFormat(fd uintptr) (PixFormat, error) {
|
|
|
- format := &v4l2Format{StreamType: BufTypeVideoCapture}
|
|
|
- if err := Send(fd, VidiocGetFormat, uintptr(unsafe.Pointer(format))); err != nil {
|
|
|
+ var v4l2Format C.struct_v4l2_format
|
|
|
+ v4l2Format._type = C.uint(BufTypeVideoCapture)
|
|
|
+
|
|
|
+ if err := send(fd, C.VIDIOC_G_FMT, uintptr(unsafe.Pointer(&v4l2Format))); err != nil {
|
|
|
return PixFormat{}, fmt.Errorf("pix format failed: %w", err)
|
|
|
}
|
|
|
|
|
|
- return format.getPixFormat(), nil
|
|
|
+ v4l2PixFmt := *(*C.struct_v4l2_pix_format)(unsafe.Pointer(&v4l2Format.fmt[0]))
|
|
|
+ return PixFormat{
|
|
|
+ Width: uint32(v4l2PixFmt.width),
|
|
|
+ Height: uint32(v4l2PixFmt.height),
|
|
|
+ PixelFormat: uint32(v4l2PixFmt.pixelformat),
|
|
|
+ Field: uint32(v4l2PixFmt.field),
|
|
|
+ BytesPerLine: uint32(v4l2PixFmt.bytesperline),
|
|
|
+ SizeImage: uint32(v4l2PixFmt.sizeimage),
|
|
|
+ Colorspace: uint32(v4l2PixFmt.colorspace),
|
|
|
+ Priv: uint32(v4l2PixFmt.priv),
|
|
|
+ Flags: uint32(v4l2PixFmt.flags),
|
|
|
+ YcbcrEnc: *(*uint32)(unsafe.Pointer(&v4l2PixFmt.anon0[0])),
|
|
|
+ HSVEnc: *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&v4l2PixFmt.anon0[0])) + unsafe.Sizeof(&v4l2PixFmt.anon0[0]))),
|
|
|
+ Quantization: uint32(v4l2PixFmt.quantization),
|
|
|
+ XferFunc: uint32(v4l2PixFmt.xfer_func),
|
|
|
+ }, nil
|
|
|
}
|
|
|
|
|
|
// SetPixFormat sets the pixel format information for the specified driver
|
|
|
// See https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/vidioc-g-fmt.html#ioctl-vidioc-g-fmt-vidioc-s-fmt-vidioc-try-fmt
|
|
|
func SetPixFormat(fd uintptr, pixFmt PixFormat) error {
|
|
|
- format := &v4l2Format{StreamType: BufTypeVideoCapture}
|
|
|
- format.setPixFormat(pixFmt)
|
|
|
- if err := Send(fd, VidiocSetFormat, uintptr(unsafe.Pointer(format))); err != nil {
|
|
|
+ var v4l2Format C.struct_v4l2_format
|
|
|
+ v4l2Format._type = C.uint(BufTypeVideoCapture)
|
|
|
+ *(*C.struct_v4l2_pix_format)(unsafe.Pointer(&v4l2Format.fmt[0])) = *(*C.struct_v4l2_pix_format)(unsafe.Pointer(&pixFmt))
|
|
|
+
|
|
|
+ if err := send(fd, C.VIDIOC_S_FMT, uintptr(unsafe.Pointer(&v4l2Format))); err != nil {
|
|
|
return fmt.Errorf("pix format failed: %w", err)
|
|
|
}
|
|
|
return nil
|