zoukankan      html  css  js  c++  java
  • WebRTC笔记(零)WebRTC基础

    一、Ninja与GN

      一般编译源码使用的是g++或clang++,这俩是编译器;

        make是调用g++实现编译的构建系统(build system),Makefile是告诉make如何构建;

        Ninja和make类似,也是一个构建系统

        GN是google用来生成Ninja配置文件的工具,WebRTC使用GN来生成Ninja配置文件;GN的配置文件使用的是Python语法(位于根目录下的BUILD.gn);

    二、 WebRTC运行模式

        WebRTC有三种运行模式:

    1. p2p,客户端之间直接建立媒体数据连接,避免使用服务器转发媒体数据;

    优缺点:优点是可以减少租用服务器和网络带宽的成本;但缺点是客户端之间的网络连接质量难以得到保证,音视频通话的效果往往会差一些;

    2. sfu,selective forwarding unit,服务端接收数据后直接转发,优点是不需要编解码,对CPU消耗小;直接转发极大的降低了延迟,提高了实时性;

    缺点是不同的人看到的不同的画面,回放也有限制;

    3. mcu, multi-point control unit, 服务端作为音视频网关,通过解码再编码可以屏蔽不同设备的差异化;多路流合成一路,所有人看到的都是同一个画面,提升了用户体验;

    缺点是编解码加混流需要大量的CPU计算,同时带来了延迟;

        调试时必须有信令服务器,Android/iOS/macOS是AppRTC Server,客户端是AppRTCMobile;Windows/Linux则是另一套,信令服务器是PeerConnection Server,客户端叫做PeerConnection Client;本文所示的是在windows平台下断点下来的堆栈。

    三、SDP协议

         SDP(Session Description Protocol)会话描述协议,描述多媒体数据传输格式和网络传输地址。之所以需要SDP协议,是因为参与会话的各成员能力不对等。这就涉及一个协商的过程,会话发起者先提出一些Offer,其他参与者再根据Offer提出自己的Answer。

    四、一次PeerConnection P2P视频通信过程

    • 发起端创建本地PeerConnection对象,并创建Offer;

    class PeerConnection {
      std::map<std::string, rtc::scoped_refptr<DataChannel>> rtp_data_channels_;
      std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_;
      std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_to_free_;
    
      bool remote_peer_supports_msid_ = false;
    
      std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
          senders_;
      std::vector<
          rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
          receivers_;
      std::unique_ptr<WebRtcSession> session_; // WebRtc数据通信
      std::unique_ptr<StatsCollector> stats_;
      rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
    };
        PeerConnection::CreateOffer->
    
            WebRtcSessionDescriptionFactory::CreateOffer
    • 发送端通过Signaling Server把Offer送到应答端;

    • 应答端创建本地PeerConnection对象,并把发起端的Offer设置给本地PeerConnection然后获得Answer;

    • 应答端通过Signaling Server把Answer发送给发起端;

    • 发起端把应答端的Answer设置给自己的PeerConnection对象;

    // 处理Signaling Server传递的消息,json格式,json中有一个字段会标识当前是Offer还是Answer
    void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) { 
        // 将获取到的Answer(SDP信息)设置给PeerConnection对象;
        peer_connection_->SetRemoteDescription(); 
    }

        发送端获取到的SDP信息:

    v=0
    o=- 3191439438210652066 2 IN IP4 127.0.0.1
    s=-
    t=0 0
    a=group:BUNDLE audio video
    a=msid-semantic: WMS stream_label
    m=audio 9 UDP/TLS/RTP/SAVPF 103 104 0 8 106 105 13 112 113 126
    c=IN IP4 0.0.0.0
    a=rtcp:9 IN IP4 0.0.0.0
    a=ice-ufrag:YXLe
    a=ice-pwd:12xORpVbT8qdIeDgwrOdgPbA
    a=fingerprint:sha-256 33:BD:49:9D:D8:9A:EF:4C:E8:BB:FE:E6:7E:D2:35:26:F6:1B:86:97:7E:47:FE:AA:79:E9:21:B0:48:37:7C:36
    a=setup:active
    a=mid:audio
    a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
    a=sendrecv
    a=rtcp-mux
    a=rtpmap:103 ISAC/16000
    a=rtpmap:104 ISAC/32000
    a=rtpmap:0 PCMU/8000
    a=rtpmap:8 PCMA/8000
    a=rtpmap:106 CN/32000
    a=rtpmap:105 CN/16000
    a=rtpmap:13 CN/8000
    a=rtpmap:112 telephone-event/32000
    a=rtpmap:113 telephone-event/16000
    a=rtpmap:126 telephone-event/8000
    a=ssrc:1030752977 cname:djnC/REx5tbxVb/6
    a=ssrc:1030752977 msid:stream_label audio_label
    a=ssrc:1030752977 mslabel:stream_label
    a=ssrc:1030752977 label:audio_label
    m=video 9 UDP/TLS/RTP/SAVPF 96 98 100 102 127 97 99 101 125
    c=IN IP4 0.0.0.0
    a=rtcp:9 IN IP4 0.0.0.0
    a=ice-ufrag:YXLe
    a=ice-pwd:12xORpVbT8qdIeDgwrOdgPbA
    a=fingerprint:sha-256 33:BD:49:9D:D8:9A:EF:4C:E8:BB:FE:E6:7E:D2:35:26:F6:1B:86:97:7E:47:FE:AA:79:E9:21:B0:48:37:7C:36
    a=setup:active
    a=mid:video
    a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
    a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
    a=extmap:4 urn:3gpp:video-orientation
    a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
    a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
    a=sendrecv
    a=rtcp-mux
    a=rtcp-rsize
    a=rtpmap:96 VP8/90000
    a=rtcp-fb:96 ccm fir
    a=rtcp-fb:96 nack
    a=rtcp-fb:96 nack pli
    a=rtcp-fb:96 goog-remb
    a=rtcp-fb:96 transport-cc
    a=rtpmap:98 VP9/90000
    a=rtcp-fb:98 ccm fir
    a=rtcp-fb:98 nack
    a=rtcp-fb:98 nack pli
    a=rtcp-fb:98 goog-remb
    a=rtcp-fb:98 transport-cc
    a=rtpmap:100 H264/90000
    a=rtcp-fb:100 ccm fir
    a=rtcp-fb:100 nack
    a=rtcp-fb:100 nack pli
    a=rtcp-fb:100 goog-remb
    a=rtcp-fb:100 transport-cc
    a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
    a=rtpmap:102 red/90000
    a=rtpmap:127 ulpfec/90000
    a=rtpmap:97 rtx/90000
    a=fmtp:97 apt=96
    a=rtpmap:99 rtx/90000
    a=fmtp:99 apt=98
    a=rtpmap:101 rtx/90000
    a=fmtp:101 apt=100
    a=rtpmap:125 rtx/90000
    a=fmtp:125 apt=102
    a=ssrc-group:FID 3701325982 3818105161
    a=ssrc:3701325982 cname:djnC/REx5tbxVb/6
    a=ssrc:3701325982 msid:stream_label video_label
    a=ssrc:3701325982 mslabel:stream_label
    a=ssrc:3701325982 label:video_label
    a=ssrc:3818105161 cname:djnC/REx5tbxVb/6
    a=ssrc:3818105161 msid:stream_label video_label
    a=ssrc:3818105161 mslabel:stream_label
    a=ssrc:3818105161 label:video_label
    • 双端都收集本地PeerConnection的ICE Candidate(包括访问TURN Server),通过Signaling Server发送给对端,对端把ICE Candidate设备给本地的PeerConnection;

    收到的Candidate信息:
    {
       "candidate" : "candidate:1221703924 1 udp 2122260223 192.168.0.105 60608 typ host generation 0 ufrag RIxM network-id 3 network-cost 50",
       "sdpMLineIndex" : 0,
       "sdpMid" : "audio"
    }
    • 端开始建立P2P的Socket,并收发音视频数据;

        Offer和Answer都属于SDP,双端协商好使用的多媒体数据格式和网络传输地址等;

    • 本文作者: Jia Yayao
    • 赞赏:如果每人给我一块钱..$$
    • 支付宝

      微信

  • 相关阅读:
    Caffe 编译
    Caffe 在 Ubuntu 中安装
    【转】git
    Using OpenCV with gcc and CMake
    【转】linux下安装opencv
    【转】shell 教程——07 Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
    【转】shell 教程——06 Shell变量:Shell变量的定义、删除变量、只读变量、变量类型
    python全栈开发-面向对象-初识2
    python全栈开发-面向对象-初识
    python全栈开发-前方高能-内置函数2
  • 原文地址:https://www.cnblogs.com/jiayayao/p/14350380.html
Copyright © 2011-2022 走看看