Fixed ffmpeg stdin not closing, io.Seeker and io.EOF errors
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
230d505377
commit
8c6e604f26
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue