mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-09-27 14:22:08 +08:00
166 lines
3.6 KiB
Go
166 lines
3.6 KiB
Go
package pkg
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/bluenviron/mediacommon/pkg/codecs/av1"
|
|
"m7s.live/v5/pkg/codec"
|
|
"m7s.live/v5/pkg/util"
|
|
)
|
|
|
|
type (
|
|
IAudioCodecCtx interface {
|
|
codec.ICodecCtx
|
|
GetSampleRate() int
|
|
GetChannels() int
|
|
GetSampleSize() int
|
|
}
|
|
IVideoCodecCtx interface {
|
|
codec.ICodecCtx
|
|
Width() int
|
|
Height() int
|
|
}
|
|
IDataFrame interface {
|
|
}
|
|
// Source -> Parse -> Demux -> (ConvertCtx) -> Mux(GetAllocator) -> Recycle
|
|
IAVFrame interface {
|
|
GetAllocator() *util.ScalableMemoryAllocator
|
|
SetAllocator(*util.ScalableMemoryAllocator)
|
|
Parse(*AVTrack) error // get codec info, idr
|
|
ConvertCtx(codec.ICodecCtx) (codec.ICodecCtx, IAVFrame, error) // convert codec from source stream
|
|
Demux(codec.ICodecCtx) (any, error) // demux to raw format
|
|
Mux(codec.ICodecCtx, *AVFrame) // mux from raw format
|
|
GetTimestamp() time.Duration
|
|
GetCTS() time.Duration
|
|
GetSize() int
|
|
Recycle()
|
|
String() string
|
|
Dump(byte, io.Writer)
|
|
}
|
|
|
|
Nalus []util.Memory
|
|
|
|
AudioData = util.Memory
|
|
|
|
OBUs AudioData
|
|
|
|
AVFrame struct {
|
|
DataFrame
|
|
IDR bool
|
|
Timestamp time.Duration // 绝对时间戳
|
|
CTS time.Duration // composition time stamp
|
|
Wraps []IAVFrame // 封装格式
|
|
}
|
|
|
|
AVRing = util.Ring[AVFrame]
|
|
DataFrame struct {
|
|
sync.RWMutex
|
|
discard bool
|
|
Sequence uint32 // 在一个Track中的序号
|
|
WriteTime time.Time // 写入时间,可用于比较两个帧的先后
|
|
Raw any // 裸格式
|
|
}
|
|
)
|
|
|
|
var _ IAVFrame = (*AnnexB)(nil)
|
|
|
|
func (frame *AVFrame) Clone() {
|
|
|
|
}
|
|
|
|
func (frame *AVFrame) Reset() {
|
|
frame.Timestamp = 0
|
|
frame.IDR = false
|
|
frame.CTS = 0
|
|
frame.Raw = nil
|
|
if len(frame.Wraps) > 0 {
|
|
for _, wrap := range frame.Wraps {
|
|
wrap.Recycle()
|
|
}
|
|
frame.Wraps = frame.Wraps[:0]
|
|
}
|
|
}
|
|
|
|
func (frame *AVFrame) Discard() {
|
|
frame.discard = true
|
|
frame.Reset()
|
|
}
|
|
|
|
func (frame *AVFrame) Demux(codecCtx codec.ICodecCtx) (err error) {
|
|
frame.Raw, err = frame.Wraps[0].Demux(codecCtx)
|
|
return
|
|
}
|
|
|
|
func (df *DataFrame) StartWrite() (success bool) {
|
|
if df.discard {
|
|
return
|
|
}
|
|
if df.TryLock() {
|
|
return true
|
|
}
|
|
df.discard = true
|
|
return
|
|
}
|
|
|
|
func (df *DataFrame) Ready() {
|
|
df.WriteTime = time.Now()
|
|
df.Unlock()
|
|
}
|
|
|
|
func (nalus *Nalus) H264Type() codec.H264NALUType {
|
|
return codec.ParseH264NALUType((*nalus)[0].Buffers[0][0])
|
|
}
|
|
|
|
func (nalus *Nalus) H265Type() codec.H265NALUType {
|
|
return codec.ParseH265NALUType((*nalus)[0].Buffers[0][0])
|
|
}
|
|
|
|
func (nalus *Nalus) Append(bytes []byte) {
|
|
*nalus = append(*nalus, util.Memory{Buffers: net.Buffers{bytes}, Size: len(bytes)})
|
|
}
|
|
|
|
func (nalus *Nalus) ParseAVCC(reader *util.MemoryReader, naluSizeLen int) error {
|
|
for reader.Length > 0 {
|
|
l, err := reader.ReadBE(naluSizeLen)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var mem util.Memory
|
|
reader.RangeN(int(l), mem.AppendOne)
|
|
*nalus = append(*nalus, mem)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (obus *OBUs) ParseAVCC(reader *util.MemoryReader) error {
|
|
var obuHeader av1.OBUHeader
|
|
startLen := reader.Length
|
|
for reader.Length > 0 {
|
|
offset := reader.Size - reader.Length
|
|
b, err := reader.ReadByte()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = obuHeader.Unmarshal([]byte{b})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// if log.Trace {
|
|
// vt.Trace("obu", zap.Any("type", obuHeader.Type), zap.Bool("iframe", vt.Value.IFrame))
|
|
// }
|
|
obuSize, _, _ := reader.LEB128Unmarshal()
|
|
end := reader.Size - reader.Length
|
|
size := end - offset + int(obuSize)
|
|
reader = &util.MemoryReader{Memory: reader.Memory, Length: startLen - offset}
|
|
obu, err := reader.ReadBytes(size)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
(*AudioData)(obus).AppendOne(obu)
|
|
}
|
|
return nil
|
|
}
|