WebRTC的JitterBuffer笔记

本文介绍了视频接收流程中的关键组件,如PacketBuffer和FrameBuffer,以及如何判断帧的完整性。详细阐述了RTP包的管理,包括帧间延时计算、JitterDelay的卡尔曼滤波估计和渲染时间的确定。同时讨论了JitterBuffer的调优参数及其在视频帧渲染时间调整中的作用。
摘要由CSDN通过智能技术生成

 接收类图不全

一  主要的类

类video_coding::PacketBuffer是接收RTP包,类RtpVideoStreamReceiver2中有用到。

packet_buffer_(clock_, kPacketBufferStartSize, PacketBufferMaxSize()),最小值512,最大2048。

类video_coding::FrameBuffer是一帧完整的视频数据,类VideoReceiveStream2中有用到。

constexpr size_t kMaxFramesBuffered = 800; //最大缓存800帧

二  判断一帧数据是否完整

判断第一包、最后一包是否在一帧中

parsed_payload->type.Video.is_first_packet_in_frame = first_fragment;

//FU_A第二字节的SER的S

video_header.is_last_packet_in_frame |= rtp_packet.Marker(); //RTP包的mark位

void RtpVideoStreamReceiver2::OnInsertedPacket(
    video_coding::PacketBuffer::InsertResult result) {

   for (auto& packet : result.packets) {
    ...
    //把rtp包写成完整一帧数据,给video_coding::RtpFrameReferenceFinder管理
    OnAssembledFrame(std::make_unique<video_coding::RtpFrameObject>()
   }
}

RtpVideoStreamReceiver2::OnAssembledFrame(
--| reference_finder_->ManageFrame(std::move(frame));

三  帧间完整性判断—gop--没懂

把最后一包的seq作为pid-图片唯一标识。

四  FrameBuffer用在那 ? 解码

VideoReceiveStream2::OnCompleteFrame()
frame_buffer_->InsertFrame(std::move(frame));


VideoReceiveStream2::StartNextDecode() {
//NextFrame()获得frame,给HandleEncodedFrame解码
frame_buffer_->NextFrame()
 --|  frame = absl::WrapUnique(GetNextFrame());	
HandleEncodedFrame(std::move(frame));
}

五  JitterDelay的计算

//卡尔曼滤波器:在不确定的数据中估算出最优结果的算法。
//用卡尔曼kalman滤波估计(或预测) JitterDelay
计算公式如下:跟最大帧长度,平均帧长度等有关
JitterDelay = theta[0] * (MaxFS – AvgFS) + [noiseStdDevs * sqrt(varNoise) – noiseStdDevOffset]

double VCMJitterEstimator::CalculateEstimate(),返回值就是JitterDelay。

VCMJitterEstimator::UpdateEstimate
--| KalmanEstimateChannel(frameDelayMS, deltaFS);--更新公式参数的值

//获取jitter估计值,单位是毫秒
int VCMJitterEstimator::GetJitterEstimate(
    double rttMultiplier,
    absl::optional<double> rttMultAddCapMs)

// Updates the estimates with the new measurements.
void VCMJitterEstimator::UpdateEstimate(int64_t frameDelayMS,
                                        uint32_t frameSizeBytes,
                                        bool incompleteFrame /* = false */) 

六  JitterDelay:1 作用于从接收队列取数据的时间(意义在那?)  2 赋值给视频帧渲染时间

//帧间延时-->JitterDelay-->wait_ms:从接收队列取frame的时间
//wait_ms值在[0、3000]
int64_t VCMTiming::RenderTimeMsInternal(
{
  int64_t estimated_complete_time_ms =
      ts_extrapolator_->ExtrapolateLocalTime(frame_timestamp); //?
  return estimated_complete_time_ms + actual_delay;
}


EncodedFrame* FrameBuffer::GetNextFrame() 
{
 //帧间延时frame_delay传给滤波
 if (inter_frame_delay_.CalculateDelay(first_frame->Timestamp(),
                                          &frame_delay, receive_time_ms)) {
      jitter_estimator_.UpdateEstimate(frame_delay, superframe_size);
 }
 ...
 timing_->SetJitterDelay(
        jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms));
 ...
}

int64_t FrameBuffer::FindNextFrame(int64_t now_ms) 
{
  EncodedFrame* frame = frame_it->second.frame.get();

  if (frame->RenderTime() == -1) {		
        frame->SetRenderTime(timing_->RenderTimeMs(frame->Timestamp(), now_ms));		
  }
  //frame->RenderTime()即期望渲染时间-当前时间-解码所需时间-渲染延迟时间(值10ms)
  wait_ms = timing_->MaxWaitingTime(frame->RenderTime(), now_ms);
  
  return wait_ms;
}

七 RenderTime视频帧渲染时间,算出渲染等待时间

看有的文章说,动态调整jitterbuffer大小,没有,只是调整了渲染的时间。

void IncomingVideoStream::Dequeue() {  
  absl::optional<VideoFrame> frame_to_render = render_buffers_.FrameToRender();
  if (frame_to_render)
    callback_->OnFrame(*frame_to_render);
    //即VideoReceiveStream2::OnFrame(

 //过wait_time,再去渲染
 if (render_buffers_.HasPendingFrames()) {
    uint32_t wait_time = render_buffers_.TimeToNextFrameRelease();	
    incoming_render_queue_.PostDelayedTask([this]() { Dequeue(); }, wait_time);
  }
}


uint32_t VideoRenderFrames::TimeToNextFrameRelease() {
 //render_time_ms()是frame->SetRenderTime()设置进去的时间。
 const int64_t time_to_release = incoming_frames_.front().render_time_ms() -
                                  render_delay_ms_ - rtc::TimeMillis();

 return time_to_release < 0 ? 0u : static_cast<uint32_t>(time_to_release);
} 
//赋值的地方
frame_info.renderTimeMs = frame.RenderTimeMs();
decodedImage.set_timestamp_us(frameInfo->renderTimeMs *
                                rtc::kNumMicrosecsPerMillisec);

八 Jitterbuffer调优参数 

1 rtp_video_header.playout_delay,rtp扩展头字段。

2 jitterbuffer和nack模块关系?nack功能需要取缓存的rtp包。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值