mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-01-23 18:46:11 +00:00
Add new YUV converter with 2x2 pixel matrix YUV color estimation. The new YUV color converter, as opposed to the original one, uses more precise color calculations based on four neighboring pixels' average color values which helps a great deal with image aliasing / shimmering artifacts. By default, it runs in the multithreaded mode with the game frames sliced between 2*(CPU cores) goroutines. In case if this estimation mode doesn't work as expected it is possible to switch back to the original mode. The default encoder is switched to x264 since it's faster now.
64 lines
1.3 KiB
Go
64 lines
1.3 KiB
Go
package encoder
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/giongto35/cloud-game/v2/pkg/encoder/yuv"
|
|
)
|
|
|
|
type VideoPipe struct {
|
|
Input chan InFrame
|
|
Output chan OutFrame
|
|
done chan struct{}
|
|
|
|
encoder Encoder
|
|
|
|
// frame size
|
|
w, h int
|
|
}
|
|
|
|
// NewVideoPipe returns new video encoder pipe.
|
|
// By default it waits for RGBA images on the input channel,
|
|
// converts them into YUV I420 format,
|
|
// encodes with provided video encoder, and
|
|
// puts the result into the output channel.
|
|
func NewVideoPipe(enc Encoder, w, h int) *VideoPipe {
|
|
return &VideoPipe{
|
|
Input: make(chan InFrame, 1),
|
|
Output: make(chan OutFrame, 2),
|
|
done: make(chan struct{}),
|
|
|
|
encoder: enc,
|
|
|
|
w: w,
|
|
h: h,
|
|
}
|
|
}
|
|
|
|
// Start begins video encoding pipe.
|
|
// Should be wrapped into a goroutine.
|
|
func (vp *VideoPipe) Start() {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Println("Warn: Recovered panic in encoding ", r)
|
|
}
|
|
}()
|
|
|
|
yuvProc := yuv.NewYuvImgProcessor(vp.w, vp.h)
|
|
for img := range vp.Input {
|
|
frame := vp.encoder.Encode(yuvProc.Process(img.Image).Get())
|
|
if len(frame) > 0 {
|
|
vp.Output <- OutFrame{Data: frame, Timestamp: img.Timestamp}
|
|
}
|
|
}
|
|
close(vp.Output)
|
|
close(vp.done)
|
|
}
|
|
|
|
func (vp *VideoPipe) Stop() {
|
|
close(vp.Input)
|
|
<-vp.done
|
|
if err := vp.encoder.Shutdown(); err != nil {
|
|
log.Println("error: failed to close the encoder")
|
|
}
|
|
}
|