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()