You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/httpflv/tag.go

122 lines
2.8 KiB
Go

package httpflv
import (
"github.com/q191201771/lal/bele"
"io"
)
// TODO chef: make these const
const tagHeaderSize int = 11
const prevTagSizeFieldSize int = 4
var (
TagTypeMetadata uint8 = 18
TagTypeVideo uint8 = 9
TagTypeAudio uint8 = 8
)
var (
frameTypeKey uint8 = 1
frameTypeInter uint8 = 2
)
var (
codecIDAVC uint8 = 7
)
var (
AVCKey = frameTypeKey<<4 | codecIDAVC
AVCInter = frameTypeInter<<4 | codecIDAVC
)
var (
isAVCKeySeqHeader uint8 = 0
AVCPacketTypeNalu uint8 = 1
)
var (
SoundFormatAAC uint8 = 10
)
var (
AACPacketTypeSeqHeader uint8 = 0
AACPacketTypeRaw uint8 = 1
)
type TagHeader struct {
T uint8 // type
DataSize uint32
Timestamp uint32
StreamID uint32 // always 0
}
type Tag struct {
Header TagHeader
Raw []byte
}
func (tag *Tag) IsMetadata() bool {
return tag.Header.T == TagTypeMetadata
}
func (tag *Tag) IsAVCKeySeqHeader() bool {
return tag.Header.T == TagTypeVideo && tag.Raw[tagHeaderSize] == AVCKey && tag.Raw[tagHeaderSize+1] == isAVCKeySeqHeader
}
func (tag *Tag) IsAVCKeyNalu() bool {
return tag.Header.T == TagTypeVideo && tag.Raw[tagHeaderSize] == AVCKey && tag.Raw[tagHeaderSize+1] == AVCPacketTypeNalu
}
func (tag *Tag) IsAACSeqHeader() bool {
return tag.Header.T == TagTypeAudio && tag.Raw[tagHeaderSize]>>4 == SoundFormatAAC && tag.Raw[tagHeaderSize+1] == AACPacketTypeSeqHeader
}
func IsMetadata(tag []byte) bool {
return tag[0] == TagTypeMetadata
}
func IsAVCKeySeqHeader(tag []byte) bool {
return tag[0] == TagTypeVideo && tag[tagHeaderSize] == AVCKey && tag[tagHeaderSize+1] == isAVCKeySeqHeader
}
func IsAVCKeyNalu(tag []byte) bool {
return tag[0] == TagTypeVideo && tag[tagHeaderSize] == AVCKey && tag[tagHeaderSize+1] == AVCPacketTypeNalu
}
func IsAACSeqHeader(tag []byte) bool {
return tag[0] == TagTypeAudio && tag[tagHeaderSize]>>4 == SoundFormatAAC && tag[tagHeaderSize+1] == AACPacketTypeSeqHeader
}
func PackHTTPFlvTag(t uint8, timestamp int, in []byte) []byte {
out := make([]byte, tagHeaderSize+len(in)+prevTagSizeFieldSize)
out[0] = t
bele.BEPutUint24(out[1:], uint32(len(in)))
bele.BEPutUint24(out[4:], uint32(timestamp&0xFFFFFF))
out[7] = uint8(timestamp >> 24)
out[8] = 0
out[9] = 0
out[10] = 0
copy(out[11:], in)
bele.BEPutUint32(out[tagHeaderSize+len(in):], uint32(tagHeaderSize+len(in)))
return out
}
func readTagHeader(rd io.Reader) (h TagHeader, rawHeader []byte, err error) {
rawHeader = make([]byte, tagHeaderSize)
if _, err = io.ReadAtLeast(rd, rawHeader, tagHeaderSize); err != nil {
return
}
h.T = rawHeader[0]
h.DataSize = bele.BEUint24(rawHeader[1:])
h.Timestamp = (uint32(rawHeader[7]) << 24) + bele.BEUint24(rawHeader[4:])
return
}
func (tag *Tag) cloneTag() *Tag {
res := &Tag{}
res.Header = tag.Header
res.Raw = append(res.Raw, tag.Raw...)
return res
}