Add codec property

Add codec property, which stores general encoding parameters,
to MediaTrackConstraints.
This commit is contained in:
Atsushi Watanabe
2020-02-10 23:15:29 +09:00
committed by Lukas Herman
parent 1e868fc3e3
commit 00bcadc238
8 changed files with 48 additions and 15 deletions

View File

@@ -52,6 +52,7 @@ func main() {
Audio: func(c *mediadevices.MediaTrackConstraints) {
c.Codec = webrtc.Opus
c.Enabled = true
c.BitRate = 32000 // 32kbps
},
Video: func(c *mediadevices.MediaTrackConstraints) {
c.Codec = videoCodecName
@@ -59,6 +60,7 @@ func main() {
c.Enabled = true
c.Width = 640
c.Height = 480
c.BitRate = 100000 // 100kbps
},
})
if err != nil {

View File

@@ -8,5 +8,5 @@ import (
"github.com/pion/mediadevices/pkg/prop"
)
type VideoEncoderBuilder func(r video.Reader, p prop.Video) (io.ReadCloser, error)
type AudioEncoderBuilder func(r audio.Reader, p prop.Audio) (io.ReadCloser, error)
type VideoEncoderBuilder func(r video.Reader, p prop.Media) (io.ReadCloser, error)
type AudioEncoderBuilder func(r audio.Reader, p prop.Media) (io.ReadCloser, error)

View File

@@ -35,7 +35,11 @@ func init() {
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{
width: C.int(p.Width),
height: C.int(p.Height),

View File

@@ -29,7 +29,7 @@ func init() {
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 {
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
}
if p.BitRate == 0 {
p.BitRate = 32000
}
// Select the nearest supported latency
var targetLatency float64
latencyInMS := float64(p.Latency.Milliseconds())
@@ -59,6 +63,9 @@ func NewEncoder(r audio.Reader, p prop.Audio) (io.ReadCloser, error) {
if err != nil {
return nil, err
}
if err := engine.SetBitrate(p.BitRate); err != nil {
return nil, err
}
inBuffSize := targetLatency * float64(p.SampleRate) / 1000
inBuff := make([][2]float32, int(inBuffSize))

View File

@@ -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]
if !ok {
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)
}
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]
if !ok {
return nil, fmt.Errorf("codec: can't find %s audio encoder", name)

View File

@@ -63,16 +63,24 @@ func init() {
}
// 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())
}
// 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())
}
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{}
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)
@@ -101,7 +109,7 @@ func newEncoder(r video.Reader, p prop.Video, codecIface *C.vpx_codec_iface_t) (
r: video.ToI420(r),
codec: codec,
raw: rawNoBuffer,
keyframeInterval: 30, // TODO: Set via prop.Video
keyframeInterval: p.KeyFrameInterval,
}, nil
}

View File

@@ -12,6 +12,7 @@ import (
type Media struct {
Video
Audio
Codec
}
func (p *Media) FitnessDistance(o Media) float64 {
@@ -62,7 +63,6 @@ type Video struct {
Width, Height int
FrameRate float32
FrameFormat frame.Format
BitRate int
}
// Audio represents an audio's properties
@@ -72,3 +72,17 @@ type Audio struct {
SampleRate 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
}

View File

@@ -99,9 +99,7 @@ func newVideoTrack(codecs []*webrtc.RTPCodec, d driver.Driver, constraints Media
return nil, err
}
// TODO: Remove hardcoded bitrate
constraints.BitRate = 100000
encoder, err := codec.BuildVideoEncoder(codecName, r, constraints.Video)
encoder, err := codec.BuildVideoEncoder(codecName, r, constraints.Media)
if err != nil {
return nil, err
}
@@ -172,7 +170,7 @@ func newAudioTrack(codecs []*webrtc.RTPCodec, d driver.Driver, constraints Media
return nil, err
}
encoder, err := codec.BuildAudioEncoder(codecName, reader, constraints.Audio)
encoder, err := codec.BuildAudioEncoder(codecName, reader, constraints.Media)
if err != nil {
return nil, err
}