Skip to content

Commit 36dd616

Browse files
committed
Added capture example
1 parent 29ac0bf commit 36dd616

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

cmd/examples/capture/context.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"os"
6+
"os/signal"
7+
)
8+
9+
///////////////////////////////////////////////////////////////////////////////
10+
// PUBLIC METHODS
11+
12+
// ContextForSignal returns a context object which is cancelled when a signal
13+
// is received. It returns nil if no signal parameter is provided
14+
func ContextForSignal(signals ...os.Signal) context.Context {
15+
if len(signals) == 0 {
16+
return nil
17+
}
18+
19+
ch := make(chan os.Signal, 1)
20+
ctx, cancel := context.WithCancel(context.Background())
21+
22+
// Send message on channel when signal received
23+
signal.Notify(ch, signals...)
24+
25+
// When any signal received, call cancel
26+
go func() {
27+
<-ch
28+
cancel()
29+
}()
30+
31+
// Return success
32+
return ctx
33+
}

cmd/examples/capture/main.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"image/jpeg"
6+
"log"
7+
"os"
8+
"regexp"
9+
"syscall"
10+
11+
// Packages
12+
media "github.com/mutablelogic/go-media"
13+
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
14+
)
15+
16+
var (
17+
reDeviceNamePath = regexp.MustCompile(`^([a-z][a-zA-Z0-9]+)\:(.*)$`)
18+
)
19+
20+
func main() {
21+
if len(os.Args) != 2 {
22+
log.Fatal("Usage: capture device:path")
23+
}
24+
25+
// Get the format associated with the input file
26+
device := reDeviceNamePath.FindStringSubmatch(os.Args[1])
27+
if device == nil {
28+
log.Fatal("Invalid device name, use device:path")
29+
}
30+
31+
// Create a media manager
32+
manager, err := ffmpeg.NewManager(ffmpeg.OptLog(false, nil))
33+
if err != nil {
34+
log.Fatal(err)
35+
}
36+
37+
// Find device
38+
devices := manager.Formats(media.DEVICE, device[1])
39+
if len(devices) == 0 {
40+
log.Fatalf("No devices found for %v", device[1])
41+
}
42+
if len(devices) > 1 {
43+
log.Fatalf("Multiple devices found: %q", devices)
44+
}
45+
46+
// Open device
47+
media, err := manager.Open(device[2], devices[0])
48+
if err != nil {
49+
log.Fatal(err)
50+
}
51+
defer media.Close()
52+
53+
// Tmpdir
54+
tmpdir, err := os.MkdirTemp("", "capture")
55+
if err != nil {
56+
log.Fatal(err)
57+
}
58+
59+
// Frame function
60+
frameFunc := func(stream int, frame *ffmpeg.Frame) error {
61+
w, err := os.Create(fmt.Sprintf("%v/frame-%v.jpg", tmpdir, frame.Ts()))
62+
if err != nil {
63+
return err
64+
}
65+
defer w.Close()
66+
67+
image, err := frame.Image()
68+
if err != nil {
69+
return err
70+
}
71+
72+
if err := jpeg.Encode(w, image, nil); err != nil {
73+
return err
74+
}
75+
76+
fmt.Println("Written", w.Name())
77+
78+
return nil
79+
}
80+
81+
// Map function
82+
mapFunc := func(_ int, in *ffmpeg.Par) (*ffmpeg.Par, error) {
83+
fmt.Println("Input", in)
84+
return ffmpeg.VideoPar("yuv420p", in.WidthHeight(), in.FrameRate()), nil
85+
}
86+
87+
// Receive frames
88+
if err := media.(*ffmpeg.Reader).Decode(
89+
ContextForSignal(os.Interrupt, syscall.SIGQUIT),
90+
mapFunc,
91+
frameFunc,
92+
); err != nil {
93+
log.Fatal(err)
94+
}
95+
}

0 commit comments

Comments
 (0)