适配引擎的升级

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

View File

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

30
flv.go
View File

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

24
hls.go
View File

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

31
mp4.go
View File

@@ -10,7 +10,6 @@ import (
. "m7s.live/engine/v4"
"m7s.live/engine/v4/codec"
"m7s.live/engine/v4/track"
"m7s.live/engine/v4/util"
)
type mediaContext struct {
@@ -91,11 +90,11 @@ func (r *MP4Recorder) OnEvent(event any) {
r.SetIO(file)
r.InitSegment = mp4.CreateEmptyInit()
r.Moov.Mvhd.NextTrackID = 1
if r.Video.Track != nil {
r.OnEvent(r.Video.Track)
if r.VideoReader.Track != nil {
r.OnEvent(r.VideoReader.Track)
}
if r.Audio.Track != nil {
r.OnEvent(r.Audio.Track)
if r.AudioReader.Track != nil {
r.OnEvent(r.AudioReader.Track)
}
r.ftyp.Encode(r)
r.Moov.Encode(r)
@@ -116,12 +115,12 @@ func (r *MP4Recorder) OnEvent(event any) {
r.ftyp = mp4.NewFtyp("isom", 0x200, []string{
"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:
r.ftyp = mp4.NewFtyp("isom", 0x200, []string{
"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)
case *track.Audio:
@@ -134,12 +133,12 @@ func (r *MP4Recorder) OnEvent(event any) {
r.audio.trackId = trackID
switch v.CodecID {
case codec.CodecID_AAC:
switch v.Profile {
case 0:
newTrak.SetAACDescriptor(aac.HEAACv1, int(v.SampleRate))
switch v.AudioObjectType {
case 1:
newTrak.SetAACDescriptor(aac.AAClc, int(v.SampleRate))
newTrak.SetAACDescriptor(aac.HEAACv1, int(v.SampleRate))
case 2:
newTrak.SetAACDescriptor(aac.AAClc, int(v.SampleRate))
case 3:
newTrak.SetAACDescriptor(aac.HEAACv2, int(v.SampleRate))
}
case codec.CodecID_PCMA:
@@ -162,18 +161,18 @@ func (r *MP4Recorder) OnEvent(event any) {
r.Moov.Encode(r)
go r.start()
}
case *AudioFrame:
case AudioFrame:
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 {
flag := mp4.NonSyncSampleFlags
if v.IFrame {
flag = mp4.SyncSampleFlags
}
if data := util.ConcatBuffers(v.AVCC); len(data) > 5 {
r.video.push(r, v.AbsTime-r.SkipTS, v.DeltaTime, data[5:], flag)
if data := v.AUList.ToBytes(); len(data) > 5 {
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/codec"
"m7s.live/engine/v4/common"
"m7s.live/engine/v4/track"
)
@@ -36,22 +37,19 @@ func (r *RawRecorder) OnEvent(event any) {
r.Ext = ".h265"
}
}
case VideoDeConf:
annexB := v.GetAnnexB()
annexB.WriteTo(r)
case *VideoFrame:
case common.ParamaterSets:
v.WriteAnnexBTo(r)
case VideoFrame:
if r.Fragment != 0 && r.newFile {
r.newFile = false
r.Close()
if file, err := r.CreateFileFn(filepath.Join(r.Stream.Path, strconv.FormatInt(time.Now().Unix(), 10)+r.Ext), false); err == nil {
r.SetIO(file)
if r.Video.Track != nil {
annexB := VideoDeConf(r.Video.Track.DecoderConfiguration).GetAnnexB()
annexB.WriteTo(r)
if r.Video != nil {
r.Video.ParamaterSets.WriteAnnexBTo(r)
}
}
}
annexB := v.GetAnnexB()
annexB.WriteTo(r)
v.WriteAnnexBTo(r)
}
}

View File

@@ -10,6 +10,7 @@ import (
type Recorder struct {
Subscriber
SkipTS uint32
*Record `json:"-"`
newFile bool // 创建了新的文件
append bool // 是否追加模式
@@ -23,7 +24,7 @@ func (r *Recorder) start() {
}
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.newFile = true
}
@@ -41,12 +42,12 @@ func (r *Recorder) OnEvent(event any) {
if file, err := r.CreateFileFn(filename, r.append); err == nil {
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)
}
case *VideoFrame:
case VideoFrame:
if r.Fragment > 0 && v.IFrame {
r.cut(v.AbsTime)
}