memory leak

This commit is contained in:
langhuihui
2024-06-14 17:13:02 +08:00
parent 00b39aee3e
commit 2b7672cdc2
14 changed files with 282 additions and 277 deletions
+4 -4
View File
@@ -63,16 +63,16 @@ type Annexb265Ctx struct {
func (a *Annexb264Ctx) CreateFrame(frame *AVFrame) (IAVFrame, error) {
var annexb AnnexB
// annexb.RecyclableBuffers.ScalableMemoryAllocator = frame.Wraps[0].GetScalableMemoryAllocator()
annexb.ReadFromBytes(codec.NALU_Delimiter2)
annexb.Append(codec.NALU_Delimiter2)
if frame.IDR {
annexb.ReadFromBytes(a.SPS[0], codec.NALU_Delimiter2, a.PPS[0], codec.NALU_Delimiter2)
annexb.Append(a.SPS[0], codec.NALU_Delimiter2, a.PPS[0], codec.NALU_Delimiter2)
}
var nalus = frame.Raw.(Nalus)
for i, nalu := range nalus.Nalus {
if i > 0 {
annexb.ReadFromBytes(codec.NALU_Delimiter1)
annexb.Append(codec.NALU_Delimiter1)
}
annexb.ReadFromBytes(nalu...)
annexb.Append(nalu...)
}
return &annexb, nil
}
+2 -4
View File
@@ -107,11 +107,9 @@ func (nalus *Nalus) ParseAVCC(reader *util.MemoryReader, naluSizeLen int) error
if err != nil {
return err
}
nalu, err := reader.ReadBytes(int(l))
if err != nil {
return err
for nalu := range reader.RangeN(l) {
nalus.Append(nalu)
}
nalus.Append(nalu)
}
return nil
}
+52 -37
View File
@@ -4,29 +4,29 @@ import (
"io"
)
const defaultBufSize = 1 << 16
const defaultBufSize = 1 << 14
type BufReader struct {
reader io.Reader
allocator *ScalableMemoryAllocator
buf MemoryReader
BufLen int
Err error
}
func NewBufReaderWithBufLen(reader io.Reader, bufLen int) (r *BufReader) {
r = &BufReader{}
r.reader = reader
r.allocator = NewScalableMemoryAllocator(bufLen)
r.BufLen = bufLen
r = &BufReader{
reader: reader,
allocator: NewScalableMemoryAllocator(bufLen),
BufLen: bufLen,
}
r.buf.Memory = &Memory{}
//fmt.Println("NewBufReaderWithBufLen", uintptr(unsafe.Pointer(r.allocator)))
return
}
func NewBufReader(reader io.Reader) (r *BufReader) {
r = &BufReader{}
r.reader = reader
r.allocator = NewScalableMemoryAllocator(defaultBufSize)
r.BufLen = defaultBufSize
return
return NewBufReaderWithBufLen(reader, defaultBufSize)
}
func (r *BufReader) Recycle() {
@@ -39,25 +39,27 @@ func (r *BufReader) eat() error {
buf := r.allocator.Malloc(r.BufLen)
if n, err := r.reader.Read(buf); err != nil {
r.allocator.Free(buf)
r.Err = err
return err
} else {
if n < r.BufLen {
r.allocator.Free(buf[n:])
buf = buf[:n]
}
r.buf.ReadFromBytes(buf)
r.buf.Buffers = append(r.buf.Buffers, buf)
r.buf.Size += n
r.buf.Length += n
}
return nil
}
func (r *BufReader) ReadByte() (b byte, err error) {
for ; r.buf.Length == 0 && err == nil; err = r.eat() {
for r.buf.Length == 0 {
if err = r.eat(); err != nil {
return
}
}
if err == nil {
b, err = r.buf.ReadByte()
}
return
return r.buf.ReadByte()
}
func (r *BufReader) ReadBE(n int) (num int, err error) {
@@ -93,30 +95,43 @@ func (r *BufReader) ReadBE32(n int) (num uint32, err error) {
return
}
func (r *BufReader) ReadBytes(n int) (mem RecyclableMemory, err error) {
mem.ScalableMemoryAllocator = r.allocator
defer func() {
if err != nil {
mem.Recycle()
mem = RecyclableMemory{}
}
}()
for r.recycleFront(); n > 0 && err == nil; err = r.eat() {
if r.buf.Length > 0 {
if r.buf.Length >= n {
mem.AddRecycleBytes(r.buf.ClipN(n)...)
return
}
n -= r.buf.Length
mem.AddRecycleBytes(r.buf.Buffers...)
r.buf = MemoryReader{}
func (r *BufReader) Skip(n int) (err error) {
r.recycleFront()
for r.buf.Length < n {
if err = r.eat(); err != nil {
return err
}
}
r.buf.RangeN(n)(nil)
return
}
func (r *BufReader) recycleFront() {
for _, buf := range r.buf.ClipFront() {
r.allocator.Free(buf)
func (r *BufReader) ReadRange(n int) func(func([]byte) bool) {
return func(yield func([]byte) bool) {
for r.recycleFront(); n > 0 && r.Err == nil; r.eat() {
if r.buf.Length > 0 {
if r.buf.Length >= n {
r.buf.RangeN(n)(yield)
return
}
n -= r.buf.Length
for _, buf := range r.buf.Buffers {
yield(buf)
}
r.buf.MoveToEnd()
}
}
}
}
func (r *BufReader) ReadBytes(n int) (mem Memory, err error) {
for buf := range r.ReadRange(n) {
mem.Buffers = append(mem.Buffers, buf)
}
mem.Size = n
return mem, r.Err
}
func (r *BufReader) recycleFront() {
r.buf.ClipFront(r.allocator.Free)
}
+1 -3
View File
@@ -114,20 +114,18 @@ func BenchmarkBufRead(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
var testData = make([]byte, 10*1024*1024)
var err error
var mem RecyclableMemory
for pb.Next() {
rand.Read(testData)
testReader := bytes.NewReader(testData)
reader := NewBufReaderWithBufLen(testReader, 1024)
for err == nil {
mem.Recycle()
r := rand.Intn(10)
if r < 4 {
_, err = reader.ReadByte()
} else if r < 7 {
_, err = reader.ReadBE(4)
} else {
mem, err = reader.ReadBytes(rand.Intn(4096))
_, err = reader.ReadBytes(rand.Intn(4096))
}
}
}
+111 -136
View File
@@ -12,7 +12,7 @@ type Memory struct {
}
type MemoryReader struct {
Memory
*Memory
Length int
offset0 int
offset1 int
@@ -24,7 +24,7 @@ func NewMemoryFromBytes(b ...[]byte) *Memory {
func NewReadableBuffersFromBytes(b ...[]byte) *MemoryReader {
buf := NewMemory(b)
return &MemoryReader{Memory: *buf, Length: buf.Size}
return &MemoryReader{Memory: NewMemory(b), Length: buf.Size}
}
func NewMemory(buffers net.Buffers) *Memory {
@@ -35,75 +35,74 @@ func NewMemory(buffers net.Buffers) *Memory {
return ret
}
func (buffers *Memory) UpdateBuffer(index int, buf []byte) {
func (m *Memory) UpdateBuffer(index int, buf []byte) {
if index < 0 {
index = len(buffers.Buffers) + index
index = len(m.Buffers) + index
}
buffers.Size = len(buf) - len(buffers.Buffers[index])
buffers.Buffers[index] = buf
m.Size = len(buf) - len(m.Buffers[index])
m.Buffers[index] = buf
}
func (buffers *Memory) CopyFrom(b Memory) {
func (m *Memory) CopyFrom(b *Memory) {
buf := make([]byte, b.Size)
bufs := slices.Clone(b.Buffers)
bufs.Read(buf)
buffers.ReadFromBytes(buf)
b.CopyTo(buf)
m.Append(buf)
}
func (buffers *Memory) ReadFromBytes(b ...[]byte) {
buffers.Buffers = append(buffers.Buffers, b...)
for _, level0 := range b {
buffers.Size += len(level0)
func (m *Memory) CopyTo(buf []byte) {
for _, b := range m.Buffers {
l := len(b)
copy(buf, b)
buf = buf[l:]
}
}
func (buffers *Memory) Count() int {
return len(buffers.Buffers)
func (m *Memory) Append(b ...[]byte) {
m.Buffers = append(m.Buffers, b...)
for _, level0 := range b {
m.Size += len(level0)
}
}
func (r Memory) NewReader() *MemoryReader {
func (m *Memory) Count() int {
return len(m.Buffers)
}
func (m *Memory) NewReader() *MemoryReader {
var reader MemoryReader
reader.Memory = r
reader.Length = r.Size
reader.Memory = m
reader.Length = m.Size
return &reader
}
func (buffers *MemoryReader) ReadFromBytes(b ...[]byte) {
buffers.Memory.Buffers = append(buffers.Memory.Buffers, b...)
for _, level0 := range b {
buffers.Size += len(level0)
buffers.Length += len(level0)
}
}
func (buffers *MemoryReader) Pop() []byte {
func (r *MemoryReader) Pop() []byte {
panic("ReadableBuffers Pop not allowed")
}
func (buffers *MemoryReader) GetCurrent() []byte {
return buffers.Memory.Buffers[buffers.offset0][buffers.offset1:]
func (r *MemoryReader) GetCurrent() []byte {
return r.Memory.Buffers[r.offset0][r.offset1:]
}
func (buffers *MemoryReader) MoveToEnd() {
buffers.offset0 = buffers.Count()
buffers.offset1 = 0
buffers.Length = 0
func (r *MemoryReader) MoveToEnd() {
r.offset0 = r.Count()
r.offset1 = 0
r.Length = 0
}
func (buffers *MemoryReader) ReadBytesTo(buf []byte) (actual int) {
func (r *MemoryReader) ReadBytesTo(buf []byte) (actual int) {
n := len(buf)
curBuf := buffers.GetCurrent()
curBuf := r.GetCurrent()
curBufLen := len(curBuf)
if n > buffers.Length {
if n > r.Length {
if curBufLen > 0 {
actual += copy(buf, curBuf)
buffers.offset0++
buffers.offset1 = 0
r.offset0++
r.offset1 = 0
}
for _, b := range buffers.Memory.Buffers[buffers.offset0:] {
for _, b := range r.Memory.Buffers[r.offset0:] {
actual += copy(buf[actual:], b)
}
buffers.MoveToEnd()
r.MoveToEnd()
return
}
l := n
@@ -111,25 +110,25 @@ func (buffers *MemoryReader) ReadBytesTo(buf []byte) (actual int) {
if n < curBufLen {
actual += n
copy(buf[l-n:], curBuf[:n])
buffers.forward(n)
r.forward(n)
break
}
copy(buf[l-n:], curBuf)
n -= curBufLen
actual += curBufLen
buffers.skipBuf()
if buffers.Length == 0 && n > 0 {
r.skipBuf()
if r.Length == 0 && n > 0 {
return
}
}
return
}
func (reader *MemoryReader) ReadByteTo(b ...*byte) (err error) {
func (r *MemoryReader) ReadByteTo(b ...*byte) (err error) {
for i := range b {
if reader.Length == 0 {
if r.Length == 0 {
return io.EOF
}
*b[i], err = reader.ReadByte()
*b[i], err = r.ReadByte()
if err != nil {
return
}
@@ -137,37 +136,37 @@ func (reader *MemoryReader) ReadByteTo(b ...*byte) (err error) {
return
}
func (reader *MemoryReader) ReadByteMask(mask byte) (byte, error) {
b, err := reader.ReadByte()
func (r *MemoryReader) ReadByteMask(mask byte) (byte, error) {
b, err := r.ReadByte()
if err != nil {
return 0, err
}
return b & mask, nil
}
func (reader *MemoryReader) ReadByte() (b byte, err error) {
if reader.Length == 0 {
func (r *MemoryReader) ReadByte() (b byte, err error) {
if r.Length == 0 {
return 0, io.EOF
}
curBuf := reader.GetCurrent()
curBuf := r.GetCurrent()
b = curBuf[0]
if len(curBuf) == 1 {
reader.skipBuf()
r.skipBuf()
} else {
reader.forward(1)
r.forward(1)
}
return
}
func (reader *MemoryReader) LEB128Unmarshal() (uint, int, error) {
func (r *MemoryReader) LEB128Unmarshal() (uint, int, error) {
v := uint(0)
n := 0
for i := 0; i < 8; i++ {
b, err := reader.ReadByte()
b, err := r.ReadByte()
if err != nil {
return 0, 0, err
}
v |= (uint(b&0b01111111) << (i * 7))
v |= uint(b&0b01111111) << (i * 7)
n++
if (b & 0b10000000) == 0 {
@@ -177,82 +176,52 @@ func (reader *MemoryReader) LEB128Unmarshal() (uint, int, error) {
return v, n, nil
}
func (reader *MemoryReader) getCurrentBufLen() int {
return len(reader.Memory.Buffers[reader.offset0]) - reader.offset1
func (r *MemoryReader) getCurrentBufLen() int {
return len(r.Memory.Buffers[r.offset0]) - r.offset1
}
func (reader *MemoryReader) Skip(n int) error {
if n > reader.Length {
func (r *MemoryReader) Skip(n int) error {
if n > r.Length {
return io.EOF
}
curBufLen := reader.getCurrentBufLen()
curBufLen := r.getCurrentBufLen()
for n > 0 {
if n < curBufLen {
reader.forward(n)
r.forward(n)
break
}
n -= curBufLen
reader.skipBuf()
if reader.Length == 0 && n > 0 {
r.skipBuf()
if r.Length == 0 && n > 0 {
return io.EOF
}
}
return nil
}
func (reader *MemoryReader) forward(n int) {
reader.Length -= n
reader.offset1 += n
func (r *MemoryReader) forward(n int) {
r.Length -= n
r.offset1 += n
}
func (buffers *MemoryReader) skipBuf() {
curBufLen := buffers.getCurrentBufLen()
buffers.Length -= curBufLen
buffers.offset0++
buffers.offset1 = 0
func (r *MemoryReader) skipBuf() {
curBufLen := r.getCurrentBufLen()
r.Length -= curBufLen
r.offset0++
r.offset1 = 0
}
func (reader *MemoryReader) ReadBytes(n int) ([]byte, error) {
if n > reader.Length {
func (r *MemoryReader) ReadBytes(n int) ([]byte, error) {
if n > r.Length {
return nil, io.EOF
}
b := make([]byte, n)
actual := reader.ReadBytesTo(b)
actual := r.ReadBytesTo(b)
return b[:actual], nil
}
// func (buffers *ReadableBuffers) WriteTo(w io.Writer) (n int64, err error) {
// var buf net.Buffers
// if buffers.Count() > buffers.offset1 {
// buf = append(buf, buffers.Buffers[buffers.offset:]...)
// }
// if buffers.curBufLen > 0 {
// buf[0] = buffers.curBuf
// }
// buffers.MoveToEnd()
// return buf.WriteTo(w)
// }
func (reader *MemoryReader) WriteNTo(n int, result *net.Buffers) (actual int) {
for actual = n; reader.Length > 0 && n > 0; reader.skipBuf() {
curBuf := reader.GetCurrent()
if len(curBuf) > n {
if result != nil {
*result = append(*result, curBuf[:n])
}
reader.forward(n)
return actual
}
if result != nil {
*result = append(*result, curBuf)
}
n -= len(curBuf)
}
return actual - n
}
func (reader *MemoryReader) ReadBE(n int) (num int, err error) {
func (r *MemoryReader) ReadBE(n int) (num int, err error) {
for i := range n {
b, err := reader.ReadByte()
b, err := r.ReadByte()
if err != nil {
return -1, err
}
@@ -261,39 +230,45 @@ func (reader *MemoryReader) ReadBE(n int) (num int, err error) {
return
}
func (reader *MemoryReader) ClipN(n int) (r net.Buffers) {
reader.WriteNTo(n, nil)
return reader.ClipFront()
func (r *MemoryReader) RangeN(n int) func(yield func([]byte) bool) {
return func(yield func([]byte) bool) {
for good := yield != nil; r.Length > 0 && n > 0; r.skipBuf() {
curBuf := r.GetCurrent()
if curBufLen := len(curBuf); curBufLen > n {
if r.forward(n); good {
good = yield(curBuf[:n])
}
return
} else if n -= curBufLen; good {
good = yield(curBuf)
}
}
}
}
func (reader *MemoryReader) ClipFront() (r net.Buffers) {
offset := reader.Size - reader.Length
func (r *MemoryReader) ClipFront(yield func([]byte) bool) {
offset := r.Size - r.Length
if offset == 0 {
return
}
buffers := &reader.Memory
if reader.Length == 0 {
r = slices.Clone(buffers.Buffers)
buffers.Buffers = buffers.Buffers[:0]
} else {
r = slices.Clone(buffers.Buffers[:reader.offset0])
if reader.offset1 > 0 {
r = append(r, buffers.Buffers[reader.offset0][:reader.offset1])
buffers.Buffers[reader.offset0] = reader.GetCurrent()
if m := r.Memory; r.Length == 0 {
for _, buf := range m.Buffers {
yield(buf)
}
if reader.offset0 > 0 {
buffers.Buffers = slices.Delete(buffers.Buffers, 0, reader.offset0)
m.Buffers = m.Buffers[:0]
} else {
for _, buf := range m.Buffers[:r.offset0] {
yield(buf)
}
if r.offset1 > 0 {
yield(m.Buffers[r.offset0][:r.offset1])
m.Buffers[r.offset0] = r.GetCurrent()
}
if r.offset0 > 0 {
m.Buffers = slices.Delete(m.Buffers, 0, r.offset0)
}
}
// bs := 0
// for _, b := range r {
// bs += len(b)
// }
// if bs != offset {
// panic("ClipFront error")
// }
reader.Size -= offset
reader.offset0 = 0
reader.offset1 = 0
return
}
r.Size -= offset
r.offset0 = 0
r.offset1 = 0
}
+33 -30
View File
@@ -1,6 +1,7 @@
package util
import (
"fmt"
"slices"
"sync"
"unsafe"
@@ -8,16 +9,16 @@ import (
const (
MaxBlockSize = 1 << 22
BuddySize = MaxBlockSize << 4
BuddySize = MaxBlockSize << 7
MinPowerOf2 = 10
)
var (
memoryPool [BuddySize]byte
buddy = NewBuddy(BuddySize >> MinPowerOf2)
lock sync.Mutex
poolStart = int64(uintptr(unsafe.Pointer(&memoryPool[0])))
//EnableCheckSize bool = false
memoryPool [BuddySize]byte
buddy = NewBuddy(BuddySize >> MinPowerOf2)
lock sync.Mutex
poolStart = int64(uintptr(unsafe.Pointer(&memoryPool[0])))
EnableCheckSize bool = false
)
type MemoryAllocator struct {
@@ -50,13 +51,14 @@ func NewMemoryAllocator(size int) (ret *MemoryAllocator) {
memory: make([]byte, size),
allocator: NewAllocator(size),
}
fmt.Println(size)
ret.start = int64(uintptr(unsafe.Pointer(&ret.memory[0])))
return
}
func (ma *MemoryAllocator) Recycle() {
lock.Lock()
_ = buddy.Free(int((poolStart - ma.start) >> 10))
_ = buddy.Free(int((poolStart - ma.start) >> MinPowerOf2))
lock.Unlock()
}
@@ -101,8 +103,12 @@ func (sma *ScalableMemoryAllocator) checkSize() {
for _, child := range sma.children {
totalFree += child.allocator.GetFreeSize()
}
if totalFree != sma.size-(int(sma.totalMalloc)-int(sma.totalFree)) {
if inUse := sma.totalMalloc - sma.totalFree; totalFree != sma.size-int(inUse) {
panic("CheckSize")
} else {
if inUse > 3000000 {
fmt.Println(uintptr(unsafe.Pointer(sma)), inUse)
}
}
}
@@ -136,9 +142,9 @@ func (sma *ScalableMemoryAllocator) Malloc(size int) (memory []byte) {
if sma == nil {
return make([]byte, size)
}
//if EnableCheckSize {
// defer sma.checkSize()
//}
if EnableCheckSize {
defer sma.checkSize()
}
defer sma.addMallocCount(size)
var child *MemoryAllocator
for _, child = range sma.children {
@@ -146,7 +152,7 @@ func (sma *ScalableMemoryAllocator) Malloc(size int) (memory []byte) {
return
}
}
for sma.childSize <= MaxBlockSize {
for sma.childSize < MaxBlockSize {
sma.childSize = sma.childSize << 1
if sma.childSize >= size {
break
@@ -167,19 +173,19 @@ func (sma *ScalableMemoryAllocator) Free(mem []byte) bool {
if sma == nil {
return false
}
//if EnableCheckSize {
// defer sma.checkSize()
//}
if EnableCheckSize {
defer sma.checkSize()
}
ptr := int64(uintptr(unsafe.Pointer(&mem[0])))
size := len(mem)
for i, child := range sma.children {
for _, child := range sma.children {
if start := int(ptr - child.start); start >= 0 && start < child.Size && child.free(start, size) {
sma.addFreeCount(size)
if len(sma.children) > 1 && child.allocator.sizeTree.End-child.allocator.sizeTree.Start == child.Size {
child.Recycle()
sma.children = slices.Delete(sma.children, i, i+1)
sma.size -= child.Size
}
//if len(sma.children) > 1 && child.allocator.sizeTree.End-child.allocator.sizeTree.Start == child.Size {
// child.Recycle()
// sma.children = slices.Delete(sma.children, i, i+1)
// sma.size -= child.Size
//}
return true
}
}
@@ -195,25 +201,22 @@ type RecyclableMemory struct {
func (r *RecyclableMemory) NextN(size int) (memory []byte) {
memory = r.ScalableMemoryAllocator.Malloc(size)
if r.RecycleIndexes != nil {
r.RecycleIndexes = append(r.RecycleIndexes, len(r.Buffers))
r.RecycleIndexes = append(r.RecycleIndexes, r.Count())
}
r.ReadFromBytes(memory)
r.Append(memory)
return
}
func (r *RecyclableMemory) AddRecycleBytes(b ...[]byte) {
func (r *RecyclableMemory) AddRecycleBytes(b []byte) {
if r.RecycleIndexes != nil {
start := len(r.Buffers)
for i := range b {
r.RecycleIndexes = append(r.RecycleIndexes, start+i)
}
r.RecycleIndexes = append(r.RecycleIndexes, r.Count())
}
r.ReadFromBytes(b...)
r.Append(b)
}
func (r *RecyclableMemory) RemoveRecycleBytes(index int) (buf []byte) {
if index < 0 {
index = len(r.Buffers) + index
index = r.Count() + index
}
buf = r.Buffers[index]
if r.RecycleIndexes != nil {
+11 -5
View File
@@ -15,13 +15,16 @@ import (
type HDLPuller struct {
*util.BufReader
*util.ScalableMemoryAllocator
hasAudio bool
hasVideo bool
absTS uint32 //绝对时间戳
}
func NewHDLPuller() *HDLPuller {
return &HDLPuller{}
return &HDLPuller{
ScalableMemoryAllocator: util.NewScalableMemoryAllocator(1024),
}
}
func (puller *HDLPuller) Connect(p *m7s.Client) (err error) {
@@ -51,9 +54,8 @@ func (puller *HDLPuller) Connect(p *m7s.Client) (err error) {
}
}
if err == nil {
var head util.RecyclableMemory
var head util.Memory
head, err = puller.BufReader.ReadBytes(13)
defer head.Recycle()
if err == nil {
var flvHead [3]byte
var version, flag byte
@@ -102,10 +104,15 @@ func (puller *HDLPuller) Pull(p *m7s.Puller) (err error) {
}
puller.ReadBE(3) // stream id always 0
var frame rtmp.RTMPData
frame.RecyclableMemory, err = puller.ReadBytes(int(dataSize))
frame.ScalableMemoryAllocator = puller.ScalableMemoryAllocator
mem, err := puller.ReadBytes(int(dataSize))
if err != nil {
return err
}
switch t {
case FLV_TAG_TYPE_AUDIO, FLV_TAG_TYPE_VIDEO:
mem.CopyTo(frame.NextN(mem.Size))
}
puller.absTS = offsetTs + (timestamp - startTs)
frame.Timestamp = puller.absTS
// fmt.Println(t, offsetTs, timestamp, startTs, puller.absTS)
@@ -116,7 +123,6 @@ func (puller *HDLPuller) Pull(p *m7s.Puller) (err error) {
p.WriteVideo(frame.WrapVideo())
case FLV_TAG_TYPE_SCRIPT:
p.Info("script")
frame.Recycle()
}
}
return
+1 -1
View File
@@ -50,7 +50,7 @@ func (avcc *RTMPAudio) Parse(t *AVTrack) (isIDR, isSeq bool, raw any, err error)
return
}
var cloneFrame RTMPAudio
cloneFrame.CopyFrom(avcc.Memory)
cloneFrame.CopyFrom(&avcc.Memory)
ctx.AudioObjectType = b0 >> 3
ctx.SamplingFrequencyIndex = (b0 & 0x07 << 1) | (b1 >> 7)
ctx.ChannelConfiguration = (b1 >> 3) & 0x0F
+2 -5
View File
@@ -119,10 +119,9 @@ func (nc *NetConnection) simple_handshake(C1 []byte, checkC2 bool) error {
if err != nil {
return err
}
C2.Recycle()
if checkC2 {
buf := nc.mediaDataPool.NextN(C2.Size)
_, err = C2.Read(buf)
C2.CopyTo(buf)
if !bytes.Equal(buf[8:], S0S1[9:]) {
return errors.New("C2 Error")
}
@@ -179,9 +178,7 @@ func (nc *NetConnection) complex_handshake(C1 []byte) error {
buffer := net.Buffers{[]byte{RTMP_HANDSHAKE_VERSION}, S1, S2_Random, S2_Digest}
_, err = buffer.WriteTo(nc)
b, _ := nc.ReadBytes(1536)
b.Recycle()
return err
return nc.Skip(1536)
}
func validateClient(C1 []byte) (scheme int, challenge []byte, digest []byte, ok bool, err error) {
+13 -11
View File
@@ -146,16 +146,13 @@ func (conn *NetConnection) readChunk() (msg *Chunk, err error) {
if msgLen == 0 {
return nil, nil
}
var mem util.RecyclableMemory
var bufSize = 0
if unRead := msgLen - chunk.bufLen; unRead < conn.readChunkSize {
mem, err = conn.ReadBytes(unRead)
bufSize = unRead
} else {
mem, err = conn.ReadBytes(conn.readChunkSize)
bufSize = conn.readChunkSize
}
if err != nil {
return nil, err
}
conn.readSeqNum += uint32(mem.Size)
conn.readSeqNum += uint32(bufSize)
if chunk.bufLen == 0 {
chunk.AVData.RecyclableMemory = util.RecyclableMemory{
ScalableMemoryAllocator: conn.mediaDataPool.ScalableMemoryAllocator,
@@ -163,9 +160,12 @@ func (conn *NetConnection) readChunk() (msg *Chunk, err error) {
chunk.AVData.NextN(msgLen)
}
buffer := chunk.AVData.Buffers[0]
for _, b := range mem.Buffers {
copy(buffer[chunk.bufLen:], b)
chunk.bufLen += len(b)
for buf := range conn.ReadRange(bufSize) {
copy(buffer[chunk.bufLen:], buf)
chunk.bufLen += len(buf)
}
if conn.Err != nil {
return nil, conn.Err
}
if chunk.bufLen == msgLen {
msg = chunk
@@ -332,7 +332,9 @@ func (conn *NetConnection) sendChunk(data net.Buffers, head *ChunkHeader, headTy
head.WriteTo(RTMP_CHUNK_HEAD_1, &chunk3)
r := util.NewReadableBuffersFromBytes(data...)
for {
r.WriteNTo(conn.WriteChunkSize, &chunks)
for buf := range r.RangeN(conn.WriteChunkSize) {
chunks = append(chunks, buf)
}
if r.Length <= 0 {
break
}
+3 -3
View File
@@ -31,7 +31,7 @@ func (avcc *RTMPVideo) Parse(t *AVTrack) (isIDR, isSeq bool, raw any, err error)
isSeq = true
isIDR = false
var cloneFrame RTMPVideo
cloneFrame.CopyFrom(avcc.Memory)
cloneFrame.CopyFrom(&avcc.Memory)
switch fourCC {
case codec.FourCC_H264:
var ctx H264Ctx
@@ -125,7 +125,7 @@ func (avcc *RTMPVideo) DecodeConfig(t *AVTrack, from ICodecCtx) (err error) {
b.Write(h264ctx.PPS[0])
t.ICodecCtx = &ctx
var seqFrame RTMPData
seqFrame.ReadFromBytes(b)
seqFrame.Append(b)
t.SequenceFrame = seqFrame.WrapVideo()
if t.Enabled(context.TODO(), TraceLevel) {
c := t.FourCC().String()
@@ -241,7 +241,7 @@ func createH26xFrame(from *AVFrame, codecID VideoCodecID) (frame IAVFrame, err e
naluLenM := rtmpVideo.NextN(4)
naluLen := uint32(util.LenOfBuffers(nalu))
binary.BigEndian.PutUint32(naluLenM, naluLen)
rtmpVideo.ReadFromBytes(nalu...)
rtmpVideo.Append(nalu...)
}
frame = &rtmpVideo
return
+7 -14
View File
@@ -1,7 +1,6 @@
package m7s
import (
"errors"
"reflect"
"sync"
"time"
@@ -182,7 +181,7 @@ func (p *Publisher) WriteVideo(data IAVFrame) (err error) {
}
t := p.VideoTrack.AVTrack
if t == nil {
t = NewAVTrack(data, p.Logger.With("track", "video"), 100)
t = NewAVTrack(data, p.Logger.With("track", "video"), 20)
p.Lock()
p.VideoTrack.AVTrack = t
p.VideoTrack.Add(t)
@@ -293,7 +292,7 @@ func (p *Publisher) WriteAudio(data IAVFrame) (err error) {
}
t := p.AudioTrack.AVTrack
if t == nil {
t = NewAVTrack(data, p.Logger.With("track", "audio"), 256)
t = NewAVTrack(data, p.Logger.With("track", "audio"), 20)
p.Lock()
p.AudioTrack.AVTrack = t
p.AudioTrack.Add(t)
@@ -363,7 +362,7 @@ func (p *Publisher) Dispose(err error) {
if p.State == PublisherStateDisposed {
return
}
if !errors.Is(p.StopReason(), ErrKick) && p.IsStopped() {
if p.IsStopped() {
if !p.AudioTrack.IsEmpty() {
p.AudioTrack.Dispose()
}
@@ -378,18 +377,12 @@ func (p *Publisher) Dispose(err error) {
func (p *Publisher) TakeOver(old *Publisher) {
p.baseTs = old.lastTs
p.VideoTrack = old.VideoTrack
p.VideoTrack.ICodecCtx = nil
p.VideoTrack.Logger = p.Logger.With("track", "video")
p.AudioTrack = old.AudioTrack
p.AudioTrack.ICodecCtx = nil
p.AudioTrack.Logger = p.Logger.With("track", "audio")
p.DataTrack = old.DataTrack
p.Info("takeOver", "old", old.ID)
for subscriber := range old.SubscriberRange {
p.AddSubscriber(subscriber)
}
if old.Plugin != nil {
old.Dispose(nil)
}
old.Subscribers = util.Collection[int, *Subscriber]{}
// for _, track := range p.TransTrack {
// track.ICodecCtx = nil
// }
}
+23 -18
View File
@@ -276,9 +276,7 @@ func (s *Server) eventLoop() {
if publisher.Plugin != nil {
if err := publisher.checkTimeout(); err != nil {
publisher.Dispose(err)
newPublisher := &Publisher{}
newPublisher.StreamPath = publisher.StreamPath
s.Waiting.Set(newPublisher)
s.createWait(publisher.StreamPath)
}
}
for sub := range publisher.SubscriberRange {
@@ -365,7 +363,7 @@ func (s *Server) eventLoop() {
func (s *Server) onUnsubscribe(subscriber *Subscriber) {
s.Subscribers.Remove(subscriber)
s.Info("unsubscribe", "streamPath", subscriber.StreamPath)
s.Info("unsubscribe", "streamPath", subscriber.StreamPath, "reason", subscriber.StopReason())
if subscriber.Closer != nil {
subscriber.Close()
}
@@ -383,9 +381,13 @@ func (s *Server) onUnsubscribe(subscriber *Subscriber) {
func (s *Server) onUnpublish(publisher *Publisher) {
s.Streams.Remove(publisher)
s.Waiting.Add(publisher)
s.Info("unpublish", "streamPath", publisher.StreamPath, "count", s.Streams.Length)
s.Info("unpublish", "streamPath", publisher.StreamPath, "count", s.Streams.Length, "reason", publisher.StopReason())
for subscriber := range publisher.SubscriberRange {
subscriber.TimeoutTimer.Reset(publisher.WaitCloseTimeout)
waitCloseTimeout := publisher.WaitCloseTimeout
if waitCloseTimeout == 0 {
waitCloseTimeout = subscriber.WaitTimeout
}
subscriber.TimeoutTimer.Reset(waitCloseTimeout)
}
if publisher.Closer != nil {
_ = publisher.Close()
@@ -407,26 +409,31 @@ func (s *Server) OnPublish(publisher *Publisher) error {
s.pidG++
p := publisher.Plugin
publisher.ID = s.pidG
publisher.Logger = p.With("streamPath", publisher.StreamPath, "puber", publisher.ID)
publisher.Logger = p.With("streamPath", publisher.StreamPath, "pubID", publisher.ID)
publisher.TimeoutTimer = time.NewTimer(p.config.PublishTimeout)
publisher.Info("publish")
if waiting, ok := s.Waiting.Get(publisher.StreamPath); ok {
if waiting.Plugin != nil {
publisher.TakeOver(waiting)
} else {
for subscriber := range waiting.SubscriberRange {
publisher.AddSubscriber(subscriber)
}
}
publisher.TakeOver(waiting)
s.Waiting.Remove(waiting)
}
return nil
}
func (s *Server) createWait(streamPath string) *Publisher {
newPublisher := &Publisher{}
s.pidG++
newPublisher.ID = s.pidG
newPublisher.Logger = s.Logger.With("pubID", newPublisher.ID, "streamPath", streamPath)
s.Info("createWait")
newPublisher.StreamPath = streamPath
s.Waiting.Set(newPublisher)
return newPublisher
}
func (s *Server) OnSubscribe(subscriber *Subscriber) error {
s.sidG++
subscriber.ID = s.sidG
subscriber.Logger = subscriber.Plugin.With("streamPath", subscriber.StreamPath, "suber", subscriber.ID)
subscriber.Logger = subscriber.Plugin.With("streamPath", subscriber.StreamPath, "subID", subscriber.ID)
subscriber.TimeoutTimer = time.NewTimer(subscriber.Plugin.config.Subscribe.WaitTimeout)
s.Subscribers.Add(subscriber)
subscriber.Info("subscribe")
@@ -435,9 +442,7 @@ func (s *Server) OnSubscribe(subscriber *Subscriber) error {
} else if publisher, ok = s.Waiting.Get(subscriber.StreamPath); ok {
publisher.AddSubscriber(subscriber)
} else {
newPublisher := &Publisher{}
newPublisher.StreamPath = subscriber.StreamPath
newPublisher.AddSubscriber(subscriber)
s.createWait(subscriber.StreamPath).AddSubscriber(subscriber)
}
return nil
}
+19 -6
View File
@@ -8,6 +8,7 @@ import (
"net/url"
"os"
"reflect"
"runtime"
"strconv"
"time"
@@ -239,10 +240,14 @@ func PlayBlock[A any, V any](s *Subscriber, onAudio func(A) error, onVideo func(
}()
sendAudioFrame := func() (err error) {
if awi >= 0 {
if s.Enabled(s, TraceLevel) {
s.Trace("send audio frame", "seq", audioFrame.Sequence)
if len(audioFrame.Wraps) > awi {
if s.Enabled(s, TraceLevel) {
s.Trace("send audio frame", "seq", audioFrame.Sequence)
}
err = onAudio(audioFrame.Wraps[awi].(A))
} else {
ar.StopRead()
}
err = onAudio(audioFrame.Wraps[awi].(A))
} else {
err = onAudio(any(audioFrame).(A))
}
@@ -254,10 +259,14 @@ func PlayBlock[A any, V any](s *Subscriber, onAudio func(A) error, onVideo func(
}
sendVideoFrame := func() (err error) {
if vwi >= 0 {
if s.Enabled(s, TraceLevel) {
s.Trace("send video frame", "seq", videoFrame.Sequence, "data", videoFrame.Wraps[vwi].String(), "size", videoFrame.Wraps[vwi].GetSize())
if len(videoFrame.Wraps) > vwi {
if s.Enabled(s, TraceLevel) {
s.Trace("send video frame", "seq", videoFrame.Sequence, "data", videoFrame.Wraps[vwi].String(), "size", videoFrame.Wraps[vwi].GetSize())
}
err = onVideo(videoFrame.Wraps[vwi].(V))
} else {
vr.StopRead()
}
err = onVideo(videoFrame.Wraps[vwi].(V))
} else {
err = onVideo(any(videoFrame).(V))
}
@@ -269,13 +278,16 @@ func PlayBlock[A any, V any](s *Subscriber, onAudio func(A) error, onVideo func(
}
checkPublisherChange := func() {
if prePublisher != s.Publisher {
s.Info("publisher changed", "prePublisher", prePublisher.ID, "publisher", s.Publisher.ID)
if ar != nil {
startAudioTs = time.Duration(ar.AbsTime) * time.Millisecond
ar.StopRead()
ar = nil
}
if vr != nil {
startVideoTs = time.Duration(vr.AbsTime) * time.Millisecond
vr.StopRead()
vr = nil
}
createAudioReader()
createVideoReader()
@@ -374,5 +386,6 @@ func PlayBlock[A any, V any](s *Subscriber, onAudio func(A) error, onVideo func(
createAudioReader()
}
checkPublisherChange()
runtime.Gosched()
}
}