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  }