mirror of
https://github.com/pion/mediadevices.git
synced 2025-10-04 16:22:46 +08:00
Add codec property
Add codec property, which stores general encoding parameters, to MediaTrackConstraints.
This commit is contained in:

committed by
Lukas Herman

parent
1e868fc3e3
commit
00bcadc238
@@ -52,6 +52,7 @@ func main() {
|
|||||||
Audio: func(c *mediadevices.MediaTrackConstraints) {
|
Audio: func(c *mediadevices.MediaTrackConstraints) {
|
||||||
c.Codec = webrtc.Opus
|
c.Codec = webrtc.Opus
|
||||||
c.Enabled = true
|
c.Enabled = true
|
||||||
|
c.BitRate = 32000 // 32kbps
|
||||||
},
|
},
|
||||||
Video: func(c *mediadevices.MediaTrackConstraints) {
|
Video: func(c *mediadevices.MediaTrackConstraints) {
|
||||||
c.Codec = videoCodecName
|
c.Codec = videoCodecName
|
||||||
@@ -59,6 +60,7 @@ func main() {
|
|||||||
c.Enabled = true
|
c.Enabled = true
|
||||||
c.Width = 640
|
c.Width = 640
|
||||||
c.Height = 480
|
c.Height = 480
|
||||||
|
c.BitRate = 100000 // 100kbps
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -8,5 +8,5 @@ import (
|
|||||||
"github.com/pion/mediadevices/pkg/prop"
|
"github.com/pion/mediadevices/pkg/prop"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VideoEncoderBuilder func(r video.Reader, p prop.Video) (io.ReadCloser, error)
|
type VideoEncoderBuilder func(r video.Reader, p prop.Media) (io.ReadCloser, error)
|
||||||
type AudioEncoderBuilder func(r audio.Reader, p prop.Audio) (io.ReadCloser, error)
|
type AudioEncoderBuilder func(r audio.Reader, p prop.Media) (io.ReadCloser, error)
|
||||||
|
@@ -35,7 +35,11 @@ func init() {
|
|||||||
codec.Register(webrtc.H264, codec.VideoEncoderBuilder(NewEncoder))
|
codec.Register(webrtc.H264, codec.VideoEncoderBuilder(NewEncoder))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEncoder(r video.Reader, p prop.Video) (io.ReadCloser, error) {
|
func NewEncoder(r video.Reader, p prop.Media) (io.ReadCloser, error) {
|
||||||
|
if p.BitRate == 0 {
|
||||||
|
p.BitRate = 100000
|
||||||
|
}
|
||||||
|
|
||||||
cEncoder, err := C.enc_new(C.EncoderOptions{
|
cEncoder, err := C.enc_new(C.EncoderOptions{
|
||||||
width: C.int(p.Width),
|
width: C.int(p.Width),
|
||||||
height: C.int(p.Height),
|
height: C.int(p.Height),
|
||||||
|
@@ -29,7 +29,7 @@ func init() {
|
|||||||
codec.Register(webrtc.Opus, codec.AudioEncoderBuilder(NewEncoder))
|
codec.Register(webrtc.Opus, codec.AudioEncoderBuilder(NewEncoder))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEncoder(r audio.Reader, p prop.Audio) (io.ReadCloser, error) {
|
func NewEncoder(r audio.Reader, p prop.Media) (io.ReadCloser, error) {
|
||||||
if p.SampleRate == 0 {
|
if p.SampleRate == 0 {
|
||||||
return nil, fmt.Errorf("opus: inProp.SampleRate is required")
|
return nil, fmt.Errorf("opus: inProp.SampleRate is required")
|
||||||
}
|
}
|
||||||
@@ -38,6 +38,10 @@ func NewEncoder(r audio.Reader, p prop.Audio) (io.ReadCloser, error) {
|
|||||||
p.Latency = 20
|
p.Latency = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.BitRate == 0 {
|
||||||
|
p.BitRate = 32000
|
||||||
|
}
|
||||||
|
|
||||||
// Select the nearest supported latency
|
// Select the nearest supported latency
|
||||||
var targetLatency float64
|
var targetLatency float64
|
||||||
latencyInMS := float64(p.Latency.Milliseconds())
|
latencyInMS := float64(p.Latency.Milliseconds())
|
||||||
@@ -59,6 +63,9 @@ func NewEncoder(r audio.Reader, p prop.Audio) (io.ReadCloser, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := engine.SetBitrate(p.BitRate); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
inBuffSize := targetLatency * float64(p.SampleRate) / 1000
|
inBuffSize := targetLatency * float64(p.SampleRate) / 1000
|
||||||
inBuff := make([][2]float32, int(inBuffSize))
|
inBuff := make([][2]float32, int(inBuffSize))
|
||||||
|
@@ -23,7 +23,7 @@ func Register(name string, builder interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildVideoEncoder(name string, r video.Reader, p prop.Video) (io.ReadCloser, error) {
|
func BuildVideoEncoder(name string, r video.Reader, p prop.Media) (io.ReadCloser, error) {
|
||||||
b, ok := videoEncoders[name]
|
b, ok := videoEncoders[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("codec: can't find %s video encoder", name)
|
return nil, fmt.Errorf("codec: can't find %s video encoder", name)
|
||||||
@@ -32,7 +32,7 @@ func BuildVideoEncoder(name string, r video.Reader, p prop.Video) (io.ReadCloser
|
|||||||
return b(r, p)
|
return b(r, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildAudioEncoder(name string, r audio.Reader, p prop.Audio) (io.ReadCloser, error) {
|
func BuildAudioEncoder(name string, r audio.Reader, p prop.Media) (io.ReadCloser, error) {
|
||||||
b, ok := audioEncoders[name]
|
b, ok := audioEncoders[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("codec: can't find %s audio encoder", name)
|
return nil, fmt.Errorf("codec: can't find %s audio encoder", name)
|
||||||
|
@@ -63,16 +63,24 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewVP8Encoder creates new VP8 encoder
|
// NewVP8Encoder creates new VP8 encoder
|
||||||
func NewVP8Encoder(r video.Reader, p prop.Video) (io.ReadCloser, error) {
|
func NewVP8Encoder(r video.Reader, p prop.Media) (io.ReadCloser, error) {
|
||||||
return newEncoder(r, p, C.ifaceVP8())
|
return newEncoder(r, p, C.ifaceVP8())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVP9Encoder creates new VP9 encoder
|
// NewVP9Encoder creates new VP9 encoder
|
||||||
func NewVP9Encoder(r video.Reader, p prop.Video) (io.ReadCloser, error) {
|
func NewVP9Encoder(r video.Reader, p prop.Media) (io.ReadCloser, error) {
|
||||||
return newEncoder(r, p, C.ifaceVP9())
|
return newEncoder(r, p, C.ifaceVP9())
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEncoder(r video.Reader, p prop.Video, codecIface *C.vpx_codec_iface_t) (io.ReadCloser, error) {
|
func newEncoder(r video.Reader, p prop.Media, codecIface *C.vpx_codec_iface_t) (io.ReadCloser, error) {
|
||||||
|
if p.BitRate == 0 {
|
||||||
|
p.BitRate = 100000
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.KeyFrameInterval == 0 {
|
||||||
|
p.KeyFrameInterval = 60
|
||||||
|
}
|
||||||
|
|
||||||
cfg := &C.vpx_codec_enc_cfg_t{}
|
cfg := &C.vpx_codec_enc_cfg_t{}
|
||||||
if ec := C.vpx_codec_enc_config_default(codecIface, cfg, 0); ec != 0 {
|
if ec := C.vpx_codec_enc_config_default(codecIface, cfg, 0); ec != 0 {
|
||||||
return nil, fmt.Errorf("vpx_codec_enc_config_default failed (%d)", ec)
|
return nil, fmt.Errorf("vpx_codec_enc_config_default failed (%d)", ec)
|
||||||
@@ -101,7 +109,7 @@ func newEncoder(r video.Reader, p prop.Video, codecIface *C.vpx_codec_iface_t) (
|
|||||||
r: video.ToI420(r),
|
r: video.ToI420(r),
|
||||||
codec: codec,
|
codec: codec,
|
||||||
raw: rawNoBuffer,
|
raw: rawNoBuffer,
|
||||||
keyframeInterval: 30, // TODO: Set via prop.Video
|
keyframeInterval: p.KeyFrameInterval,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@ import (
|
|||||||
type Media struct {
|
type Media struct {
|
||||||
Video
|
Video
|
||||||
Audio
|
Audio
|
||||||
|
Codec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Media) FitnessDistance(o Media) float64 {
|
func (p *Media) FitnessDistance(o Media) float64 {
|
||||||
@@ -62,7 +63,6 @@ type Video struct {
|
|||||||
Width, Height int
|
Width, Height int
|
||||||
FrameRate float32
|
FrameRate float32
|
||||||
FrameFormat frame.Format
|
FrameFormat frame.Format
|
||||||
BitRate int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio represents an audio's properties
|
// Audio represents an audio's properties
|
||||||
@@ -72,3 +72,17 @@ type Audio struct {
|
|||||||
SampleRate int
|
SampleRate int
|
||||||
SampleSize int
|
SampleSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Codec represents an codec's encoding properties
|
||||||
|
type Codec struct {
|
||||||
|
// Target bitrate in bps.
|
||||||
|
BitRate int
|
||||||
|
|
||||||
|
// Quolity of the encoding [0-9].
|
||||||
|
// Larger value results higher quality and higher CPU usage.
|
||||||
|
// It depends on the selected codec.
|
||||||
|
Quality int
|
||||||
|
|
||||||
|
// Expected interval of the keyframes in frames.
|
||||||
|
KeyFrameInterval int
|
||||||
|
}
|
||||||
|
6
track.go
6
track.go
@@ -99,9 +99,7 @@ func newVideoTrack(codecs []*webrtc.RTPCodec, d driver.Driver, constraints Media
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove hardcoded bitrate
|
encoder, err := codec.BuildVideoEncoder(codecName, r, constraints.Media)
|
||||||
constraints.BitRate = 100000
|
|
||||||
encoder, err := codec.BuildVideoEncoder(codecName, r, constraints.Video)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -172,7 +170,7 @@ func newAudioTrack(codecs []*webrtc.RTPCodec, d driver.Driver, constraints Media
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder, err := codec.BuildAudioEncoder(codecName, reader, constraints.Audio)
|
encoder, err := codec.BuildAudioEncoder(codecName, reader, constraints.Media)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user