#include #include #include #include #define ERR_DEFAULT_PRESET -1 #define ERR_APPLY_PROFILE -2 #define ERR_ALLOC_PICTURE -3 #define ERR_OPEN_ENGINE -4 #define ERR_ENCODE -5 typedef struct Slice { unsigned char *data; int data_len; } Slice; typedef struct Encoder { x264_t *h; x264_picture_t pic_in, pic_out; x264_param_t param; } Encoder; Encoder *enc_new(x264_param_t param, char *preset, int *rc) { Encoder *e = (Encoder *)malloc(sizeof(Encoder)); if (x264_param_default_preset(&e->param, preset, "zerolatency") < 0) { free(preset); *rc = ERR_DEFAULT_PRESET; goto fail; } free(preset); /* Configure non-default params */ e->param.i_csp = param.i_csp; e->param.i_width = param.i_width; e->param.i_height = param.i_height; e->param.i_fps_num = param.i_fps_num; e->param.i_fps_den = 1; // Intra refres: e->param.i_keyint_max = param.i_keyint_max; // Rate control: e->param.rc.i_rc_method = X264_RC_ABR; e->param.rc.i_bitrate = param.rc.i_bitrate; e->param.rc.i_vbv_max_bitrate = param.rc.i_vbv_max_bitrate; e->param.rc.i_vbv_buffer_size = param.rc.i_vbv_buffer_size; // For streaming: e->param.b_repeat_headers = 1; e->param.b_annexb = 1; if (x264_param_apply_profile(&e->param, "high") < 0) { *rc = ERR_APPLY_PROFILE; goto fail; } if (x264_picture_alloc(&e->pic_in, param.i_csp, param.i_width, param.i_height) < 0) { *rc = ERR_ALLOC_PICTURE; goto fail; } e->h = x264_encoder_open(&e->param); if (!e->h) { *rc = ERR_OPEN_ENGINE; x264_picture_clean(&e->pic_in); goto fail; } return e; fail: free(e); return NULL; } Slice enc_encode(Encoder *e, uint8_t *y, uint8_t *cb, uint8_t *cr, int *rc) { x264_nal_t *nal; int i_nal; e->pic_in.img.plane[0] = y; e->pic_in.img.plane[1] = cb; e->pic_in.img.plane[2] = cr; int frame_size = x264_encoder_encode(e->h, &nal, &i_nal, &e->pic_in, &e->pic_out); Slice s = {.data_len = frame_size}; if (frame_size <= 0) { *rc = ERR_ENCODE; return s; } e->pic_in.i_pts++; s.data = nal->p_payload; return s; } void enc_close(Encoder *e, int *rc) { x264_encoder_close(e->h); x264_picture_clean(&e->pic_in); free(e); }