github.com/pion/webrtc/v4@v4.0.1/internal/fmtp/fmtp.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 // Package fmtp implements per codec parsing of fmtp lines 5 package fmtp 6 7 import ( 8 "strings" 9 ) 10 11 func parseParameters(line string) map[string]string { 12 parameters := make(map[string]string) 13 14 for _, p := range strings.Split(line, ";") { 15 pp := strings.SplitN(strings.TrimSpace(p), "=", 2) 16 key := strings.ToLower(pp[0]) 17 var value string 18 if len(pp) > 1 { 19 value = pp[1] 20 } 21 parameters[key] = value 22 } 23 24 return parameters 25 } 26 27 // FMTP interface for implementing custom 28 // FMTP parsers based on MimeType 29 type FMTP interface { 30 // MimeType returns the MimeType associated with 31 // the fmtp 32 MimeType() string 33 // Match compares two fmtp descriptions for 34 // compatibility based on the MimeType 35 Match(f FMTP) bool 36 // Parameter returns a value for the associated key 37 // if contained in the parsed fmtp string 38 Parameter(key string) (string, bool) 39 } 40 41 // Parse parses an fmtp string based on the MimeType 42 func Parse(mimeType, line string) FMTP { 43 var f FMTP 44 45 parameters := parseParameters(line) 46 47 switch { 48 case strings.EqualFold(mimeType, "video/h264"): 49 f = &h264FMTP{ 50 parameters: parameters, 51 } 52 53 case strings.EqualFold(mimeType, "video/vp9"): 54 f = &vp9FMTP{ 55 parameters: parameters, 56 } 57 58 case strings.EqualFold(mimeType, "video/av1"): 59 f = &av1FMTP{ 60 parameters: parameters, 61 } 62 63 default: 64 f = &genericFMTP{ 65 mimeType: mimeType, 66 parameters: parameters, 67 } 68 } 69 70 return f 71 } 72 73 type genericFMTP struct { 74 mimeType string 75 parameters map[string]string 76 } 77 78 func (g *genericFMTP) MimeType() string { 79 return g.mimeType 80 } 81 82 // Match returns true if g and b are compatible fmtp descriptions 83 // The generic implementation is used for MimeTypes that are not defined 84 func (g *genericFMTP) Match(b FMTP) bool { 85 c, ok := b.(*genericFMTP) 86 if !ok { 87 return false 88 } 89 90 if !strings.EqualFold(g.mimeType, c.MimeType()) { 91 return false 92 } 93 94 for k, v := range g.parameters { 95 if vb, ok := c.parameters[k]; ok && !strings.EqualFold(vb, v) { 96 return false 97 } 98 } 99 100 for k, v := range c.parameters { 101 if va, ok := g.parameters[k]; ok && !strings.EqualFold(va, v) { 102 return false 103 } 104 } 105 106 return true 107 } 108 109 func (g *genericFMTP) Parameter(key string) (string, bool) { 110 v, ok := g.parameters[key] 111 return v, ok 112 }