【obs-studio开源项目从入门到放弃】obs中 x264编码器的使用


前言

obs系列文章入口:https://blog.csdn.net/qq_33844311/article/details/121479224

目前使用最广泛的视频编码格式依然是h264编码,开源的编码库有x264OpenH264,obs-studio使用的libx264编码,webRTC使用OpenH264。具体两者之间的优劣,这里不做讨论。这篇blog主要分析一下obs是怎么将libx264作为编码器,以及用于直播低延迟编码的x264参数设置。

x264编码器的创建

设置好断点,点击UI开始推流,得到以下堆栈。可以看到x264编码器的创建是在obs_output_initialize_encoders() 函数里面创建视频编码器和音频编码器。

>	obs-x264.dll!obs_x264_create(obs_data * settings, obs_encoder * encoder)688	C
 	obs.dll!obs_encoder_initialize_internal(obs_encoder * encoder)462	C
 	obs.dll!obs_encoder_initialize(obs_encoder * encoder)507	C
 	obs.dll!obs_output_initialize_encoders(obs_output * output, unsigned int flags)2100	C 创建视频编码器和音频编码器
 	obs-outputs.dll!rtmp_stream_start(void * data)1158	C
 	obs.dll!obs_output_actual_start(obs_output * output)256	C
 	obs.dll!obs_output_start(obs_output * output)293	C
 	obs64.exe!AdvancedOutput::StartStreaming(obs_service * service)1836	C++
 	obs64.exe!OBSBasic::StartStreaming()6449	C++
 	obs64.exe!OBSBasic::on_streamButton_clicked()7559	C++
 	obs64.exe!OBSBasic::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a)1305	C++
 	obs64.exe!OBSBasic::qt_metacall(QMetaObject::Call _c, int _id, void * * _a)1500	C++
 	[外部代码]	
 	obs64.exe!run_program(std::basic_fstream<char,std::char_traits<char>> & logFile, int argc, char * * argv)2143	C++
 	obs64.exe!main(int argc, char * * argv)2839	C++
 	obs64.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal)97	C++

obs_x264_create() 创建x264编码器

static void *obs_x264_create(obs_data_t *settings, obs_encoder_t *encoder)
{
	struct obs_x264 *obsx264 = bzalloc(sizeof(struct obs_x264));
	obsx264->encoder = encoder;
	
	// 设置编码器参数
	if (update_settings(obsx264, settings, false)) {
		//调用x264的api创建编码器上下文 x264_t *context
		//参考:https://blog.csdn.net/weixin_34256074/article/details/90656698
		obsx264->context = x264_encoder_open(&obsx264->params);

		if (obsx264->context == NULL)
			warn("x264 failed to load");
		else
			//加载SPS/PPS/SEI这些H.264码流的头信息
			load_headers(obsx264);
	} else {
		warn("bad settings specified");
	}
	// 打开编码器失败判断
	if (!obsx264->context) {
		bfree(obsx264);
		return NULL;
	}
	// windows平台该接口无用,其他平台看源码具体实现吧
	obsx264->performance_token = os_request_high_performance("x264 encoding");
	return obsx264;
}

x264编码视频帧

通过调用堆栈分析,在视频编码线程中调用 obs_x264_encode 完成视频编码。
obs视频编码线程的介绍参考这篇文章:https://blog.csdn.net/qq_33844311/article/details/121745673

>	obs-x264.dll!obs_x264_encode(void * data, encoder_frame * frame, encoder_packet * packet, bool * received_packet)764	C
 	obs.dll!do_encode(obs_encoder * encoder, encoder_frame * frame)984	C
 	obs.dll!receive_video(void * param, video_data * frame)1056	C
 	obs.dll!video_output_cur_frame(video_output * video)143	C
 	obs.dll!video_thread(void * param)188	C	//视频编码线程
 	w32-pthreads.dll!ptw32_threadStart(void * vthreadParms)225	C

obs_x264_encode() 编码一帧视频

真正的将原始视频帧编码成nalu视频包的接口 obs_x264_encode,主要是通过调用x264的编码api完成原始视频编码。代码比较简单,看注释即可。

static bool obs_x264_encode(void *data, struct encoder_frame *frame,
			    struct encoder_packet *packet,
			    bool *received_packet)
{
	struct obs_x264 *obsx264 = data;
	x264_nal_t *nals;
	int nal_count;
	int ret;
	x264_picture_t pic, pic_out;

	if (!frame || !packet || !received_packet)
		return false;
	// 初始化编码信息,将frame的图像数据指针复制给x264的上下文 pic->img.plane
	if (frame)
		init_pic_data(obsx264, &pic, frame);
	//调用x264的编码api完成原始视频的编码
	ret = x264_encoder_encode(obsx264->context, &nals, &nal_count,
				  (frame ? &pic : NULL), &pic_out);
	if (ret < 0) {
		warn("encode failed");
		return false;
	}
	// nal_count > 0表示编码成功
	*received_packet = (nal_count != 0);
	// 将编码后的视频nal拷贝到 packet,送出去打包flv发送
	parse_packet(obsx264, packet, nals, nal_count, &pic_out);

	return true;
}

x264低延迟编码参数的设置

x264支持非常丰富的编码参数设置,针对不同的场景,有不同的编码参数设置。有三个非常重要的影响编码的速度和编码图像质量的参数。

  • preset
  • profile
  • tune

想要了解更多的x264编码参数的设置,建议多找些资料,多测试不同的编码参数的表现效果(图像质量、编码延迟),找到最适合自己场景的编码参数设置,没有一劳永逸的编码参数设置。

这里提供一个在直播场景低延迟编码的参数设置,以下的设置基本上是编码延迟最低的设置。
缺点:会牺牲一些图像质量。
优点:编码延迟极低。

//=======超低延迟编码参数========
preset=ultrafast
profile=baseline
tune=zerolatency

总结

obs的软件编码使用的x264,软件编码的兼容性最好,在同等码率条件下,图像质量也好于硬件编码。这块儿的代码比较好理解,主要是针对自己的直播场景,或者录制场景,找到适合自己的编码参数。对x264编码原理感兴趣的可以多找些资料研究下,视频编码原理这块我也正在学习。

以上都是个人工作当中对obs-studio开源项目的理解,难免有错误的地方,如果有欢迎指出。

若有帮助幸甚。

技术参考

  1. 视频技术参考: https://ke.qq.com/course/3202131?flowToken=1041285
  2. x264代码剖析1:https://blog.csdn.net/lifei092/article/details/81907312
  3. x264代码剖析2:https://blog.csdn.net/weixin_34256074/article/details/90656698
  4. x264编码参数说明:https://www.jianshu.com/p/b46a33dd958d
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值