Allow to use user defined Track

Add WithTrackGenerator option to specify TrackGenerator.
This allows user to replace Track by user defined one that
has WriteSample() and Codec() interface.
This commit is contained in:
Atsushi Watanabe
2020-02-12 19:18:12 +09:00
committed by Lukas Herman
parent 99af57a42a
commit bca254261d
3 changed files with 54 additions and 19 deletions
+39 -8
View File
@@ -20,7 +20,7 @@ type MediaDevices interface {
// NewMediaDevices creates MediaDevices interface that provides access to connected media input devices
// like cameras and microphones, as well as screen sharing.
// In essence, it lets you obtain access to any hardware source of media data.
func NewMediaDevices(pc *webrtc.PeerConnection) MediaDevices {
func NewMediaDevices(pc *webrtc.PeerConnection, opts ...MediaDevicesOption) MediaDevices {
codecs := make(map[webrtc.RTPCodecType][]*webrtc.RTPCodec)
for _, kind := range []webrtc.RTPCodecType{
webrtc.RTPCodecTypeAudio,
@@ -28,20 +28,51 @@ func NewMediaDevices(pc *webrtc.PeerConnection) MediaDevices {
} {
codecs[kind] = pc.GetRegisteredRTPCodecs(kind)
}
return &mediaDevices{codecs}
return NewMediaDevicesFromCodecs(codecs, opts...)
}
// NewMediaDevicesFromCodecs creates MediaDevices interface from lists of the available codecs
// that provides access to connected media input devices like cameras and microphones,
// as well as screen sharing.
// In essence, it lets you obtain access to any hardware source of media data.
func NewMediaDevicesFromCodecs(codecs map[webrtc.RTPCodecType][]*webrtc.RTPCodec) MediaDevices {
return &mediaDevices{codecs}
func NewMediaDevicesFromCodecs(codecs map[webrtc.RTPCodecType][]*webrtc.RTPCodec, opts ...MediaDevicesOption) MediaDevices {
mdo := MediaDevicesOptions{
codecs: codecs,
trackGenerator: defaultTrackGenerator,
}
for _, o := range opts {
o(&mdo)
}
return &mediaDevices{
MediaDevicesOptions: mdo,
}
}
// TrackGenerator is a function to create new track.
type TrackGenerator func(payloadType uint8, ssrc uint32, id, label string, codec *webrtc.RTPCodec) (LocalTrack, error)
var defaultTrackGenerator = TrackGenerator(func(pt uint8, ssrc uint32, id, label string, codec *webrtc.RTPCodec) (LocalTrack, error) {
return webrtc.NewTrack(pt, ssrc, id, label, codec)
})
type mediaDevices struct {
codecs map[webrtc.RTPCodecType][]*webrtc.RTPCodec
MediaDevicesOptions
}
// MediaDevicesOptions stores parameters used by MediaDevices.
type MediaDevicesOptions struct {
codecs map[webrtc.RTPCodecType][]*webrtc.RTPCodec
trackGenerator TrackGenerator
}
// MediaDevicesOption is a type of MediaDevices functional option.
type MediaDevicesOption func(*MediaDevicesOptions)
// WithTrackGenerator specifies a TrackGenerator to use customized track.
func WithTrackGenerator(gen TrackGenerator) MediaDevicesOption {
return func(o *MediaDevicesOptions) {
o.trackGenerator = gen
}
}
// GetUserMedia prompts the user for permission to use a media input which produces a MediaStream
@@ -161,7 +192,7 @@ func (m *mediaDevices) selectAudio(constraints MediaTrackConstraints) (Tracker,
return nil, err
}
return newAudioTrack(m.codecs[webrtc.RTPCodecTypeAudio], d, c)
return newAudioTrack(&m.MediaDevicesOptions, d, c)
}
func (m *mediaDevices) selectVideo(constraints MediaTrackConstraints) (Tracker, error) {
filter := driver.FilterVideoRecorder()
@@ -178,7 +209,7 @@ func (m *mediaDevices) selectVideo(constraints MediaTrackConstraints) (Tracker,
return nil, err
}
return newVideoTrack(m.codecs[webrtc.RTPCodecTypeVideo], d, c)
return newVideoTrack(&m.MediaDevicesOptions, d, c)
}
func (m *mediaDevices) EnumerateDevices() []MediaDeviceInfo {
+2 -3
View File
@@ -3,17 +3,16 @@ package mediadevices
import (
"time"
"github.com/pion/webrtc/v2"
"github.com/pion/webrtc/v2/pkg/media"
)
type sampler struct {
track *webrtc.Track
track LocalTrack
clockRate float64
lastTimestamp time.Time
}
func newSampler(track *webrtc.Track) *sampler {
func newSampler(track LocalTrack) *sampler {
return &sampler{
track: track,
clockRate: float64(track.Codec().ClockRate),
+13 -8
View File
@@ -21,14 +21,19 @@ type Tracker interface {
OnEnded(func(error))
}
type LocalTrack interface {
WriteSample(s media.Sample) error
Codec() *webrtc.RTPCodec
}
type track struct {
t *webrtc.Track
t LocalTrack
s *sampler
onErrorHandler atomic.Value // func(error)
}
func newTrack(codecs []*webrtc.RTPCodec, d driver.Driver, codecName string) (*track, error) {
func newTrack(codecs []*webrtc.RTPCodec, trackGenerator TrackGenerator, d driver.Driver, codecName string) (*track, error) {
var selectedCodec *webrtc.RTPCodec
for _, c := range codecs {
if c.Name == codecName {
@@ -40,7 +45,7 @@ func newTrack(codecs []*webrtc.RTPCodec, d driver.Driver, codecName string) (*tr
return nil, fmt.Errorf("track: %s is not registered in media engine", codecName)
}
t, err := webrtc.NewTrack(
t, err := trackGenerator(
selectedCodec.PayloadType,
rand.Uint32(),
d.ID(),
@@ -69,7 +74,7 @@ func (t *track) onError(err error) {
}
func (t *track) Track() *webrtc.Track {
return t.t
return t.t.(*webrtc.Track)
}
type videoTrack struct {
@@ -81,9 +86,9 @@ type videoTrack struct {
var _ Tracker = &videoTrack{}
func newVideoTrack(codecs []*webrtc.RTPCodec, d driver.Driver, constraints MediaTrackConstraints) (*videoTrack, error) {
func newVideoTrack(opts *MediaDevicesOptions, d driver.Driver, constraints MediaTrackConstraints) (*videoTrack, error) {
codecName := constraints.CodecName
t, err := newTrack(codecs, d, codecName)
t, err := newTrack(opts.codecs[webrtc.RTPCodecTypeVideo], opts.trackGenerator, d, codecName)
if err != nil {
return nil, err
}
@@ -156,9 +161,9 @@ type audioTrack struct {
var _ Tracker = &audioTrack{}
func newAudioTrack(codecs []*webrtc.RTPCodec, d driver.Driver, constraints MediaTrackConstraints) (*audioTrack, error) {
func newAudioTrack(opts *MediaDevicesOptions, d driver.Driver, constraints MediaTrackConstraints) (*audioTrack, error) {
codecName := constraints.CodecName
t, err := newTrack(codecs, d, codecName)
t, err := newTrack(opts.codecs[webrtc.RTPCodecTypeAudio], opts.trackGenerator, d, codecName)
if err != nil {
return nil, err
}