x264 yuv to h264 c99
如何编译引入x264
正式编码
#include <stdint.h>
#include <x264.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define CLEAR(x) (memset((&x),0,sizeof(x)))
#define IMAGE_WIDTH 1920
#define IMAGE_HEIGHT 1080
#define ENCODER_PRESET "veryfast"
#define ENCODER_TUNE "zerolatency"
#define ENCODER_PROFILE "baseline"
#define ENCODER_COLORSPACE X264_CSP_I420
typedef struct my_x264_encoder
{
x264_param_t* x264_parameter;
char parameter_preset[20];
char parameter_tune[20];
char parameter_profile[20];
x264_t* x264_encoder;
x264_picture_t* yuv420p_picture;
long colorspace;
unsigned char* yuv;
x264_nal_t* nal;
} my_x264_encoder;
char* read_filename = "/Users/jimogangdan/Downloads/video1.yuv";
char* write_filename = "/Users/jimogangdan/CLionProjects/x264_encoder/video1.h264";
int main(int argc, char** argv)
{
// 初始化my_x264_encoder结构体,并设置编码器的参数preset、tune
my_x264_encoder* encoder = malloc(sizeof(my_x264_encoder));
if (!encoder)
{
printf("cannot malloc my_x264_encoder !\n");
exit(EXIT_FAILURE);
}
CLEAR(*encoder);
strcpy(encoder->parameter_preset, ENCODER_PRESET); // 高速编码
strcpy(encoder->parameter_tune, ENCODER_TUNE); //低延迟
// 参数初始化
encoder->x264_parameter = (x264_param_t*)malloc(sizeof(x264_param_t));
if (!encoder->x264_parameter)
{
printf("malloc x264_parameter error!\n");
exit(EXIT_FAILURE);
}
CLEAR(*(encoder->x264_parameter));
// 分配内存并初始化x264参数对象x264_param_t,设置视频帧宽高、关键帧间隔、B帧数等编码参数。
x264_param_default(encoder->x264_parameter);
if (x264_param_default_preset(encoder->x264_parameter, encoder->parameter_preset, encoder->parameter_tune) < 0)
{
printf("x264_param_default_preset error!\n");
exit(EXIT_FAILURE);
}
// 编码参数
encoder->x264_parameter->i_threads = X264_SYNC_LOOKAHEAD_AUTO; //自适应线程数
encoder->x264_parameter->i_width = IMAGE_WIDTH; // 分辨率的宽度
encoder->x264_parameter->i_height = IMAGE_HEIGHT; // 分辨率的高度
encoder->x264_parameter->i_frame_total = 0; // 帧总数 默认0
encoder->x264_parameter->i_keyint_max = 25; // I帧最大间隔
encoder->x264_parameter->i_bframe = 5; // B帧的数量
encoder->x264_parameter->b_open_gop = 0; // 闭合式GOP 不共享帧
encoder->x264_parameter->i_bframe_pyramid = 0; // 关闭了B帧金字塔模式 按照默认顺序
encoder->x264_parameter->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; // 帧自适应性模式中采用 Trellis 模式
// 流参数
encoder->x264_parameter->i_fps_den = 1; //fps帧率的分母 不限制帧率
encoder->x264_parameter->i_fps_num = 25; //fps帧率的分子 每秒25帧
encoder->x264_parameter->b_intra_refresh = 1; // 启用了关键帧刷新模式 周期性地额外插入关键帧
encoder->x264_parameter->b_annexb = 1; // 输出的AnnexB格式为比特流
// 日志
encoder->x264_parameter->i_log_level = X264_LOG_DEBUG;
// 打开编码器
strcpy(encoder->parameter_profile, ENCODER_PROFILE);
encoder->x264_encoder = x264_encoder_open(encoder->x264_parameter);
encoder->colorspace = ENCODER_COLORSPACE; // 颜色空间格式使用YUV420
// yuv初始化
encoder->yuv420p_picture = (x264_picture_t*)malloc(sizeof(x264_picture_t));
if (!encoder->yuv420p_picture)
{
printf("malloc encoder->yuv420p_picture error!\n");
exit(EXIT_FAILURE);
}
if (x264_picture_alloc(encoder->yuv420p_picture, encoder->colorspace,IMAGE_WIDTH,IMAGE_HEIGHT) < 0)
{
printf("ret=%d\n", -1);
printf("x264_picture_alloc error!\n");
exit(EXIT_FAILURE);
}
// yuv 模型、平面、类型参数
encoder->yuv420p_picture->img.i_csp = encoder->colorspace;
encoder->yuv420p_picture->img.i_plane = 3; // 平面数设置为 3 包含亮度(Y)平面和两个色度(UV)平面
encoder->yuv420p_picture->i_type = X264_TYPE_AUTO; // 图像的类型设置为自动类型
// 指定帧的像素数目
encoder->yuv = (uint8_t*)malloc(IMAGE_WIDTH * IMAGE_HEIGHT * 3 / 2);
if (!encoder->yuv)
{
printf("malloc yuv error!\n");
exit(EXIT_FAILURE);
}
CLEAR(*(encoder->yuv));
// Y 、U 、V分量的数据关联起始地址
encoder->yuv420p_picture->img.plane[0] = encoder->yuv;
encoder->yuv420p_picture->img.plane[1] = encoder->yuv + IMAGE_WIDTH * IMAGE_HEIGHT;
encoder->yuv420p_picture->img.plane[2] = encoder->yuv + IMAGE_WIDTH * IMAGE_HEIGHT + IMAGE_WIDTH * IMAGE_HEIGHT / 4;
// 打开yuv源文件
int fd_read, fd_write;
if ((fd_read = open(read_filename,O_RDONLY)) < 0)
{
printf("cannot open input file!\n");
exit(EXIT_FAILURE);
}
// 打开h264目标文件
if ((fd_write = open(write_filename,O_WRONLY | O_APPEND | O_CREAT, 0777)) < 0)
{
printf("cannot open output file!\n");
exit(EXIT_FAILURE);
}
// nal单元初始化
encoder->nal = (x264_nal_t*)malloc(sizeof(x264_nal_t));
if (!encoder->nal)
{
printf("malloc x264_nal_t error!\n");
exit(EXIT_FAILURE);
}
CLEAR(*(encoder->nal));
// 数据读入到encoder->yuv纳冲中
int n_nal = 0;
x264_picture_t pic_out;
x264_nal_t* my_nal;
while (read(fd_read, encoder->yuv,IMAGE_WIDTH * IMAGE_HEIGHT * 3 / 2) > 0)
{
encoder->yuv420p_picture->i_pts++; // 自增时间帧
if (x264_encoder_encode(encoder->x264_encoder, &encoder->nal, &n_nal, encoder->yuv420p_picture, &pic_out) < 0)
{
printf("x264_encoder_encode error!\n");
exit(EXIT_FAILURE);
}
// 读取当前缓冲全部NAL单元
for (my_nal = encoder->nal; my_nal < encoder->nal + n_nal; ++my_nal)
{
//写入数据内容p_payload ,写入长度i_payload
write(fd_write, my_nal->p_payload, my_nal->i_payload);
}
}
// 释放内存
free(encoder->yuv);
free(encoder->yuv420p_picture);
free(encoder->x264_parameter);
x264_encoder_close(encoder->x264_encoder);
free(encoder);
// 关闭文件
close(fd_read);
close(fd_write);
return 0;
}
本文来自博客园,作者:vx_guanchaoguo0,转载请注明原文链接:https://www.cnblogs.com/guanchaoguo/p/18025198