如何使用x264 C API将RBG图像编码为H264帧?我已经创建了一系列RBG图像,现在如何将该序列转换为H264帧的序列?特别是,如何将这一系列RGB图像编码为H264帧序列,该序列由单个初始H264关键帧和从属H264帧组成?

推荐答案

首先:判断x264.h文件,它或多或少包含每个函数和 struct 的引用.x264.下载的c文件包含一个示例实现.大多数人都说要以这一点为基础,但我发现这对初学者来说相当复杂,不过这是一个很好的例子.

首先设置一些参数,类型为x264_param_t,描述参数的好站点是http://mewiki.project357.com/wiki/X264_Settings.还可以看看x264_param_default_preset函数,它允许您在不需要了解所有(有时相当复杂)参数的情况下针对某些功能.之后也使用x264_param_apply_profile(你可能需要"基线"配置文件)

以下是我的代码中的一些示例设置:

x264_param_t param;
x264_param_default_preset(&param, "veryfast", "zerolatency");
param.i_threads = 1;
param.i_width = width;
param.i_height = height;
param.i_fps_num = fps;
param.i_fps_den = 1;
// Intra refres:
param.i_keyint_max = fps;
param.b_intra_refresh = 1;
//Rate control:
param.rc.i_rc_method = X264_RC_CRF;
param.rc.f_rf_constant = 25;
param.rc.f_rf_constant_max = 35;
//For streaming:
param.b_repeat_headers = 1;
param.b_annexb = 1;
x264_param_apply_profile(&param, "baseline");

在此之后,您可以按如下方式初始化编码器

x264_t* encoder = x264_encoder_open(&param);
x264_picture_t pic_in, pic_out;
x264_picture_alloc(&pic_in, X264_CSP_I420, w, h)

X264需要YUV420P数据(我想其他一些也需要,但这是常见的).可以使用libswscale(来自ffmpeg)将图像转换为正确的格式.初始化过程如下(我假设RGB数据为24bpp).

struct SwsContext* convertCtx = sws_getContext(in_w, in_h, PIX_FMT_RGB24, out_w, out_h, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);

编码就像这样简单,那么对于每一帧都要这样做:

//data is a pointer to you RGB structure
int srcstride = w*3; //RGB stride is just 3*width
sws_scale(convertCtx, &data, &srcstride, 0, h, pic_in.img.plane, pic_in.img.stride);
x264_nal_t* nals;
int i_nals;
int frame_size = x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);
if (frame_size >= 0)
{
    // OK
}

我希望这能让你走;),我自己花了很长时间才开始.X264是一款功能强大但有时非常复杂的软件.

编辑:当您使用其他参数时,会出现延迟帧,而我的参数则不是这种情况(主要是由于nolatency选项).如果是这种情况,frame_size有时会为零,只要函数x264_encoder_delayed_frames不返回0,就必须调用x264_encoder_encode.但对于这个功能,您应该深入了解x264.c和x264.H

C++相关问答推荐

数组元素的编号索引

rSP堆栈指针在返回函数调用的值时有任何用途吗?

错误:在.h程序中重新定义 struct

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

ATTiny1606定时器TCA 0中断未触发

ESP32在vTaskDelay上崩溃

如何将字符串传递给函数并返回在C中更改的相同字符串?

模拟shell并运行.sh文件

Clang:如何强制运行时错误的崩溃/异常由于-fsanitize=undefined

LONG_DOUBLE_T是否存在(标准C:C23)

非正规化边缘毛刺

如何使用_newindex数组我总是得到错误的参数

在for循环中指向数组开头之前

当b是无符号字符时,int a=(b<;<;2)>;>;2;和int a=b&;0x3F;之间有什么区别?

为什么这个分配做得不好呢?

使用正则表达式获取字符串中标记的开始和结束

Realloc():中止的下一个大小无效(核心转储)

在下面的C程序中,.Ap0是如何解释的?

可以对两种 struct 类型中的任何一种进行操作的C函数

Ubuntu编译:C中的文件格式无法识别错误