capability.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package v4l2
  2. /*
  3. #cgo linux CFLAGS: -I ${SRCDIR}/../include/
  4. #include <linux/videodev2.h>
  5. */
  6. import "C"
  7. import (
  8. "fmt"
  9. "unsafe"
  10. )
  11. // V4l2 video capability constants
  12. // see https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L451
  13. const (
  14. CapVideoCapture uint32 = C.V4L2_CAP_VIDEO_CAPTURE
  15. CapVideoOutput uint32 = C.V4L2_CAP_VIDEO_OUTPUT
  16. CapVideoOverlay uint32 = C.V4L2_CAP_VIDEO_OVERLAY
  17. CapVBICapture uint32 = C.V4L2_CAP_VBI_CAPTURE
  18. CapVBIOutput uint32 = C.V4L2_CAP_VBI_OUTPUT
  19. CapSlicedVBICapture uint32 = C.V4L2_CAP_SLICED_VBI_CAPTURE
  20. CapSlicedVBIOutput uint32 = C.V4L2_CAP_SLICED_VBI_OUTPUT
  21. CapRDSCapture uint32 = C.V4L2_CAP_RDS_CAPTURE
  22. CapVideoOutputOverlay uint32 = C.V4L2_CAP_VIDEO_OUTPUT_OVERLAY
  23. CapHWFrequencySeek uint32 = C.V4L2_CAP_HW_FREQ_SEEK
  24. CapRDSOutput uint32 = C.V4L2_CAP_RDS_OUTPUT
  25. CapVideoCaptureMPlane uint32 = C.V4L2_CAP_VIDEO_CAPTURE_MPLANE
  26. CapVideoOutputMPlane uint32 = C.V4L2_CAP_VIDEO_OUTPUT_MPLANE
  27. CapVideoMem2MemMPlane uint32 = C.V4L2_CAP_VIDEO_M2M_MPLANE
  28. CapVideoMem2Mem uint32 = C.V4L2_CAP_VIDEO_M2M
  29. CapTuner uint32 = C.V4L2_CAP_TUNER
  30. CapAudio uint32 = C.V4L2_CAP_AUDIO
  31. CapRadio uint32 = C.V4L2_CAP_RADIO
  32. CapModulator uint32 = C.V4L2_CAP_MODULATOR
  33. CapSDRCapture uint32 = C.V4L2_CAP_SDR_CAPTURE
  34. CapExtendedPixFormat uint32 = C.V4L2_CAP_EXT_PIX_FORMAT
  35. CapSDROutput uint32 = C.V4L2_CAP_SDR_OUTPUT
  36. CapMetadataCapture uint32 = C.V4L2_CAP_META_CAPTURE
  37. CapReadWrite uint32 = C.V4L2_CAP_READWRITE
  38. CapAsyncIO uint32 = C.V4L2_CAP_ASYNCIO
  39. CapStreaming uint32 = C.V4L2_CAP_STREAMING
  40. CapMetadataOutput uint32 = C.V4L2_CAP_META_OUTPUT
  41. CapTouch uint32 = C.V4L2_CAP_TOUCH
  42. CapIOMediaController uint32 = C.V4L2_CAP_IO_MC
  43. CapDeviceCapabilities uint32 = C.V4L2_CAP_DEVICE_CAPS
  44. )
  45. type CapabilityDesc struct {
  46. Cap uint32
  47. Desc string
  48. }
  49. var (
  50. Capabilities = []CapabilityDesc{
  51. {Cap: CapVideoCapture, Desc: "video capture (single-planar)"},
  52. {Cap: CapVideoOutput, Desc: "video output (single-planar)"},
  53. {Cap: CapVideoOverlay, Desc: "video overlay"},
  54. {Cap: CapVBICapture, Desc: "raw VBI capture"},
  55. {Cap: CapVBIOutput, Desc: "raw VBI output"},
  56. {Cap: CapSlicedVBICapture, Desc: "sliced VBI capture"},
  57. {Cap: CapSlicedVBIOutput, Desc: "sliced VBI output"},
  58. {Cap: CapRDSCapture, Desc: "RDS capture"},
  59. {Cap: CapVideoOutputOverlay, Desc: "video output overlay"},
  60. {Cap: CapHWFrequencySeek, Desc: "hardware frequency seeking"},
  61. {Cap: CapRDSOutput, Desc: "RDS output"},
  62. {Cap: CapVideoCaptureMPlane, Desc: "video capture (multi-planar)"},
  63. {Cap: CapVideoOutputMPlane, Desc: "video output (multi-planar)"},
  64. {Cap: CapVideoMem2MemMPlane, Desc: "memory-to-memory video (multi-planar)"},
  65. {Cap: CapVideoMem2Mem, Desc: "memory-to-memory video (single-planar)"},
  66. {Cap: CapTuner, Desc: "video tuner"},
  67. {Cap: CapAudio, Desc: "audio inputs or outputs"},
  68. {Cap: CapRadio, Desc: "radio receiver"},
  69. {Cap: CapModulator, Desc: "radio frequency modulator"},
  70. {Cap: CapSDRCapture, Desc: "SDR capture"},
  71. {Cap: CapExtendedPixFormat, Desc: "extended pixel format"},
  72. {Cap: CapSDROutput, Desc: "SDR output"},
  73. {Cap: CapMetadataCapture, Desc: "metadata capture"},
  74. {Cap: CapReadWrite, Desc: "read/write IO"},
  75. {Cap: CapAsyncIO, Desc: "asynchronous IO"},
  76. {Cap: CapStreaming, Desc: "streaming IO"},
  77. {Cap: CapMetadataOutput, Desc: "metadata output"},
  78. {Cap: CapTouch, Desc: "touch capability"},
  79. {Cap: CapIOMediaController, Desc: "IO media controller"},
  80. {Cap: CapDeviceCapabilities, Desc: "device capabilities"},
  81. }
  82. )
  83. // Capability represents capabilities retrieved for the device (see v4l2_capability).
  84. // Use attached methods on this type to access capabilities.
  85. // https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/videodev2.h#L440
  86. // https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/vidioc-querycap.html#c.V4L.v4l2_capability
  87. type Capability struct {
  88. // Driver name of the driver module
  89. Driver string
  90. // Card name of the device card
  91. Card string
  92. // BusInfo is the name of the device bus
  93. BusInfo string
  94. // Version is the kernel version
  95. Version uint32
  96. // Capabilities returns all exported capabilities for the physical device (opened or not)
  97. Capabilities uint32
  98. // DeviceCapabilities is the capability for this particular (opened) device or node
  99. DeviceCapabilities uint32
  100. }
  101. // GetCapability retrieves capability info for device
  102. func GetCapability(fd uintptr) (Capability, error) {
  103. var v4l2Cap C.struct_v4l2_capability
  104. if err := send(fd, C.VIDIOC_QUERYCAP, uintptr(unsafe.Pointer(&v4l2Cap))); err != nil {
  105. return Capability{}, fmt.Errorf("capability: %w", err)
  106. }
  107. return Capability{
  108. Driver: C.GoString((*C.char)(unsafe.Pointer(&v4l2Cap.driver[0]))),
  109. Card: C.GoString((*C.char)(unsafe.Pointer(&v4l2Cap.card[0]))),
  110. BusInfo: C.GoString((*C.char)(unsafe.Pointer(&v4l2Cap.bus_info[0]))),
  111. Version: uint32(v4l2Cap.version),
  112. Capabilities: uint32(v4l2Cap.capabilities),
  113. DeviceCapabilities: uint32(v4l2Cap.device_caps),
  114. }, nil
  115. }
  116. // GetCapabilities returns device capabilities if supported
  117. func (c Capability) GetCapabilities() uint32 {
  118. if c.IsDeviceCapabilitiesProvided() {
  119. return c.DeviceCapabilities
  120. }
  121. return c.Capabilities
  122. }
  123. // IsVideoCaptureSupported returns caps & CapVideoCapture
  124. func (c Capability) IsVideoCaptureSupported() bool {
  125. return c.Capabilities&CapVideoCapture != 0
  126. }
  127. // IsVideoOutputSupported returns caps & CapVideoOutput
  128. func (c Capability) IsVideoOutputSupported() bool {
  129. return c.Capabilities&CapVideoOutput != 0
  130. }
  131. // IsVideoOverlaySupported returns caps & CapVideoOverlay
  132. func (c Capability) IsVideoOverlaySupported() bool {
  133. return c.Capabilities&CapVideoOverlay != 0
  134. }
  135. // IsVideoOutputOverlaySupported returns caps & CapVideoOutputOverlay
  136. func (c Capability) IsVideoOutputOverlaySupported() bool {
  137. return c.Capabilities&CapVideoOutputOverlay != 0
  138. }
  139. // IsVideoCaptureMultiplanarSupported returns caps & CapVideoCaptureMPlane
  140. func (c Capability) IsVideoCaptureMultiplanarSupported() bool {
  141. return c.Capabilities&CapVideoCaptureMPlane != 0
  142. }
  143. // IsVideoOutputMultiplanerSupported returns caps & CapVideoOutputMPlane
  144. func (c Capability) IsVideoOutputMultiplanerSupported() bool {
  145. return c.Capabilities&CapVideoOutputMPlane != 0
  146. }
  147. // IsReadWriteSupported returns caps & CapReadWrite
  148. func (c Capability) IsReadWriteSupported() bool {
  149. return c.Capabilities&CapReadWrite != 0
  150. }
  151. // IsStreamingSupported returns caps & CapStreaming
  152. func (c Capability) IsStreamingSupported() bool {
  153. return c.Capabilities&CapStreaming != 0
  154. }
  155. // IsDeviceCapabilitiesProvided returns true if the device returns
  156. // device-specific capabilities (via CapDeviceCapabilities)
  157. // See notes on VL42_CAP_DEVICE_CAPS:
  158. // https://linuxtv.org/downloads/v4l-dvb-apis/userspace-api/v4l/vidioc-querycap.html?highlight=v4l2_cap_device_caps
  159. func (c Capability) IsDeviceCapabilitiesProvided() bool {
  160. return c.Capabilities&CapDeviceCapabilities != 0
  161. }
  162. // GetDriverCapDescriptions return textual descriptions of driver capabilities
  163. func (c Capability) GetDriverCapDescriptions() []CapabilityDesc {
  164. var result []CapabilityDesc
  165. for _, cap := range Capabilities {
  166. if c.Capabilities&cap.Cap == cap.Cap {
  167. result = append(result, cap)
  168. }
  169. }
  170. return result
  171. }
  172. // GetDeviceCapDescriptions return textual descriptions of device capabilities
  173. func (c Capability) GetDeviceCapDescriptions() []CapabilityDesc {
  174. var result []CapabilityDesc
  175. for _, cap := range Capabilities {
  176. if c.DeviceCapabilities&cap.Cap == cap.Cap {
  177. result = append(result, cap)
  178. }
  179. }
  180. return result
  181. }
  182. func (c Capability) GetVersionInfo() VersionInfo {
  183. return VersionInfo{value: c.Version}
  184. }
  185. // String returns a string value representing driver information
  186. func (c Capability) String() string {
  187. return fmt.Sprintf("driver: %s; card: %s; bus info: %s", c.Driver, c.Card, c.BusInfo)
  188. }