diff options
Diffstat (limited to 'ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp')
-rw-r--r-- | ACE/TAO/orbsvcs/orbsvcs/AV/RTCP_Channel.cpp | 364 |
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 |