diff --git a/pkg/config/config.yaml b/pkg/config/config.yaml index 59a123bfa..95dc4e4db 100644 --- a/pkg/config/config.yaml +++ b/pkg/config/config.yaml @@ -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 diff --git a/pkg/encoder/h264/libx264.go b/pkg/encoder/h264/libx264.go index 775f9563f..0539b437b 100644 --- a/pkg/encoder/h264/libx264.go +++ b/pkg/encoder/h264/libx264.go @@ -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)) } diff --git a/pkg/encoder/h264/x264.go b/pkg/encoder/h264/x264.go index c4b4ea00d..ee7cb0972 100644 --- a/pkg/encoder/h264/x264.go +++ b/pkg/encoder/h264/x264.go @@ -1,7 +1,5 @@ package h264 -// #include -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 } diff --git a/pkg/encoder/h264/x264_test.go b/pkg/encoder/h264/x264_test.go new file mode 100644 index 000000000..e819ba187 --- /dev/null +++ b/pkg/encoder/h264/x264_test.go @@ -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() + } +}