mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-27 04:36:12 +08:00
97 lines
1.9 KiB
Go
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
|
|
}
|