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), fHaveComputedFirstTimestamp(False),
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 fCurrentTimestamp = fTimestampBase;
00065
00066 fTransmissionStatsDB = new RTPTransmissionStatsDB(*this);
00067 }
00068
00069 RTPSink::~RTPSink() {
00070 delete fTransmissionStatsDB;
00071 delete[] (char*)fRTPPayloadFormatName;
00072 }
00073
00074 u_int32_t RTPSink::convertToRTPTimestamp(struct timeval tv) {
00075 u_int32_t rtpTimestampIncrement = timevalToTimestamp(tv);
00076
00077 if (!fHaveComputedFirstTimestamp) {
00078
00079
00080 fTimestampBase -= rtpTimestampIncrement;
00081 fHaveComputedFirstTimestamp = True;
00082 }
00083
00084 u_int32_t const rtpTimestamp = fTimestampBase + rtpTimestampIncrement;
00085 #ifdef DEBUG_TIMESTAMPS
00086 fprintf(stderr, "fTimestampBase: 0x%08x, tv: %lu.%06ld\n\t=> RTP timestamp: 0x%08x\n",
00087 fTimestampBase, tv.tv_sec, tv.tv_usec, rtpTimestamp);
00088 fflush(stderr);
00089 #endif
00090
00091 return rtpTimestamp;
00092 }
00093
00094 u_int32_t RTPSink::timevalToTimestamp(struct timeval tv) const {
00095 u_int32_t timestamp = (fTimestampFrequency*tv.tv_sec);
00096 timestamp += (u_int32_t)((2.0*fTimestampFrequency*tv.tv_usec + 1000000.0)/2000000);
00097
00098 return timestamp;
00099 }
00100
00101 void RTPSink::getTotalBitrate(unsigned& outNumBytes, double& outElapsedTime) {
00102 struct timeval timeNow;
00103 gettimeofday(&timeNow, NULL);
00104
00105 outNumBytes = fTotalOctetCount;
00106 outElapsedTime = (double)(timeNow.tv_sec-fTotalOctetCountStartTime.tv_sec)
00107 + (timeNow.tv_usec-fTotalOctetCountStartTime.tv_usec)/1000000.0;
00108
00109 fTotalOctetCount = 0;
00110 fTotalOctetCountStartTime = timeNow;
00111 }
00112
00113 char const* RTPSink::sdpMediaType() const {
00114 return "data";
00115
00116 }
00117
00118 char* RTPSink::rtpmapLine() const {
00119 if (rtpPayloadType() >= 96) {
00120 char* encodingParamsPart;
00121 if (numChannels() != 1) {
00122 encodingParamsPart = new char[1 + 20 ];
00123 sprintf(encodingParamsPart, "/%d", numChannels());
00124 } else {
00125 encodingParamsPart = strDup("");
00126 }
00127 char const* const rtpmapFmt = "a=rtpmap:%d %s/%d%s\r\n";
00128 unsigned rtpmapFmtSize = strlen(rtpmapFmt)
00129 + 3 + strlen(rtpPayloadFormatName())
00130 + 20 + strlen(encodingParamsPart);
00131 char* rtpmapLine = new char[rtpmapFmtSize];
00132 sprintf(rtpmapLine, rtpmapFmt,
00133 rtpPayloadType(), rtpPayloadFormatName(),
00134 rtpTimestampFrequency(), encodingParamsPart);
00135 delete[] encodingParamsPart;
00136
00137 return rtpmapLine;
00138 } else {
00139
00140 return strDup("");
00141 }
00142 }
00143
00144 char const* RTPSink::auxSDPLine() {
00145 return NULL;
00146 }
00147
00148
00150
00151 RTPTransmissionStatsDB::RTPTransmissionStatsDB(RTPSink& rtpSink)
00152 : fOurRTPSink(rtpSink),
00153 fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
00154 fNumReceivers=0;
00155 }
00156
00157 RTPTransmissionStatsDB::~RTPTransmissionStatsDB() {
00158
00159 RTPTransmissionStats* stats;
00160 while ((stats = (RTPTransmissionStats*)fTable->RemoveNext()) != NULL) {
00161 delete stats;
00162 }
00163
00164
00165 delete fTable;
00166 }
00167
00168 void RTPTransmissionStatsDB
00169 ::noteIncomingRR(u_int32_t SSRC, struct sockaddr_in const& lastFromAddress,
00170 unsigned lossStats, unsigned lastPacketNumReceived,
00171 unsigned jitter, unsigned lastSRTime, unsigned diffSR_RRTime) {
00172 RTPTransmissionStats* stats = lookup(SSRC);
00173 if (stats == NULL) {
00174
00175
00176 stats = new RTPTransmissionStats(fOurRTPSink, SSRC);
00177 if (stats == NULL) return;
00178 add(SSRC, stats);
00179 #ifdef DEBUG_RR
00180 fprintf(stderr, "Adding new entry for SSRC %x in RTPTransmissionStatsDB\n", SSRC);
00181 #endif
00182 }
00183
00184 stats->noteIncomingRR(lastFromAddress,
00185 lossStats, lastPacketNumReceived, jitter,
00186 lastSRTime, diffSR_RRTime);
00187 }
00188
00189 void RTPTransmissionStatsDB::removeRecord(u_int32_t SSRC) {
00190 RTPTransmissionStats* stats = lookup(SSRC);
00191 if (stats != NULL) {
00192 long SSRC_long = (long)SSRC;
00193 fTable->Remove((char const*)SSRC_long);
00194 --fNumReceivers;
00195 delete stats;
00196 }
00197 }
00198
00199 RTPTransmissionStatsDB::Iterator
00200 ::Iterator(RTPTransmissionStatsDB& receptionStatsDB)
00201 : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
00202 }
00203
00204 RTPTransmissionStatsDB::Iterator::~Iterator() {
00205 delete fIter;
00206 }
00207
00208 RTPTransmissionStats*
00209 RTPTransmissionStatsDB::Iterator::next() {
00210 char const* key;
00211
00212 return (RTPTransmissionStats*)(fIter->next(key));
00213 }
00214
00215 RTPTransmissionStats* RTPTransmissionStatsDB::lookup(u_int32_t SSRC) const {
00216 long SSRC_long = (long)SSRC;
00217 return (RTPTransmissionStats*)(fTable->Lookup((char const*)SSRC_long));
00218 }
00219
00220 void RTPTransmissionStatsDB::add(u_int32_t SSRC, RTPTransmissionStats* stats) {
00221 long SSRC_long = (long)SSRC;
00222 fTable->Add((char const*)SSRC_long, stats);
00223 ++fNumReceivers;
00224 }
00225
00226
00228
00229 RTPTransmissionStats::RTPTransmissionStats(RTPSink& rtpSink, u_int32_t SSRC)
00230 : fOurRTPSink(rtpSink), fSSRC(SSRC), fLastPacketNumReceived(0),
00231 fPacketLossRatio(0), fTotNumPacketsLost(0), fJitter(0),
00232 fLastSRTime(0), fDiffSR_RRTime(0), fFirstPacket(True),
00233 fTotalOctetCount_hi(0), fTotalOctetCount_lo(0),
00234 fTotalPacketCount_hi(0), fTotalPacketCount_lo(0) {
00235 gettimeofday(&fTimeCreated, NULL);
00236
00237 fLastOctetCount = rtpSink.octetCount();
00238 fLastPacketCount = rtpSink.packetCount();
00239 }
00240
00241 RTPTransmissionStats::~RTPTransmissionStats() {}
00242
00243 void RTPTransmissionStats
00244 ::noteIncomingRR(struct sockaddr_in const& lastFromAddress,
00245 unsigned lossStats, unsigned lastPacketNumReceived,
00246 unsigned jitter, unsigned lastSRTime,
00247 unsigned diffSR_RRTime) {
00248 if (fFirstPacket) {
00249 fFirstPacket = False;
00250 fFirstPacketNumReported = lastPacketNumReceived;
00251 } else {
00252 fOldValid = True;
00253 fOldLastPacketNumReceived = fLastPacketNumReceived;
00254 fOldTotNumPacketsLost = fTotNumPacketsLost;
00255 }
00256 gettimeofday(&fTimeReceived, NULL);
00257
00258 fLastFromAddress = lastFromAddress;
00259 fPacketLossRatio = lossStats>>24;
00260 fTotNumPacketsLost = lossStats&0xFFFFFF;
00261 fLastPacketNumReceived = lastPacketNumReceived;
00262 fJitter = jitter;
00263 fLastSRTime = lastSRTime;
00264 fDiffSR_RRTime = diffSR_RRTime;
00265 #ifdef DEBUG_RR
00266 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",
00267 fTimeReceived.tv_sec, fTimeReceived.tv_usec, lossStats, lastPacketNumReceived, jitter, lastSRTime, diffSR_RRTime);
00268 unsigned rtd = roundTripDelay();
00269 fprintf(stderr, "=> round-trip delay: 0x%04x (== %f seconds)\n", rtd, rtd/65536.0);
00270 #endif
00271
00272
00273
00274 u_int32_t newOctetCount = fOurRTPSink.octetCount();
00275 u_int32_t octetCountDiff = newOctetCount - fLastOctetCount;
00276 fLastOctetCount = newOctetCount;
00277 u_int32_t prevTotalOctetCount_lo = fTotalOctetCount_lo;
00278 fTotalOctetCount_lo += octetCountDiff;
00279 if (fTotalOctetCount_lo < prevTotalOctetCount_lo) {
00280 ++fTotalOctetCount_hi;
00281 }
00282
00283 u_int32_t newPacketCount = fOurRTPSink.packetCount();
00284 u_int32_t packetCountDiff = newPacketCount - fLastPacketCount;
00285 fLastPacketCount = newPacketCount;
00286 u_int32_t prevTotalPacketCount_lo = fTotalPacketCount_lo;
00287 fTotalPacketCount_lo += packetCountDiff;
00288 if (fTotalPacketCount_lo < prevTotalPacketCount_lo) {
00289 ++fTotalPacketCount_hi;
00290 }
00291 }
00292
00293 unsigned RTPTransmissionStats::roundTripDelay() const {
00294
00295
00296
00297 if (fLastSRTime == 0) {
00298
00299
00300 return 0;
00301 }
00302
00303
00304
00305 unsigned lastReceivedTimeNTP_high
00306 = fTimeReceived.tv_sec + 0x83AA7E80;
00307 double fractionalPart = (fTimeReceived.tv_usec*0x0400)/15625.0;
00308 unsigned lastReceivedTimeNTP
00309 = (unsigned)((lastReceivedTimeNTP_high<<16) + fractionalPart + 0.5);
00310
00311 int rawResult = lastReceivedTimeNTP - fLastSRTime - fDiffSR_RRTime;
00312 if (rawResult < 0) {
00313
00314
00315 rawResult = 0;
00316 }
00317 return (unsigned)rawResult;
00318 }
00319
00320 void RTPTransmissionStats::getTotalOctetCount(u_int32_t& hi, u_int32_t& lo) {
00321 hi = fTotalOctetCount_hi;
00322 lo = fTotalOctetCount_lo;
00323 }
00324
00325 void RTPTransmissionStats::getTotalPacketCount(u_int32_t& hi, u_int32_t& lo) {
00326 hi = fTotalPacketCount_hi;
00327 lo = fTotalPacketCount_lo;
00328 }
00329
00330 unsigned RTPTransmissionStats::packetsReceivedSinceLastRR() const {
00331 if (!fOldValid) return 0;
00332
00333 return fLastPacketNumReceived-fOldLastPacketNumReceived;
00334 }
00335
00336 int RTPTransmissionStats::packetsLostBetweenRR() const {
00337 if (!fOldValid) return 0;
00338
00339 return fTotNumPacketsLost - fOldTotNumPacketsLost;
00340 }