testProgs/testOnDemandRTSPServer.cpp File Reference

#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"

Include dependency graph for testOnDemandRTSPServer.cpp:

Go to the source code of this file.

Functions

static void announceStream (RTSPServer *rtspServer, ServerMediaSession *sms, char const *streamName, char const *inputFileName)
static void onMatroskaDemuxCreation (MatroskaFileServerDemux *newDemux, void *)
static void onOggDemuxCreation (OggFileServerDemux *newDemux, void *)
int main (int argc, char **argv)

Variables

UsageEnvironmentenv
Boolean reuseFirstSource = False
Boolean iFramesOnly = False
static char newDemuxWatchVariable
static MatroskaFileServerDemuxmatroskaDemux
static OggFileServerDemuxoggDemux


Function Documentation

static void announceStream ( RTSPServer rtspServer,
ServerMediaSession sms,
char const *  streamName,
char const *  inputFileName 
) [static]

Definition at line 447 of file testOnDemandRTSPServer.cpp.

References env, Medium::envir(), rtspServer, RTSPServer::rtspURL(), and sms.

Referenced by main().

00448                                                                               {
00449   char* url = rtspServer->rtspURL(sms);
00450   UsageEnvironment& env = rtspServer->envir();
00451   env << "\n\"" << streamName << "\" stream, from the file \""
00452       << inputFileName << "\"\n";
00453   env << "Play this stream using the URL \"" << url << "\"\n";
00454   delete[] url;
00455 }

int main ( int  argc,
char **  argv 
)

Definition at line 53 of file testOnDemandRTSPServer.cpp.

References RTSPServer::addServerMediaSession(), ServerMediaSession::addSubsession(), UserAuthenticationDatabase::addUserRecord(), announceStream(), authDB, OggFileServerDemux::createNew(), MatroskaFileServerDemux::createNew(), MPEG1or2FileServerDemux::createNew(), ServerMediaSession::createNew(), RTSPServer::createNew(), BasicUsageEnvironment::createNew(), BasicTaskScheduler::createNew(), TaskScheduler::doEventLoop(), env, exit, False, UsageEnvironment::getResultMsg(), RTSPServer::httpServerPortNum(), iFramesOnly, inputFileName, matroskaDemux, OutPacketBuffer::maxSize, MPEG1or2FileServerDemux::newAC3AudioServerMediaSubsession(), MPEG1or2FileServerDemux::newAudioServerMediaSubsession(), newDemuxWatchVariable, MPEG1or2FileServerDemux::newVideoServerMediaSubsession(), NULL, oggDemux, onMatroskaDemuxCreation(), onOggDemuxCreation(), reuseFirstSource, rtspServer, RTSPServer::rtspURL(), RTSPServer::setUpTunnelingOverHTTP(), sms, UsageEnvironment::taskScheduler(), and True.

