0

I'm building an app that is capturing frames from any v4l2 supported webcam. I'm controlling the camera with v4l2 (golang package https://github.com/blackjack/webcam) and one of the things I need is pixel format. However, what I get is uint32 representing the format in v4l2.

I do the streaming by wrapping ffmpeg command and reading from its stdout:

args := []string{
    "-f", "v4l2",
    "-c:v", "rawvideo",
    "-pix_fmt", pixFmt,
    "-s", size,
    "-i", input,
    "-f", "image2pipe",
    "-c:v", "mjpeg",
    "-qscale:v", "5",
    "-", // pipes to stdout
}

cmd := exec.Command("ffmpeg", args...)

Now the problem is that -pix_fmt option requires format name in string that is recognized by ffmpeg (for example 8-bit Bayer RGGB8 corresponds to bayer_rggb8, while this format in v4l2 has code 1111967570).

I found the mapping code for it in ffmpeg's libavdevice: https://github.com/FFmpeg/FFmpeg/blob/master/libavdevice/v4l2-common.h includes the functions I need, but somehow I'm not able to include <libavdevice/v4l2-common.h> in CGo (no problems with <libavdevice/avdevice.h>):

package conv

/*
    #cgo pkg-config: libavdevice
    #include <libavdevice/avdevice.h>
    #include <libavdevice/v4l2-common.h>
*/
import "C"

type (
)

// PixFmtToFF takes v4l2 pixel format code and converts it to a string
// recognized by ffmpeg command
// example: 1111967570 to "bayer_rggb8"
func PixFmtToFF(v4l2code uint32) (string, error) {
    // should work something like this, couldn't test
    codecID := C.ff_fmt_v4l2codec(v4l2code)
    pixFmt := C.ff_fmt_v4l2ff(vfd.pixelformat, codec_id)
    return C.av_get_pix_fmt_name(pixFmt)
}

Build output returns:

go build \
        -mod=vendor \
        -o ./bin/camera-api \
        ./cmd/camera-api
# kca/internal/camera/conv
internal/camera/conv/convert.go:6:11: fatal error: libavdevice/v4l2-common.h: No such file or directory
  #include <libavdevice/v4l2-common.h>
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:13: build/camera-api] Error 2
make: *** [builder/camera-api] Error 2

Output of pkg-config --libs libavdevice is -L/usr/local/lib -lavdevice.

So, I have two questions:

1) How could I include v4l2-common.h so I can use the mapping functions?

2) Is there a better way? I need ffmpeg wrapping so we can support wide range of formats for captured frames.

DekiChan
  • 375
  • 1
  • 4
  • 14
  • Why not use ffmpeg to tell you the supported pixel format(s)? `ffmpeg -f v4l2 -list_formats all -i /dev/video0` Do you even need to declare `-pixel_format` input option? – llogan Dec 12 '19 at 20:09
  • @llogan I'd rather not parse the text output from ffmpeg since the devices connected are not predetermined (there could be more of them, different models) and device identification is happening inside the app, not manually. `-pixel_format` is necessary because sometimes source format could be RAW (such as bayer_rggb8) and in this case ffmpeg cannot determine the format on its own. – DekiChan Dec 13 '19 at 06:53

0 Answers0