testProgs/testMPEG1or2VideoStreamer.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-1 or 2 Video Elementary 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 // Uncomment the following if the input file is a MPEG Program Stream
00026 // rather than a MPEG Video Elementary Stream
00027 //#define SOURCE_IS_PROGRAM_STREAM 1
00028 
00029 // To stream using "source-specific multicast" (SSM), uncomment the following:
00030 //#define USE_SSM 1
00031 #ifdef USE_SSM
00032 Boolean const isSSM = True;
00033 #else
00034 Boolean const isSSM = False;
00035 #endif
00036 
00037 // To set up an internal RTSP server, uncomment the following:
00038 //#define IMPLEMENT_RTSP_SERVER 1
00039 // (Note that this RTSP server works for multicast only)
00040 
00041 // To stream *only* MPEG "I" frames (e.g., to reduce network bandwidth),
00042 // change the following "False" to "True":
00043 Boolean iFramesOnly = False;
00044 
00045 UsageEnvironment* env;
00046 char const* inputFileName = "test.mpg";
00047 #ifdef SOURCE_IS_PROGRAM_STREAM
00048 MPEG1or2Demux* mpegDemux;
00049 #endif
00050 MediaSource* videoSource;
00051 RTPSink* videoSink;
00052 
00053 void play(); // forward
00054 
00055 int main(int argc, char** argv) {
00056   // Begin by setting up our usage environment:
00057   TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00058   env = BasicUsageEnvironment::createNew(*scheduler);
00059 
00060   // Create 'groupsocks' for RTP and RTCP:
00061   char const* destinationAddressStr
00062 #ifdef USE_SSM
00063     = "232.255.42.42";
00064 #else
00065     = "239.255.42.42";
00066   // Note: This is a multicast address.  If you wish to stream using
00067   // unicast instead, then replace this string with the unicast address
00068   // of the (single) destination.  (You may also need to make a similar
00069   // change to the receiver program.)
00070 #endif
00071   const unsigned short rtpPortNum = 8888;
00072   const unsigned short rtcpPortNum = rtpPortNum+1;
00073   const unsigned char ttl = 7; // low, in case routers don't admin scope
00074 
00075   struct in_addr destinationAddress;
00076   destinationAddress.s_addr = our_inet_addr(destinationAddressStr);
00077   const Port rtpPort(rtpPortNum);
00078   const Port rtcpPort(rtcpPortNum);
00079 
00080   Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
00081   Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
00082 #ifdef USE_SSM
00083   rtpGroupsock.multicastSendOnly();
00084   rtcpGroupsock.multicastSendOnly();
00085 #endif
00086 
00087   // Create a 'MPEG Video RTP' sink from the RTP 'groupsock':
00088   videoSink = MPEG1or2VideoRTPSink::createNew(*env, &rtpGroupsock);
00089 
00090   // Create (and start) a 'RTCP instance' for this RTP sink:
00091   const unsigned estimatedSessionBandwidth = 4500; // in kbps; for RTCP b/w share
00092   const unsigned maxCNAMElen = 100;
00093   unsigned char CNAME[maxCNAMElen+1];
00094   gethostname((char*)CNAME, maxCNAMElen);
00095   CNAME[maxCNAMElen] = '\0'; // just in case
00096 #ifdef IMPLEMENT_RTSP_SERVER
00097   RTCPInstance* rtcp =
00098 #endif
00099     RTCPInstance::createNew(*env, &rtcpGroupsock,
00100                               estimatedSessionBandwidth, CNAME,
00101                               videoSink, NULL /* we're a server */, isSSM);
00102   // Note: This starts RTCP running automatically
00103 
00104 #ifdef IMPLEMENT_RTSP_SERVER
00105   RTSPServer* rtspServer = RTSPServer::createNew(*env);
00106   // Note that this (attempts to) start a server on the default RTSP server
00107   // port: 554.  To use a different port number, add it as an extra
00108   // (optional) parameter to the "RTSPServer::createNew()" call above.
00109   if (rtspServer == NULL) {
00110     *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
00111     exit(1);
00112   }
00113   ServerMediaSession* sms
00114     = ServerMediaSession::createNew(*env, "testStream", inputFileName,
00115                    "Session streamed by \"testMPEG1or2VideoStreamer\"",
00116                                            isSSM);
00117   sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
00118   rtspServer->addServerMediaSession(sms);
00119 
00120   char* url = rtspServer->rtspURL(sms);
00121   *env << "Play this stream using the URL \"" << url << "\"\n";
00122   delete[] url;
00123 #endif
00124 
00125   // Finally, start the streaming:
00126   *env << "Beginning streaming...\n";
00127   play();
00128 
00129   env->taskScheduler().doEventLoop(); // does not return
00130 
00131   return 0; // only to prevent compiler warning
00132 }
00133 
00134 void afterPlaying(void* /*clientData*/) {
00135   *env << "...done reading from file\n";
00136 
00137   videoSink->stopPlaying();
00138   Medium::close(videoSource);
00139 #ifdef SOURCE_IS_PROGRAM_STREAM
00140   Medium::close(mpegDemux);
00141 #endif
00142   // Note that this also closes the input file that this source read from.
00143 
00144   play();
00145 }
00146 
00147 void play() {
00148   // Open the input file as a 'byte-stream file source':
00149   ByteStreamFileSource* fileSource
00150     = ByteStreamFileSource::createNew(*env, inputFileName);
00151   if (fileSource == NULL) {
00152     *env << "Unable to open file \"" << inputFileName
00153          << "\" as a byte-stream file source\n";
00154     exit(1);
00155   }
00156 
00157   FramedSource* videoES;
00158 #ifdef SOURCE_IS_PROGRAM_STREAM
00159   // We must demultiplex a Video Elementary Stream from the input source:
00160   mpegDemux = MPEG1or2Demux::createNew(*env, fileSource);
00161   videoES = mpegDemux->newVideoStream();
00162 #else
00163   // The input source is assumed to already be a Video Elementary Stream:
00164   videoES = fileSource;
00165 #endif
00166 
00167   // Create a framer for the Video Elementary Stream:
00168   videoSource
00169     = MPEG1or2VideoStreamFramer::createNew(*env, videoES, iFramesOnly);
00170 
00171   // Finally, start playing:
00172   *env << "Beginning to read from file...\n";
00173   videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
00174 }

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