现象是视频通话,给FS配置录制到rtsp服务器,单路通话Freeswitch占用CPU高:
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
录制配置:
//录本端 <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方法:
		//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方法:
#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是否一致:
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%左右:
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%
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
 本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com
:您好~我是腾讯云开发者社区运营,关注了您分享的技术文章,觉得内容很棒,我们诚挚邀请您加入腾讯云自媒体分享计划。完整福利和申请地址请见:https://cloud.tencent.com/developer/support-plan作者申请此计划后将作者的文章进行搬迁同步到社区的专栏下,你只需要简单填写一下表单申请即可,我们会给作者提供包括流量、云服务器等,另外还有些周边礼物。
2022-07-20 10:33:41 回复