github.com/pion/webrtc/v4@v4.0.1/internal/fmtp/h264.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  package fmtp
     5  
     6  import (
     7  	"encoding/hex"
     8  )
     9  
    10  func profileLevelIDMatches(a, b string) bool {
    11  	aa, err := hex.DecodeString(a)
    12  	if err != nil || len(aa) < 2 {
    13  		return false
    14  	}
    15  	bb, err := hex.DecodeString(b)
    16  	if err != nil || len(bb) < 2 {
    17  		return false
    18  	}
    19  	return aa[0] == bb[0] && aa[1] == bb[1]
    20  }
    21  
    22  type h264FMTP struct {
    23  	parameters map[string]string
    24  }
    25  
    26  func (h *h264FMTP) MimeType() string {
    27  	return "video/h264"
    28  }
    29  
    30  // Match returns true if h and b are compatible fmtp descriptions
    31  // Based on RFC6184 Section 8.2.2:
    32  //
    33  //	The parameters identifying a media format configuration for H.264
    34  //	are profile-level-id and packetization-mode.  These media format
    35  //	configuration parameters (except for the level part of profile-
    36  //	level-id) MUST be used symmetrically; that is, the answerer MUST
    37  //	either maintain all configuration parameters or remove the media
    38  //	format (payload type) completely if one or more of the parameter
    39  //	values are not supported.
    40  //	  Informative note: The requirement for symmetric use does not
    41  //	  apply for the level part of profile-level-id and does not apply
    42  //	  for the other stream properties and capability parameters.
    43  func (h *h264FMTP) Match(b FMTP) bool {
    44  	c, ok := b.(*h264FMTP)
    45  	if !ok {
    46  		return false
    47  	}
    48  
    49  	// test packetization-mode
    50  	hpmode, hok := h.parameters["packetization-mode"]
    51  	if !hok {
    52  		return false
    53  	}
    54  	cpmode, cok := c.parameters["packetization-mode"]
    55  	if !cok {
    56  		return false
    57  	}
    58  
    59  	if hpmode != cpmode {
    60  		return false
    61  	}
    62  
    63  	// test profile-level-id
    64  	hplid, hok := h.parameters["profile-level-id"]
    65  	if !hok {
    66  		return false
    67  	}
    68  
    69  	cplid, cok := c.parameters["profile-level-id"]
    70  	if !cok {
    71  		return false
    72  	}
    73  
    74  	if !profileLevelIDMatches(hplid, cplid) {
    75  		return false
    76  	}
    77  
    78  	return true
    79  }
    80  
    81  func (h *h264FMTP) Parameter(key string) (string, bool) {
    82  	v, ok := h.parameters[key]
    83  	return v, ok
    84  }