123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- package v4l2
- // #include <linux/videodev2.h>
- import "C"
- import (
- "fmt"
- "unsafe"
- )
- // 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 (
- PixelFmtRGB24 FourCCType = C.V4L2_PIX_FMT_RGB24
- PixelFmtGrey 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
- )
- // PixelFormats provides a map of FourCCType encoding description
- var PixelFormats = map[FourCCType]string{
- PixelFmtRGB24: "24-bit RGB 8-8-8",
- PixelFmtGrey: "8-bit Greyscale",
- PixelFmtYUYV: "YUYV 4:2:2",
- PixelFmtMJPEG: "Motion-JPEG",
- PixelFmtJPEG: "JFIF JPEG",
- PixelFmtMPEG: "MPEG-1/2/4",
- PixelFmtH264: "H.264",
- PixelFmtMPEG4: "MPEG-4 Part 2 ES",
- }
- // IsPixYUVEncoded returns true if the pixel format is a chrome+luminance YUV format
- func IsPixYUVEncoded(pixFmt FourCCType) bool {
- switch pixFmt {
- case
- PixelFmtYUYV,
- PixelFmtYYUV,
- PixelFmtYVYU,
- PixelFmtUYVY,
- PixelFmtVYUY:
- return true
- default:
- return false
- }
- }
- // ColorspaceType
- // See https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L195
- type ColorspaceType = uint32
- const (
- 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{
- ColorspaceDefault: "Default",
- ColorspaceREC709: "Rec. 709",
- Colorspace470SystemBG: "470 System BG",
- ColorspaceJPEG: "JPEG",
- ColorspaceSRGB: "sRGB",
- ColorspaceOPRGB: "opRGB",
- ColorspaceBT2020: "BT.2020",
- ColorspaceRaw: "Raw",
- ColorspaceDCIP3: "DCI-P3",
- }
- // YCbCrEncodingType (v4l2_ycbcr_encoding)
- // https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-defs.html?highlight=v4l2_ycbcr_encoding
- // https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L300
- type YCbCrEncodingType = uint32
- const (
- 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{
- YCbCrEncodingDefault: "Default",
- YCbCrEncoding601: "ITU-R 601",
- YCbCrEncoding709: "Rec. 709",
- YCbCrEncodingXV601: "xvYCC 601",
- YCbCrEncodingXV709: "xvYCC 709",
- YCbCrEncodingBT2020: "BT.2020",
- YCbCrEncodingBT2020ConstLum: "BT.2020 constant luminance",
- HSVEncoding180: "HSV 0-179",
- HSVEncoding256: "HSV 0-255",
- }
- // ColorspaceToYCbCrEnc is used to get the YCbCrEncoding when only a default YCbCr and the colorspace is known
- func ColorspaceToYCbCrEnc(cs ColorspaceType) YCbCrEncodingType {
- switch cs {
- case ColorspaceREC709, ColorspaceDCIP3:
- return YCbCrEncoding709
- case ColorspaceBT2020:
- return YCbCrEncodingBT2020
- default:
- return YCbCrEncoding601
- }
- }
- // HSVEncodingType (v4l2_hsv_encoding)
- // See https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L352
- type HSVEncodingType = YCbCrEncodingType
- const (
- HSVEncoding180 HSVEncodingType = C.V4L2_HSV_ENC_180
- HSVEncoding256 HSVEncodingType = C.V4L2_HSV_ENC_256
- )
- // QuantizationType (v4l2_quantization)
- // https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-defs.html?highlight=v4l2_quantization#c.V4L.v4l2_quantization
- // https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L372
- type QuantizationType = uint32
- const (
- 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{
- QuantizationDefault: "Default",
- QuantizationFullRange: "Full range",
- QuantizationLimitedRange: "Limited range",
- }
- func ColorspaceToQuantization(cs ColorspaceType) QuantizationType {
- // TODO any RGB/HSV pixel formats should also return full-range
- switch cs {
- case ColorspaceOPRGB, ColorspaceSRGB, ColorspaceJPEG:
- return QuantizationFullRange
- default:
- return QuantizationLimitedRange
- }
- }
- // XferFunctionType (v4l2_xfer_func)
- // https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/colorspaces-defs.html?highlight=v4l2_xfer_func#c.V4L.v4l2_xfer_func
- // https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L259
- type XferFunctionType = uint32
- const (
- 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{
- XferFuncDefault: "Default",
- XferFunc709: "Rec. 709",
- XferFuncSRGB: "sRGB",
- XferFuncOpRGB: "opRGB",
- XferFuncSMPTE240M: "SMPTE 240M",
- XferFuncNone: "None",
- XferFuncDCIP3: "DCI-P3",
- XferFuncSMPTE2084: "SMPTE 2084",
- }
- // ColorspaceToXferFunc used to get true XferFunc when only colorspace and default XferFuc are known.
- func ColorspaceToXferFunc(cs ColorspaceType) XferFunctionType {
- switch cs {
- case ColorspaceOPRGB:
- return XferFuncOpRGB
- case ColorspaceSMPTE240M:
- return XferFuncSMPTE240M
- case ColorspaceDCIP3:
- return XferFuncDCIP3
- case ColorspaceRaw:
- return XferFuncNone
- case ColorspaceSRGB:
- return XferFuncSRGB
- case ColorspaceJPEG:
- return XferFuncSRGB
- default:
- return XferFunc709
- }
- }
- // FieldType (v4l2_field)
- // https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/field-order.html?highlight=v4l2_field#c.v4l2_field
- // https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L88
- type FieldType = uint32
- const (
- 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
- var Fields = map[FieldType]string{
- FieldAny: "any",
- FieldNone: "none",
- FieldTop: "top",
- FieldBottom: "bottom",
- FieldInterlaced: "interlaced",
- FieldSequentialTopBottom: "sequential top-bottom",
- FieldSequentialBottomTop: "Sequential botton-top",
- FieldAlternate: "alternating",
- FieldInterlacedTopBottom: "interlaced top-bottom",
- FieldInterlacedBottomTop: "interlaced bottom-top",
- }
- // 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 FourCCType
- Field FieldType
- BytesPerLine uint32
- SizeImage uint32
- Colorspace ColorspaceType
- Priv uint32
- Flags uint32
- YcbcrEnc YCbCrEncodingType
- HSVEnc HSVEncodingType
- Quantization QuantizationType
- XferFunc XferFunctionType
- }
- func (f PixFormat) String() string {
- return fmt.Sprintf(
- "%s [%dx%d]; field=%s; bytes per line=%d; size image=%d; colorspace=%s; YCbCr=%s; Quant=%s; XferFunc=%s",
- PixelFormats[f.PixelFormat],
- f.Width, f.Height,
- Fields[f.Field],
- f.BytesPerLine,
- f.SizeImage,
- Colorspaces[f.Colorspace],
- YCbCrEncodings[f.YcbcrEnc],
- Quantizations[f.Quantization],
- XferFunctions[f.XferFunc],
- )
- }
- // 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) {
- 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)
- }
- 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(C.uint(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 {
- 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
- }
|