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 ipAddress;
00187 ipAddress.s_addr = ourIPAddress(envir());
00188 char* const ipAddressStr = strDup(our_inet_ntoa(ipAddress));
00189 unsigned ipAddressStrSize = strlen(ipAddressStr);
00190
00191
00192 char* sourceFilterLine;
00193 if (fIsSSM) {
00194 char const* const sourceFilterFmt =
00195 "a=source-filter: incl IN IP4 * %s\r\n"
00196 "a=rtcp-unicast: reflection\r\n";
00197 unsigned const sourceFilterFmtSize = strlen(sourceFilterFmt) + ipAddressStrSize + 1;
00198
00199 sourceFilterLine = new char[sourceFilterFmtSize];
00200 sprintf(sourceFilterLine, sourceFilterFmt, ipAddressStr);
00201 } else {
00202 sourceFilterLine = strDup("");
00203 }
00204
00205 char* rangeLine = NULL;
00206 char* sdp = NULL;
00207
00208 do {
00209
00210
00211
00212 unsigned sdpLength = 0;
00213 ServerMediaSubsession* subsession;
00214 for (subsession = fSubsessionsHead; subsession != NULL;
00215 subsession = subsession->fNext) {
00216 char const* sdpLines = subsession->sdpLines();
00217 if (sdpLines == NULL) break;
00218 sdpLength += strlen(sdpLines);
00219 }
00220 if (subsession != NULL) break;
00221
00222
00223 float dur = duration();
00224 if (dur == 0.0) {
00225 rangeLine = strDup("a=range:npt=0-\r\n");
00226 } else if (dur > 0.0) {
00227 char buf[100];
00228 sprintf(buf, "a=range:npt=0-%.3f\r\n", dur);
00229 rangeLine = strDup(buf);
00230 } else {
00231 rangeLine = strDup("");
00232 }
00233
00234 char const* const sdpPrefixFmt =
00235 "v=0\r\n"
00236 "o=- %ld%06ld %d IN IP4 %s\r\n"
00237 "s=%s\r\n"
00238 "i=%s\r\n"
00239 "t=0 0\r\n"
00240 "a=tool:%s%s\r\n"
00241 "a=type:broadcast\r\n"
00242 "a=control:*\r\n"
00243 "%s"
00244 "%s"
00245 "a=x-qt-text-nam:%s\r\n"
00246 "a=x-qt-text-inf:%s\r\n"
00247 "%s";
00248 sdpLength += strlen(sdpPrefixFmt)
00249 + 20 + 6 + 20 + ipAddressStrSize
00250 + strlen(fDescriptionSDPString)
00251 + strlen(fInfoSDPString)
00252 + strlen(libNameStr) + strlen(libVersionStr)
00253 + strlen(sourceFilterLine)
00254 + strlen(rangeLine)
00255 + strlen(fDescriptionSDPString)
00256 + strlen(fInfoSDPString)
00257 + strlen(fMiscSDPLines);
00258 sdp = new char[sdpLength];
00259 if (sdp == NULL) break;
00260
00261
00262 sprintf(sdp, sdpPrefixFmt,
00263 fCreationTime.tv_sec, fCreationTime.tv_usec,
00264 1,
00265 ipAddressStr,
00266 fDescriptionSDPString,
00267 fInfoSDPString,
00268 libNameStr, libVersionStr,
00269 sourceFilterLine,
00270 rangeLine,
00271 fDescriptionSDPString,
00272 fInfoSDPString,
00273 fMiscSDPLines);
00274
00275
00276 char* mediaSDP = sdp;
00277 for (subsession = fSubsessionsHead; subsession != NULL;
00278 subsession = subsession->fNext) {
00279 mediaSDP += strlen(mediaSDP);
00280 sprintf(mediaSDP, "%s", subsession->sdpLines());
00281 }
00282 } while (0);
00283
00284 delete[] rangeLine; delete[] sourceFilterLine; delete[] ipAddressStr;
00285 return sdp;
00286 }
00287
00288
00290
00291 ServerMediaSubsessionIterator
00292 ::ServerMediaSubsessionIterator(ServerMediaSession& session)
00293 : fOurSession(session) {
00294 reset();
00295 }
00296
00297 ServerMediaSubsessionIterator::~ServerMediaSubsessionIterator() {
00298 }
00299
00300 ServerMediaSubsession* ServerMediaSubsessionIterator::next() {
00301 ServerMediaSubsession* result = fNextPtr;
00302
00303 if (fNextPtr != NULL) fNextPtr = fNextPtr->fNext;
00304
00305 return result;
00306 }
00307
00308 void ServerMediaSubsessionIterator::reset() {
00309 fNextPtr = fOurSession.fSubsessionsHead;
00310 }
00311
00312
00314
00315 ServerMediaSubsession::ServerMediaSubsession(UsageEnvironment& env)
00316 : Medium(env),
00317 fParentSession(NULL), fServerAddressForSDP(0), fPortNumForSDP(0),
00318 fNext(NULL), fTrackNumber(0), fTrackId(NULL) {
00319 }
00320
00321 ServerMediaSubsession::~ServerMediaSubsession() {
00322 delete[] (char*)fTrackId;
00323 Medium::close(fNext);
00324 }
00325
00326 char const* ServerMediaSubsession::trackId() {
00327 if (fTrackNumber == 0) return NULL;
00328
00329 if (fTrackId == NULL) {
00330 char buf[100];
00331 sprintf(buf, "track%d", fTrackNumber);
00332 fTrackId = strDup(buf);
00333 }
00334 return fTrackId;
00335 }
00336
00337 void ServerMediaSubsession::pauseStream(unsigned ,
00338 void* ) {
00339
00340 }
00341 void ServerMediaSubsession::seekStream(unsigned ,
00342 void* , float ) {
00343
00344 }
00345 void ServerMediaSubsession::setStreamScale(unsigned ,
00346 void* , float ) {
00347
00348 }
00349 void ServerMediaSubsession::deleteStream(unsigned ,
00350 void*& ) {
00351
00352 }
00353
00354 void ServerMediaSubsession::testScaleFactor(float& scale) {
00355
00356 scale = 1;
00357 }
00358
00359 float ServerMediaSubsession::duration() const {
00360
00361 return 0.0;
00362 }
00363
00364 void ServerMediaSubsession::setServerAddressAndPortForSDP(netAddressBits addressBits,
00365 portNumBits portBits) {
00366 fServerAddressForSDP = addressBits;
00367 fPortNumForSDP = portBits;
00368 }
00369
00370 char const*
00371 ServerMediaSubsession::rangeSDPLine() const {
00372 if (fParentSession == NULL) return NULL;
00373
00374
00375
00376 if (fParentSession->duration() >= 0.0) return strDup("");
00377
00378
00379 float ourDuration = duration();
00380 if (ourDuration == 0.0) {
00381 return strDup("a=range:npt=0-\r\n");
00382 } else {
00383 char buf[100];
00384 sprintf(buf, "a=range:npt=0-%.3f\r\n", ourDuration);
00385 return strDup(buf);
00386 }
00387 }