00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "liveMedia.hh"
00021 #include "GroupsockHelper.hh"
00022
00023 #include "BasicUsageEnvironment.hh"
00024
00025
00026
00027
00028
00029 UsageEnvironment* env;
00030
00031 void play();
00032
00033 int main(int argc, char** argv) {
00034
00035 TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00036 env = BasicUsageEnvironment::createNew(*scheduler);
00037
00038 play();
00039
00040 env->taskScheduler().doEventLoop();
00041 return 0;
00042 }
00043
00044 char const* inputFileName = "test.wav";
00045
00046 void afterPlaying(void* clientData);
00047
00048
00049
00050 struct sessionState_t {
00051 FramedSource* source;
00052 RTPSink* sink;
00053 RTCPInstance* rtcpInstance;
00054 Groupsock* rtpGroupsock;
00055 Groupsock* rtcpGroupsock;
00056 RTSPServer* rtspServer;
00057 } sessionState;
00058
00059 void play() {
00060
00061 WAVAudioFileSource* pcmSource
00062 = WAVAudioFileSource::createNew(*env, inputFileName);
00063 if (pcmSource == NULL) {
00064 *env << "Unable to open file \"" << inputFileName
00065 << "\" as a WAV audio file source: "
00066 << env->getResultMsg() << "\n";
00067 exit(1);
00068 }
00069
00070
00071 unsigned char const bitsPerSample = pcmSource->bitsPerSample();
00072 if (bitsPerSample != 8 && bitsPerSample != 16) {
00073 *env << "The input file contains " << bitsPerSample
00074 << " bit-per-sample audio, which we don't handle\n";
00075 exit(1);
00076 }
00077 sessionState.source = pcmSource;
00078 unsigned const samplingFrequency = pcmSource->samplingFrequency();
00079 unsigned char const numChannels = pcmSource->numChannels();
00080 unsigned bitsPerSecond
00081 = samplingFrequency*bitsPerSample*numChannels;
00082 *env << "Audio source parameters:\n\t" << samplingFrequency << " Hz, ";
00083 *env << bitsPerSample << " bits-per-sample, ";
00084 *env << numChannels << " channels => ";
00085 *env << bitsPerSecond << " bits-per-second\n";
00086
00087
00088
00089 char const* mimeType;
00090 unsigned char payloadFormatCode;
00091 if (bitsPerSample == 16) {
00092 #ifdef CONVERT_TO_ULAW
00093
00094
00095 sessionState.source
00096 = uLawFromPCMAudioSource::createNew(*env, pcmSource, 1);
00097 if (sessionState.source == NULL) {
00098 *env << "Unable to create a u-law filter from the PCM audio source: "
00099 << env->getResultMsg() << "\n";
00100 exit(1);
00101 }
00102 bitsPerSecond /= 2;
00103 mimeType = "PCMU";
00104 if (samplingFrequency == 8000 && numChannels == 1) {
00105 payloadFormatCode = 0;
00106 } else {
00107 payloadFormatCode = 96;
00108 }
00109 *env << "Converting to 8-bit u-law audio for streaming => "
00110 << bitsPerSecond << " bits-per-second\n";
00111 #else
00112
00113
00114 sessionState.source = EndianSwap16::createNew(*env, pcmSource);
00115 if (sessionState.source == NULL) {
00116 *env << "Unable to create a little->bit-endian order filter from the PCM audio source: "
00117 << env->getResultMsg() << "\n";
00118 exit(1);
00119 }
00120 mimeType = "L16";
00121 if (samplingFrequency == 44100 && numChannels == 2) {
00122 payloadFormatCode = 10;
00123 } else if (samplingFrequency == 44100 && numChannels == 1) {
00124 payloadFormatCode = 11;
00125 } else {
00126 payloadFormatCode = 96;
00127 }
00128 *env << "Converting to network byte order for streaming\n";
00129 #endif
00130 } else {
00131
00132 mimeType = "L8";
00133 payloadFormatCode = 96;
00134 }
00135
00136
00137 struct in_addr destinationAddress;
00138 destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
00139
00140
00141
00142
00143 const unsigned short rtpPortNum = 2222;
00144 const unsigned short rtcpPortNum = rtpPortNum+1;
00145 const unsigned char ttl = 255;
00146
00147 const Port rtpPort(rtpPortNum);
00148 const Port rtcpPort(rtcpPortNum);
00149
00150 sessionState.rtpGroupsock
00151 = new Groupsock(*env, destinationAddress, rtpPort, ttl);
00152 sessionState.rtpGroupsock->multicastSendOnly();
00153 sessionState.rtcpGroupsock
00154 = new Groupsock(*env, destinationAddress, rtcpPort, ttl);
00155 sessionState.rtcpGroupsock->multicastSendOnly();
00156
00157
00158
00159 sessionState.sink
00160 = SimpleRTPSink::createNew(*env, sessionState.rtpGroupsock,
00161 payloadFormatCode, samplingFrequency,
00162 "audio", mimeType, numChannels);
00163
00164
00165 const unsigned estimatedSessionBandwidth = bitsPerSecond/1000;
00166
00167 const unsigned maxCNAMElen = 100;
00168 unsigned char CNAME[maxCNAMElen+1];
00169 gethostname((char*)CNAME, maxCNAMElen);
00170 CNAME[maxCNAMElen] = '\0';
00171 sessionState.rtcpInstance
00172 = RTCPInstance::createNew(*env, sessionState.rtcpGroupsock,
00173 estimatedSessionBandwidth, CNAME,
00174 sessionState.sink, NULL ,
00175 True );
00176
00177
00178
00179 sessionState.rtspServer = RTSPServer::createNew(*env, 8554);
00180 if (sessionState.rtspServer == NULL) {
00181 *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
00182 exit(1);
00183 }
00184 ServerMediaSession* sms
00185 = ServerMediaSession::createNew(*env, "testStream", inputFileName,
00186 "Session streamed by \"testWAVAudiotreamer\"", True);
00187 sms->addSubsession(PassiveServerMediaSubsession::createNew(*sessionState.sink, sessionState.rtcpInstance));
00188 sessionState.rtspServer->addServerMediaSession(sms);
00189
00190 char* url = sessionState.rtspServer->rtspURL(sms);
00191 *env << "Play this stream using the URL \"" << url << "\"\n";
00192 delete[] url;
00193
00194
00195 *env << "Beginning streaming...\n";
00196 sessionState.sink->startPlaying(*sessionState.source, afterPlaying, NULL);
00197 }
00198
00199
00200 void afterPlaying(void* ) {
00201 *env << "...done streaming\n";
00202
00203
00204 Medium::close(sessionState.rtspServer);
00205 Medium::close(sessionState.rtcpInstance);
00206 Medium::close(sessionState.sink);
00207 delete sessionState.rtpGroupsock;
00208 Medium::close(sessionState.source);
00209 delete sessionState.rtcpGroupsock;
00210
00211
00212 exit(0);
00213 }