mediamtx/internal/rtmp/message/video.go
2023-05-16 16:14:20 +02:00

104 lines
2.1 KiB
Go

package message
import (
"fmt"
"time"
"github.com/notedit/rtmp/format/flv/flvio"
"github.com/bluenviron/mediamtx/internal/rtmp/rawmessage"
)
const (
// VideoChunkStreamID is the chunk stream ID that is usually used to send Video{}
VideoChunkStreamID = 6
)
// supported video codecs
const (
CodecH264 = 7
)
// VideoType is the type of a video message.
type VideoType uint8
// VideoType values.
const (
VideoTypeConfig VideoType = 0
VideoTypeAU VideoType = 1
VideoTypeEOS VideoType = 2
)
// Video is a video message.
type Video struct {
ChunkStreamID byte
DTS time.Duration
MessageStreamID uint32
Codec uint8
IsKeyFrame bool
Type VideoType
PTSDelta time.Duration
Payload []byte
}
// Unmarshal implements Message.
func (m *Video) Unmarshal(raw *rawmessage.Message) error {
m.ChunkStreamID = raw.ChunkStreamID
m.DTS = raw.Timestamp
m.MessageStreamID = raw.MessageStreamID
if len(raw.Body) < 5 {
return fmt.Errorf("invalid body size")
}
m.IsKeyFrame = (raw.Body[0] >> 4) == flvio.FRAME_KEY
m.Codec = raw.Body[0] & 0x0F
switch m.Codec {
case CodecH264:
default:
return fmt.Errorf("unsupported video codec: %d", m.Codec)
}
m.Type = VideoType(raw.Body[1])
switch m.Type {
case VideoTypeConfig, VideoTypeAU, VideoTypeEOS:
default:
return fmt.Errorf("unsupported video message type: %d", m.Type)
}
m.PTSDelta = time.Duration(uint32(raw.Body[2])<<16|uint32(raw.Body[3])<<8|uint32(raw.Body[4])) * time.Millisecond
m.Payload = raw.Body[5:]
return nil
}
// Marshal implements Message.
func (m Video) Marshal() (*rawmessage.Message, error) {
body := make([]byte, 5+len(m.Payload))
if m.IsKeyFrame {
body[0] = flvio.FRAME_KEY << 4
} else {
body[0] = flvio.FRAME_INTER << 4
}
body[0] |= m.Codec
body[1] = uint8(m.Type)
tmp := uint32(m.PTSDelta / time.Millisecond)
body[2] = uint8(tmp >> 16)
body[3] = uint8(tmp >> 8)
body[4] = uint8(tmp)
copy(body[5:], m.Payload)
return &rawmessage.Message{
ChunkStreamID: m.ChunkStreamID,
Timestamp: m.DTS,
Type: uint8(TypeVideo),
MessageStreamID: m.MessageStreamID,
Body: body,
}, nil
}