// Package fmtp implements per codec parsing of fmtp lines package fmtp import ( "strings" ) // FMTP interface for implementing custom // FMTP parsers based on MimeType type FMTP interface { // MimeType returns the MimeType associated with // the fmtp MimeType() string // Match compares two fmtp descriptions for // compatibility based on the MimeType Match(f FMTP) bool // Parameter returns a value for the associated key // if contained in the parsed fmtp string Parameter(key string) (string, bool) } // Parse parses an fmtp string based on the MimeType func Parse(mimetype, line string) FMTP { var f FMTP parameters := make(map[string]string) for _, p := range strings.Split(line, ";") { pp := strings.SplitN(strings.TrimSpace(p), "=", 2) key := strings.ToLower(pp[0]) var value string if len(pp) > 1 { value = pp[1] } parameters[key] = value } switch { case strings.EqualFold(mimetype, "video/h264"): f = &h264FMTP{ parameters: parameters, } default: f = &genericFMTP{ mimeType: mimetype, parameters: parameters, } } return f } type genericFMTP struct { mimeType string parameters map[string]string } func (g *genericFMTP) MimeType() string { return g.mimeType } // Match returns true if g and b are compatible fmtp descriptions // The generic implementation is used for MimeTypes that are not defined func (g *genericFMTP) Match(b FMTP) bool { c, ok := b.(*genericFMTP) if !ok { return false } if g.mimeType != c.MimeType() { return false } for k, v := range g.parameters { if vb, ok := c.parameters[k]; ok && !strings.EqualFold(vb, v) { return false } } for k, v := range c.parameters { if va, ok := g.parameters[k]; ok && !strings.EqualFold(va, v) { return false } } return true } func (g *genericFMTP) Parameter(key string) (string, bool) { v, ok := g.parameters[key] return v, ok }