Преглед изворни кода

Refactoring device to support camera module 3 for RPi

Vladimir Vivien пре 1 година
родитељ
комит
579bcbe5d5
3 измењених фајлова са 74 додато и 43 уклоњено
  1. 29 2
      device/device.go
  2. 38 35
      examples/capture1/capture1.go
  3. 7 6
      v4l2/format_desc.go

+ 29 - 2
device/device.go

@@ -232,8 +232,8 @@ func (d *Device) GetFormatDescription(idx uint32) (v4l2.FormatDescription, error
 	return v4l2.GetFormatDescription(d.fd, idx)
 }
 
-// GetFormatDescriptions returns all possible format descriptions for device
-func (d *Device) GetFormatDescriptions() ([]v4l2.FormatDescription, error) {
+// GetAllFormatDescriptions returns all possible format descriptions for device
+func (d *Device) GetAllFormatDescriptions() ([]v4l2.FormatDescription, error) {
 	if !d.cap.IsVideoCaptureSupported() {
 		return nil, v4l2.ErrorUnsupportedFeature
 	}
@@ -241,6 +241,33 @@ func (d *Device) GetFormatDescriptions() ([]v4l2.FormatDescription, error) {
 	return v4l2.GetAllFormatDescriptions(d.fd)
 }
 
+// GetFormatDescriptions returns all device format descriptions for specified format
+func (d *Device) GetFormatDescriptions(format v4l2.FourCCType) ([]v4l2.FormatDescription, error) {
+	if !d.cap.IsVideoCaptureSupported() {
+		return nil, v4l2.ErrorUnsupportedFeature
+	}
+
+	return v4l2.GetFormatDescriptions(d.fd, format)
+}
+
+// GetAllFormatFrameSizes returns all supported device frame sizes
+func (d *Device) GetAllFormatFrameSizes() ([]v4l2.FrameSizeEnum, error) {
+	if !d.cap.IsVideoCaptureSupported() {
+		return nil, v4l2.ErrorUnsupportedFeature
+	}
+
+	return v4l2.GetAllFormatFrameSizes(d.fd)
+}
+
+// GetFormatFrameSizes returns all supported device frame sizes for specified pixel format
+func (d *Device) GetFormatFrameSizes(format v4l2.FourCCType) ([]v4l2.FrameSizeEnum, error) {
+	if !d.cap.IsVideoCaptureSupported() {
+		return nil, v4l2.ErrorUnsupportedFeature
+	}
+
+	return v4l2.GetFormatFrameSizes(d.fd, format)
+}
+
 // GetVideoInputIndex returns current video input index for device
 func (d *Device) GetVideoInputIndex() (int32, error) {
 	if !d.cap.IsVideoCaptureSupported() {

+ 38 - 35
examples/capture1/capture1.go

@@ -37,64 +37,67 @@ func main() {
 		log.Fatalf("failed to get framerate: %s", err)
 	}
 
+	allFormats, err := device.GetAllFormatDescriptions()
+	if err != nil {
+		log.Fatal("failed to get format descriptions: %s", err)
+	}
+
 	// helper function to search for format descriptions
-	findPreferredFmt := func(fmts []v4l2.FormatDescription, pixEncoding v4l2.FourCCType) *v4l2.FormatDescription {
-		for _, desc := range fmts {
+	findPreferredFmt := func(pixEncoding v4l2.FourCCType) (v4l2.FormatDescription, error) {
+		for _, desc := range allFormats {
 			if desc.PixelFormat == pixEncoding {
-				return &desc
+				return desc, nil
 			}
 		}
-		return nil
-	}
-
-	// get supported format descriptions
-	fmtDescs, err := device.GetFormatDescriptions()
-	if err != nil {
-		log.Fatal("failed to get format desc:", err)
+		return v4l2.FormatDescription{}, fmt.Errorf("preferred format not found")
 	}
 
 	// search for preferred formats
-	preferredFmts := []v4l2.FourCCType{v4l2.PixelFmtMPEG, v4l2.PixelFmtMJPEG, v4l2.PixelFmtJPEG, v4l2.PixelFmtYUYV}
-	var fmtDesc *v4l2.FormatDescription
-	for _, preferredFmt := range preferredFmts {
-		fmtDesc = findPreferredFmt(fmtDescs, preferredFmt)
-		if fmtDesc != nil {
+	preferredPixFmts := []v4l2.FourCCType{v4l2.PixelFmtMPEG, v4l2.PixelFmtMJPEG, v4l2.PixelFmtJPEG, v4l2.PixelFmtYUYV}
+
+	var sizes []v4l2.FrameSizeEnum
+	var preferredFmt v4l2.FormatDescription
+	for _, pixFmt := range preferredPixFmts {
+		preferredFmt, err = findPreferredFmt(pixFmt)
+		if err != nil {
+			continue
+		}
+		sizes, err = device.GetFormatFrameSizes(preferredFmt.PixelFormat)
+		if err != nil {
+			continue
+		}
+		if sizes != nil && len(sizes) > 0 {
 			break
 		}
 	}
 
-	// no preferred pix fmt supported
-	if fmtDesc == nil {
-		log.Fatalf("device does not support any of %#v", preferredFmts)
+	if sizes == nil || len(sizes) == 0 {
+		log.Fatal("no appropriate sizes found for specified format: %s", preferredFmt)
 	}
-	log.Printf("Found preferred fmt: %s", fmtDesc)
 
-	frameSizes, err := v4l2.GetFormatFrameSizes(device.Fd(), fmtDesc.PixelFormat)
-	if err != nil {
-		log.Fatalf("failed to get framesize info: %s", err)
-	}
-
-	// select size 640x480 for format
-	var frmSize v4l2.FrameSizeEnum
-	for _, size := range frameSizes {
+	// select size
+	prefSize := sizes[0]
+	prefSizeFound := false
+	for _, size := range sizes {
 		if size.Size.MinWidth == uint32(width) && size.Size.MinHeight == uint32(height) {
-			frmSize = size
+			prefSizeFound = true
 			break
 		}
 	}
 
-	if frmSize.Size.MinWidth == 0 {
-		log.Fatalf("Size %dx%d not supported for fmt: %s", width, height, fmtDesc)
+	if !prefSizeFound {
+		log.Printf("Specified size %dx%d not supported, setting to %dx%d: %s", width, height, prefSize.Size.MinWidth, prefSize.Size.MinHeight)
+		width = int(prefSize.Size.MinWidth)
+		height = int(prefSize.Size.MinHeight)
 	}
 
-	log.Printf("Found preferred size: %#v", frmSize)
+	log.Printf("Found preferred size: %#v", prefSize)
 
 	// configure device with preferred fmt
-
 	if err := device.SetPixFormat(v4l2.PixFormat{
-		Width:       frmSize.Size.MinWidth,
-		Height:      frmSize.Size.MinHeight,
-		PixelFormat: fmtDesc.PixelFormat,
+		Width:       prefSize.Size.MinWidth,
+		Height:      prefSize.Size.MinHeight,
+		PixelFormat: preferredFmt.PixelFormat,
 		Field:       v4l2.FieldNone,
 	}); err != nil {
 		log.Fatalf("failed to set format: %s", err)

+ 7 - 6
v4l2/format_desc.go

@@ -115,17 +115,18 @@ func GetAllFormatDescriptions(fd uintptr) (result []FormatDescription, err error
 	return result, nil
 }
 
-// GetFormatDescriptionByEncoding returns a FormatDescription that matches the specified encoded pixel format
-func GetFormatDescriptionByEncoding(fd uintptr, enc FourCCType) (FormatDescription, error) {
+// GetFormatDescriptions returns format descriptions for specified pixel format
+func GetFormatDescriptions(fd uintptr, format FourCCType) ([]FormatDescription, error) {
+	var result []FormatDescription
 	descs, err := GetAllFormatDescriptions(fd)
 	if err != nil {
-		return FormatDescription{}, fmt.Errorf("format desc: encoding %s: %s", PixelFormats[enc], err)
+		return nil, fmt.Errorf("format desc: encoding %s: %s", PixelFormats[format], err)
 	}
 	for _, desc := range descs {
-		if desc.PixelFormat == enc {
-			return desc, nil
+		if desc.PixelFormat == format {
+			result = append(result, desc)
 		}
 	}
 
-	return FormatDescription{}, fmt.Errorf("format desc: driver does not support encoding %d", enc)
+	return result, nil
 }