fmtp.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Package fmtp implements per codec parsing of fmtp lines
  2. package fmtp
  3. import (
  4. "strings"
  5. )
  6. // FMTP interface for implementing custom
  7. // FMTP parsers based on MimeType
  8. type FMTP interface {
  9. // MimeType returns the MimeType associated with
  10. // the fmtp
  11. MimeType() string
  12. // Match compares two fmtp descriptions for
  13. // compatibility based on the MimeType
  14. Match(f FMTP) bool
  15. // Parameter returns a value for the associated key
  16. // if contained in the parsed fmtp string
  17. Parameter(key string) (string, bool)
  18. }
  19. // Parse parses an fmtp string based on the MimeType
  20. func Parse(mimetype, line string) FMTP {
  21. var f FMTP
  22. parameters := make(map[string]string)
  23. for _, p := range strings.Split(line, ";") {
  24. pp := strings.SplitN(strings.TrimSpace(p), "=", 2)
  25. key := strings.ToLower(pp[0])
  26. var value string
  27. if len(pp) > 1 {
  28. value = pp[1]
  29. }
  30. parameters[key] = value
  31. }
  32. switch {
  33. case strings.EqualFold(mimetype, "video/h264"):
  34. f = &h264FMTP{
  35. parameters: parameters,
  36. }
  37. default:
  38. f = &genericFMTP{
  39. mimeType: mimetype,
  40. parameters: parameters,
  41. }
  42. }
  43. return f
  44. }
  45. type genericFMTP struct {
  46. mimeType string
  47. parameters map[string]string
  48. }
  49. func (g *genericFMTP) MimeType() string {
  50. return g.mimeType
  51. }
  52. // Match returns true if g and b are compatible fmtp descriptions
  53. // The generic implementation is used for MimeTypes that are not defined
  54. func (g *genericFMTP) Match(b FMTP) bool {
  55. c, ok := b.(*genericFMTP)
  56. if !ok {
  57. return false
  58. }
  59. if !strings.EqualFold(g.mimeType, c.MimeType()) {
  60. return false
  61. }
  62. for k, v := range g.parameters {
  63. if vb, ok := c.parameters[k]; ok && !strings.EqualFold(vb, v) {
  64. return false
  65. }
  66. }
  67. for k, v := range c.parameters {
  68. if va, ok := g.parameters[k]; ok && !strings.EqualFold(va, v) {
  69. return false
  70. }
  71. }
  72. return true
  73. }
  74. func (g *genericFMTP) Parameter(key string) (string, bool) {
  75. v, ok := g.parameters[key]
  76. return v, ok
  77. }