goffmpeg/pkg/ffmpeg/stream/pipe.go

71 lines
1.3 KiB
Go

package stream
import (
"io"
"os"
"sync"
)
// pipeReader bridges io.Reader to a file descriptor that can be used as FFmpeg input
type pipeReader struct {
r io.Reader
pr *io.PipeReader
pw *io.PipeWriter
f *os.File
err error
mu sync.Mutex
}
// newPipeReader creates a new pipe reader that bridges io.Reader to a pipe
func newPipeReader(r io.Reader) (*pipeReader, error) {
pr, pw := io.Pipe()
return &pipeReader{
r: r,
pr: pr,
pw: pw,
}, nil
}
// start begins copying data from the underlying reader to the pipe in background
func (p *pipeReader) start() {
go func() {
buf := make([]byte, 32768)
for {
n, err := p.r.Read(buf)
if n > 0 {
_, writeErr := p.pw.Write(buf[:n])
if writeErr != nil {
p.mu.Lock()
p.err = writeErr
p.mu.Unlock()
p.pw.CloseWithError(writeErr)
return
}
}
if err != nil {
p.pw.CloseWithError(err)
return
}
}
}()
}
// Read implements io.Reader
func (p *pipeReader) Read(data []byte) (n int, err error) {
return p.pr.Read(data)
}
// Close closes the pipe
func (p *pipeReader) Close() error {
err := p.pr.Close()
p.pw.Close()
return err
}
// Error returns any error that occurred during reading
func (p *pipeReader) Error() error {
p.mu.Lock()
defer p.mu.Unlock()
return p.err
}