Fixed ffmpeg stdin not closing, io.Seeker and io.EOF errors
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2023-11-07 09:24:01 +01:00
parent 230d505377
commit 8c6e604f26
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
5 changed files with 40 additions and 17 deletions

View file

@ -4,6 +4,7 @@ package main
import ( import (
"encoding/csv" "encoding/csv"
"errors"
"flag" "flag"
"fmt" "fmt"
"git.gammaspectra.live/S.O.N.G/Ignite/encoder/libaom" "git.gammaspectra.live/S.O.N.G/Ignite/encoder/libaom"
@ -91,7 +92,7 @@ func main() {
for { for {
record, err := c.Read() record, err := c.Read()
if err != nil { if err != nil {
if err == io.EOF { if errors.Is(err, io.EOF) {
break break
} }
panic(err) panic(err)

View file

@ -29,23 +29,31 @@ func NewDecoder(r io.Reader, settings map[string]any) (d *Decoder, err error) {
cmd := exec.Command(ffmpegBinary, cmd := exec.Command(ffmpegBinary,
//"-v", "quiet", //"-v", "quiet",
"-probesize", "8192",
"-strict", "experimental", "-strict", "experimental",
"-i", "-", "-i", "pipe:",
"-map_metadata", "-1", "-map_metadata", "-1",
"-map", fmt.Sprintf("0:v:%d", videoIndex), "-map", fmt.Sprintf("0:v:%d", videoIndex),
"-f", "yuv4mpegpipe", "-f", "yuv4mpegpipe",
"-strict", "experimental", "-strict", "experimental",
"-", "pipe:",
) )
cmd.Stdin = r
pipeR, pipeW := io.Pipe() cmdIn, err := cmd.StdinPipe()
cmd.Stdout = pipeW if err != nil {
return nil, err
}
cmdOut, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
err = cmd.Start() err = cmd.Start()
if err != nil { if err != nil {
defer cmd.Process.Release()
return nil, err return nil, err
} }
@ -53,9 +61,14 @@ func NewDecoder(r io.Reader, settings map[string]any) (d *Decoder, err error) {
cmd: cmd, cmd: cmd,
} }
d.y4m, err = y4m.NewDecoder(pipeR, settings) go func() {
defer cmdIn.Close()
_, _ = io.Copy(cmdIn, r)
}()
d.y4m, err = y4m.NewDecoder(cmdOut, settings)
if err != nil { if err != nil {
d.Close() defer d.Close()
return nil, err return nil, err
} }

View file

@ -125,7 +125,7 @@ func (d *Decoder) decodeFrame() C.int {
if d.data.sz == 0 { if d.data.sz == 0 {
if err := d.readIvf(); err != nil { if err := d.readIvf(); err != nil {
if err == io.EOF { if errors.Is(err, io.EOF) {
//try flush? //try flush?
if res = d.flushPicture(); res != -ErrEAGAIN { if res = d.flushPicture(); res != -ErrEAGAIN {
return res return res

View file

@ -15,6 +15,7 @@ import (
type Decoder struct { type Decoder struct {
r io.Reader r io.Reader
seeker io.ReadSeeker
frameSeekTable []int64 frameSeekTable []int64
parameters map[Parameter][]string parameters map[Parameter][]string
@ -60,6 +61,13 @@ func NewDecoder(reader io.Reader, settings map[string]any) (*Decoder, error) {
} }
var err error var err error
if seeker, ok := s.r.(io.ReadSeeker); ok {
//test seeker
if _, err = seeker.Seek(0, io.SeekCurrent); err == nil {
s.seeker = seeker
}
}
if err = s.readHeader(); err != nil { if err = s.readHeader(); err != nil {
return nil, err return nil, err
} }
@ -130,9 +138,9 @@ func (s *Decoder) SeekToFrame(frameNumber int) (err error) {
return nil return nil
} }
if seeker, ok := s.r.(io.Seeker); ok { if s.seeker != nil {
if frameNumber >= 0 && len(s.frameSeekTable) > frameNumber && s.frameSeekTable[frameNumber] != 0 { if frameNumber >= 0 && len(s.frameSeekTable) > frameNumber && s.frameSeekTable[frameNumber] != 0 {
if _, err = seeker.Seek(s.frameSeekTable[frameNumber], io.SeekStart); err != nil { if _, err = s.seeker.Seek(s.frameSeekTable[frameNumber], io.SeekStart); err != nil {
return err return err
} }
@ -143,7 +151,7 @@ func (s *Decoder) SeekToFrame(frameNumber int) (err error) {
//attempt blind seek from last decoded frame //attempt blind seek from last decoded frame
framesToSeekFromLast := frameNumber + 1 - len(s.frameSeekTable) framesToSeekFromLast := frameNumber + 1 - len(s.frameSeekTable)
if _, err = seeker.Seek(s.frameSeekTable[len(s.frameSeekTable)-1]+int64(5+1+s.frameSize)*int64(framesToSeekFromLast), io.SeekStart); err != nil { if _, err = s.seeker.Seek(s.frameSeekTable[len(s.frameSeekTable)-1]+int64(5+1+s.frameSize)*int64(framesToSeekFromLast), io.SeekStart); err != nil {
return err return err
} }
@ -152,7 +160,7 @@ func (s *Decoder) SeekToFrame(frameNumber int) (err error) {
return nil return nil
} else if frameNumber >= 0 && s.frameStartOffset != 0 { } else if frameNumber >= 0 && s.frameStartOffset != 0 {
//attempt full blind seek from start //attempt full blind seek from start
if _, err = seeker.Seek(s.frameStartOffset+int64(5+1+s.frameSize)*int64(frameNumber), io.SeekStart); err != nil { if _, err = s.seeker.Seek(s.frameStartOffset+int64(5+1+s.frameSize)*int64(frameNumber), io.SeekStart); err != nil {
return err return err
} }
@ -194,8 +202,8 @@ func (s *Decoder) GetFrameSeekTable() []int64 {
func (s *Decoder) GetFrame() (parameters map[Parameter][]string, frameObject frame.Frame, err error) { func (s *Decoder) GetFrame() (parameters map[Parameter][]string, frameObject frame.Frame, err error) {
var index int64 var index int64
if seeker, ok := s.r.(io.Seeker); ok { if s.seeker != nil {
if index, err = seeker.Seek(0, io.SeekCurrent); err != nil { if index, err = s.seeker.Seek(0, io.SeekCurrent); err != nil {
return nil, nil, err return nil, nil, err
} }
} }
@ -377,8 +385,8 @@ func (s *Decoder) parseParameters() (err error) {
s.frameSize, err = s.properties.ColorSpace.FrameSize(s.properties.Width, s.properties.Height) s.frameSize, err = s.properties.ColorSpace.FrameSize(s.properties.Width, s.properties.Height)
if seeker, ok := s.r.(io.Seeker); ok { if s.seeker != nil {
if index, err := seeker.Seek(0, io.SeekCurrent); err == nil { if index, err := s.seeker.Seek(0, io.SeekCurrent); err == nil {
s.frameStartOffset = index s.frameStartOffset = index
} }
} }

View file

@ -231,6 +231,7 @@ func (e *Encoder) Encode(f frame.Frame) error {
copy(unsafe.Slice((*byte)(e.pictureIn.img.plane[2]), len(cr)), cr) copy(unsafe.Slice((*byte)(e.pictureIn.img.plane[2]), len(cr)), cr)
e.pictureIn.i_pts = C.int64_t(f.PTS()) e.pictureIn.i_pts = C.int64_t(f.PTS())
//TODO: read flags for statistic tracking
return e.encoderEncode(e.pictureIn) return e.encoderEncode(e.pictureIn)
} }