github.com/pion/webrtc/v3@v3.2.24/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  // FMTP interface for implementing custom
    12  // FMTP parsers based on MimeType
    13  type FMTP interface {
    14  	// MimeType returns the MimeType associated with
    15  	// the fmtp
    16  	MimeType() string
    17  	// Match compares two fmtp descriptions for
    18  	// compatibility based on the MimeType
    19  	Match(f FMTP) bool
    20  	// Parameter returns a value for the associated key
    21  	// if contained in the parsed fmtp string
    22  	Parameter(key string) (string, bool)
    23  }
    24  
    25  // Parse parses an fmtp string based on the MimeType
    26  func Parse(mimetype, line string) FMTP {
    27  	var f FMTP
    28  
    29  	parameters := make(map[string]string)
    30  
    31  	for _, p := range strings.Split(line, ";") {
    32  		pp := strings.SplitN(strings.TrimSpace(p), "=", 2)
    33  		key := strings.ToLower(pp[0])
    34  		var value string
    35  		if len(pp) > 1 {
    36  			value = pp[1]
    37  		}
    38  		parameters[key] = value
    39  	}
    40  
    41  	switch {
    42  	case strings.EqualFold(mimetype, "video/h264"):
    43  		f = &h264FMTP{
    44  			parameters: parameters,
    45  		}
    46  	default:
    47  		f = &genericFMTP{
    48  			mimeType:   mimetype,
    49  			parameters: parameters,
    50  		}
    51  	}
    52  
    53  	return f
    54  }
    55  
    56  type genericFMTP struct {
    57  	mimeType   string
    58  	parameters map[string]string
    59  }
    60  
    61  func (g *genericFMTP) MimeType() string {
    62  	return g.mimeType
    63  }
    64  
    65  // Match returns true if g and b are compatible fmtp descriptions
    66  // The generic implementation is used for MimeTypes that are not defined
    67  func (g *genericFMTP) Match(b FMTP) bool {
    68  	c, ok := b.(*genericFMTP)
    69  	if !ok {
    70  		return false
    71  	}
    72  
    73  	if !strings.EqualFold(g.mimeType, c.MimeType()) {
    74  		return false
    75  	}
    76  
    77  	for k, v := range g.parameters {
    78  		if vb, ok := c.parameters[k]; ok && !strings.EqualFold(vb, v) {
    79  			return false
    80  		}
    81  	}
    82  
    83  	for k, v := range c.parameters {
    84  		if va, ok := g.parameters[k]; ok && !strings.EqualFold(va, v) {
    85  			return false
    86  		}
    87  	}
    88  
    89  	return true
    90  }
    91  
    92  func (g *genericFMTP) Parameter(key string) (string, bool) {
    93  	v, ok := g.parameters[key]
    94  	return v, ok
    95  }