WebRTC視頻採集和編碼過程

WebRTC音視頻採集和編碼過程(基於2014年11月代碼)

一、採集時間戳

首先,需要確定下代碼中對時間戳的定義,便於後面閱讀代碼更好的理解思路。

1、 NTP時間

獲取從1900-01-01 00:00.00到當前時刻的毫秒數。

int64_t RealTimeClock::CurrentNtpInMilliseconds()

2、本地時間戳

時間單位爲毫秒ms。

這個值在不同平臺的含義有所不同,可能是本機開機時刻到當前時刻的時間,也可能是從1970-01-01 00:00.00到當前時刻的值gettimeofday()。

int64_t TickTime::MillisecondTimestamp()

二、攝像頭採集時間戳以及數據傳遞過程

VideoCaptureImpl是視頻採集的實現類,各個平臺都會實現它的子類。子類中會做平臺相關的具體實現,採集得到的Frame數據都是通過父類的接口VideoCaptureImpl::IncomingFrame作爲出口輸出。如Android平臺具體實現的子類爲VideoCaptureAndroid,Linux平臺爲VideoCaptureModuleV4L2。

下面以Android平臺爲例:

VideoCaptureAndroid採集到數據之後通過如下接口返回:

int32_t VideoCaptureImpl::IncomingFrame(
    uint8_t* videoFrame,
    int32_t videoFrameLength,
    const VideoCaptureCapability& frameInfo,
    int64_t captureTime/*=0*/) // must be specified in the NTP time format in milliseconds.

上述接口中captureTime若有值,必須爲NTP時間格式,VideoCaptureAndroid在調用時傳入的值爲0。

如下是Frame傳遞流程:

VideoCaptureImpl::IncomingFrame(captureTime = 0) // VideoCaptureAndroid 傳入了默認值0
 --> VideoCaptureImpl::DeliverCapturedFrame(capture_time)
  --> 設置Frame的render_time_ms
      1.由於傳入的captureTime值爲0,設置爲本機時間戳
      captureFrame.set_render_time_ms(TickTime::MillisecondTimestamp())
      2.否則,設置爲NTP值減去(NTP值與本機時間戳的差值)

      類對象在構造函數內會初始化NTP值與本機時間戳的差值:

      delta_ntp_internal_ms_(
          Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() - TickTime::MillisecondTimestamp())

      captureFrame.set_render_time_ms(capture_time - delta_ntp_internal_ms_);

      可以看出計算得到的值其實就是本機時間戳

  --> last_capture_time_ = captureFrame.render_time_ms();保存最新的採集時間戳,本地時間戳
   --> ViECapturer::OnIncomingCapturedFrame(I420VideoFrame& video_frame)
   --> // Make sure we render this frame earlier since we know the render time set
      // is slightly off since it's being set when the frame has been received from

      // the camera, and not when the camera actually captured the frame.

      去除採集的延遲,Android爲190ms

video_frame.set_render_time_ms(video_frame.render_time_ms() - FrameDelay());

三、視頻幀從採集到編碼過程

ViECapturer::ViECaptureProcess()
 --> ViECapturer::DeliverI420Frame(I420VideoFrame* video_frame)
  --> ViEFrameProviderBase::DeliverFrame()
   --> ViERenderer::DeliverFrame() 視頻回顯窗口
   --> ViEEncoder::DeliverFrame()傳遞到編碼器
    --> Convert render time, in ms, to RTP timestamp.
      const int kMsToRtpTimestamp = 90;
      const uint32_t time_stamp = kMsToRtpTimestamp * static_cast<uint32_t>(video_frame->render_time_ms());
      video_frame->set_timestamp(time_stamp);
    --> VideoCodingModuleImpl::AddVideoFrame()
     --> VideoSender::AddVideoFrame
      --> VCMGenericEncoder::Encode
       --> VideoEncoder::Encode() 對於VP8,這裏應該是VideoEncoder子類VP8Encoder
                         對於H264,這裏應該是VideoEncoder子類H264Encoder
       --> VCMEncodedFrameCallback::Encoded()
        --> VCMPacketizationCallback::SendData()
   --> ViEEncoder::SendData()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章