summaryrefslogtreecommitdiff
path: root/ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp')
-rw-r--r--ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp b/ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp
new file mode 100644
index 00000000000..7011dab5371
--- /dev/null
+++ b/ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp
@@ -0,0 +1,364 @@
+// $Id$
+
+#include "orbsvcs/AV/RTCP_Channel.h"
+#include "orbsvcs/AV/RTP.h"
+#include "tao/debug.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+RTCP_Channel_In::RTCP_Channel_In (ACE_UINT32 ssrc,
+ const ACE_Addr *peer_addr)
+ : remote_ssrc_ (ssrc),
+ cname_ (""),
+ transit_ (0),
+ jitter_ (0.0),
+ first_data_packet_ (1),
+ ntp_ts_msw_ (0),
+ ntp_ts_lsw_ (0),
+ last_sr_time_ (0),
+ active_ (0),
+ no_data_counter_ (0),
+ data_since_last_report_ (0)
+{
+ const ACE_INET_Addr *const_inet_addr = dynamic_cast<const ACE_INET_Addr*> (peer_addr);
+
+ ACE_INET_Addr *inet_addr;
+ ACE_NEW (inet_addr,
+ ACE_INET_Addr (*const_inet_addr));
+
+ this->peer_address_ = inet_addr;
+}
+
+RTCP_Channel_In::~RTCP_Channel_In(void)
+{
+ delete this->peer_address_;
+}
+
+void
+RTCP_Channel_In::updateStatistics(RTP_Packet* dataPkt)
+{
+ ACE_Time_Value current_time;
+ ACE_UINT32 arrival;
+ int transit, d;
+
+ this->active_ = 0;
+
+ // determine if the source has been declared valid
+ if (update_seq(dataPkt->sn ()) == 0)
+ return;
+
+ // Set initial values if this is the first data packet.
+ if (this->first_data_packet_)
+ {
+ // store the initial timestamp
+ this->init_time_stamp_ = dataPkt->ts ();
+ this->init_local_time_ = ACE_OS::gettimeofday ();
+ this->first_data_packet_ = 0;
+ }
+
+ // Get the current time.
+ current_time = ACE_OS::gettimeofday ();
+
+ unsigned int samples_per_sec;
+ double samples_per_usec;
+
+
+ switch (dataPkt->pt())
+ {
+ case RTP_PT_PCMU:
+ case RTP_PT_CELP:
+ case RTP_PT_G721:
+ case RTP_PT_GSM:
+ case RTP_PT_DVI:
+ case RTP_PT_LPC:
+ case RTP_PT_PCMA:
+ case RTP_PT_G722:
+ samples_per_sec = 8000;
+ break;
+ case RTP_PT_L16_STEREO:
+ case RTP_PT_L16_MONO:
+ samples_per_sec = 44100;
+ break;
+ default:
+ samples_per_sec = 1000000;
+ };
+
+ samples_per_usec = samples_per_sec/1000000.0;
+
+ // Calculate the current timestamp.
+ arrival = (ACE_UINT32)((current_time.sec () -
+ this->init_local_time_.sec ()) * samples_per_sec +
+ ((double)(current_time.usec () -
+ (double)this->init_local_time_.usec ()) * samples_per_usec) +
+ this->init_time_stamp_);
+
+
+ // jitter calc from RFC 1889 app a.8
+ transit = arrival - dataPkt->ts ();
+ d = transit - this->transit_;
+ this->transit_ = transit;
+ if (d < 0)
+ d = -d;
+
+ // Calculate the inter-arrival jitter.
+ this->jitter_ += (1./16.)*((double)d - this->jitter_);
+
+ // Indicate that data has been received since the last report.
+ this->data_since_last_report_ = 1;
+
+ // Store the payload type.
+ this->payload_type_ = dataPkt->pt ();
+}
+
+int
+RTCP_Channel_In::updateStatistics(RTCP_SR_Packet *sr)
+{
+ // calculate the last SR time in 1/65536 sec.
+ ACE_Time_Value now = ACE_OS::gettimeofday ();
+ this->last_sr_time_ = (ACE_UINT32)
+ (now.sec () * 65536 +
+ now.usec () * 0.065536);
+
+ this->ntp_ts_msw_ = sr->ntp_ts_msw ();
+ this->ntp_ts_lsw_ = sr->ntp_ts_lsw ();
+
+ return 0;
+}
+
+int
+RTCP_Channel_In::updateStatistics(RTCP_RR_Packet * /*rr*/)
+{
+ return 0;
+}
+
+void
+RTCP_Channel_In::init_seq(ACE_UINT16 seq)
+{
+ this->base_seq_ = seq - 1;
+ this->max_seq_ = seq;
+ this->bad_seq_ = RTP_SEQ_MOD + 1;
+ this->cycles_ = 0;
+ this->received_ = 0;
+ this->received_prior_ = 0;
+ this->expected_prior_ = 0;
+}
+
+int
+RTCP_Channel_In::update_seq(ACE_UINT16 seq)
+{
+ // The following is taken from RFC 1889 Appendix A.1
+ ACE_UINT16 udelta = seq - this->max_seq_;
+ const int MAX_DROPOUT = 3000;
+ const int MAX_MISORDER = 100;
+ const int MIN_SEQUENTIAL = 2;
+
+ // Source is not valid until MIN_SEQUENTIAL packets with
+ // sequential sequence numbers have been received.
+ if (this->probation_)
+ {
+ // packet is in sequence
+ if (seq == this->max_seq_ + (ACE_UINT16)1)
+ {
+ this->probation_ --;
+ this->max_seq_ = seq;
+ if (this->probation_ == 0)
+ {
+ this->init_seq(seq);
+ this->received_++;
+ return 1;
+ }
+ }
+ else
+ {
+ this->probation_ = MIN_SEQUENTIAL - 1;
+ this->max_seq_ = seq;
+ }
+ return 0;
+ }
+ else if (udelta < MAX_DROPOUT)
+ {
+ // in order, with permissible gap
+ if (seq < this->max_seq_)
+ {
+ // seq number wrapped - count another 64k cycle
+ this->cycles_+=RTP_SEQ_MOD;
+ }
+ this->max_seq_ = seq;
+ }
+ else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER)
+ {
+ // the sequence number made a large jump
+ ACE_UINT32 temp = seq; // Borland reports a warning on the next line
+ // without this line.
+ if (temp == this->bad_seq_)
+ {
+ // two sequential packets, assume the other side restarted without
+ // telling us so just re-sync
+ // (i.e., pretend this was the first packet).
+ this->init_seq (seq);
+
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "RTCP_Channel_In: large jump in sequence number",
+ "; init seq\n"));
+ }
+ else
+ {
+ this->bad_seq_ = (seq+1)&(RTP_SEQ_MOD-1);
+ return 0;
+ }
+ }
+ else
+ {
+ // dup or reordered packet
+ }
+ this->received_++;
+
+ return 1;
+}
+
+void
+RTCP_Channel_In::recv_rtp_packet(ACE_Message_Block *mb,
+ const ACE_Addr *peer_address)
+{
+ if (*peer_address != *this->peer_address_)
+ ACE_DEBUG ((LM_DEBUG,
+ "RTCP_Channel_In::recv_rtp_packet - possible loop/collision detected"));
+
+ RTP_Packet data_packet(mb->rd_ptr (), static_cast<int> (mb->length ()));
+
+ // make sure the packet is valid
+ if (data_packet.is_valid ())
+ this->updateStatistics(&data_packet);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "RTCP_Channel_In::recvDataPacket - invalid RTP packet\n"));
+}
+
+
+RR_Block *
+RTCP_Channel_In::getRRBlock(void)
+{
+ // If no data has been received since the last report, don't create a block.
+ if (!this->data_since_last_report_)
+ {
+ this->no_data_counter_++;
+
+ // make the source inactive if significant time has passed since last report
+ if (this->no_data_counter_ == 32)
+ this->active_ = 0;
+
+ return 0;
+ }
+
+ this->no_data_counter_ = 0;
+
+ RR_Block *local_block_ptr = 0;
+
+ ACE_NEW_RETURN (local_block_ptr,
+ RR_Block,
+ 0);
+
+ ACE_OS::memset(local_block_ptr, 0, sizeof(RR_Block));
+
+ // Set the ssrc of the source this report is for.
+ local_block_ptr->ssrc_ = this->remote_ssrc_;
+
+ // Calculate packets expected/lost (from RFC 1889 Appendix A.3)
+ ACE_UINT32 extended_max;
+ ACE_UINT32 expected;
+ ACE_UINT32 expected_interval;
+ ACE_UINT32 received_interval;
+ int lost_interval;
+
+ extended_max = this->cycles_ + this->max_seq_;
+ expected = extended_max - this->base_seq_ + 1;
+
+ local_block_ptr->lost_ = expected - this->received_;
+ expected_interval = expected - this->expected_prior_;
+ this->expected_prior_ = expected;
+ received_interval = this->received_ - this->received_prior_;
+ this->received_prior_ = this->received_;
+ lost_interval = expected_interval - received_interval;
+
+ if ((expected_interval == 0) || (lost_interval <= 0))
+ local_block_ptr->fraction_ = 0;
+ else
+ local_block_ptr->fraction_ = (lost_interval << 8) / expected_interval;
+
+
+ local_block_ptr->last_seq_ = extended_max;
+
+ // taken from RFC 1889 App A.8
+ local_block_ptr->jitter_ = (ACE_UINT32)this->jitter_;
+
+ // calculate the last SR timestamp (lsr)
+ local_block_ptr->lsr_ = ((this->ntp_ts_msw_ & 0xFFFF) << 16) |
+ ((this->ntp_ts_lsw_ & 0xFFFF0000) >> 16);
+
+ // calculate the delay since last SR (dlsr)
+ ACE_Time_Value now = ACE_OS::gettimeofday ();
+ ACE_UINT32 now32 = (ACE_UINT32)
+ (now.sec () * 65536 +
+ now.usec () * 0.065536);
+
+ local_block_ptr->dlsr_ = now32 - this->last_sr_time_;
+
+ // indicate that no data has been received since the last report
+ this->data_since_last_report_ = 0;
+
+ return local_block_ptr;
+}
+
+RTCP_Channel_Out::RTCP_Channel_Out(void)
+ :cname_ ("cname"),
+ active_ (0),
+ timestamp_ (0),
+ timestamp_offset_ (0),
+ packets_sent_ (0),
+ octets_sent_ (0)
+{
+}
+
+RTCP_Channel_Out::~RTCP_Channel_Out(void)
+{
+}
+
+void
+RTCP_Channel_Out::updateStatistics (RTP_Packet *data_packet)
+{
+ // indicate that this source is active
+ this->active_ = 1;
+
+ // Update various counters.
+ this->octets_sent_ += data_packet->payload_size();
+ this->packets_sent_ ++;
+ this->seq_num_ = data_packet->sn ();
+ this->timestamp_ = data_packet->ts ();
+}
+
+ACE_UINT32
+RTCP_Channel_Out::timestamp (void)
+{
+ return this->timestamp_;
+}
+
+ACE_UINT32
+RTCP_Channel_Out::packets_sent (void)
+{
+ return this->packets_sent_;
+}
+
+ACE_UINT32
+RTCP_Channel_Out::octets_sent (void)
+{
+ return this->octets_sent_;
+}
+
+char
+RTCP_Channel_Out::active (void)
+{
+ return this->active_;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL