mirror of
https://github.com/Monibuca/engine.git
synced 2025-09-27 04:46:03 +08:00
114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package avformat
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/Monibuca/engine/v3/pool"
|
|
"github.com/Monibuca/engine/v3/util"
|
|
)
|
|
|
|
const (
|
|
// FLV Tag Type
|
|
FLV_TAG_TYPE_AUDIO = 0x08
|
|
FLV_TAG_TYPE_VIDEO = 0x09
|
|
FLV_TAG_TYPE_SCRIPT = 0x12
|
|
)
|
|
|
|
var (
|
|
// 音频格式. 4 bit
|
|
SoundFormat = map[byte]string{
|
|
0: "Linear PCM, platform endian",
|
|
1: "ADPCM",
|
|
2: "MP3",
|
|
3: "Linear PCM, little endian",
|
|
4: "Nellymoser 16kHz mono",
|
|
5: "Nellymoser 8kHz mono",
|
|
6: "Nellymoser",
|
|
7: "G.711 A-law logarithmic PCM",
|
|
8: "G.711 mu-law logarithmic PCM",
|
|
9: "reserved",
|
|
10: "AAC",
|
|
11: "Speex",
|
|
14: "MP3 8Khz",
|
|
15: "Device-specific sound"}
|
|
|
|
// 采样频率. 2 bit
|
|
SoundRate = map[byte]int{
|
|
0: 5500,
|
|
1: 11000,
|
|
2: 22000,
|
|
3: 44000}
|
|
|
|
// 量化精度. 1 bit
|
|
SoundSize = map[byte]string{
|
|
0: "8Bit",
|
|
1: "16Bit"}
|
|
|
|
// 音频类型. 1bit
|
|
SoundType = map[byte]string{
|
|
0: "Mono",
|
|
1: "Stereo"}
|
|
|
|
// 视频帧类型. 4bit
|
|
FrameType = map[byte]string{
|
|
1: "keyframe (for AVC, a seekable frame)",
|
|
2: "inter frame (for AVC, a non-seekable frame)",
|
|
3: "disposable inter frame (H.263 only)",
|
|
4: "generated keyframe (reserved for server use only)",
|
|
5: "video info/command frame"}
|
|
|
|
// 视频编码类型. 4bit
|
|
CodecID = map[byte]string{
|
|
1: "JPEG (currently unused)",
|
|
2: "Sorenson H.263",
|
|
3: "Screen video",
|
|
4: "On2 VP6",
|
|
5: "On2 VP6 with alpha channel",
|
|
6: "Screen video version 2",
|
|
7: "AVC",
|
|
12: "H265"}
|
|
)
|
|
|
|
var FLVHeader = []byte{0x46, 0x4c, 0x56, 0x01, 0x05, 0, 0, 0, 9, 0, 0, 0, 0}
|
|
|
|
func WriteFLVTag(w io.Writer, tag *SendPacket) (err error) {
|
|
head := pool.GetSlice(11)
|
|
defer pool.RecycleSlice(head)
|
|
tail := pool.GetSlice(4)
|
|
defer pool.RecycleSlice(tail)
|
|
head[0] = tag.Type
|
|
dataSize := uint32(len(tag.Payload))
|
|
util.BigEndian.PutUint32(tail, dataSize+11)
|
|
util.BigEndian.PutUint24(head[1:], dataSize)
|
|
util.BigEndian.PutUint24(head[4:], tag.Timestamp)
|
|
util.BigEndian.PutUint32(head[7:], 0)
|
|
if _, err = w.Write(head); err != nil {
|
|
return
|
|
}
|
|
// Tag Data
|
|
if _, err = w.Write(tag.Payload); err != nil {
|
|
return
|
|
}
|
|
if _, err = w.Write(tail); err != nil { // PreviousTagSizeN(4)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
func ReadFLVTag(r io.Reader) (t byte, timestamp uint32, payload []byte, err error) {
|
|
head := pool.GetSlice(11)
|
|
defer pool.RecycleSlice(head)
|
|
if _, err = io.ReadFull(r, head); err != nil {
|
|
return
|
|
}
|
|
t = head[0]
|
|
dataSize := util.BigEndian.Uint24(head[1:])
|
|
timestamp = util.BigEndian.Uint24(head[4:])
|
|
payload = make([]byte, int(dataSize))
|
|
if _, err = io.ReadFull(r, payload); err == nil {
|
|
t := pool.GetSlice(4)
|
|
_, err = io.ReadFull(r, t)
|
|
pool.RecycleSlice(t)
|
|
}
|
|
return
|
|
}
|