00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "ServerMediaSession.hh"
00025 #include <GroupsockHelper.hh>
00026 #include <math.h>
00027
00029
00030 ServerMediaSession* ServerMediaSession
00031 ::createNew(UsageEnvironment& env,
00032 char const* streamName, char const* info,
00033 char const* description, Boolean isSSM, char const* miscSDPLines) {
00034 return new ServerMediaSession(env, streamName, info, description,
00035 isSSM, miscSDPLines);
00036 }
00037
00038 Boolean ServerMediaSession
00039 ::lookupByName(UsageEnvironment& env, char const* mediumName,
00040 ServerMediaSession*& resultSession) {
00041 resultSession = NULL;
00042
00043 Medium* medium;
00044 if (!Medium::lookupByName(env, mediumName, medium)) return False;
00045
00046 if (!medium->isServerMediaSession()) {
00047 env.setResultMsg(mediumName, " is not a 'ServerMediaSession' object");
00048 return False;
00049 }
00050
00051 resultSession = (ServerMediaSession*)medium;
00052 return True;
00053 }
00054
00055 static char const* const libNameStr = "LIVE555 Streaming Media v";
00056 char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING;
00057
00058 ServerMediaSession::ServerMediaSession(UsageEnvironment& env,
00059 char const* streamName,
00060 char const* info,
00061 char const* description,
00062 Boolean isSSM, char const* miscSDPLines)
00063 : Medium(env), fIsSSM(isSSM), fSubsessionsHead(NULL),
00064 fSubsessionsTail(NULL), fSubsessionCounter(0),
00065 fReferenceCount(0), fDeleteWhenUnreferenced(False) {
00066 fStreamName = strDup(streamName == NULL ? "" : streamName);
00067 fInfoSDPString = strDup(info == NULL ? libNameStr : info);
00068 fDescriptionSDPString
00069 = strDup(description == NULL ? libNameStr : description);
00070 fMiscSDPLines = strDup(miscSDPLines == NULL ? "" : miscSDPLines);
00071
00072 gettimeofday(&fCreationTime, NULL);
00073 }
00074
00075 ServerMediaSession::~ServerMediaSession() {
00076 Medium::close(fSubsessionsHead);
00077 delete[] fStreamName;
00078 delete[] fInfoSDPString;
00079 delete[] fDescriptionSDPString;
00080 delete[] fMiscSDPLines;
00081 }
00082
00083 Boolean
00084 ServerMediaSession::addSubsession(ServerMediaSubsession* subsession) {
00085 if (subsession->fParentSession != NULL) return False;
00086
00087 if (fSubsessionsTail == NULL) {
00088 fSubsessionsHead = subsession;
00089 } else {
00090 fSubsessionsTail->fNext = subsession;
00091 }
00092 fSubsessionsTail = subsession;
00093
00094 subsession->fParentSession = this;
00095 subsession->fTrackNumber = ++fSubsessionCounter;
00096 return True;
00097 }
00098
00099 void ServerMediaSession::testScaleFactor(float& scale) {
00100
00101
00102
00103
00104 float minSSScale = 1.0;
00105 float maxSSScale = 1.0;
00106 float bestSSScale = 1.0;
00107 float bestDistanceTo1 = 0.0;
00108 ServerMediaSubsession* subsession;
00109 for (subsession = fSubsessionsHead; subsession != NULL;
00110 subsession = subsession->fNext) {
00111 float ssscale = scale;
00112 subsession->testScaleFactor(ssscale);
00113 if (subsession == fSubsessionsHead) {
00114 minSSScale = maxSSScale = bestSSScale = ssscale;
00115 bestDistanceTo1 = (float)fabs(ssscale - 1.0f);
00116 } else {
00117 if (ssscale < minSSScale) {
00118 minSSScale = ssscale;
00119 } else if (ssscale > maxSSScale) {
00120 maxSSScale = ssscale;
00121 }
00122
00123 float distanceTo1 = (float)fabs(ssscale - 1.0f);
00124 if (distanceTo1 < bestDistanceTo1) {
00125 bestSSScale = ssscale;
00126 bestDistanceTo1 = distanceTo1;
00127 }
00128 }
00129 }
00130 if (minSSScale == maxSSScale) {
00131
00132 scale = minSSScale;
00133 return;
00134 }
00135
00136
00137
00138 for (subsession = fSubsessionsHead; subsession != NULL;
00139 subsession = subsession->fNext) {
00140 float ssscale = bestSSScale;
00141 subsession->testScaleFactor(ssscale);
00142 if (ssscale != bestSSScale) break;
00143 }
00144 if (subsession == NULL) {
00145
00146 scale = bestSSScale;
00147 return;
00148 }
00149
00150
00151 for (subsession = fSubsessionsHead; subsession != NULL;
00152 subsession = subsession->fNext) {
00153 float ssscale = 1;
00154 subsession->testScaleFactor(ssscale);
00155 }
00156 scale = 1;
00157 }
00158
00159 float ServerMediaSession::duration() const {
00160 float minSubsessionDuration = 0.0;
00161 float maxSubsessionDuration = 0.0;
00162 for (ServerMediaSubsession* subsession = fSubsessionsHead; subsession != NULL;
00163 subsession = subsession->fNext) {
00164 float ssduration = subsession->duration();
00165 if (subsession == fSubsessionsHead) {
00166 minSubsessionDuration = maxSubsessionDuration = ssduration;
00167 } else if (ssduration < minSubsessionDuration) {
00168 minSubsessionDuration = ssduration;
00169 } else if (ssduration > maxSubsessionDuration) {
00170 maxSubsessionDuration = ssduration;
00171 }
00172 }
00173
00174 if (maxSubsessionDuration != minSubsessionDuration) {
00175 return -maxSubsessionDuration;
00176 } else {
00177 return maxSubsessionDuration;
00178 }
00179 }
00180
00181 Boolean ServerMediaSession::isServerMediaSession() const {
00182 return True;
00183 }
00184
00185 char* ServerMediaSession::generateSDPDescription() {
00186 struct in_addr ourIPAddress;
00187 ourIPAddress.s_addr = ourSourceAddressForMulticast(envir());
00188 char* const ourIPAddressStr
00189 = strDup(our_inet_ntoa(ourIPAddress));
00190 unsigned ourIPAddressStrSize = strlen(ourIPAddressStr);
00191
00192
00193 char* sourceFilterLine;
00194 if (fIsSSM) {
00195 char const* const sourceFilterFmt =
00196 "a=source-filter: incl IN IP4 * %s\r\n"
00197 "a=rtcp-unicast: reflection\r\n";
00198 unsigned sourceFilterFmtSize = strlen(sourceFilterFmt)
00199 + ourIPAddressStrSize;
00200
00201 sourceFilterLine = new char[sourceFilterFmtSize];
00202 sprintf(sourceFilterLine, sourceFilterFmt,
00203 ourIPAddressStr);
00204 } else {
00205 sourceFilterLine = strDup("");
00206 }
00207
00208 char* rangeLine = NULL;
00209 char* sdp = NULL;
00210
00211 do {
00212
00213
00214
00215 unsigned sdpLength = 0;
00216 ServerMediaSubsession* subsession;
00217 for (subsession = fSubsessionsHead; subsession != NULL;
00218 subsession = subsession->fNext) {
00219 char const* sdpLines = subsession->sdpLines();
00220 if (sdpLines == NULL) break;
00221 sdpLength += strlen(sdpLines);
00222 }
00223 if (subsession != NULL) break;
00224
00225
00226 float dur = duration();
00227 if (dur == 0.0) {
00228 rangeLine = strDup("a=range:npt=0-\r\n");
00229 } else if (dur > 0.0) {
00230 char buf[100];
00231 sprintf(buf, "a=range:npt=0-%.3f\r\n", dur);
00232 rangeLine = strDup(buf);
00233 } else {
00234 rangeLine = strDup("");
00235 }
00236
00237 char const* const sdpPrefixFmt =
00238 "v=0\r\n"
00239 "o=- %ld%06ld %d IN IP4 %s\r\n"
00240 "s=%s\r\n"
00241 "i=%s\r\n"
00242 "t=0 0\r\n"
00243 "a=tool:%s%s\r\n"
00244 "a=type:broadcast\r\n"
00245 "a=control:*\r\n"
00246 "%s"
00247 "%s"
00248 "a=x-qt-text-nam:%s\r\n"
00249 "a=x-qt-text-inf:%s\r\n"
00250 "%s";
00251 sdpLength += strlen(sdpPrefixFmt)
00252 + 20 + 6 + 20 + ourIPAddressStrSize
00253 + strlen(fDescriptionSDPString)
00254 + strlen(fInfoSDPString)
00255 + strlen(libNameStr) + strlen(libVersionStr)
00256 + strlen(sourceFilterLine)
00257 + strlen(rangeLine)
00258 + strlen(fDescriptionSDPString)
00259 + strlen(fInfoSDPString)
00260 + strlen(fMiscSDPLines);
00261 sdp = new char[sdpLength];
00262 if (sdp == NULL) break;
00263
00264
00265 sprintf(sdp, sdpPrefixFmt,
00266 fCreationTime.tv_sec, fCreationTime.tv_usec,
00267 1,
00268 ourIPAddressStr,
00269 fDescriptionSDPString,
00270 fInfoSDPString,
00271 libNameStr, libVersionStr,
00272 sourceFilterLine,
00273 rangeLine,
00274 fDescriptionSDPString,
00275 fInfoSDPString,
00276 fMiscSDPLines);
00277
00278
00279 char* mediaSDP = sdp;
00280 for (subsession = fSubsessionsHead; subsession != NULL;
00281 subsession = subsession->fNext) {
00282 mediaSDP += strlen(mediaSDP);
00283 sprintf(mediaSDP, "%s", subsession->sdpLines());
00284 }
00285 } while (0);
00286
00287 delete[] rangeLine; delete[] sourceFilterLine; delete[] ourIPAddressStr;
00288 return sdp;
00289 }
00290
00291
00293
00294 ServerMediaSubsessionIterator
00295 ::ServerMediaSubsessionIterator(ServerMediaSession& session)
00296 : fOurSession(session) {
00297 reset();
00298 }
00299
00300 ServerMediaSubsessionIterator::~ServerMediaSubsessionIterator() {
00301 }
00302
00303 ServerMediaSubsession* ServerMediaSubsessionIterator::next() {
00304 ServerMediaSubsession* result = fNextPtr;
00305
00306 if (fNextPtr != NULL) fNextPtr = fNextPtr->fNext;
00307
00308 return result;
00309 }
00310
00311 void ServerMediaSubsessionIterator::reset() {
00312 fNextPtr = fOurSession.fSubsessionsHead;
00313 }
00314
00315
00317
00318 ServerMediaSubsession::ServerMediaSubsession(UsageEnvironment& env)
00319 : Medium(env),
00320 fParentSession(NULL), fServerAddressForSDP(0), fPortNumForSDP(0),
00321 fNext(NULL), fTrackNumber(0), fTrackId(NULL) {
00322 }
00323
00324 ServerMediaSubsession::~ServerMediaSubsession() {
00325 delete[] (char*)fTrackId;
00326 Medium::close(fNext);
00327 }
00328
00329 char const* ServerMediaSubsession::trackId() {
00330 if (fTrackNumber == 0) return NULL;
00331
00332 if (fTrackId == NULL) {
00333 char buf[100];
00334 sprintf(buf, "track%d", fTrackNumber);
00335 fTrackId = strDup(buf);
00336 }
00337 return fTrackId;
00338 }
00339
00340 void ServerMediaSubsession::pauseStream(unsigned ,
00341 void* ) {
00342
00343 }
00344 void ServerMediaSubsession::seekStream(unsigned ,
00345 void* , float ) {
00346
00347 }
00348 void ServerMediaSubsession::setStreamScale(unsigned ,
00349 void* , float ) {
00350
00351 }
00352 void ServerMediaSubsession::deleteStream(unsigned ,
00353 void*& ) {
00354
00355 }
00356
00357 void ServerMediaSubsession::testScaleFactor(float& scale) {
00358
00359 scale = 1;
00360 }
00361
00362 float ServerMediaSubsession::duration() const {
00363
00364 return 0.0;
00365 }
00366
00367 void ServerMediaSubsession::setServerAddressAndPortForSDP(netAddressBits addressBits,
00368 portNumBits portBits) {
00369 fServerAddressForSDP = addressBits;
00370 fPortNumForSDP = portBits;
00371 }
00372
00373 char const*
00374 ServerMediaSubsession::rangeSDPLine() const {
00375 if (fParentSession == NULL) return NULL;
00376
00377
00378
00379 if (fParentSession->duration() >= 0.0) return strDup("");
00380
00381
00382 float ourDuration = duration();
00383 if (ourDuration == 0.0) {
00384 return strDup("a=range:npt=0-\r\n");
00385 } else {
00386 char buf[100];
00387 sprintf(buf, "a=range:npt=0-%.3f\r\n", ourDuration);
00388 return strDup(buf);
00389 }
00390 }