Files
gortsplib/pkg/format/format.go
Alessandro Ros a1396206b5 convert Tracks into Medias and Formats (#155)
* split tracks from medias

* move tracks into dedicated package

* move media into dedicated package

* edit Medias.Marshal() in order to return SDP

* add medias.Find() and simplify examples

* improve coverage

* fix rebase errors

* replace TrackIDs with MediaIDs

* implement media-specific and track-specific callbacks for reading RTCP and RTP packets

* rename publish into record, read into play

* add v2 tag

* rename tracks into formats
2022-12-11 22:03:22 +01:00

129 lines
2.7 KiB
Go

// Package format contains format definitions.
package format
import (
"strconv"
"strings"
"github.com/pion/rtp"
psdp "github.com/pion/sdp/v3"
)
func getFormatAttribute(attributes []psdp.Attribute, payloadType uint8, key string) string {
for _, attr := range attributes {
if attr.Key == key {
v := strings.TrimSpace(attr.Value)
if parts := strings.SplitN(v, " ", 2); len(parts) == 2 {
if tmp, err := strconv.ParseInt(parts[0], 10, 8); err == nil && uint8(tmp) == payloadType {
return parts[1]
}
}
}
}
return ""
}
func getCodecAndClock(rtpMap string) (string, string) {
parts2 := strings.SplitN(rtpMap, "/", 2)
if len(parts2) != 2 {
return "", ""
}
return parts2[0], parts2[1]
}
// Format is a RTSP format.
type Format interface {
// String returns a description of the format.
String() string
// ClockRate returns the clock rate.
ClockRate() int
// PayloadType returns the payload type.
PayloadType() uint8
unmarshal(payloadType uint8, clock string, codec string, rtpmap string, fmtp string) error
// Marshal encodes the format in SDP format.
Marshal() (string, string)
// Clone clones the format.
Clone() Format
// PTSEqualsDTS checks whether PTS is equal to DTS in the RTP packet.
PTSEqualsDTS(*rtp.Packet) bool
}
// Unmarshal decodes a format from a media description.
func Unmarshal(md *psdp.MediaDescription, payloadTypeStr string) (Format, error) {
tmp, err := strconv.ParseInt(payloadTypeStr, 10, 8)
if err != nil {
return nil, err
}
payloadType := uint8(tmp)
rtpMap := getFormatAttribute(md.Attributes, payloadType, "rtpmap")
codec, clock := getCodecAndClock(rtpMap)
codec = strings.ToLower(codec)
fmtp := getFormatAttribute(md.Attributes, payloadType, "fmtp")
format := func() Format {
switch {
case md.MediaName.Media == "video":
switch {
case payloadType == 26:
return &JPEG{}
case payloadType == 32:
return &MPEG2Video{}
case codec == "h264" && clock == "90000":
return &H264{}
case codec == "h265" && clock == "90000":
return &H265{}
case codec == "vp8" && clock == "90000":
return &VP8{}
case codec == "vp9" && clock == "90000":
return &VP9{}
}
case md.MediaName.Media == "audio":
switch {
case payloadType == 0, payloadType == 8:
return &G711{}
case payloadType == 9:
return &G722{}
case payloadType == 14:
return &MPEG2Audio{}
case codec == "l8", codec == "l16", codec == "l24":
return &LPCM{}
case codec == "mpeg4-generic":
return &MPEG4Audio{}
case codec == "vorbis":
return &Vorbis{}
case codec == "opus":
return &Opus{}
}
}
return &Generic{}
}()
err = format.unmarshal(payloadType, clock, codec, rtpMap, fmtp)
if err != nil {
return nil, err
}
return format, nil
}