2
0
Vladimir Vivien 2 жил өмнө
parent
commit
7ccb61c632

+ 22 - 64
README.md

@@ -28,28 +28,13 @@ It hides all the complexities of working with V4L2 and provides idiomatic Go typ
 * Kernel minimum v5.10.x
 * Kernel minimum v5.10.x
 * A locally configured C compiler (or a cross-compiler if building off-device)
 * A locally configured C compiler (or a cross-compiler if building off-device)
 
 
-See [example/simplecam](./examples/simplecam/README.md) for further example of building projects that uses go4vl including cross-compilation instructions.
+See [example/README.md](./examples/README.md) for further example of how to build projects that uses go4vl, including cross-compilation.
 
 
 All examples have been tested using a Raspberry PI 3, running 32-bit Raspberry PI OS.
 All examples have been tested using a Raspberry PI 3, running 32-bit Raspberry PI OS.
 The package should work with no problem on your 64-bit Linux OS.
 The package should work with no problem on your 64-bit Linux OS.
 
 
 ## Getting started
 ## Getting started
 
 
-### System upgrade
-
-To avoid issues with old header files on your machine, upgrade your system to pull down the latest OS packages
-with something similar to the following (follow directions for your system for proper upgrade):
-
-```shell
-sudo apt update
-sudo apt full-upgrade
-```
-
-Install the `build-essential` package to install required C compilers:
-```shell
-sudo apt install build-essential
-```
-
 ### Using the go4vl package
 ### Using the go4vl package
 
 
 To include `go4vl` in your own code, `go get` the package:
 To include `go4vl` in your own code, `go get` the package:
@@ -60,70 +45,43 @@ go get github.com/vladimirvivien/go4vl/v4l2
 
 
 ## Video capture example
 ## Video capture example
 
 
-The following is a simple example that captures video data from an attached camera device to
-and saves the captured frames as JPEG files. 
+The following is a simple example that shows how to capture a single frame from an attached camera device
+and save the image to a file. 
 
 
 The example assumes the attached device supports JPEG (MJPEG) output format inherently.
 The example assumes the attached device supports JPEG (MJPEG) output format inherently.
 
 
 ```go
 ```go
 func main() {
 func main() {
-	devName := "/dev/video0"
-	flag.StringVar(&devName, "d", devName, "device name (path)")
-	flag.Parse()
-
-	// open device
-	device, err := device.Open(
-		devName,
-		device.WithPixFormat(v4l2.PixFormat{PixelFormat: v4l2.PixelFmtMPEG, Width: 640, Height: 480}),
-	)
+	dev, err := device.Open("/dev/video0", device.WithBufferSize(1))
 	if err != nil {
 	if err != nil {
-		log.Fatalf("failed to open device: %s", err)
+		log.Fatal(err)
 	}
 	}
-	defer device.Close()
+	defer dev.Close()
 
 
-	// start stream with cancellable context
-	ctx, stop := context.WithCancel(context.TODO())
-	if err := device.Start(ctx); err != nil {
-		log.Fatalf("failed to start stream: %s", err)
+	if err := dev.Start(context.TODO()); err != nil {
+		log.Fatal(err)
 	}
 	}
 
 
-	// process frames from capture channel
-	totalFrames := 10
-	count := 0
-	log.Printf("Capturing %d frames...", totalFrames)
-
-	for frame := range device.GetOutput() {
-		fileName := fmt.Sprintf("capture_%d.jpg", count)
-		file, err := os.Create(fileName)
-		if err != nil {
-			log.Printf("failed to create file %s: %s", fileName, err)
-			continue
-		}
-		if _, err := file.Write(frame); err != nil {
-			log.Printf("failed to write file %s: %s", fileName, err)
-			continue
-		}
-		log.Printf("Saved file: %s", fileName)
-		if err := file.Close(); err != nil {
-			log.Printf("failed to close file %s: %s", fileName, err)
-		}
-		count++
-		if count >= totalFrames {
-			break
-		}
+	// capture frame
+	frame := <-dev.GetOutput()
+
+	file, err := os.Create("pic.jpg")
+	if err != nil {
+		log.Fatal(err)
 	}
 	}
+	defer file.Close()
 
 
-	stop() // stop capture
-	fmt.Println("Done.")
+	if _, err := file.Write(frame); err != nil {
+		log.Fatal(err)
+	}
 }
 }
 ```
 ```
 
 
