mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-08-03 07:13:08 +00:00
Make x264 glue code not mem-pinned
This commit is contained in:
parent
99976dd560
commit
ede15c4fe5
1 changed files with 68 additions and 48 deletions
|
|
@ -8,25 +8,72 @@ package h264
|
|||
#include "stdint.h"
|
||||
#include "x264.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
x264_t *h;
|
||||
x264_nal_t *nal; // array of NALs
|
||||
int i_nal; // number of NALs
|
||||
int y; // Y size
|
||||
int uv; // U or V size
|
||||
x264_picture_t pic;
|
||||
x264_picture_t pic_out;
|
||||
} h264;
|
||||
|
||||
h264 *h264_new(x264_param_t *param)
|
||||
{
|
||||
h264 tmp;
|
||||
x264_picture_t pic;
|
||||
|
||||
tmp.h = x264_encoder_open(param);
|
||||
if (!tmp.h)
|
||||
return NULL;
|
||||
|
||||
x264_picture_init(&pic);
|
||||
pic.img.i_csp = param->i_csp;
|
||||
pic.img.i_plane = 3;
|
||||
pic.img.i_stride[0] = param->i_width;
|
||||
pic.img.i_stride[1] = param->i_width >> 1;
|
||||
pic.img.i_stride[2] = param->i_width >> 1;
|
||||
tmp.pic = pic;
|
||||
|
||||
// crashes during x264_picture_clean :/
|
||||
//if (x264_picture_alloc(&pic, param->i_csp, param->i_width, param->i_height) < 0)
|
||||
// return NULL;
|
||||
|
||||
tmp.y = param->i_width * param->i_height;
|
||||
tmp.uv = tmp.y >> 2;
|
||||
|
||||
h264 *h = malloc(sizeof(h264));
|
||||
*h = tmp;
|
||||
return h;
|
||||
}
|
||||
|
||||
int h264_encode(h264 *h, uint8_t *yuv)
|
||||
{
|
||||
h->pic.img.plane[0] = yuv;
|
||||
h->pic.img.plane[1] = h->pic.img.plane[0] + h->y;
|
||||
h->pic.img.plane[2] = h->pic.img.plane[1] + h->uv;
|
||||
h->pic.i_pts += 1;
|
||||
return x264_encoder_encode(h->h, &h->nal, &h->i_nal, &h->pic, &h->pic_out);
|
||||
}
|
||||
|
||||
void h264_destroy(h264 *h)
|
||||
{
|
||||
if (h == NULL) return;
|
||||
x264_encoder_close(h->h);
|
||||
free(h);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type H264 struct {
|
||||
ref *C.x264_t
|
||||
|
||||
nal *C.x264_nal_t // array of NALs
|
||||
cNal *C.int // number of NALs
|
||||
y int // Y size
|
||||
uv int // U or V size
|
||||
in, out *C.x264_picture_t
|
||||
|
||||
p runtime.Pinner
|
||||
h *C.h264
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
|
|
@ -100,46 +147,18 @@ func NewEncoder(w, h int, th int, opts *Options) (encoder *H264, err error) {
|
|||
param.rc.i_rc_method = C.X264_RC_CRF
|
||||
param.rc.f_rf_constant = C.float(opts.Crf)
|
||||
|
||||
encoder = &H264{
|
||||
y: w * h,
|
||||
uv: w * h / 4,
|
||||
cNal: new(C.int),
|
||||
nal: new(C.x264_nal_t),
|
||||
out: new(C.x264_picture_t),
|
||||
in: &C.x264_picture_t{
|
||||
img: C.x264_image_t{
|
||||
i_csp: param.i_csp,
|
||||
i_plane: 3,
|
||||
i_stride: [4]C.int{0: C.int(w), 1: C.int(w >> 1), 2: C.int(w >> 1)},
|
||||
},
|
||||
},
|
||||
ref: C.x264_encoder_open(¶m),
|
||||
h264 := C.h264_new(¶m)
|
||||
if h264 == nil {
|
||||
return nil, fmt.Errorf("x264: cannot open the encoder")
|
||||
}
|
||||
|
||||
if encoder.ref == nil {
|
||||
err = fmt.Errorf("x264: cannot open the encoder")
|
||||
}
|
||||
return
|
||||
return &H264{h264}, nil
|
||||
}
|
||||
|
||||
func (e *H264) Encode(yuv []byte) []byte {
|
||||
e.in.img.plane[0] = (*C.uchar)(unsafe.Pointer(&yuv[0]))
|
||||
e.in.img.plane[1] = (*C.uchar)(unsafe.Pointer(&yuv[e.y]))
|
||||
e.in.img.plane[2] = (*C.uchar)(unsafe.Pointer(&yuv[e.y+e.uv]))
|
||||
|
||||
e.in.i_pts += 1
|
||||
|
||||
e.p.Pin(e.in.img.plane[0])
|
||||
e.p.Pin(e.in.img.plane[1])
|
||||
e.p.Pin(e.in.img.plane[2])
|
||||
|
||||
e.p.Pin(e.nal)
|
||||
bytes := C.x264_encoder_encode(e.ref, &e.nal, e.cNal, e.in, e.out)
|
||||
e.p.Unpin()
|
||||
|
||||
bytes := C.h264_encode(e.h, (*C.uchar)(unsafe.SliceData(yuv)))
|
||||
// we merge multiple NALs stored in **nal into a single byte stream
|
||||
// ret contains the total size of NALs in bytes, i.e. each e.nal[...].p_payload * i_payload
|
||||
return unsafe.Slice((*byte)(e.nal.p_payload), bytes)
|
||||
return unsafe.Slice((*byte)(e.h.nal.p_payload), bytes)
|
||||
}
|
||||
|
||||
func (e *H264) IntraRefresh() {
|
||||
|
|
@ -150,15 +169,16 @@ func (e *H264) Info() string { return fmt.Sprintf("x264: v%v", Version()) }
|
|||
|
||||
func (e *H264) SetFlip(b bool) {
|
||||
if b {
|
||||
e.in.img.i_csp |= C.X264_CSP_VFLIP
|
||||
(*e.h).pic.img.i_csp |= C.X264_CSP_VFLIP
|
||||
} else {
|
||||
e.in.img.i_csp &= ^C.X264_CSP_VFLIP
|
||||
(*e.h).pic.img.i_csp &= ^C.X264_CSP_VFLIP
|
||||
}
|
||||
}
|
||||
|
||||
func (e *H264) Shutdown() error {
|
||||
C.x264_encoder_close(e.ref)
|
||||
e.p.Unpin()
|
||||
if e.h != nil {
|
||||
C.h264_destroy(e.h)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue