mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
92 lines
1.9 KiB
Go
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
|
|
}
|