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(False), fEnableRTCPReports(True),
00055 fNumChannels(numChannels) {
00056 fRTPPayloadFormatName
00057 = strDup(rtpPayloadFormatName == NULL ? "???" : rtpPayloadFormatName);
00058 gettimeofday(&fCreationTime, NULL);
00059 fTotalOctetCountStartTime = fCreationTime;
00060 resetPresentationTimes();
00061
00062 fSeqNo = (u_int16_t)our_random();
00063 fSSRC = our_random32();
00064 fTimestampBase = our_random32();
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
00076 u_int32_t timestampIncrement = (fTimestampFrequency*tv.tv_sec);
00077 timestampIncrement += (u_int32_t)(fTimestampFrequency*(tv.tv_usec/1000000.0) + 0.5);
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 void RTPSink::resetPresentationTimes() {
00121 fInitialPresentationTime.tv_sec = fMostRecentPresentationTime.tv_sec = 0;
00122 fInitialPresentationTime.tv_usec = fMostRecentPresentationTime.tv_usec = 0;
00123 }
00124
00125 char const* RTPSink::sdpMediaType() const {
00126 return "data";
00127
00128 }
00129
00130 char* RTPSink::rtpmapLine() const {
00131 if (rtpPayloadType() >= 96) {
00132 char* encodingParamsPart;
00133 if (numChannels() != 1) {
00134 encodingParamsPart = new char[1 + 20 ];
00135 sprintf(encodingParamsPart, "/%d", numChannels());
00136 } else {
00137 encodingParamsPart = strDup("");
00138 }
00139 char const* const rtpmapFmt = "a=rtpmap:%d %s/%d%s\r\n";
00140 unsigned rtpmapFmtSize = strlen(rtpmapFmt)
00141 + 3 + strlen(rtpPayloadFormatName())
00142 + 20 + strlen(encodingParamsPart);
00143 char* rtpmapLine = new char[rtpmapFmtSize];
00144 sprintf(rtpmapLine, rtpmapFmt,
00145 rtpPayloadType(), rtpPayloadFormatName(),
00146 rtpTimestampFrequency(), encodingParamsPart);
00147 delete[] encodingParamsPart;
00148
00149 return rtpmapLine;
00150 } else {
00151
00152 return strDup("");
00153 }
00154 }
00155
00156 char const* RTPSink::auxSDPLine() {
00157 return NULL;
00158 }
00159
00160
00162
00163 RTPTransmissionStatsDB::RTPTransmissionStatsDB(RTPSink& rtpSink)
00164 : fOurRTPSink(rtpSink),
00165 fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
00166 fNumReceivers=0;
00167 }
00168
00169 RTPTransmissionStatsDB::~RTPTransmissionStatsDB() {
00170
00171 RTPTransmissionStats* stats;
00172 while ((stats = (RTPTransmissionStats*)fTable->RemoveNext()) != NULL) {
00173 delete stats;
00174 }
00175
00176
00177 delete fTable;
00178 }
00179
00180 void RTPTransmissionStatsDB
00181 ::noteIncomingRR(u_int32_t SSRC, struct sockaddr_in const& lastFromAddress,
00182 unsigned lossStats, unsigned lastPacketNumReceived,
00183 unsigned jitter, unsigned lastSRTime, unsigned diffSR_RRTime) {
00184 RTPTransmissionStats* stats = lookup(SSRC);
00185 if (stats == NULL) {
00186
00187
00188 stats = new RTPTransmissionStats(fOurRTPSink, SSRC);
00189 if (stats == NULL) return;
00190 add(SSRC, stats);
00191 #ifdef DEBUG_RR
00192 fprintf(stderr, "Adding new entry for SSRC %x in RTPTransmissionStatsDB\n", SSRC);
00193 #endif
00194 }
00195
00196 stats->noteIncomingRR(lastFromAddress,
00197 lossStats, lastPacketNumReceived, jitter,
00198 lastSRTime, diffSR_RRTime);
00199 }
00200
00201 void RTPTransmissionStatsDB::removeRecord(u_int32_t SSRC) {
00202 RTPTransmissionStats* stats = lookup(SSRC);
00203 if (stats != NULL) {
00204 long SSRC_long = (long)SSRC;
00205 fTable->Remove((char const*)SSRC_long);
00206 --fNumReceivers;
00207 delete stats;
00208 }
00209 }
00210
00211 RTPTransmissionStatsDB::Iterator
00212 ::Iterator(RTPTransmissionStatsDB& receptionStatsDB)
00213 : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
00214 }
00215
00216 RTPTransmissionStatsDB::Iterator::~Iterator() {
00217 delete fIter;
00218 }
00219
00220 RTPTransmissionStats*
00221 RTPTransmissionStatsDB::Iterator::next() {
00222 char const* key;
00223
00224 return (RTPTransmissionStats*)(fIter->next(key));
00225 }
00226
00227 RTPTransmissionStats* RTPTransmissionStatsDB::lookup(u_int32_t SSRC) const {
00228 long SSRC_long = (long)SSRC;
00229 return (RTPTransmissionStats*)(fTable->Lookup((char const*)SSRC_long));
00230 }
00231
00232 void RTPTransmissionStatsDB::add(u_int32_t SSRC, RTPTransmissionStats* stats) {
00233 long SSRC_long = (long)SSRC;
00234 fTable->Add((char const*)SSRC_long, stats);
00235 ++fNumReceivers;
00236 }
00237
00238
00240
00241 RTPTransmissionStats::RTPTransmissionStats(RTPSink& rtpSink, u_int32_t SSRC)
00242 : fOurRTPSink(rtpSink), fSSRC(SSRC), fLastPacketNumReceived(0),
00243 fPacketLossRatio(0), fTotNumPacketsLost(0), fJitter(0),
00244 fLastSRTime(0), fDiffSR_RRTime(0), fAtLeastTwoRRsHaveBeenReceived(False), fFirstPacket(True),
00245 fTotalOctetCount_hi(0), fTotalOctetCount_lo(0),
00246 fTotalPacketCount_hi(0), fTotalPacketCount_lo(0) {
00247 gettimeofday(&fTimeCreated, NULL);
00248
00249 fLastOctetCount = rtpSink.octetCount();
00250 fLastPacketCount = rtpSink.packetCount();
00251 }
00252
00253 RTPTransmissionStats::~RTPTransmissionStats() {}
00254
00255 void RTPTransmissionStats
00256 ::noteIncomingRR(struct sockaddr_in const& lastFromAddress,
00257 unsigned lossStats, unsigned lastPacketNumReceived,
00258 unsigned jitter, unsigned lastSRTime,
00259 unsigned diffSR_RRTime) {
00260 if (fFirstPacket) {
00261 fFirstPacket = False;
00262 fFirstPacketNumReported = lastPacketNumReceived;
00263 } else {
00264 fAtLeastTwoRRsHaveBeenReceived = True;
00265 fOldLastPacketNumReceived = fLastPacketNumReceived;
00266 fOldTotNumPacketsLost = fTotNumPacketsLost;
00267 }
00268 gettimeofday(&fTimeReceived, NULL);
00269
00270 fLastFromAddress = lastFromAddress;
00271 fPacketLossRatio = lossStats>>24;
00272 fTotNumPacketsLost = lossStats&0xFFFFFF;
00273 fLastPacketNumReceived = lastPacketNumReceived;
00274 fJitter = jitter;
00275 fLastSRTime = lastSRTime;
00276 fDiffSR_RRTime = diffSR_RRTime;
00277 #ifdef DEBUG_RR
00278 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",
00279 fTimeReceived.tv_sec, fTimeReceived.tv_usec, lossStats, lastPacketNumReceived, jitter, lastSRTime, diffSR_RRTime);
00280 unsigned rtd = roundTripDelay();
00281 fprintf(stderr, "=> round-trip delay: 0x%04x (== %f seconds)\n", rtd, rtd/65536.0);
00282 #endif
00283
00284
00285
00286 u_int32_t newOctetCount = fOurRTPSink.octetCount();
00287 u_int32_t octetCountDiff = newOctetCount - fLastOctetCount;
00288 fLastOctetCount = newOctetCount;
00289 u_int32_t prevTotalOctetCount_lo = fTotalOctetCount_lo;
00290 fTotalOctetCount_lo += octetCountDiff;
00291 if (fTotalOctetCount_lo < prevTotalOctetCount_lo) {
00292 ++fTotalOctetCount_hi;
00293 }
00294
00295 u_int32_t newPacketCount = fOurRTPSink.packetCount();
00296 u_int32_t packetCountDiff = newPacketCount - fLastPacketCount;
00297 fLastPacketCount = newPacketCount;
00298 u_int32_t prevTotalPacketCount_lo = fTotalPacketCount_lo;
00299 fTotalPacketCount_lo += packetCountDiff;
00300 if (fTotalPacketCount_lo < prevTotalPacketCount_lo) {
00301 ++fTotalPacketCount_hi;
00302 }
00303 }
00304
00305 unsigned RTPTransmissionStats::roundTripDelay() const {
00306
00307
00308
00309 if (fLastSRTime == 0) {
00310
00311
00312 return 0;
00313 }
00314
00315
00316
00317 unsigned lastReceivedTimeNTP_high
00318 = fTimeReceived.tv_sec + 0x83AA7E80;
00319 double fractionalPart = (fTimeReceived.tv_usec*0x0400)/15625.0;
00320 unsigned lastReceivedTimeNTP
00321 = (unsigned)((lastReceivedTimeNTP_high<<16) + fractionalPart + 0.5);
00322
00323 int rawResult = lastReceivedTimeNTP - fLastSRTime - fDiffSR_RRTime;
00324 if (rawResult < 0) {
00325
00326
00327 rawResult = 0;
00328 }
00329 return (unsigned)rawResult;
00330 }
00331
00332 void RTPTransmissionStats::getTotalOctetCount(u_int32_t& hi, u_int32_t& lo) {
00333 hi = fTotalOctetCount_hi;
00334 lo = fTotalOctetCount_lo;
00335 }
00336
00337 void RTPTransmissionStats::getTotalPacketCount(u_int32_t& hi, u_int32_t& lo) {
00338 hi = fTotalPacketCount_hi;
00339 lo = fTotalPacketCount_lo;
00340 }
00341
00342 unsigned RTPTransmissionStats::packetsReceivedSinceLastRR() const {
00343 if (!fAtLeastTwoRRsHaveBeenReceived) return 0;
00344
00345 return fLastPacketNumReceived-fOldLastPacketNumReceived;
00346 }
00347
00348 int RTPTransmissionStats::packetsLostBetweenRR() const {
00349 if (!fAtLeastTwoRRsHaveBeenReceived) return 0;
00350
00351 return fTotNumPacketsLost - fOldTotNumPacketsLost;
00352 }