Moved all to videoio.go for portability
This commit is contained in:
parent
ff24be3154
commit
3faf4aa9c8
7 changed files with 316 additions and 340 deletions
114
video.go
114
video.go
|
@ -1,114 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Video struct {
|
||||
filename string
|
||||
width int
|
||||
height int
|
||||
channels int
|
||||
bitrate int
|
||||
duration float64
|
||||
fps float64
|
||||
codec string
|
||||
pix_fmt string
|
||||
framebuffer []byte
|
||||
pipe *io.ReadCloser
|
||||
cmd *exec.Cmd
|
||||
}
|
||||
|
||||
func NewVideo(filename string) *Video {
|
||||
if !Exists(filename) {
|
||||
panic("File: " + filename + " does not exist")
|
||||
}
|
||||
// Execute ffmpeg -i command to get video information.
|
||||
cmd := exec.Command("ffmpeg", "-i", filename, "-")
|
||||
// ffmpeg output piped to Stderr.
|
||||
pipe, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buffer := make([]byte, 2<<12)
|
||||
total := 0
|
||||
for {
|
||||
n, err := pipe.Read(buffer[total:])
|
||||
total += n
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
cmd.Wait()
|
||||
video := &Video{filename: filename, channels: 3}
|
||||
parseFFMPEGHeader(video, string(buffer))
|
||||
return video
|
||||
}
|
||||
|
||||
func (video *Video) initVideoStream() {
|
||||
// If user exits with Ctrl+C, stop ffmpeg process.
|
||||
video.cleanup()
|
||||
|
||||
cmd := exec.Command(
|
||||
"ffmpeg",
|
||||
"-loglevel", "quiet",
|
||||
"-i", video.filename,
|
||||
"-f", "image2pipe",
|
||||
"-pix_fmt", "rgb24",
|
||||
"-vcodec", "rawvideo", "-",
|
||||
)
|
||||
video.cmd = cmd
|
||||
pipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
video.pipe = &pipe
|
||||
if err := cmd.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
video.framebuffer = make([]byte, video.width*video.height*video.channels)
|
||||
}
|
||||
|
||||
func (video *Video) NextFrame() bool {
|
||||
// If cmd is nil, video reading has not been initialized.
|
||||
if video.cmd == nil {
|
||||
video.initVideoStream()
|
||||
}
|
||||
total := 0
|
||||
for total < video.width*video.height*video.channels {
|
||||
n, err := (*video.pipe).Read(video.framebuffer[total:])
|
||||
if err == io.EOF {
|
||||
(*video.pipe).Close()
|
||||
if err := video.cmd.Wait(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
total += n
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Stops the "cmd" process running when the user presses Ctrl+C.
|
||||
// https://stackoverflow.com/questions/11268943/is-it-possible-to-capture-a-ctrlc-signal-and-run-a-cleanup-function-in-a-defe
|
||||
func (video *Video) cleanup() {
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
if video.pipe != nil {
|
||||
(*video.pipe).Close()
|
||||
}
|
||||
if video.cmd != nil {
|
||||
video.cmd.Process.Kill()
|
||||
}
|
||||
os.Exit(1)
|
||||
}()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue