适配引擎的升级

This commit is contained in:
dexter
2023-02-02 12:07:49 +08:00
parent d75f7cc100
commit dd63ca86c8
7 changed files with 56 additions and 59 deletions

View File

@@ -8,6 +8,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"time"
"m7s.live/engine/v4" "m7s.live/engine/v4"
) )
@@ -29,7 +30,7 @@ type Record struct {
Path string //存储文件的目录 Path string //存储文件的目录
AutoRecord bool AutoRecord bool
Filter string Filter string
Fragment int //分片大小0表示不分片 Fragment time.Duration //分片大小0表示不分片
filterReg *regexp.Regexp filterReg *regexp.Regexp
fs http.Handler fs http.Handler
CreateFileFn func(filename string, append bool) (FileWr, error) `yaml:"-" json:"-"` CreateFileFn func(filename string, append bool) (FileWr, error) `yaml:"-" json:"-"`

View File

@@ -1,2 +1,2 @@
subscribe: subscribe:
livemode: false submode: 1

30
flv.go
View File

@@ -2,7 +2,6 @@ package record
import ( import (
"io" "io"
"net"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@@ -11,6 +10,7 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
. "m7s.live/engine/v4" . "m7s.live/engine/v4"
"m7s.live/engine/v4/codec" "m7s.live/engine/v4/codec"
"m7s.live/engine/v4/util"
) )
type FLVRecorder struct { type FLVRecorder struct {
@@ -43,10 +43,10 @@ func (r *FLVRecorder) start() {
func (r *FLVRecorder) writeMetaData(file *os.File, duration int64) { func (r *FLVRecorder) writeMetaData(file *os.File, duration int64) {
defer file.Close() defer file.Close()
at, vt := r.Audio.Track, r.Video.Track at, vt := r.Audio, r.Video
hasAudio, hasVideo := at != nil, vt != nil hasAudio, hasVideo := at != nil, vt != nil
var amf codec.AMF var amf util.AMF
metaData := codec.EcmaArray{ metaData := util.EcmaArray{
"MetaDataCreator": "m7s " + Engine.Version, "MetaDataCreator": "m7s " + Engine.Version,
"hasVideo": hasVideo, "hasVideo": hasVideo,
"hasAudio": hasAudio, "hasAudio": hasAudio,
@@ -99,7 +99,7 @@ func (r *FLVRecorder) writeMetaData(file *os.File, duration int64) {
} else { } else {
tempFile.Write([]byte{'F', 'L', 'V', 0x01, flags, 0, 0, 0, 9, 0, 0, 0, 0}) tempFile.Write([]byte{'F', 'L', 'V', 0x01, flags, 0, 0, 0, 9, 0, 0, 0, 0})
amf.Reset() amf.Reset()
codec.WriteFLVTag(tempFile, codec.FLV_TAG_TYPE_SCRIPT, 0, net.Buffers{amf.Marshals("onMetaData", metaData)}) codec.WriteFLVTag(tempFile, codec.FLV_TAG_TYPE_SCRIPT, 0, amf.Marshals("onMetaData", metaData))
file.Seek(int64(len(codec.FLVHeader)), io.SeekStart) file.Seek(int64(len(codec.FLVHeader)), io.SeekStart)
io.Copy(tempFile, file) io.Copy(tempFile, file)
tempFile.Seek(0, io.SeekStart) tempFile.Seek(0, io.SeekStart)
@@ -130,18 +130,18 @@ func (r *FLVRecorder) OnEvent(event any) {
case FLVFrame: case FLVFrame:
check := false check := false
var absTime uint32 var absTime uint32
if r.Video.Track == nil { if r.VideoReader.Track == nil {
check = true check = true
absTime = r.Audio.Frame.AbsTime absTime = r.AudioReader.Frame.AbsTime
} else { } else {
check = r.Video.Frame.IFrame check = r.VideoReader.Frame.IFrame
absTime = r.Video.Frame.AbsTime absTime = r.VideoReader.Frame.AbsTime
if check { if check {
r.filepositions = append(r.filepositions, uint64(r.Offset)) r.filepositions = append(r.filepositions, uint64(r.Offset))
r.times = append(r.times, float64(absTime)/1000) r.times = append(r.times, float64(absTime)/1000)
} }
} }
if r.Fragment > 0 && check && r.duration >= int64(r.Fragment*1000) { if r.Fragment > 0 && check && time.Duration(r.duration)*time.Millisecond >= r.Fragment {
r.SkipTS = absTime r.SkipTS = absTime
if file, ok := r.Writer.(*os.File); ok { if file, ok := r.Writer.(*os.File); ok {
go r.writeMetaData(file, r.duration) go r.writeMetaData(file, r.duration)
@@ -152,15 +152,15 @@ func (r *FLVRecorder) OnEvent(event any) {
if file, err := r.CreateFileFn(filepath.Join(r.Stream.Path, strconv.FormatInt(time.Now().Unix(), 10)+r.Ext), false); err == nil { if file, err := r.CreateFileFn(filepath.Join(r.Stream.Path, strconv.FormatInt(time.Now().Unix(), 10)+r.Ext), false); err == nil {
r.SetIO(file) r.SetIO(file)
r.Write(codec.FLVHeader) r.Write(codec.FLVHeader)
if r.Video.Track != nil { if r.VideoReader.Track != nil {
dcflv := codec.VideoAVCC2FLV(r.Video.Track.DecoderConfiguration.AVCC, 0) dcflv := codec.VideoAVCC2FLV(0, r.VideoReader.Track.SequenceHead)
dcflv.WriteTo(r) dcflv.WriteTo(r)
} }
if r.Audio.Track != nil && r.Audio.Track.CodecID == codec.CodecID_AAC { if r.AudioReader.Track != nil && r.Audio.CodecID == codec.CodecID_AAC {
dcflv := codec.AudioAVCC2FLV(r.Audio.Track.Value.AVCC, 0) dcflv := codec.AudioAVCC2FLV(0, r.AudioReader.Track.Value.AVCC.ToBuffers()...)
dcflv.WriteTo(r) dcflv.WriteTo(r)
} }
flv := codec.VideoAVCC2FLV(r.Video.Frame.AVCC, 0) flv := codec.VideoAVCC2FLV(0, r.VideoReader.Track.Value.AVCC.ToBuffers()...)
flv.WriteTo(r) flv.WriteTo(r)
return return
} }

24
hls.go
View File

@@ -2,6 +2,7 @@ package record
import ( import (
"io" "io"
"math"
"path/filepath" "path/filepath"
"strconv" "strconv"
"time" "time"
@@ -15,7 +16,6 @@ import (
type HLSRecorder struct { type HLSRecorder struct {
playlist hls.Playlist playlist hls.Playlist
asc *codec.AudioSpecificConfig
video_cc, audio_cc byte video_cc, audio_cc byte
packet mpegts.MpegTsPESPacket packet mpegts.MpegTsPESPacket
Recorder Recorder
@@ -46,7 +46,7 @@ func (h *HLSRecorder) OnEvent(event any) {
Writer: h.Writer, Writer: h.Writer,
Version: 3, Version: 3,
Sequence: 0, Sequence: 0,
Targetduration: h.Fragment * 1000, Targetduration: int(math.Ceil(h.Fragment.Seconds())),
} }
if err = h.playlist.Init(); err != nil { if err = h.playlist.Init(); err != nil {
return return
@@ -55,10 +55,8 @@ func (h *HLSRecorder) OnEvent(event any) {
return return
} }
go h.start() go h.start()
case AudioDeConf: case AudioFrame:
h.asc, err = hls.DecodeAudioSpecificConfig(v.AVCC[0]) if h.packet, err = hls.AudioPacketToPES(&v, &h.Audio.AudioSpecificConfig); err != nil {
case *AudioFrame:
if h.packet, err = hls.AudioPacketToPES(v, h.asc); err != nil {
return return
} }
pes := &mpegts.MpegtsPESFrame{ pes := &mpegts.MpegtsPESFrame{
@@ -72,8 +70,8 @@ func (h *HLSRecorder) OnEvent(event any) {
return return
} }
h.audio_cc = pes.ContinuityCounter h.audio_cc = pes.ContinuityCounter
case *VideoFrame: case VideoFrame:
h.packet, err = hls.VideoPacketToPES(v, h.Video.Track.DecoderConfiguration, h.SkipTS) h.packet, err = hls.VideoPacketToPES(&v, h.Video)
if err != nil { if err != nil {
return return
} }
@@ -107,7 +105,7 @@ func (h *HLSRecorder) createHlsTsSegmentFile() (err error) {
} }
h.tsWriter = fw h.tsWriter = fw
inf := hls.PlaylistInf{ inf := hls.PlaylistInf{
Duration: float64(h.Fragment), Duration: h.Fragment.Seconds(),
Title: tsFilename, Title: tsFilename,
} }
if err = h.playlist.WriteInf(inf); err != nil { if err = h.playlist.WriteInf(inf); err != nil {
@@ -118,11 +116,11 @@ func (h *HLSRecorder) createHlsTsSegmentFile() (err error) {
} }
var vcodec codec.VideoCodecID = 0 var vcodec codec.VideoCodecID = 0
var acodec codec.AudioCodecID = 0 var acodec codec.AudioCodecID = 0
if h.Video.Track != nil { if h.Video != nil {
vcodec = h.Video.Track.CodecID vcodec = h.Video.CodecID
} }
if h.Audio.Track != nil { if h.Audio != nil {
acodec = h.Audio.Track.CodecID acodec = h.Audio.CodecID
} }
mpegts.WritePMTPacket(fw, vcodec, acodec) mpegts.WritePMTPacket(fw, vcodec, acodec)
return err return err

31
mp4.go
View File

@@ -10,7 +10,6 @@ import (
. "m7s.live/engine/v4" . "m7s.live/engine/v4"
"m7s.live/engine/v4/codec" "m7s.live/engine/v4/codec"
"m7s.live/engine/v4/track" "m7s.live/engine/v4/track"
"m7s.live/engine/v4/util"
) )
type mediaContext struct { type mediaContext struct {
@@ -91,11 +90,11 @@ func (r *MP4Recorder) OnEvent(event any) {
r.SetIO(file) r.SetIO(file)
r.InitSegment = mp4.CreateEmptyInit() r.InitSegment = mp4.CreateEmptyInit()
r.Moov.Mvhd.NextTrackID = 1 r.Moov.Mvhd.NextTrackID = 1
if r.Video.Track != nil { if r.VideoReader.Track != nil {
r.OnEvent(r.Video.Track) r.OnEvent(r.VideoReader.Track)
} }
if r.Audio.Track != nil { if r.AudioReader.Track != nil {
r.OnEvent(r.Audio.Track) r.OnEvent(r.AudioReader.Track)
} }
r.ftyp.Encode(r) r.ftyp.Encode(r)
r.Moov.Encode(r) r.Moov.Encode(r)
@@ -116,12 +115,12 @@ func (r *MP4Recorder) OnEvent(event any) {
r.ftyp = mp4.NewFtyp("isom", 0x200, []string{ r.ftyp = mp4.NewFtyp("isom", 0x200, []string{
"isom", "iso2", "avc1", "mp41", "isom", "iso2", "avc1", "mp41",
}) })
newTrak.SetAVCDescriptor("avc1", v.DecoderConfiguration.Raw[0:1], v.DecoderConfiguration.Raw[1:2], true) newTrak.SetAVCDescriptor("avc1", v.ParamaterSets[0:1], v.ParamaterSets[1:2], true)
case codec.CodecID_H265: case codec.CodecID_H265:
r.ftyp = mp4.NewFtyp("isom", 0x200, []string{ r.ftyp = mp4.NewFtyp("isom", 0x200, []string{
"isom", "iso2", "hvc1", "mp41", "isom", "iso2", "hvc1", "mp41",
}) })
newTrak.SetHEVCDescriptor("hvc1", v.DecoderConfiguration.Raw[0:1], v.DecoderConfiguration.Raw[1:2], v.DecoderConfiguration.Raw[2:3], true) newTrak.SetHEVCDescriptor("hvc1", v.ParamaterSets[0:1], v.ParamaterSets[1:2], v.ParamaterSets[2:3], true)
} }
r.AddTrack(v) r.AddTrack(v)
case *track.Audio: case *track.Audio:
@@ -134,12 +133,12 @@ func (r *MP4Recorder) OnEvent(event any) {
r.audio.trackId = trackID r.audio.trackId = trackID
switch v.CodecID { switch v.CodecID {
case codec.CodecID_AAC: case codec.CodecID_AAC:
switch v.Profile { switch v.AudioObjectType {
case 0:
newTrak.SetAACDescriptor(aac.HEAACv1, int(v.SampleRate))
case 1: case 1:
newTrak.SetAACDescriptor(aac.AAClc, int(v.SampleRate)) newTrak.SetAACDescriptor(aac.HEAACv1, int(v.SampleRate))
case 2: case 2:
newTrak.SetAACDescriptor(aac.AAClc, int(v.SampleRate))
case 3:
newTrak.SetAACDescriptor(aac.HEAACv2, int(v.SampleRate)) newTrak.SetAACDescriptor(aac.HEAACv2, int(v.SampleRate))
} }
case codec.CodecID_PCMA: case codec.CodecID_PCMA:
@@ -162,18 +161,18 @@ func (r *MP4Recorder) OnEvent(event any) {
r.Moov.Encode(r) r.Moov.Encode(r)
go r.start() go r.start()
} }
case *AudioFrame: case AudioFrame:
if r.audio.trackId != 0 { if r.audio.trackId != 0 {
r.audio.push(r, v.AbsTime-r.SkipTS, v.DeltaTime, util.ConcatBuffers(v.Raw), mp4.SyncSampleFlags) r.audio.push(r, v.AbsTime, v.DeltaTime, v.AUList.ToBytes(), mp4.SyncSampleFlags)
} }
case *VideoFrame: case VideoFrame:
if r.video.trackId != 0 { if r.video.trackId != 0 {
flag := mp4.NonSyncSampleFlags flag := mp4.NonSyncSampleFlags
if v.IFrame { if v.IFrame {
flag = mp4.SyncSampleFlags flag = mp4.SyncSampleFlags
} }
if data := util.ConcatBuffers(v.AVCC); len(data) > 5 { if data := v.AUList.ToBytes(); len(data) > 5 {
r.video.push(r, v.AbsTime-r.SkipTS, v.DeltaTime, data[5:], flag) r.video.push(r, v.AbsTime, v.DeltaTime, data[5:], flag)
} }
} }
} }

16
raw.go
View File

@@ -7,6 +7,7 @@ import (
. "m7s.live/engine/v4" . "m7s.live/engine/v4"
"m7s.live/engine/v4/codec" "m7s.live/engine/v4/codec"
"m7s.live/engine/v4/common"
"m7s.live/engine/v4/track" "m7s.live/engine/v4/track"
) )
@@ -36,22 +37,19 @@ func (r *RawRecorder) OnEvent(event any) {
r.Ext = ".h265" r.Ext = ".h265"
} }
} }
case VideoDeConf: case common.ParamaterSets:
annexB := v.GetAnnexB() v.WriteAnnexBTo(r)
annexB.WriteTo(r) case VideoFrame:
case *VideoFrame:
if r.Fragment != 0 && r.newFile { if r.Fragment != 0 && r.newFile {
r.newFile = false r.newFile = false
r.Close() r.Close()
if file, err := r.CreateFileFn(filepath.Join(r.Stream.Path, strconv.FormatInt(time.Now().Unix(), 10)+r.Ext), false); err == nil { if file, err := r.CreateFileFn(filepath.Join(r.Stream.Path, strconv.FormatInt(time.Now().Unix(), 10)+r.Ext), false); err == nil {
r.SetIO(file) r.SetIO(file)
if r.Video.Track != nil { if r.Video != nil {
annexB := VideoDeConf(r.Video.Track.DecoderConfiguration).GetAnnexB() r.Video.ParamaterSets.WriteAnnexBTo(r)
annexB.WriteTo(r)
} }
} }
} }
annexB := v.GetAnnexB() v.WriteAnnexBTo(r)
annexB.WriteTo(r)
} }
} }

View File

@@ -10,6 +10,7 @@ import (
type Recorder struct { type Recorder struct {
Subscriber Subscriber
SkipTS uint32
*Record `json:"-"` *Record `json:"-"`
newFile bool // 创建了新的文件 newFile bool // 创建了新的文件
append bool // 是否追加模式 append bool // 是否追加模式
@@ -23,7 +24,7 @@ func (r *Recorder) start() {
} }
func (r *Recorder) cut(absTime uint32) { func (r *Recorder) cut(absTime uint32) {
if ts := absTime - r.SkipTS; int64(ts) >= int64(r.Fragment*1000) { if ts := absTime - r.SkipTS; time.Duration(ts)*time.Millisecond >= r.Fragment {
r.SkipTS = absTime r.SkipTS = absTime
r.newFile = true r.newFile = true
} }
@@ -41,12 +42,12 @@ func (r *Recorder) OnEvent(event any) {
if file, err := r.CreateFileFn(filename, r.append); err == nil { if file, err := r.CreateFileFn(filename, r.append); err == nil {
r.SetIO(file) r.SetIO(file)
} }
case *AudioFrame: case AudioFrame:
// 纯音频流的情况下需要切割文件 // 纯音频流的情况下需要切割文件
if r.Fragment > 0 && r.Video.Track == nil { if r.Fragment > 0 && r.VideoReader.Track == nil {
r.cut(v.AbsTime) r.cut(v.AbsTime)
} }
case *VideoFrame: case VideoFrame:
if r.Fragment > 0 && v.IFrame { if r.Fragment > 0 && v.IFrame {
r.cut(v.AbsTime) r.cut(v.AbsTime)
} }