mirror of
https://github.com/aler9/gortsplib
synced 2025-10-13 10:53:58 +08:00

* 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
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package media
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
|
|
psdp "github.com/pion/sdp/v3"
|
|
|
|
"github.com/aler9/gortsplib/v2/pkg/sdp"
|
|
)
|
|
|
|
// Medias is a list of media streams.
|
|
type Medias []*Media
|
|
|
|
// Unmarshal decodes medias from the SDP format.
|
|
func (ms *Medias) Unmarshal(mds []*psdp.MediaDescription) error {
|
|
*ms = make(Medias, len(mds))
|
|
|
|
for i, md := range mds {
|
|
var m Media
|
|
err := m.unmarshal(md)
|
|
if err != nil {
|
|
return fmt.Errorf("media %d is invalid: %v", i+1, err)
|
|
}
|
|
(*ms)[i] = &m
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Marshal encodes the medias in SDP format.
|
|
func (ms Medias) Marshal(multicast bool) *sdp.SessionDescription {
|
|
var address string
|
|
if multicast {
|
|
address = "224.1.0.0"
|
|
} else {
|
|
address = "0.0.0.0"
|
|
}
|
|
|
|
sout := &sdp.SessionDescription{
|
|
SessionName: psdp.SessionName("Stream"),
|
|
Origin: psdp.Origin{
|
|
Username: "-",
|
|
NetworkType: "IN",
|
|
AddressType: "IP4",
|
|
UnicastAddress: "127.0.0.1",
|
|
},
|
|
// required by Darwin Streaming Server
|
|
ConnectionInformation: &psdp.ConnectionInformation{
|
|
NetworkType: "IN",
|
|
AddressType: "IP4",
|
|
Address: &psdp.Address{Address: address},
|
|
},
|
|
TimeDescriptions: []psdp.TimeDescription{
|
|
{Timing: psdp.Timing{StartTime: 0, StopTime: 0}},
|
|
},
|
|
MediaDescriptions: make([]*psdp.MediaDescription, len(ms)),
|
|
}
|
|
|
|
for i, media := range ms {
|
|
sout.MediaDescriptions[i] = media.Marshal()
|
|
}
|
|
|
|
return sout
|
|
}
|
|
|
|
// Clone clones the media list.
|
|
func (ms Medias) Clone() Medias {
|
|
ret := make(Medias, len(ms))
|
|
for i, media := range ms {
|
|
ret[i] = media.Clone()
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// CloneAndSetControls clones the media list and sets the control attribute
|
|
// of all medias in the list.
|
|
func (ms Medias) CloneAndSetControls() Medias {
|
|
ret := ms.Clone()
|
|
ret.SetControls()
|
|
return ret
|
|
}
|
|
|
|
// SetControls sets the control attribute of all medias in the list.
|
|
func (ms Medias) SetControls() {
|
|
for i, media := range ms {
|
|
media.Control = "mediaID=" + strconv.FormatInt(int64(i), 10)
|
|
}
|
|
}
|
|
|
|
// Find finds a certain format among all the formats in all the medias.
|
|
// If the format is found, it is inserted into trak, and format media is returned.
|
|
func (ms *Medias) Find(trak interface{}) *Media {
|
|
for _, media := range *ms {
|
|
for _, trakk := range media.Formats {
|
|
if reflect.TypeOf(trakk) == reflect.TypeOf(trak).Elem() {
|
|
reflect.ValueOf(trak).Elem().Set(reflect.ValueOf(trakk))
|
|
return media
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|