Files
go2rtc/pkg/rtmp/flv.go
2024-06-16 06:20:45 +03:00

97 lines
1.9 KiB
Go

package rtmp
import (
"github.com/AlexxIT/go2rtc/pkg/flv"
)
func (c *Conn) Producer() (*flv.Producer, error) {
c.rdBuf = []byte{
'F', 'L', 'V', // signature
1, // version
0, // flags (has video/audio)
0, 0, 0, 9, // header size
}
prod, err := flv.Open(c)
if err != nil {
return nil, err
}
prod.FormatName = "rtmp"
prod.Protocol = "rtmp"
prod.RemoteAddr = c.conn.RemoteAddr().String()
prod.URL = c.url
return prod, nil
}
// Read - convert RTMP to FLV format
func (c *Conn) Read(p []byte) (n int, err error) {
// 1. Check temporary tempbuffer
if len(c.rdBuf) == 0 {
msgType, timeMS, payload, err2 := c.readMessage()
if err2 != nil {
return 0, err2
}
// previous tag size (4 byte) + header (11 byte) + payload
n = 4 + 11 + len(payload)
// 2. Check if the message fits in the buffer
if n <= len(p) {
encodeFLV(p, msgType, timeMS, payload)
return
}
// 3. Put the message into a temporary buffer
c.rdBuf = make([]byte, n)
encodeFLV(c.rdBuf, msgType, timeMS, payload)
}
// 4. Send temporary buffer
n = copy(p, c.rdBuf)
c.rdBuf = c.rdBuf[n:]
return
}
func encodeFLV(b []byte, msgType byte, time uint32, payload []byte) {
_ = b[4+11]
b[0] = 0
b[1] = 0
b[2] = 0
b[3] = 0
b[4+0] = msgType
PutUint24(b[4+1:], uint32(len(payload)))
PutUint24(b[4+4:], time)
b[4+7] = byte(time >> 24)
copy(b[4+11:], payload)
}
// Write - convert FLV format to RTMP format
func (c *Conn) Write(p []byte) (n int, err error) {
n = len(p)
if p[0] == 'F' {
p = p[9+4:] // skip first msg with FLV header
for len(p) > 0 {
size := 11 + uint16(p[2])<<8 + uint16(p[3]) + 4
if _, err = c.Write(p[:size]); err != nil {
return 0, err
}
p = p[size:]
}
return
}
// decode FLV: 11 bytes header + payload + 4 byte size
tagType := p[0]
timeMS := uint32(p[4])<<16 | uint32(p[5])<<8 | uint32(p[6]) | uint32(p[7])<<24
payload := p[11 : len(p)-4]
err = c.writeMessage(4, tagType, timeMS, payload)
return
}