WebRTC学习(九)RTP 媒体控制与数据统计

补充:查找手册MDN Web Docs

1、WebRTC中的RTP/RTCP模块

1.1 RTP/RTCP简介

RTP/RTCP协议是流媒体通信的基石。RTP协议定义流媒体数据在互联网上传输的数据包格式而RTCP协议则负责可靠传输、流量控制和拥塞控制等服务质量保证。

在WebRTC项目中,RTP/RTCP模块作为传输模块的一部分,负责对发送端采集到的媒体数据进行进行封包,然后交给上层网络模块发送;

在接收端RTP/RTCP模块收到上层模块的数据包后,进行解包操作,最后把负载发送到解码模块。

因此,RTP/RTCP 模块在WebRTC通信中发挥非常重要的作用。

2.2 RTP Media(webrtc中真正处理数据传输的模块)

在RTP Media中有两个重要的类:Receiver与Sender

每一个媒体轨都会对应一个对会对应一个Receiver对象(接收时)和一个Sender对象(发送时)

1.3RTCRtpReceiver与RTCRtpSender属性一致(3种)

以RTCRtpReceiver为例:

RTCRtpReceiver.track:返回与当前RTCRtpReceiver实例关联的MediaStreamTrack

通过媒体轨属性可以获取当前轨的类型,是audio/video

RTCRtpReceiver.transport:返回接收到的接收者媒体轨的RTCDTLTransport实例

存放着媒体数据传输相关的属性,其中trnasport用于媒体数据的传输,媒体流通过底层的transport进行传输。transport可以进行复用,多个媒体轨复用一个transport传输!

RTCRtpReceiver.rtcpTransport:返回发送和接收RTCP的RTCDTLTransport实例

与rtcp传输相关的属性,比如传输抖动,丢包数量、延迟....。接受方进行统计,反馈给发送端,发送方根据这些数据进行网络质量的评估,适当调整网络流量的发送,这就是流量控制

1.4RTCRtpReceiver实例的方法(5种)

getParameters:返回一个RTCRtpParameters对象,其中包含有关如何解码RTP数据的信息。

方法返回一个RTCRtpReceiveParameters对象,该对象描述了在接收轨上面的媒体关于编码和传输的配置。

对于第2、3个方法,先查看RTP头部格式:

getSynchronizationSources: 方法返回一个RTCRTPContributionSource实例数组,每个实例对应于当前RTCRtpReceiver在最近10秒内接收到的一个SSRC(同步源)标识符。

返回了一组RTCRtpSynchronizationSource实例,每个实例描述在过去10秒内向传入流提供数据的一个同步源。它继承了RTCRtpContributingSource的属性,包括时间戳、源和音频级别。同步源对象添加了voiceActivityFlag属性,该属性指示接收到的最后一个RTP数据包是否包含语音活动。

getContributingSources:方法返回一个RTCRtpContributingSource实例数组,每个实例对应于当前RTCRtpReceiver在最近10秒内接收到的一个CSRC(贡献源)标识符。

每个实例描述了在过去10秒内向传入流提供数据的一个贡献源。

getStats:异步请求一个RTCStatsReport对象,该对象提供有关所属RTCPeerConnection上传入流量的统计信息,并返回一个Promise,一旦结果可用,将调用该Promise的异步处理程序。

getCapabilities:返回一个RTCRtpCapabilities对象,描述当前设备上RTCRtpReceiver支持的编解码器和功能。类似地,您可以通过调用静态函数RTCRtpSender.getCapabilities()来获取RTCRtpSender的功能。

1.5 RTCRtpSender实例的方法(5种)

getParameters(同receiver):返回一个RTCRtpParameters对象,其中包含有关如何解码RTP数据的信息。

方法返回一个RTCRtpReceiveParameters对象,该对象描述了在发送轨上面的媒体关于编码和传输的配置。

setParameters:由于更改发送方轨的配置,该轨是RTCRtpSender负责的MediaStreamTrack。比如最大码率、帧率都是可以改变的

换句话说,setParameters()更新RTP传输的配置以及WebRTC连接上特定传出媒体轨的编码配置。

getStats(同上):异步请求一个RTCStatsReport对象,该对象提供有关拥有发送方的RTCPeerConnection上传出流量的统计信息,并返回一个Promise,一旦结果可用,将调用该Promise的异步处理程序。

replaceTrack:RTCRtpSender方法replaceTrack将当前用作发送方源的媒体流轨替换为新的MediaStreamTrack。新媒体流轨必须是相同的媒体类型(音频、视频等),切换轨不需要协商。

replaceTrack()的用例之一是在手机的后向和前向摄像头之间切换的常见需求。使用replaceTrack(),可以为每个摄影机设置一个轨迹对象,并根据需要在两者之间切换。

getCapabilities(同上):返回一个RTCRtpCapabilities对象,描述当前设备上RTCRtpSender支持的编解码器和功能。类似地,您可以通过调用静态函数RTCRtpReceiver.getCapabilities()来获取RTCRtpSender的功能。

2、RTP Media结构体

2.1 RTP Media结构体

