testProgs/testMPEG1or2AudioVideoToDarwin.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 Program Stream file,
00018 // splits it into Audio and Video Elementary Streams,
00019 // and streams both using RTP, through a remote Darwin Streaming Server.
00020 // main program
00021 
00023 // This demo software is provided only as a courtesy to those developers who - for whatever reason - wish
00024 // to send outgoing streams through a separate Darwin Streaming Server.  However, it is not necessary to use
00025 // a Darwin Streaming Server in order to serve streams using RTP/RTSP.  Instead, the "LIVE555 Streaming Media"
00026 // software includes its own RTSP/RTP server implementation, which you should use instead.  For tips on using
00027 // our RTSP/RTP server implementation, see the "testOnDemandRTSPServer" demo application, and/or the
00028 // "live555MediaServer" application (in the "mediaServer") directory.
00030 
00031 #include "liveMedia.hh"
00032 #include "BasicUsageEnvironment.hh"
00033 
00034 UsageEnvironment* env;
00035 char const* inputFileName = "test.mpg";
00036 char const* remoteStreamName = "test.sdp"; // the stream name, as served by the DSS
00037 MPEG1or2Demux* mpegDemux;
00038 FramedSource* audioSource;
00039 FramedSource* videoSource;
00040 RTPSink* audioSink;
00041 RTPSink* videoSink;
00042 
00043 char const* programName;
00044 
00045 // To stream *only* MPEG "I" frames (e.g., to reduce network bandwidth),
00046 // change the following "False" to "True":
00047 Boolean iFramesOnly = False;
00048 
00049 void usage() {
00050   *env << "usage: " << programName
00051        << " <Darwin Streaming Server name or IP address>\n";
00052   exit(1);
00053 }
00054 
00055 void play(); // forward
00056 
00057 int main(int argc, char** argv) {
00058   // Begin by setting up our usage environment:
00059   TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00060   env = BasicUsageEnvironment::createNew(*scheduler);
00061 
00062   // Parse command-line arguments:
00063   programName = argv[0];
00064   if (argc != 2) usage();
00065   char const* dssNameOrAddress = argv[1];
00066 
00067   // Create a 'Darwin injector' object:
00068   DarwinInjector* injector = DarwinInjector::createNew(*env, programName);
00069 
00071   // Create 'groupsocks' for RTP and RTCP.
00072   // (Note: Because we will actually be streaming through a remote Darwin server,
00073   // via TCP, we just use dummy destination addresses, port numbers, and TTLs here.)
00074   struct in_addr dummyDestAddress;
00075   dummyDestAddress.s_addr = 0;
00076   Groupsock rtpGroupsockAudio(*env, dummyDestAddress, 0, 0);
00077   Groupsock rtcpGroupsockAudio(*env, dummyDestAddress, 0, 0);
00078 
00079   // Create a 'MPEG Audio RTP' sink from the RTP 'groupsock':
00080   audioSink = MPEG1or2AudioRTPSink::createNew(*env, &rtpGroupsockAudio);
00081 
00082   // Create (and start) a 'RTCP instance' for this RTP sink:
00083   const unsigned estimatedSessionBandwidthAudio = 160; // in kbps; for RTCP b/w share
00084   const unsigned maxCNAMElen = 100;
00085   unsigned char CNAME[maxCNAMElen+1];
00086   gethostname((char*)CNAME, maxCNAMElen);
00087   CNAME[maxCNAMElen] = '\0'; // just in case
00088   RTCPInstance* audioRTCP =
00089     RTCPInstance::createNew(*env, &rtcpGroupsockAudio,
00090                             estimatedSessionBandwidthAudio, CNAME,
00091                             audioSink, NULL /* we're a server */);
00092   // Note: This starts RTCP running automatically
00093 
00094   // Add these to our 'Darwin injector':
00095   injector->addStream(audioSink, audioRTCP);
00097 
00099   // Create 'groupsocks' for RTP and RTCP.
00100   // (Note: Because we will actually be streaming through a remote Darwin server,
00101   // via TCP, we just use dummy destination addresses, port numbers, and TTLs here.)
00102   Groupsock rtpGroupsockVideo(*env, dummyDestAddress, 0, 0);
00103   Groupsock rtcpGroupsockVideo(*env, dummyDestAddress, 0, 0);
00104 
00105   // Create a 'MPEG Video RTP' sink from the RTP 'groupsock':
00106   videoSink = MPEG1or2VideoRTPSink::createNew(*env, &rtpGroupsockVideo);
00107 
00108   // Create (and start) a 'RTCP instance' for this RTP sink:
00109   const unsigned estimatedSessionBandwidthVideo = 4500; // in kbps; for RTCP b/w share
00110   RTCPInstance* videoRTCP =
00111     RTCPInstance::createNew(*env, &rtcpGroupsockVideo,
00112                               estimatedSessionBandwidthVideo, CNAME,
00113                               videoSink, NULL /* we're a server */);
00114   // Note: This starts RTCP running automatically
00115 
00116   // Add these to our 'Darwin injector':
00117   injector->addStream(videoSink, videoRTCP);
00119 
00120   // Next, specify the destination Darwin Streaming Server:
00121   if (!injector->setDestination(dssNameOrAddress, remoteStreamName,
00122                                 programName, "LIVE555 Streaming Media")) {
00123     *env << "injector->setDestination() failed: "
00124          << env->getResultMsg() << "\n";
00125     exit(1);
00126   }
00127 
00128   *env << "Play this stream (from the Darwin Streaming Server) using the URL:\n"
00129        << "\trtsp://" << dssNameOrAddress << "/" << remoteStreamName << "\n";
00130 
00131   // Finally, start the streaming:
00132   *env << "Beginning streaming...\n";
00133   play();
00134 
00135   env->taskScheduler().doEventLoop(); // does not return
00136 
00137   return 0; // only to prevent compiler warning
00138 }
00139 
00140 void afterPlaying(void* clientData) {
00141   // One of the sinks has ended playing.
00142   // Check whether any of the sources have a pending read.  If so,
00143   // wait until its sink ends playing also:
00144   if (audioSource->isCurrentlyAwaitingData()
00145       || videoSource->isCurrentlyAwaitingData()) return;
00146 
00147   // Now that both sinks have ended, close both input sources,
00148   // and start playing again:
00149   *env << "...done reading from file\n";
00150 
00151   audioSink->stopPlaying();
00152   videoSink->stopPlaying();
00153       // ensures that both are shut down
00154   Medium::close(audioSource);
00155   Medium::close(videoSource);
00156   Medium::close(mpegDemux);
00157   // Note: This also closes the input file that this source read from.
00158 
00159   // Start playing once again:
00160   play();
00161 }
00162 
00163 void play() {
00164   // Open the input file as a 'byte-stream file source':
00165   ByteStreamFileSource* fileSource
00166     = ByteStreamFileSource::createNew(*env, inputFileName);
00167   if (fileSource == NULL) {
00168     *env << "Unable to open file \"" << inputFileName
00169          << "\" as a byte-stream file source\n";
00170     exit(1);
00171   }
00172 
00173   // We must demultiplex Audio and Video Elementary Streams
00174   // from the input source:
00175   mpegDemux = MPEG1or2Demux::createNew(*env, fileSource);
00176   FramedSource* audioES = mpegDemux->newAudioStream();
00177   FramedSource* videoES = mpegDemux->newVideoStream();
00178 
00179   // Create a framer for each Elementary Stream:
00180   audioSource
00181     = MPEG1or2AudioStreamFramer::createNew(*env, audioES);
00182   videoSource
00183     = MPEG1or2VideoStreamFramer::createNew(*env, videoES, iFramesOnly);
00184 
00185   // Finally, start playing each sink.
00186   *env << "Beginning to read from file...\n";
00187   videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
00188   audioSink->startPlaying(*audioSource, afterPlaying, audioSink);
00189 }

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