Add support H264, H265, NV12 for V4L2 source #1546
This commit is contained in:
@@ -11,8 +11,9 @@ import (
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
fd int
|
||||
bufs [][]byte
|
||||
fd int
|
||||
bufs [][]byte
|
||||
pixFmt uint32
|
||||
}
|
||||
|
||||
func Open(path string) (*Device, error) {
|
||||
@@ -119,6 +120,8 @@ func (d *Device) ListFrameRates(pixFmt, width, height uint32) ([]uint32, error)
|
||||
}
|
||||
|
||||
func (d *Device) SetFormat(width, height, pixFmt uint32) error {
|
||||
d.pixFmt = pixFmt
|
||||
|
||||
f := v4l2_format{
|
||||
typ: V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
pix: v4l2_pix_format{
|
||||
@@ -196,7 +199,7 @@ func (d *Device) StreamOff() (err error) {
|
||||
return ioctl(d.fd, VIDIOC_REQBUFS, unsafe.Pointer(&rb))
|
||||
}
|
||||
|
||||
func (d *Device) Capture(planarYUV bool) ([]byte, error) {
|
||||
func (d *Device) Capture() ([]byte, error) {
|
||||
dec := v4l2_buffer{
|
||||
typ: V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
memory: V4L2_MEMORY_MMAP,
|
||||
@@ -205,11 +208,16 @@ func (d *Device) Capture(planarYUV bool) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := make([]byte, dec.bytesused)
|
||||
if planarYUV {
|
||||
YUYV2YUV(buf, d.bufs[dec.index][:dec.bytesused])
|
||||
} else {
|
||||
copy(buf, d.bufs[dec.index][:dec.bytesused])
|
||||
src := d.bufs[dec.index][:dec.bytesused]
|
||||
dst := make([]byte, dec.bytesused)
|
||||
|
||||
switch d.pixFmt {
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
YUYVtoYUV(dst, src)
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
NV12toYUV(dst, src)
|
||||
default:
|
||||
copy(dst, d.bufs[dec.index][:dec.bytesused])
|
||||
}
|
||||
|
||||
enc := v4l2_buffer{
|
||||
@@ -221,7 +229,7 @@ func (d *Device) Capture(planarYUV bool) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (d *Device) Close() error {
|
||||
|
||||
@@ -2,7 +2,10 @@ package device
|
||||
|
||||
const (
|
||||
V4L2_PIX_FMT_YUYV = 'Y' | 'U'<<8 | 'Y'<<16 | 'V'<<24
|
||||
V4L2_PIX_FMT_NV12 = 'N' | 'V'<<8 | '1'<<16 | '2'<<24
|
||||
V4L2_PIX_FMT_MJPEG = 'M' | 'J'<<8 | 'P'<<16 | 'G'<<24
|
||||
V4L2_PIX_FMT_H264 = 'H' | '2'<<8 | '6'<<16 | '4'<<24
|
||||
V4L2_PIX_FMT_HEVC = 'H' | 'E'<<8 | 'V'<<16 | 'C'<<24
|
||||
)
|
||||
|
||||
type Format struct {
|
||||
@@ -13,11 +16,13 @@ type Format struct {
|
||||
|
||||
var Formats = []Format{
|
||||
{V4L2_PIX_FMT_YUYV, "YUV 4:2:2", "yuyv422"},
|
||||
{V4L2_PIX_FMT_NV12, "Y/UV 4:2:0", "nv12"},
|
||||
{V4L2_PIX_FMT_MJPEG, "Motion-JPEG", "mjpeg"},
|
||||
{V4L2_PIX_FMT_H264, "H.264", "h264"},
|
||||
{V4L2_PIX_FMT_HEVC, "HEVC", "hevc"},
|
||||
}
|
||||
|
||||
// YUYV2YUV convert packed YUV to planar YUV
|
||||
func YUYV2YUV(dst, src []byte) {
|
||||
func YUYVtoYUV(dst, src []byte) {
|
||||
n := len(src)
|
||||
i0 := 0
|
||||
iy := 0
|
||||
@@ -38,3 +43,20 @@ func YUYV2YUV(dst, src []byte) {
|
||||
iv++
|
||||
}
|
||||
}
|
||||
|
||||
func NV12toYUV(dst, src []byte) {
|
||||
n := len(src)
|
||||
k := n / 6
|
||||
i0 := k * 4
|
||||
iu := i0
|
||||
iv := i0 + k
|
||||
copy(dst, src[:i0]) // copy Y
|
||||
for i0 < n {
|
||||
dst[iu] = src[i0]
|
||||
i0++
|
||||
iu++
|
||||
dst[iv] = src[i0]
|
||||
i0++
|
||||
iv++
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user