mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-09-27 03:56:15 +08:00

* support reading AV1, VP9, H265, Opus, AC-3, G711, LPCM * support reading multiple video or audio tracks at once
130 lines
2.4 KiB
Go
130 lines
2.4 KiB
Go
package message
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/bluenviron/mediamtx/internal/protocols/rtmp/rawmessage"
|
|
)
|
|
|
|
const (
|
|
// AudioChunkStreamID is the chunk stream ID that is usually used to send Audio{}
|
|
AudioChunkStreamID = 4
|
|
)
|
|
|
|
// audio codecs
|
|
const (
|
|
CodecMPEG1Audio = 2
|
|
CodecLPCM = 3
|
|
CodecPCMA = 7
|
|
CodecPCMU = 8
|
|
CodecMPEG4Audio = 10
|
|
)
|
|
|
|
// audio rates
|
|
const (
|
|
Rate5512 = 0
|
|
Rate11025 = 1
|
|
Rate22050 = 2
|
|
Rate44100 = 3
|
|
)
|
|
|
|
// audio depths
|
|
const (
|
|
Depth8 = 0
|
|
Depth16 = 1
|
|
)
|
|
|
|
// AudioAACType is the AAC type of a Audio.
|
|
type AudioAACType uint8
|
|
|
|
// AudioAACType values.
|
|
const (
|
|
AudioAACTypeConfig AudioAACType = 0
|
|
AudioAACTypeAU AudioAACType = 1
|
|
)
|
|
|
|
// Audio is an audio message.
|
|
type Audio struct {
|
|
ChunkStreamID byte
|
|
DTS time.Duration
|
|
MessageStreamID uint32
|
|
Codec uint8
|
|
Rate uint8
|
|
Depth uint8
|
|
IsStereo bool
|
|
AACType AudioAACType // only for CodecMPEG4Audio
|
|
Payload []byte
|
|
}
|
|
|
|
func (m *Audio) unmarshal(raw *rawmessage.Message) error {
|
|
m.ChunkStreamID = raw.ChunkStreamID
|
|
m.DTS = raw.Timestamp
|
|
m.MessageStreamID = raw.MessageStreamID
|
|
|
|
if len(raw.Body) < 2 {
|
|
return fmt.Errorf("invalid body size")
|
|
}
|
|
|
|
m.Codec = raw.Body[0] >> 4
|
|
switch m.Codec {
|
|
case CodecMPEG4Audio, CodecMPEG1Audio, CodecPCMA, CodecPCMU, CodecLPCM:
|
|
default:
|
|
return fmt.Errorf("unsupported audio codec: %d", m.Codec)
|
|
}
|
|
|
|
m.Rate = (raw.Body[0] >> 2) & 0x03
|
|
m.Depth = (raw.Body[0] >> 1) & 0x01
|
|
|
|
if (raw.Body[0] & 0x01) != 0 {
|
|
m.IsStereo = true
|
|
}
|
|
|
|
if m.Codec == CodecMPEG4Audio {
|
|
m.AACType = AudioAACType(raw.Body[1])
|
|
switch m.AACType {
|
|
case AudioAACTypeConfig, AudioAACTypeAU:
|
|
default:
|
|
return fmt.Errorf("unsupported audio message type: %d", m.AACType)
|
|
}
|
|
|
|
m.Payload = raw.Body[2:]
|
|
} else {
|
|
m.Payload = raw.Body[1:]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m Audio) marshalBodySize() int {
|
|
if m.Codec == CodecMPEG4Audio {
|
|
return 2 + len(m.Payload)
|
|
}
|
|
return 1 + len(m.Payload)
|
|
}
|
|
|
|
func (m Audio) marshal() (*rawmessage.Message, error) {
|
|
body := make([]byte, m.marshalBodySize())
|
|
|
|
body[0] = m.Codec<<4 | m.Rate<<2 | m.Depth<<1
|
|
|
|
if m.IsStereo {
|
|
body[0] |= 1
|
|
}
|
|
|
|
if m.Codec == CodecMPEG4Audio {
|
|
body[1] = uint8(m.AACType)
|
|
copy(body[2:], m.Payload)
|
|
} else {
|
|
copy(body[1:], m.Payload)
|
|
}
|
|
|
|
return &rawmessage.Message{
|
|
ChunkStreamID: m.ChunkStreamID,
|
|
Timestamp: m.DTS,
|
|
Type: uint8(TypeAudio),
|
|
MessageStreamID: m.MessageStreamID,
|
|
Body: body,
|
|
}, nil
|
|
}
|