WebRTC在web上如何支持H265

由于H265受版权的影响,浏览器都不愿意支持,所以webrtc不能实现H265的解码播放。但是工作中需要h265去解决带宽问题,所以要解决浏览器不支持H265播放。从度娘上了解,可以通过发送sctp替换rtp包(webrtc的数据通道可以走三种协议:1、SCTP;2、RTP;3、QUIC。这里先研究第一种)。web端接收数据,然后解码、显示。

目前谷歌支持:

WebCodecs(browserInfo.type.toLowerCase()===’chrome’ && browserInfo.version >= 107&&(location.protocol===’https:’||location)

MSE(isTypeSupported(‘video/mp4; codecs=”hev1.1.6.L123.b0″‘))

ffmpeg wasm,本文讲解才用ffmpeg wasm软解。

图片

SCTP

SCTP的全称是Stream Control Transmission Protocol,它是一种传输协议,默认使用5000端口,在TCP/IP协议栈中所处的位置和TCP、UDP类似,同时具备TCP和UDP的特征。

sdp交互 

offer:

a=end-of-candidates
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 23.101.8.213
a=sendrecv
a=sctp-port:5000
a=mid:data
a=ice-ufrag:ePgh
a=ice-pwd:ZURiB67/xs69E76aOa7JDw
a=ice-options:trickle
a=fingerprint:sha-256 EF:7A:50:9C:05:8C:EF:84:4D:72:B2:74:30:BA:FD:82:76:D1:C3:FE:0C:A0:10:43:B8:6C:B2:ED:B3:F7:77:8B
a=setup:actpass
a=candidate:1 1 udp 2013266431 23.101.8.213 41901 typ host
a=end-of-candidates

answer:

m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=sendrecv
a=ice-pwd:518cb4fc626f82bef2ada4e9221dfb50
a=ice-ufrag:d5484fed
a=mid:data
a=setup:active
a=sctp-port:5000
a=max-message-size:1073741823
static void  onapplication(void* param, uint32_t track,/* uint32_t object, */int width, int height, const void* extra, size_t bytes)
{
  ice_session_t* s = (ice_session_t*)param;
  // 6.2.  SDP Parameters
  static const char* pattern =
    "m=application 9 UDP/DTLS/SCTP webrtc-datachanneln"
    "a=mid:2n"
    "a=sctp-port:5000n"
    "a=sendrecvn";
      "a=setup:passiven";
  strcat((char*)s->app.sender.buffer, pattern);
  int n = snprintf(s->app.sdp, sizeof(s->app.sdp), "%s", (char*)s->app.sender.buffer);
  n += ice_transport_getsdp(s->avt, s->app.stream, (char*)s->app.sender.buffer + n, sizeof(s->app.sender.buffer) - n);
}

数据传输

DataChannel的数据通过boringssl加密后再通过udp发送给对端,发送datachannel数据和音视频数据的是同一个socket。音视频数据传输使用了RTP协议,通过NACK和FEC的策略来抗丢包,而DataChannel底层使用了SCTP(stream control transmission protocol)协议,SCTP和TCP类似,是一个具备流量控制、拥塞控制的可靠性传输协议,因此无需再采取其它措施即可实现DataChannel数据的可靠传输。webrtc采用了第三方开源库usrsctplib来实现SCTP协议。

注:usrsctp提供了SCTP的UDP封装,但我们需要这些消息封装在DTLS中,实际由我们之前交互的DTLS同个socket发送/接收,而不是由usrscp本身……因此,我们使用AF_CONN方法。

demo

int ice_transport_send_sctp(struct ice_transport_t* avt, int streamid, uint64_t time, int flags ,const void* data, int bytes)
{
  int n = RTP_FIXED_HEADER + bytes;
  unsigned char* ptr = (uint8_t*)calloc( 1,n+1);
  rtp_header_t header;
   memset(&header,0,sizeof(rtp_header_t));
  header.timestamp = 1667895211;
  header.v = RTP_VERSION;
  header.pt = 100;
  header.ssrc = bytes;
  nbo_write_rtp_header(ptr, &header);
  memcpy(ptr + RTP_FIXED_HEADER, data, bytes);//data 265的裸数据
  janus_dtls_wrap_sctp_data(avt->dtls, "doc-datachannel", "udp",0, ptr, n);
  free(ptr);//后面优化释放
  return -1;
}

web接收

接收数据,解析rtp包头:

function ReadBig32(array, index) {
    return ((array[index] << 24)     |
            (array[index + 1] << 16) |
            (array[index + 2] << 8)  |
            (array[index + 3]));
}
function initH265DC(pc, player) {
    console.log("initH265DC", Date());
    bFindFirstKeyFrame = false;
    bRecH265 = false;
    isKeyFrame = false;
    receivet1 = new Date().getTime();
    h265DC = pc.createDataChannel("webrtc-datachannel");

    // var ctx = canvas.getContext("2d");
    console.log("initH265DC0", h265DC);
    h265DC.onmessage = function (event) {
       // console.log("receive message: ",event.data.slice(12));
        //console.log("receive message: ", buf2hex(event.data));
        let data = new Uint8Array(event.data);
        version = ((data[0] & 0xC0) >>> 6);
    padding = ((data[0] & 0x20) >>> 5);
    itemCount = (data[0] & 0x1F);
    packetType =  data[1];
        let pts = ReadBig32(data, 4);

        let len = ReadBig32(data, 8);
        console.log("initH265DC0", version,padding ,itemCount,packetType,pts,len);
        //console.log("receive message: ", buf2hex(event.data.split(12)));event.data.byteLength-12
        var req = {
            t: ksendPlayerVideoFrameReq,
            l: len,
            d:  data.subarray(12).buffer
        };
        player.postMessage(req, [req.d]);

    };
WebRTC在web上如何支持H265

参考

  • [1] github
  • [2] flv-h265.js、webrtc_H265player.juans
  • [3] C/C++面向WebAssembly编程

作者:aliveyun

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(2)

相关推荐

发表回复

登录后才能评论