前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Freeswitch单路带录制的视频通话CPU持续高到15%问题解决

Freeswitch单路带录制的视频通话CPU持续高到15%问题解决

作者头像
呱牛笔记
发布2023-05-02 15:47:29
5981
发布2023-05-02 15:47:29
举报
文章被收录于专栏:呱牛笔记呱牛笔记

现象是视频通话,给FS配置录制到rtsp服务器,单路通话Freeswitch占用CPU高:

代码语言:javascript
复制
?PID?USER??????PR??NI????VIRT????RES????SHR?S??%CPU??%MEM?????TIME+?
COMMAND?696684?root??????-2?-10??848068?144700??24264?S??15.0???3.6??23:25.80?freeswitch

录制配置:

代码语言:javascript
复制
//录本端
<action?application=\"set\"?data=\"execute_on_answer=record_session?rtsp://192.168.16.83/live/"?.?$this->account_id?.?"_".?$destination_number."\"/>"

CPU高主要发生在几个方面:

a_leg -> FS收包

? ? ? ? ? ? ? 配置了录制bug通达后,FS收包先会进行H264解码,然后在发送给对方前,再H264编码发给b_leg

? ? ? ? ? ? ? ? ->? ?FS将解码的img 通过record_callback 方法,调用switch_core_file_write写到rtsp流,这里使用的是avformat.c的实现;

FS要转流到rtsp服务器,需要修改avformat.c, 配置rtsp,修改av_file_open方法:

代码语言:javascript
复制
		//if?((handle->stream_name?&&?(!strcasecmp(handle->stream_name,?"rtmp")?||?!strcasecmp(handle->stream_name,?"rtmps"))))?{
		if?((handle->stream_name?&&?(!strcasecmp(handle->stream_name,?"rtmp")?||?!strcasecmp(handle->stream_name,?"rtmps")?||?!strcasecmp(handle->stream_name,?"rtsp"))))?{
			if?(fmt->video_codec?!=?AV_CODEC_ID_H264?)?{
				fmt->video_codec?=?AV_CODEC_ID_H264;?//?force?H264
			}

			fmt->audio_codec?=?AV_CODEC_ID_AAC;
			handle->samplerate?=?44100;
			handle->mm.samplerate?=?44100;
			handle->mm.ab?=?128;
			handle->mm.cbr?=?1;
			handle->mm.vencspd?=?SWITCH_VIDEO_ENCODE_SPEED_FAST;
			handle->mm.vprofile?=?SWITCH_VIDEO_PROFILE_BASELINE;

			if?(!handle->mm.vb?&&?handle->mm.vw?&&?handle->mm.vh)?{
				switch(handle->mm.vh)?{
				case?240:
					handle->mm.vb?=?400;
					break;
				case?360:
					handle->mm.vb?=?750;
					break;
				case?480:
					handle->mm.vb?=?1000;
					break;
				case?720:
					handle->mm.vb?=?2500;
					break;
				case?1080:
					handle->mm.vb?=?4500;
					break;
				default:
					handle->mm.vb?=?switch_calc_bitrate(handle->mm.vw,?handle->mm.vh,?1,?handle->mm.fps);
					break;
				}
			}

			if?(handle->mm.fps?>?0.0f)?{
				handle->mm.keyint?=?(int)?2.0f?*?handle->mm.fps;
			}
		}

		desc?=?avcodec_descriptor_get(fmt->video_codec);

		switch_log_printf(SWITCH_CHANNEL_LOG,?SWITCH_LOG_DEBUG,?"use?video?codec:?[%d]?%s?(%s)\n",?fmt->video_codec,?desc->name,?desc->long_name);
	}

?在av_file_write_video方法中,img会进行再次编码后发送出去;

所以一共有一次解码、两次编码,所以单路视频通话配置record_session后,CPU一直高的原因在这里;

怎么修改,首先H264转发前的编码可以不用做,因为两端都支持H264的情况下,不需要FS做中间的转码;

修改switch_core_media.c中的switch_core_session_write_video_frame方法:

代码语言:javascript
复制
#if?1//modify?for?no?need?encode?h264
??????{
?????????const?char?*s;
?????????if?((s?=?switch_channel_get_variable(session->channel,?"v_codec_match"))?&&?switch_true(s))?{
		switch_status_t?vstatus;

????????????//direct?proxy?packet.
		switch_set_flag((frame),?SFF_PROXY_PACKET);
		//switch_set_flag(frame,?SWITCH_RTP_FLAG_RAW_WRITE);//
	
		//switch_set_flag(frame,?SFF_RAW_RTP_PARSE_FRAME?|?SWITCH_RTP_FLAG_RAW_WRITE);
?
		//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),?SWITCH_LOG_INFO,?"%s?is?same?codec?no?need?encode.\n",?switch_channel_get_name(session->channel));
		vstatus?=?switch_core_session_write_encoded_video_frame(session,?frame,?flags,?stream_id);
		switch_goto_status(vstatus,?done);
?????????}else{
???????
????????	if?(!img)?{
????????		switch_status_t?vstatus;

????????		vstatus?=?switch_core_session_write_encoded_video_frame(session,?frame,?flags,?stream_id);
????????		switch_goto_status(vstatus,?done);
????????	}
?????????}
??????}
#else
???????
	if?(!img)?{
		switch_status_t?vstatus;

		vstatus?=?switch_core_session_write_encoded_video_frame(session,?frame,?flags,?stream_id);
		switch_goto_status(vstatus,?done);
	}

#endif

?在video_bridge_thread记录两端video的codec是否一致:

代码语言:javascript
复制
static?void?video_bridge_thread(switch_core_session_t?*session,?void?*obj)
????????????????#if?1
				if?(a_codec->implementation->impl_id?==?b_codec->implementation->impl_id){????????????????????????????
?????????????????????????????????switch_channel_set_variable(channel,?"v_codec_match",?"true");??????????????????????????
?????????????????????????????????switch_channel_set_variable(b_channel,?"v_codec_match",?"true");
				}else{?????????????
?????????????????????????????????switch_channel_set_variable(channel,?"v_codec_match",?"false");??????????????????????????
?????????????????????????????????switch_channel_set_variable(b_channel,?"v_codec_match",?"false");
???????????????????????????}
????????????????#endif//lyz?add?for?codec

结果,单路带录制的视频通话CPU降到了10%左右:

代码语言:javascript
复制
?PID?USER??????PR??NI????VIRT????RES????SHR?S??%CPU??%MEM?????TIME+?
COMMAND?696684?root??????-2?-10??848068?144700??24264?S??10.0???3.6??23:25.80?freeswitch

下一步计划是去掉record的视频编码动作,一并去掉收包的解码动作!

下篇:通过减少一次H264编码和两次H264解码,录制视频到RTSP服务器,cpu降到2%

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com