webrtc的源码流程
一篇介绍webrtc的h264编码,从视频采集,编码,rtp传输,包解析,解码,渲染流程的文章:
https://blog.piasy.com/2019/01/01/WebRTC-RTP-Mux-Demux/index.html#webrtc-h264-%E8%A7%A3%E5%8C%85%E5%AE%9E%E7%8E%B0
1. 整体模块流程见下图。
发送流程
大致流程:
在java层,比如从camera获取到帧数据后,通过调用VideoSource::onFrameCaptured()传入帧数据,再传入native层AndroidVideoTrackSource::OnFrameCaptured()
a. 然后encoder编码得到要发送的视频帧; (在andriod平台,是调用mediacodec进行编解码,webrtc_android\src\sdk\android\src\jni\video_encoder_wrapper.cc)
b. RtpSender模块对要发送的视频帧进行打包;
c. 打包后的packet,一份送到PacedSender准备平滑发送,同时送一份到RtpPacketHistory模块(后面重发可能会用到);
d. 最后在RtpSender发送到网络,调用 LogAndSendToNetwork(std::move(rtp_packets), unpacketized_payload_size)。
对应模块
java:
VideoSource::onFrameCaptured()
native:
AndroidVideoTrackSource::OnFrameCaptured(video_frame_buffer)
VideoStreamEncoder::OnFrame(VideoFrame)
webrtc_android\src\video\video_stream_encoder.cc ==> VideoStreamEncoder::EncodeVideoFrame
webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h ==> H264EncoderImpl
webrtc/video/video_send_stream.h ==> VideoSendStream
webrtc/modules/rtp_rtcp/source/rtp_sender_video.h ==> RTPSenderVideo (打包RtpPacket)
webrtc/modules/rtp_rtcp/source/rtp_sender.h ==> RTPSender
webrtc/modules/pacing/paced_sender.h ==> PacedSender
webrtc/modules/pacing/packet_router.h ==> PacketRouter
user数据的流程修改,发送端:
- VideoStreamEncoder通过onFrame接口拿到VideoFrame帧数据,然后调用VideoStreamEncoder::EncodeVideoFrame(),最后调用encode,对数据进行编码。
- 编码前,上层需要将user信息传入encoder模块, 调用具体编码器的Encode(const VideoFrame& input_image, const std::vector
* frame_types) 接口时,通过VideoFrame 类结构传入 user 信息; - 修改具体编码器代码,如安卓上(../../sdk/android/src/jni/video_encoder_wrapper.cc),将user 信息传入编码后的 EncodedImage 结构。
- 在编码后,encoder模块在回调函数OnEncodedImage中,可以通过类 EncodedImage 传递user信息;(扩展EncodedImage类,添加user信息)
- 在函数 RtpPayloadParams::GetRtpVideoHeader,从 EncodedImage 类传递给 RTPVideoHeader 类;
- user信息传递到 RTPSenderVideo::SendVideo 函数的参数 RTPVideoHeader,
在rtp_sender_video.cc文件中,有个函数 AddRtpHeaderExtensions(),里面会设置rtp扩展头;
接收流程:
大致流程:
a. 通过call模块收到rtp数据包;
b. 根据其SSRC找到对应的VideoReceiverStream,通过调用其DeliverRtp()函数到RtpStreamReceiver::DeliverRtp();
c. 调用RtpReceiver::IncomingRtpPacket和RtpReceiverVideo::ParseRtpPacket获取rtp报文信息和视频帧信息
d. 交给jitterBuffer缓存,解码渲染
对应模块
- webrtc/call/call.cc ==> Call::DeliverRtp()
- webrtc/src/modules/rtp_rtcp/source/rtp_packet.cc ==> RtpPacket::Parse()
- webrtc/src/modules/rtp_rtcp/source/rtp_packet.cc ==> RtpPacket::ParseBuffer() //解析rtp头等信息
- webrtc/video/rtp_video_stream_receiver.cc ==> RtpVideoStreamReceiver::ReceivePacket() //解析payload类型,扩展头信息,这里获取PoseInfo
- webrtc/video/rtp_video_stream_receiver2.cc (4289分支用这个文件)
- webrtc/src/modules/video_coding/packet_buffer.cc ==> PacketBuffer::InsertPacket() //转VCMPacket,放入缓存
- webrtc/src/modules/video_coding/packet_buffer.cc ==> PacketBuffer::FindFrames() //重组获取视频帧
- RtpFrameReferenceFinder::ManageFrame()
- VCMReceiver::FrameForDecoding() //从VCMJitterBuffer的队列获取要解码的帧
- VideoReceiver::Decode()
- VideoDecoderWrapper::Decode()
VideoDecoderWrapper::onDecodedFrame() //sure - VCMDecodedFrameCallback::Decoded() //sure
- VideoStreamDecoder::FrameToRender() //sure
- VideoReceiveStream::OnFrame() //sure
- VideoSinkWrapper::OnFrame() //sure
java:
VideoTrack.sinks.onFrame()
pose数据结构的流程:
- video_header
- VCMPacket
- RtpFrameObject (对象的video_header变量中,包含pose_info信息)
- VCMEncodedFrame
- EncodedImage
VideoFrame
报文封装格式:
________________________________________________________________
| ip header | udp header | rtp header | Nalu header | frame data |
从编码到数据发送调用流程:
LibvpxVp8Encoder::GetEncodedPartitions() ==>
VideoSendStreamImpl::OnEncodedImage() ==>
RtpVideoSenderInterface::OnEncodedImage() ==>
RtpVideoSender::OnEncodedImage() ==>
RTPSenderVideo::SendEncodedImage() ==>
RTPSenderVideo::SendVideo ==> 这个函数内部会详细设置rtp的header参数值,要设置扩展头,可以考虑在此修改代码;
RtpVideoSender::OnEncodedImage
RTPSenderVideo::SendVideo ==> 这个函数内部会详细设置rtp的header参数值,要设置扩展头,可以考虑在此修改代码;
RTPSenderVideo::LogAndSendToNetwork ==>
RTPSender::SendToNetwork ==>
PacedSender::EnqueuePackets ==>
还没有评论,来说两句吧...