mirror of
https://github.com/asticode/go-astiav.git
synced 2025-10-04 15:52:52 +08:00
Added software resample context
This commit is contained in:
129
astiav_test.go
129
astiav_test.go
@@ -47,7 +47,11 @@ func (h *helper) close() {
|
||||
type helperInput struct {
|
||||
firstPkt *Packet
|
||||
formatContext *FormatContext
|
||||
lastFrame *Frame
|
||||
lastFrames map[MediaType]*Frame
|
||||
}
|
||||
|
||||
func newHelperInput() *helperInput {
|
||||
return &helperInput{lastFrames: make(map[MediaType]*Frame)}
|
||||
}
|
||||
|
||||
func (h *helper) inputFormatContext(name string, ifmt *InputFormat) (fc *FormatContext, err error) {
|
||||
@@ -78,7 +82,7 @@ func (h *helper) inputFormatContext(name string, ifmt *InputFormat) (fc *FormatC
|
||||
|
||||
h.m.Lock()
|
||||
if _, ok := h.inputs[name]; !ok {
|
||||
h.inputs[name] = &helperInput{}
|
||||
h.inputs[name] = newHelperInput()
|
||||
}
|
||||
h.inputs[name].formatContext = fc
|
||||
h.m.Unlock()
|
||||
@@ -118,127 +122,124 @@ func (h *helper) inputFirstPacket(name string) (pkt *Packet, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (h *helper) inputLastFrame(name string, mediaType MediaType, ifmt *InputFormat) (f *Frame, err error) {
|
||||
func (h *helper) inputLastFrame(name string, mediaType MediaType, ifmt *InputFormat) (*Frame, error) {
|
||||
h.m.Lock()
|
||||
i, ok := h.inputs[name]
|
||||
if ok && i.lastFrame != nil {
|
||||
h.m.Unlock()
|
||||
return i.lastFrame, nil
|
||||
if i, ok := h.inputs[name]; ok {
|
||||
if len(i.lastFrames) > 0 {
|
||||
f, ok := i.lastFrames[mediaType]
|
||||
h.m.Unlock()
|
||||
if ok {
|
||||
return f, nil
|
||||
}
|
||||
return nil, fmt.Errorf("astiav_test: no last frame for media type %s", mediaType)
|
||||
}
|
||||
}
|
||||
h.m.Unlock()
|
||||
|
||||
var fc *FormatContext
|
||||
if fc, err = h.inputFormatContext(name, ifmt); err != nil {
|
||||
err = fmt.Errorf("astiav_test: getting input format context failed: %w", err)
|
||||
return
|
||||
fc, err := h.inputFormatContext(name, ifmt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("astiav_test: getting input format context failed: %w", err)
|
||||
}
|
||||
|
||||
var cc *CodecContext
|
||||
var cs *Stream
|
||||
for _, s := range fc.Streams() {
|
||||
if s.CodecParameters().MediaType() != mediaType {
|
||||
continue
|
||||
}
|
||||
type stream struct {
|
||||
cc *CodecContext
|
||||
s *Stream
|
||||
}
|
||||
streams := make(map[int]*stream)
|
||||
mediaTypeFound := false
|
||||
for _, v := range fc.Streams() {
|
||||
s := &stream{s: v}
|
||||
streams[v.Index()] = s
|
||||
|
||||
cs = s
|
||||
|
||||
c := FindDecoder(s.CodecParameters().CodecID())
|
||||
c := FindDecoder(v.CodecParameters().CodecID())
|
||||
if c == nil {
|
||||
err = errors.New("astiav_test: no codec")
|
||||
return
|
||||
return nil, errors.New("astiav_test: no codec")
|
||||
}
|
||||
|
||||
cc = AllocCodecContext(c)
|
||||
if cc == nil {
|
||||
err = errors.New("astiav_test: no codec context")
|
||||
return
|
||||
s.cc = AllocCodecContext(c)
|
||||
if s.cc == nil {
|
||||
return nil, errors.New("astiav_test: no codec context")
|
||||
}
|
||||
h.closer.Add(cc.Free)
|
||||
h.closer.Add(s.cc.Free)
|
||||
|
||||
if err = cs.CodecParameters().ToCodecContext(cc); err != nil {
|
||||
err = fmt.Errorf("astiav_test: updating codec context failed: %w", err)
|
||||
return
|
||||
if err = s.s.CodecParameters().ToCodecContext(s.cc); err != nil {
|
||||
return nil, fmt.Errorf("astiav_test: updating codec context failed: %w", err)
|
||||
}
|
||||
|
||||
if err = cc.Open(c, nil); err != nil {
|
||||
err = fmt.Errorf("astiav_test: opening codec context failed: %w", err)
|
||||
return
|
||||
if err = s.cc.Open(c, nil); err != nil {
|
||||
return nil, fmt.Errorf("astiav_test: opening codec context failed: %w", err)
|
||||
}
|
||||
|
||||
if _, ok := h.inputs[name].lastFrames[s.cc.MediaType()]; !ok {
|
||||
h.inputs[name].lastFrames[s.cc.MediaType()] = AllocFrame()
|
||||
h.closer.Add(h.inputs[name].lastFrames[s.cc.MediaType()].Free)
|
||||
}
|
||||
|
||||
if s.cc.MediaType() == mediaType {
|
||||
mediaTypeFound = true
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if cs == nil {
|
||||
err = errors.New("astiav_test: no valid video stream")
|
||||
return
|
||||
if !mediaTypeFound {
|
||||
return nil, fmt.Errorf("astiav_test: no stream for media type %s", mediaType)
|
||||
}
|
||||
|
||||
var pkt1 *Packet
|
||||
if pkt1, err = h.inputFirstPacket(name); err != nil {
|
||||
err = fmt.Errorf("astiav_test: getting input first packet failed: %w", err)
|
||||
return
|
||||
return nil, fmt.Errorf("astiav_test: getting input first packet failed: %w", err)
|
||||
}
|
||||
|
||||
pkt2 := AllocPacket()
|
||||
h.closer.Add(pkt2.Free)
|
||||
|
||||
f = AllocFrame()
|
||||
f := AllocFrame()
|
||||
h.closer.Add(f.Free)
|
||||
|
||||
lastFrame := AllocFrame()
|
||||
h.closer.Add(lastFrame.Free)
|
||||
|
||||
pkts := []*Packet{pkt1}
|
||||
for {
|
||||
if err = fc.ReadFrame(pkt2); err != nil {
|
||||
if errors.Is(err, ErrEof) || errors.Is(err, ErrEagain) {
|
||||
if len(pkts) == 0 {
|
||||
if err = f.Ref(lastFrame); err != nil {
|
||||
err = fmt.Errorf("astiav_test: last refing frame failed: %w", err)
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("astiav_test: reading frame failed: %w", err)
|
||||
return
|
||||
return nil, fmt.Errorf("astiav_test: reading frame failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
pkts = append(pkts, pkt2)
|
||||
}
|
||||
|
||||
for _, pkt := range pkts {
|
||||
if pkt.StreamIndex() != cs.Index() {
|
||||
s, ok := streams[pkt.StreamIndex()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = cc.SendPacket(pkt); err != nil {
|
||||
err = fmt.Errorf("astiav_test: sending packet failed: %w", err)
|
||||
return
|
||||
if err = s.cc.SendPacket(pkt); err != nil {
|
||||
return nil, fmt.Errorf("astiav_test: sending packet failed: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
if err = cc.ReceiveFrame(f); err != nil {
|
||||
if err = s.cc.ReceiveFrame(f); err != nil {
|
||||
if errors.Is(err, ErrEof) || errors.Is(err, ErrEagain) {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
err = fmt.Errorf("astiav_test: receiving frame failed: %w", err)
|
||||
return
|
||||
return nil, fmt.Errorf("astiav_test: receiving frame failed: %w", err)
|
||||
}
|
||||
|
||||
if err = lastFrame.Ref(f); err != nil {
|
||||
err = fmt.Errorf("astiav_test: refing frame failed: %w", err)
|
||||
return
|
||||
h.m.Lock()
|
||||
h.inputs[name].lastFrames[s.cc.MediaType()].Unref()
|
||||
err = h.inputs[name].lastFrames[s.cc.MediaType()].Ref(f)
|
||||
h.m.Unlock()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("astiav_test: refing frame failed: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pkts = []*Packet{}
|
||||
}
|
||||
|
||||
h.m.Lock()
|
||||
h.inputs[name].lastFrame = f
|
||||
h.m.Unlock()
|
||||
return
|
||||
return h.inputs[name].lastFrames[mediaType], nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user