-
Notifications
You must be signed in to change notification settings - Fork 123
Source Sink Design
Lukas Herman edited this page Oct 11, 2020
·
63 revisions
- Provide a standard way of reading media data
- Provide an extension to non-webrtc applications
- Easy to use
- The current design is tightly coupled to WebRTC, it feels awkward if being used for other use cases
- The simple example is not actually that simple 😓
Location: pkg/io/video and pkg/io/audio
type Broadcaster struct {}
func (broadcaster *Broadcaster) Source() Reader {}
func (broadcaster *Broadcaster) ReplaceSource(source Reader) {}
func (broadcaster *Broadcaster) NewReader() Reader {}
Location: root
package mediadevices
type videoRef struct {
*video.Broadcaster
counter uint
}
type audioRef struct {
*audio.Broadcaster
counter uint
}
// refCounters is being used for letting us know when to Close drivers. For example, if 1 driver is being shared to
// multiple tracks, we don't want to close the driver when there's another track that's still consuming the driver.
var videoRefCounters map[string]*videoRef
var audioRefCounters map[string]*audioRef
func GetUserMedia(c MediaStreamConstraints) MediaStream {}
type Track interface {
ID() string
Stop() error
OnEnded(func(error))
Bind(LocalTrackContext)
Unbind(LocalTrackContext)
}
type VideoTrack interface {
Track
*video.Broadcaster
TransformSource(...video.TransformFunc)
}
type AudioTrack interface {
Track
*audio.Broadcaster
TransformSource(...video.TransformFunc)
}
type VideoSource interface {
video.Reader
Close() error
}
type AudioSource interface {
audio.Reader
Close() error
}
func NewVideoTrack(source VideoSource) Track {
// 1. shim source to capture error in the stream and report it through the handler
// that's set from OnEnded.
// 2. Wrap source with broadcaster
// 3. Fill all necessary fields
}
// internal video track creation from driver
func newVideoTrackFromDriver(d driver.Driver) Track {
// 1. Retrieve video.Reader from the driver
// 2. Wrap the retrieved video.Reader and the driver into a VideoSource
// 3. Create track by calling NewVideoTrack
}
// CodecSelector is preinitialized with a list of video/audio encoder builders.
// It is responsible to find desired codec and create a generic encoded Reader
type CodecSelector struct {
}
func (selector *CodecSelector) Populate(...) {}
func (selector *CodecSelector) selectVideoCodec(name string, track *VideoTrack) (codec.ReadCloser, err) {}
func (selector *CodecSelector) selectVideoCodec(name string, track *AudioTrack) (codec.ReadCloser, err) {}
package main
import (
"github.com/pion/mediadevices"
"github.com/pion/mediadevices/pkg/codec/openh264"
"github.com/pion/mediadevices/pkg/codec/x264"
"github.com/pion/mediadevices/pkg/prop"
// Note: If you don't have a camera or microphone or your adapters are not supported,
// you can always swap your adapters with our dummy adapters below.
// _ "github.com/pion/mediadevices/pkg/driver/videotest"
_ "github.com/pion/mediadevices/pkg/driver/camera" // This is required to register camera adapter
)
func main() {
var setting webrtc.SettingEngine
x264Params, _ := x264.NewParams()
openh264Params, _ := openh264.NewParams()
codecSelector, _ := mediadevices.NewCodecSelector(x264Params, openh264Params)
codecSelector.Populate(&setting)
// User can still modify setting to their needs here
api := webrtc.NewAPI(webrtc.WithSettingEngine(&setting))
// Assume that we have configured the api and have proper config
pc, _ := api.NewPeerConnection(peerConnectionConfig)
mediaStream, _ := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
Video: func(constraint *mediadevices.MediaTrackConstraints) {
constraint.Width = prop.Int(600)
constraint.Height = prop.Int(400)
},
Codec: codecSelector,
})
// Add a custom video transformation
videoTrack := mediaStream.GetVideoTracks()[0]
videoTrack.TransformSource(transformFn1, transformFn2)
pc.AddTransceiverFromTrack(videoTrack,
webrtc.RtpTransceiverInit{
Direction: webrtc.RTPTransceiverDirectionSendonly,
},
)
// peerconnection should negotiate with the other peer
// peerconnection should set the negotiated codec with LocalRTPTrack.setParameters()
// mediadevices then will set the codec and attach the encoder to the pipeline. PeerConnection now can start
// pulling encoded frames from mediadevices.
}
package main
import (
"github.com/pion/webrtc/v2"
"github.com/pion/mediadevices"
)
func main() {
s, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
Video: func(c *mediadevices.MediaTrackConstraints) {
c.Width = 640
c.Height = 480
},
})
videoTrack := s.GetVideoTracks()[0]
videoReader := videoTrack.NewReader()
// Do whatever with this videoReader
}
Usage
Developer Guide