00053                                 {
00054   // Begin by setting up our usage environment:
00055   TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00056   env = BasicUsageEnvironment::createNew(*scheduler);
00057 
00058   UserAuthenticationDatabase* authDB = NULL;
00059 #ifdef ACCESS_CONTROL
00060   // To implement client access control to the RTSP server, do the following:
00061   authDB = new UserAuthenticationDatabase;
00062   authDB->addUserRecord("username1", "password1"); // replace these with real strings
00063   // Repeat the above with each <username>, <password> that you wish to allow
00064   // access to the server.
00065 #endif
00066 
00067   // Create the RTSP server:
00068   RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);
00069   if (rtspServer == NULL) {
00070     *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
00071     exit(1);
00072   }
00073 
00074   char const* descriptionString
00075     = "Session streamed by \"testOnDemandRTSPServer\"";
00076 
00077   // Set up each of the possible streams that can be served by the
00078   // RTSP server.  Each such stream is implemented using a
00079   // "ServerMediaSession" object, plus one or more
00080   // "ServerMediaSubsession" objects for each audio/video substream.
00081 
00082   // A MPEG-4 video elementary stream:
00083   {
00084     char const* streamName = "mpeg4ESVideoTest";
00085     char const* inputFileName = "test.m4e";
00086     ServerMediaSession* sms
00087       = ServerMediaSession::createNew(*env, streamName, streamName,
00088                                       descriptionString);
00089     sms->addSubsession(MPEG4VideoFileServerMediaSubsession
00090                        ::createNew(*env, inputFileName, reuseFirstSource));
00091     rtspServer->addServerMediaSession(sms);
00092 
00093     announceStream(rtspServer, sms, streamName, inputFileName);
00094   }
00095 
00096   // A H.264 video elementary stream:
00097   {
00098     char const* streamName = "h264ESVideoTest";
00099     char const* inputFileName = "test.264";
00100     ServerMediaSession* sms
00101       = ServerMediaSession::createNew(*env, streamName, streamName,
00102                                       descriptionString);
00103     sms->addSubsession(H264VideoFileServerMediaSubsession
00104                        ::createNew(*env, inputFileName, reuseFirstSource));
00105     rtspServer->addServerMediaSession(sms);
00106 
00107     announceStream(rtspServer, sms, streamName, inputFileName);
00108   }
00109 
00110   // A H.265 video elementary stream:
00111   {
00112     char const* streamName = "h265ESVideoTest";
00113     char const* inputFileName = "test.265";
00114     ServerMediaSession* sms
00115       = ServerMediaSession::createNew(*env, streamName, streamName,
00116                                       descriptionString);
00117     sms->addSubsession(H265VideoFileServerMediaSubsession
00118                        ::createNew(*env, inputFileName, reuseFirstSource));
00119     rtspServer->addServerMediaSession(sms);
00120 
00121     announceStream(rtspServer, sms, streamName, inputFileName);
00122   }
00123 
00124   // A MPEG-1 or 2 audio+video program stream:
00125   {
00126     char const* streamName = "mpeg1or2AudioVideoTest";
00127     char const* inputFileName = "test.mpg";
00128     // NOTE: This *must* be a Program Stream; not an Elementary Stream
00129     ServerMediaSession* sms
00130       = ServerMediaSession::createNew(*env, streamName, streamName,
00131                                       descriptionString);
00132     MPEG1or2FileServerDemux* demux
00133       = MPEG1or2FileServerDemux::createNew(*env, inputFileName, reuseFirstSource);
00134     sms->addSubsession(demux->newVideoServerMediaSubsession(iFramesOnly));
00135     sms->addSubsession(demux->newAudioServerMediaSubsession());
00136     rtspServer->addServerMediaSession(sms);
00137 
00138     announceStream(rtspServer, sms, streamName, inputFileName);
00139   }
00140 
00141   // A MPEG-1 or 2 video elementary stream:
00142   {
00143     char const* streamName = "mpeg1or2ESVideoTest";
00144     char const* inputFileName = "testv.mpg";
00145     // NOTE: This *must* be a Video Elementary Stream; not a Program Stream
00146     ServerMediaSession* sms
00147       = ServerMediaSession::createNew(*env, streamName, streamName,
00148                                       descriptionString);
00149     sms->addSubsession(MPEG1or2VideoFileServerMediaSubsession
00150                ::createNew(*env, inputFileName, reuseFirstSource, iFramesOnly));
00151     rtspServer->addServerMediaSession(sms);
00152 
00153     announceStream(rtspServer, sms, streamName, inputFileName);
00154   }
00155 
00156   // A MP3 audio stream (actually, any MPEG-1 or 2 audio file will work):
00157   // To stream using 'ADUs' rather than raw MP3 frames, uncomment the following:
00158 //#define STREAM_USING_ADUS 1
00159   // To also reorder ADUs before streaming, uncomment the following:
00160 //#define INTERLEAVE_ADUS 1
00161   // (For more information about ADUs and interleaving,
00162   //  see <http://www.live555.com/rtp-mp3/>)
00163   {
00164     char const* streamName = "mp3AudioTest";
00165     char const* inputFileName = "test.mp3";
00166     ServerMediaSession* sms
00167       = ServerMediaSession::createNew(*env, streamName, streamName,
00168                                       descriptionString);
00169     Boolean useADUs = False;
00170     Interleaving* interleaving = NULL;
00171 #ifdef STREAM_USING_ADUS
00172     useADUs = True;
00173 #ifdef INTERLEAVE_ADUS
00174     unsigned char interleaveCycle[] = {0,2,1,3}; // or choose your own...
00175     unsigned const interleaveCycleSize
00176       = (sizeof interleaveCycle)/(sizeof (unsigned char));
00177     interleaving = new Interleaving(interleaveCycleSize, interleaveCycle);
00178 #endif
00179 #endif
00180     sms->addSubsession(MP3AudioFileServerMediaSubsession
00181                        ::createNew(*env, inputFileName, reuseFirstSource,
00182                                    useADUs, interleaving));
00183     rtspServer->addServerMediaSession(sms);
00184 
00185     announceStream(rtspServer, sms, streamName, inputFileName);
00186   }
00187 
00188   // A WAV audio stream:
00189   {
00190     char const* streamName = "wavAudioTest";
00191     char const* inputFileName = "test.wav";
00192     ServerMediaSession* sms
00193       = ServerMediaSession::createNew(*env, streamName, streamName,
00194                                       descriptionString);
00195     // To convert 16-bit PCM data to 8-bit u-law, prior to streaming,
00196     // change the following to True:
00197     Boolean convertToULaw = False;
00198     sms->addSubsession(WAVAudioFileServerMediaSubsession
00199                ::createNew(*env, inputFileName, reuseFirstSource, convertToULaw));
00200     rtspServer->addServerMediaSession(sms);
00201 
00202     announceStream(rtspServer, sms, streamName, inputFileName);
00203   }
00204 
00205   // An AMR audio stream:
00206   {
00207     char const* streamName = "amrAudioTest";
00208     char const* inputFileName = "test.amr";
00209     ServerMediaSession* sms
00210       = ServerMediaSession::createNew(*env, streamName, streamName,
00211                                       descriptionString);
00212     sms->addSubsession(AMRAudioFileServerMediaSubsession
00213                        ::createNew(*env, inputFileName, reuseFirstSource));
00214     rtspServer->addServerMediaSession(sms);
00215 
00216     announceStream(rtspServer, sms, streamName, inputFileName);
00217   }
00218 
00219   // A 'VOB' file (e.g., from an unencrypted DVD):
00220   {
00221     char const* streamName = "vobTest";
00222     char const* inputFileName = "test.vob";
00223     ServerMediaSession* sms
00224       = ServerMediaSession::createNew(*env, streamName, streamName,
00225                                       descriptionString);
00226     // Note: VOB files are MPEG-2 Program Stream files, but using AC-3 audio
00227     MPEG1or2FileServerDemux* demux
00228       = MPEG1or2FileServerDemux::createNew(*env, inputFileName, reuseFirstSource);
00229     sms->addSubsession(demux->newVideoServerMediaSubsession(iFramesOnly));
00230     sms->addSubsession(demux->newAC3AudioServerMediaSubsession());
00231     rtspServer->addServerMediaSession(sms);
00232 
00233     announceStream(rtspServer, sms, streamName, inputFileName);
00234   }
00235 
00236   // A MPEG-2 Transport Stream:
00237   {
00238     char const* streamName = "mpeg2TransportStreamTest";
00239     char const* inputFileName = "test.ts";
00240     char const* indexFileName = "test.tsx";
00241     ServerMediaSession* sms
00242       = ServerMediaSession::createNew(*env, streamName, streamName,
00243                                       descriptionString);
00244     sms->addSubsession(MPEG2TransportFileServerMediaSubsession
00245                        ::createNew(*env, inputFileName, indexFileName, reuseFirstSource));
00246     rtspServer->addServerMediaSession(sms);
00247 
00248     announceStream(rtspServer, sms, streamName, inputFileName);
00249   }
00250 
00251   // An AAC audio stream (ADTS-format file):
00252   {
00253     char const* streamName = "aacAudioTest";
00254     char const* inputFileName = "test.aac";
00255     ServerMediaSession* sms
00256       = ServerMediaSession::createNew(*env, streamName, streamName,
00257                                       descriptionString);
00258     sms->addSubsession(ADTSAudioFileServerMediaSubsession
00259                        ::createNew(*env, inputFileName, reuseFirstSource));
00260     rtspServer->addServerMediaSession(sms);
00261 
00262     announceStream(rtspServer, sms, streamName, inputFileName);
00263   }
00264 
00265   // A DV video stream:
00266   {
00267     // First, make sure that the RTPSinks' buffers will be large enough to handle the huge size of DV frames (as big as 288000).
00268     OutPacketBuffer::maxSize = 300000;
00269 
00270     char const* streamName = "dvVideoTest";
00271     char const* inputFileName = "test.dv";
00272     ServerMediaSession* sms
00273       = ServerMediaSession::createNew(*env, streamName, streamName,
00274                                       descriptionString);
00275     sms->addSubsession(DVVideoFileServerMediaSubsession
00276                        ::createNew(*env, inputFileName, reuseFirstSource));
00277     rtspServer->addServerMediaSession(sms);
00278 
00279     announceStream(rtspServer, sms, streamName, inputFileName);
00280   }
00281 
00282   // A AC3 video elementary stream:
00283   {
00284     char const* streamName = "ac3AudioTest";
00285     char const* inputFileName = "test.ac3";
00286     ServerMediaSession* sms
00287       = ServerMediaSession::createNew(*env, streamName, streamName,
00288                                       descriptionString);
00289 
00290     sms->addSubsession(AC3AudioFileServerMediaSubsession
00291                        ::createNew(*env, inputFileName, reuseFirstSource));
00292 
00293     rtspServer->addServerMediaSession(sms);
00294 
00295     announceStream(rtspServer, sms, streamName, inputFileName);
00296   }
00297 
00298   // A Matroska ('.mkv') file, with video+audio+subtitle streams:
00299   {
00300     char const* streamName = "matroskaFileTest";
00301     char const* inputFileName = "test.mkv";
00302     ServerMediaSession* sms
00303       = ServerMediaSession::createNew(*env, streamName, streamName,
00304                                       descriptionString);
00305 
00306     newDemuxWatchVariable = 0;
00307     MatroskaFileServerDemux::createNew(*env, inputFileName, onMatroskaDemuxCreation, NULL);
00308     env->taskScheduler().doEventLoop(&newDemuxWatchVariable);
00309 
00310     Boolean sessionHasTracks = False;
00311     ServerMediaSubsession* smss;
00312     while ((smss = matroskaDemux->newServerMediaSubsession()) != NULL) {
00313       sms->addSubsession(smss);
00314       sessionHasTracks = True;
00315     }
00316     if (sessionHasTracks) {
00317       rtspServer->addServerMediaSession(sms);
00318     }
00319     // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server.
00320 
00321     announceStream(rtspServer, sms, streamName, inputFileName);
00322   }
00323 
00324   // A WebM ('.webm') file, with video(VP8)+audio(Vorbis) streams:
00325   // (Note: ".webm' files are special types of Matroska files, so we use the same code as the Matroska ('.mkv') file code above.)
00326   {
00327     char const* streamName = "webmFileTest";
00328     char const* inputFileName = "test.webm";
00329     ServerMediaSession* sms
00330       = ServerMediaSession::createNew(*env, streamName, streamName,
00331                                       descriptionString);
00332 
00333     newDemuxWatchVariable = 0;
00334     MatroskaFileServerDemux::createNew(*env, inputFileName, onMatroskaDemuxCreation, NULL);
00335     env->taskScheduler().doEventLoop(&newDemuxWatchVariable);
00336 
00337     Boolean sessionHasTracks = False;
00338     ServerMediaSubsession* smss;
00339     while ((smss = matroskaDemux->newServerMediaSubsession()) != NULL) {
00340       sms->addSubsession(smss);
00341       sessionHasTracks = True;
00342     }
00343     if (sessionHasTracks) {
00344       rtspServer->addServerMediaSession(sms);
00345     }
00346     // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server.
00347 
00348     announceStream(rtspServer, sms, streamName, inputFileName);
00349   }
00350 
00351   // An Ogg ('.ogg') file, with video and/or audio streams:
00352   {
00353     char const* streamName = "oggFileTest";
00354     char const* inputFileName = "test.ogg";
00355     ServerMediaSession* sms
00356       = ServerMediaSession::createNew(*env, streamName, streamName,
00357                                       descriptionString);
00358 
00359     newDemuxWatchVariable = 0;
00360     OggFileServerDemux::createNew(*env, inputFileName, onOggDemuxCreation, NULL);
00361     env->taskScheduler().doEventLoop(&newDemuxWatchVariable);
00362 
00363     Boolean sessionHasTracks = False;
00364     ServerMediaSubsession* smss;
00365     while ((smss = oggDemux->newServerMediaSubsession()) != NULL) {
00366       sms->addSubsession(smss);
00367       sessionHasTracks = True;
00368     }
00369     if (sessionHasTracks) {
00370       rtspServer->addServerMediaSession(sms);
00371     }
00372     // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server.
00373 
00374     announceStream(rtspServer, sms, streamName, inputFileName);
00375   }
00376 
00377   // An Opus ('.opus') audio file:
00378   // (Note: ".opus' files are special types of Ogg files, so we use the same code as the Ogg ('.ogg') file code above.)
00379   {
00380     char const* streamName = "opusFileTest";
00381     char const* inputFileName = "test.opus";
00382     ServerMediaSession* sms
00383       = ServerMediaSession::createNew(*env, streamName, streamName,
00384                                       descriptionString);
00385 
00386     newDemuxWatchVariable = 0;
00387     OggFileServerDemux::createNew(*env, inputFileName, onOggDemuxCreation, NULL);
00388     env->taskScheduler().doEventLoop(&newDemuxWatchVariable);
00389 
00390     Boolean sessionHasTracks = False;
00391     ServerMediaSubsession* smss;
00392     while ((smss = oggDemux->newServerMediaSubsession()) != NULL) {
00393       sms->addSubsession(smss);
00394       sessionHasTracks = True;
00395     }
00396     if (sessionHasTracks) {
00397       rtspServer->addServerMediaSession(sms);
00398     }
00399     // otherwise, because the stream has no tracks, we don't add a ServerMediaSession to the server.
00400 
00401     announceStream(rtspServer, sms, streamName, inputFileName);
00402   }
00403 
00404   // A MPEG-2 Transport Stream, coming from a live UDP (raw-UDP or RTP/UDP) source:
00405   {
00406     char const* streamName = "mpeg2TransportStreamFromUDPSourceTest";
00407     char const* inputAddressStr = "239.255.42.42";
00408         // This causes the server to take its input from the stream sent by the "testMPEG2TransportStreamer" demo application.
00409         // (Note: If the input UDP source is unicast rather than multicast, then change this to NULL.)
00410     portNumBits const inputPortNum = 1234;
00411         // This causes the server to take its input from the stream sent by the "testMPEG2TransportStreamer" demo application.
00412     Boolean const inputStreamIsRawUDP = False; 
00413     ServerMediaSession* sms
00414       = ServerMediaSession::createNew(*env, streamName, streamName,
00415                                       descriptionString);
00416     sms->addSubsession(MPEG2TransportUDPServerMediaSubsession
00417                        ::createNew(*env, inputAddressStr, inputPortNum, inputStreamIsRawUDP));
00418     rtspServer->addServerMediaSession(sms);
00419 
00420     char* url = rtspServer->rtspURL(sms);
00421     *env << "\n\"" << streamName << "\" stream, from a UDP Transport Stream input source \n\t(";
00422     if (inputAddressStr != NULL) {
00423       *env << "IP multicast address " << inputAddressStr << ",";
00424     } else {
00425       *env << "unicast;";
00426     }
00427     *env << " port " << inputPortNum << ")\n";
00428     *env << "Play this stream using the URL \"" << url << "\"\n";
00429     delete[] url;
00430   }
00431 
00432   // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
00433   // Try first with the default HTTP port (80), and then with the alternative HTTP
00434   // port numbers (8000 and 8080).
00435 
00436   if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
00437     *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
00438   } else {
00439     *env << "\n(RTSP-over-HTTP tunneling is not available.)\n";
00440   }
00441 
00442   env->taskScheduler().doEventLoop(); // does not return
00443 
00444   return 0; // only to prevent compiler warning
00445 }