-> Read a detail walk-through about this example [here](./examples/capture0/README.md).
+> See complete example [here](./examples/snapshot/snap.go).
 
 
-### Other examples
-The [./examples](./examples/README.md) directory contains additional examples including:
-* [device_info](./examples/device_info/README.md) - queries and prints video device information
-* [webcam](./examples/webcam/README.md) - uses the v4l2 package to create a simple webcam that streams images from an attached camera accessible via a web page.
+## Examples
+This repository comes with several examples that show how to use the API to build Go programs that can capture images from Linux.
+> See list of [examples](./examples/README.md)
 
 
 ## Roadmap
 ## Roadmap
 The main goal is to port as many functionalities as possible so that 
 The main goal is to port as many functionalities as possible so that 

+ 4 - 3
TODO.md

@@ -5,8 +5,9 @@ A general list (of no implied order) of high level tasks for the project.
 * [x] Create device package
 * [x] Create device package
 * [x] List/query device available
 * [x] List/query device available
 * [x] Add repo documentation
 * [x] Add repo documentation
-* [ ] Document examples 
+* [x] Document examples 
 * [ ] Support for YUYV conversion
 * [ ] Support for YUYV conversion
-* [ ] Set and query device controls
+* [x] Set and query device controls
 * [ ] Support for User pointer and other stream mode
 * [ ] Support for User pointer and other stream mode
-* [x] Use cgo-generated Go types to avoid alignment bugs
+* [x] Use cgo-generated Go types to avoid alignment bugs
+* [ ] Pre-generate cgo code

+ 0 - 11
build.sh

@@ -1,11 +0,0 @@
-# docker run --rm --platform=linux/amd64 \
-#   -v "$(pwd):/myapp" \
-#   -w /myapp \
-#   -e GOOS=linux -e GOARCH=arm \
-#   golang:1.19 go build -v ./examples/simplecam
-
-CGO_ENABLED=1 \
-    GOOS=linux \
-    GOARCH=arm \
-    CC="zig cc -target arm-linux-musleabihf"\
-    CXX="zig c++ -target arm-linux-musleabihf" go build .

+ 41 - 4
examples/README.md

@@ -1,6 +1,43 @@
 # Examples
 # Examples
 
 
-* [capture0](./capture0) - simple capture example with hardcoded pixel format
-* [capture1](./capture1) - capture example with preferred format search
-* [device_info](./device_info) - uses go4vl to retrieve device and format info
-* [webcam](./webcam) - use go4vl to build a working webcam example
+* [snapshot](./snapshot/) - A simple example to capture a single frame and save it to a file.
+* [capture0](./capture0) - Shows how to capture multiple images and saves them to files.
+* [capture1](./capture1) - Shows how to capture multiple images using specified image format.
+* [device_info](./device_info) - Uses go4vl to query and print device and format information.
+* [format](./format) - Shows how to query and apply device and format information.
+* [ext_ctrls](./ext_ctrls/) Shows how to query and apply extended controls.
+* [user_ctrl](./user_ctrl/) Shows how to query and apply user controls.
+* [simplecam](./simplecam/) A functional webcam program that streams video to web page.
+* [webcam](./webcam) - Builds on simplecam and adds image control, format control, and face detection.
+
+## Building your code
+
+There are three ways to build the example.
+
+### On device builds
+One of the easiest ways to get started is to setup your Linux workstation, or device, with Go to build your source code directly there.
+
+Install the `build-essential` package to install required C compilers:
+```shell
+sudo apt install build-essential
+```
+Also, upgrade your system to pull down the latest OS packages (follow directions for your system-specific steps):
+
+```
+sudo apt update
+sudo apt full-upgrade
+```
+
+### Cross-compile with Zig toolchain
+The Zig language comes with a full C/C++ cross-compiler including flag compatibility with gcc and clang. It can be used as a drop-in replacement for those compilers allowing easy cross-compilation of source code.
+
+Zig cross-compilers can be used for building CGo-enabled Go code with little fuss. Assuming you have the Zig build tools installed, you can cross-compile the code in this directory as shown below:
+
+```
+CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 CC="zig cc -target arm-linux-musleabihf" CXX="zig c++ -target arm-linux-musleabihf" go build -o simple-cam ./simplecam
+```
+
+The previous build command will create a static binary that can run on Linux for the Arm/v7 architecture.
+
+### Cross-compile with Docker
+There are some Docker images that you can use to properly cross-compile your code. Example [./simplecam](./simplecam/Dockerfile) includes a Dockerfile that uses image `crazymax/goxx` to cross-compile go4vl code.

