cleanup (#1754)
This commit is contained in:
@@ -10,10 +10,10 @@ Live streams can be published to the server with:
|
||||
|
||||
|protocol|variants|codecs|
|
||||
|--------|--------|------|
|
||||
|RTSP clients (FFmpeg, GStreamer, etc)|UDP, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG-2 video, M-JPEG, MPEG-4 video, MPEG-2 audio (MP3), MPEG-4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|
||||
|RTSP servers and cameras|UDP, UDP-Multicast, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG-2 video, M-JPEG, MPEG-4 video, MPEG-2 audio (MP3), MPEG-4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|
||||
|RTMP clients (OBS Studio)|RTMP, RTMPS|H264, H265, MPEG-2 audio (MP3), MPEG-4 Audio (AAC)|
|
||||
|RTMP servers and cameras|RTMP, RTMPS|H264, MPEG-2 audio (MP3), MPEG-4 Audio (AAC)|
|
||||
|RTSP clients (FFmpeg, GStreamer, etc)|UDP, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG-2 Video, M-JPEG, MPEG-4 Video (H263, Xvid), MPEG-2 Audio (MP3), MPEG-4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|
||||
|RTSP servers and cameras|UDP, UDP-Multicast, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG-2 Video, M-JPEG, MPEG-4 Video (H263, Xvid), MPEG-2 Audio (MP3), MPEG-4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|
||||
|RTMP clients (OBS Studio)|RTMP, RTMPS|H264, H265, MPEG-2 Audio (MP3), MPEG-4 Audio (AAC)|
|
||||
|RTMP servers and cameras|RTMP, RTMPS|H264, MPEG-2 Audio (MP3), MPEG-4 Audio (AAC)|
|
||||
|HLS servers and cameras|Low-Latency HLS, MP4-based HLS, legacy HLS|H264, H265, MPEG-4 Audio (AAC), Opus|
|
||||
|UDP/MPEG-TS streams|Unicast, broadcast, multicast|H264, H265, MPEG-4 Audio (AAC), Opus|
|
||||
|Raspberry Pi Cameras||H264|
|
||||
@@ -22,8 +22,8 @@ And can be read from the server with:
|
||||
|
||||
|protocol|variants|codecs|
|
||||
|--------|--------|------|
|
||||
|RTSP|UDP, UDP-Multicast, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG-2 video, M-JPEG, MPEG-4 video, MPEG-2 audio (MP3), MPEG-4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|
||||
|RTMP|RTMP, RTMPS|H264, MPEG-2 audio (MP3), MPEG-4 Audio (AAC)|
|
||||
|RTSP|UDP, UDP-Multicast, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG-2 Video, M-JPEG, MPEG-4 Video (H263, Xvid), MPEG-2 Audio (MP3), MPEG-4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|
||||
|RTMP|RTMP, RTMPS|H264, MPEG-2 Audio (MP3), MPEG-4 Audio (AAC)|
|
||||
|HLS|Low-Latency HLS, MP4-based HLS, legacy HLS|H264, H265, MPEG-4 Audio (AAC), Opus|
|
||||
|WebRTC||H264, VP8, VP9, Opus, G711, G722|
|
||||
|
||||
|
||||
+25
-14
@@ -48,7 +48,8 @@ func getRTMPWriteFunc(medi *media.Media, format formats.Format, stream *stream)
|
||||
return func(msg interface{}) error {
|
||||
tmsg := msg.(*message.MsgVideo)
|
||||
|
||||
if tmsg.H264Type == flvio.AVC_SEQHDR {
|
||||
switch tmsg.Type {
|
||||
case message.MsgVideoTypeConfig:
|
||||
var conf h264conf.Conf
|
||||
err := conf.Unmarshal(tmsg.Payload)
|
||||
if err != nil {
|
||||
@@ -65,9 +66,8 @@ func getRTMPWriteFunc(medi *media.Media, format formats.Format, stream *stream)
|
||||
AU: au,
|
||||
NTP: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
if tmsg.H264Type == flvio.AVC_NALU {
|
||||
case message.MsgVideoTypeAU:
|
||||
au, err := h264.AVCCUnmarshal(tmsg.Payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to decode AVCC: %v", err)
|
||||
@@ -114,15 +114,15 @@ func getRTMPWriteFunc(medi *media.Media, format formats.Format, stream *stream)
|
||||
return func(msg interface{}) error {
|
||||
tmsg := msg.(*message.MsgAudio)
|
||||
|
||||
if tmsg.AACType != flvio.AAC_RAW {
|
||||
return nil
|
||||
if tmsg.AACType == message.MsgAudioAACTypeAU {
|
||||
return stream.writeUnit(medi, format, &formatprocessor.UnitMPEG4Audio{
|
||||
PTS: tmsg.DTS,
|
||||
AUs: [][]byte{tmsg.Payload},
|
||||
NTP: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return stream.writeUnit(medi, format, &formatprocessor.UnitMPEG4Audio{
|
||||
PTS: tmsg.DTS,
|
||||
AUs: [][]byte{tmsg.Payload},
|
||||
NTP: time.Now(),
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -366,7 +366,7 @@ func (c *rtmpConn) runRead(ctx context.Context, u *url.URL) error {
|
||||
|
||||
if videoFormat == nil && audioFormat == nil {
|
||||
return fmt.Errorf(
|
||||
"the stream doesn't contain any supported codec, which are currently H264, MPEG2-Audio, MPEG4-Audio")
|
||||
"the stream doesn't contain any supported codec, which are currently H264, MPEG-2 Audio, MPEG-4 Audio")
|
||||
}
|
||||
|
||||
defer res.stream.readerRemove(c)
|
||||
@@ -496,8 +496,9 @@ func (c *rtmpConn) findVideoFormat(stream *stream, ringBuffer *ringbuffer.RingBu
|
||||
err = c.conn.WriteMessage(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: idrPresent,
|
||||
H264Type: flvio.AVC_NALU,
|
||||
Type: message.MsgVideoTypeAU,
|
||||
Payload: avcc,
|
||||
DTS: dts,
|
||||
PTSDelta: pts - dts,
|
||||
@@ -560,7 +561,7 @@ func (c *rtmpConn) findAudioFormat(stream *stream, ringBuffer *ringbuffer.RingBu
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_RAW,
|
||||
AACType: message.MsgAudioAACTypeAU,
|
||||
Payload: au,
|
||||
DTS: pts + time.Duration(i)*mpeg4audio.SamplesPerAccessUnit*
|
||||
time.Second/time.Duration(audioFormatMPEG4.ClockRate()),
|
||||
@@ -621,11 +622,21 @@ func (c *rtmpConn) findAudioFormat(stream *stream, ringBuffer *ringbuffer.RingBu
|
||||
channels = flvio.SOUND_MONO
|
||||
}
|
||||
|
||||
rate := uint8(flvio.SOUND_44Khz)
|
||||
switch h.SampleRate {
|
||||
case 5500:
|
||||
rate = flvio.SOUND_5_5Khz
|
||||
case 11025:
|
||||
rate = flvio.SOUND_11Khz
|
||||
case 22050:
|
||||
rate = flvio.SOUND_22Khz
|
||||
}
|
||||
|
||||
msg := &message.MsgAudio{
|
||||
ChunkStreamID: message.MsgAudioChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecMPEG2Audio,
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Rate: rate,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: channels,
|
||||
Payload: frame,
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/formats"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
||||
"github.com/notedit/rtmp/format/flv/flvio"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aler9/mediamtx/internal/rtmp"
|
||||
@@ -149,8 +148,9 @@ func TestRTMPServerPublishRead(t *testing.T) {
|
||||
err = conn1.WriteMessage(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_NALU,
|
||||
Type: message.MsgVideoTypeAU,
|
||||
Payload: []byte{
|
||||
0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04, // IDR 1
|
||||
0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04, // IDR 2
|
||||
@@ -163,8 +163,9 @@ func TestRTMPServerPublishRead(t *testing.T) {
|
||||
require.Equal(t, &message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_NALU,
|
||||
Type: message.MsgVideoTypeAU,
|
||||
Payload: []byte{
|
||||
0x00, 0x00, 0x00, 0x19, // SPS
|
||||
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/formats"
|
||||
"github.com/bluenviron/gortsplib/v3/pkg/url"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
||||
"github.com/notedit/rtmp/format/flv/flvio"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -90,8 +89,9 @@ func TestRTMPSource(t *testing.T) {
|
||||
err = conn.WriteMessage(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_NALU,
|
||||
Type: message.MsgVideoTypeAU,
|
||||
Payload: []byte{0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
// UnitMPEG2Audio is a MPEG2-audio data unit.
|
||||
// UnitMPEG2Audio is a MPEG-2 Audio data unit.
|
||||
type UnitMPEG2Audio struct {
|
||||
RTPPackets []*rtp.Packet
|
||||
NTP time.Time
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
// UnitMPEG4Audio is a MPEG4-audio data unit.
|
||||
// UnitMPEG4Audio is a MPEG-4 Audio data unit.
|
||||
type UnitMPEG4Audio struct {
|
||||
RTPPackets []*rtp.Packet
|
||||
NTP time.Time
|
||||
|
||||
+18
-23
@@ -21,10 +21,6 @@ import (
|
||||
"github.com/aler9/mediamtx/internal/rtmp/message"
|
||||
)
|
||||
|
||||
const (
|
||||
codecH264 = 7
|
||||
)
|
||||
|
||||
func resultIsOK1(res *message.MsgCommandAMF0) bool {
|
||||
if len(res.Arguments) < 2 {
|
||||
return false
|
||||
@@ -641,7 +637,7 @@ func (c *Conn) readTracksFromMetadata(payload []interface{}) (formats.Format, fo
|
||||
case 0:
|
||||
return false, nil
|
||||
|
||||
case codecH264:
|
||||
case message.CodecH264:
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -651,7 +647,7 @@ func (c *Conn) readTracksFromMetadata(payload []interface{}) (formats.Format, fo
|
||||
}
|
||||
}
|
||||
|
||||
return false, fmt.Errorf("unsupported video codec %v", v)
|
||||
return false, fmt.Errorf("unsupported video codec: %v", v)
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -694,6 +690,11 @@ func (c *Conn) readTracksFromMetadata(payload []interface{}) (formats.Format, fo
|
||||
}
|
||||
|
||||
for {
|
||||
if (!hasVideo || videoTrack != nil) &&
|
||||
(!hasAudio || audioTrack != nil) {
|
||||
return videoTrack, audioTrack, nil
|
||||
}
|
||||
|
||||
msg, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -706,12 +707,12 @@ func (c *Conn) readTracksFromMetadata(payload []interface{}) (formats.Format, fo
|
||||
}
|
||||
|
||||
if videoTrack == nil {
|
||||
if tmsg.H264Type == flvio.AVC_SEQHDR {
|
||||
if tmsg.Type == message.MsgVideoTypeConfig {
|
||||
videoTrack, err = trackFromH264DecoderConfig(tmsg.Payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
} else if tmsg.H264Type == 1 && tmsg.IsKeyFrame {
|
||||
} else if tmsg.Type == message.MsgVideoTypeAU && tmsg.IsKeyFrame {
|
||||
nalus, err := h264.AVCCUnmarshal(tmsg.Payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -753,7 +754,7 @@ func (c *Conn) readTracksFromMetadata(payload []interface{}) (formats.Format, fo
|
||||
}
|
||||
|
||||
if audioTrack == nil {
|
||||
if tmsg.Codec == message.CodecMPEG4Audio && tmsg.AACType == flvio.AVC_SEQHDR {
|
||||
if tmsg.Codec == message.CodecMPEG4Audio && tmsg.AACType == message.MsgAudioAACTypeConfig {
|
||||
audioTrack, err = trackFromAACDecoderConfig(tmsg.Payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -761,11 +762,6 @@ func (c *Conn) readTracksFromMetadata(payload []interface{}) (formats.Format, fo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasVideo || videoTrack != nil) &&
|
||||
(!hasAudio || audioTrack != nil) {
|
||||
return videoTrack, audioTrack, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,7 +780,7 @@ outer:
|
||||
startTime = &v
|
||||
}
|
||||
|
||||
if tmsg.H264Type == flvio.AVC_SEQHDR {
|
||||
if tmsg.Type == message.MsgVideoTypeConfig {
|
||||
if videoTrack == nil {
|
||||
var err error
|
||||
videoTrack, err = trackFromH264DecoderConfig(tmsg.Payload)
|
||||
@@ -809,7 +805,7 @@ outer:
|
||||
startTime = &v
|
||||
}
|
||||
|
||||
if tmsg.AACType == flvio.AVC_SEQHDR {
|
||||
if tmsg.AACType == message.MsgAudioAACTypeConfig {
|
||||
if audioTrack == nil {
|
||||
var err error
|
||||
audioTrack, err = trackFromAACDecoderConfig(tmsg.Payload)
|
||||
@@ -921,7 +917,7 @@ func (c *Conn) WriteTracks(videoTrack formats.Format, audioTrack formats.Format)
|
||||
V: func() float64 {
|
||||
switch videoTrack.(type) {
|
||||
case *formats.H264:
|
||||
return codecH264
|
||||
return message.CodecH264
|
||||
|
||||
default:
|
||||
return 0
|
||||
@@ -954,12 +950,10 @@ func (c *Conn) WriteTracks(videoTrack formats.Format, audioTrack formats.Format)
|
||||
return err
|
||||
}
|
||||
|
||||
if h264Track, ok := videoTrack.(*formats.H264); ok {
|
||||
sps, pps := h264Track.SafeParams()
|
||||
|
||||
if videoTrack, ok := videoTrack.(*formats.H264); ok {
|
||||
// write decoder config only if SPS and PPS are available.
|
||||
// if they're not available yet, they're sent later.
|
||||
if sps != nil && pps != nil {
|
||||
if sps, pps := videoTrack.SafeParams(); sps != nil && pps != nil {
|
||||
buf, _ := h264conf.Conf{
|
||||
SPS: sps,
|
||||
PPS: pps,
|
||||
@@ -968,8 +962,9 @@ func (c *Conn) WriteTracks(videoTrack formats.Format, audioTrack formats.Format)
|
||||
err = c.WriteMessage(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: message.MsgVideoTypeConfig,
|
||||
Payload: buf,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -991,7 +986,7 @@ func (c *Conn) WriteTracks(videoTrack formats.Format, audioTrack formats.Format)
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
+22
-16
@@ -793,7 +793,7 @@ func TestReadTracks(t *testing.T) {
|
||||
},
|
||||
{
|
||||
K: "videocodecid",
|
||||
V: float64(codecH264),
|
||||
V: float64(message.CodecH264),
|
||||
},
|
||||
{
|
||||
K: "audiodatarate",
|
||||
@@ -816,8 +816,9 @@ func TestReadTracks(t *testing.T) {
|
||||
err = mrw.Write(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: message.MsgVideoTypeConfig,
|
||||
Payload: buf,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -836,7 +837,7 @@ func TestReadTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -855,7 +856,7 @@ func TestReadTracks(t *testing.T) {
|
||||
},
|
||||
{
|
||||
K: "videocodecid",
|
||||
V: float64(codecH264),
|
||||
V: float64(message.CodecH264),
|
||||
},
|
||||
{
|
||||
K: "audiodatarate",
|
||||
@@ -878,8 +879,9 @@ func TestReadTracks(t *testing.T) {
|
||||
err = mrw.Write(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: message.MsgVideoTypeConfig,
|
||||
Payload: buf,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -917,8 +919,9 @@ func TestReadTracks(t *testing.T) {
|
||||
err = mrw.Write(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: message.MsgVideoTypeConfig,
|
||||
Payload: buf,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -937,7 +940,7 @@ func TestReadTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -951,8 +954,9 @@ func TestReadTracks(t *testing.T) {
|
||||
err = mrw.Write(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: message.MsgVideoTypeConfig,
|
||||
Payload: buf,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -971,7 +975,7 @@ func TestReadTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -991,7 +995,7 @@ func TestReadTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -1003,7 +1007,7 @@ func TestReadTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
DTS: 1 * time.Second,
|
||||
})
|
||||
@@ -1023,7 +1027,7 @@ func TestReadTracks(t *testing.T) {
|
||||
},
|
||||
{
|
||||
K: "videocodecid",
|
||||
V: float64(codecH264),
|
||||
V: float64(message.CodecH264),
|
||||
},
|
||||
{
|
||||
K: "audiodatarate",
|
||||
@@ -1064,8 +1068,9 @@ func TestReadTracks(t *testing.T) {
|
||||
err = mrw.Write(&message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: 1,
|
||||
Type: message.MsgVideoTypeAU,
|
||||
Payload: avcc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -1084,7 +1089,7 @@ func TestReadTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: enc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -1364,8 +1369,9 @@ func TestWriteTracks(t *testing.T) {
|
||||
require.Equal(t, &message.MsgVideo{
|
||||
ChunkStreamID: message.MsgVideoChunkStreamID,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: message.CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: message.MsgVideoTypeConfig,
|
||||
Payload: []byte{
|
||||
0x1, 0x64, 0x0,
|
||||
0xc, 0xff, 0xe1, 0x0, 0x15, 0x67, 0x64, 0x0,
|
||||
@@ -1385,7 +1391,7 @@ func TestWriteTracks(t *testing.T) {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_SEQHDR,
|
||||
AACType: message.MsgAudioAACTypeConfig,
|
||||
Payload: []byte{0x12, 0x10},
|
||||
}, msg)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,15 @@ const (
|
||||
CodecMPEG4Audio = 10
|
||||
)
|
||||
|
||||
// MsgAudioAACType is the AAC type of a MsgAudio.
|
||||
type MsgAudioAACType uint8
|
||||
|
||||
// MsgAudioAACType values.
|
||||
const (
|
||||
MsgAudioAACTypeConfig MsgAudioAACType = 0
|
||||
MsgAudioAACTypeAU MsgAudioAACType = 1
|
||||
)
|
||||
|
||||
// MsgAudio is an audio message.
|
||||
type MsgAudio struct {
|
||||
ChunkStreamID byte
|
||||
@@ -28,7 +37,7 @@ type MsgAudio struct {
|
||||
Rate uint8
|
||||
Depth uint8
|
||||
Channels uint8
|
||||
AACType uint8 // only for CodecMPEG4Audio
|
||||
AACType MsgAudioAACType // only for CodecMPEG4Audio
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
@@ -56,7 +65,13 @@ func (m *MsgAudio) Unmarshal(raw *rawmessage.Message) error {
|
||||
if m.Codec == CodecMPEG2Audio {
|
||||
m.Payload = raw.Body[1:]
|
||||
} else {
|
||||
m.AACType = raw.Body[1]
|
||||
m.AACType = MsgAudioAACType(raw.Body[1])
|
||||
switch m.AACType {
|
||||
case MsgAudioAACTypeConfig, MsgAudioAACTypeAU:
|
||||
default:
|
||||
return fmt.Errorf("unsupported audio message type: %d", m.AACType)
|
||||
}
|
||||
|
||||
m.Payload = raw.Body[2:]
|
||||
}
|
||||
|
||||
@@ -78,7 +93,7 @@ func (m MsgAudio) Marshal() (*rawmessage.Message, error) {
|
||||
if m.Codec == CodecMPEG2Audio {
|
||||
copy(body[1:], m.Payload)
|
||||
} else {
|
||||
body[1] = m.AACType
|
||||
body[1] = uint8(m.AACType)
|
||||
copy(body[2:], m.Payload)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,29 @@ const (
|
||||
MsgVideoChunkStreamID = 6
|
||||
)
|
||||
|
||||
// supported video codecs
|
||||
const (
|
||||
CodecH264 = 7
|
||||
)
|
||||
|
||||
// MsgVideoType is the type of a video message.
|
||||
type MsgVideoType uint8
|
||||
|
||||
// MsgVideoType values.
|
||||
const (
|
||||
MsgVideoTypeConfig MsgVideoType = 0
|
||||
MsgVideoTypeAU MsgVideoType = 1
|
||||
MsgVideoTypeEOS MsgVideoType = 2
|
||||
)
|
||||
|
||||
// MsgVideo is a video message.
|
||||
type MsgVideo struct {
|
||||
ChunkStreamID byte
|
||||
DTS time.Duration
|
||||
MessageStreamID uint32
|
||||
Codec uint8
|
||||
IsKeyFrame bool
|
||||
H264Type uint8
|
||||
Type MsgVideoType
|
||||
PTSDelta time.Duration
|
||||
Payload []byte
|
||||
}
|
||||
@@ -38,12 +54,19 @@ func (m *MsgVideo) Unmarshal(raw *rawmessage.Message) error {
|
||||
|
||||
m.IsKeyFrame = (raw.Body[0] >> 4) == flvio.FRAME_KEY
|
||||
|
||||
codec := raw.Body[0] & 0x0F
|
||||
if codec != flvio.VIDEO_H264 {
|
||||
return fmt.Errorf("unsupported video codec: %d", codec)
|
||||
m.Codec = raw.Body[0] & 0x0F
|
||||
switch m.Codec {
|
||||
case CodecH264:
|
||||
default:
|
||||
return fmt.Errorf("unsupported video codec: %d", m.Codec)
|
||||
}
|
||||
|
||||
m.H264Type = raw.Body[1]
|
||||
m.Type = MsgVideoType(raw.Body[1])
|
||||
switch m.Type {
|
||||
case MsgVideoTypeConfig, MsgVideoTypeAU, MsgVideoTypeEOS:
|
||||
default:
|
||||
return fmt.Errorf("unsupported video message type: %d", m.Type)
|
||||
}
|
||||
|
||||
tmp := uint32(raw.Body[2])<<16 | uint32(raw.Body[3])<<8 | uint32(raw.Body[4])
|
||||
m.PTSDelta = time.Duration(tmp) * time.Millisecond
|
||||
@@ -62,8 +85,8 @@ func (m MsgVideo) Marshal() (*rawmessage.Message, error) {
|
||||
} else {
|
||||
body[0] = flvio.FRAME_INTER << 4
|
||||
}
|
||||
body[0] |= flvio.VIDEO_H264
|
||||
body[1] = m.H264Type
|
||||
body[0] |= m.Codec
|
||||
body[1] = uint8(m.Type)
|
||||
|
||||
tmp := uint32(m.PTSDelta / time.Millisecond)
|
||||
body[2] = uint8(tmp >> 16)
|
||||
|
||||
@@ -53,7 +53,7 @@ var readWriterCases = []struct {
|
||||
Rate: flvio.SOUND_44Khz,
|
||||
Depth: flvio.SOUND_16BIT,
|
||||
Channels: flvio.SOUND_STEREO,
|
||||
AACType: flvio.AAC_RAW,
|
||||
AACType: MsgAudioAACTypeAU,
|
||||
Payload: []byte{0x5A, 0xC0, 0x77, 0x40},
|
||||
},
|
||||
[]byte{
|
||||
@@ -220,8 +220,9 @@ var readWriterCases = []struct {
|
||||
ChunkStreamID: 6,
|
||||
DTS: 2543534 * time.Millisecond,
|
||||
MessageStreamID: 0x1000000,
|
||||
Codec: CodecH264,
|
||||
IsKeyFrame: true,
|
||||
H264Type: flvio.AVC_SEQHDR,
|
||||
Type: MsgVideoTypeConfig,
|
||||
PTSDelta: 10 * time.Millisecond,
|
||||
Payload: []byte{0x01, 0x02, 0x03},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user