|
|
// Copyright 2020, Chef. All rights reserved.
|
|
|
// https://github.com/q191201771/lal
|
|
|
//
|
|
|
// Use of this source code is governed by a MIT-style license
|
|
|
// that can be found in the License file.
|
|
|
//
|
|
|
// Author: Chef (191201771@qq.com)
|
|
|
|
|
|
package base
|
|
|
|
|
|
const (
|
|
|
// spec-rtmp_specification_1.0.pdf
|
|
|
// 7.1. Types of Messages
|
|
|
RtmpTypeIdAudio uint8 = 8
|
|
|
RtmpTypeIdVideo uint8 = 9
|
|
|
RtmpTypeIdMetadata uint8 = 18 // RtmpTypeIdDataMessageAmf0
|
|
|
RtmpTypeIdSetChunkSize uint8 = 1
|
|
|
RtmpTypeIdAck uint8 = 3
|
|
|
RtmpTypeIdUserControl uint8 = 4
|
|
|
RtmpTypeIdWinAckSize uint8 = 5
|
|
|
RtmpTypeIdBandwidth uint8 = 6
|
|
|
RtmpTypeIdCommandMessageAmf3 uint8 = 17
|
|
|
RtmpTypeIdCommandMessageAmf0 uint8 = 20
|
|
|
RtmpTypeIdAggregateMessage uint8 = 22
|
|
|
|
|
|
// user control message type
|
|
|
RtmpUserControlStreamBegin uint8 = 0
|
|
|
RtmpUserControlRecorded uint8 = 4
|
|
|
|
|
|
// spec-video_file_format_spec_v10.pdf
|
|
|
// Video tags
|
|
|
// VIDEODATA
|
|
|
// FrameType UB[4]
|
|
|
// CodecId UB[4]
|
|
|
// AVCVIDEOPACKET
|
|
|
// AVCPacketType UI8
|
|
|
// CompositionTime SI24
|
|
|
// Data UI8[n]
|
|
|
RtmpFrameTypeKey uint8 = 1
|
|
|
RtmpFrameTypeInter uint8 = 2
|
|
|
|
|
|
RtmpCodecIdAvc uint8 = 7
|
|
|
RtmpCodecIdHevc uint8 = 12
|
|
|
|
|
|
RtmpAvcPacketTypeSeqHeader uint8 = 0
|
|
|
RtmpAvcPacketTypeNalu uint8 = 1
|
|
|
RtmpHevcPacketTypeSeqHeader = RtmpAvcPacketTypeSeqHeader
|
|
|
RtmpHevcPacketTypeNalu = RtmpAvcPacketTypeNalu
|
|
|
|
|
|
RtmpAvcKeyFrame = RtmpFrameTypeKey<<4 | RtmpCodecIdAvc
|
|
|
RtmpHevcKeyFrame = RtmpFrameTypeKey<<4 | RtmpCodecIdHevc
|
|
|
RtmpAvcInterFrame = RtmpFrameTypeInter<<4 | RtmpCodecIdAvc
|
|
|
RtmpHevcInterFrame = RtmpFrameTypeInter<<4 | RtmpCodecIdHevc
|
|
|
|
|
|
// spec-video_file_format_spec_v10.pdf
|
|
|
// Audio tags
|
|
|
// AUDIODATA
|
|
|
// SoundFormat UB[4]
|
|
|
// SoundRate UB[2]
|
|
|
// SoundSize UB[1]
|
|
|
// SoundType UB[1]
|
|
|
// AACAUDIODATA
|
|
|
// AACPacketType UI8
|
|
|
// Data UI8[n]
|
|
|
RtmpSoundFormatAac uint8 = 10 // 注意,视频的CodecId是后4位,音频是前4位
|
|
|
RtmpAacPacketTypeSeqHeader = 0
|
|
|
RtmpAacPacketTypeRaw = 1
|
|
|
)
|
|
|
|
|
|
type RtmpHeader struct {
|
|
|
Csid int
|
|
|
MsgLen uint32 // 不包含header的大小
|
|
|
MsgTypeId uint8 // 8 audio 9 video 18 metadata
|
|
|
MsgStreamId int
|
|
|
TimestampAbs uint32 // 经过计算得到的流上的绝对时间戳,单位毫秒
|
|
|
}
|
|
|
|
|
|
type RtmpMsg struct {
|
|
|
Header RtmpHeader
|
|
|
Payload []byte // Payload不包含Header内容。如果需要将RtmpMsg序列化成RTMP chunk,可调用rtmp.ChunkDivider相关的函数
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsAvcKeySeqHeader() bool {
|
|
|
return msg.Header.MsgTypeId == RtmpTypeIdVideo && msg.Payload[0] == RtmpAvcKeyFrame && msg.Payload[1] == RtmpAvcPacketTypeSeqHeader
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsHevcKeySeqHeader() bool {
|
|
|
return msg.Header.MsgTypeId == RtmpTypeIdVideo && msg.Payload[0] == RtmpHevcKeyFrame && msg.Payload[1] == RtmpHevcPacketTypeSeqHeader
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsVideoKeySeqHeader() bool {
|
|
|
return msg.IsAvcKeySeqHeader() || msg.IsHevcKeySeqHeader()
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsAvcKeyNalu() bool {
|
|
|
return msg.Header.MsgTypeId == RtmpTypeIdVideo && msg.Payload[0] == RtmpAvcKeyFrame && msg.Payload[1] == RtmpAvcPacketTypeNalu
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsHevcKeyNalu() bool {
|
|
|
return msg.Header.MsgTypeId == RtmpTypeIdVideo && msg.Payload[0] == RtmpHevcKeyFrame && msg.Payload[1] == RtmpHevcPacketTypeNalu
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsVideoKeyNalu() bool {
|
|
|
return msg.IsAvcKeyNalu() || msg.IsHevcKeyNalu()
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) IsAacSeqHeader() bool {
|
|
|
return msg.Header.MsgTypeId == RtmpTypeIdAudio && (msg.Payload[0]>>4) == RtmpSoundFormatAac && msg.Payload[1] == RtmpAacPacketTypeSeqHeader
|
|
|
}
|
|
|
|
|
|
func (msg RtmpMsg) Clone() (ret RtmpMsg) {
|
|
|
ret.Header = msg.Header
|
|
|
ret.Payload = make([]byte, len(msg.Payload))
|
|
|
copy(ret.Payload, msg.Payload)
|
|
|
return
|
|
|
}
|