testProgs/testMPEG2TransportStreamer.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // Copyright (c) 1996-2012, Live Networks, Inc.  All rights reserved
00017 // A test program that reads a MPEG-2 Transport Stream file,
00018 // and streams it using RTP
00019 // main program
00020 
00021 #include "liveMedia.hh"
00022 #include "BasicUsageEnvironment.hh"
00023 #include "GroupsockHelper.hh"
00024 
00025 // To stream using "source-specific multicast" (SSM), uncomment the following:
00026 //#define USE_SSM 1
00027 #ifdef USE_SSM
00028 Boolean const isSSM = True;
00029 #else
00030 Boolean const isSSM = False;
00031 #endif
00032 
00033 // To set up an internal RTSP server, uncomment the following:
00034 //#define IMPLEMENT_RTSP_SERVER 1
00035 // (Note that this RTSP server works for multicast only)
00036 
00037 #define TRANSPORT_PACKET_SIZE 188
00038 #define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7
00039 // The product of these two numbers must be enough to fit within a network packet
00040 
00041 UsageEnvironment* env;
00042 char const* inputFileName = "test.ts";
00043 FramedSource* videoSource;
00044 RTPSink* videoSink;
00045 
00046 void play(); // forward
00047 
00048 int main(int argc, char** argv) {
00049   // Begin by setting up our usage environment:
00050   TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00051   env = BasicUsageEnvironment::createNew(*scheduler);
00052 
00053   // Create 'groupsocks' for RTP and RTCP:
00054   char const* destinationAddressStr
00055 #ifdef USE_SSM
00056     = "232.255.42.42";
00057 #else
00058   = "239.255.42.42";
00059   // Note: This is a multicast address.  If you wish to stream using
00060   // unicast instead, then replace this string with the unicast address
00061   // of the (single) destination.  (You may also need to make a similar
00062   // change to the receiver program.)
00063 #endif
00064   const unsigned short rtpPortNum = 1234;
00065   const unsigned short rtcpPortNum = rtpPortNum+1;
00066   const unsigned char ttl = 7; // low, in case routers don't admin scope
00067 
00068   struct in_addr destinationAddress;
00069   destinationAddress.s_addr = our_inet_addr(destinationAddressStr);
00070   const Port rtpPort(rtpPortNum);
00071   const Port rtcpPort(rtcpPortNum);
00072 
00073   Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
00074   Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
00075 #ifdef USE_SSM
00076   rtpGroupsock.multicastSendOnly();
00077   rtcpGroupsock.multicastSendOnly();
00078 #endif
00079 
00080   // Create an appropriate 'RTP sink' from the RTP 'groupsock':
00081   videoSink =
00082     SimpleRTPSink::createNew(*env, &rtpGroupsock, 33, 90000, "video", "MP2T",
00083                              1, True, False /*no 'M' bit*/);
00084 
00085   // Create (and start) a 'RTCP instance' for this RTP sink:
00086   const unsigned estimatedSessionBandwidth = 5000; // in kbps; for RTCP b/w share
00087   const unsigned maxCNAMElen = 100;
00088   unsigned char CNAME[maxCNAMElen+1];
00089   gethostname((char*)CNAME, maxCNAMElen);
00090   CNAME[maxCNAMElen] = '\0'; // just in case
00091 #ifdef IMPLEMENT_RTSP_SERVER
00092   RTCPInstance* rtcp =
00093 #endif
00094     RTCPInstance::createNew(*env, &rtcpGroupsock,
00095                             estimatedSessionBandwidth, CNAME,
00096                             videoSink, NULL /* we're a server */, isSSM);
00097   // Note: This starts RTCP running automatically
00098 
00099 #ifdef IMPLEMENT_RTSP_SERVER
00100   RTSPServer* rtspServer = RTSPServer::createNew(*env);
00101   // Note that this (attempts to) start a server on the default RTSP server
00102   // port: 554.  To use a different port number, add it as an extra
00103   // (optional) parameter to the "RTSPServer::createNew()" call above.
00104   if (rtspServer == NULL) {
00105     *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
00106     exit(1);
00107   }
00108   ServerMediaSession* sms
00109     = ServerMediaSession::createNew(*env, "testStream", inputFileName,
00110                    "Session streamed by \"testMPEG2TransportStreamer\"",
00111                                            isSSM);
00112   sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
00113   rtspServer->addServerMediaSession(sms);
00114 
00115   char* url = rtspServer->rtspURL(sms);
00116   *env << "Play this stream using the URL \"" << url << "\"\n";
00117   delete[] url;
00118 #endif
00119 
00120   // Finally, start the streaming:
00121   *env << "Beginning streaming...\n";
00122   play();
00123 
00124   env->taskScheduler().doEventLoop(); // does not return
00125 
00126   return 0; // only to prevent compiler warning
00127 }
00128 
00129 void afterPlaying(void* /*clientData*/) {
00130   *env << "...done reading from file\n";
00131 
00132   videoSink->stopPlaying();
00133   Medium::close(videoSource);
00134   // Note that this also closes the input file that this source read from.
00135 
00136   play();
00137 }
00138 
00139 void play() {
00140   unsigned const inputDataChunkSize
00141     = TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;
00142 
00143   // Open the input file as a 'byte-stream file source':
00144   ByteStreamFileSource* fileSource
00145     = ByteStreamFileSource::createNew(*env, inputFileName, inputDataChunkSize);
00146   if (fileSource == NULL) {
00147     *env << "Unable to open file \"" << inputFileName
00148          << "\" as a byte-stream file source\n";
00149     exit(1);
00150   }
00151 
00152   // Create a 'framer' for the input source (to give us proper inter-packet gaps):
00153   videoSource = MPEG2TransportStreamFramer::createNew(*env, fileSource);
00154 
00155   // Finally, start playing:
00156   *env << "Beginning to read from file...\n";
00157   videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
00158 }

Generated on Thu May 17 07:11:48 2012 for live by  doxygen 1.5.2