diff --git a/codec/codec.go b/codec/codec.go index 3e18095..c928447 100644 --- a/codec/codec.go +++ b/codec/codec.go @@ -59,8 +59,8 @@ func (asc *AudioSpecificConfig) Parse(data []byte) { asc.ExtensionFlag = data[1] & 0x01 } -func (asc *AudioSpecificConfig) ToADTS(rawDataLength int) (adts ADTS, adtsByte []byte, err error) { - return AudioSpecificConfigToADTS(asc, rawDataLength) +func (asc *AudioSpecificConfig) ToADTS(rawDataLength int, adtsByte []byte) (adts ADTS, err error) { + return AudioSpecificConfigToADTS(asc, rawDataLength, adtsByte) } type GASpecificConfig struct { @@ -172,7 +172,7 @@ type ADTSVariableHeader struct { // 所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) -func AudioSpecificConfigToADTS(asc *AudioSpecificConfig, rawDataLength int) (adts ADTS, adtsByte []byte, err error) { +func AudioSpecificConfigToADTS(asc *AudioSpecificConfig, rawDataLength int, adtsByte []byte) (adts ADTS, err error) { if asc.ChannelConfiguration > 8 || asc.FrameLengthFlag > 13 { err = errors.New("Reserved field.") return @@ -185,9 +185,8 @@ func AudioSpecificConfigToADTS(asc *AudioSpecificConfig, rawDataLength int) (adt adts.ProtectionAbsent = 1 // SyncWord(12) + ID(1) + Layer(2) + ProtectionAbsent(1) - adtsByte = append(adtsByte, 0xff) - adtsByte = append(adtsByte, 0xf1) - + adtsByte[0] = 0xFF + adtsByte[1] = 0xF1 if asc.AudioObjectType >= 3 || asc.AudioObjectType == 0 { adts.Profile = 1 } else { @@ -201,9 +200,7 @@ func AudioSpecificConfigToADTS(asc *AudioSpecificConfig, rawDataLength int) (adt adts.Home = 0 // Profile(2) + SamplingFrequencyIndex(4) + PrivateBit(1) + ChannelConfiguration(3)(取高1位) - byte3 := uint8(adts.Profile<<6) + uint8(adts.SamplingFrequencyIndex<<2) + uint8(adts.PrivateBit<<1) + uint8((adts.ChannelConfiguration&0x7)>>2) - adtsByte = append(adtsByte, byte3) - + adtsByte[2] = uint8(adts.Profile<<6) + uint8(adts.SamplingFrequencyIndex<<2) + uint8(adts.PrivateBit<<1) + uint8((adts.ChannelConfiguration&0x7)>>2) // ADTSVariableHeader adts.CopyrightIdentificationBit = 0 adts.CopyrightIdentificationStart = 0 @@ -212,21 +209,17 @@ func AudioSpecificConfigToADTS(asc *AudioSpecificConfig, rawDataLength int) (adt adts.NumberOfRawDataBlockInFrame = 0 // ChannelConfiguration(3)(取低2位) + OriginalCopy(1) + Home(1) + CopyrightIdentificationBit(1) + CopyrightIdentificationStart(1) + AACFrameLength(13)(取高2位) - byte4 := uint8((adts.ChannelConfiguration&0x3)<<6) + uint8((adts.AACFrameLength&0x1fff)>>11) - adtsByte = append(adtsByte, byte4) + adtsByte[3] = uint8((adts.ChannelConfiguration&0x3)<<6) + uint8((adts.AACFrameLength&0x1fff)>>11) // AACFrameLength(13) // xx xxxxxxxx xxx // 取中间的部分 - byte5 := uint8(((adts.AACFrameLength & 0x1fff) >> 3) & 0x0ff) - adtsByte = append(adtsByte, byte5) + adtsByte[4] = uint8(((adts.AACFrameLength & 0x1fff) >> 3) & 0x0ff) // AACFrameLength(13)(取低3位) + ADTSBufferFullness(11)(取高5位) - byte6 := uint8((adts.AACFrameLength&0x0007)<<5) + 0x1f - adtsByte = append(adtsByte, byte6) + adtsByte[5] = uint8((adts.AACFrameLength&0x0007)<<5) + 0x1f // ADTSBufferFullness(11)(取低6位) + NumberOfRawDataBlockInFrame(2) - adtsByte = append(adtsByte, 0xfc) - + adtsByte[6] = 0xfc return } diff --git a/codec/mpegts/mpegts_pes.go b/codec/mpegts/mpegts_pes.go index c0e8b62..7df9f60 100644 --- a/codec/mpegts/mpegts_pes.go +++ b/codec/mpegts/mpegts_pes.go @@ -1,10 +1,9 @@ package mpegts import ( - "bytes" "errors" - "fmt" "io" + "net" "m7s.live/engine/v4/util" ) @@ -25,7 +24,8 @@ type MpegTsPesStream struct { // 110x xxxx 为音频流(0xC0) type MpegTsPESPacket struct { Header MpegTsPESHeader - Payload util.Buffer + Payload util.Buffer //从TS包中读取的数据 + Buffers net.Buffers //用于写TS包 } type MpegTsPESHeader struct { @@ -453,298 +453,3 @@ func WritePESHeader(w io.Writer, header MpegTsPESHeader) (written int, err error return } - -func WritePESPacket(w io.Writer, frame *MpegtsPESFrame, packet MpegTsPESPacket) (err error) { - var tsPkts []byte - if tsPkts, err = PESToTs(frame, packet); err != nil { - return - } - - // bw.Bytes == PES Packet - if _, err = w.Write(tsPkts); err != nil { - return - } - - return -} - -// func IowWritePESPacket(w io.Writer, tsHeader MpegTsHeader, packet MpegTsPESPacket) (err error) { -// if packet.Header.PacketStartCodePrefix != 0x000001 { -// return errors.New("packetStartCodePrefix != 0x000001") -// } - -// bw := &bytes.Buffer{} - -// // TODO:如果头长度大于65536,字段会为0,是否要改? -// _, err = WritePESHeader(bw, packet.Header) -// if err != nil { -// return -// } - -// PESPacket := &util.IOVec{} -// PESPacket.Append(bw.Bytes()) // header -// PESPacket.Append(packet.Payload) // packet - -// // 用IOVecWriter来写PES包,IOVecWriter实现了Write方法. -// // 因为通常在将一帧PES封装成TS包(188字节)的时候,一般情况下一帧PES字节数会大于188,并且分多次封装. -// // 例如这一帧PES字节数为189,那么在封装第二个TS包的时候就只会封装1字节,会导致多次写操作,降低性能. -// // 因此将所有的字节数,都写进缓冲中去,然后用系统调用syscall来写入. -// iow := util.NewIOVecWriter(w) - -// var isKeyFrame bool -// var headerLength int - -// isKeyFrame = CheckPESPacketIsKeyFrame(packet) - -// // 写一帧PES -// // 如果是I帧,会有pcr,所以会有调整字段AF. -// // 如果当前包字节不满188字节,会需要填充0xff,所以会有调整字段AF. -// for i := 0; PESPacket.Length > 0; i++ { - -// header := MpegTsHeader{ -// SyncByte: 0x47, -// Pid: tsHeader.Pid, -// AdaptionFieldControl: 1, -// ContinuityCounter: byte(i % 15), -// } - -// // 每一帧开头 -// if i == 0 { -// header.PayloadUnitStartIndicator = 1 -// } - -// // I帧 -// if isKeyFrame { -// header.AdaptionFieldControl = 0x03 -// header.AdaptationFieldLength = 7 -// header.PCRFlag = 1 -// header.RandomAccessIndicator = tsHeader.RandomAccessIndicator -// header.ProgramClockReferenceBase = tsHeader.ProgramClockReferenceBase -// header.ProgramClockReferenceExtension = tsHeader.ProgramClockReferenceExtension - -// isKeyFrame = false -// } - -// // 这个包大小,会在每一次PESPacket.WriteTo中慢慢减少. -// packetLength := PESPacket.Length - -// // 包不满188字节 -// if packetLength < TS_PACKET_SIZE-4 { - -// if header.AdaptionFieldControl >= 2 { -// header.AdaptationFieldLength = uint8(TS_PACKET_SIZE - 4 - 1 - packetLength - 7) -// } else { -// header.AdaptionFieldControl = 0x03 -// header.AdaptationFieldLength = uint8(TS_PACKET_SIZE - 4 - 1 - packetLength) -// } - -// headerLength, err = WriteTsHeader(iow, header) -// if err != nil { -// return -// } - -// stuffingLength := int(header.AdaptationFieldLength - 1) -// if _, err = iow.Write(util.GetFillBytes(0xff, stuffingLength)); err != nil { -// return -// } - -// headerLength += stuffingLength - -// } else { -// headerLength, err = WriteTsHeader(iow, header) -// if err != nil { -// return -// } -// } - -// /* -// if headerLength, err = writeTsHeader(iow, header, packetLength); err != nil { -// return -// } -// */ - -// payloadLength := 188 - headerLength - -// // 写PES负载 -// if _, err = PESPacket.WriteTo(iow, payloadLength); err != nil { -// return -// } -// } - -// iow.Flush() - -// return -// } - -// func CheckPESPacketIsKeyFrame(packet MpegTsPESPacket) bool { - -// nalus := bytes.SplitN(packet.Payload, codec.NALU_Delimiter1, -1) - -// for _, v := range nalus { -// if codec.H264NALUType.ParseBytes(codec.NALU_IDR_Picture, v) == codec.NALU_IDR_Picture { -// return true -// } -// } - -// return false -// } - -func TsToPES(tsPkts []MpegTsPacket) (pesPkt MpegTsPESPacket, err error) { - var index int - - for i := 0; i < len(tsPkts); i++ { - if tsPkts[i].Header.SyncByte != 0x47 { - err = errors.New("mpegts header sync error!") - return - } - - if tsPkts[i].Header.PayloadUnitStartIndicator == 1 { - index++ - - // 一个PES包里面只可能包含一个PayloadUnitStartIndicator=1的TS包. - if index >= 2 { - err = errors.New("TsToPES error PayloadUnitStartIndicator >= 2") - return - } - - r := bytes.NewReader(tsPkts[i].Payload) - lr := &io.LimitedReader{R: r, N: int64(len(tsPkts[i].Payload))} - - // TS Packet PES Header Start Index - hBegin := lr.N - - // PES Header - pesPkt.Header, err = ReadPESHeader(lr) - if err != nil { - return - } - - // TS Packet PES Header End Index - hEnd := lr.N - - pesHeaderLength := hBegin - hEnd - - if pesHeaderLength > 0 && pesHeaderLength <= hBegin { - pesPkt.Payload = append(pesPkt.Payload, tsPkts[i].Payload[pesHeaderLength:]...) - } - } - - if tsPkts[i].Header.PayloadUnitStartIndicator == 0 { - // MpegTsPacket Header 已经包含了自适应字段在里面,所以MpegTsPacket Payload直接就是PES Pyaload - pesPkt.Payload = append(pesPkt.Payload, tsPkts[i].Payload...) - } - - } - - return -} - -func PESToTs(frame *MpegtsPESFrame, packet MpegTsPESPacket) (tsPkts []byte, err error) { - if packet.Header.PacketStartCodePrefix != 0x000001 { - err = errors.New("packetStartCodePrefix != 0x000001") - return - } - bwTsHeader := &bytes.Buffer{} - bwPESPkt := &bytes.Buffer{} - _, err = WritePESHeader(bwPESPkt, packet.Header) - if err != nil { - return - } - - if _, err = bwPESPkt.Write(packet.Payload); err != nil { - return - } - - var tsHeaderLength int - for i := 0; bwPESPkt.Len() > 0; i++ { - bwTsHeader.Reset() - tsHeader := MpegTsHeader{ - SyncByte: 0x47, - TransportErrorIndicator: 0, - PayloadUnitStartIndicator: 0, - TransportPriority: 0, - Pid: frame.Pid, - TransportScramblingControl: 0, - AdaptionFieldControl: 1, - ContinuityCounter: frame.ContinuityCounter, - } - - frame.ContinuityCounter++ - frame.ContinuityCounter = frame.ContinuityCounter % 16 - - // 每一帧的开头,当含有pcr的时候,包含调整字段 - if i == 0 { - tsHeader.PayloadUnitStartIndicator = 1 - - // 当PCRFlag为1的时候,包含调整字段 - if frame.IsKeyFrame { - tsHeader.AdaptionFieldControl = 0x03 - tsHeader.AdaptationFieldLength = 7 - tsHeader.PCRFlag = 1 - tsHeader.RandomAccessIndicator = 1 - tsHeader.ProgramClockReferenceBase = frame.ProgramClockReferenceBase - } - } - - pesPktLength := bwPESPkt.Len() - - // 每一帧的结尾,当不满足188个字节的时候,包含调整字段 - if pesPktLength < TS_PACKET_SIZE-4 { - var tsStuffingLength uint8 - - tsHeader.AdaptionFieldControl = 0x03 - tsHeader.AdaptationFieldLength = uint8(TS_PACKET_SIZE - 4 - 1 - pesPktLength) - - // TODO:如果第一个TS包也是最后一个TS包,是不是需要考虑这个情况? - // MpegTsHeader最少占6个字节.(前4个走字节 + AdaptationFieldLength(1 byte) + 3个指示符5个标志位(1 byte)) - if tsHeader.AdaptationFieldLength >= 1 { - tsStuffingLength = tsHeader.AdaptationFieldLength - 1 - } else { - tsStuffingLength = 0 - } - - // error - tsHeaderLength, err = WriteTsHeader(bwTsHeader, tsHeader) - if err != nil { - return - } - - if tsStuffingLength > 0 { - if _, err = bwTsHeader.Write(stuffing[:tsStuffingLength]); err != nil { - return - } - } - - tsHeaderLength += int(tsStuffingLength) - } else { - tsHeaderLength, err = WriteTsHeader(bwTsHeader, tsHeader) - if err != nil { - return - } - } - - tsPayloadLength := TS_PACKET_SIZE - tsHeaderLength - - //fmt.Println("tsPayloadLength :", tsPayloadLength) - - // 这里不断的减少PES包 - tsHeaderByte := bwTsHeader.Bytes() - tsPayloadByte := bwPESPkt.Next(tsPayloadLength) - - // tmp := tsHeaderByte[3] << 2 - // tmp = tmp >> 6 - // if tmp == 2 { - // fmt.Println("fuck you mother.") - // } - tsPktByteLen := len(tsHeaderByte) + len(tsPayloadByte) - - if tsPktByteLen != TS_PACKET_SIZE { - err = errors.New(fmt.Sprintf("%s, packet size=%d", "TS_PACKET_SIZE != 188,", tsPktByteLen)) - return - } - tsPkts = append(tsPkts, tsHeaderByte...) - tsPkts = append(tsPkts, tsPayloadByte...) - } - - return -} diff --git a/codec/mpegts/mpegts_pmt.go b/codec/mpegts/mpegts_pmt.go index 0a6aa6a..ebb2cd4 100644 --- a/codec/mpegts/mpegts_pmt.go +++ b/codec/mpegts/mpegts_pmt.go @@ -22,11 +22,11 @@ var ( aac = []byte{STREAM_TYPE_AAC, 0xe0 | (PID_AUDIO >> 8), PID_AUDIO & 0xff, 0xf0, 0x00} pcma = []byte{STREAM_TYPE_G711A, 0xe0 | (PID_AUDIO >> 8), PID_AUDIO & 0xff, 0xf0, 0x00} pcmu = []byte{STREAM_TYPE_G711U, 0xe0 | (PID_AUDIO >> 8), PID_AUDIO & 0xff, 0xf0, 0x00} - stuffing []byte + Stuffing []byte ) func init() { - stuffing = util.GetFillBytes(0xff, TS_PACKET_SIZE) + Stuffing = util.GetFillBytes(0xff, TS_PACKET_SIZE) } // TS Header : @@ -363,6 +363,6 @@ func WritePMTPacket(w io.Writer, videoCodec codec.VideoCodecID, audioCodec codec paddingSize += 5 } util.PutBE(crc, GetCRC32_2(pmt)) - pmt = append(pmt, crc, stuffing[:paddingSize]) + pmt = append(pmt, crc, Stuffing[:paddingSize]) pmt.WriteTo(w) } diff --git a/common/frame.go b/common/frame.go index 7671ce7..2348a2e 100644 --- a/common/frame.go +++ b/common/frame.go @@ -51,13 +51,13 @@ type DataFrame[T any] struct { type AVFrame struct { BaseFrame IFrame bool + CanRead bool `json:"-"` PTS uint32 DTS uint32 AVCC util.BLL `json:"-"` // 打包好的AVCC格式(MPEG-4格式、Byte-Stream Format) RTP util.List[RTPFrame] `json:"-"` AUList util.BLLs `json:"-"` // 裸数据 mem util.BLL - CanRead bool `json:"-"` } func (av *AVFrame) WriteAVCC(ts uint32, frame *util.BLL) { diff --git a/memory-ts.go b/memory-ts.go new file mode 100644 index 0000000..fa95a4b --- /dev/null +++ b/memory-ts.go @@ -0,0 +1,174 @@ +package engine + +import ( + "errors" + "fmt" + "io" + "net" + + "m7s.live/engine/v4/codec" + "m7s.live/engine/v4/codec/mpegts" + "m7s.live/engine/v4/common" + "m7s.live/engine/v4/util" +) + +type MemoryTs struct { + util.BytesPool + PMT util.Buffer + util.BLL +} + +func (ts *MemoryTs) WriteTo(w io.Writer) (int64, error) { + w.Write(mpegts.DefaultPATPacket) + w.Write(ts.PMT) + return ts.BLL.WriteTo(w) +} + +func (ts *MemoryTs) WritePESPacket(frame *mpegts.MpegtsPESFrame, packet mpegts.MpegTsPESPacket) (err error) { + if packet.Header.PacketStartCodePrefix != 0x000001 { + err = errors.New("packetStartCodePrefix != 0x000001") + return + } + + var pesBuffers net.Buffers = packet.Buffers + var pesPktLength int + var tsHeaderLength int + for i := 0; len(pesBuffers) > 0; i++ { + headerItem := ts.Get(mpegts.TS_PACKET_SIZE) + ts.BLL.Push(headerItem) + bwTsHeader := headerItem.Value + tsHeaderBuffer := bwTsHeader.SubBuf(0, 0) + copy(bwTsHeader, mpegts.Stuffing) + if i == 0 { + _, err = mpegts.WritePESHeader(&tsHeaderBuffer, packet.Header) + if err != nil { + return + } + pesPktLength = len(tsHeaderBuffer) + util.SizeOfBuffers(pesBuffers) + } + tsHeader := mpegts.MpegTsHeader{ + SyncByte: 0x47, + TransportErrorIndicator: 0, + PayloadUnitStartIndicator: 0, + TransportPriority: 0, + Pid: frame.Pid, + TransportScramblingControl: 0, + AdaptionFieldControl: 1, + ContinuityCounter: frame.ContinuityCounter, + } + + frame.ContinuityCounter++ + frame.ContinuityCounter = frame.ContinuityCounter % 16 + + // 每一帧的开头,当含有pcr的时候,包含调整字段 + if i == 0 { + tsHeader.PayloadUnitStartIndicator = 1 + + // 当PCRFlag为1的时候,包含调整字段 + if frame.IsKeyFrame { + tsHeader.AdaptionFieldControl = 0x03 + tsHeader.AdaptationFieldLength = 7 + tsHeader.PCRFlag = 1 + tsHeader.RandomAccessIndicator = 1 + tsHeader.ProgramClockReferenceBase = frame.ProgramClockReferenceBase + } + } + + // 每一帧的结尾,当不满足188个字节的时候,包含调整字段 + if pesPktLength < mpegts.TS_PACKET_SIZE-4 { + var tsStuffingLength uint8 + + tsHeader.AdaptionFieldControl = 0x03 + tsHeader.AdaptationFieldLength = uint8(mpegts.TS_PACKET_SIZE - 4 - 1 - pesPktLength) + + // TODO:如果第一个TS包也是最后一个TS包,是不是需要考虑这个情况? + // MpegTsHeader最少占6个字节.(前4个走字节 + AdaptationFieldLength(1 byte) + 3个指示符5个标志位(1 byte)) + if tsHeader.AdaptationFieldLength >= 1 { + tsStuffingLength = tsHeader.AdaptationFieldLength - 1 + } else { + tsStuffingLength = 0 + } + // error + tsHeaderLength, err = mpegts.WriteTsHeader(&tsHeaderBuffer, tsHeader) + if err != nil { + return + } + tsHeaderLength += int(tsStuffingLength) + } else { + + tsHeaderLength, err = mpegts.WriteTsHeader(&tsHeaderBuffer, tsHeader) + if err != nil { + return + } + } + + tsPayloadLength := mpegts.TS_PACKET_SIZE - tsHeaderLength + + //fmt.Println("tsPayloadLength :", tsPayloadLength) + + // 这里不断的减少PES包 + io.CopyN(&tsHeaderBuffer, &pesBuffers, int64(tsPayloadLength)) + // tmp := tsHeaderByte[3] << 2 + // tmp = tmp >> 6 + // if tmp == 2 { + // fmt.Println("fuck you mother.") + // } + tsPktByteLen := len(tsHeaderBuffer) + + if tsPktByteLen != mpegts.TS_PACKET_SIZE { + err = errors.New(fmt.Sprintf("%s, packet size=%d", "TS_PACKET_SIZE != 188,", tsPktByteLen)) + return + } + } + + return nil +} + +func (ts *MemoryTs) WriteAudioFrame(frame *AudioFrame, aac_asc *codec.AudioSpecificConfig, pes *mpegts.MpegtsPESFrame) (err error) { + adtsItem := ts.Get(7) + defer adtsItem.Recycle() + adts := adtsItem.Value + aac_asc.ToADTS(frame.AUList.ByteLength, adts) + // packetLength = 原始音频流长度 + adts(7) + MpegTsOptionalPESHeader长度(8 bytes, 因为只含有pts) + pktLength := len(adts) + frame.AUList.ByteLength + 8 + var packet mpegts.MpegTsPESPacket + packet.Header.PacketStartCodePrefix = 0x000001 + packet.Header.ConstTen = 0x80 + packet.Header.StreamID = mpegts.STREAM_ID_AUDIO + packet.Header.PesPacketLength = uint16(pktLength) + packet.Header.Pts = uint64(frame.PTS) + packet.Header.PtsDtsFlags = 0x80 + packet.Header.PesHeaderDataLength = 5 + packet.Buffers = append(append(packet.Buffers, adts), frame.AUList.ToBuffers()...) + return ts.WritePESPacket(pes, packet) +} + +func (ts *MemoryTs) WriteVideoFrame(frame *VideoFrame, paramaterSets common.ParamaterSets, pes *mpegts.MpegtsPESFrame) (err error) { + var buffer net.Buffers + //需要对原始数据(ES),进行一些预处理,视频需要分割nalu(H264编码),并且打上sps,pps,nalu_aud信息. + if len(paramaterSets) == 2 { + buffer = append(buffer, codec.NALU_AUD_BYTE) + } else { + buffer = append(buffer, codec.AudNalu) + } + if frame.IFrame { + buffer = append(buffer, paramaterSets.GetAnnexB()...) + } + buffer = append(buffer, frame.GetAnnexB()...) + pktLength := util.SizeOfBuffers(buffer) + 10 + 3 + if pktLength > 0xffff { + pktLength = 0 + } + + var packet mpegts.MpegTsPESPacket + packet.Header.PacketStartCodePrefix = 0x000001 + packet.Header.ConstTen = 0x80 + packet.Header.StreamID = mpegts.STREAM_ID_VIDEO + packet.Header.PesPacketLength = uint16(pktLength) + packet.Header.Pts = uint64(frame.PTS) + packet.Header.Dts = uint64(frame.DTS) + packet.Header.PtsDtsFlags = 0xC0 + packet.Header.PesHeaderDataLength = 10 + packet.Buffers = buffer + return ts.WritePESPacket(pes, packet) +} diff --git a/subscriber.go b/subscriber.go index 8ba5775..aa76b88 100644 --- a/subscriber.go +++ b/subscriber.go @@ -127,6 +127,7 @@ func (s *Subscriber) AddTrack(t Track) bool { } s.VideoReader.Poll = s.Config.Poll s.VideoReader.Track = &v.Media + s.VideoReader.Logger = s.With(zap.String("track", v.Name)) s.Video = v case *track.Audio: if s.AudioReader.Track != nil || !s.Config.SubAudio { @@ -134,6 +135,7 @@ func (s *Subscriber) AddTrack(t Track) bool { } s.AudioReader.Poll = s.Config.Poll s.AudioReader.Track = &v.Media + s.AudioReader.Logger = s.With(zap.String("track", v.Name)) s.Audio = v case *track.Data: default: diff --git a/track/aac.go b/track/aac.go index f832318..81ef64a 100644 --- a/track/aac.go +++ b/track/aac.go @@ -21,7 +21,7 @@ func NewAAC(stream IStream, stuff ...any) (aac *AAC) { aac.CodecID = codec.CodecID_AAC aac.Channels = 2 aac.SampleSize = 16 - aac.SetStuff("aac", stream, int(256+128), byte(97), aac, time.Millisecond*10) + aac.SetStuff("aac", uint32(90000), stream, int(256+128), byte(97), aac, time.Millisecond*10) aac.SetStuff(stuff...) aac.AVCCHead = []byte{0xAF, 1} return diff --git a/track/reader-av.go b/track/reader-av.go index 5a18abd..1318953 100644 --- a/track/reader-av.go +++ b/track/reader-av.go @@ -31,6 +31,7 @@ type AVRingReader struct { startTime time.Time Frame *common.AVFrame AbsTime uint32 + *zap.Logger } func (r *AVRingReader) DecConfChanged() bool { @@ -66,12 +67,12 @@ func (r *AVRingReader) Read(ctx context.Context, mode int) (err error) { r.ctx = ctx switch r.State { case READSTATE_INIT: - r.Track.Info("start read", zap.Int("mode", mode)) + r.Info("start read", zap.Int("mode", mode)) startRing := r.Track.Ring if r.Track.IDRing != nil { startRing = r.Track.IDRing } else { - r.Track.Warn("no IDRring") + r.Warn("no IDRring") } switch mode { case 0: @@ -100,7 +101,7 @@ func (r *AVRingReader) Read(ctx context.Context, mode int) (err error) { r.SkipTs = r.FirstTs r.SkipRTPTs = r.Track.Ms2RTPTs(r.SkipTs) r.FirstSeq = r.Frame.Sequence - r.Track.Info("first frame read", zap.Uint32("firstTs", r.FirstTs), zap.Uint32("firstSeq", r.FirstSeq)) + r.Info("first frame read", zap.Uint32("firstTs", r.FirstTs), zap.Uint32("firstSeq", r.FirstSeq)) case READSTATE_FIRST: if r.Track.IDRing.Value.Sequence != r.FirstSeq { r.Ring = r.Track.IDRing @@ -110,7 +111,7 @@ func (r *AVRingReader) Read(ctx context.Context, mode int) (err error) { } r.SkipTs = frame.AbsTime - r.beforeJump r.SkipRTPTs = r.Track.Ms2RTPTs(r.SkipTs) - r.Track.Info("jump", zap.Uint32("skipSeq", r.Track.IDRing.Value.Sequence-r.FirstSeq), zap.Uint32("skipTs", r.SkipTs)) + r.Info("jump", zap.Uint32("skipSeq", r.Track.IDRing.Value.Sequence-r.FirstSeq), zap.Uint32("skipTs", r.SkipTs)) r.State = READSTATE_NORMAL } else { r.MoveNext() diff --git a/util/pool.go b/util/pool.go index 94d6ec9..6996c3d 100644 --- a/util/pool.go +++ b/util/pool.go @@ -128,6 +128,14 @@ func (list *BLLs) ToList() (result [][][]byte) { return } +func (list *BLLs) ToBuffers() (result net.Buffers) { + list.Range(func(bll *BLL) bool { + result = append(result, bll.ToBuffers()...) + return true + }) + return +} + func (list *BLLs) ToBytes() (result []byte) { list.Range(func(bll *BLL) bool { result = append(result, bll.ToBytes()...)