mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-12 20:11:14 +08:00
150 lines
3.6 KiB
Go
150 lines
3.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"go.uber.org/zap"
|
|
"m7s.live/engine/v4/codec"
|
|
"m7s.live/engine/v4/common"
|
|
"m7s.live/engine/v4/config"
|
|
"m7s.live/engine/v4/track"
|
|
"m7s.live/engine/v4/util"
|
|
)
|
|
|
|
type IPublisher interface {
|
|
common.IPuber
|
|
GetPublisher() *Publisher
|
|
}
|
|
|
|
var _ IPublisher = (*Publisher)(nil)
|
|
|
|
type Publisher struct {
|
|
IO
|
|
Config *config.Publish
|
|
common.AudioTrack `json:"-" yaml:"-"`
|
|
common.VideoTrack `json:"-" yaml:"-"`
|
|
}
|
|
|
|
func (p *Publisher) Publish(streamPath string, pub common.IPuber) error {
|
|
return p.receive(streamPath, pub)
|
|
}
|
|
|
|
func (p *Publisher) GetPublisher() *Publisher {
|
|
return p
|
|
}
|
|
|
|
// func (p *Publisher) Stop(reason ...zapcore.Field) {
|
|
// p.IO.Stop(reason...)
|
|
// p.Stream.Receive(ACTION_PUBLISHCLOSE)
|
|
// }
|
|
|
|
func (p *Publisher) GetAudioTrack() common.AudioTrack {
|
|
return p.AudioTrack
|
|
}
|
|
|
|
func (p *Publisher) GetVideoTrack() common.VideoTrack {
|
|
return p.VideoTrack
|
|
}
|
|
|
|
func (p *Publisher) GetConfig() *config.Publish {
|
|
return p.Config
|
|
}
|
|
|
|
// func (p *Publisher) OnEvent(event any) {
|
|
// p.IO.OnEvent(event)
|
|
// switch event.(type) {
|
|
// case SEclose, SEKick:
|
|
// p.AudioTrack = nil
|
|
// p.VideoTrack = nil
|
|
// }
|
|
// }
|
|
|
|
func (p *Publisher) CreateAudioTrack(codecID codec.AudioCodecID, stuff ...any) common.AudioTrack {
|
|
switch codecID {
|
|
case codec.CodecID_AAC:
|
|
p.AudioTrack = track.NewAAC(p, stuff...)
|
|
case codec.CodecID_PCMA:
|
|
p.AudioTrack = track.NewG711(p, true, stuff...)
|
|
case codec.CodecID_PCMU:
|
|
p.AudioTrack = track.NewG711(p, false, stuff...)
|
|
case codec.CodecID_OPUS:
|
|
p.AudioTrack = track.NewOpus(p, stuff...)
|
|
}
|
|
return p.AudioTrack
|
|
}
|
|
|
|
func (p *Publisher) CreateVideoTrack(codecID codec.VideoCodecID, stuff ...any) common.VideoTrack {
|
|
switch codecID {
|
|
case codec.CodecID_H264:
|
|
p.VideoTrack = track.NewH264(p, stuff...)
|
|
case codec.CodecID_H265:
|
|
p.VideoTrack = track.NewH265(p, stuff...)
|
|
case codec.CodecID_AV1:
|
|
p.VideoTrack = track.NewAV1(p, stuff...)
|
|
}
|
|
return p.VideoTrack
|
|
}
|
|
|
|
func (p *Publisher) WriteAVCCVideo(ts uint32, frame *util.BLL, pool util.BytesPool) {
|
|
if frame.ByteLength < 6 {
|
|
return
|
|
}
|
|
if p.VideoTrack == nil {
|
|
b0 := frame.GetByte(0)
|
|
// https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
|
|
if isExtHeader := b0 & 0b1000_0000; isExtHeader != 0 {
|
|
fourCC := frame.GetUintN(1, 4)
|
|
switch fourCC {
|
|
case codec.FourCC_H265_32:
|
|
p.VideoTrack = track.NewH265(p, pool)
|
|
p.VideoTrack.WriteAVCC(ts, frame)
|
|
case codec.FourCC_AV1_32:
|
|
p.VideoTrack = track.NewAV1(p, pool)
|
|
p.VideoTrack.WriteAVCC(ts, frame)
|
|
}
|
|
} else {
|
|
if frame.GetByte(1) == 0 {
|
|
ts = 0
|
|
p.CreateVideoTrack(codec.VideoCodecID(b0&0x0F), pool)
|
|
if p.VideoTrack == nil {
|
|
p.Stream.Error("video codecID not support", zap.Uint8("codeId", uint8(codec.VideoCodecID(b0&0x0F))))
|
|
return
|
|
}
|
|
p.VideoTrack.WriteAVCC(ts, frame)
|
|
} else {
|
|
p.Stream.Warn("need sequence frame")
|
|
}
|
|
}
|
|
} else {
|
|
p.VideoTrack.WriteAVCC(ts, frame)
|
|
}
|
|
}
|
|
|
|
func (p *Publisher) WriteAVCCAudio(ts uint32, frame *util.BLL, pool util.BytesPool) {
|
|
if frame.ByteLength < 4 {
|
|
return
|
|
}
|
|
if p.AudioTrack == nil {
|
|
b0 := frame.GetByte(0)
|
|
t := p.CreateAudioTrack(codec.AudioCodecID(b0>>4), pool)
|
|
switch a := t.(type) {
|
|
case *track.AAC:
|
|
if frame.GetByte(1) != 0 {
|
|
return
|
|
}
|
|
a.AVCCHead = []byte{frame.GetByte(0), 1}
|
|
a.WriteAVCC(0, frame)
|
|
case *track.G711:
|
|
a.Audio.SampleRate = uint32(codec.SoundRate[(b0&0x0c)>>2])
|
|
if b0&0x02 == 0 {
|
|
a.Audio.SampleSize = 8
|
|
}
|
|
a.Channels = b0&0x01 + 1
|
|
a.AVCCHead = []byte{b0}
|
|
a.WriteAVCC(ts, frame)
|
|
default:
|
|
p.Stream.Error("audio codec not support yet", zap.Uint8("codecId", uint8(codec.AudioCodecID(b0>>4))))
|
|
}
|
|
} else {
|
|
p.AudioTrack.WriteAVCC(ts, frame)
|
|
}
|
|
}
|