mirror of
https://github.com/pion/mediadevices.git
synced 2025-10-07 09:31:03 +08:00
99 lines
2.2 KiB
C
99 lines
2.2 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <x264.h>
|
|
|
|
#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);
|
|
}
|