Explicitly set RTP timestamp to cope with variable frame rate. (#211)

Set the timestamp as early as possible and propagate it through the pipeline.
This commit is contained in:
88hcsif 2020-06-28 10:25:23 +01:00 committed by GitHub
parent 2703692d1a
commit 85bb99f8f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 43 deletions

View file

@ -2,7 +2,6 @@ package h264encoder
import (
"bytes"
"image"
"log"
"runtime/debug"
@ -14,8 +13,8 @@ const chanSize = 2
// H264Encoder yuvI420 image to vp8 video
type H264Encoder struct {
Output chan []byte // frame
Input chan *image.RGBA // yuvI420
Output chan encoder.OutFrame
Input chan encoder.InFrame
buf *bytes.Buffer
enc *x264.Encoder
@ -29,8 +28,8 @@ type H264Encoder struct {
// NewH264Encoder create h264 encoder
func NewH264Encoder(width, height, fps int) (encoder.Encoder, error) {
v := &H264Encoder{
Output: make(chan []byte, 5*chanSize),
Input: make(chan *image.RGBA, chanSize),
Output: make(chan encoder.OutFrame, 5*chanSize),
Input: make(chan encoder.InFrame, chanSize),
buf: bytes.NewBuffer(make([]byte, 0)),
width: width,
@ -75,11 +74,11 @@ func (v *H264Encoder) startLooping() {
}()
for img := range v.Input {
err := v.enc.Encode(img)
err := v.enc.Encode(img.Image)
if err != nil {
log.Println("err encoding ", img, " using h264")
log.Println("err encoding ", img.Image, " using h264")
}
v.Output <- v.buf.Bytes()
v.Output <- encoder.OutFrame{ Data: v.buf.Bytes(), Timestamp: img.Timestamp }
v.buf.Reset()
}
}
@ -96,12 +95,12 @@ func (v *H264Encoder) release() {
}
// GetInputChan returns input channel
func (v *H264Encoder) GetInputChan() chan *image.RGBA {
func (v *H264Encoder) GetInputChan() chan encoder.InFrame {
return v.Input
}
// GetInputChan returns output channel
func (v *H264Encoder) GetOutputChan() chan []byte {
func (v *H264Encoder) GetOutputChan() chan encoder.OutFrame {
return v.Output
}

View file

@ -2,8 +2,18 @@ package encoder
import "image"
type InFrame struct {
Image *image.RGBA
Timestamp uint32
}
type OutFrame struct {
Data []byte
Timestamp uint32
}
type Encoder interface {
GetInputChan() chan *image.RGBA
GetOutputChan() chan []byte
GetInputChan() chan InFrame
GetOutputChan() chan OutFrame
Stop()
}

View file

@ -2,7 +2,6 @@ package vpxencoder
import (
"fmt"
"image"
"log"
"unsafe"
@ -46,8 +45,8 @@ const chanSize = 2
// VpxEncoder yuvI420 image to vp8 video
type VpxEncoder struct {
Output chan []byte // frame
Input chan *image.RGBA // yuvI420
Output chan encoder.OutFrame
Input chan encoder.InFrame
width int
height int
@ -64,8 +63,8 @@ type VpxEncoder struct {
// NewVpxEncoder create vp8 encoder
func NewVpxEncoder(w, h, fps, bitrate, keyframe int) (encoder.Encoder, error) {
v := &VpxEncoder{
Output: make(chan []byte, 5*chanSize),
Input: make(chan *image.RGBA, chanSize),
Output: make(chan encoder.OutFrame, 5*chanSize),
Input: make(chan encoder.InFrame, chanSize),
// C
width: w,
@ -126,7 +125,7 @@ func (v *VpxEncoder) startLooping() {
yuv := make([]byte, size, size)
for img := range v.Input {
util.RgbaToYuvInplace(img, yuv, v.width, v.height)
util.RgbaToYuvInplace(img.Image, yuv, v.width, v.height)
// Add Image
v.vpxCodexIter = nil
@ -151,7 +150,7 @@ func (v *VpxEncoder) startLooping() {
if len(v.Output) >= cap(v.Output) {
continue
}
v.Output <- bs
v.Output <- encoder.OutFrame{ Data: bs, Timestamp: img.Timestamp }
}
}
@ -168,12 +167,12 @@ func (v *VpxEncoder) release() {
}
// GetInputChan returns input channel
func (v *VpxEncoder) GetInputChan() chan *image.RGBA {
func (v *VpxEncoder) GetInputChan() chan encoder.InFrame {
return v.Input
}
// GetInputChan returns output channel
func (v *VpxEncoder) GetOutputChan() chan []byte {
func (v *VpxEncoder) GetOutputChan() chan encoder.OutFrame {
return v.Output
}