webrtc入门系列(二)easy_webrtc_server 入门example测试

《webrtc入门系列(一)easy_webrtc_server 入门环境搭建》
《webrtc入门系列(二)easy_webrtc_server 入门example测试》
《webrtc入门系列(三)云服务器coturn环境搭建》
《webrtc入门系列(四) zlmediakit webrtc sdp交互详细解读》


rtp_src_example

这个样例,非常的典型,对我们做设备端的同学来说,就需要一样这样的例子,模拟IPC发送视频到web播放。

环境

demo运行系统:Ubuntu20.04
播放环境:win10,chrom浏览器、edge浏览器
系统这里特别说下,我用Ubuntu18.04测试失败,打开文件错误,应该是Ubuntu18.04apt默认安装的ffmpeg的版本编译选项的问题。
解决办法,要么升级系统,要么自己源码安装ffmpeg。

测试过程

  1. 拷贝测试文件到build目录

rtp_src_example.cc里面是读了一个test.flv文件发送,作者工程里又只有一个test.h264,看代码是用ffmpeg接口打开的文件,所以格式没关系,ffmpge能自己解析,我们只要输入一个视频文件即可。拷贝test.h264到build目录,改名test.flv或者代码打开test.h264即可
cd easy_webrtc_server/build;cp ../test.h264 test.flv
2. 启动测试程序
记得sudo启动

./rtp_src_example 192.168.1.16 8000

将IP替换成你运行demo系统的IP
3. 打开网页播放视频
将easy_web_rtc目录下面index.html文件直接拖到浏览器打开,IP改成Ubuntu的ip地址,点call即可以看到视频。
webrtc入门系列(二)easy_webrtc_server 入门example测试_第1张图片

chrom浏览器和Edge浏览器测试OK。
Firefox浏览器不允许跨源请求。

至此,就可以完整的抓包和分析代码学习了。

源码简读

muduo不支持udp,本项目基于muduo的Channel类简单封装一个udp通信的类;
基于muduo_http建立一个http信令服务器,交换webrtc所需要的sdp信息。
网页上打开一个http连接,服务器建立一个WebRtcTransport,传输层是一个UdpSocket。
WebRtcTransport生成sdp信息,通过http协议传到前端。
sdp信息包括媒体信息如编码格式、ssrc等,stun协议需要的ice-ufrag、ice-pwd、candidate,dtls需要的fingerprint。
前端通过candidate获取ip地址和端口号,通过udp协议连接到服务器的。
服务器收到udp报文,先后通过类UdpSocket接收报文;StunPacket和IceServer解析stun协议,此处的Stun协议解析,只要收到stun request,验证账户密码成功,就认为连接成功。
stun协议交互成功后,通过DtlsTransport进行dtls握手;交换密钥后就可以初始化SrtpChannel。此处没有通过签名验证客户端的证书,所以省略了前端返回sdp的步骤。
读取h264码流文件,通过ffmpeg生成rtp流,通过SrtpChannel加密,通过UdpSocket发送,前端就可以看到视频。

//起一个线程读取发送文件,WriteRtpCallback函数回调将数据通过webrtc的端口发送
std::thread flv_2_rtp_thread(
      [&webrtc_session_factory]() { H2642Rtp("./test.h264", &webrtc_session_factory); });

  //udp通道
  UdpServer rtc_server(&loop, muduo::net::InetAddress("0.0.0.0", port), "rtc_server", 2);
  
  //http信令服务器,交换sdp
  HttpServer http_server(&loop, muduo::net::InetAddress("0.0.0.0", 8000), "http_server",
                         TcpServer::kReusePort);

  //信令响应
  rtc_server.SetPacketCallback([&webrtc_session_factory](UdpServer* server, const uint8_t* buf,
                                                         size_t len,
                                                         const muduo::net::InetAddress& peer_addr,
                                                         muduo::Timestamp timestamp) {
    WebRTCSessionFactory::HandlePacket(&webrtc_session_factory, server, buf, len, peer_addr,
                                       timestamp);
  });

  http_server.setHttpCallback(
      [&loop, &webrtc_session_factory, port, ip](const HttpRequest& req, HttpResponse* resp) {
        if (req.path() == "/webrtc") {
          resp->setStatusCode(HttpResponse::k200Ok);
          resp->setStatusMessage("OK");
          resp->setContentType("text/plain");
          //跨域
          resp->addHeader("Access-Control-Allow-Origin", "*");
          auto rtc_session = webrtc_session_factory.CreateWebRTCSession(ip, port);
          //回复本地sdp
          resp->setBody(rtc_session->webrtc_transport()->GetLocalSdp());
          std::cout << rtc_session->webrtc_transport()->GetLocalSdp() << std::endl;
        }
      });
  loop.runInLoop([&]() {
    rtc_server.Start();
    http_server.start();
  });
  loop.loop();
  
  

你可能感兴趣的:(webRTC,入门系列,webrtc,ffmpeg,webrtc入门,教程,easy_webrtc)