mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-07-28 12:36:30 +00:00
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:
parent
2703692d1a
commit
85bb99f8f8
8 changed files with 72 additions and 43 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue