streaming

Media streaming and broadcast systems in Go
Log | Files | Refs | README | LICENSE

commit 34e2532ac4dd304348fb3babce0f85c8b272610d
parent fd089add456294f2b1ac042ab8f58324f8cc31d0
Author: Oliver Lowe <o@olowe.co>
Date:   Fri,  5 Jul 2024 12:34:02 +1000

sdp: add basic media description parsing

Not fully tested; need to test e.g. port count. The Media struct is
probably not complete yet, either, as we may need to add connection
info (the data from the "c=" line from the SDP text). For now we parse
the example SDP text from the RFC, so worth a commit!

Diffstat:
Msdp/sdp.go | 54++++++++++++++++++++++++++++++++++++++++++++++++++----
Msdp/sdp_test.go | 5+++++
2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/sdp/sdp.go b/sdp/sdp.go @@ -22,7 +22,7 @@ type Session struct { Email *mail.Address Phone string Bandwidth *Bandwidth - Media []MediaInfo + Media []Media // TODO(otl): add rest of fields } @@ -220,8 +220,54 @@ func parseBandwidth(s string) (Bandwidth, error) { return Bandwidth{t, kbps * 1e3}, nil } -type MediaInfo struct{} +type Media struct { + Type string // TODO(otl): new type mediaType? + Port int + PortCount int + Protocol uint8 + Format []string +} + +const ( + ProtoUDP uint8 = iota + ProtoRTP + ProtoRTPSecure + ProtoRTPSecureFeedback +) + +func parseMedia(s string) (Media, error) { + fields := strings.Fields(s) + if len(fields) < 4 { + return Media{}, fmt.Errorf("found %d fields, need at least %d", len(fields), 4) + } + m := Media{Type: fields[0]} + + p, n, found := strings.Cut(fields[1], "/") + var err error + m.Port, err = strconv.Atoi(p) + if err != nil { + return Media{}, fmt.Errorf("parse port: %w", err) + } + if found { + m.PortCount, err = strconv.Atoi(n) + if err != nil { + return Media{}, fmt.Errorf("parse port count: %w", err) + } + } + + switch fields[2] { + case "udp": + m.Protocol = ProtoUDP + case "RTP/AVP": + m.Protocol = ProtoRTP + case "RTP/SAVP": + m.Protocol = ProtoRTPSecure + case "RTP/SAVPF": + m.Protocol = ProtoRTPSecureFeedback + default: + return Media{}, fmt.Errorf("unknown protocol %s", fields[2]) + } -func parseMedia(s string) (MediaInfo, error) { - return MediaInfo{}, fmt.Errorf("not yet implemented") + m.Format = fields[3:] + return m, nil } diff --git a/sdp/sdp_test.go b/sdp/sdp_test.go @@ -27,6 +27,11 @@ func TestReadSession(t *testing.T) { }, Email: &mail.Address{"Jane Doe", "jane@jdoe.example.com"}, Phone: "+16175556011", + Media: []Media{ + {"audio", 49170, 0, ProtoRTP, []string{"0"}}, + {"audio", 49180, 0, ProtoRTP, []string{"0"}}, + {"video", 51372, 0, ProtoRTP, []string{"99"}}, + }, }, }, {