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