mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 07:06:58 +08:00
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
This commit is contained in:
128
pkg/format/format.go
Normal file
128
pkg/format/format.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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
|
||||
}
|
Reference in New Issue
Block a user