71 lines
1.3 KiB
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
|
|
}
|