mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
111 lines
2.7 KiB
Go
111 lines
2.7 KiB
Go
package sei
|
|
|
|
import (
|
|
"github.com/deepch/vdk/codec/h265parser"
|
|
"github.com/langhuihui/gomem"
|
|
"m7s.live/v5"
|
|
"m7s.live/v5/pkg"
|
|
"m7s.live/v5/pkg/codec"
|
|
"m7s.live/v5/pkg/format"
|
|
"m7s.live/v5/pkg/util"
|
|
)
|
|
|
|
type Transformer struct {
|
|
m7s.DefaultTransformer
|
|
data chan util.Buffer
|
|
}
|
|
|
|
func (t *Transformer) AddSEI(tp byte, data []byte) {
|
|
l := len(data)
|
|
var buffer util.Buffer
|
|
buffer.WriteByte(tp)
|
|
for l >= 255 {
|
|
buffer.WriteByte(255)
|
|
l -= 255
|
|
}
|
|
buffer.WriteByte(byte(l))
|
|
buffer.Write(data)
|
|
buffer.WriteByte(0x80)
|
|
if len(t.data) == cap(t.data) {
|
|
<-t.data
|
|
}
|
|
t.data <- buffer
|
|
}
|
|
|
|
func NewTransform() m7s.ITransformer {
|
|
ret := &Transformer{
|
|
data: make(chan util.Buffer, 10),
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (t *Transformer) Start() (err error) {
|
|
return t.TransformJob.Subscribe()
|
|
}
|
|
|
|
func (t *Transformer) Run() (err error) {
|
|
err = t.TransformJob.Publish(t.TransformJob.Config.Output[0].StreamPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
pub := t.TransformJob.Publisher
|
|
allocator := gomem.NewScalableMemoryAllocator(1 << gomem.MinPowerOf2)
|
|
defer allocator.Recycle()
|
|
writer := m7s.NewPublisherWriter[*format.RawAudio, *format.H26xFrame](pub, allocator)
|
|
return m7s.PlayBlock(t.TransformJob.Subscriber, func(audio *format.RawAudio) (err error) {
|
|
writer.AudioFrame.ICodecCtx = audio.ICodecCtx
|
|
*writer.AudioFrame.BaseSample = *audio.BaseSample
|
|
audio.CopyTo(writer.AudioFrame.NextN(audio.Size))
|
|
err = writer.NextAudio()
|
|
return
|
|
}, func(video *format.H26xFrame) (err error) {
|
|
writer.VideoFrame.ICodecCtx = video.ICodecCtx
|
|
*writer.VideoFrame.BaseSample = *video.BaseSample
|
|
nalus := writer.VideoFrame.GetNalus()
|
|
var seis [][]byte
|
|
continueLoop := true
|
|
for continueLoop {
|
|
select {
|
|
case seiFrame := <-t.data:
|
|
seis = append(seis, seiFrame)
|
|
default:
|
|
continueLoop = false
|
|
}
|
|
}
|
|
seiCount := len(seis)
|
|
writer.VideoFrame.InitRecycleIndexes(video.Raw.Count())
|
|
for nalu := range video.Raw.(*pkg.Nalus).RangePoint {
|
|
p := nalus.GetNextPointer()
|
|
mem := writer.VideoFrame.NextN(nalu.Size)
|
|
nalu.CopyTo(mem)
|
|
if seiCount > 0 {
|
|
switch video.ICodecCtx.FourCC() {
|
|
case codec.FourCC_H264:
|
|
switch codec.ParseH264NALUType(mem[0]) {
|
|
case codec.NALU_IDR_Picture, codec.NALU_Non_IDR_Picture:
|
|
for _, sei := range seis {
|
|
p.Push(append([]byte{byte(codec.NALU_SEI)}, sei...))
|
|
}
|
|
}
|
|
case codec.FourCC_H265:
|
|
if naluType := codec.ParseH265NALUType(mem[0]); naluType < 21 {
|
|
for _, sei := range seis {
|
|
p.Push(append([]byte{byte(0b10000000 | byte(h265parser.NAL_UNIT_PREFIX_SEI<<1))}, sei...))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
p.PushOne(mem)
|
|
}
|
|
if seiCount > 0 {
|
|
t.Info("insert sei", "count", seiCount)
|
|
}
|
|
err = writer.NextVideo()
|
|
return
|
|
})
|
|
}
|
|
|
|
func (t *Transformer) Dispose() {
|
|
close(t.data)
|
|
}
|