Skip to content

Commit

Permalink
Support for capture stream param; error refactor; fix fmt desc, frame…
Browse files Browse the repository at this point in the history
… sizes
  • Loading branch information
vladimirvivien committed Sep 11, 2021
1 parent 1d9f59b commit aab6d9c
Show file tree
Hide file tree
Showing 8 changed files with 423 additions and 78 deletions.
114 changes: 111 additions & 3 deletions examples/device_info/devinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"log"
"strings"

"github.com/vladimirvivien/go4vl/v4l2"
)
Expand Down Expand Up @@ -31,6 +32,14 @@ func main() {
if err := printFormatInfo(device); err != nil {
log.Fatal(err)
}

if err := printCropInfo(device); err != nil {
log.Fatal(err)
}

if err := printCaptureParam(device); err != nil {
log.Fatal(err)
}
}

func printDeviceDriverInfo(dev *v4l2.Device) error {
Expand Down Expand Up @@ -88,13 +97,112 @@ func printFormatInfo(dev *v4l2.Device) error {
if err != nil {
return fmt.Errorf("video capture format: %w", err)
}
fmt.Println("Format video capture:")
fmt.Printf(template, "WidthxHeight", fmt.Sprintf("%dx%d", pixFmt.Width, pixFmt.Height))
fmt.Println("Video format for capture (default):")
fmt.Printf(template, "Width x Height", fmt.Sprintf("%d x %d", pixFmt.Width, pixFmt.Height))
fmt.Printf(template, "Pixel format", v4l2.PixelFormats[pixFmt.PixelFormat])
fmt.Printf(template, "Field", v4l2.Fields[pixFmt.Field])
fmt.Printf(template, "Bytes per line", fmt.Sprintf("%d",pixFmt.BytesPerLine))
fmt.Printf(template, "Bytes per line", fmt.Sprintf("%d", pixFmt.BytesPerLine))
fmt.Printf(template, "Size image", fmt.Sprintf("%d", pixFmt.SizeImage))
fmt.Printf(template, "Colorspace", v4l2.Colorspaces[pixFmt.Colorspace])

// xferfunc
xfunc := v4l2.XferFunctions[pixFmt.XferFunc]
if pixFmt.XferFunc == v4l2.XferFuncDefault {
xfunc = fmt.Sprintf("%s (map to %s)", xfunc, v4l2.XferFunctions[v4l2.ColorspaceToXferFunc(pixFmt.XferFunc)])
}
fmt.Printf(template, "Transfer function", xfunc)

// ycbcr
ycbcr := v4l2.YCbCrEncodings[pixFmt.YcbcrEnc]
if pixFmt.YcbcrEnc == v4l2.YCbCrEncodingDefault {
ycbcr = fmt.Sprintf("%s (map to %s)", ycbcr, v4l2.YCbCrEncodings[v4l2.ColorspaceToYCbCrEnc(pixFmt.YcbcrEnc)])
}
fmt.Printf(template, "YCbCr/HSV encoding", ycbcr)

// quant
quant := v4l2.Quantizations[pixFmt.Quantization]
if pixFmt.Quantization == v4l2.QuantizationDefault {
if v4l2.IsPixYUVEncoded(pixFmt.PixelFormat) {
quant = fmt.Sprintf("%s (map to %s)", quant, v4l2.Quantizations[v4l2.QuantizationLimitedRange])
} else {
quant = fmt.Sprintf("%s (map to %s)", quant, v4l2.Quantizations[v4l2.QuantizationFullRange])
}
}
fmt.Printf(template, "Quantization", quant)

// format desc
return printFormatDesc(dev)
}

func printFormatDesc(dev *v4l2.Device) error {
descs, err := dev.GetFormatDescriptions()
if err != nil {
return fmt.Errorf("format desc: %w", err)
}
fmt.Println("Supported formats:")
for i, desc := range descs{
frmSizes, err := desc.GetFrameSizes()
if err != nil {
return fmt.Errorf("format desc: %w", err)
}
var sizeStr strings.Builder
sizeStr.WriteString("Sizes: ")
for _, size := range frmSizes{
sizeStr.WriteString(fmt.Sprintf("[%dx%d] ", size.Width, size.Height))
}
fmt.Printf(template, fmt.Sprintf("[%0d] %s", i, desc.GetDescription()), sizeStr.String())

}
return nil
}

func printCropInfo(dev *v4l2.Device) error {
crop, err := dev.GetCropCapability()
if err != nil {
return fmt.Errorf("crop capability: %w", err)
}

fmt.Println("Crop capability for video capture:")
fmt.Printf(
template,
"Bounds:",
fmt.Sprintf(
"left=%d; top=%d; width=%d; heigh=%d",
crop.Bounds.Left, crop.Bounds.Top, crop.Bounds.Width, crop.Bounds.Height,
),
)
fmt.Printf(
template,
"Default:",
fmt.Sprintf(
"left=%d; top=%d; width=%d; heigh=%d",
crop.DefaultRect.Left, crop.DefaultRect.Top, crop.DefaultRect.Width, crop.DefaultRect.Height,
),
)
fmt.Printf(template, "Pixel aspect", fmt.Sprintf("%d/%d", crop.PixelAspect.Numerator, crop.PixelAspect.Denominator))
return nil
}

func printCaptureParam(dev *v4l2.Device) error {
params, err := dev.GetCaptureParam()
if err != nil {
return fmt.Errorf("streaming capture param: %w", err)
}
fmt.Println("Streaming parameters for video capture:")

tpf := "not specified"
if params.Capability == v4l2.StreamParamTimePerFrame {
tpf = "time per frame"
}
fmt.Printf(template, "Capability", tpf)

hiqual := "not specified"
if params.CaptureMode == v4l2.StreamParamModeHighQuality {
hiqual = "high quality"
}
fmt.Printf(template, "Capture mode", hiqual)

fmt.Printf(template, "Frames per second", fmt.Sprintf("%d/%d", params.TimePerFrame.Denominator, params.TimePerFrame.Numerator))
fmt.Printf(template, "Read buffers", fmt.Sprintf("%d",params.ReadBuffers))
return nil
}
26 changes: 26 additions & 0 deletions v4l2/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ func (d *Device) Close() error {
return d.file.Close()
}

// GetFileDescriptor returns the file descriptor value for the device
func (d *Device) GetFileDescriptor() uintptr {
return d.fd
}

// GetCapability retrieves device capability info and
// caches it for future capability check.
func (d *Device) GetCapability() (*Capability, error) {
Expand Down Expand Up @@ -108,6 +113,17 @@ func (d *Device) SetPixFormat(pixFmt PixFormat) error {
return nil
}

// GetFormatDescription returns a format description for the device at specified format index
func (d *Device) GetFormatDescription(idx uint32) (FormatDescription, error) {
if err := d.assertVideoCaptureSupport(); err != nil {
return FormatDescription{}, fmt.Errorf("device: %w", err)
}

return GetFormatDescription(d.fd, idx)
}


// GetFormatDescriptions returns all possible format descriptions for device
func (d *Device) GetFormatDescriptions() ([]FormatDescription, error) {
if err := d.assertVideoCaptureSupport(); err != nil {
return nil, fmt.Errorf("device: %w", err)
Expand All @@ -116,20 +132,30 @@ func (d *Device) GetFormatDescriptions() ([]FormatDescription, error) {
return GetAllFormatDescriptions(d.fd)
}

// GetVideoInputIndex returns current video input index for device
func (d *Device) GetVideoInputIndex()(int32, error) {
if err := d.assertVideoCaptureSupport(); err != nil {
return 0, fmt.Errorf("device: %w", err)
}
return GetCurrentVideoInputIndex(d.fd)
}

// GetVideoInputInfo returns video input info for device
func (d *Device) GetVideoInputInfo(index uint32) (InputInfo, error) {
if err := d.assertVideoCaptureSupport(); err != nil {
return InputInfo{}, fmt.Errorf("device: %w", err)
}
return GetVideoInputInfo(d.fd, index)
}

// GetCaptureParam returns streaming capture parameter information
func (d *Device) GetCaptureParam() (CaptureParam, error) {
if err := d.assertVideoCaptureSupport(); err != nil {
return CaptureParam{}, fmt.Errorf("device: %w", err)
}
return GetStreamCaptureParam(d.fd)
}

func (d *Device) StartStream(buffSize uint32) error {
if d.streaming {
return nil
Expand Down
4 changes: 2 additions & 2 deletions v4l2/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ var (

func parseErrorType(errno sys.Errno) error {
switch errno {
case sys.EBADF, sys.ENOMEM, sys.ENODEV, sys.EIO, sys.ENXIO: // structural, terminal
case sys.EBADF, sys.ENOMEM, sys.ENODEV, sys.EIO, sys.ENXIO, sys.EFAULT: // structural, terminal
return ErrorSystem
case sys.EFAULT, sys.EINVAL: // bad argument, terminal
case sys.EINVAL: // bad argument
return ErrorBadArgument
case sys.ENOTTY: // unsupported
return ErrorUnsupported
Expand Down
Loading

0 comments on commit aab6d9c

Please sign in to comment.