00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "RTPSink.hh"
00022 #include "GroupsockHelper.hh"
00023
00025
00026 Boolean RTPSink::lookupByName(UsageEnvironment& env, char const* sinkName,
00027 RTPSink*& resultSink) {
00028 resultSink = NULL;
00029
00030 MediaSink* sink;
00031 if (!MediaSink::lookupByName(env, sinkName, sink)) return False;
00032
00033 if (!sink->isRTPSink()) {
00034 env.setResultMsg(sinkName, " is not a RTP sink");
00035 return False;
00036 }
00037
00038 resultSink = (RTPSink*)sink;
00039 return True;
00040 }
00041
00042 Boolean RTPSink::isRTPSink() const {
00043 return True;
00044 }
00045
00046 RTPSink::RTPSink(UsageEnvironment& env,
00047 Groupsock* rtpGS, unsigned char rtpPayloadType,
00048 unsigned rtpTimestampFrequency,
00049 char const* rtpPayloadFormatName,
00050 unsigned numChannels)
00051 : MediaSink(env), fRTPInterface(this, rtpGS),
00052 fRTPPayloadType(rtpPayloadType),
00053 fPacketCount(0), fOctetCount(0), fTotalOctetCount(0),
00054 fTimestampFrequency(rtpTimestampFrequency), fNextTimestampHasBeenPreset(True),
00055 fNumChannels(numChannels) {
00056 fRTPPayloadFormatName
00057 = strDup(rtpPayloadFormatName == NULL ? "???" : rtpPayloadFormatName);
00058 gettimeofday(&fCreationTime, NULL);
00059 fTotalOctetCountStartTime = fCreationTime;
00060
00061 fSeqNo = (u_int16_t)our_random();
00062 fSSRC = our_random32();
00063 fTimestampBase = our_random32();
00064
00065 fTransmissionStatsDB = new RTPTransmissionStatsDB(*this);
00066 }
00067
00068 RTPSink::~RTPSink() {
00069 delete fTransmissionStatsDB;
00070 delete[] (char*)fRTPPayloadFormatName;
00071 }
00072
00073 u_int32_t RTPSink::convertToRTPTimestamp(struct timeval tv) {
00074
00075 u_int32_t timestampIncrement = (fTimestampFrequency*tv.tv_sec);
00076 timestampIncrement += (u_int32_t)((2.0*fTimestampFrequency*tv.tv_usec + 1000000.0)/2000000);
00077
00078
00079
00080 if (fNextTimestampHasBeenPreset) {
00081
00082
00083 fTimestampBase -= timestampIncrement;
00084 fNextTimestampHasBeenPreset = False;
00085 }
00086
00087 u_int32_t const rtpTimestamp = fTimestampBase + timestampIncrement;
00088 #ifdef DEBUG_TIMESTAMPS
00089 fprintf(stderr, "fTimestampBase: 0x%08x, tv: %lu.%06ld\n\t=> RTP timestamp: 0x%08x\n",
00090 fTimestampBase, tv.tv_sec, tv.tv_usec, rtpTimestamp);
00091 fflush(stderr);
00092 #endif
00093
00094 return rtpTimestamp;
00095 }
00096
00097 u_int32_t RTPSink::presetNextTimestamp() {
00098 struct timeval timeNow;
00099 gettimeofday(&timeNow, NULL);
00100
00101 u_int32_t tsNow = convertToRTPTimestamp(timeNow);
00102 fTimestampBase = tsNow;
00103 fNextTimestampHasBeenPreset = True;
00104
00105 return tsNow;
00106 }
00107
00108 void RTPSink::getTotalBitrate(unsigned& outNumBytes, double& outElapsedTime) {
00109 struct timeval timeNow;
00110 gettimeofday(&timeNow, NULL);
00111
00112 outNumBytes = fTotalOctetCount;
00113 outElapsedTime = (double)(timeNow.tv_sec-fTotalOctetCountStartTime.tv_sec)
00114 + (timeNow.tv_usec-fTotalOctetCountStartTime.tv_usec)/1000000.0;
00115
00116 fTotalOctetCount = 0;
00117 fTotalOctetCountStartTime = timeNow;
00118 }
00119
00120 char const* RTPSink::sdpMediaType() const {
00121 return "data";
00122
00123 }
00124
00125 char* RTPSink::rtpmapLine() const {
00126 if (rtpPayloadType() >= 96) {
00127 char* encodingParamsPart;
00128 if (numChannels() != 1) {
00129 encodingParamsPart = new char[1 + 20 ];
00130 sprintf(encodingParamsPart, "/%d", numChannels());
00131 } else {
00132 encodingParamsPart = strDup("");
00133 }
00134 char const* const rtpmapFmt = "a=rtpmap:%d %s/%d%s\r\n";
00135 unsigned rtpmapFmtSize = strlen(rtpmapFmt)
00136 + 3 + strlen(rtpPayloadFormatName())
00137 + 20 + strlen(encodingParamsPart);
00138 char* rtpmapLine = new char[rtpmapFmtSize];
00139 sprintf(rtpmapLine, rtpmapFmt,
00140 rtpPayloadType(), rtpPayloadFormatName(),
00141 rtpTimestampFrequency(), encodingParamsPart);
00142 delete[] encodingParamsPart;
00143
00144 return rtpmapLine;
00145 } else {
00146
00147 return strDup("");
00148 }
00149 }
00150
00151 char const* RTPSink::auxSDPLine() {
00152 return NULL;
00153 }
00154
00155
00157
00158 RTPTransmissionStatsDB::RTPTransmissionStatsDB(RTPSink& rtpSink)
00159 : fOurRTPSink(rtpSink),
00160 fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
00161 fNumReceivers=0;
00162 }
00163
00164 RTPTransmissionStatsDB::~RTPTransmissionStatsDB() {
00165
00166 RTPTransmissionStats* stats;
00167 while ((stats = (RTPTransmissionStats*)fTable->RemoveNext()) != NULL) {
00168 delete stats;
00169 }
00170
00171
00172 delete fTable;
00173 }
00174
00175 void RTPTransmissionStatsDB
00176 ::noteIncomingRR(u_int32_t SSRC, struct sockaddr_in const& lastFromAddress,
00177 unsigned lossStats, unsigned lastPacketNumReceived,
00178 unsigned jitter, unsigned lastSRTime, unsigned diffSR_RRTime) {
00179 RTPTransmissionStats* stats = lookup(SSRC);
00180 if (stats == NULL) {
00181
00182
00183 stats = new RTPTransmissionStats(fOurRTPSink, SSRC);
00184 if (stats == NULL) return;
00185 add(SSRC, stats);
00186 #ifdef DEBUG_RR
00187 fprintf(stderr, "Adding new entry for SSRC %x in RTPTransmissionStatsDB\n", SSRC);
00188 #endif
00189 }
00190
00191 stats->noteIncomingRR(lastFromAddress,
00192 lossStats, lastPacketNumReceived, jitter,
00193 lastSRTime, diffSR_RRTime);
00194 }
00195
00196 void RTPTransmissionStatsDB::removeRecord(u_int32_t SSRC) {
00197 RTPTransmissionStats* stats = lookup(SSRC);
00198 if (stats != NULL) {
00199 long SSRC_long = (long)SSRC;
00200 fTable->Remove((char const*)SSRC_long);
00201 --fNumReceivers;
00202 delete stats;
00203 }
00204 }
00205
00206 RTPTransmissionStatsDB::Iterator
00207 ::Iterator(RTPTransmissionStatsDB& receptionStatsDB)
00208 : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
00209 }
00210
00211 RTPTransmissionStatsDB::Iterator::~Iterator() {
00212 delete fIter;
00213 }
00214
00215 RTPTransmissionStats*
00216 RTPTransmissionStatsDB::Iterator::next() {
00217 char const* key;
00218
00219 return (RTPTransmissionStats*)(fIter->next(key));
00220 }
00221
00222 RTPTransmissionStats* RTPTransmissionStatsDB::lookup(u_int32_t SSRC) const {
00223 long SSRC_long = (long)SSRC;
00224 return (RTPTransmissionStats*)(fTable->Lookup((char const*)SSRC_long));
00225 }
00226
00227 void RTPTransmissionStatsDB::add(u_int32_t SSRC, RTPTransmissionStats* stats) {
00228 long SSRC_long = (long)SSRC;
00229 fTable->Add((char const*)SSRC_long, stats);
00230 ++fNumReceivers;
00231 }
00232
00233
00235
00236 RTPTransmissionStats::RTPTransmissionStats(RTPSink& rtpSink, u_int32_t SSRC)
00237 : fOurRTPSink(rtpSink), fSSRC(SSRC), fLastPacketNumReceived(0),
00238 fPacketLossRatio(0), fTotNumPacketsLost(0), fJitter(0),
00239 fLastSRTime(0), fDiffSR_RRTime(0), fFirstPacket(True),
00240 fTotalOctetCount_hi(0), fTotalOctetCount_lo(0),
00241 fTotalPacketCount_hi(0), fTotalPacketCount_lo(0) {
00242 gettimeofday(&fTimeCreated, NULL);
00243
00244 fLastOctetCount = rtpSink.octetCount();
00245 fLastPacketCount = rtpSink.packetCount();
00246 }
00247
00248 RTPTransmissionStats::~RTPTransmissionStats() {}
00249
00250 void RTPTransmissionStats
00251 ::noteIncomingRR(struct sockaddr_in const& lastFromAddress,
00252 unsigned lossStats, unsigned lastPacketNumReceived,
00253 unsigned jitter, unsigned lastSRTime,
00254 unsigned diffSR_RRTime) {
00255 if (fFirstPacket) {
00256 fFirstPacket = False;
00257 fFirstPacketNumReported = lastPacketNumReceived;
00258 } else {
00259 fOldValid = True;
00260 fOldLastPacketNumReceived = fLastPacketNumReceived;
00261 fOldTotNumPacketsLost = fTotNumPacketsLost;
00262 }
00263 gettimeofday(&fTimeReceived, NULL);
00264
00265 fLastFromAddress = lastFromAddress;
00266 fPacketLossRatio = lossStats>>24;
00267 fTotNumPacketsLost = lossStats&0xFFFFFF;
00268 fLastPacketNumReceived = lastPacketNumReceived;
00269 fJitter = jitter;
00270 fLastSRTime = lastSRTime;
00271 fDiffSR_RRTime = diffSR_RRTime;
00272 #ifdef DEBUG_RR
00273 fprintf(stderr, "RTCP RR data (received at %lu.%06ld): lossStats 0x%08x, lastPacketNumReceived 0x%08x, jitter 0x%08x, lastSRTime 0x%08x, diffSR_RRTime 0x%08x\n",
00274 fTimeReceived.tv_sec, fTimeReceived.tv_usec, lossStats, lastPacketNumReceived, jitter, lastSRTime, diffSR_RRTime);
00275 unsigned rtd = roundTripDelay();
00276 fprintf(stderr, "=> round-trip delay: 0x%04x (== %f seconds)\n", rtd, rtd/65536.0);
00277 #endif
00278
00279
00280
00281 u_int32_t newOctetCount = fOurRTPSink.octetCount();
00282 u_int32_t octetCountDiff = newOctetCount - fLastOctetCount;
00283 fLastOctetCount = newOctetCount;
00284 u_int32_t prevTotalOctetCount_lo = fTotalOctetCount_lo;
00285 fTotalOctetCount_lo += octetCountDiff;
00286 if (fTotalOctetCount_lo < prevTotalOctetCount_lo) {
00287 ++fTotalOctetCount_hi;
00288 }
00289
00290 u_int32_t newPacketCount = fOurRTPSink.packetCount();
00291 u_int32_t packetCountDiff = newPacketCount - fLastPacketCount;
00292 fLastPacketCount = newPacketCount;
00293 u_int32_t prevTotalPacketCount_lo = fTotalPacketCount_lo;
00294 fTotalPacketCount_lo += packetCountDiff;
00295 if (fTotalPacketCount_lo < prevTotalPacketCount_lo) {
00296 ++fTotalPacketCount_hi;
00297 }
00298 }
00299
00300 unsigned RTPTransmissionStats::roundTripDelay() const {
00301
00302
00303
00304 if (fLastSRTime == 0) {
00305
00306
00307 return 0;
00308 }
00309
00310
00311
00312 unsigned lastReceivedTimeNTP_high
00313 = fTimeReceived.tv_sec + 0x83AA7E80;
00314 double fractionalPart = (fTimeReceived.tv_usec*0x0400)/15625.0;
00315 unsigned lastReceivedTimeNTP
00316 = (unsigned)((lastReceivedTimeNTP_high<<16) + fractionalPart + 0.5);
00317
00318 int rawResult = lastReceivedTimeNTP - fLastSRTime - fDiffSR_RRTime;
00319 if (rawResult < 0) {
00320
00321
00322 rawResult = 0;
00323 }
00324 return (unsigned)rawResult;
00325 }
00326
00327 void RTPTransmissionStats::getTotalOctetCount(u_int32_t& hi, u_int32_t& lo) {
00328 hi = fTotalOctetCount_hi;
00329 lo = fTotalOctetCount_lo;
00330 }
00331
00332 void RTPTransmissionStats::getTotalPacketCount(u_int32_t& hi, u_int32_t& lo) {
00333 hi = fTotalPacketCount_hi;
00334 lo = fTotalPacketCount_lo;
00335 }
00336
00337 unsigned RTPTransmissionStats::packetsReceivedSinceLastRR() const {
00338 if (!fOldValid) return 0;
00339
00340 return fLastPacketNumReceived-fOldLastPacketNumReceived;
00341 }
00342
00343 int RTPTransmissionStats::packetsLostBetweenRR() const {
00344 if (!fOldValid) return 0;
00345
00346 return fTotNumPacketsLost - fOldTotNumPacketsLost;
00347 }