00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00022
00023
00024
00025
00026
00027
00029
00030 #include "liveMedia.hh"
00031 #include "BasicUsageEnvironment.hh"
00032
00033 UsageEnvironment* env;
00034 char const* inputFileName = "test.m4e";
00035 char const* remoteStreamName = "test.sdp";
00036 MPEG4VideoStreamFramer* videoSource;
00037 RTPSink* videoSink;
00038
00039 char const* programName;
00040
00041 void usage() {
00042 *env << "usage: " << programName
00043 << " <Darwin Streaming Server name or IP address>\n";
00044 exit(1);
00045 }
00046
00047 Boolean awaitConfigInfo(RTPSink* sink);
00048 void play();
00049
00050 int main(int argc, char** argv) {
00051
00052 TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00053 env = BasicUsageEnvironment::createNew(*scheduler);
00054
00055
00056 programName = argv[0];
00057 if (argc != 2) usage();
00058 char const* dssNameOrAddress = argv[1];
00059
00060
00061 DarwinInjector* injector = DarwinInjector::createNew(*env, programName);
00062
00063
00064
00065
00066 struct in_addr dummyDestAddress;
00067 dummyDestAddress.s_addr = 0;
00068 Groupsock rtpGroupsockVideo(*env, dummyDestAddress, 0, 0);
00069 Groupsock rtcpGroupsockVideo(*env, dummyDestAddress, 0, 0);
00070
00071
00072 videoSink = MPEG4ESVideoRTPSink::createNew(*env, &rtpGroupsockVideo, 96);
00073
00074
00075
00076
00077
00078
00079
00080
00081 *env << "Beginning streaming...\n";
00082 play();
00083
00084 if (!awaitConfigInfo(videoSink)) {
00085 *env << "Failed to get MPEG-4 'config' information from input file: "
00086 << env->getResultMsg() << "\n";
00087 exit(1);
00088 }
00089
00090
00091 const unsigned estimatedSessionBandwidthVideo = 500;
00092 const unsigned maxCNAMElen = 100;
00093 unsigned char CNAME[maxCNAMElen+1];
00094 gethostname((char*)CNAME, maxCNAMElen);
00095 CNAME[maxCNAMElen] = '\0';
00096 RTCPInstance* videoRTCP =
00097 RTCPInstance::createNew(*env, &rtcpGroupsockVideo,
00098 estimatedSessionBandwidthVideo, CNAME,
00099 videoSink, NULL );
00100
00101
00102
00103 injector->addStream(videoSink, videoRTCP);
00104
00105
00106 if (!injector->setDestination(dssNameOrAddress, remoteStreamName,
00107 programName, "LIVE555 Streaming Media")) {
00108 *env << "injector->setDestination() failed: "
00109 << env->getResultMsg() << "\n";
00110 exit(1);
00111 }
00112
00113 *env << "Play this stream (from the Darwin Streaming Server) using the URL:\n"
00114 << "\trtsp://" << dssNameOrAddress << "/" << remoteStreamName << "\n";
00115
00116 env->taskScheduler().doEventLoop();
00117
00118 return 0;
00119 }
00120
00121 void afterPlaying(void* clientData) {
00122 *env << "...done reading from file\n";
00123
00124 Medium::close(videoSource);
00125
00126
00127
00128 play();
00129 }
00130
00131 void play() {
00132
00133 ByteStreamFileSource* fileSource
00134 = ByteStreamFileSource::createNew(*env, inputFileName);
00135 if (fileSource == NULL) {
00136 *env << "Unable to open file \"" << inputFileName
00137 << "\" as a byte-stream file source\n";
00138 exit(1);
00139 }
00140
00141 FramedSource* videoES = fileSource;
00142
00143
00144 FramedSource* videoSource = MPEG4VideoStreamFramer::createNew(*env, videoES);
00145
00146
00147 *env << "Beginning to read from file...\n";
00148 videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
00149 }
00150
00151 static char doneFlag = 0;
00152
00153 static void checkForAuxSDPLine(void* clientData) {
00154 RTPSink* sink = (RTPSink*)clientData;
00155 if (sink->auxSDPLine() != NULL) {
00156
00157 doneFlag = ~0;
00158 } else {
00159
00160 int uSecsToDelay = 100000;
00161 env->taskScheduler().scheduleDelayedTask(uSecsToDelay,
00162 (TaskFunc*)checkForAuxSDPLine, sink);
00163 }
00164 }
00165
00166 Boolean awaitConfigInfo(RTPSink* sink) {
00167
00168 checkForAuxSDPLine(sink);
00169
00170 env->taskScheduler().doEventLoop(&doneFlag);
00171
00172 char const* auxSDPLine = sink->auxSDPLine();
00173 return auxSDPLine != NULL;
00174 }