优化amf读取

This commit is contained in:
dexter
2023-01-30 10:35:43 +08:00
parent 092719a61d
commit db6f8de3a7
10 changed files with 118 additions and 52 deletions

View File

@@ -76,7 +76,7 @@ type AVTrack interface {
CurrentFrame() *AVFrame CurrentFrame() *AVFrame
Attach() Attach()
Detach() Detach()
WriteAVCC(ts uint32, frame util.BLL) //写入AVCC格式的数据 WriteAVCC(ts uint32, frame util.BLL) error //写入AVCC格式的数据
WriteRTP([]byte) WriteRTP([]byte)
WriteRTPPack(*rtp.Packet) WriteRTPPack(*rtp.Packet)
Flush() Flush()

View File

@@ -27,12 +27,16 @@ const (
SUBSTATE_NORMAL SUBSTATE_NORMAL
) )
// AVCC 格式的序列帧
type VideoDeConf []byte type VideoDeConf []byte
// AVCC 格式的序列帧
type AudioDeConf []byte type AudioDeConf []byte
type AudioFrame struct { type AudioFrame struct {
*AVFrame *AVFrame
AbsTime uint32 AbsTime uint32
PTS uint32 PTS uint32
DTS uint32
} }
type VideoFrame struct { type VideoFrame struct {
*AVFrame *AVFrame
@@ -168,13 +172,13 @@ func (s *Subscriber) PlayBlock(subType byte) {
s.TrackPlayer.Context, s.TrackPlayer.CancelFunc = context.WithCancel(s.IO) s.TrackPlayer.Context, s.TrackPlayer.CancelFunc = context.WithCancel(s.IO)
ctx := s.TrackPlayer.Context ctx := s.TrackPlayer.Context
sendVideoDecConf := func() { sendVideoDecConf := func() {
spesic.OnEvent(s.Video.ParamaterSets)
spesic.OnEvent(VideoDeConf(s.VideoReader.Track.SequenceHead)) spesic.OnEvent(VideoDeConf(s.VideoReader.Track.SequenceHead))
} }
sendAudioDecConf := func() { sendAudioDecConf := func() {
spesic.OnEvent(AudioDeConf(s.AudioReader.Track.SequenceHead)) spesic.OnEvent(AudioDeConf(s.AudioReader.Track.SequenceHead))
} }
var sendVideoFrame func(*AVFrame) var sendAudioFrame, sendVideoFrame func(*AVFrame)
var sendAudioFrame func(*AVFrame)
switch subType { switch subType {
case SUBTYPE_RAW: case SUBTYPE_RAW:
sendVideoFrame = func(frame *AVFrame) { sendVideoFrame = func(frame *AVFrame) {
@@ -183,7 +187,7 @@ func (s *Subscriber) PlayBlock(subType byte) {
} }
sendAudioFrame = func(frame *AVFrame) { sendAudioFrame = func(frame *AVFrame) {
// println("a", frame.Sequence, s.AudioReader.AbsTime) // println("a", frame.Sequence, s.AudioReader.AbsTime)
spesic.OnEvent(AudioFrame{frame, s.AudioReader.AbsTime, frame.DTS - s.VideoReader.SkipTs*90}) spesic.OnEvent(AudioFrame{frame, s.AudioReader.AbsTime, s.AudioReader.AbsTime * 90, s.AudioReader.AbsTime * 90})
} }
case SUBTYPE_RTP: case SUBTYPE_RTP:
var videoSeq, audioSeq uint16 var videoSeq, audioSeq uint16
@@ -201,7 +205,7 @@ func (s *Subscriber) PlayBlock(subType byte) {
audioSeq++ audioSeq++
vp := *p vp := *p
vp.Header.SequenceNumber = audioSeq vp.Header.SequenceNumber = audioSeq
vp.Header.Timestamp = vp.Header.Timestamp - s.VideoReader.SkipTs*90 vp.Header.Timestamp = vp.Header.Timestamp - s.AudioReader.SkipTs*90
spesic.OnEvent((AudioRTP)(vp)) spesic.OnEvent((AudioRTP)(vp))
} }
} }
@@ -225,10 +229,11 @@ func (s *Subscriber) PlayBlock(subType byte) {
// spesic.OnEvent(FLVFrame(copyBuffers(s.Audio.Track.DecoderConfiguration.FLV))) // spesic.OnEvent(FLVFrame(copyBuffers(s.Audio.Track.DecoderConfiguration.FLV)))
} }
sendVideoFrame = func(frame *AVFrame) { sendVideoFrame = func(frame *AVFrame) {
// println(frame.Sequence, frame.AbsTime, frame.DeltaTime, frame.IFrame) // println(frame.Sequence, s.VideoReader.AbsTime, frame.DeltaTime, frame.IFrame)
sendFlvFrame(codec.FLV_TAG_TYPE_VIDEO, s.VideoReader.AbsTime, frame.AVCC.ToBuffers()...) sendFlvFrame(codec.FLV_TAG_TYPE_VIDEO, s.VideoReader.AbsTime, frame.AVCC.ToBuffers()...)
} }
sendAudioFrame = func(frame *AVFrame) { sendAudioFrame = func(frame *AVFrame) {
// println(frame.Sequence, s.AudioReader.AbsTime, frame.DeltaTime)
sendFlvFrame(codec.FLV_TAG_TYPE_AUDIO, s.AudioReader.AbsTime, frame.AVCC.ToBuffers()...) sendFlvFrame(codec.FLV_TAG_TYPE_AUDIO, s.AudioReader.AbsTime, frame.AVCC.ToBuffers()...)
} }
} }
@@ -237,32 +242,49 @@ func (s *Subscriber) PlayBlock(subType byte) {
if s.Args.Has(s.Config.SubModeArgName) { if s.Args.Has(s.Config.SubModeArgName) {
subMode, _ = strconv.Atoi(s.Args.Get(s.Config.SubModeArgName)) subMode, _ = strconv.Atoi(s.Args.Get(s.Config.SubModeArgName))
} }
var videoFrame, audioFrame *AVFrame
for ctx.Err() == nil { for ctx.Err() == nil {
hasVideo, hasAudio := s.VideoReader.Track != nil && s.Config.SubVideo, s.AudioReader.Track != nil && s.Config.SubAudio hasVideo, hasAudio := s.VideoReader.Track != nil && s.Config.SubVideo, s.AudioReader.Track != nil && s.Config.SubAudio
if hasVideo { if hasVideo {
if videoFrame != nil {
sendVideoFrame(videoFrame)
videoFrame = nil
}
for ctx.Err() == nil { for ctx.Err() == nil {
s.VideoReader.Read(ctx, subMode) s.VideoReader.Read(ctx, subMode)
frame := s.VideoReader.Frame frame := s.VideoReader.Frame
// println("video", frame.Sequence, frame.AbsTime) // println("video", frame.Sequence, frame.AbsTime)
if frame == nil { if frame == nil || ctx.Err() != nil {
return return
} }
if audioFrame != nil {
if frame.AbsTime > audioFrame.AbsTime {
sendAudioFrame(audioFrame)
audioFrame = nil
}
}
if frame.IFrame && s.VideoReader.DecConfChanged() { if frame.IFrame && s.VideoReader.DecConfChanged() {
s.VideoReader.ConfSeq = s.VideoReader.Track.SequenceHeadSeq s.VideoReader.ConfSeq = s.VideoReader.Track.SequenceHeadSeq
// println(s.Video.confSeq, s.Video.Track.SPSInfo.Width, s.Video.Track.SPSInfo.Height) // println(s.Video.confSeq, s.Video.Track.SPSInfo.Width, s.Video.Track.SPSInfo.Height)
sendVideoDecConf() sendVideoDecConf()
} }
if !s.Config.IFrameOnly || frame.IFrame { if !s.Config.IFrameOnly || frame.IFrame {
sendVideoFrame(frame)
}
if frame.AbsTime > lastPlayAbsTime { if frame.AbsTime > lastPlayAbsTime {
lastPlayAbsTime = frame.AbsTime lastPlayAbsTime = frame.AbsTime
videoFrame = frame
break break
} else {
sendVideoFrame(frame)
}
} }
} }
} }
// 正常模式下或者纯音频模式下,音频开始播放 // 正常模式下或者纯音频模式下,音频开始播放
if hasAudio { if hasAudio {
if audioFrame != nil {
sendAudioFrame(audioFrame)
audioFrame = nil
}
for ctx.Err() == nil { for ctx.Err() == nil {
switch s.AudioReader.State { switch s.AudioReader.State {
case track.READSTATE_INIT: case track.READSTATE_INIT:
@@ -277,17 +299,25 @@ func (s *Subscriber) PlayBlock(subType byte) {
s.AudioReader.Read(ctx, subMode) s.AudioReader.Read(ctx, subMode)
frame := s.AudioReader.Frame frame := s.AudioReader.Frame
// println("audio", frame.Sequence, frame.AbsTime) // println("audio", frame.Sequence, frame.AbsTime)
if frame == nil { if frame == nil || ctx.Err() != nil {
return return
} }
if videoFrame != nil {
if frame.AbsTime > videoFrame.AbsTime {
sendVideoFrame(videoFrame)
videoFrame = nil
}
}
if s.AudioReader.DecConfChanged() { if s.AudioReader.DecConfChanged() {
s.AudioReader.ConfSeq = s.AudioReader.Track.SequenceHeadSeq s.AudioReader.ConfSeq = s.AudioReader.Track.SequenceHeadSeq
sendAudioDecConf() sendAudioDecConf()
} }
sendAudioFrame(frame)
if frame.AbsTime > lastPlayAbsTime { if frame.AbsTime > lastPlayAbsTime {
lastPlayAbsTime = frame.AbsTime lastPlayAbsTime = frame.AbsTime
audioFrame = frame
break break
} else {
sendAudioFrame(frame)
} }
} }
} }

View File

@@ -1,6 +1,7 @@
package track package track
import ( import (
"io"
"net" "net"
"time" "time"
@@ -100,10 +101,10 @@ func (aac *AAC) WriteAVCCSequenceHead(sh []byte) {
aac.WriteSequenceHead(append([]byte{0xAF, 0x00}, sh...)) aac.WriteSequenceHead(append([]byte{0xAF, 0x00}, sh...))
} }
func (aac *AAC) WriteAVCC(ts uint32, frame util.BLL) { func (aac *AAC) WriteAVCC(ts uint32, frame util.BLL) error {
if l := frame.ByteLength; l < 4 { if l := frame.ByteLength; l < 4 {
aac.Stream.Error("AVCC data too short", zap.Int("len", l)) aac.Stream.Error("AVCC data too short", zap.Int("len", l))
return return io.ErrShortWrite
} }
if frame.GetByte(1) == 0 { if frame.GetByte(1) == 0 {
aac.WriteSequenceHead(frame.ToBytes()) aac.WriteSequenceHead(frame.ToBytes())
@@ -114,6 +115,7 @@ func (aac *AAC) WriteAVCC(ts uint32, frame util.BLL) {
aac.AppendAuBytes(au...) aac.AppendAuBytes(au...)
aac.Audio.WriteAVCC(ts, frame) aac.Audio.WriteAVCC(ts, frame)
} }
return nil
} }
func (aac *AAC) CompleteRTP(value *AVFrame) { func (aac *AAC) CompleteRTP(value *AVFrame) {

View File

@@ -93,7 +93,7 @@ func (av *Media) SnapForJson() {
av.RawPart = av.RawPart[:0] av.RawPart = av.RawPart[:0]
} }
av.RawSize = v.AUList.ByteLength av.RawSize = v.AUList.ByteLength
r := v.AUList.Next.Value.NewReader() r := v.AUList.NewReader()
for b, err := r.ReadByte(); err == nil && len(av.RawPart) < 10; b, err = r.ReadByte() { for b, err := r.ReadByte(); err == nil && len(av.RawPart) < 10; b, err = r.ReadByte() {
av.RawPart = append(av.RawPart, int(b)) av.RawPart = append(av.RawPart, int(b))
} }

View File

@@ -1,6 +1,7 @@
package track package track
import ( import (
"io"
"time" "time"
"go.uber.org/zap" "go.uber.org/zap"
@@ -36,17 +37,18 @@ type G711 struct {
Audio Audio
} }
func (g711 *G711) WriteAVCC(ts uint32, frame util.BLL) { func (g711 *G711) WriteAVCC(ts uint32, frame util.BLL) error {
if l := frame.ByteLength; l < 2 { if l := frame.ByteLength; l < 2 {
g711.Stream.Error("AVCC data too short", zap.Int("len", l)) g711.Stream.Error("AVCC data too short", zap.Int("len", l))
return return io.ErrShortWrite
} }
g711.Value.AUList.Push(g711.BytesPool.GetShell(frame.Next.Value[1:])) g711.Value.AUList.Push(g711.BytesPool.GetShell(frame.Next.Value[1:]))
frame.Next.Range(func(v util.BLI) bool { frame.Range(func(v util.BLI) bool {
g711.Value.AUList.Push(g711.BytesPool.GetShell(v)) g711.Value.AUList.Push(g711.BytesPool.GetShell(v))
return true return true
}) })
g711.Audio.WriteAVCC(ts, frame) g711.Audio.WriteAVCC(ts, frame)
return nil
} }
func (g711 *G711) WriteRTPFrame(frame *RTPFrame) { func (g711 *G711) WriteRTPFrame(frame *RTPFrame) {

View File

@@ -1,6 +1,7 @@
package track package track
import ( import (
"io"
"time" "time"
"go.uber.org/zap" "go.uber.org/zap"
@@ -65,22 +66,23 @@ func (vt *H264) WriteSliceBytes(slice []byte) {
case codec.NALU_SEI: case codec.NALU_SEI:
vt.AppendAuBytes(slice) vt.AppendAuBytes(slice)
case codec.NALU_Access_Unit_Delimiter: case codec.NALU_Access_Unit_Delimiter:
case codec.NALU_Filler_Data:
default: default:
vt.Stream.Error("H264 WriteSliceBytes naluType not support", zap.Int("naluType", int(naluType))) vt.Stream.Error("H264 WriteSliceBytes naluType not support", zap.Int("naluType", int(naluType)))
} }
} }
func (vt *H264) WriteAVCC(ts uint32, frame util.BLL) { func (vt *H264) WriteAVCC(ts uint32, frame util.BLL) (err error) {
if l := frame.ByteLength; l < 6 { if l := frame.ByteLength; l < 6 {
vt.Stream.Error("AVCC data too short", zap.Int("len", l)) vt.Stream.Error("AVCC data too short", zap.Int("len", l))
return return io.ErrShortWrite
} }
if frame.GetByte(1) == 0 { if frame.GetByte(1) == 0 {
vt.SequenceHead = frame.ToBytes() vt.SequenceHead = frame.ToBytes()
frame.Recycle() frame.Recycle()
vt.updateSequeceHead() vt.updateSequeceHead()
var info codec.AVCDecoderConfigurationRecord var info codec.AVCDecoderConfigurationRecord
if _, err := info.Unmarshal(vt.SequenceHead[5:]); err == nil { if _, err = info.Unmarshal(vt.SequenceHead[5:]); err == nil {
vt.SPSInfo, _ = codec.ParseSPS(info.SequenceParameterSetNALUnit) vt.SPSInfo, _ = codec.ParseSPS(info.SequenceParameterSetNALUnit)
vt.nalulenSize = int(info.LengthSizeMinusOne&3 + 1) vt.nalulenSize = int(info.LengthSizeMinusOne&3 + 1)
vt.SPS = info.SequenceParameterSetNALUnit vt.SPS = info.SequenceParameterSetNALUnit
@@ -91,8 +93,9 @@ func (vt *H264) WriteAVCC(ts uint32, frame util.BLL) {
vt.Stream.Error("H264 ParseSpsPps Error") vt.Stream.Error("H264 ParseSpsPps Error")
vt.Stream.Close() vt.Stream.Close()
} }
return
} else { } else {
vt.Video.WriteAVCC(ts, frame) return vt.Video.WriteAVCC(ts, frame)
} }
} }

View File

@@ -1,6 +1,7 @@
package track package track
import ( import (
"io"
"time" "time"
"go.uber.org/zap" "go.uber.org/zap"
@@ -62,27 +63,25 @@ func (vt *H265) WriteSliceBytes(slice []byte) {
} }
} }
func (vt *H265) WriteAVCC(ts uint32, frame util.BLL) { func (vt *H265) WriteAVCC(ts uint32, frame util.BLL) (err error) {
if l := frame.ByteLength; l < 6 { if l := frame.ByteLength; l < 6 {
vt.Stream.Error("AVCC data too short", zap.Int("len", l)) vt.Stream.Error("AVCC data too short", zap.Int("len", l))
return return io.ErrShortWrite
} }
if frame.GetByte(1) == 0 { if frame.GetByte(1) == 0 {
vt.SequenceHead = frame.ToBytes() vt.SequenceHead = frame.ToBytes()
frame.Recycle() frame.Recycle()
vt.updateSequeceHead() vt.updateSequeceHead()
if vps, sps, pps, err := codec.ParseVpsSpsPpsFromSeqHeaderWithoutMalloc(vt.SequenceHead); err == nil { if vt.VPS, vt.SPS, vt.PPS, err = codec.ParseVpsSpsPpsFromSeqHeaderWithoutMalloc(vt.SequenceHead); err == nil {
vt.SPSInfo, _ = codec.ParseHevcSPS(vt.SequenceHead) vt.SPSInfo, _ = codec.ParseHevcSPS(vt.SequenceHead)
vt.nalulenSize = (int(vt.SequenceHead[26]) & 0x03) + 1 vt.nalulenSize = (int(vt.SequenceHead[26]) & 0x03) + 1
vt.VPS = vps
vt.SPS = sps
vt.PPS = pps
} else { } else {
vt.Stream.Error("H265 ParseVpsSpsPps Error") vt.Stream.Error("H265 ParseVpsSpsPps Error")
vt.Stream.Close() vt.Stream.Close()
} }
return
} else { } else {
vt.Video.WriteAVCC(ts, frame) return vt.Video.WriteAVCC(ts, frame)
} }
} }

View File

@@ -101,11 +101,11 @@ func (vt *Video) WriteAnnexB(pts uint32, dts uint32, frame AnnexBFrame) {
vt.Flush() vt.Flush()
} }
func (vt *Video) WriteAVCC(ts uint32, frame util.BLL) { func (vt *Video) WriteAVCC(ts uint32, frame util.BLL) error {
r := frame.NewReader() r := frame.NewReader()
b, err := r.ReadByte() b, err := r.ReadByte()
if err != nil { if err != nil {
return return err
} }
b = b >> 4 b = b >> 4
vt.Value.IFrame = b == 1 || b == 4 vt.Value.IFrame = b == 1 || b == 4
@@ -113,13 +113,14 @@ func (vt *Video) WriteAVCC(ts uint32, frame util.BLL) {
vt.Value.WriteAVCC(ts, frame) vt.Value.WriteAVCC(ts, frame)
cts, err := r.ReadBE(3) cts, err := r.ReadBE(3)
if err != nil { if err != nil {
return return err
} }
vt.Value.PTS = (ts + cts) * 90 vt.Value.PTS = (ts + cts) * 90
for nalulen, err := r.ReadBE(vt.nalulenSize); err == nil; nalulen, err = r.ReadBE(vt.nalulenSize) { for nalulen, err := r.ReadBE(vt.nalulenSize); err == nil; nalulen, err = r.ReadBE(vt.nalulenSize) {
vt.AppendAuBytes(r.ReadN(int(nalulen))...) vt.AppendAuBytes(r.ReadN(int(nalulen))...)
} }
vt.Flush() vt.Flush()
return nil
} }
func (vt *Video) WriteSliceByte(b ...byte) { func (vt *Video) WriteSliceByte(b ...byte) {

View File

@@ -83,27 +83,29 @@ type AMF struct {
Buffer Buffer
} }
func (amf *AMF) ReadShortString() string { func ReadAMF[T any](amf *AMF) (result T) {
value, _ := amf.Unmarshal() value, err := amf.Unmarshal()
return value.(string) if err != nil {
} return
func (amf *AMF) ReadNumber() float64 {
value, _ := amf.Unmarshal()
return value.(float64)
}
func (amf *AMF) ReadObject() map[string]any {
value, _ := amf.Unmarshal()
if value == nil {
return nil
} }
return value.(map[string]any) result, _ = value.(T)
return
} }
func (amf *AMF) ReadBool() bool { func (amf *AMF) ReadShortString() (result string) {
value, _ := amf.Unmarshal() return ReadAMF[string](amf)
return value.(bool) }
func (amf *AMF) ReadNumber() (result float64) {
return ReadAMF[float64](amf)
}
func (amf *AMF) ReadObject() (result map[string]any) {
return ReadAMF[map[string]any](amf)
}
func (amf *AMF) ReadBool() (result bool) {
return ReadAMF[bool](amf)
} }
func (amf *AMF) readKey() (string, error) { func (amf *AMF) readKey() (string, error) {

View File

@@ -69,6 +69,29 @@ func (r *BLLReader) ReadN(n int) (result net.Buffers) {
return return
} }
type BLLsReader struct {
*ListItem[*BLL]
BLLReader
}
func (r *BLLsReader) CanRead() bool {
return r.ListItem != nil && !r.IsRoot()
}
func (r *BLLsReader) ReadByte() (b byte, err error) {
if r.BLLReader.CanRead() {
b, err = r.BLLReader.ReadByte()
if err == nil {
return
}
}
r.ListItem = r.Next
if !r.CanRead() {
return 0, io.EOF
}
r.BLLReader = *r.Value.NewReader()
return r.BLLReader.ReadByte()
}
type BLLs struct { type BLLs struct {
List[*BLL] List[*BLL]
ByteLength int ByteLength int
@@ -121,6 +144,10 @@ func (list *BLLs) Recycle() {
list.ByteLength = 0 list.ByteLength = 0
} }
func (list *BLLs) NewReader() *BLLsReader {
return &BLLsReader{list.Next, *list.Next.Value.NewReader()}
}
// ByteLinkList // ByteLinkList
type BLL struct { type BLL struct {
List[BLI] List[BLI]