Skip to content

Commit

Permalink
Added capture example
Browse files Browse the repository at this point in the history
  • Loading branch information
djthorpe committed Jul 5, 2024
1 parent 29ac0bf commit 36dd616
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
33 changes: 33 additions & 0 deletions cmd/examples/capture/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"context"
"os"
"os/signal"
)

///////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

// ContextForSignal returns a context object which is cancelled when a signal
// is received. It returns nil if no signal parameter is provided
func ContextForSignal(signals ...os.Signal) context.Context {
if len(signals) == 0 {
return nil
}

ch := make(chan os.Signal, 1)
ctx, cancel := context.WithCancel(context.Background())

// Send message on channel when signal received
signal.Notify(ch, signals...)

// When any signal received, call cancel
go func() {
<-ch
cancel()
}()

// Return success
return ctx
}
95 changes: 95 additions & 0 deletions cmd/examples/capture/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
"fmt"
"image/jpeg"
"log"
"os"
"regexp"
"syscall"

// Packages
media "github.com/mutablelogic/go-media"
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
)

var (
reDeviceNamePath = regexp.MustCompile(`^([a-z][a-zA-Z0-9]+)\:(.*)$`)
)

func main() {
if len(os.Args) != 2 {
log.Fatal("Usage: capture device:path")
}

// Get the format associated with the input file
device := reDeviceNamePath.FindStringSubmatch(os.Args[1])
if device == nil {
log.Fatal("Invalid device name, use device:path")
}

// Create a media manager
manager, err := ffmpeg.NewManager(ffmpeg.OptLog(false, nil))
if err != nil {
log.Fatal(err)
}

// Find device
devices := manager.Formats(media.DEVICE, device[1])
if len(devices) == 0 {
log.Fatalf("No devices found for %v", device[1])
}
if len(devices) > 1 {
log.Fatalf("Multiple devices found: %q", devices)
}

// Open device
media, err := manager.Open(device[2], devices[0])
if err != nil {
log.Fatal(err)
}
defer media.Close()

// Tmpdir
tmpdir, err := os.MkdirTemp("", "capture")
if err != nil {
log.Fatal(err)
}

// Frame function
frameFunc := func(stream int, frame *ffmpeg.Frame) error {
w, err := os.Create(fmt.Sprintf("%v/frame-%v.jpg", tmpdir, frame.Ts()))
if err != nil {
return err
}
defer w.Close()

image, err := frame.Image()
if err != nil {
return err
}

if err := jpeg.Encode(w, image, nil); err != nil {
return err
}

fmt.Println("Written", w.Name())

return nil
}

// Map function
mapFunc := func(_ int, in *ffmpeg.Par) (*ffmpeg.Par, error) {
fmt.Println("Input", in)
return ffmpeg.VideoPar("yuv420p", in.WidthHeight(), in.FrameRate()), nil
}

// Receive frames
if err := media.(*ffmpeg.Reader).Decode(
ContextForSignal(os.Interrupt, syscall.SIGQUIT),
mapFunc,
frameFunc,
); err != nil {
log.Fatal(err)
}
}

0 comments on commit 36dd616

Please sign in to comment.