extmap.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package sdp
  4. import (
  5. "fmt"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. )
  10. // Default ext values
  11. const (
  12. DefExtMapValueABSSendTime = 1
  13. DefExtMapValueTransportCC = 2
  14. DefExtMapValueSDESMid = 3
  15. DefExtMapValueSDESRTPStreamID = 4
  16. ABSSendTimeURI = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time"
  17. TransportCCURI = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
  18. SDESMidURI = "urn:ietf:params:rtp-hdrext:sdes:mid"
  19. SDESRTPStreamIDURI = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"
  20. AudioLevelURI = "urn:ietf:params:rtp-hdrext:ssrc-audio-level"
  21. )
  22. // ExtMap represents the activation of a single RTP header extension
  23. type ExtMap struct {
  24. Value int
  25. Direction Direction
  26. URI *url.URL
  27. ExtAttr *string
  28. }
  29. // Clone converts this object to an Attribute
  30. func (e *ExtMap) Clone() Attribute {
  31. return Attribute{Key: "extmap", Value: e.string()}
  32. }
  33. // Unmarshal creates an Extmap from a string
  34. func (e *ExtMap) Unmarshal(raw string) error {
  35. parts := strings.SplitN(raw, ":", 2)
  36. if len(parts) != 2 {
  37. return fmt.Errorf("%w: %v", errSyntaxError, raw)
  38. }
  39. fields := strings.Fields(parts[1])
  40. if len(fields) < 2 {
  41. return fmt.Errorf("%w: %v", errSyntaxError, raw)
  42. }
  43. valdir := strings.Split(fields[0], "/")
  44. value, err := strconv.ParseInt(valdir[0], 10, 64)
  45. if (value < 1) || (value > 246) {
  46. return fmt.Errorf("%w: %v -- extmap key must be in the range 1-256", errSyntaxError, valdir[0])
  47. }
  48. if err != nil {
  49. return fmt.Errorf("%w: %v", errSyntaxError, valdir[0])
  50. }
  51. var direction Direction
  52. if len(valdir) == 2 {
  53. direction, err = NewDirection(valdir[1])
  54. if err != nil {
  55. return err
  56. }
  57. }
  58. uri, err := url.Parse(fields[1])
  59. if err != nil {
  60. return err
  61. }
  62. if len(fields) == 3 {
  63. tmp := fields[2]
  64. e.ExtAttr = &tmp
  65. }
  66. e.Value = int(value)
  67. e.Direction = direction
  68. e.URI = uri
  69. return nil
  70. }
  71. // Marshal creates a string from an ExtMap
  72. func (e *ExtMap) Marshal() string {
  73. return e.Name() + ":" + e.string()
  74. }
  75. func (e *ExtMap) string() string {
  76. output := fmt.Sprintf("%d", e.Value)
  77. dirstring := e.Direction.String()
  78. if dirstring != directionUnknownStr {
  79. output += "/" + dirstring
  80. }
  81. if e.URI != nil {
  82. output += " " + e.URI.String()
  83. }
  84. if e.ExtAttr != nil {
  85. output += " " + *e.ExtAttr
  86. }
  87. return output
  88. }
  89. // Name returns the constant name of this object
  90. func (e *ExtMap) Name() string {
  91. return "extmap"
  92. }