From abe875deb8605476dd02eb352ddff6fa249f8291 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:33:09 +0200 Subject: [PATCH] add Speex format --- README.md | 4 +- pkg/formats/format.go | 3 ++ pkg/formats/format_test.go | 18 ++++++++ pkg/formats/speex.go | 86 ++++++++++++++++++++++++++++++++++++++ pkg/formats/speex_test.go | 18 ++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 pkg/formats/speex.go create mode 100644 pkg/formats/speex_test.go diff --git a/README.md b/README.md index 147dfdd6..188afe89 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ https://pkg.go.dev/github.com/bluenviron/gortsplib/v3#pkg-index ## RTP Payload Formats -In RTSP, media streams are routed between server and clients by using RTP packets. In order to decode a stream, RTP packets must be converted into codec-specific frames. This conversion happens by using a RTP payload format. This library recognizes the following formats: +In RTSP, media streams are routed between server and clients by using RTP packets. Conversion between RTP packets and codec-specific frames happens by using a payload format. This library recognizes the following payload formats: ### Video @@ -120,6 +120,7 @@ In RTSP, media streams are routed between server and clients by using RTP packet |MPEG-4 Audio (AAC)|Generic (RFC3640)|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG4AudioGeneric)|:heavy_check_mark:| |MPEG-4 Audio (AAC)|LATM (RFC6416)|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG4AudioLATM)|:heavy_check_mark:| |MPEG-1/2 Audio (MP3)||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG1Audio)|:heavy_check_mark:| +|Speex||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#Speex)|| |G726||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#G726)|| |G722||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#G722)|:heavy_check_mark:| |G711 (PCMA, PCMU)||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#G711)|:heavy_check_mark:| @@ -148,6 +149,7 @@ In RTSP, media streams are routed between server and clients by using RTP packet * [RFC5215, RTP Payload Format for Vorbis Encoded Audio](https://datatracker.ietf.org/doc/html/rfc5215) * [RFC7587, RTP Payload Format for the Opus Speech and Audio Codec](https://datatracker.ietf.org/doc/html/rfc7587) * [RFC3640, RTP Payload Format for Transport of MPEG-4 Elementary Streams](https://datatracker.ietf.org/doc/html/rfc3640) +* [RFC5574, RTP Payload Format for the Speex Codec](https://datatracker.ietf.org/doc/html/rfc5574) * [RTP Payload Format For AV1 (v1.0)](https://aomediacodec.github.io/av1-rtp-spec/) * [Codec standards](https://github.com/bluenviron/mediacommon#standards) * [Golang project layout](https://github.com/golang-standards/project-layout) diff --git a/pkg/formats/format.go b/pkg/formats/format.go index 62d430c3..688fa94b 100644 --- a/pkg/formats/format.go +++ b/pkg/formats/format.go @@ -109,6 +109,9 @@ func Unmarshal(mediaType string, payloadType uint8, rtpMap string, fmtp map[stri case codec == "mp4a-latm": return &MPEG4AudioLATM{} + case codec == "speex": + return &Speex{} + case codec == "vorbis": return &Vorbis{} diff --git a/pkg/formats/format_test.go b/pkg/formats/format_test.go index e2acb9ff..f6259d13 100644 --- a/pkg/formats/format_test.go +++ b/pkg/formats/format_test.go @@ -526,6 +526,24 @@ var casesFormat = []struct { "config": "400023103fc0", }, }, + { + "audio speex", + "audio", + 96, + "speex/16000", + map[string]string{ + "vbr": "off", + }, + &Speex{ + PayloadTyp: 96, + SampleRate: 16000, + VBR: boolPtr(false), + }, + "speex/16000", + map[string]string{ + "vbr": "off", + }, + }, { "audio vorbis", "audio", diff --git a/pkg/formats/speex.go b/pkg/formats/speex.go new file mode 100644 index 00000000..5484df1a --- /dev/null +++ b/pkg/formats/speex.go @@ -0,0 +1,86 @@ +package formats + +import ( + "fmt" + "strconv" + + "github.com/pion/rtp" +) + +// Speex is a RTP format for the Speex codec. +// Specification: https://datatracker.ietf.org/doc/html/rfc5574 +type Speex struct { + PayloadTyp uint8 + SampleRate int + VBR *bool +} + +func (f *Speex) unmarshal(payloadType uint8, clock string, _ string, _ string, fmtp map[string]string) error { + f.PayloadTyp = payloadType + + sampleRate, err := strconv.ParseUint(clock, 10, 31) + if err != nil { + return err + } + f.SampleRate = int(sampleRate) + + for key, val := range fmtp { + if key == "vbr" { + if val != "on" && val != "off" { + return fmt.Errorf("invalid vbr value: %v", val) + } + + v := (val == "on") + f.VBR = &v + } + } + + return nil +} + +// Codec implements Format. +func (f *Speex) Codec() string { + return "Speex" +} + +// String implements Format. +// +// Deprecated: replaced by Codec(). +func (f *Speex) String() string { + return f.Codec() +} + +// ClockRate implements Format. +func (f *Speex) ClockRate() int { + return f.SampleRate +} + +// PayloadType implements Format. +func (f *Speex) PayloadType() uint8 { + return f.PayloadTyp +} + +// RTPMap implements Format. +func (f *Speex) RTPMap() string { + return "speex/" + strconv.FormatInt(int64(f.SampleRate), 10) +} + +// FMTP implements Format. +func (f *Speex) FMTP() map[string]string { + fmtp := make(map[string]string) + + if f.VBR != nil { + if *f.VBR { + fmtp["vbr"] = "on" + } else { + fmtp["vbr"] = "off" + } + } + + return fmtp +} + +// PTSEqualsDTS implements Format. +func (f *Speex) PTSEqualsDTS(*rtp.Packet) bool { + return true +} diff --git a/pkg/formats/speex_test.go b/pkg/formats/speex_test.go new file mode 100644 index 00000000..2f057a08 --- /dev/null +++ b/pkg/formats/speex_test.go @@ -0,0 +1,18 @@ +package formats + +import ( + "testing" + + "github.com/pion/rtp" + "github.com/stretchr/testify/require" +) + +func TestSpeexAttributes(t *testing.T) { + format := &Speex{ + PayloadTyp: 96, + SampleRate: 16000, + } + require.Equal(t, "Speex", format.Codec()) + require.Equal(t, 16000, format.ClockRate()) + require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{})) +}