From a5399ed11fa3f44f3ed951abfd805be73c8cd168 Mon Sep 17 00:00:00 2001 From: langhuihui <178529795@qq.com> Date: Thu, 13 Feb 2025 14:02:55 +0800 Subject: [PATCH] fix: demuxer mp4 one more time --- plugin/mp4/pkg/box/box.go | 10 +++--- plugin/mp4/pkg/box/mdat.go | 14 ++++++++ plugin/mp4/pkg/box/trak.go | 7 ++++ plugin/mp4/pkg/demuxer.go | 10 ++++-- plugin/mp4/pkg/pull-recorder.go | 57 ++++++++++++++++++--------------- 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/plugin/mp4/pkg/box/box.go b/plugin/mp4/pkg/box/box.go index a88d970..9e84ed8 100644 --- a/plugin/mp4/pkg/box/box.go +++ b/plugin/mp4/pkg/box/box.go @@ -15,7 +15,7 @@ type ( BoxHeader interface { Type() BoxType HeaderSize() uint32 - Size() uint32 + Size() uint64 Header() BoxHeader HeaderWriteTo(w io.Writer) (n int64, err error) } @@ -85,7 +85,7 @@ func CreateContainerBox(typ BoxType, children ...IBox) *ContainerBox { if reflect.ValueOf(child).IsNil() { continue } - size += child.Size() + size += uint32(child.Size()) realChildren = append(realChildren, child) } return &ContainerBox{ @@ -101,9 +101,9 @@ func (b *BigBox) HeaderSize() uint32 { return BasicBoxLen + 8 } func (b *BaseBox) Header() BoxHeader { return b } func (b *BaseBox) HeaderSize() uint32 { return BasicBoxLen } -func (b *BaseBox) Size() uint32 { return b.size } - -func (b *BaseBox) Type() BoxType { return b.typ } +func (b *BaseBox) Size() uint64 { return uint64(b.size) } +func (b *BigBox) Size() uint64 { return uint64(b.size) } +func (b *BaseBox) Type() BoxType { return b.typ } func (b *BaseBox) HeaderWriteTo(w io.Writer) (n int64, err error) { var tmp [4]byte diff --git a/plugin/mp4/pkg/box/mdat.go b/plugin/mp4/pkg/box/mdat.go index 9c979fa..43b52e3 100644 --- a/plugin/mp4/pkg/box/mdat.go +++ b/plugin/mp4/pkg/box/mdat.go @@ -16,6 +16,20 @@ type MediaDataBox struct { net.Buffers } +func (box *MediaDataBox) HeaderSize() uint32 { + if box.size == 1 { + return BasicBoxLen + 8 + } + return BasicBoxLen +} + +func (box *MediaDataBox) Size() uint64 { + if box.size == 1 { + return uint64(len(box.Data)) + 8 + 8 + } + return uint64(box.size) +} + func (box *MediaDataBox) WriteTo(w io.Writer) (n int64, err error) { var tmp [8]byte var buffers net.Buffers diff --git a/plugin/mp4/pkg/box/trak.go b/plugin/mp4/pkg/box/trak.go index 8afee7d..5c08f39 100644 --- a/plugin/mp4/pkg/box/trak.go +++ b/plugin/mp4/pkg/box/trak.go @@ -144,6 +144,13 @@ func (t *TrakBox) ParseSamples() (samplelist []Sample) { } } } + + if stbl.STSS != nil { + for _, keyIndex := range stbl.STSS.Entries { + samplelist[keyIndex-1].KeyFrame = true + } + } + return samplelist } diff --git a/plugin/mp4/pkg/demuxer.go b/plugin/mp4/pkg/demuxer.go index 3958c5d..fe7daf3 100644 --- a/plugin/mp4/pkg/demuxer.go +++ b/plugin/mp4/pkg/demuxer.go @@ -49,9 +49,10 @@ type ( ReadSampleIdx []uint32 IsFragment bool // pssh []*PsshBox - moov *MoovBox - mdat *MediaDataBox - QuicTime bool + moov *MoovBox + mdat *MediaDataBox + mdatOffset uint64 + QuicTime bool } ) @@ -96,6 +97,7 @@ func (d *Demuxer) Demux() (err error) { // return // } var b IBox + var offset uint64 for { b, err = box.ReadFrom(d.reader) if err != nil { @@ -104,6 +106,7 @@ func (d *Demuxer) Demux() (err error) { } return err } + offset += b.Size() switch box := b.(type) { case *FileTypeBox: if slices.Contains(box.CompatibleBrands, [4]byte{'q', 't', ' ', ' '}) { @@ -112,6 +115,7 @@ func (d *Demuxer) Demux() (err error) { case *FreeBox: case *MediaDataBox: d.mdat = box + d.mdatOffset = offset - b.Size() + uint64(box.HeaderSize()) case *MoovBox: if box.MVEX != nil { d.IsFragment = true diff --git a/plugin/mp4/pkg/pull-recorder.go b/plugin/mp4/pkg/pull-recorder.go index a20c7b8..ae06de3 100644 --- a/plugin/mp4/pkg/pull-recorder.go +++ b/plugin/mp4/pkg/pull-recorder.go @@ -1,7 +1,6 @@ package mp4 import ( - "io" "os" "strings" "time" @@ -40,10 +39,10 @@ func NewPuller(conf config.Pull) m7s.IPuller { func (p *RecordReader) Run() (err error) { pullJob := &p.PullJob publisher := pullJob.Publisher - allocator := util.NewScalableMemoryAllocator(1 << 10) + // allocator := util.NewScalableMemoryAllocator(1 << 10) var ts, tsOffset int64 var realTime time.Time - defer allocator.Recycle() + // defer allocator.Recycle() publisher.OnGetPosition = func() time.Time { return realTime } @@ -67,17 +66,17 @@ func (p *RecordReader) Run() (err error) { switch track.Cid { case box.MP4_CODEC_H264: var sequence rtmp.RTMPVideo - sequence.SetAllocator(allocator) + // sequence.SetAllocator(allocator) sequence.Append([]byte{0x17, 0x00, 0x00, 0x00, 0x00}, track.ExtraData) err = publisher.WriteVideo(&sequence) case box.MP4_CODEC_H265: var sequence rtmp.RTMPVideo - sequence.SetAllocator(allocator) + // sequence.SetAllocator(allocator) sequence.Append([]byte{0b1001_0000 | rtmp.PacketTypeSequenceStart}, codec.FourCC_H265[:], track.ExtraData) err = publisher.WriteVideo(&sequence) case box.MP4_CODEC_AAC: var sequence rtmp.RTMPAudio - sequence.SetAllocator(allocator) + // sequence.SetAllocator(allocator) sequence.Append([]byte{0xaf, 0x00}, track.ExtraData) err = publisher.WriteAudio(&sequence) } @@ -109,14 +108,19 @@ func (p *RecordReader) Run() (err error) { goto nextStream } - if _, err = p.demuxer.reader.Seek(sample.Offset, io.SeekStart); err != nil { - return - } - sample.Data = allocator.Malloc(sample.Size) - if _, err = io.ReadFull(p.demuxer.reader, sample.Data); err != nil { - allocator.Free(sample.Data) + // if _, err = p.demuxer.reader.Seek(sample.Offset, io.SeekStart); err != nil { + // return + // } + sampleOffset := int(sample.Offset) - int(p.demuxer.mdatOffset) + if sampleOffset < 0 || sampleOffset+sample.Size > len(p.demuxer.mdat.Data) { return } + sample.Data = p.demuxer.mdat.Data[sampleOffset : sampleOffset+sample.Size] + // sample.Data = allocator.Malloc(sample.Size) + // if _, err = io.ReadFull(p.demuxer.reader, sample.Data); err != nil { + // allocator.Free(sample.Data) + // return + // } ts = int64(sample.DTS + uint64(tsOffset)) realTime = stream.StartTime.Add(time.Duration(sample.DTS) * time.Millisecond) if p.MaxTS > 0 && ts > p.MaxTS { @@ -125,15 +129,15 @@ func (p *RecordReader) Run() (err error) { switch track.Cid { case box.MP4_CODEC_H264: var videoFrame rtmp.RTMPVideo - videoFrame.SetAllocator(allocator) + // videoFrame.SetAllocator(allocator) videoFrame.CTS = uint32(sample.PTS - sample.DTS) videoFrame.Timestamp = uint32(ts) - videoFrame.AppendOne([]byte{util.Conditional[byte](sample.KeyFrame, 0x17, 0x27), 0x01, byte(videoFrame.CTS >> 24), byte(videoFrame.CTS >> 8), byte(videoFrame.CTS)}) - videoFrame.AddRecycleBytes(sample.Data) + videoFrame.Append([]byte{util.Conditional[byte](sample.KeyFrame, 0x17, 0x27), 0x01, byte(videoFrame.CTS >> 24), byte(videoFrame.CTS >> 8), byte(videoFrame.CTS)}, sample.Data) + // videoFrame.AddRecycleBytes(sample.Data) err = publisher.WriteVideo(&videoFrame) case box.MP4_CODEC_H265: var videoFrame rtmp.RTMPVideo - videoFrame.SetAllocator(allocator) + // videoFrame.SetAllocator(allocator) videoFrame.CTS = uint32(sample.PTS - sample.DTS) videoFrame.Timestamp = uint32(ts) var head []byte @@ -150,28 +154,29 @@ func (p *RecordReader) Run() (err error) { util.PutBE(head[5:8], videoFrame.CTS) // cts } copy(head[1:], codec.FourCC_H265[:]) - videoFrame.AddRecycleBytes(sample.Data) + videoFrame.Append(head, sample.Data) + // videoFrame.AddRecycleBytes(sample.Data) err = publisher.WriteVideo(&videoFrame) case box.MP4_CODEC_AAC: var audioFrame rtmp.RTMPAudio - audioFrame.SetAllocator(allocator) + // audioFrame.SetAllocator(allocator) audioFrame.Timestamp = uint32(ts) - audioFrame.AppendOne([]byte{0xaf, 0x01}) - audioFrame.AddRecycleBytes(sample.Data) + audioFrame.Append([]byte{0xaf, 0x01}, sample.Data) + // audioFrame.AddRecycleBytes(sample.Data) err = publisher.WriteAudio(&audioFrame) case box.MP4_CODEC_G711A: var audioFrame rtmp.RTMPAudio - audioFrame.SetAllocator(allocator) + // audioFrame.SetAllocator(allocator) audioFrame.Timestamp = uint32(ts) - audioFrame.AppendOne([]byte{0x72}) - audioFrame.AddRecycleBytes(sample.Data) + audioFrame.Append([]byte{0x72}, sample.Data) + // audioFrame.AddRecycleBytes(sample.Data) err = publisher.WriteAudio(&audioFrame) case box.MP4_CODEC_G711U: var audioFrame rtmp.RTMPAudio - audioFrame.SetAllocator(allocator) + // audioFrame.SetAllocator(allocator) audioFrame.Timestamp = uint32(ts) - audioFrame.AppendOne([]byte{0x82}) - audioFrame.AddRecycleBytes(sample.Data) + audioFrame.Append([]byte{0x82}, sample.Data) + // audioFrame.AddRecycleBytes(sample.Data) err = publisher.WriteAudio(&audioFrame) } }