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
00068 char* libNamePlusVersionStr = NULL;
00069 if (info == NULL || description == NULL) {
00070 libNamePlusVersionStr = new char[strlen(libNameStr) + strlen(libVersionStr) + 1];
00071 sprintf(libNamePlusVersionStr, "%s%s", libNameStr, libVersionStr);
00072 }
00073 fInfoSDPString = strDup(info == NULL ? libNamePlusVersionStr : info);
00074 fDescriptionSDPString = strDup(description == NULL ? libNamePlusVersionStr : description);
00075 delete[] libNamePlusVersionStr;
00076
00077 fMiscSDPLines = strDup(miscSDPLines == NULL ? "" : miscSDPLines);
00078
00079 gettimeofday(&fCreationTime, NULL);
00080 }
00081
00082 ServerMediaSession::~ServerMediaSession() {
00083 Medium::close(fSubsessionsHead);
00084 delete[] fStreamName;
00085 delete[] fInfoSDPString;
00086 delete[] fDescriptionSDPString;
00087 delete[] fMiscSDPLines;
00088 }
00089
00090 Boolean
00091 ServerMediaSession::addSubsession(ServerMediaSubsession* subsession) {
00092 if (subsession->fParentSession != NULL) return False;
00093
00094 if (fSubsessionsTail == NULL) {
00095 fSubsessionsHead = subsession;
00096 } else {
00097 fSubsessionsTail->fNext = subsession;
00098 }
00099 fSubsessionsTail = subsession;
00100
00101 subsession->fParentSession = this;
00102 subsession->fTrackNumber = ++fSubsessionCounter;
00103 return True;
00104 }
00105
00106 void ServerMediaSession::testScaleFactor(float& scale) {
00107
00108
00109
00110
00111 float minSSScale = 1.0;
00112 float maxSSScale = 1.0;
00113 float bestSSScale = 1.0;
00114 float bestDistanceTo1 = 0.0;
00115 ServerMediaSubsession* subsession;
00116 for (subsession = fSubsessionsHead; subsession != NULL;
00117 subsession = subsession->fNext) {
00118 float ssscale = scale;
00119 subsession->testScaleFactor(ssscale);
00120 if (subsession == fSubsessionsHead) {
00121 minSSScale = maxSSScale = bestSSScale = ssscale;
00122 bestDistanceTo1 = (float)fabs(ssscale - 1.0f);
00123 } else {
00124 if (ssscale < minSSScale) {
00125 minSSScale = ssscale;
00126 } else if (ssscale > maxSSScale) {
00127 maxSSScale = ssscale;
00128 }
00129
00130 float distanceTo1 = (float)fabs(ssscale - 1.0f);
00131 if (distanceTo1 < bestDistanceTo1) {
00132 bestSSScale = ssscale;
00133 bestDistanceTo1 = distanceTo1;
00134 }
00135 }
00136 }
00137 if (minSSScale == maxSSScale) {
00138
00139 scale = minSSScale;
00140 return;
00141 }
00142
00143
00144
00145 for (subsession = fSubsessionsHead; subsession != NULL;
00146 subsession = subsession->fNext) {
00147 float ssscale = bestSSScale;
00148 subsession->testScaleFactor(ssscale);
00149 if (ssscale != bestSSScale) break;
00150 }
00151 if (subsession == NULL) {
00152
00153 scale = bestSSScale;
00154 return;
00155 }
00156
00157
00158 for (subsession = fSubsessionsHead; subsession != NULL;
00159 subsession = subsession->fNext) {
00160 float ssscale = 1;
00161 subsession->testScaleFactor(ssscale);
00162 }
00163 scale = 1;
00164 }
00165
00166 float ServerMediaSession::duration() const {
00167 float minSubsessionDuration = 0.0;
00168 float maxSubsessionDuration = 0.0;
00169 for (ServerMediaSubsession* subsession = fSubsessionsHead; subsession != NULL;
00170 subsession = subsession->fNext) {
00171 float ssduration = subsession->duration();
00172 if (subsession == fSubsessionsHead) {
00173 minSubsessionDuration = maxSubsessionDuration = ssduration;
00174 } else if (ssduration < minSubsessionDuration) {
00175 minSubsessionDuration = ssduration;
00176 } else if (ssduration > maxSubsessionDuration) {
00177 maxSubsessionDuration = ssduration;
00178 }
00179 }
00180
00181 if (maxSubsessionDuration != minSubsessionDuration) {
00182 return -maxSubsessionDuration;
00183 } else {
00184 return maxSubsessionDuration;
00185 }
00186 }
00187
00188 Boolean ServerMediaSession::isServerMediaSession() const {
00189 return True;
00190 }
00191
00192 char* ServerMediaSession::generateSDPDescription() {
00193 AddressString ipAddressStr(ourIPAddress(envir()));
00194 unsigned ipAddressStrSize = strlen(ipAddressStr.val());
00195
00196
00197 char* sourceFilterLine;
00198 if (fIsSSM) {
00199 char const* const sourceFilterFmt =
00200 "a=source-filter: incl IN IP4 * %s\r\n"
00201 "a=rtcp-unicast: reflection\r\n";
00202 unsigned const sourceFilterFmtSize = strlen(sourceFilterFmt) + ipAddressStrSize + 1;
00203
00204 sourceFilterLine = new char[sourceFilterFmtSize];
00205 sprintf(sourceFilterLine, sourceFilterFmt, ipAddressStr.val());
00206 } else {
00207 sourceFilterLine = strDup("");
00208 }
00209
00210 char* rangeLine = NULL;
00211 char* sdp = NULL;
00212
00213 do {
00214
00215
00216
00217 unsigned sdpLength = 0;
00218 ServerMediaSubsession* subsession;
00219 for (subsession = fSubsessionsHead; subsession != NULL;
00220 subsession = subsession->fNext) {
00221 char const* sdpLines = subsession->sdpLines();
00222 if (sdpLines == NULL) break;
00223 sdpLength += strlen(sdpLines);
00224 }
00225 if (subsession != NULL) break;
00226
00227
00228 float dur = duration();
00229 if (dur == 0.0) {
00230 rangeLine = strDup("a=range:npt=0-\r\n");
00231 } else if (dur > 0.0) {
00232 char buf[100];
00233 sprintf(buf, "a=range:npt=0-%.3f\r\n", dur);
00234 rangeLine = strDup(buf);
00235 } else {
00236 rangeLine = strDup("");
00237 }
00238
00239 char const* const sdpPrefixFmt =
00240 "v=0\r\n"
00241 "o=- %ld%06ld %d IN IP4 %s\r\n"
00242 "s=%s\r\n"
00243 "i=%s\r\n"
00244 "t=0 0\r\n"
00245 "a=tool:%s%s\r\n"
00246 "a=type:broadcast\r\n"
00247 "a=control:*\r\n"
00248 "%s"
00249 "%s"
00250 "a=x-qt-text-nam:%s\r\n"
00251 "a=x-qt-text-inf:%s\r\n"
00252 "%s";
00253 sdpLength += strlen(sdpPrefixFmt)
00254 + 20 + 6 + 20 + ipAddressStrSize
00255 + strlen(fDescriptionSDPString)
00256 + strlen(fInfoSDPString)
00257 + strlen(libNameStr) + strlen(libVersionStr)
00258 + strlen(sourceFilterLine)
00259 + strlen(rangeLine)
00260 + strlen(fDescriptionSDPString)
00261 + strlen(fInfoSDPString)
00262 + strlen(fMiscSDPLines);
00263 sdp = new char[sdpLength];
00264 if (sdp == NULL) break;
00265
00266
00267 sprintf(sdp, sdpPrefixFmt,
00268 fCreationTime.tv_sec, fCreationTime.tv_usec,
00269 1,
00270 ipAddressStr.val(),
00271 fDescriptionSDPString,
00272 fInfoSDPString,
00273 libNameStr, libVersionStr,
00274 sourceFilterLine,
00275 rangeLine,
00276 fDescriptionSDPString,
00277 fInfoSDPString,
00278 fMiscSDPLines);
00279
00280
00281 char* mediaSDP = sdp;
00282 for (subsession = fSubsessionsHead; subsession != NULL;
00283 subsession = subsession->fNext) {
00284 mediaSDP += strlen(mediaSDP);
00285 sprintf(mediaSDP, "%s", subsession->sdpLines());
00286 }
00287 } while (0);
00288
00289 delete[] rangeLine; delete[] sourceFilterLine;
00290 return sdp;
00291 }
00292
00293
00295
00296 ServerMediaSubsessionIterator
00297 ::ServerMediaSubsessionIterator(ServerMediaSession& session)
00298 : fOurSession(session) {
00299 reset();
00300 }
00301
00302 ServerMediaSubsessionIterator::~ServerMediaSubsessionIterator() {
00303 }
00304
00305 ServerMediaSubsession* ServerMediaSubsessionIterator::next() {
00306 ServerMediaSubsession* result = fNextPtr;
00307
00308 if (fNextPtr != NULL) fNextPtr = fNextPtr->fNext;
00309
00310 return result;
00311 }
00312
00313 void ServerMediaSubsessionIterator::reset() {
00314 fNextPtr = fOurSession.fSubsessionsHead;
00315 }
00316
00317
00319
00320 ServerMediaSubsession::ServerMediaSubsession(UsageEnvironment& env)
00321 : Medium(env),
00322 fParentSession(NULL), fServerAddressForSDP(0), fPortNumForSDP(0),
00323 fNext(NULL), fTrackNumber(0), fTrackId(NULL) {
00324 }
00325
00326 ServerMediaSubsession::~ServerMediaSubsession() {
00327 delete[] (char*)fTrackId;
00328 Medium::close(fNext);
00329 }
00330
00331 char const* ServerMediaSubsession::trackId() {
00332 if (fTrackNumber == 0) return NULL;
00333
00334 if (fTrackId == NULL) {
00335 char buf[100];
00336 sprintf(buf, "track%d", fTrackNumber);
00337 fTrackId = strDup(buf);
00338 }
00339 return fTrackId;
00340 }
00341
00342 void ServerMediaSubsession::pauseStream(unsigned ,
00343 void* ) {
00344
00345 }
00346 void ServerMediaSubsession::seekStream(unsigned ,
00347 void* , double& , double , u_int64_t& numBytes) {
00348
00349 numBytes = 0;
00350 }
00351 FramedSource* ServerMediaSubsession::getStreamSource(void* ) {
00352
00353 return NULL;
00354 }
00355 void ServerMediaSubsession::setStreamScale(unsigned ,
00356 void* , float ) {
00357
00358 }
00359 void ServerMediaSubsession::deleteStream(unsigned ,
00360 void*& ) {
00361
00362 }
00363
00364 void ServerMediaSubsession::testScaleFactor(float& scale) {
00365
00366 scale = 1;
00367 }
00368
00369 float ServerMediaSubsession::duration() const {
00370
00371 return 0.0;
00372 }
00373
00374 void ServerMediaSubsession::setServerAddressAndPortForSDP(netAddressBits addressBits,
00375 portNumBits portBits) {
00376 fServerAddressForSDP = addressBits;
00377 fPortNumForSDP = portBits;
00378 }
00379
00380 char const*
00381 ServerMediaSubsession::rangeSDPLine() const {
00382 if (fParentSession == NULL) return NULL;
00383
00384
00385
00386 if (fParentSession->duration() >= 0.0) return strDup("");
00387
00388
00389 float ourDuration = duration();
00390 if (ourDuration == 0.0) {
00391 return strDup("a=range:npt=0-\r\n");
00392 } else {
00393 char buf[100];
00394 sprintf(buf, "a=range:npt=0-%.3f\r\n", ourDuration);
00395 return strDup(buf);
00396 }
00397 }