⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtpsink.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA  02111-1307  USA**********/// "liveMedia"// Copyright (c) 1996-2004 Live Networks, Inc.  All rights reserved.// RTP Sinks// Implementation#include "RTPSink.hh"#include "GroupsockHelper.hh"////////// RTPSink //////////Boolean RTPSink::lookupByName(UsageEnvironment& env, char const* sinkName,				RTPSink*& resultSink) {  resultSink = NULL; // unless we succeed  MediaSink* sink;  if (!MediaSink::lookupByName(env, sinkName, sink)) return False;  if (!sink->isRTPSink()) {    env.setResultMsg(sinkName, " is not a RTP sink");    return False;  }  resultSink = (RTPSink*)sink;  return True;}Boolean RTPSink::isRTPSink() const {  return True;}RTPSink::RTPSink(UsageEnvironment& env,		 Groupsock* rtpGS, unsigned char rtpPayloadType,		 unsigned rtpTimestampFrequency,		 char const* rtpPayloadFormatName,		 unsigned numChannels)  : MediaSink(env), fRTPInterface(this, rtpGS),    fRTPPayloadType(rtpPayloadType),    fPacketCount(0), fOctetCount(0), fTotalOctetCount(0),    fTimestampFrequency(rtpTimestampFrequency), fHaveComputedFirstTimestamp(False),    fNumChannels(numChannels) {  fRTPPayloadFormatName    = strDup(rtpPayloadFormatName == NULL ? "???" : rtpPayloadFormatName);  gettimeofday(&fCreationTime, NULL);  fTotalOctetCountStartTime = fCreationTime;  fSeqNo = (u_int16_t)our_random();  fSSRC = our_random32();  fTimestampBase = our_random32();  fCurrentTimestamp = fTimestampBase;  fTransmissionStatsDB = new RTPTransmissionStatsDB(*this);}RTPSink::~RTPSink() {  delete fTransmissionStatsDB;  delete[] (char*)fRTPPayloadFormatName;}u_int32_t RTPSink::convertToRTPTimestamp(struct timeval tv) {  u_int32_t rtpTimestampIncrement = timevalToTimestamp(tv);  if (!fHaveComputedFirstTimestamp) {    // Make the first timestamp the same as the current "fTimestampBase", so that    // timestamps begin with the value we promised when this "RTPSink" was created:    fTimestampBase -= rtpTimestampIncrement;    fHaveComputedFirstTimestamp = True;  }  u_int32_t const rtpTimestamp = fTimestampBase + rtpTimestampIncrement;#ifdef DEBUG_TIMESTAMPS  fprintf(stderr, "fTimestampBase: 0x%08x, tv: %lu.%06ld\n\t=> RTP timestamp: 0x%08x\n",	  fTimestampBase, tv.tv_sec, tv.tv_usec, rtpTimestamp);  fflush(stderr);#endif  return rtpTimestamp;}u_int32_t RTPSink::timevalToTimestamp(struct timeval tv) const {  u_int32_t timestamp = (fTimestampFrequency*tv.tv_sec);  timestamp += (u_int32_t)((2.0*fTimestampFrequency*tv.tv_usec + 1000000.0)/2000000);       // note: rounding  return timestamp;}void RTPSink::getTotalBitrate(unsigned& outNumBytes, double& outElapsedTime) {  struct timeval timeNow;  gettimeofday(&timeNow, NULL);  outNumBytes = fTotalOctetCount;  outElapsedTime = (double)(timeNow.tv_sec-fTotalOctetCountStartTime.tv_sec)    + (timeNow.tv_usec-fTotalOctetCountStartTime.tv_usec)/1000000.0;  fTotalOctetCount = 0;  fTotalOctetCountStartTime = timeNow;}char const* RTPSink::sdpMediaType() const {  return "data";  // default SDP media (m=) type, unless redefined by subclasses}char* RTPSink::rtpmapLine() const {  if (rtpPayloadType() >= 96) { // the payload format type is dynamic    char* encodingParamsPart;    if (numChannels() != 1) {      encodingParamsPart = new char[1 + 20 /* max int len */];      sprintf(encodingParamsPart, "/%d", numChannels());    } else {      encodingParamsPart = strDup("");    }    char const* const rtpmapFmt = "a=rtpmap:%d %s/%d%s\r\n";    unsigned rtpmapFmtSize = strlen(rtpmapFmt)      + 3 /* max char len */ + strlen(rtpPayloadFormatName())      + 20 /* max int len */ + strlen(encodingParamsPart);    char* rtpmapLine = new char[rtpmapFmtSize];    sprintf(rtpmapLine, rtpmapFmt,	    rtpPayloadType(), rtpPayloadFormatName(),	    rtpTimestampFrequency(), encodingParamsPart);    delete[] encodingParamsPart;    return rtpmapLine;  } else {    // The payload format is staic, so there's no "a=rtpmap:" line:    return strDup("");  }}char const* RTPSink::auxSDPLine() {  return NULL; // by default}////////// RTPTransmissionStatsDB //////////RTPTransmissionStatsDB::RTPTransmissionStatsDB(RTPSink& rtpSink)  : fOurRTPSink(rtpSink),    fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {  fNumReceivers=0;}RTPTransmissionStatsDB::~RTPTransmissionStatsDB() {  // First, remove and delete all stats records from the table:  RTPTransmissionStats* stats;  while ((stats = (RTPTransmissionStats*)fTable->RemoveNext()) != NULL) {    delete stats;  }  // Then, delete the table itself:  delete fTable;}void RTPTransmissionStatsDB::noteIncomingRR(u_int32_t SSRC, struct sockaddr_in const& lastFromAddress,                 unsigned lossStats, unsigned lastPacketNumReceived,                 unsigned jitter, unsigned lastSRTime, unsigned diffSR_RRTime) {  RTPTransmissionStats* stats = lookup(SSRC);  if (stats == NULL) {    // This is the first time we've heard of this SSRC.    // Create a new record for it:    stats = new RTPTransmissionStats(fOurRTPSink, SSRC);    if (stats == NULL) return;    add(SSRC, stats);#ifdef DEBUG_RR    fprintf(stderr, "Adding new entry for SSRC %x in RTPTransmissionStatsDB\n", SSRC);#endif  }  stats->noteIncomingRR(lastFromAddress,			lossStats, lastPacketNumReceived, jitter,                        lastSRTime, diffSR_RRTime);}void RTPTransmissionStatsDB::removeRecord(u_int32_t SSRC) {  RTPTransmissionStats* stats = lookup(SSRC);  if (stats != NULL) {    long SSRC_long = (long)SSRC;    fTable->Remove((char const*)SSRC_long);    --fNumReceivers;    delete stats;  }}RTPTransmissionStatsDB::Iterator::Iterator(RTPTransmissionStatsDB& receptionStatsDB)  : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {}RTPTransmissionStatsDB::Iterator::~Iterator() {  delete fIter;}RTPTransmissionStats*RTPTransmissionStatsDB::Iterator::next() {  char const* key; // dummy   return (RTPTransmissionStats*)(fIter->next(key));}RTPTransmissionStats* RTPTransmissionStatsDB::lookup(u_int32_t SSRC) const {  long SSRC_long = (long)SSRC;  return (RTPTransmissionStats*)(fTable->Lookup((char const*)SSRC_long));}void RTPTransmissionStatsDB::add(u_int32_t SSRC, RTPTransmissionStats* stats) {  long SSRC_long = (long)SSRC;  fTable->Add((char const*)SSRC_long, stats);  ++fNumReceivers;}////////// RTPTransmissionStats //////////RTPTransmissionStats::RTPTransmissionStats(RTPSink& rtpSink, u_int32_t SSRC)  : fOurRTPSink(rtpSink), fSSRC(SSRC), fLastPacketNumReceived(0),    fPacketLossRatio(0), fTotNumPacketsLost(0), fJitter(0),    fLastSRTime(0), fDiffSR_RRTime(0), fFirstPacket(True),    fTotalOctetCount_hi(0), fTotalOctetCount_lo(0),     fTotalPacketCount_hi(0), fTotalPacketCount_lo(0) {  gettimeofday(&fTimeCreated, NULL);  fLastOctetCount = rtpSink.octetCount();  fLastPacketCount = rtpSink.packetCount();}RTPTransmissionStats::~RTPTransmissionStats() {}void RTPTransmissionStats::noteIncomingRR(struct sockaddr_in const& lastFromAddress,		 unsigned lossStats, unsigned lastPacketNumReceived,		 unsigned jitter, unsigned lastSRTime,		 unsigned diffSR_RRTime) {  if (fFirstPacket) {    fFirstPacket = False;    fFirstPacketNumReported = lastPacketNumReceived;  } else {    fOldValid = True;    fOldLastPacketNumReceived = fLastPacketNumReceived;    fOldTotNumPacketsLost = fTotNumPacketsLost;  }  gettimeofday(&fTimeReceived, NULL);  fLastFromAddress = lastFromAddress;  fPacketLossRatio = lossStats>>24;  fTotNumPacketsLost = lossStats&0xFFFFFF;  fLastPacketNumReceived = lastPacketNumReceived;  fJitter = jitter;  fLastSRTime = lastSRTime;  fDiffSR_RRTime = diffSR_RRTime;#ifdef DEBUG_RR  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",          fTimeReceived.tv_sec, fTimeReceived.tv_usec, lossStats, lastPacketNumReceived, jitter, lastSRTime, diffSR_RRTime);  unsigned rtd = roundTripDelay();   fprintf(stderr, "=> round-trip delay: 0x%04x (== %f seconds)\n", rtd, rtd/65536.0);#endif  // Update our counts of the total number of octets and packets sent towards  // this receiver:  u_int32_t newOctetCount = fOurRTPSink.octetCount();  u_int32_t octetCountDiff = newOctetCount - fLastOctetCount;  fLastOctetCount = newOctetCount;  u_int32_t prevTotalOctetCount_lo = fTotalOctetCount_lo;  fTotalOctetCount_lo += octetCountDiff;  if (fTotalOctetCount_lo < prevTotalOctetCount_lo) { // wrap around    ++fTotalOctetCount_hi;  }  u_int32_t newPacketCount = fOurRTPSink.packetCount();  u_int32_t packetCountDiff = newPacketCount - fLastPacketCount;  fLastPacketCount = newPacketCount;  u_int32_t prevTotalPacketCount_lo = fTotalPacketCount_lo;  fTotalPacketCount_lo += packetCountDiff;  if (fTotalPacketCount_lo < prevTotalPacketCount_lo) { // wrap around    ++fTotalPacketCount_hi;  }}unsigned RTPTransmissionStats::roundTripDelay() const {  // Compute the round-trip delay that was indicated by the most recently-received  // RTCP RR packet.  Use the method noted in the RTP/RTCP specification (RFC 3350).    if (fLastSRTime == 0) {    // Either no RTCP RR packet has been received yet, or else the    // reporting receiver has not yet received any RTCP SR packets from us:    return 0;  }  // First, convert the time that we received the last RTCP RR packet to NTP format,  // in units of 1/65536 (2^-16) seconds:  unsigned lastReceivedTimeNTP_high    = fTimeReceived.tv_sec + 0x83AA7E80; // 1970 epoch -> 1900 epoch  double fractionalPart = (fTimeReceived.tv_usec*0x0400)/15625.0; // 2^16/10^6  unsigned lastReceivedTimeNTP    = (unsigned)((lastReceivedTimeNTP_high<<16) + fractionalPart + 0.5);  int rawResult = lastReceivedTimeNTP - fLastSRTime - fDiffSR_RRTime;  if (rawResult < 0) {    // This can happen if there's clock drift between the sender and receiver,    // and if the round-trip time was very small.    rawResult = 0;  }  return (unsigned)rawResult;}void RTPTransmissionStats::getTotalOctetCount(u_int32_t& hi, u_int32_t& lo) {  hi = fTotalOctetCount_hi;  lo = fTotalOctetCount_lo;}void RTPTransmissionStats::getTotalPacketCount(u_int32_t& hi, u_int32_t& lo) {  hi = fTotalPacketCount_hi;  lo = fTotalPacketCount_lo;}unsigned RTPTransmissionStats::packetsReceivedSinceLastRR() const {  if (!fOldValid) return 0;  return fLastPacketNumReceived-fOldLastPacketNumReceived;}int RTPTransmissionStats::packetsLostBetweenRR() const {  if (!fOldValid) return 0;  return fTotNumPacketsLost - fOldTotNumPacketsLost;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -