mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-01-23 02:34:42 +00:00
Don't copy YUV planes in x264
This commit is contained in:
parent
fb5d8c216b
commit
e4aab1019c
4 changed files with 53 additions and 45 deletions
|
|
@ -260,7 +260,7 @@ encoder:
|
|||
# see: https://trac.ffmpeg.org/wiki/Encode/H.264
|
||||
h264:
|
||||
# Constant Rate Factor (CRF) 0-51 (default: 23)
|
||||
crf: 23
|
||||
crf: 26
|
||||
# ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
|
||||
preset: superfast
|
||||
# baseline, main, high, high10, high422, high444
|
||||
|
|
|
|||
|
|
@ -362,10 +362,10 @@ type Sei struct {
|
|||
}
|
||||
|
||||
type Image struct {
|
||||
ICsp int32 /* Colorspace */
|
||||
IPlane int32 /* Number of image planes */
|
||||
IStride [4]int32 /* Strides for each plane */
|
||||
Plane [4]unsafe.Pointer /* Pointers to each plane */
|
||||
ICsp int32 /* Colorspace */
|
||||
IPlane int32 /* Number of image planes */
|
||||
IStride [4]int32 /* Strides for each plane */
|
||||
Plane [4]uintptr /* Pointers to each plane */
|
||||
}
|
||||
|
||||
type ImageProperties struct {
|
||||
|
|
@ -455,12 +455,6 @@ type Picture struct {
|
|||
Opaque unsafe.Pointer
|
||||
}
|
||||
|
||||
func (p *Picture) freePlanes() {
|
||||
for _, ptr := range p.Img.Plane {
|
||||
C.free(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *T) cptr() *C.x264_t { return (*C.x264_t)(unsafe.Pointer(t)) }
|
||||
|
||||
func (n *Nal) cptr() *C.x264_nal_t { return (*C.x264_nal_t)(unsafe.Pointer(n)) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package h264
|
||||
|
||||
// #include <stdint.h>
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
|
@ -18,7 +16,6 @@ type H264 struct {
|
|||
nals []*Nal
|
||||
|
||||
in, out *Picture
|
||||
y, u, v []byte
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
|
|
@ -86,35 +83,26 @@ func NewEncoder(w, h int, opts *Options) (encoder *H264, err error) {
|
|||
|
||||
encoder = &H264{
|
||||
csp: param.ICsp,
|
||||
lumaSize: int32(w * h),
|
||||
chromaSize: int32(w*h) / 4,
|
||||
lumaSize: param.IWidth * param.IHeight,
|
||||
chromaSize: param.IWidth * param.IHeight / 4,
|
||||
nals: make([]*Nal, 1),
|
||||
width: int32(w),
|
||||
width: param.IWidth,
|
||||
out: new(Picture),
|
||||
in: &Picture{
|
||||
Img: Image{
|
||||
ICsp: param.ICsp,
|
||||
IPlane: 3,
|
||||
IStride: [4]int32{
|
||||
0: param.IWidth,
|
||||
1: param.IWidth >> 1,
|
||||
2: param.IWidth >> 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// pool
|
||||
var picIn Picture
|
||||
|
||||
picIn.Img.ICsp = encoder.csp
|
||||
picIn.Img.IPlane = 3
|
||||
picIn.Img.IStride[0] = encoder.width
|
||||
picIn.Img.IStride[1] = encoder.width >> 1
|
||||
picIn.Img.IStride[2] = encoder.width >> 1
|
||||
|
||||
picIn.Img.Plane[0] = C.malloc(C.size_t(encoder.lumaSize))
|
||||
picIn.Img.Plane[1] = C.malloc(C.size_t(encoder.chromaSize))
|
||||
picIn.Img.Plane[2] = C.malloc(C.size_t(encoder.chromaSize))
|
||||
|
||||
encoder.y = unsafe.Slice((*byte)(picIn.Img.Plane[0]), encoder.lumaSize)
|
||||
encoder.u = unsafe.Slice((*byte)(picIn.Img.Plane[1]), encoder.chromaSize)
|
||||
encoder.v = unsafe.Slice((*byte)(picIn.Img.Plane[2]), encoder.chromaSize)
|
||||
|
||||
encoder.in = &picIn
|
||||
|
||||
if encoder.ref = EncoderOpen(¶m); encoder.ref == nil {
|
||||
err = fmt.Errorf("x264: cannot open the encoder")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -122,15 +110,16 @@ func NewEncoder(w, h int, opts *Options) (encoder *H264, err error) {
|
|||
func LibVersion() int { return int(Build) }
|
||||
|
||||
func (e *H264) LoadBuf(yuv []byte) {
|
||||
copy(e.y, yuv[:e.lumaSize])
|
||||
copy(e.u, yuv[e.lumaSize:e.lumaSize+e.chromaSize])
|
||||
copy(e.v, yuv[e.lumaSize+e.chromaSize:])
|
||||
e.in.Img.Plane[0] = uintptr(unsafe.Pointer(&yuv[0]))
|
||||
e.in.Img.Plane[1] = uintptr(unsafe.Pointer(&yuv[e.lumaSize]))
|
||||
e.in.Img.Plane[2] = uintptr(unsafe.Pointer(&yuv[e.lumaSize+e.chromaSize]))
|
||||
}
|
||||
|
||||
func (e *H264) Encode() []byte {
|
||||
e.in.IPts += 1
|
||||
if ret := EncoderEncode(e.ref, e.nals, &e.nnals, e.in, e.out); ret > 0 {
|
||||
return C.GoBytes(e.nals[0].PPayload, C.int(ret))
|
||||
return unsafe.Slice((*byte)(e.nals[0].PPayload), ret)
|
||||
//return C.GoBytes(e.nals[0].PPayload, C.int(ret))
|
||||
}
|
||||
return []byte{}
|
||||
}
|
||||
|
|
@ -148,10 +137,6 @@ func (e *H264) SetFlip(b bool) {
|
|||
}
|
||||
|
||||
func (e *H264) Shutdown() error {
|
||||
e.y = nil
|
||||
e.u = nil
|
||||
e.v = nil
|
||||
e.in.freePlanes()
|
||||
EncoderClose(e.ref)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
29
pkg/encoder/h264/x264_test.go
Normal file
29
pkg/encoder/h264/x264_test.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package h264
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestH264Encode(t *testing.T) {
|
||||
h264, err := NewEncoder(120, 120, nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
data := make([]byte, 120*120*1.5)
|
||||
h264.LoadBuf(data)
|
||||
h264.Encode()
|
||||
if err := h264.Shutdown(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark(b *testing.B) {
|
||||
w, h := 1920, 1080
|
||||
h264, err := NewEncoder(w, h, nil)
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
data := make([]byte, int(float64(w)*float64(h)*1.5))
|
||||
for i := 0; i < b.N; i++ {
|
||||
h264.LoadBuf(data)
|
||||
h264.Encode()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue