mediaServer/DynamicRTSPServer.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-2008, Live Networks, Inc.  All rights reserved
00017 // A subclass of "RTSPServer" that creates "ServerMediaSession"s on demand,
00018 // based on whether or not the specified stream name exists as a file
00019 // Implementation
00020 
00021 #include "DynamicRTSPServer.hh"
00022 #include <liveMedia.hh>
00023 #include <string.h>
00024 
00025 DynamicRTSPServer*
00026 DynamicRTSPServer::createNew(UsageEnvironment& env, Port ourPort,
00027                              UserAuthenticationDatabase* authDatabase,
00028                              unsigned reclamationTestSeconds) {
00029   int ourSocket = -1;
00030 
00031   do {
00032     int ourSocket = setUpOurSocket(env, ourPort);
00033     if (ourSocket == -1) break;
00034 
00035     return new DynamicRTSPServer(env, ourSocket, ourPort, authDatabase, reclamationTestSeconds);
00036   } while (0);
00037 
00038   if (ourSocket != -1) ::closeSocket(ourSocket);
00039   return NULL;
00040 }
00041 
00042 DynamicRTSPServer::DynamicRTSPServer(UsageEnvironment& env, int ourSocket,
00043                                      Port ourPort,
00044                                      UserAuthenticationDatabase* authDatabase, unsigned reclamationTestSeconds)
00045   : RTSPServer(env, ourSocket, ourPort, authDatabase, reclamationTestSeconds) {
00046 }
00047 
00048 DynamicRTSPServer::~DynamicRTSPServer() {
00049 }
00050 
00051 static ServerMediaSession* createNewSMS(UsageEnvironment& env,
00052                                         char const* fileName, FILE* fid); // forward
00053 
00054 ServerMediaSession*
00055 DynamicRTSPServer::lookupServerMediaSession(char const* streamName) {
00056   // First, check whether the specified "streamName" exists as a local file:
00057   FILE* fid = fopen(streamName, "rb");
00058   Boolean fileExists = fid != NULL;
00059 
00060   // Next, check whether we already have a "ServerMediaSession" for this file:
00061   ServerMediaSession* sms = RTSPServer::lookupServerMediaSession(streamName);
00062   Boolean smsExists = sms != NULL;
00063 
00064   // Handle the four possibilities for "fileExists" and "smsExists":
00065   if (!fileExists) {
00066     if (smsExists) {
00067       // "sms" was created for a file that no longer exists. Remove it:
00068       removeServerMediaSession(sms);
00069     }
00070     return NULL;
00071   } else {
00072     if (!smsExists) {
00073       // Create a new "ServerMediaSession" object for streaming from the named file.
00074       sms = createNewSMS(envir(), streamName, fid);
00075       addServerMediaSession(sms);
00076     }
00077     fclose(fid);
00078     return sms;
00079   }
00080 }
00081 
00082 #define NEW_SMS(description) do {\
00083 char* descStr = description\
00084     ", streamed by the LIVE555 Media Server";\
00085 sms = ServerMediaSession::createNew(env, fileName, fileName, descStr);\
00086 } while(0)
00087 
00088 static ServerMediaSession* createNewSMS(UsageEnvironment& env,
00089                                         char const* fileName, FILE* /*fid*/) {
00090   // Use the file name extension to determine the type of "ServerMediaSession":
00091   char const* extension = strrchr(fileName, '.');
00092   if (extension == NULL) return NULL;
00093 
00094   ServerMediaSession* sms = NULL;
00095   Boolean const reuseSource = False;
00096   if (strcmp(extension, ".aac") == 0) {
00097     // Assumed to be an AAC Audio (ADTS format) file:
00098     NEW_SMS("AAC Audio");
00099     sms->addSubsession(ADTSAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));
00100   } else if (strcmp(extension, ".amr") == 0) {
00101     // Assumed to be an AMR Audio file:
00102     NEW_SMS("AMR Audio");
00103     sms->addSubsession(AMRAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource));
00104   } else if (strcmp(extension, ".m4e") == 0) {
00105     // Assumed to be a MPEG-4 Video Elementary Stream file:
00106     NEW_SMS("MPEG-4 Video");
00107     sms->addSubsession(MPEG4VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
00108   } else if (strcmp(extension, ".mp3") == 0) {
00109     // Assumed to be a MPEG-1 or 2 Audio file:
00110     NEW_SMS("MPEG-1 or 2 Audio");
00111     // To stream using 'ADUs' rather than raw MP3 frames, uncomment the following:
00112 //#define STREAM_USING_ADUS 1
00113     // To also reorder ADUs before streaming, uncomment the following:
00114 //#define INTERLEAVE_ADUS 1
00115     // (For more information about ADUs and interleaving,
00116     //  see <http://www.live555.com/rtp-mp3/>)
00117     Boolean useADUs = False;
00118     Interleaving* interleaving = NULL;
00119 #ifdef STREAM_USING_ADUS
00120     useADUs = True;
00121 #ifdef INTERLEAVE_ADUS
00122     unsigned char interleaveCycle[] = {0,2,1,3}; // or choose your own...
00123     unsigned const interleaveCycleSize
00124       = (sizeof interleaveCycle)/(sizeof (unsigned char));
00125     interleaving = new Interleaving(interleaveCycleSize, interleaveCycle);
00126 #endif
00127 #endif
00128     sms->addSubsession(MP3AudioFileServerMediaSubsession::createNew(env, fileName, reuseSource, useADUs, interleaving));
00129   } else if (strcmp(extension, ".mpg") == 0) {
00130     // Assumed to be a MPEG-1 or 2 Program Stream (audio+video) file:
00131     NEW_SMS("MPEG-1 or 2 Program Stream");
00132     MPEG1or2FileServerDemux* demux
00133       = MPEG1or2FileServerDemux::createNew(env, fileName, reuseSource);
00134     sms->addSubsession(demux->newVideoServerMediaSubsession());
00135     sms->addSubsession(demux->newAudioServerMediaSubsession());
00136   } else if (strcmp(extension, ".ts") == 0) {
00137     // Assumed to be a MPEG Transport Stream file:
00138     // Use an index file name that's the same as the TS file name, except with ".tsx":
00139     unsigned indexFileNameLen = strlen(fileName) + 2; // allow for trailing "x\0"
00140     char* indexFileName = new char[indexFileNameLen];
00141     sprintf(indexFileName, "%sx", fileName);
00142     NEW_SMS("MPEG Transport Stream");
00143     sms->addSubsession(MPEG2TransportFileServerMediaSubsession::createNew(env, fileName, indexFileName, reuseSource));
00144     delete[] indexFileName;
00145   } else if (strcmp(extension, ".wav") == 0) {
00146     // Assumed to be a WAV Audio file:
00147     NEW_SMS("WAV Audio Stream");
00148     // To convert 16-bit PCM data to 8-bit u-law, prior to streaming,
00149     // change the following to True:
00150     Boolean convertToULaw = False;
00151     sms->addSubsession(WAVAudioFileServerMediaSubsession::createNew(env, fileName, reuseSource, convertToULaw));
00152   }
00153 
00154   return sms;
00155 }

Generated on Tue Oct 7 15:38:10 2008 for live by  doxygen 1.5.2