+ 2 - 3
examples/capture0/README.md

@@ -1,6 +1,6 @@
 # Capture example
 # Capture example
 
 
-This example shows how to use the `go4vl` API to create a simple program that captures a video frames from an attached input (camera) device.
+This example shows how to use the `go4vl` API to create a simple program that captures several video frames, from an attached input (camera) device, and save them to  files.
 
 
 Firstly, the source code opens a device, `devName`, with a hard-coded pixel format (MPEG) and size. If the device does not support 
 Firstly, the source code opens a device, `devName`, with a hard-coded pixel format (MPEG) and size. If the device does not support 
 the specified format, the open operation will fail, returning an error.
 the specified format, the open operation will fail, returning an error.
@@ -34,8 +34,7 @@ func main() {
 }
 }
 ```
 ```
 
 
-Once the device starts, the code sets up a loop capture incoming video frame buffer from the input device and save each 
-frame to a local file.
+Once the device starts, the code sets up a loop to capture incoming video frame buffers from the input device and save each frame to a local file.
 
 
 ```go
 ```go
 func main() {
 func main() {

+ 1 - 1
examples/ccapture/README.md

@@ -1,6 +1,6 @@
 # V4L2 video capture example in C
 # V4L2 video capture example in C
 
 
-This an example in C showing the minimally required steps to capture video using the V4L2 framework. This can be used as a test tool to compare results between C and the Go4VL Go code.
+This an example in C showing the minimally required steps to capture video using the V4L2 framework. This C code is used as a test tool to compare results between C and the Go4VL Go code.
 
 
 ## Build and run
 ## Build and run
 On a Linux machine, run the following:
 On a Linux machine, run the following:

+ 3 - 0
examples/ext_ctrls/README.md

@@ -0,0 +1,3 @@
+# Extended controls
+
+This example shows go4vl support for extended controls. The API allows users to query and set control values.

+ 58 - 14
examples/simplecam/README.md

@@ -3,25 +3,69 @@
 This is a simple example shows how easy it is to use go4vl to 
 This is a simple example shows how easy it is to use go4vl to 
 create a simple web application to stream camera images.
 create a simple web application to stream camera images.
 
 
-## Build
-There are three ways to build the example.
+### Setup the server
 
 
-### On device
-You can always setup Go on your device and build your source code directly on the device.
+First, the code sets up a channel where the captured frames will be sent.
 
 
-### Cross-compile with Zig
-The Zig language is (itself) full C/C++ cross-compiler. With flag compatibility with gcc and clang, 
-Zig can be used as a drop-in replacement for those compilers allowing easy cross-compilation of source code.
-
-It turns out that Zig can be used as the cross-compiler for building Go code with CGo enabled. Assuming you have
-the Zig build tools installed, you can cross-compile the source code to target Linux/Arm/v7 as shown below:;
+```go
 
 
+var (
+	frames <-chan []byte
+)
 ```
 ```
-CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 CC="zig cc -target arm-linux-musleabihf" CXX="zig c++ -target arm-linux-musleabihf" go build -o simple-cam .
+
+The `main` function then sets up the device with a hard-coded JPEG image format. The function also creates a simple HTTP server that will handle incoming resource request on (default) port ":9090".
+
+```go
+func main() {
+	port := ":9090"
+	devName := "/dev/video0"
+	flag.StringVar(&devName, "d", devName, "device name (path)")
+	flag.StringVar(&port, "p", port, "webcam service port")
+
+	camera, err := device.Open(
+		devName,
+		device.WithPixFormat(v4l2.PixFormat{PixelFormat: v4l2.PixelFmtMJPEG, Width: 640, Height: 480}),
+	)
+	if err != nil {
+		log.Fatalf("failed to open device: %s", err)
+	}
+	defer camera.Close()
+
+	if err := camera.Start(context.TODO()); err != nil {
+		log.Fatalf("camera start: %s", err)
+	}
+
+	frames = camera.GetOutput()
+
+	log.Printf("Serving images: [%s/stream]", port)
+	http.HandleFunc("/stream", imageServ)
+	log.Fatal(http.ListenAndServe(port, nil))
+}
 ```
 ```
 
 
-The previous build command will create a staticly linked binary that can run on Linux for the Arm/v7 architecture:
+Lastly, the code defines the HTTP handler that will send the frames, in the channel, back to the browser as a multi-part mime stream.
+
+```go
+func imageServ(w http.ResponseWriter, req *http.Request) {
+	mimeWriter := multipart.NewWriter(w)
+	w.Header().Set("Content-Type", fmt.Sprintf("multipart/x-mixed-replace; boundary=%s", mimeWriter.Boundary()))
+	partHeader := make(textproto.MIMEHeader)
+	partHeader.Add("Content-Type", "image/jpeg")
 
 
+	var frame []byte
+	for frame = range frames {
+		partWriter, err := mimeWriter.CreatePart(partHeader)
+		if err != nil {
+			log.Printf("failed to create multi-part writer: %s", err)
+			return
+		}
+
+		if _, err := partWriter.Write(frame); err != nil {
+			log.Printf("failed to write image: %s", err)
+		}
+	}
+}
 ```
 ```
-simple-cam: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), static-pie linked, Go BuildID=WYa4l3EGlIvd9EErrWkc/5Aa4CZdUXG8bERpToUcN/jjwKBQqSAfDbNfJGzSou/27sOKN7B1e0dtPc7PqmR, with debug_info, not stripped
-```
+
+> See complete source code [here](./simplecam.go).

+ 11 - 36
examples/webcam/README.md

@@ -1,47 +1,22 @@
 # Webcam example
 # Webcam example
 
 
-The webcam examples shows how the `go4vl` API can be used to create a webcam that streams incoming video frames from an attached camera to a web page. The code sets up a web server that returns a web page with an image element that continuously stream the captured video from the camera.
+The webcam examples shows how the `go4vl` API can be used to create a webcam that streams incoming video frames, from an attached camera, to a web page. This program showcases the followings:
 
 
-## Running the example
-Keep in mind that this code can only run on systems with the Linux operating system.
-Before you can build and run the code, you must satisfy the following prerequisites.
+* go4vl device control API
+* go4vl format description API
+* go4vl capture API
 
 
-### Pre-requisites
+The example also includes code that shows how to do face detection using the captured image.
 
 
-* Go compiler/tools
-* Linux OS (32- or 64-bit)
-* Kernel minimum v5.10.x or higher
-* A locally configured C compiler (or cross-compiler if building off-device)
-* A video camera (with support for Video for Linux API)
+The code sets up a web server that returns a web page with an image element that continuously stream the captured video from the camera.
 
 
+## Building the source code
 
 
-### On-device preparation
-If you are running a system that has not been upgraded in a while, ensure to issue the following commands:
+### Fix face detection modules 
+The project uses an external package for face detection. For it to build properly, some Go modules must be specically pulled. This is done by running shell script file [./fix-mods.sh](./fix-mods.sh).
 
 
-```
-sudo apt update
-sudo apt full-upgrade
-```
-
-This example has been tested using a Raspberry Pi 3 running 32-bit Linux, with kernel version 5.14, with an attached USB video camera.
-
-### On-device build 
-
-Copy (or use git) the code on the device. From within the webcam directory, run the helper script:
-
-```
-./build-on-device.sh
-```
-
-This will build the webcam binary.
-
-### Cross-compile build
-If you are building off-device, on a platform different then Linux/Arm/v7, use the cross-build helper script to compile the binary:
-
-```
-./cross-build.sh
-```
-This will create a binary for the Linux/Arm/v7 using the Zig compiler as a cross compiler (see examples/simplecam for detail about Zig).
+### Compile the code
+See instructions for on-device compilation or off-device cross-compilation [here](../README.md).
 
 
 ### Run
 ### Run
 
 

+ 1 - 3
examples/webcam/build-on-device.sh → examples/webcam/fix-mods.sh

@@ -4,6 +4,4 @@ go get github.com/vladimirvivien/go4vl@latest
 go get github.com/esimov/pigo/core@latest
 go get github.com/esimov/pigo/core@latest
 go get github.com/fogleman/gg@8febc0f526adecda6f8ae80f3869b7cd77e52984
 go get github.com/fogleman/gg@8febc0f526adecda6f8ae80f3869b7cd77e52984
 
 
-go mod tidy
-
-go build -o webcam .
+go mod tidy