package usbcapture import ( "bufio" "bytes" "fmt" "os/exec" "regexp" "strconv" "strings" ) // Struct to store the size and fps info type FormatInfo struct { Format string Sizes []SizeInfo } type SizeInfo struct { Width int Height int FPS []float64 } // CheckVideoCaptureDevice checks if the given video device is a video capture device func checkVideoCaptureDevice(device string) (bool, error) { // Run v4l2-ctl to get device capabilities cmd := exec.Command("v4l2-ctl", "--device", device, "--all") output, err := cmd.CombinedOutput() if err != nil { return false, fmt.Errorf("failed to execute v4l2-ctl: %w", err) } // Convert output to string and check for the "Video Capture" capability outputStr := string(output) if strings.Contains(outputStr, "Video Capture") { return true, nil } return false, nil } // Function to run the v4l2-ctl command and parse the output func getV4L2FormatInfo(devicePath string) ([]FormatInfo, error) { // Run the v4l2-ctl command to list formats cmd := exec.Command("v4l2-ctl", "--list-formats-ext", "-d", devicePath) var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err != nil { return nil, err } // Parse the output var formats []FormatInfo var currentFormat *FormatInfo scanner := bufio.NewScanner(&out) formatRegex := regexp.MustCompile(`\[(\d+)\]: '(\S+)'`) sizeRegex := regexp.MustCompile(`Size: Discrete (\d+)x(\d+)`) intervalRegex := regexp.MustCompile(`Interval: Discrete (\d+\.\d+)s \((\d+\.\d+) fps\)`) for scanner.Scan() { line := scanner.Text() // Match format line if matches := formatRegex.FindStringSubmatch(line); matches != nil { if currentFormat != nil { formats = append(formats, *currentFormat) } // Start a new format entry currentFormat = &FormatInfo{ Format: matches[2], } } // Match size line if matches := sizeRegex.FindStringSubmatch(line); matches != nil { width, _ := strconv.Atoi(matches[1]) height, _ := strconv.Atoi(matches[2]) // Initialize the size entry sizeInfo := SizeInfo{ Width: width, Height: height, } // Match FPS intervals for the current size for scanner.Scan() { line = scanner.Text() if fpsMatches := intervalRegex.FindStringSubmatch(line); fpsMatches != nil { fps, _ := strconv.ParseFloat(fpsMatches[2], 64) sizeInfo.FPS = append(sizeInfo.FPS, fps) } else { // Stop parsing FPS intervals when no more matches are found break } } // Add the size information to the current format currentFormat.Sizes = append(currentFormat.Sizes, sizeInfo) } } // Append the last format if present if currentFormat != nil { formats = append(formats, *currentFormat) } if err := scanner.Err(); err != nil { return nil, err } return formats, nil }