Files
monibuca/plugin/flv/pkg/flv.go
2025-01-07 13:14:30 +08:00

92 lines
1.9 KiB
Go

package flv
import (
"bufio"
"io"
"net"
"m7s.live/v5/pkg/util"
rtmp "m7s.live/v5/plugin/rtmp/pkg"
)
const (
// FLV Tag Type
FLV_TAG_TYPE_AUDIO = 0x08
FLV_TAG_TYPE_VIDEO = 0x09
FLV_TAG_TYPE_SCRIPT = 0x12
)
var FLVHead = []byte{'F', 'L', 'V', 0x01, 0x05, 0, 0, 0, 9, 0, 0, 0, 0}
type Tag struct {
Type byte
Data []byte
Timestamp uint32
}
type FlvWriter struct {
io.Writer
buf [15]byte
}
func NewFlvWriter(w io.Writer) *FlvWriter {
return &FlvWriter{Writer: w}
}
func (w *FlvWriter) WriteHeader(hasAudio, hasVideo bool) (err error) {
var flags byte
if hasAudio {
flags |= 0x04
}
if hasVideo {
flags |= 0x01
}
_, err = w.Write([]byte{'F', 'L', 'V', 0x01, flags, 0, 0, 0, 9, 0, 0, 0, 0})
return
}
func (w *FlvWriter) WriteTag(t byte, ts, dataSize uint32, payload ...[]byte) (err error) {
WriteFLVTagHead(t, ts, dataSize, w.buf[:])
var buffers net.Buffers = append(append(net.Buffers{w.buf[:11]}, payload...), util.PutBE(w.buf[11:], dataSize+11))
_, err = buffers.WriteTo(w)
return
}
func PutFlvTimestamp(header []byte, timestamp uint32) {
header[4] = byte(timestamp >> 16)
header[5] = byte(timestamp >> 8)
header[6] = byte(timestamp)
header[7] = byte(timestamp >> 24)
}
func WriteFLVTagHead(t uint8, ts, dataSize uint32, b []byte) {
b[0] = t
b[1], b[2], b[3] = byte(dataSize>>16), byte(dataSize>>8), byte(dataSize)
PutFlvTimestamp(b, ts)
}
func ReadMetaData(reader io.Reader) (metaData rtmp.EcmaArray, err error) {
r := bufio.NewReader(reader)
_, err = r.Discard(13)
tagHead := make(util.Buffer, 11)
_, err = io.ReadFull(r, tagHead)
if err != nil {
return
}
tmp := tagHead
t := tmp.ReadByte()
dataLen := tmp.ReadUint24()
_, err = r.Discard(4)
if t == FLV_TAG_TYPE_SCRIPT {
data := make([]byte, dataLen+4)
_, err = io.ReadFull(reader, data)
amf := &rtmp.AMF{
Buffer: util.Buffer(data[1+2+len("onMetaData") : len(data)-4]),
}
var obj any
obj, err = amf.Unmarshal()
metaData = obj.(rtmp.EcmaArray)
}
return
}