Explorar o código

Add support for media devices; add examples

Vladimir Vivien %!s(int64=3) %!d(string=hai) anos
pai
achega
7f6c7e211a
Modificáronse 4 ficheiros con 105 adicións e 0 borrados
  1. 57 0
      examples/device_info/devinfo.go
  2. 5 0
      v4l2/device/device.go
  3. 38 0
      v4l2/media.go
  4. 5 0
      v4l2/types.go

+ 57 - 0
examples/device_info/devinfo.go

@@ -4,6 +4,7 @@ import (
 	"flag"
 	"fmt"
 	"log"
+	"os"
 	"strings"
 
 	"github.com/vladimirvivien/go4vl/v4l2"
@@ -14,8 +15,18 @@ var template = "\t%-24s : %s\n"
 
 func main() {
 	var devName string
+	var devList bool
 	flag.StringVar(&devName, "d", "/dev/video0", "device name (path)")
+	flag.BoolVar(&devList, "l", false, "list all devices")
 	flag.Parse()
+
+	if devList {
+		if err := listDevices(); err != nil{
+			log.Fatal(err)
+		}
+		os.Exit(0)
+	}
+
 	device, err := device.Open(devName)
 	if err != nil {
 		log.Fatal(err)
@@ -43,6 +54,52 @@ func main() {
 	}
 }
 
+func listDevices() error {
+	paths, err := device.GetAllDevicePaths()
+	if err != nil {
+		return err
+	}
+	for _, path := range paths {
+		dev, err := device.Open(path)
+		if err != nil {
+			log.Print(err)
+			continue
+		}
+
+		var busInfo, card string
+		cap, err := dev.GetCapability()
+		if err != nil {
+			// is a media device?
+			if mdi, err := dev.GetMediaInfo(); err == nil {
+				if mdi.BusInfo != "" {
+					busInfo = mdi.BusInfo
+				}else{
+					busInfo = "platform: " + mdi.Driver
+				}
+				if mdi.Model != "" {
+					card = mdi.Model
+				}else{
+					card = mdi.Driver
+				}
+			}
+		}else{
+			busInfo = cap.BusInfo
+			card = cap.Card
+		}
+
+		// close device
+		if err := dev.Close(); err != nil {
+			log.Print(err)
+			continue
+		}
+
+		fmt.Printf("Device [%s]: %s: %s\n", path, card, busInfo)
+
+
+	}
+	return nil
+}
+
 func printDeviceDriverInfo(dev *device.Device) error {
 	caps, err := dev.GetCapability()
 	if err != nil {

+ 5 - 0
v4l2/device/device.go

@@ -158,6 +158,11 @@ func (d *Device) GetCaptureParam() (v4l2.CaptureParam, error) {
 	return v4l2.GetStreamCaptureParam(d.fd)
 }
 
+// GetMediaInfo returns info for a device that supports the Media API
+func (d *Device) GetMediaInfo() (v4l2.MediaDeviceInfo, error) {
+	return v4l2.GetMediaDeviceInfo(d.fd)
+}
+
 func (d *Device) StartStream(buffSize uint32) error {
 	if d.streaming {
 		return nil

+ 38 - 0
v4l2/media.go

@@ -0,0 +1,38 @@
+package v4l2
+
+// #include <linux/media.h>
+import "C"
+import (
+	"fmt"
+	"unsafe"
+)
+
+// MediaDeviceInfo (media_device_info)
+// See https://www.kernel.org/doc/html/latest/userspace-api/media/mediactl/media-ioc-device-info.html
+// See https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/media.h#L29
+type MediaDeviceInfo struct {
+	Driver           string
+	Model            string
+	Serial           string
+	BusInfo          string
+	MediaVersion     VersionInfo
+	HardwareRevision uint32
+	DriverVersion    VersionInfo
+}
+
+// GetMediaDeviceInfo retrieves media information for specified device, if supported.
+func GetMediaDeviceInfo(fd uintptr) (MediaDeviceInfo, error) {
+	var mdi C.struct_media_device_info
+	if err := send(fd, C.MEDIA_IOC_DEVICE_INFO, uintptr(unsafe.Pointer(&mdi))); err != nil {
+		return MediaDeviceInfo{}, fmt.Errorf("media device info: %w", err)
+	}
+	return MediaDeviceInfo{
+		Driver:           C.GoString((*C.char)(&mdi.driver[0])),
+		Model:            C.GoString((*C.char)(&mdi.model[0])),
+		Serial:           C.GoString((*C.char)(&mdi.serial[0])),
+		BusInfo:          C.GoString((*C.char)(&mdi.bus_info[0])),
+		MediaVersion:     VersionInfo{value: uint32(mdi.media_version)},
+		HardwareRevision: uint32(mdi.hw_revision),
+		DriverVersion:    VersionInfo{value: uint32(mdi.driver_version)},
+	}, nil
+}

+ 5 - 0
v4l2/types.go

@@ -20,6 +20,11 @@ func (v VersionInfo) Patch() uint32{
 	return v.value&0xff
 }
 
+// Value returns the raw numeric version value
+func (v VersionInfo) Value() uint32 {
+	return v.value
+}
+
 func (v VersionInfo) String() string {
 	return fmt.Sprintf("v%d.%d.%d", v.Major(), v.Minor(), v.Patch())
 }