webrtc视频卡顿分析一本地视频卡顿

视频卡顿几个原因

1、网络抖动,丢包

2、发布端因设置码率不够丢帧或因cpu处理不及时丢帧

3、显卡渲染能力不足

4、逻辑有问题导致渲染间隔不均匀

最近在处理高帧率,高分辨率时遇到视频帧卡顿,抖动问题,记录处理过程,下面分析几个可能出现卡顿的流程

一、本地视频卡顿排查

1、本地采集伪代码

CaptureSinkFilter::ProcessCapturedFrame  //循环执行采集                                               //
{
       VideoCaptureImpl::IncomingFrame //分辨率格式安全检查  ,缩放    
       {
               ConvertToI420 //格式转换
               CropAndScaleFrom // 如果不是目标分辨率 缩放
               VideoCaptureImpl::DeliverCapturedFrame//传递
               {
                       _dataCallBack->OnIncomingCapturedFrame//传递到自定义的capture接收接口
                       {
							OnIncomingCapturedFrame//自定义的采集接收接口
                           {
                                  sink_->OnFrame//编码器接收接口
                                  {
                                     	ViEEncoder::OnFrame //编码器接收到采集的视频帧,放入任务队列
                                     	{
                                     			incoming_frame.set_render_time_ms //设置采集时间
                                     			incoming_frame.set_ntp_time_ms //设置ntp ,rtcp sr用
                                     			incoming_frame.set_timestamp //设置时间戳,rtp用
                                     			encoder_queue_.PostTask //放入编码队列
                                     	}
                                   }
                            }
                      }
               }
       }
}

这个过程除了格式错误,没有地方进行丢帧处理

2、本地调用渲染伪代码

前面采集的帧已经放入队列,后面编码线程从队列中取出数据,在取数据的时候有丢帧处理

TaskQueue::ProcessQueuedMessages //循环执行任务
{
	ViEEncoder::EncodeTask::Run()  //执行编码 本地显示
	{
		if (--vie_encoder_->posted_frames_waiting_for_encode_ == 0) //如果任务队列只有一帧,则执行编码,超过一帧的就丢弃
		{
			 vie_encoder_->EncodeVideoFrame //执行编码
			 {
			 	pre_encode_callback_->OnFrame  //本地渲染
			    {
			    	RTCD3dRenderer::OnFrame //执行渲染
			    }
			 	EncoderPaused() //判断是否丢帧
			 }
		}
		else
		{
			++vie_encoder_->dropped_frame_count_ //丢弃,当cpu能力不足,造成队列堆积会丢帧处理
		}
	}
}

由此看来本地视频卡顿,可能有以下几个原因
1、cpu处理不及时,造成队列堆积,丢弃
2、渲染和编码一个线程,会不会存在因编码造成的渲染间隔不均匀?
3、显卡渲染有问题,渲染展现出的卡顿
4、摄像头采集到的就是不均匀的

3、具体原因分析

配置:cpu: amd R5-2400G 集显,相当于gtx1030
摄像头:1080p60 usb3.0
现象:本地渲染出现卡顿

步骤1、怀疑是cpu处理不及时,丢帧,或者编码慢,导致渲染不均匀,先把编码逻辑去掉,只做渲染

void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
                                  int64_t time_when_posted_in_ms) 
{
  RTC_DCHECK_RUN_ON(&encoder_queue_);
  if (pre_encode_callback_)
  {
	  pre_encode_callback_->OnFrame(video_frame);
  }
  return; //在此直接返回,不做编码处理,只渲染
}

测试发现,依然卡顿,尤其是在背景是高亮的情况下

步骤2、确认不是cpu造成的,日志打印渲染,查看渲染时间

n:1559288807289 c:1226 du:12 ---------------------------
n:1559288807303 c:1240 du:14 ---------------------------
n:1559288807320 c:1644 du:17
n:1559288807337 c:1578 du:17
n:1559288807352 c:1413 du:15
n:1559288807371 c:1595 du:19 ---------------------------
n:1559288807386 c:1609 du:15
n:1559288807405 c:1906 du:19 ---------------------------
n:1559288807419 c:1233 du:14 ---------------------------
n:1559288807437 c:1720 du:18 ---------------------------
n:1559288807453 c:1348 du:16
n:1559288807471 c:1716 du:18 ---------------------------
n:1559288807489 c:1614 du:18 ---------------------------
n:1559288807503 c:1226 du:14 ---------------------------
n:1559288807521 c:1667 du:18 ---------------------------
n:1559288807537 c:1330 du:16
n:1559288807554 c:1582 du:17
n:1559288807572 c:1633 du:18 ---------------------------
n:1559288807586 c:1210 du:14 ---------------------------
n:1559288807603 c:1612 du:17
n:1559288807622 c:1795 du:19 ---------------------------
n:1559288807636 c:1518 du:14 ---------------------------
n:1559288807653 c:1749 du:17
n:1559288807671 c:1704 du:18 ---------------------------

可以看到帧率不稳定,间隔时间应该是16,17ms,但在明暗变化的时候,进一步确认是摄像头硬件问题 还是 逻辑问题
步骤3、在最接近摄像头采集出来的地方,日志打印

int32_t VideoCaptureImpl::IncomingFrame(
    uint8_t* videoFrame,
    size_t videoFrameLength,
    const VideoCaptureCapability& frameInfo,
    int64_t captureTime/*=0*/)
//在这个函数直接打印日志, 返回
1559289895617 capture time:2430 cost 17 
1559289895634 capture time:2447 cost 17 
1559289895650 capture time:2463 cost 16 
1559289895667 capture time:2480 cost 17 
1559289895684 capture time:2497 cost 17 
1559289895700 capture time:2513 cost 16 
1559289895717 capture time:2530 cost 17 
1559289895817 capture time:2630 cost 100  error 2433--------------
1559289895834 capture time:2647 cost 17 
1559289895851 capture time:2664 cost 17 
1559289895867 capture time:2680 cost 16 
1559289895884 capture time:2697 cost 17 
1559289895901 capture time:2714 cost 17 
1559289895917 capture time:2730 cost 16 
1559289895934 capture time:2747 cost 17 
1559289895951 capture time:2764 cost 17 
1559289895967 capture time:2780 cost 16 
1559289895984 capture time:2797 cost 17 
1559289896001 capture time:2814 cost 17 
1559289896017 capture time:2830 cost 16 
1559289896034 capture time:2847 cost 17 
1559289896051 capture time:2864 cost 17 
1559289896067 capture time:2880 cost 16 

总体来说比较均匀,偶尔一次比较大,可能是因为摄像头硬件问题,或者usb传输导致,暂且放过

原因在哪呢

怀疑是这个转换,有的摄像头采集出来的不是yuv420,需要做转换,这个转换需要时间

VideoCaptureImpl::IncomingFrame
{
	ConvertToI420  //转换
	VideoFrame captureFrame(buffer, 0, rtc::TimeMillis(), !apply_rotation ? _rotateFrame : kVideoRotation_0);//在此设置的capture 时间,是有问题的
}

正常情况下先转格式,再赋值时间没什么影响,但是在大分辨率先转换,再赋值,可能会有几ms的差异,会出现卡顿,稍后验证一下。我先写个渲染,加个平滑机制试试

你可能感兴趣的:(webrtc)