mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 07:06:58 +08:00
change way tracks are initialized
A config object is now required to initialize tracks. Config objects are provided for H264 and AAC. This allows to pass parameters easily and treat AAC parameters explicitly.
This commit is contained in:
@@ -171,7 +171,7 @@ func TestClientPublishSerial(t *testing.T) {
|
|||||||
}(),
|
}(),
|
||||||
}
|
}
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
||||||
@@ -313,7 +313,7 @@ func TestClientPublishParallel(t *testing.T) {
|
|||||||
}(),
|
}(),
|
||||||
}
|
}
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
writerDone := make(chan struct{})
|
writerDone := make(chan struct{})
|
||||||
@@ -471,7 +471,7 @@ func TestClientPublishPauseSerial(t *testing.T) {
|
|||||||
}(),
|
}(),
|
||||||
}
|
}
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
||||||
@@ -609,7 +609,7 @@ func TestClientPublishPauseParallel(t *testing.T) {
|
|||||||
}(),
|
}(),
|
||||||
}
|
}
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
||||||
@@ -747,7 +747,7 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn, err := DialPublish("rtsp://localhost:8554/teststream",
|
conn, err := DialPublish("rtsp://localhost:8554/teststream",
|
||||||
@@ -888,7 +888,7 @@ func TestClientPublishRTCPReport(t *testing.T) {
|
|||||||
senderReportPeriod: 1 * time.Second,
|
senderReportPeriod: 1 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
conn, err := c.DialPublish("rtsp://localhost:8554/teststream",
|
||||||
|
@@ -23,13 +23,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestClientReadTracks(t *testing.T) {
|
func TestClientReadTracks(t *testing.T) {
|
||||||
track1, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track1, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
track2, err := NewTrackAAC(96, []byte{17, 144})
|
track2, err := NewTrackAAC(96, &TrackConfigAAC{Type: 1, SampleRate: 44100, ChannelCount: 2})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
track3, err := NewTrackAAC(96, []byte{0x12, 0x30})
|
track3, err := NewTrackAAC(96, &TrackConfigAAC{Type: 1, SampleRate: 96000, ChannelCount: 2})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
l, err := net.Listen("tcp", "localhost:8554")
|
l, err := net.Listen("tcp", "localhost:8554")
|
||||||
@@ -221,7 +221,7 @@ func TestClientRead(t *testing.T) {
|
|||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
require.Equal(t, mustParseURL(scheme+"://"+listenIP+":8554/teststream"), req.URL)
|
require.Equal(t, mustParseURL(scheme+"://"+listenIP+":8554/teststream"), req.URL)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -463,10 +463,10 @@ func TestClientReadPartial(t *testing.T) {
|
|||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream"), req.URL)
|
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream"), req.URL)
|
||||||
|
|
||||||
track1, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track1, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
track2, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track2, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track1, track2})
|
tracks := cloneAndClearTracks(Tracks{track1, track2})
|
||||||
@@ -611,7 +611,7 @@ func TestClientReadNoContentBase(t *testing.T) {
|
|||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -719,7 +719,7 @@ func TestClientReadAnyPort(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -847,7 +847,7 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -979,7 +979,7 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
|
|||||||
err = v.ValidateRequest(req, nil)
|
err = v.ValidateRequest(req, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -1172,7 +1172,7 @@ func TestClientReadDifferentInterleavedIDs(t *testing.T) {
|
|||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
||||||
|
|
||||||
track1, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track1, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track1})
|
tracks := cloneAndClearTracks(Tracks{track1})
|
||||||
@@ -1334,7 +1334,7 @@ func TestClientReadRedirect(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -1493,7 +1493,7 @@ func TestClientReadPause(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -1679,7 +1679,7 @@ func TestClientReadRTCPReport(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -1854,7 +1854,7 @@ func TestClientReadErrorTimeout(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -2011,7 +2011,7 @@ func TestClientReadIgnoreTCPInvalidTrack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -2141,7 +2141,7 @@ func TestClientReadSeek(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
|
@@ -69,7 +69,7 @@ func TestClientSession(t *testing.T) {
|
|||||||
|
|
||||||
require.Equal(t, base.HeaderValue{"123456"}, req.Header["Session"])
|
require.Equal(t, base.HeaderValue{"123456"}, req.Header["Session"])
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -149,7 +149,7 @@ func TestClientAuth(t *testing.T) {
|
|||||||
err = v.ValidateRequest(req, nil)
|
err = v.ValidateRequest(req, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := cloneAndClearTracks(Tracks{track})
|
tracks := cloneAndClearTracks(Tracks{track})
|
||||||
@@ -212,7 +212,7 @@ func TestClientDescribeCharset(t *testing.T) {
|
|||||||
require.Equal(t, base.Describe, req.Method)
|
require.Equal(t, base.Describe, req.Method)
|
||||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
||||||
|
|
||||||
track1, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track1, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = base.Response{
|
err = base.Response{
|
||||||
|
@@ -36,7 +36,7 @@ func main() {
|
|||||||
fmt.Println("stream connected")
|
fmt.Println("stream connected")
|
||||||
|
|
||||||
// create a H264 track
|
// create a H264 track
|
||||||
track, err := gortsplib.NewTrackH264(96, sps, pps)
|
track, err := gortsplib.NewTrackH264(96, &gortsplib.TrackConfigH264{sps, pps})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ func main() {
|
|||||||
fmt.Println("stream connected")
|
fmt.Println("stream connected")
|
||||||
|
|
||||||
// create a H264 track
|
// create a H264 track
|
||||||
track, err := gortsplib.NewTrackH264(96, sps, pps)
|
track, err := gortsplib.NewTrackH264(96, &gortsplib.TrackConfigH264{sps, pps})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,7 @@ func main() {
|
|||||||
fmt.Println("stream connected")
|
fmt.Println("stream connected")
|
||||||
|
|
||||||
// create a H264 track
|
// create a H264 track
|
||||||
track, err := gortsplib.NewTrackH264(96, sps, pps)
|
track, err := gortsplib.NewTrackH264(96, &gortsplib.TrackConfigH264{sps, pps})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package rtpaac
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/icza/bitio"
|
"github.com/icza/bitio"
|
||||||
)
|
)
|
||||||
@@ -43,12 +44,13 @@ var channelCounts = []int{
|
|||||||
|
|
||||||
// MPEG4AudioConfig is a MPEG-4 Audio configuration.
|
// MPEG4AudioConfig is a MPEG-4 Audio configuration.
|
||||||
type MPEG4AudioConfig struct {
|
type MPEG4AudioConfig struct {
|
||||||
Type MPEG4AudioType
|
Type MPEG4AudioType
|
||||||
SampleRate int
|
SampleRate int
|
||||||
ChannelCount int
|
ChannelCount int
|
||||||
|
AOTSpecificConfig []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode decodes an MPEG-4 Audio configuration.
|
// Decode decodes an MPEG4AudioConfig.
|
||||||
func (c *MPEG4AudioConfig) Decode(byts []byte) error {
|
func (c *MPEG4AudioConfig) Decode(byts []byte) error {
|
||||||
// ref: https://wiki.multimedia.cx/index.php/MPEG-4_Audio
|
// ref: https://wiki.multimedia.cx/index.php/MPEG-4_Audio
|
||||||
|
|
||||||
@@ -60,14 +62,6 @@ func (c *MPEG4AudioConfig) Decode(byts []byte) error {
|
|||||||
}
|
}
|
||||||
c.Type = MPEG4AudioType(tmp)
|
c.Type = MPEG4AudioType(tmp)
|
||||||
|
|
||||||
if tmp == 31 {
|
|
||||||
tmp, err = r.ReadBits(6)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.Type = MPEG4AudioType(tmp + 32)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case MPEG4AudioTypeAACLC:
|
case MPEG4AudioTypeAACLC:
|
||||||
default:
|
default:
|
||||||
@@ -110,5 +104,64 @@ func (c *MPEG4AudioConfig) Decode(byts []byte) error {
|
|||||||
return fmt.Errorf("invalid channel configuration (%d)", channelConfig)
|
return fmt.Errorf("invalid channel configuration (%d)", channelConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
byt, err := r.ReadBits(8)
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AOTSpecificConfig = append(c.AOTSpecificConfig, uint8(byt))
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode encodes an MPEG4AudioConfig.
|
||||||
|
func (c MPEG4AudioConfig) Encode() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := bitio.NewWriter(&buf)
|
||||||
|
|
||||||
|
w.WriteBits(uint64(c.Type), 5)
|
||||||
|
|
||||||
|
sampleRateIndex := func() int {
|
||||||
|
for i, s := range sampleRates {
|
||||||
|
if s == c.SampleRate {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}()
|
||||||
|
|
||||||
|
if sampleRateIndex != -1 {
|
||||||
|
w.WriteBits(uint64(sampleRateIndex), 4)
|
||||||
|
} else {
|
||||||
|
w.WriteBits(uint64(15), 4)
|
||||||
|
w.WriteBits(uint64(c.SampleRate), 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
channelConfig := func() int {
|
||||||
|
for i, co := range channelCounts {
|
||||||
|
if co == c.ChannelCount {
|
||||||
|
return i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}()
|
||||||
|
|
||||||
|
if channelConfig == -1 {
|
||||||
|
return nil, fmt.Errorf("invalid channel count (%d)", c.ChannelCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteBits(uint64(channelConfig), 4)
|
||||||
|
|
||||||
|
for _, b := range c.AOTSpecificConfig {
|
||||||
|
w.WriteBits(uint64(b), 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
@@ -15,9 +15,10 @@ var configCases = []struct {
|
|||||||
"aac-lc 44.1khz mono",
|
"aac-lc 44.1khz mono",
|
||||||
[]byte{0x12, 0x08, 0x56, 0xe5, 0x00},
|
[]byte{0x12, 0x08, 0x56, 0xe5, 0x00},
|
||||||
MPEG4AudioConfig{
|
MPEG4AudioConfig{
|
||||||
Type: MPEG4AudioTypeAACLC,
|
Type: MPEG4AudioTypeAACLC,
|
||||||
SampleRate: 44100,
|
SampleRate: 44100,
|
||||||
ChannelCount: 1,
|
ChannelCount: 1,
|
||||||
|
AOTSpecificConfig: []byte{0x0A, 0xDC, 0xA0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -33,9 +34,10 @@ var configCases = []struct {
|
|||||||
"aac-lc 96khz stereo",
|
"aac-lc 96khz stereo",
|
||||||
[]byte{0x10, 0x10, 0x56, 0xE5, 0x00},
|
[]byte{0x10, 0x10, 0x56, 0xE5, 0x00},
|
||||||
MPEG4AudioConfig{
|
MPEG4AudioConfig{
|
||||||
Type: MPEG4AudioTypeAACLC,
|
Type: MPEG4AudioTypeAACLC,
|
||||||
SampleRate: 96000,
|
SampleRate: 96000,
|
||||||
ChannelCount: 2,
|
ChannelCount: 2,
|
||||||
|
AOTSpecificConfig: []byte{0x0A, 0xDC, 0xA0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -81,14 +83,9 @@ func TestConfigDecodeErrors(t *testing.T) {
|
|||||||
"EOF",
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"extended type missing",
|
"unsupported type",
|
||||||
[]byte{31 << 3},
|
[]byte{18 << 3},
|
||||||
"EOF",
|
"unsupported type: 18",
|
||||||
},
|
|
||||||
{
|
|
||||||
"extended type invalid",
|
|
||||||
[]byte{31 << 3, 20},
|
|
||||||
"unsupported type: 32",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sample rate missing",
|
"sample rate missing",
|
||||||
@@ -123,3 +120,36 @@ func TestConfigDecodeErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigEncode(t *testing.T) {
|
||||||
|
for _, ca := range configCases {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
enc, err := ca.dec.Encode()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ca.enc, enc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigEncodeErrors(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
conf MPEG4AudioConfig
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid channel config",
|
||||||
|
MPEG4AudioConfig{
|
||||||
|
Type: 2,
|
||||||
|
SampleRate: 44100,
|
||||||
|
ChannelCount: 0,
|
||||||
|
},
|
||||||
|
"invalid channel count (0)",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
_, err := ca.conf.Encode()
|
||||||
|
require.Equal(t, ca.err, err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -100,7 +100,7 @@ func TestServerPublishErrorAnnounce(t *testing.T) {
|
|||||||
"Content-Type": base.HeaderValue{"application/sdp"},
|
"Content-Type": base.HeaderValue{"application/sdp"},
|
||||||
},
|
},
|
||||||
Body: func() []byte {
|
Body: func() []byte {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
||||||
Key: "control",
|
Key: "control",
|
||||||
@@ -139,7 +139,7 @@ func TestServerPublishErrorAnnounce(t *testing.T) {
|
|||||||
"Content-Type": base.HeaderValue{"application/sdp"},
|
"Content-Type": base.HeaderValue{"application/sdp"},
|
||||||
},
|
},
|
||||||
Body: func() []byte {
|
Body: func() []byte {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
||||||
Key: "control",
|
Key: "control",
|
||||||
@@ -178,7 +178,7 @@ func TestServerPublishErrorAnnounce(t *testing.T) {
|
|||||||
"Content-Type": base.HeaderValue{"application/sdp"},
|
"Content-Type": base.HeaderValue{"application/sdp"},
|
||||||
},
|
},
|
||||||
Body: func() []byte {
|
Body: func() []byte {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
||||||
Key: "control",
|
Key: "control",
|
||||||
@@ -320,7 +320,7 @@ func TestServerPublishSetupPath(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
|
||||||
Key: "control",
|
Key: "control",
|
||||||
@@ -415,7 +415,7 @@ func TestServerPublishErrorSetupDifferentPaths(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -497,7 +497,7 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -596,10 +596,10 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track1, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track1, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
track2, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track2, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track1, track2}
|
tracks := Tracks{track1, track2}
|
||||||
@@ -749,7 +749,7 @@ func TestServerPublish(t *testing.T) {
|
|||||||
|
|
||||||
<-connOpened
|
<-connOpened
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -937,7 +937,7 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -1038,7 +1038,7 @@ func TestServerPublishRTCPReport(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -1197,7 +1197,7 @@ func TestServerPublishTimeout(t *testing.T) {
|
|||||||
defer nconn.Close()
|
defer nconn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -1324,7 +1324,7 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
@@ -1443,7 +1443,7 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
|
@@ -89,7 +89,7 @@ func TestServerReadSetupPath(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track, track, track, track, track})
|
stream := NewServerStream(Tracks{track, track, track, track, track})
|
||||||
@@ -145,7 +145,7 @@ func TestServerReadSetupPath(t *testing.T) {
|
|||||||
func TestServerReadErrorSetupDifferentPaths(t *testing.T) {
|
func TestServerReadErrorSetupDifferentPaths(t *testing.T) {
|
||||||
connClosed := make(chan struct{})
|
connClosed := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -217,7 +217,7 @@ func TestServerReadErrorSetupDifferentPaths(t *testing.T) {
|
|||||||
func TestServerReadErrorSetupTrackTwice(t *testing.T) {
|
func TestServerReadErrorSetupTrackTwice(t *testing.T) {
|
||||||
connClosed := make(chan struct{})
|
connClosed := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -300,7 +300,7 @@ func TestServerRead(t *testing.T) {
|
|||||||
sessionClosed := make(chan struct{})
|
sessionClosed := make(chan struct{})
|
||||||
framesReceived := make(chan struct{})
|
framesReceived := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -593,7 +593,7 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
|
|||||||
writerDone := make(chan struct{})
|
writerDone := make(chan struct{})
|
||||||
writerTerminate := make(chan struct{})
|
writerTerminate := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -686,7 +686,7 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServerReadPlayPlay(t *testing.T) {
|
func TestServerReadPlayPlay(t *testing.T) {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -767,7 +767,7 @@ func TestServerReadPlayPausePlay(t *testing.T) {
|
|||||||
writerDone := make(chan struct{})
|
writerDone := make(chan struct{})
|
||||||
writerTerminate := make(chan struct{})
|
writerTerminate := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -884,7 +884,7 @@ func TestServerReadPlayPausePause(t *testing.T) {
|
|||||||
writerDone := make(chan struct{})
|
writerDone := make(chan struct{})
|
||||||
writerTerminate := make(chan struct{})
|
writerTerminate := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1008,7 +1008,7 @@ func TestServerReadTimeout(t *testing.T) {
|
|||||||
t.Run(proto, func(t *testing.T) {
|
t.Run(proto, func(t *testing.T) {
|
||||||
sessionClosed := make(chan struct{})
|
sessionClosed := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1100,7 +1100,7 @@ func TestServerReadWithoutTeardown(t *testing.T) {
|
|||||||
connClosed := make(chan struct{})
|
connClosed := make(chan struct{})
|
||||||
sessionClosed := make(chan struct{})
|
sessionClosed := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1197,7 +1197,7 @@ func TestServerReadWithoutTeardown(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServerReadUDPChangeConn(t *testing.T) {
|
func TestServerReadUDPChangeConn(t *testing.T) {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1295,7 +1295,7 @@ func TestServerReadUDPChangeConn(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServerReadNonSetuppedPath(t *testing.T) {
|
func TestServerReadNonSetuppedPath(t *testing.T) {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1459,7 +1459,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
|
|||||||
return &ri, ssrcs
|
return &ri, ssrcs
|
||||||
}
|
}
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track, track})
|
stream := NewServerStream(Tracks{track, track})
|
||||||
|
@@ -633,7 +633,7 @@ func TestServerErrorInvalidMethod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -730,7 +730,7 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
|
func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -989,7 +989,7 @@ func TestServerSessionClose(t *testing.T) {
|
|||||||
func TestServerSessionAutoClose(t *testing.T) {
|
func TestServerSessionAutoClose(t *testing.T) {
|
||||||
sessionClosed := make(chan struct{})
|
sessionClosed := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1055,7 +1055,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
|
|||||||
t.Run(string(method), func(t *testing.T) {
|
t.Run(string(method), func(t *testing.T) {
|
||||||
connClosed := make(chan struct{})
|
connClosed := make(chan struct{})
|
||||||
|
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
stream := NewServerStream(Tracks{track})
|
stream := NewServerStream(Tracks{track})
|
||||||
@@ -1096,7 +1096,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
|
|||||||
sxID := ""
|
sxID := ""
|
||||||
|
|
||||||
if method == base.Record {
|
if method == base.Record {
|
||||||
track, err := NewTrackH264(96, []byte("123456"), []byte("123456"))
|
track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tracks := Tracks{track}
|
tracks := Tracks{track}
|
||||||
|
107
track.go
107
track.go
@@ -20,6 +20,20 @@ type Track struct {
|
|||||||
Media *psdp.MediaDescription
|
Media *psdp.MediaDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrackConfigH264 is the configuration of an H264 track.
|
||||||
|
type TrackConfigH264 struct {
|
||||||
|
SPS []byte
|
||||||
|
PPS []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrackConfigAAC is the configuration of an AAC track.
|
||||||
|
type TrackConfigAAC struct {
|
||||||
|
Type int
|
||||||
|
SampleRate int
|
||||||
|
ChannelCount int
|
||||||
|
AOTSpecificConfig []byte
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Track) hasControlAttribute() bool {
|
func (t *Track) hasControlAttribute() bool {
|
||||||
for _, attr := range t.Media.Attributes {
|
for _, attr := range t.Media.Attributes {
|
||||||
if attr.Key == "control" {
|
if attr.Key == "control" {
|
||||||
@@ -127,10 +141,10 @@ func (t *Track) ClockRate() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTrackH264 initializes an H264 track from a SPS and PPS.
|
// NewTrackH264 initializes an H264 track from a SPS and PPS.
|
||||||
func NewTrackH264(payloadType uint8, sps []byte, pps []byte) (*Track, error) {
|
func NewTrackH264(payloadType uint8, conf *TrackConfigH264) (*Track, error) {
|
||||||
spropParameterSets := base64.StdEncoding.EncodeToString(sps) +
|
spropParameterSets := base64.StdEncoding.EncodeToString(conf.SPS) +
|
||||||
"," + base64.StdEncoding.EncodeToString(pps)
|
"," + base64.StdEncoding.EncodeToString(conf.PPS)
|
||||||
profileLevelID := strings.ToUpper(hex.EncodeToString(sps[1:4]))
|
profileLevelID := strings.ToUpper(hex.EncodeToString(conf.SPS[1:4]))
|
||||||
|
|
||||||
typ := strconv.FormatInt(int64(payloadType), 10)
|
typ := strconv.FormatInt(int64(payloadType), 10)
|
||||||
|
|
||||||
@@ -176,21 +190,18 @@ func (t *Track) IsH264() bool {
|
|||||||
return vals[1] == "H264/90000"
|
return vals[1] == "H264/90000"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractDataH264 extracts the SPS and PPS from an H264 track.
|
// ExtractConfigH264 extracts the configuration from an H264 track.
|
||||||
func (t *Track) ExtractDataH264() ([]byte, []byte, error) {
|
func (t *Track) ExtractConfigH264() (*TrackConfigH264, error) {
|
||||||
v, ok := t.Media.Attribute("fmtp")
|
v, ok := t.Media.Attribute("fmtp")
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil, fmt.Errorf("fmtp attribute is missing")
|
return nil, fmt.Errorf("fmtp attribute is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp := strings.SplitN(v, " ", 2)
|
tmp := strings.SplitN(v, " ", 2)
|
||||||
if len(tmp) != 2 {
|
if len(tmp) != 2 {
|
||||||
return nil, nil, fmt.Errorf("invalid fmtp attribute (%v)", v)
|
return nil, fmt.Errorf("invalid fmtp attribute (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sps []byte
|
|
||||||
var pps []byte
|
|
||||||
|
|
||||||
for _, kv := range strings.Split(tmp[1], ";") {
|
for _, kv := range strings.Split(tmp[1], ";") {
|
||||||
kv = strings.Trim(kv, " ")
|
kv = strings.Trim(kv, " ")
|
||||||
|
|
||||||
@@ -200,41 +211,47 @@ func (t *Track) ExtractDataH264() ([]byte, []byte, error) {
|
|||||||
|
|
||||||
tmp := strings.SplitN(kv, "=", 2)
|
tmp := strings.SplitN(kv, "=", 2)
|
||||||
if len(tmp) != 2 {
|
if len(tmp) != 2 {
|
||||||
return nil, nil, fmt.Errorf("invalid fmtp attribute (%v)", v)
|
return nil, fmt.Errorf("invalid fmtp attribute (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tmp[0] == "sprop-parameter-sets" {
|
if tmp[0] == "sprop-parameter-sets" {
|
||||||
tmp := strings.SplitN(tmp[1], ",", 2)
|
tmp := strings.SplitN(tmp[1], ",", 2)
|
||||||
if len(tmp) != 2 {
|
if len(tmp) != 2 {
|
||||||
return nil, nil, fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
|
return nil, fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
sps, err := base64.StdEncoding.DecodeString(tmp[0])
|
||||||
sps, err = base64.StdEncoding.DecodeString(tmp[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
|
return nil, fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pps, err = base64.StdEncoding.DecodeString(tmp[1])
|
pps, err := base64.StdEncoding.DecodeString(tmp[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
|
return nil, fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf := &TrackConfigH264{
|
||||||
|
SPS: sps,
|
||||||
|
PPS: pps,
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sps == nil || pps == nil {
|
return nil, fmt.Errorf("sprop-parameter-sets is missing (%v)", v)
|
||||||
return nil, nil, fmt.Errorf("sprop-parameter-sets is missing (%v)", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sps, pps, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTrackAAC initializes an AAC track from a configuration.
|
// NewTrackAAC initializes an AAC track.
|
||||||
func NewTrackAAC(payloadType uint8, config []byte) (*Track, error) {
|
func NewTrackAAC(payloadType uint8, conf *TrackConfigAAC) (*Track, error) {
|
||||||
var conf rtpaac.MPEG4AudioConfig
|
mpegConf, err := rtpaac.MPEG4AudioConfig{
|
||||||
err := conf.Decode(config)
|
Type: rtpaac.MPEG4AudioType(conf.Type),
|
||||||
|
SampleRate: conf.SampleRate,
|
||||||
|
ChannelCount: conf.ChannelCount,
|
||||||
|
AOTSpecificConfig: conf.AOTSpecificConfig,
|
||||||
|
}.Encode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid MPEG-4 Audio config: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := strconv.FormatInt(int64(payloadType), 10)
|
typ := strconv.FormatInt(int64(payloadType), 10)
|
||||||
@@ -259,7 +276,7 @@ func NewTrackAAC(payloadType uint8, config []byte) (*Track, error) {
|
|||||||
"sizelength=13; " +
|
"sizelength=13; " +
|
||||||
"indexlength=3; " +
|
"indexlength=3; " +
|
||||||
"indexdeltalength=3; " +
|
"indexdeltalength=3; " +
|
||||||
"config=" + hex.EncodeToString(config),
|
"config=" + hex.EncodeToString(mpegConf),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -285,8 +302,8 @@ func (t *Track) IsAAC() bool {
|
|||||||
return strings.HasPrefix(strings.ToLower(vals[1]), "mpeg4-generic/")
|
return strings.HasPrefix(strings.ToLower(vals[1]), "mpeg4-generic/")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractDataAAC extracts the config from an AAC track.
|
// ExtractConfigAAC extracts the configuration from an AAC track.
|
||||||
func (t *Track) ExtractDataAAC() ([]byte, error) {
|
func (t *Track) ExtractConfigAAC() (*TrackConfigAAC, error) {
|
||||||
v, ok := t.Media.Attribute("fmtp")
|
v, ok := t.Media.Attribute("fmtp")
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("fmtp attribute is missing")
|
return nil, fmt.Errorf("fmtp attribute is missing")
|
||||||
@@ -297,8 +314,6 @@ func (t *Track) ExtractDataAAC() ([]byte, error) {
|
|||||||
return nil, fmt.Errorf("invalid fmtp (%v)", v)
|
return nil, fmt.Errorf("invalid fmtp (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
var config []byte
|
|
||||||
|
|
||||||
for _, kv := range strings.Split(tmp[1], ";") {
|
for _, kv := range strings.Split(tmp[1], ";") {
|
||||||
kv = strings.Trim(kv, " ")
|
kv = strings.Trim(kv, " ")
|
||||||
|
|
||||||
@@ -312,19 +327,29 @@ func (t *Track) ExtractDataAAC() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmp[0] == "config" {
|
if tmp[0] == "config" {
|
||||||
var err error
|
enc, err := hex.DecodeString(tmp[1])
|
||||||
config, err = hex.DecodeString(tmp[1])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid config (%v)", v)
|
return nil, fmt.Errorf("invalid AAC config (%v)", tmp[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mpegConf rtpaac.MPEG4AudioConfig
|
||||||
|
err = mpegConf.Decode(enc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid AAC config (%v)", tmp[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := &TrackConfigAAC{
|
||||||
|
Type: int(mpegConf.Type),
|
||||||
|
SampleRate: mpegConf.SampleRate,
|
||||||
|
ChannelCount: mpegConf.ChannelCount,
|
||||||
|
AOTSpecificConfig: mpegConf.AOTSpecificConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config == nil {
|
return nil, fmt.Errorf("config is missing (%v)", v)
|
||||||
return nil, fmt.Errorf("config is missing (%v)", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tracks is a list of tracks.
|
// Tracks is a list of tracks.
|
||||||
|
@@ -225,7 +225,7 @@ func TestTrackH264New(t *testing.T) {
|
|||||||
0x68, 0xee, 0x3c, 0x80,
|
0x68, 0xee, 0x3c, 0x80,
|
||||||
}
|
}
|
||||||
|
|
||||||
tr, err := NewTrackH264(96, sps, pps)
|
tr, err := NewTrackH264(96, &TrackConfigH264{sps, pps})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &Track{
|
require.Equal(t, &Track{
|
||||||
Media: &psdp.MediaDescription{
|
Media: &psdp.MediaDescription{
|
||||||
@@ -282,12 +282,11 @@ func TestTrackIsH264(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrackH264Extract(t *testing.T) {
|
func TestTrackExtractConfigH264(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
track *Track
|
track *Track
|
||||||
sps []byte
|
conf *TrackConfigH264
|
||||||
pps []byte
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"generic",
|
"generic",
|
||||||
@@ -310,13 +309,15 @@ func TestTrackH264Extract(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[]byte{
|
&TrackConfigH264{
|
||||||
0x67, 0x64, 0x00, 0x0c, 0xac, 0x3b, 0x50, 0xb0,
|
SPS: []byte{
|
||||||
0x4b, 0x42, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
|
0x67, 0x64, 0x00, 0x0c, 0xac, 0x3b, 0x50, 0xb0,
|
||||||
0x00, 0x03, 0x00, 0x3d, 0x08,
|
0x4b, 0x42, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
|
||||||
},
|
0x00, 0x03, 0x00, 0x3d, 0x08,
|
||||||
[]byte{
|
},
|
||||||
0x68, 0xee, 0x3c, 0x80,
|
PPS: []byte{
|
||||||
|
0x68, 0xee, 0x3c, 0x80,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -340,27 +341,28 @@ func TestTrackH264Extract(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[]byte{
|
&TrackConfigH264{
|
||||||
0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50,
|
SPS: []byte{
|
||||||
0x05, 0xbb, 0x01, 0x6c, 0x80, 0x00, 0x00, 0x03,
|
0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50,
|
||||||
0x00, 0x80, 0x00, 0x00, 0x1e, 0x07, 0x8c, 0x18,
|
0x05, 0xbb, 0x01, 0x6c, 0x80, 0x00, 0x00, 0x03,
|
||||||
0xcb,
|
0x00, 0x80, 0x00, 0x00, 0x1e, 0x07, 0x8c, 0x18,
|
||||||
},
|
0xcb,
|
||||||
[]byte{
|
},
|
||||||
0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0,
|
PPS: []byte{
|
||||||
|
0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
sps, pps, err := ca.track.ExtractDataH264()
|
conf, err := ca.track.ExtractConfigH264()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, ca.sps, sps)
|
require.Equal(t, ca.conf, conf)
|
||||||
require.Equal(t, ca.pps, pps)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrackH264ExtractErrors(t *testing.T) {
|
func TestTrackConfigH264Errors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
track *Track
|
track *Track
|
||||||
@@ -525,14 +527,14 @@ func TestTrackH264ExtractErrors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
_, _, err := ca.track.ExtractDataH264()
|
_, err := ca.track.ExtractConfigH264()
|
||||||
require.Equal(t, ca.err, err.Error())
|
require.Equal(t, ca.err, err.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrackAACNew(t *testing.T) {
|
func TestTrackAACNew(t *testing.T) {
|
||||||
tr, err := NewTrackAAC(96, []byte{17, 144})
|
track, err := NewTrackAAC(96, &TrackConfigAAC{Type: 2, SampleRate: 48000, ChannelCount: 2})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, &Track{
|
require.Equal(t, &Track{
|
||||||
Media: &psdp.MediaDescription{
|
Media: &psdp.MediaDescription{
|
||||||
@@ -552,7 +554,7 @@ func TestTrackAACNew(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, tr)
|
}, track)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrackIsAAC(t *testing.T) {
|
func TestTrackIsAAC(t *testing.T) {
|
||||||
@@ -611,11 +613,11 @@ func TestTrackIsAAC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrackAACExtract(t *testing.T) {
|
func TestTrackExtractConfigAAC(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
track *Track
|
track *Track
|
||||||
config []byte
|
conf *TrackConfigAAC
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"generic",
|
"generic",
|
||||||
@@ -638,7 +640,11 @@ func TestTrackAACExtract(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[]byte{17, 144},
|
&TrackConfigAAC{
|
||||||
|
Type: 2,
|
||||||
|
SampleRate: 48000,
|
||||||
|
ChannelCount: 2,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"vlc rtsp server",
|
"vlc rtsp server",
|
||||||
@@ -661,18 +667,22 @@ func TestTrackAACExtract(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[]byte{17, 144},
|
&TrackConfigAAC{
|
||||||
|
Type: 2,
|
||||||
|
SampleRate: 48000,
|
||||||
|
ChannelCount: 2,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
config, err := ca.track.ExtractDataAAC()
|
conf, err := ca.track.ExtractConfigAAC()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, ca.config, config)
|
require.Equal(t, ca.conf, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrackAACExtractErrors(t *testing.T) {
|
func TestTrackConfigAACErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
track *Track
|
track *Track
|
||||||
@@ -787,11 +797,11 @@ func TestTrackAACExtractErrors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"invalid config (96 profile-level-id=1; config=zz)",
|
"invalid AAC config (zz)",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
_, err := ca.track.ExtractDataAAC()
|
_, err := ca.track.ExtractConfigAAC()
|
||||||
require.Equal(t, ca.err, err.Error())
|
require.Equal(t, ca.err, err.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user