mirror of
https://github.com/gen2brain/cam2ip.git
synced 2026-01-09 08:08:33 +00:00
Add support for native V4L implementation on Linux/RPi
This commit is contained in:
@@ -11,9 +11,14 @@ or
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
* [OpenCV](http://opencv.org/) (default is version 2.x via [go-opencv](https://github.com/lazywei/go-opencv), use `-tags cv3` for [gocv](https://github.com/hybridgroup/gocv))
|
* [OpenCV](http://opencv.org/)
|
||||||
* [libjpeg-turbo](https://www.libjpeg-turbo.org/) (use `-tags jpeg` for native image/jpeg, but note that CPU usage will be much higher)
|
* [libjpeg-turbo](https://www.libjpeg-turbo.org/)
|
||||||
|
|
||||||
|
### Build tags
|
||||||
|
|
||||||
|
* `cv3` - build with OpenCV 3.x [gocv](https://github.com/hybridgroup/gocv), default is version 2.x via [go-opencv](https://github.com/lazywei/go-opencv)
|
||||||
|
* `native` - build with native Go [V4L](https://github.com/korandiz/v4l) implementation on Linux/RPi instead of `OpenCV`
|
||||||
|
* `jpeg` - build with native Go `image/jpeg` instead of `libjpeg-turbo`
|
||||||
|
|
||||||
### Download
|
### Download
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// +build !native
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -57,15 +59,12 @@ func main() {
|
|||||||
|
|
||||||
srv.Reader = vid
|
srv.Reader = vid
|
||||||
} else {
|
} else {
|
||||||
cam, err := camera.New(camera.Options{srv.Index, srv.Rotate})
|
cam, err := camera.New(camera.Options{srv.Index, srv.Rotate, srv.FrameWidth, srv.FrameHeight})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
cam.SetProperty(camera.PropFrameWidth, srv.FrameWidth)
|
|
||||||
cam.SetProperty(camera.PropFrameHeight, srv.FrameHeight)
|
|
||||||
|
|
||||||
srv.Reader = cam
|
srv.Reader = cam
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
68
cam2ip_native.go
Normal file
68
cam2ip_native.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// +build native
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/gen2brain/cam2ip/camera"
|
||||||
|
"github.com/gen2brain/cam2ip/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
name = "cam2ip"
|
||||||
|
version = "1.4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
srv := server.NewServer()
|
||||||
|
|
||||||
|
flag.IntVar(&srv.Index, "index", 0, "Camera index")
|
||||||
|
flag.IntVar(&srv.Delay, "delay", 10, "Delay between frames, in milliseconds")
|
||||||
|
flag.Float64Var(&srv.FrameWidth, "width", 640, "Frame width")
|
||||||
|
flag.Float64Var(&srv.FrameHeight, "height", 480, "Frame height")
|
||||||
|
flag.IntVar(&srv.Rotate, "rotate", 0, "Rotate image, valid values are 90, 180, 270")
|
||||||
|
flag.BoolVar(&srv.NoWebGL, "nowebgl", false, "Disable WebGL drawing of images (html handler)")
|
||||||
|
flag.StringVar(&srv.Bind, "bind-addr", ":56000", "Bind address")
|
||||||
|
flag.StringVar(&srv.Htpasswd, "htpasswd-file", "", "Path to htpasswd file, if empty auth is disabled")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
srv.Name = name
|
||||||
|
srv.Version = version
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if srv.Htpasswd != "" {
|
||||||
|
if _, err = os.Stat(srv.Htpasswd); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if srv.FileName != "" {
|
||||||
|
if _, err = os.Stat(srv.FileName); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cam, err := camera.New(camera.Options{srv.Index, srv.Rotate, srv.FrameWidth, srv.FrameHeight})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
srv.Reader = cam
|
||||||
|
|
||||||
|
defer srv.Reader.Close()
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "Listening on %s\n", srv.Bind)
|
||||||
|
|
||||||
|
err = srv.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// +build !cv3
|
// +build !cv3,!native
|
||||||
|
|
||||||
// Package camera.
|
// Package camera.
|
||||||
package camera
|
package camera
|
||||||
@@ -15,6 +15,8 @@ import (
|
|||||||
type Options struct {
|
type Options struct {
|
||||||
Index int
|
Index int
|
||||||
Rotate int
|
Rotate int
|
||||||
|
Width float64
|
||||||
|
Height float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Camera represents camera.
|
// Camera represents camera.
|
||||||
@@ -34,6 +36,9 @@ func New(opts Options) (camera *Camera, err error) {
|
|||||||
err = fmt.Errorf("camera: can not open camera %d", opts.Index)
|
err = fmt.Errorf("camera: can not open camera %d", opts.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
camera.SetProperty(PropFrameWidth, opts.Width)
|
||||||
|
camera.SetProperty(PropFrameHeight, opts.Height)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +48,7 @@ func (c *Camera) Read() (img image.Image, err error) {
|
|||||||
c.frame = c.camera.RetrieveFrame(1)
|
c.frame = c.camera.RetrieveFrame(1)
|
||||||
|
|
||||||
if c.frame == nil {
|
if c.frame == nil {
|
||||||
err = fmt.Errorf("camera: can not grab frame")
|
err = fmt.Errorf("camera: can not retrieve frame")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// +build !native
|
||||||
|
|
||||||
package camera
|
package camera
|
||||||
|
|
||||||
// Property identifiers.
|
// Property identifiers.
|
||||||
|
|||||||
21
camera/camera_const_native.go
Normal file
21
camera/camera_const_native.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// +build native
|
||||||
|
|
||||||
|
package camera
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/korandiz/v4l"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Property identifiers.
|
||||||
|
const (
|
||||||
|
PropBrightness = v4l.CtrlBrightness
|
||||||
|
PropContrast = v4l.CtrlContrast
|
||||||
|
PropSaturation = v4l.CtrlSaturation
|
||||||
|
PropHue = v4l.CtrlHue
|
||||||
|
PropGain = v4l.CtrlGain
|
||||||
|
PropExposure = v4l.CtrlExposure
|
||||||
|
PropWhiteBalanceU = v4l.CtrlWhiteBalance
|
||||||
|
PropSharpness = v4l.CtrlSharpness
|
||||||
|
PropWhiteBalanceV = v4l.CtrlDoWhiteBalance
|
||||||
|
PropBacklight = v4l.CtrlBacklightCompensation
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// +build cv3
|
// +build cv3,!native
|
||||||
|
|
||||||
// Package camera.
|
// Package camera.
|
||||||
package camera
|
package camera
|
||||||
@@ -15,6 +15,8 @@ import (
|
|||||||
type Options struct {
|
type Options struct {
|
||||||
Index int
|
Index int
|
||||||
Rotate int
|
Rotate int
|
||||||
|
Width float64
|
||||||
|
Height float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Camera represents camera.
|
// Camera represents camera.
|
||||||
@@ -37,6 +39,9 @@ func New(opts Options) (camera *Camera, err error) {
|
|||||||
err = fmt.Errorf("camera: can not open camera %d: %s", opts.Index, err.Error())
|
err = fmt.Errorf("camera: can not open camera %d: %s", opts.Index, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
camera.SetProperty(PropFrameWidth, opts.Width)
|
||||||
|
camera.SetProperty(PropFrameHeight, opts.Height)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +60,7 @@ func (c *Camera) Read() (img image.Image, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.frame == nil {
|
if c.frame == nil {
|
||||||
err = fmt.Errorf("camera: can not grab frame")
|
err = fmt.Errorf("camera: can not retrieve frame")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
132
camera/camera_native_linux.go
Normal file
132
camera/camera_native_linux.go
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// +build native
|
||||||
|
|
||||||
|
// Package camera.
|
||||||
|
package camera
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
|
"github.com/korandiz/v4l"
|
||||||
|
"github.com/korandiz/v4l/fmt/mjpeg"
|
||||||
|
|
||||||
|
im "github.com/gen2brain/cam2ip/image"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options.
|
||||||
|
type Options struct {
|
||||||
|
Index int
|
||||||
|
Rotate int
|
||||||
|
Width float64
|
||||||
|
Height float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Camera represents camera.
|
||||||
|
type Camera struct {
|
||||||
|
opts Options
|
||||||
|
camera *v4l.Device
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns new Camera for given camera index.
|
||||||
|
func New(opts Options) (camera *Camera, err error) {
|
||||||
|
camera = &Camera{}
|
||||||
|
camera.opts = opts
|
||||||
|
|
||||||
|
devices := v4l.FindDevices()
|
||||||
|
if len(devices) < opts.Index+1 {
|
||||||
|
err = fmt.Errorf("camera: no camera at index %d", opts.Index)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
camera.camera, err = v4l.Open(devices[opts.Index].Path)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if camera.camera == nil {
|
||||||
|
err = fmt.Errorf("camera: can not open camera %d", opts.Index)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config, err := camera.camera.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Format = mjpeg.FourCC
|
||||||
|
config.Width = int(opts.Width)
|
||||||
|
config.Height = int(opts.Height)
|
||||||
|
|
||||||
|
err = camera.camera.SetConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = camera.camera.TurnOn()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads next frame from camera and returns image.
|
||||||
|
func (c *Camera) Read() (img image.Image, err error) {
|
||||||
|
|
||||||
|
buffer, err := c.camera.Capture()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: can not grab frame: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img, err = im.NewDecoder(buffer).Decode()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.opts.Rotate == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c.opts.Rotate {
|
||||||
|
case 90:
|
||||||
|
img = imaging.Rotate90(img)
|
||||||
|
case 180:
|
||||||
|
img = imaging.Rotate180(img)
|
||||||
|
case 270:
|
||||||
|
img = imaging.Rotate270(img)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProperty returns the specified camera property.
|
||||||
|
func (c *Camera) GetProperty(id int) float64 {
|
||||||
|
ret, _ := c.camera.GetControl(uint32(id))
|
||||||
|
return float64(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperty sets a camera property.
|
||||||
|
func (c *Camera) SetProperty(id int, value float64) {
|
||||||
|
c.camera.SetControl(uint32(id), int32(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes camera.
|
||||||
|
func (c *Camera) Close() (err error) {
|
||||||
|
if c.camera == nil {
|
||||||
|
err = fmt.Errorf("camera: camera is not opened")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.camera.TurnOff()
|
||||||
|
|
||||||
|
c.camera.Close()
|
||||||
|
c.camera = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestCamera(t *testing.T) {
|
func TestCamera(t *testing.T) {
|
||||||
camera, err := New(1)
|
camera, err := New(Options{0, 0, 640, 480})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -25,18 +25,6 @@ func TestCamera(t *testing.T) {
|
|||||||
|
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
var width, height float64 = 640, 480
|
|
||||||
camera.SetProperty(PropFrameWidth, width)
|
|
||||||
camera.SetProperty(PropFrameHeight, height)
|
|
||||||
|
|
||||||
if camera.GetProperty(PropFrameWidth) != width {
|
|
||||||
t.Error("FrameWidth not correct")
|
|
||||||
}
|
|
||||||
|
|
||||||
if camera.GetProperty(PropFrameHeight) != height {
|
|
||||||
t.Error("FrameHeight not correct")
|
|
||||||
}
|
|
||||||
|
|
||||||
var i int
|
var i int
|
||||||
var n int = 10
|
var n int = 10
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gen2brain/cam2ip/encoder"
|
"github.com/gen2brain/cam2ip/image"
|
||||||
"github.com/gen2brain/cam2ip/reader"
|
"github.com/gen2brain/cam2ip/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ func (j *JPEG) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = encoder.New(w).Encode(img)
|
err = image.NewEncoder(w).Encode(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("jpeg: encode: %v", err)
|
log.Printf("jpeg: encode: %v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"net/textproto"
|
"net/textproto"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gen2brain/cam2ip/encoder"
|
"github.com/gen2brain/cam2ip/image"
|
||||||
"github.com/gen2brain/cam2ip/reader"
|
"github.com/gen2brain/cam2ip/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ loop:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = encoder.New(partWriter).Encode(img)
|
err = image.NewEncoder(partWriter).Encode(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("mjpeg: encode: %v", err)
|
log.Printf("mjpeg: encode: %v", err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
|
|
||||||
"github.com/gen2brain/cam2ip/encoder"
|
"github.com/gen2brain/cam2ip/image"
|
||||||
"github.com/gen2brain/cam2ip/reader"
|
"github.com/gen2brain/cam2ip/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ func (s *Socket) write(ws *websocket.Conn) {
|
|||||||
|
|
||||||
w := new(bytes.Buffer)
|
w := new(bytes.Buffer)
|
||||||
|
|
||||||
err = encoder.New(w).Encode(img)
|
err = image.NewEncoder(w).Encode(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("socket: encode: %v", err)
|
log.Printf("socket: encode: %v", err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
"goost.org/encoding/base64"
|
"goost.org/encoding/base64"
|
||||||
|
|
||||||
"github.com/gen2brain/cam2ip/encoder"
|
"github.com/gen2brain/cam2ip/image"
|
||||||
"github.com/gen2brain/cam2ip/reader"
|
"github.com/gen2brain/cam2ip/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ func (s *Socket) write(ws *websocket.Conn) {
|
|||||||
|
|
||||||
w := new(bytes.Buffer)
|
w := new(bytes.Buffer)
|
||||||
|
|
||||||
err = encoder.New(w).Encode(img)
|
err = image.NewEncoder(w).Encode(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("socket: encode: %v", err)
|
log.Printf("socket: encode: %v", err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
26
image/decode.go
Normal file
26
image/decode.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// +build !jpeg
|
||||||
|
|
||||||
|
// Package image.
|
||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
jpeg "github.com/antonini/golibjpegturbo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewDecoder returns a new Decoder.
|
||||||
|
func NewDecoder(r io.Reader) *Decoder {
|
||||||
|
return &Decoder{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoder struct.
|
||||||
|
type Decoder struct {
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes image from JPEG.
|
||||||
|
func (d Decoder) Decode() (image.Image, error) {
|
||||||
|
return jpeg.Decode(d.r)
|
||||||
|
}
|
||||||
25
image/decode_jpeg.go
Normal file
25
image/decode_jpeg.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// +build jpeg
|
||||||
|
|
||||||
|
// Package image.
|
||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/jpeg"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewDecoder returns a new Decoder.
|
||||||
|
func NewDecoder(r io.Reader) *Decoder {
|
||||||
|
return &Decoder{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoder struct.
|
||||||
|
type Decoder struct {
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes image from JPEG.
|
||||||
|
func (d Decoder) Decode() (image.Image, error) {
|
||||||
|
return jpeg.Decode(d.r)
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build !jpeg
|
// +build !jpeg
|
||||||
|
|
||||||
// Package encoder.
|
// Package image.
|
||||||
package encoder
|
package image
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
jpeg "github.com/antonini/golibjpegturbo"
|
jpeg "github.com/antonini/golibjpegturbo"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a new Encoder.
|
// NewEncoder returns a new Encoder.
|
||||||
func New(w io.Writer) *Encoder {
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
return &Encoder{w}
|
return &Encoder{w}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// +build jpeg
|
// +build jpeg
|
||||||
|
|
||||||
// Package encoder.
|
// Package image.
|
||||||
package encoder
|
package image
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a new Encoder.
|
// NewEncoder returns a new Encoder.
|
||||||
func New(w io.Writer) *Encoder {
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
return &Encoder{w}
|
return &Encoder{w}
|
||||||
}
|
}
|
||||||
|
|
||||||
33
make.bash
33
make.bash
@@ -13,7 +13,14 @@ PKG_CONFIG_PATH="$CHROOT/usr/lib/pkgconfig" \
|
|||||||
PKG_CONFIG_LIBDIR="$CHROOT/usr/lib/pkgconfig" \
|
PKG_CONFIG_LIBDIR="$CHROOT/usr/lib/pkgconfig" \
|
||||||
CGO_LDFLAGS="-L$CHROOT/usr/lib -L$CHROOT/lib" \
|
CGO_LDFLAGS="-L$CHROOT/usr/lib -L$CHROOT/lib" \
|
||||||
CGO_CFLAGS="-I$CHROOT/usr/include" \
|
CGO_CFLAGS="-I$CHROOT/usr/include" \
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -v -x -o build/cam2ip.linux.amd64 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o build/cam2ip.linux.amd64 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
|
LIBRARY_PATH="$CHROOT/usr/lib:$CHROOT/lib" \
|
||||||
|
PKG_CONFIG_PATH="$CHROOT/usr/lib/pkgconfig" \
|
||||||
|
PKG_CONFIG_LIBDIR="$CHROOT/usr/lib/pkgconfig" \
|
||||||
|
CGO_LDFLAGS="-L$CHROOT/usr/lib -L$CHROOT/lib" \
|
||||||
|
CGO_CFLAGS="-I$CHROOT/usr/include" \
|
||||||
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags native -o build/cam2ip.linux.native.amd64 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
PKG_CONFIG="/usr/bin/i686-w64-mingw32-pkg-config" \
|
PKG_CONFIG="/usr/bin/i686-w64-mingw32-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$MINGW/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$MINGW/usr/lib/pkgconfig" \
|
||||||
@@ -21,7 +28,7 @@ PKG_CONFIG_LIBDIR="$MINGW/usr/lib/pkgconfig" \
|
|||||||
CGO_LDFLAGS="-L$MINGW/usr/lib" \
|
CGO_LDFLAGS="-L$MINGW/usr/lib" \
|
||||||
CGO_CFLAGS="-I$MINGW/usr/include" \
|
CGO_CFLAGS="-I$MINGW/usr/include" \
|
||||||
CC="i686-w64-mingw32-gcc" CXX="i686-w64-mingw32-g++" \
|
CC="i686-w64-mingw32-gcc" CXX="i686-w64-mingw32-g++" \
|
||||||
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -v -x -o build/cam2ip.exe -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -o build/cam2ip.exe -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
PKG_CONFIG="/usr/bin/x86_64-w64-mingw32-pkg-config" \
|
PKG_CONFIG="/usr/bin/x86_64-w64-mingw32-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$MINGW64/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$MINGW64/usr/lib/pkgconfig" \
|
||||||
@@ -29,7 +36,7 @@ PKG_CONFIG_LIBDIR="$MINGW64/usr/lib/pkgconfig" \
|
|||||||
CGO_LDFLAGS="-L$MINGW64/usr/lib" \
|
CGO_LDFLAGS="-L$MINGW64/usr/lib" \
|
||||||
CGO_CFLAGS="-I$MINGW64/usr/include" \
|
CGO_CFLAGS="-I$MINGW64/usr/include" \
|
||||||
CC="x86_64-w64-mingw32-gcc" CXX="x86_64-w64-mingw32-g++" \
|
CC="x86_64-w64-mingw32-gcc" CXX="x86_64-w64-mingw32-g++" \
|
||||||
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -v -x -o build/cam2ip.exe.amd64 -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -o build/cam2ip.exe.amd64 -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
PKG_CONFIG="/usr/bin/armv6j-hardfloat-linux-gnueabi-pkg-config" \
|
PKG_CONFIG="/usr/bin/armv6j-hardfloat-linux-gnueabi-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$RPI/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$RPI/usr/lib/pkgconfig" \
|
||||||
@@ -37,7 +44,15 @@ PKG_CONFIG_LIBDIR="$RPI/usr/lib/pkgconfig" \
|
|||||||
CGO_LDFLAGS="-L$RPI/usr/lib" \
|
CGO_LDFLAGS="-L$RPI/usr/lib" \
|
||||||
CGO_CFLAGS="-I$RPI/usr/include" \
|
CGO_CFLAGS="-I$RPI/usr/include" \
|
||||||
CC="armv6j-hardfloat-linux-gnueabi-gcc" CXX="armv6j-hardfloat-linux-gnueabi-g++" \
|
CC="armv6j-hardfloat-linux-gnueabi-gcc" CXX="armv6j-hardfloat-linux-gnueabi-g++" \
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -v -x -o build/cam2ip.linux.arm -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -o build/cam2ip.linux.arm -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
|
PKG_CONFIG="/usr/bin/armv6j-hardfloat-linux-gnueabi-pkg-config" \
|
||||||
|
PKG_CONFIG_PATH="$RPI/usr/lib/pkgconfig" \
|
||||||
|
PKG_CONFIG_LIBDIR="$RPI/usr/lib/pkgconfig" \
|
||||||
|
CGO_LDFLAGS="-L$RPI/usr/lib" \
|
||||||
|
CGO_CFLAGS="-I$RPI/usr/include" \
|
||||||
|
CC="armv6j-hardfloat-linux-gnueabi-gcc" CXX="armv6j-hardfloat-linux-gnueabi-g++" \
|
||||||
|
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -tags native -o build/cam2ip.linux.native.arm -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
PKG_CONFIG="/usr/bin/armv7a-hardfloat-linux-gnueabi-pkg-config" \
|
PKG_CONFIG="/usr/bin/armv7a-hardfloat-linux-gnueabi-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$RPI3/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$RPI3/usr/lib/pkgconfig" \
|
||||||
@@ -45,4 +60,12 @@ PKG_CONFIG_LIBDIR="$RPI3/usr/lib/pkgconfig" \
|
|||||||
CGO_LDFLAGS="-L$RPI3/usr/lib" \
|
CGO_LDFLAGS="-L$RPI3/usr/lib" \
|
||||||
CGO_CFLAGS="-I$RPI3/usr/include" \
|
CGO_CFLAGS="-I$RPI3/usr/include" \
|
||||||
CC="armv7a-hardfloat-linux-gnueabi-gcc" CXX="armv7a-hardfloat-linux-gnueabi-g++" \
|
CC="armv7a-hardfloat-linux-gnueabi-gcc" CXX="armv7a-hardfloat-linux-gnueabi-g++" \
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -v -x -o build/cam2ip.linux.arm7 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -o build/cam2ip.linux.arm7 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
|
PKG_CONFIG="/usr/bin/armv7a-hardfloat-linux-gnueabi-pkg-config" \
|
||||||
|
PKG_CONFIG_PATH="$RPI3/usr/lib/pkgconfig" \
|
||||||
|
PKG_CONFIG_LIBDIR="$RPI3/usr/lib/pkgconfig" \
|
||||||
|
CGO_LDFLAGS="-L$RPI3/usr/lib" \
|
||||||
|
CGO_CFLAGS="-I$RPI3/usr/include" \
|
||||||
|
CC="armv7a-hardfloat-linux-gnueabi-gcc" CXX="armv7a-hardfloat-linux-gnueabi-g++" \
|
||||||
|
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -tags native -o build/cam2ip.linux.native.arm7 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// +build !cv3
|
// +build !cv3,!native
|
||||||
|
|
||||||
// Package video.
|
// Package video.
|
||||||
package video
|
package video
|
||||||
@@ -42,7 +42,7 @@ func (v *Video) Read() (img image.Image, err error) {
|
|||||||
if v.video.GrabFrame() {
|
if v.video.GrabFrame() {
|
||||||
v.frame = v.video.RetrieveFrame(1)
|
v.frame = v.video.RetrieveFrame(1)
|
||||||
if v.frame == nil {
|
if v.frame == nil {
|
||||||
err = fmt.Errorf("video: can not grab frame")
|
err = fmt.Errorf("video: can not retrieve frame")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// +build cv3
|
// +build cv3,!native
|
||||||
|
|
||||||
// Package video.
|
// Package video.
|
||||||
package video
|
package video
|
||||||
@@ -49,7 +49,7 @@ func (v *Video) Read() (img image.Image, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v.frame == nil {
|
if v.frame == nil {
|
||||||
err = fmt.Errorf("video: can not grab frame")
|
err = fmt.Errorf("video: can not retrieve frame")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestVideo(t *testing.T) {
|
func TestVideo(t *testing.T) {
|
||||||
video, err := New("test.mp4")
|
video, err := New(video.Options{"test.mp4", 0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user