mirror of
https://github.com/langhuihui/monibuca.git
synced 2026-04-23 01:07:03 +08:00
feat(codec): Add unified AV1 raw format and protocol mux/demux support (#354)
* cherry-pick 95191a3: AV1 raw format support and protocol mux/demux integration * feat(rtp/av1): 完善 AV1 RTP 封装分片及关键帧检测 - Implements RTP packetization for AV1 with OBU fragmentation per RFC9304 - Adds accurate detection of AV1 keyframes using OBU inspection - Updates AV1 RTP demuxing to reconstruct fragmented OBUs - Ensures keyframe (IDR) flag is set correctly throughout mux/demux pipeline --------- Co-authored-by: engine-labs-app[bot] <140088366+engine-labs-app[bot]@users.noreply.github.com>
This commit is contained in:
+13
-14
@@ -51,7 +51,7 @@ type (
|
||||
|
||||
AudioData = gomem.Memory
|
||||
|
||||
OBUs AudioData
|
||||
OBUs = util.ReuseArray[gomem.Memory]
|
||||
|
||||
AVFrame struct {
|
||||
DataFrame
|
||||
@@ -148,6 +148,13 @@ func (b *BaseSample) GetNalus() *Nalus {
|
||||
return b.Raw.(*Nalus)
|
||||
}
|
||||
|
||||
func (b *BaseSample) GetOBUs() *OBUs {
|
||||
if b.Raw == nil {
|
||||
b.Raw = &OBUs{}
|
||||
}
|
||||
return b.Raw.(*OBUs)
|
||||
}
|
||||
|
||||
func (b *BaseSample) GetAudioData() *AudioData {
|
||||
if b.Raw == nil {
|
||||
b.Raw = &AudioData{}
|
||||
@@ -203,21 +210,21 @@ func (df *DataFrame) Ready() {
|
||||
df.Unlock()
|
||||
}
|
||||
|
||||
func (obus *OBUs) ParseAVCC(reader *gomem.MemoryReader) error {
|
||||
func (b *BaseSample) ParseAV1OBUs(reader *gomem.MemoryReader) error {
|
||||
var obuHeader av1.OBUHeader
|
||||
startLen := reader.Length
|
||||
for reader.Length > 0 {
|
||||
offset := reader.Size - reader.Length
|
||||
b, err := reader.ReadByte()
|
||||
b0, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = obuHeader.Unmarshal([]byte{b})
|
||||
err = obuHeader.Unmarshal([]byte{b0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// if log.Trace {
|
||||
// vt.Trace("obu", zap.Any("type", obuHeader.Type), zap.Bool("iframe", vt.Value.IFrame))
|
||||
// vt.Trace("obu", zap.Any("type", obuHeader.Type), zap.Bool("iframe", vt.Value.IFrame))
|
||||
// }
|
||||
obuSize, _, _ := reader.LEB128Unmarshal()
|
||||
end := reader.Size - reader.Length
|
||||
@@ -227,15 +234,7 @@ func (obus *OBUs) ParseAVCC(reader *gomem.MemoryReader) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
(*AudioData)(obus).PushOne(obu)
|
||||
b.GetNalus().GetNextPointer().PushOne(obu)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (obus *OBUs) Reset() {
|
||||
((*gomem.Memory)(obus)).Reset()
|
||||
}
|
||||
|
||||
func (obus *OBUs) Count() int {
|
||||
return (*gomem.Memory)(obus).Count()
|
||||
}
|
||||
|
||||
@@ -129,3 +129,44 @@ func (r *H26xFrame) GetSize() (ret int) {
|
||||
func (h *H26xFrame) String() string {
|
||||
return fmt.Sprintf("H26xFrame{FourCC: %s, Timestamp: %s, CTS: %s}", h.FourCC, h.Timestamp, h.CTS)
|
||||
}
|
||||
|
||||
var _ pkg.IAVFrame = (*AV1Frame)(nil)
|
||||
|
||||
type AV1Frame struct {
|
||||
pkg.Sample
|
||||
}
|
||||
|
||||
func (a *AV1Frame) CheckCodecChange() (err error) {
|
||||
if a.ICodecCtx == nil {
|
||||
return pkg.ErrUnsupportCodec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AV1Frame) GetSize() (ret int) {
|
||||
if obus, ok := a.Raw.(*pkg.OBUs); ok {
|
||||
for obu := range obus.RangePoint {
|
||||
ret += obu.Size
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *AV1Frame) Demux() error {
|
||||
a.Raw = &a.Memory
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AV1Frame) Mux(from *pkg.Sample) (err error) {
|
||||
a.InitRecycleIndexes(0)
|
||||
obus := from.Raw.(*pkg.OBUs)
|
||||
for obu := range obus.RangePoint {
|
||||
a.Push(obu.Buffers...)
|
||||
}
|
||||
a.ICodecCtx = from.GetBase()
|
||||
return
|
||||
}
|
||||
|
||||
func (a *AV1Frame) String() string {
|
||||
return fmt.Sprintf("AV1Frame{FourCC: %s, Timestamp: %s, CTS: %s}", a.FourCC, a.Timestamp, a.CTS)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user