Parcourir la source

Update to documentation

Vladimir Vivien il y a 2 ans
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
 * 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.
 The package should work with no problem on your 64-bit Linux OS.
 
 ## 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
 
 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
 
-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.
 
 ```go
 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 {
-		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
 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] List/query device available
 * [x] Add repo documentation
-* [ ] Document examples 
+* [x] Document examples 
 * [ ] Support for YUYV conversion
-* [ ] Set and query device controls
+* [x] Set and query device controls
 * [ ] 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
 
-* [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
 
-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 
 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
 func main() {

+ 1 - 1
examples/ccapture/README.md

@@ -1,6 +1,6 @@
 # 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
 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 
 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
 
-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
 

+ 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/fogleman/gg@8febc0f526adecda6f8ae80f3869b7cd77e52984
 
-go mod tidy
-
-go build -o webcam .
+go mod tidy