static void onMatroskaDemuxCreation ( MatroskaFileServerDemux newDemux,
void *   
) [static]

Definition at line 42 of file testOnDemandRTSPServer.cpp.

References matroskaDemux, and newDemuxWatchVariable.

Referenced by createNewSMS(), and main().

00042                                                                                              {
00043   matroskaDemux = newDemux;
00044   newDemuxWatchVariable = 1;
00045 }

static void onOggDemuxCreation ( OggFileServerDemux newDemux,
void *   
) [static]

Definition at line 48 of file testOnDemandRTSPServer.cpp.

References newDemuxWatchVariable, and oggDemux.

Referenced by createNewSMS(), and main().

00048                                                                                    {
00049   oggDemux = newDemux;
00050   newDemuxWatchVariable = 1;
00051 }


Variable Documentation

UsageEnvironment* env

Definition at line 24 of file testOnDemandRTSPServer.cpp.

Boolean iFramesOnly = False

Definition at line 34 of file testOnDemandRTSPServer.cpp.

MatroskaFileServerDemux* matroskaDemux [static]

Definition at line 41 of file testOnDemandRTSPServer.cpp.

char newDemuxWatchVariable [static]

Definition at line 39 of file testOnDemandRTSPServer.cpp.

Referenced by main(), onMatroskaDemuxCreation(), and onOggDemuxCreation().

OggFileServerDemux* oggDemux [static]

Definition at line 47 of file testOnDemandRTSPServer.cpp.

Boolean reuseFirstSource = False

Definition at line 29 of file testOnDemandRTSPServer.cpp.

Referenced by main().


Generated on Tue Mar 25 14:38:52 2014 for live by  doxygen 1.5.2