소스 검색

Support for format desc; fmt conversion; example updates

Vladimir Vivien 4 년 전
부모
커밋
3bf55b04eb
9개의 변경된 파일111개의 추가작업 그리고 13개의 파일을 삭제
  1. 18 3
      README.md
  2. 40 4
      examples/capture/capture.go
  3. 1 1
      examples/device_info/devinfo.go
  4. 0 5
      examples/raw_v4l2/README.md
  5. 15 0
      examples/v4l2_direct/README.md
  6. 0 0
      examples/v4l2_direct/v4l2_capture.go
  7. 27 0
      imgsupport/converters.go
  8. 2 0
      imgsupport/doc.go
  9. 8 0
      v4l2/device.go

+ 18 - 3
README.md

@@ -1,10 +1,25 @@
 # go4vl
-A Go library for working with the Video for Linux user API (V4L2).
+A Go library for the Video for Linux user API (V4L2).
 
 ----
 
-Gov4l hides all the complexities of working with V4L2 and exposes idiomatic Go types, like channels, to consume captured frame.
+`go4vl` hides all the complexities of working with V4L2 and 
+provides idiomatic Go types, like channels, to consume and process captured video frames.
 
 ## Features
 * Capture and control video data from your Go programs
-* Idiomatic Go API
+* Idiomatic Go API for device access and video capture
+* Use familiar types such as channels to stream video data
+* Exposes device enumeration and information
+* Provides device capture control
+* Access to video format information
+* Streaming support using memory map (other methods coming soon)
+
+## Getting started
+To include `go4vl` in your own code, pull the package
+
+```bash
+go get github.com/vladimirvivien/go4vl/v4l2
+```
+
+## Example

+ 40 - 4
examples/capture/capture.go

@@ -22,11 +22,47 @@ func main() {
 	}
 	defer device.Close()
 
-	// configuration
+	// helper function to search for format descriptions
+	findPreferredFmt := func(fmts []v4l2.FormatDescription, pixEncoding v4l2.FourCCEncoding) *v4l2.FormatDescription {
+		for _, desc := range fmts {
+			if desc.GetPixelFormat() == pixEncoding{
+				return &desc
+			}
+		}
+		return nil
+	}
+
+	// get supported format descriptions
+	fmtDescs, err := device.GetFormatDescriptions()
+	if err != nil{
+		log.Fatal("failed to get format desc:", err)
+	}
+
+	// search for preferred formats
+	preferredFmts := []v4l2.FourCCEncoding{v4l2.PixelFmtMPEG, v4l2.PixelFmtMJPEG, v4l2.PixelFmtJPEG, v4l2.PixelFmtYUYV}
+	var fmtDesc *v4l2.FormatDescription
+	for _, preferredFmt := range preferredFmts{
+		fmtDesc = findPreferredFmt(fmtDescs, preferredFmt)
+		if fmtDesc != nil {
+			break
+		}
+	}
+
+	// no preferred pix fmt supported
+	if fmtDesc == nil {
+		log.Fatalf("device does not support any of %#v", preferredFmts)
+	}
+
+	frameSize, err := fmtDesc.GetFrameSize()
+	if err!=nil{
+		log.Fatalf("failed to get framesize info: %s", err)
+	}
+
+	// configure device with preferred fmt
 	if err := device.SetPixFormat(v4l2.PixFormat{
-		Width:       640,
-		Height:      480,
-		PixelFormat: v4l2.PixelFmtMJPEG,
+		Width:       frameSize.Width,
+		Height:      frameSize.Height,
+		PixelFormat: fmtDesc.GetPixelFormat(),
 		Field:       v4l2.FieldNone,
 	}); err != nil {
 		log.Fatalf("failed to set format: %s", err)

+ 1 - 1
examples/device_info/devinfo.go

@@ -24,7 +24,7 @@ func setDefaultCrop(device *v4l2.Device) error {
 		return err
 	}
 	log.Printf("device crop capability: %s", cap.String())
-	err = device.SetCropRect(cap.DefaultRect())
+	err = device.SetCropRect(cap.DefaultRect)
 	if err != nil {
 		log.Printf("setcrop unsupported: %s", err)
 	}

+ 0 - 5
examples/raw_v4l2/README.md

@@ -1,5 +0,0 @@
-# Raw V4L2
-The example in this directory shows all of the moving pieces that make
-the V4L2 API works using Go.  It shows all of the steps, in detail, that
-are required to communicate with a device driver to configure, initiate,
-and capture images.

+ 15 - 0
examples/v4l2_direct/README.md

@@ -0,0 +1,15 @@
+# Example: capture with V4L2 directly
+:warning: 
+
+This example is here to illustrate the complexity of v4l2.
+Do not use it. 
+
+If you want to play around with image capture, use the 
+[examples/capture](../capture).
+
+:warning:
+
+The example in this directory shows most of the moving pieces that make
+the V4L2 API works using Go.  It illustrates the steps, in detail, that
+are required to communicate with a device driver to configure, initiate,
+and capture images without using the Go v4l2 device type provided.

+ 0 - 0
examples/raw_v4l2/raw_capture.go → examples/v4l2_direct/v4l2_capture.go


+ 27 - 0
imgsupport/converters.go

@@ -0,0 +1,27 @@
+package imgsupport
+
+import (
+	"bytes"
+	"image"
+	"image/jpeg"
+)
+
+func Yuyv2Jpeg(width, height int, frame []byte) ([]byte, error) {
+	size := len(frame)
+	ycbr := image.NewYCbCr(image.Rect(0, 0, width, height), image.YCbCrSubsampleRatio422)
+
+	for i := 0; i < size; i += 4 {
+		y1, u, y2, v := frame[i], frame[i+1], frame[i+2], frame[i+3]
+		ycbr.Y[i]   = y1
+		ycbr.Y[i+1] = y2
+		ycbr.Cb[i]  = u
+		ycbr.Cr[i]  = v
+	}
+
+	var jpgBuf bytes.Buffer
+	if err := jpeg.Encode(&jpgBuf, ycbr, nil); err != nil {
+		return nil, err
+	}
+
+	return jpgBuf.Bytes(), nil
+}

+ 2 - 0
imgsupport/doc.go

@@ -0,0 +1,2 @@
+// Package imgsupport provides image functionalities
+package imgsupport

+ 8 - 0
v4l2/device.go

@@ -108,6 +108,14 @@ func (d *Device) SetPixFormat(pixFmt PixFormat) error {
 	return nil
 }
 
+func (d *Device) GetFormatDescriptions() ([]FormatDescription, error) {
+	if err := d.assertVideoCaptureSupport(); err != nil {
+		return nil, fmt.Errorf("device: %w", err)
+	}
+
+	return GetAllFormatDescriptions(d.fd)
+}
+
 func (d *Device) StartStream(buffSize uint32) error {
 	if d.streaming {
 		return nil