mirror of
https://github.com/pion/mediadevices.git
synced 2026-04-23 00:07:29 +08:00
2f5e4ee914
Changelog: * Better support for non-webrtc use cases * Enable multiple readers * Enhance codec selectors * Update APIs to reflect on the new v3 webrtc design * Cleaner APIs
118 lines
3.3 KiB
Go
118 lines
3.3 KiB
Go
package mediadevices
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/pion/mediadevices/pkg/codec"
|
|
"github.com/pion/mediadevices/pkg/io/audio"
|
|
"github.com/pion/mediadevices/pkg/io/video"
|
|
"github.com/pion/mediadevices/pkg/prop"
|
|
"github.com/pion/webrtc/v2"
|
|
)
|
|
|
|
// CodecSelector is a container of video and audio encoder builders, which later will be used
|
|
// for codec matching.
|
|
type CodecSelector struct {
|
|
videoEncoders []codec.VideoEncoderBuilder
|
|
audioEncoders []codec.AudioEncoderBuilder
|
|
}
|
|
|
|
// CodecSelectorOption is a type for specifying CodecSelector options
|
|
type CodecSelectorOption func(*CodecSelector)
|
|
|
|
// WithVideoEncoders replace current video codecs with listed encoders
|
|
func WithVideoEncoders(encoders ...codec.VideoEncoderBuilder) CodecSelectorOption {
|
|
return func(t *CodecSelector) {
|
|
t.videoEncoders = encoders
|
|
}
|
|
}
|
|
|
|
// WithVideoEncoders replace current audio codecs with listed encoders
|
|
func WithAudioEncoders(encoders ...codec.AudioEncoderBuilder) CodecSelectorOption {
|
|
return func(t *CodecSelector) {
|
|
t.audioEncoders = encoders
|
|
}
|
|
}
|
|
|
|
// NewCodecSelector constructs CodecSelector with given variadic options
|
|
func NewCodecSelector(opts ...CodecSelectorOption) *CodecSelector {
|
|
var track CodecSelector
|
|
|
|
for _, opt := range opts {
|
|
opt(&track)
|
|
}
|
|
|
|
return &track
|
|
}
|
|
|
|
// Populate lets the webrtc engine be aware of supported codecs that are contained in CodecSelector
|
|
func (selector *CodecSelector) Populate(setting *webrtc.MediaEngine) {
|
|
for _, encoder := range selector.videoEncoders {
|
|
setting.RegisterCodec(encoder.RTPCodec().RTPCodec)
|
|
}
|
|
|
|
for _, encoder := range selector.audioEncoders {
|
|
setting.RegisterCodec(encoder.RTPCodec().RTPCodec)
|
|
}
|
|
}
|
|
|
|
func (selector *CodecSelector) selectVideoCodec(wantCodecs []*webrtc.RTPCodec, reader video.Reader, inputProp prop.Media) (codec.ReadCloser, *codec.RTPCodec, error) {
|
|
var selectedEncoder codec.VideoEncoderBuilder
|
|
var encodedReader codec.ReadCloser
|
|
var errReasons []string
|
|
var err error
|
|
|
|
outer:
|
|
for _, wantCodec := range wantCodecs {
|
|
name := wantCodec.Name
|
|
for _, encoder := range selector.videoEncoders {
|
|
if encoder.RTPCodec().Name == name {
|
|
encodedReader, err = encoder.BuildVideoEncoder(reader, inputProp)
|
|
if err == nil {
|
|
selectedEncoder = encoder
|
|
break outer
|
|
}
|
|
}
|
|
|
|
errReasons = append(errReasons, fmt.Sprintf("%s: %s", encoder.RTPCodec().Name, err))
|
|
}
|
|
}
|
|
|
|
if selectedEncoder == nil {
|
|
return nil, nil, errors.New(strings.Join(errReasons, "\n\n"))
|
|
}
|
|
|
|
return encodedReader, selectedEncoder.RTPCodec(), nil
|
|
}
|
|
|
|
func (selector *CodecSelector) selectAudioCodec(wantCodecs []*webrtc.RTPCodec, reader audio.Reader, inputProp prop.Media) (codec.ReadCloser, *codec.RTPCodec, error) {
|
|
var selectedEncoder codec.AudioEncoderBuilder
|
|
var encodedReader codec.ReadCloser
|
|
var errReasons []string
|
|
var err error
|
|
|
|
outer:
|
|
for _, wantCodec := range wantCodecs {
|
|
name := wantCodec.Name
|
|
for _, encoder := range selector.audioEncoders {
|
|
if encoder.RTPCodec().Name == name {
|
|
encodedReader, err = encoder.BuildAudioEncoder(reader, inputProp)
|
|
if err == nil {
|
|
selectedEncoder = encoder
|
|
break outer
|
|
}
|
|
}
|
|
|
|
errReasons = append(errReasons, fmt.Sprintf("%s: %s", encoder.RTPCodec().Name, err))
|
|
}
|
|
}
|
|
|
|
if selectedEncoder == nil {
|
|
return nil, nil, errors.New(strings.Join(errReasons, "\n\n"))
|
|
}
|
|
|
|
return encodedReader, selectedEncoder.RTPCodec(), nil
|
|
}
|