下图列举了receiver与sender用到的所有的结构,以RTCRtpSendParameters最为关键,继承自RTCRtpParameters

在RTCRtpParameters类中,包含3个成员:

RTCRtpHeaderExtensionParameters:扩展头,包括id,uri,encrypted是否加密,默认false不加密
RTCRtcpParameters:对于没一个Rtp都有一个RTCP与之对应,包括cname(可识别),reduceSize带宽不够时,减少RTCP数量,从而降低带宽
RTCRtpCodecParameters:与编解码相关的参数包括payloadType,mimeType,clockRate,channels,sdpFmtpLine...

除了上面继承的字段之外,RTCRtpSendParameters还包括:

transactionID:事物ID,是唯一标识。使用getParameters会获取到,使用setParameters可以指定要设置的事物的transactionID
encodings:指向RTCRtpEncodingParamters对象,指向一堆编解码器
degradationPreference:指向RTCDegradationPreference对象
priority:指定优先级

RTCRtpEncodingParamters:编解码相关结构体

RTCDegradationPreference:降低码流方法,保持帧率、分辨率或者平衡两者

RTCRtpReceiveParameters相对简单,只进行接收,将数据进行上报给发送端,发送端进行整体的控制,所以发送端的参数会更多些!!

2.2 RTCRtpTransceiver

是sender、receiver对,可以同时处理sender与receiver,是对两者的封装

【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发

【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~

3、RTCRtpTransceiver

基于:WebRTC学习(八)1V1音视频实时互动直播系统(2)

3.1 代码实现

index2.html

<html>
    <head>
        <title>    WebRTC PeerConnection </title>
        <link href="./css/main.css" rel="stylesheet" />
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
    </head>
    <body>
        <div>
            <button id=connserver>Connect Signal Server</button>
            <button id="leave" disabled>Leave</button>
        </div>
        <div id="preview">
            <div>
                <h2>Local:</h2>
                <video autoplay playsinline id="localvideo"></video>
            </div>
            <div>
                <h2>Remote:</h2>
                <video autoplay playsinline id="remotevideo"></video>
            </div>
        </div>
​
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/main2.js"></script>
</html>

main2.js

'use strict'
​
var localVideo = document.querySelector("video#localvideo");
var remoteVideo = document.querySelector("video#remotevideo");
​
var btnConn = document.querySelector("button#connserver");
var btnLeave = document.querySelector("button#leave");
​
var SltBW = document.querySelector("select#bandwidth");
​
var localStream = null;                    //保存本地流为全局变量
var socket = null;
​
var roomid = "111111";
var state = "init";                        //客户端状态机
​
var pc = null;                            //定义全局peerconnection变量
​
function sendMessage(roomid,data){
    console.log("send SDP message",roomid,data);
    if(socket){
        socket.emit("message",roomid,data);
    }
}
​
function getOffer(desc){
    pc.setLocalDescription(desc);
    sendMessage(roomid,desc);    //发送SDP信息到对端
}
​
//这里我们本机是远端,收到了对方的offer,一会需要把自己本端的数据回去!!!!!
function getAnswer(desc){                //在offer获取后,设置了远端描述
    pc.setLocalDescription(desc);        //这里只需要设置本端了
    sendMessage(roomid,desc);
​
    //本端已经收到offer,开始回复answer,说明本端协商完成
    SltBW.disabled = false;
}
​
//媒体协商方法,发起方调用,创建offer
function call(){
    if(state === "joined_conn"){
        if(pc){
            var options = {
                offerToReceiveAudio:1,
                offerToReceiveVideo:1
            };
​
            pc.createOffer(options)
                .then(getOffer)
                .catch(handleError);
        }
    }
}
​
//创建peerconnection,监听一些事件:candidate,当收到candidate事件之后(TURN服务返回),之后转发给另外一端(SIGNAL 服务器实现)
//将本端的媒体流加入peerconnection中去
function createPeerConnection(){
    console.log("Create RTCPeerConnection!");
    if(!pc){
        //设置ICEservers
        var pcConfig = {
            "iceServers" : [{
                'urls':"turn:82.156.184.3:3478",
                'credential':"ssyfj",
                'username':"ssyfj"
            }]
        }
        pc = new RTCPeerConnection(pcConfig);
​
        pc.onicecandidate = (e)=>{        //处理turn服务返回的candidate信息,媒体协商之后SDP规范中属性获取
            if(e.candidate){
                //发送candidate消息给对端
                console.log("find a new candidate",e.candidate);
                sendMessage(roomid,{
                    type:"candidate",    
                    label:e.candidate.sdpMLineIndex,
                    id:e.candidate.sdpMid,
                    candidate:e.candidate.candidate
                });
            }
        };
​
        pc.ontrack = (e)=>{                //获取到远端的轨数据,设置到页面显示
            remoteVideo.srcObject = e.streams[0];
        }
    }
​
    if(localStream){                    //将本端的流加入到peerconnection中去
        localStream.getTracks().forEach((track)=>{
            pc.addTrack(track,localStream);
        });
    }
}
​
//销毁当前peerconnection的流信息
function closeLocalMedia(){
    if(localStream && localStream.getTracks()){
        localStream.getTra
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值