diff --git a/README.md b/README.md index 08dba3f9..ba0f9253 100644 --- a/README.md +++ b/README.md @@ -100,35 +100,36 @@ In RTSP, media streams are routed between server and clients by using RTP packet ### Video -|codec|rtp format|documentation|encoder and decoder available| -|-----|----------|-------------|-----------------------------| -|AV1|AV1|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#AV1)|:heavy_check_mark:| -|VP9|VP9|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#VP9)|:heavy_check_mark:| -|VP8|VP8|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#VP8)|:heavy_check_mark:| -|H265|H265|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#H265)|:heavy_check_mark:| -|H264|H264|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#H264)|:heavy_check_mark:| -|MPEG-2 Video|unnamed|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG2Video)|| -|MPEG-4 Video (H263, Xvid)|MP4V-ES|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG4VideoES)|:heavy_check_mark:| -|M-JPEG|JPEG|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MJPEG)|:heavy_check_mark:| +|format / codec|variant|documentation|encoder and decoder available| +|--------------|-------|-------------|-----------------------------| +|AV1||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#AV1)|:heavy_check_mark:| +|VP9||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#VP9)|:heavy_check_mark:| +|VP8||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#VP8)|:heavy_check_mark:| +|H265||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#H265)|:heavy_check_mark:| +|H264||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#H264)|:heavy_check_mark:| +|MPEG-4 Video (H263, Xvid)||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG4VideoES)|:heavy_check_mark:| +|MPEG-2 Video||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG2Video)|| +|M-JPEG||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MJPEG)|:heavy_check_mark:| ### Audio -|codec|rtp format|documentation|encoder and decoder available| -|-----|----------|-------------|-----------------------------| -|Opus|opus|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#Opus)|:heavy_check_mark:| -|Vorbis|VORBIS|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#Vorbis)|| -|MPEG-4 Audio (AAC)|mpeg4-generic|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG4AudioGeneric)|:heavy_check_mark:| -|MPEG-4 Audio (AAC)|MP4A-LATM|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG4AudioLATM)|:heavy_check_mark:| -|MPEG-1/2 Audio (MP3)|unnamed|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEG2Audio)|:heavy_check_mark:| -|G722|unnamed|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#G722)|:heavy_check_mark:| -|G711 (PCMA, PCMU)|unnamed|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#G711)|:heavy_check_mark:| -|LPCM|L8/L16/L24|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#LPCM)|:heavy_check_mark:| +|format / codec|variant|documentation|encoder and decoder available| +|--------------|-------|-------------|-----------------------------| +|Opus||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#Opus)|:heavy_check_mark:| +|Vorbis||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#Vorbis)|| +|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#MPEG2Audio)|:heavy_check_mark:| +|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:| +|LPCM||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#LPCM)|:heavy_check_mark:| ### Mixed -|codec|rtp format|documentation|encoder and decoder available| -|-----|----------|-------------|-----------------------------| -|MPEG-TS|MP2T|[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEGTS)|| +|format / codec|variant|documentation|encoder and decoder available| +|--------------|-------|-------------|-----------------------------| +|MPEG-TS||[link](https://pkg.go.dev/github.com/bluenviron/gortsplib/v3/pkg/formats#MPEGTS)|| ## Standards diff --git a/pkg/formats/format.go b/pkg/formats/format.go index 219aa95c..5df22a70 100644 --- a/pkg/formats/format.go +++ b/pkg/formats/format.go @@ -87,6 +87,16 @@ func Unmarshal(mediaType string, payloadType uint8, rtpMap string, fmtp map[stri case payloadType == 9: return &G722{} + case (codec == "g726-16" || + codec == "g726-24" || + codec == "g726-32" || + codec == "g726-40" || + codec == "aal2-g726-16" || + codec == "aal2-g726-24" || + codec == "aal2-g726-32" || + codec == "aal2-g726-40") && clock == "8000": + return &G726{} + case payloadType == 14: return &MPEG2Audio{} diff --git a/pkg/formats/format_test.go b/pkg/formats/format_test.go index 4f84d08d..602d1825 100644 --- a/pkg/formats/format_test.go +++ b/pkg/formats/format_test.go @@ -58,6 +58,72 @@ var casesFormat = []struct { "G722/8000", nil, }, + { + "audio g726 le 1", + "audio", + 97, + "G726-16/8000", + nil, + &G726{ + PayloadTyp: 97, + BitRate: 16, + }, + "G726-16/8000", + nil, + }, + { + "audio g726 le 2", + "audio", + 97, + "G726-24/8000", + nil, + &G726{ + PayloadTyp: 97, + BitRate: 24, + }, + "G726-24/8000", + nil, + }, + { + "audio g726 le 3", + "audio", + 97, + "G726-32/8000", + nil, + &G726{ + PayloadTyp: 97, + BitRate: 32, + }, + "G726-32/8000", + nil, + }, + { + "audio g726 le 4", + "audio", + 97, + "G726-40/8000", + nil, + &G726{ + PayloadTyp: 97, + BitRate: 40, + }, + "G726-40/8000", + nil, + }, + { + "audio g726 be", + "audio", + 97, + "AAL2-G726-32/8000", + nil, + &G726{ + PayloadTyp: 97, + BitRate: 32, + BigEndian: true, + }, + "AAL2-G726-32/8000", + nil, + }, { "audio lpcm 8", "audio", diff --git a/pkg/formats/g726.go b/pkg/formats/g726.go new file mode 100644 index 00000000..a15fb9f8 --- /dev/null +++ b/pkg/formats/g726.go @@ -0,0 +1,80 @@ +package formats + +import ( + "strconv" + "strings" + + "github.com/pion/rtp" +) + +// G726 is a RTP format for the G726 codec. +// Specification: https://datatracker.ietf.org/doc/html/rfc3551 +type G726 struct { + PayloadTyp uint8 + BitRate int + BigEndian bool +} + +func (f *G726) unmarshal(payloadType uint8, _ string, codec string, _ string, _ map[string]string) error { + f.PayloadTyp = payloadType + + if strings.HasPrefix(codec, "aal2-") { + f.BigEndian = true + } + + switch { + case strings.HasSuffix(codec, "-16"): + f.BitRate = 16 + case strings.HasSuffix(codec, "-24"): + f.BitRate = 24 + case strings.HasSuffix(codec, "-32"): + f.BitRate = 32 + default: + f.BitRate = 40 + } + + return nil +} + +// Codec implements Format. +func (f *G726) Codec() string { + return "G726" +} + +// String implements Format. +// +// Deprecated: replaced by Codec(). +func (f *G726) String() string { + return f.Codec() +} + +// ClockRate implements Format. +func (f *G726) ClockRate() int { + return 8000 +} + +// PayloadType implements Format. +func (f *G726) PayloadType() uint8 { + return f.PayloadTyp +} + +// RTPMap implements Format. +func (f *G726) RTPMap() string { + codec := "" + + if f.BigEndian { + codec += "AAL2-" + } + + return codec + "G726-" + strconv.FormatInt(int64(f.BitRate), 10) + "/8000" +} + +// FMTP implements Format. +func (f *G726) FMTP() map[string]string { + return nil +} + +// PTSEqualsDTS implements Format. +func (f *G726) PTSEqualsDTS(*rtp.Packet) bool { + return true +} diff --git a/pkg/formats/g726_test.go b/pkg/formats/g726_test.go new file mode 100644 index 00000000..afee52d7 --- /dev/null +++ b/pkg/formats/g726_test.go @@ -0,0 +1,15 @@ +package formats + +import ( + "testing" + + "github.com/pion/rtp" + "github.com/stretchr/testify/require" +) + +func TestG726Attributes(t *testing.T) { + format := &G726{} + require.Equal(t, "G726", format.Codec()) + require.Equal(t, 8000, format.ClockRate()) + require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{})) +}