zoukankan      html  css  js  c++  java
  • 使用Live555类库实现的网络直播系统

    Live555主要有四个类库:

    libUsageEnvironment.lib;libliveMedia.lib;libgroupsock.lib;libBasicUsageEnvironment.lib

    将这四个类库以及相关的头文件导入VC++2010之后,可以轻松实现网络直播系统。

    在这里直接贴上完整代码,粘贴到VC里面就可以运行。

    注:程序运行后,使用播放器软件(VLC Media Player,FFplay等),打开URL:rtp://239.255.42.42:1234,即可收看直播的视频。

    // 网络直播系统.cpp : 定义控制台应用程序的入口点。
    // 雷霄骅
    // 中国传媒大学/数字电视技术
    // leixiaohua1020@126.com
    
    #include "stdafx.h"
    
    #include "liveMedia.hh"
    #include "BasicUsageEnvironment.hh"
    #include "GroupsockHelper.hh"
    
    //#define IMPLEMENT_RTSP_SERVER
    //#define USE_SSM 1
    #ifdef USE_SSM
    Boolean const isSSM = True;
    #else
    Boolean const isSSM = False;
    #endif
    
    
    
    #define TRANSPORT_PACKET_SIZE 188
    #define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7
    
    
    UsageEnvironment* env;
    char const* inputFileName = "test.ts";
    FramedSource* videoSource;
    RTPSink* videoSink;
    
    void play(); // forward
    
    int main(int argc, char** argv) {
      // 首先建立使用环境:
      TaskScheduler* scheduler = BasicTaskScheduler::createNew();
      env = BasicUsageEnvironment::createNew(*scheduler);
    
      // 创建 'groupsocks' for RTP and RTCP:
      char const* destinationAddressStr
    #ifdef USE_SSM
        = "232.255.42.42";
    #else
        = "239.255.42.42";
      // Note: 这是一个多播地址。如果你希望流使用单播地址,然后替换这个字符串与单播地址  
    #endif
      const unsigned short rtpPortNum = 1234;
      const unsigned short rtcpPortNum = rtpPortNum+1;
      const unsigned char ttl = 7; //
    
    
      struct in_addr destinationAddress;
      destinationAddress.s_addr = our_inet_addr(destinationAddressStr);
      const Port rtpPort(rtpPortNum);
      const Port rtcpPort(rtcpPortNum);
    
      Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
      Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
    #ifdef USE_SSM
      rtpGroupsock.multicastSendOnly();
      rtcpGroupsock.multicastSendOnly();
    #endif
    
      // 创建一个适当的“RTPSink”:
    
      videoSink =
        SimpleRTPSink::createNew(*env, &rtpGroupsock, 33, 90000, "video", "mp2t",
    			     1, True, False /*no 'M' bit*/);
    
    
      const unsigned estimatedSessionBandwidth = 5000; // in kbps; for RTCP b/w share
      const unsigned maxCNAMElen = 100;
      unsigned char CNAME[maxCNAMElen+1];
      gethostname((char*)CNAME, maxCNAMElen);
      CNAME[maxCNAMElen] = ''; 
    #ifdef IMPLEMENT_RTSP_SERVER
      RTCPInstance* rtcp =
    #endif
        RTCPInstance::createNew(*env, &rtcpGroupsock,
    			    estimatedSessionBandwidth, CNAME,
    			    videoSink, NULL /* we're a server */, isSSM);
      // 开始自动运行的媒体
    
    #ifdef IMPLEMENT_RTSP_SERVER
      RTSPServer* rtspServer = RTSPServer::createNew(*env);
      
      if (rtspServer == NULL) {
        *env << "Failed to create RTSP server: " << env->getResultMsg() << "
    ";
        exit(1);
      }
      ServerMediaSession* sms
        = ServerMediaSession::createNew(*env, "testStream", inputFileName,
    		   "Session streamed by "testMPEG2TransportStreamer"",
    					   isSSM);
      sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
      rtspServer->addServerMediaSession(sms);
    
      char* url = rtspServer->rtspURL(sms);
      *env << "Play this stream using the URL "" << url << ""
    ";
      delete[] url;
    #endif
    
     
      *env << "开始发送流媒体...
    ";
      play();
    
      env->taskScheduler().doEventLoop(); 
    
      return 0; // 只是为了防止编译器警告
    
    }
    
    void afterPlaying(void* /*clientData*/) {
      *env << "...从文件中读取完毕
    ";
    
      Medium::close(videoSource);
      // 将关闭从源读取的输入文件
    
      play();
    }
    
    void play() {
      unsigned const inputDataChunkSize
        = TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;
    
      // 打开输入文件作为一个“ByteStreamFileSource":
    
      ByteStreamFileSource* fileSource
        = ByteStreamFileSource::createNew(*env, inputFileName, inputDataChunkSize);
      if (fileSource == NULL) {
        *env << "无法打开文件 "" << inputFileName
    	 << "" 作为 file source
    ";
        exit(1);
      }
    
      
      videoSource = MPEG2TransportStreamFramer::createNew(*env, fileSource);
    
      
      *env << "Beginning to read from file...
    ";
      videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
    }

    完整工程下载地址:http://download.csdn.net/detail/leixiaohua1020/6272839

    
    
    
    
    
    
    
  • 相关阅读:
    倒立摆
    Mybatis在oracle、mysql、db2、sql server的like模糊查询
    BUG系列:转让startActivityForResult()&amp;onActivityResult()没有反应
    建立地方Jekyll周边环境
    HDU 1535 Invitation Cards (POJ 1511)
    STM8S---IO复用配置(STVP方式)
    【菜鸟看框架】——EF怎样自己主动生成实体
    Keywords Search (ac 自己主动机)
    liGDX life_cycle (生命周期)
    html浏览器兼容性的 JavaScript语法
  • 原文地址:https://www.cnblogs.com/leixiaohua1020/p/3902240.html
Copyright © 2011-2022 走看看