#include <RTCP.h>
Inheritance diagram for TAO_AV_RTCP_Callback:
Public Member Functions | |
TAO_AV_RTCP_Callback (void) | |
RTCP callback. | |
virtual | ~TAO_AV_RTCP_Callback (void) |
virtual destructor. | |
virtual int | handle_start (void) |
Called during Streamctrl->start. | |
virtual int | handle_stop (void) |
Called during Streamctrl->stop. | |
virtual int | handle_timeout (void *arg) |
Called during timeout for Flow Producers. | |
virtual int | receive_frame (ACE_Message_Block *frame, TAO_AV_frame_info *frame_info=0, const ACE_Addr &peer_address=ACE_Addr::sap_any) |
Called when a frame arrives for a FlowConsumer. | |
int | send_frame (ACE_Message_Block *frame) |
virtual int | receive_control_frame (ACE_Message_Block *frame, const ACE_Addr &peer_address=ACE_Addr::sap_any) |
virtual int | handle_destroy (void) |
virtual void | get_timeout (ACE_Time_Value *&tv, void *&arg) |
int | send_report (int bye) |
void | schedule (int ms) |
TAO_AV_RTP_State * | state (void) |
void | ts_offset (ACE_UINT32 offset) |
Protected Attributes | |
ACE_Hash_Map_Manager< ACE_UINT32, RTCP_Channel_In *, ACE_Null_Mutex > | inputs_ |
RTCP_Channel_Out | output_ |
int | timeout_ |
int | timestamp_offset_ |
int | sdes_count_ |
int | is_initial_timeout_ |
int | avg_rtcp_size_ |
int | packet_size_ |
Definition at line 139 of file RTCP.h.
TAO_AV_RTCP_Callback::TAO_AV_RTCP_Callback | ( | void | ) |
RTCP callback.
Definition at line 497 of file RTCP.cpp.
References RTCP_Channel_Out::cname(), ACE_OS::hostname(), output_, and ACE_OS::sprintf().
00498 :is_initial_timeout_(1), 00499 packet_size_(0) 00500 { 00501 char cname[256]; 00502 char host[256]; 00503 ACE_OS::hostname(host, sizeof(host)); 00504 00505 // TODO: determine username auto-magically? 00506 ACE_OS::sprintf(cname, "username@%s", host); 00507 00508 this->output_.cname(cname); 00509 }
TAO_AV_RTCP_Callback::~TAO_AV_RTCP_Callback | ( | void | ) | [virtual] |
void TAO_AV_RTCP_Callback::get_timeout | ( | ACE_Time_Value *& | tv, | |
void *& | arg | |||
) | [virtual] |
Called to get the timeout. If tv is 0 then the framework stop calling this.
Reimplemented from TAO_AV_Callback.
Definition at line 726 of file RTCP.cpp.
References ACE_NEW, avg_rtcp_size_, ACE_Hash_Map_Manager_Ex< EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK >::begin(), inputs_, is_initial_timeout_, packet_size_, TAO_AV_RTCP::rtcp_interval(), ACE_Time_Value::sec(), and ACE_Time_Value::usec().
00728 { 00729 int senders = 0; 00730 int members = 1; // count self as member 00731 00732 // TODO: this should be 5% of the session bw 00733 double rtcp_bw = 1000; 00734 double interval; 00735 00736 ACE_Hash_Map_Iterator<ACE_UINT32, RTCP_Channel_In*, ACE_Null_Mutex> iter (this->inputs_); 00737 iter = this->inputs_.begin(); 00738 00739 if (this->output_.active ()) 00740 senders++; 00741 00742 // determine the number of senders and members of this session 00743 while (iter != this->inputs_.end ()) 00744 { 00745 if ((*iter).int_id_->active ()) 00746 { 00747 if ((*iter).int_id_->sender ()) 00748 senders++; 00749 members++; 00750 } 00751 iter++; 00752 } 00753 00754 // Here we do the RTCP timeout calculation. 00755 interval = TAO_AV_RTCP::rtcp_interval (members, // members 00756 senders, // senders 00757 rtcp_bw, // rtcp_bw 00758 this->output_.active (), // we_sent 00759 this->packet_size_, // packet_size 00760 &this->avg_rtcp_size_, // avg_rtcp_size 00761 this->is_initial_timeout_); // initial) 00762 00763 this->is_initial_timeout_ = 0; 00764 00765 ACE_NEW (tv, 00766 ACE_Time_Value); 00767 00768 tv->sec ((int)interval); 00769 tv->usec ((int)((interval - (int)interval) * 1000000)); 00770 }
int TAO_AV_RTCP_Callback::handle_destroy | ( | void | ) | [virtual] |
Called during Streamctrl->destroy i.e tear_down of the stream @coryan:Call it handle_destroy or handle_close.
Reimplemented from TAO_AV_Callback.
Definition at line 773 of file RTCP.cpp.
int TAO_AV_RTCP_Callback::handle_start | ( | void | ) | [virtual] |
Called during Streamctrl->start.
Reimplemented from TAO_AV_Callback.
Definition at line 522 of file RTCP.cpp.
int TAO_AV_RTCP_Callback::handle_stop | ( | void | ) | [virtual] |
Called during Streamctrl->stop.
Reimplemented from TAO_AV_Callback.
Definition at line 528 of file RTCP.cpp.
References send_report().
00529 { 00530 return this->send_report(1); 00531 }
int TAO_AV_RTCP_Callback::handle_timeout | ( | void * | arg | ) | [virtual] |
Called during timeout for Flow Producers.
Reimplemented from TAO_AV_Callback.
Definition at line 534 of file RTCP.cpp.
References send_report().
00535 { 00536 return this->send_report(0); 00537 }
TAO_BEGIN_VERSIONED_NAMESPACE_DECL int TAO_AV_RTCP_Callback::receive_control_frame | ( | ACE_Message_Block * | data, | |
const ACE_Addr & | peer_address = ACE_Addr::sap_any | |||
) | [virtual] |
Copyright (c) 1994-1995 Regents of the University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and the Network Research Group at Lawrence Berkeley Laboratory. 4. Neither the name of the University nor of the Laboratory may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Reimplemented from TAO_AV_Callback.
Definition at line 50 of file RTCP.cpp.
References ACE_DEBUG, ACE_NEW_RETURN, ACE_Hash_Map_Manager_Ex< EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK >::bind(), RTCP_BYE_Packet::dump(), RTCP_SDES_Packet::dump(), RTCP_RR_Packet::dump(), RTCP_SR_Packet::dump(), inputs_, RTCP_Packet::is_valid(), ACE_Message_Block::length(), LM_DEBUG, ACE_Message_Block::rd_ptr(), RTCP_PT_APP, RTCP_PT_BYE, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, RTCP_RR_Packet::ssrc(), RTCP_SR_Packet::ssrc(), RTCP_BYE_Packet::ssrc_list(), TAO_debug_level, ACE_Hash_Map_Manager_Ex< EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK >::unbind(), and RTCP_Channel_In::updateStatistics().
00052 { 00053 int length = static_cast<int> (data->length ()); 00054 int more = length; 00055 char *buf_ptr = data->rd_ptr (); 00056 char first_rtcp_packet = 1; 00057 RTCP_Channel_In *c; 00058 00059 // This code performs the RTCP Header validity checks detailed in RFC 1889 00060 // Appendix A.2 00061 00062 while (more > 0) 00063 { 00064 // the second byte of the control packet is the type 00065 switch ((unsigned char)buf_ptr[length - more + 1]) 00066 { 00067 case RTCP_PT_SR: 00068 { 00069 RTCP_SR_Packet sr(&buf_ptr[length-more], 00070 &more); 00071 00072 if (!sr.is_valid(first_rtcp_packet)) 00073 ACE_DEBUG ((LM_DEBUG, 00074 "TAO_AV_RTCP_Callback::receive_control_frame - " 00075 "warning invalid rtcp packet\n")); 00076 00077 if (this->inputs_.find (sr.ssrc (), c) == -1) 00078 { 00079 ACE_NEW_RETURN (c, 00080 RTCP_Channel_In (sr.ssrc (), 00081 &peer_address), 00082 -1); 00083 this->inputs_.bind (sr.ssrc (), c); 00084 } 00085 c->updateStatistics (&sr); 00086 00087 if (TAO_debug_level > 0) 00088 sr.dump (); 00089 break; 00090 } 00091 case RTCP_PT_RR: 00092 { 00093 RTCP_RR_Packet rr(&buf_ptr[length-more], 00094 &more); 00095 00096 if (!rr.is_valid(first_rtcp_packet)) 00097 ACE_DEBUG ((LM_DEBUG, 00098 "TAO_AV_RTCP_Callback::receive_control_frame - " 00099 "warning invalid rtcp packet\n")); 00100 00101 if (this->inputs_.find (rr.ssrc (), c) == -1) 00102 { 00103 ACE_NEW_RETURN (c, 00104 RTCP_Channel_In (rr.ssrc (), 00105 &peer_address), 00106 -1); 00107 this->inputs_.bind (rr.ssrc (), c); 00108 } 00109 00110 c->updateStatistics (&rr); 00111 00112 if (TAO_debug_level > 0) 00113 rr.dump (); 00114 break; 00115 } 00116 case RTCP_PT_SDES: 00117 { 00118 RTCP_SDES_Packet sdes (&buf_ptr[length-more], 00119 &more); 00120 00121 if (!sdes.is_valid(first_rtcp_packet)) 00122 ACE_DEBUG ((LM_DEBUG, 00123 "TAO_AV_RTCP_Callback::receive_control_frame - " 00124 "warning invalid rtcp packet\n")); 00125 00126 if (TAO_debug_level > 0) 00127 sdes.dump (); 00128 break; 00129 } 00130 case RTCP_PT_BYE: 00131 { 00132 RTCP_BYE_Packet bye (&buf_ptr[length-more], 00133 &more); 00134 00135 if (!bye.is_valid(first_rtcp_packet)) 00136 ACE_DEBUG ((LM_DEBUG, 00137 "TAO_AV_RTCP_Callback::receive_control_frame - " 00138 "warning invalid rtcp packet\n")); 00139 00140 // Inform the listener that a source(s) has left the session 00141 ACE_UINT32 *ssrc_list; 00142 unsigned char length; 00143 00144 bye.ssrc_list(&ssrc_list, length); 00145 00146 for (int i=0; i<length; i++) 00147 { 00148 RTCP_Channel_In *c = 0; 00149 00150 // remove the channel from the list 00151 this->inputs_.unbind(ssrc_list[i], c); 00152 00153 if (c != 0) 00154 delete c; 00155 } 00156 00157 if (TAO_debug_level > 0) 00158 bye.dump (); 00159 00160 break; 00161 } 00162 case RTCP_PT_APP: 00163 // If we receive one of these, ignore it. 00164 ACE_DEBUG ((LM_DEBUG, 00165 "TAO_AV_RTCP_Callback::receive_control_frame - " 00166 "APP packet - ignore\n")); 00167 more -= (4 + (ACE_UINT16)buf_ptr[length - more + 2]); 00168 break; 00169 default: 00170 ACE_DEBUG ((LM_DEBUG, 00171 "TAO_AV_RTCP_Callback::receive_control_frame - " 00172 "UNKNOWN packet type %u; ignore the rest\n", 00173 (int)buf_ptr[length - more + 1])); 00174 more = 0; 00175 } 00176 00177 first_rtcp_packet = 0; 00178 00179 } 00180 00181 if (more != 0) 00182 ACE_DEBUG ((LM_DEBUG, 00183 "TAO_AV_RTCP_Callback::receive_control_frame - " 00184 "Error in overall packet length\n")); 00185 return 0; 00186 }
int TAO_AV_RTCP_Callback::receive_frame | ( | ACE_Message_Block * | frame, | |
TAO_AV_frame_info * | frame_info = 0 , |
|||
const ACE_Addr & | peer_address = ACE_Addr::sap_any | |||
) | [virtual] |
Called when a frame arrives for a FlowConsumer.
Reimplemented from TAO_AV_Callback.
Definition at line 779 of file RTCP.cpp.
References ACE_NEW_RETURN, ACE_Hash_Map_Manager_Ex< EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK >::bind(), inputs_, ACE_Message_Block::length(), ACE_Message_Block::rd_ptr(), RTCP_Channel_In::recv_rtp_packet(), and RTP_Packet::ssrc().
00782 { 00783 RTCP_Channel_In *c; 00784 00785 RTP_Packet packet (frame->rd_ptr(), static_cast<int> (frame->length())); 00786 00787 if (this->inputs_.find (packet.ssrc(), c) < 0) 00788 { 00789 ACE_NEW_RETURN (c, 00790 RTCP_Channel_In (packet.ssrc(), 00791 &peer_address), 00792 -1); 00793 00794 this->inputs_.bind (packet.ssrc(), c); 00795 } 00796 00797 c->recv_rtp_packet (frame, &peer_address); 00798 return 0; 00799 }
void TAO_AV_RTCP_Callback::schedule | ( | int | ms | ) |
int TAO_AV_RTCP_Callback::send_frame | ( | ACE_Message_Block * | frame | ) |
Definition at line 802 of file RTCP.cpp.
References ACE_Message_Block::length(), output_, ACE_Message_Block::rd_ptr(), and RTCP_Channel_Out::updateStatistics().
Referenced by TAO_AV_RTCP_Object::handle_control_output().
00803 { 00804 RTP_Packet packet (frame->rd_ptr(), static_cast<int> (frame->length())); 00805 this->output_.updateStatistics (&packet); 00806 00807 return 0; 00808 }
int TAO_AV_RTCP_Callback::send_report | ( | int | bye | ) |
Definition at line 540 of file RTCP.cpp.
References ACE_NEW_RETURN, RTCP_SDES_Packet::add_item(), ACE_Hash_Map_Manager_Ex< EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK >::begin(), ACE_String_Base< CHAR >::c_str(), RTCP_Channel_Out::cname(), RTCP_Packet::get_packet_data(), ACE_OS::gettimeofday(), inputs_, ACE_String_Base< CHAR >::length(), TAO_AV_RTCP::ntp64::lower, ACE_OS::memcpy(), RR_Block::next_, ntp64time(), RTCP_Channel_Out::octets_sent(), output_, packet_size_, TAO_AV_Callback::protocol_object_, RTCP_SDES_CNAME, RTCP_SDES_EMAIL, RTCP_SDES_NAME, RTCP_SDES_NOTE, RTCP_SDES_TOOL, sdes_count_, TAO_AV_Protocol_Object::send_frame(), TAO_AV_RTCP_Object::ssrc(), ACE_OS::strlen(), timestamp_offset_, TAO_AV_RTCP::ntp64::upper, and ACE_Message_Block::wr_ptr().
Referenced by handle_stop(), and handle_timeout().
00541 { 00542 // get the RTCP control object in order to get the ssrc 00543 TAO_AV_RTCP_Object *rtcp_prot_obj = dynamic_cast<TAO_AV_RTCP_Object*> (this->protocol_object_); 00544 ACE_UINT32 my_ssrc = rtcp_prot_obj->ssrc (); 00545 00546 RTCP_Packet *cp; 00547 RTCP_SDES_Packet sdes; 00548 ACE_CString value = ""; 00549 ACE_CString note = ""; 00550 unsigned char sdes_type = 0; 00551 RTCP_BYE_Packet *bye_packet = 0; // only used for bye 00552 ACE_UINT32 ssrc_list[1]; // only used for bye 00553 00554 // get an iterator for the incoming channels. 00555 ACE_Hash_Map_Iterator<ACE_UINT32, RTCP_Channel_In*, ACE_Null_Mutex> iter (this->inputs_); 00556 iter = this->inputs_.begin(); 00557 00558 // first send an SR/RR 00559 RR_Block *blocks = 0; 00560 RR_Block *b_iter = 0; 00561 RR_Block *b_ptr = 0; 00562 00563 while (iter != this->inputs_.end() ) 00564 { 00565 if (!b_iter) 00566 { 00567 b_ptr = (*iter).int_id_->getRRBlock (); 00568 if (b_ptr) 00569 { 00570 blocks = b_ptr; 00571 b_iter = b_ptr; 00572 } 00573 } 00574 else 00575 { 00576 b_ptr = (*iter).int_id_->getRRBlock (); 00577 if (b_ptr) 00578 { 00579 b_iter->next_ = b_ptr; 00580 } 00581 } 00582 00583 iter++; 00584 } 00585 00586 if (b_iter) 00587 b_iter->next_ = 0; 00588 00589 if (this->output_.active ()) 00590 { 00591 // get the NTP timestamp 00592 ACE_Time_Value unix_now = ACE_OS::gettimeofday (); 00593 TAO_AV_RTCP::ntp64 ntp_now = ntp64time (unix_now); 00594 ACE_UINT32 rtp_ts = unix_now.sec () * 8000 + unix_now.usec () / 125 + 00595 this->timestamp_offset_; 00596 ACE_NEW_RETURN(cp, 00597 RTCP_SR_Packet (my_ssrc, 00598 ntp_now.upper, 00599 ntp_now.lower, 00600 rtp_ts, 00601 this->output_.packets_sent (), 00602 this->output_.octets_sent (), 00603 blocks), 00604 -1); 00605 } 00606 else 00607 { 00608 ACE_NEW_RETURN(cp, 00609 RTCP_RR_Packet (my_ssrc, 00610 blocks), 00611 -1); 00612 } 00613 00614 /* 00615 * We always send a cname plus one other sdes 00616 * There's a schedule for what we send sequenced by sdes_seq_: 00617 * - send 'email' every 0th & 4th packet 00618 * - send 'note' every 2nd packet 00619 * - send 'tool' every 6th packet 00620 * - send 'name' in all the odd slots 00621 * (if 'note' is not the empty string, we switch the roles 00622 * of name & note) 00623 */ 00624 00625 // TODO: need capability to change these settings 00626 switch (this->sdes_count_%8) 00627 { 00628 case 0: 00629 case 4: 00630 value = "tao-users@wustl.edu"; 00631 sdes_type = RTCP_SDES_EMAIL; 00632 break; 00633 case 2: 00634 if (note.length () > 0) 00635 { 00636 value = "Joe User"; 00637 sdes_type = RTCP_SDES_NAME; 00638 } 00639 else 00640 { 00641 value = "An important note..."; 00642 sdes_type = RTCP_SDES_NOTE; 00643 } 00644 break; 00645 case 6: 00646 value = "TAO A/V Service"; 00647 sdes_type = RTCP_SDES_TOOL; 00648 break; 00649 case 1: 00650 case 3: 00651 case 5: 00652 case 7: 00653 if (note.length () == 0) 00654 { 00655 value = "Joe User"; 00656 sdes_type = RTCP_SDES_NAME; 00657 } 00658 else 00659 { 00660 value = "An important note..."; 00661 sdes_type = RTCP_SDES_NOTE; 00662 } 00663 break; 00664 } 00665 00666 ++this->sdes_count_; 00667 00668 sdes.add_item (my_ssrc, 00669 RTCP_SDES_CNAME, 00670 static_cast<unsigned char> (ACE_OS::strlen(this->output_.cname())), 00671 this->output_.cname()); 00672 if (bye) 00673 { 00674 ssrc_list[0] = rtcp_prot_obj->ssrc (); 00675 00676 ACE_NEW_RETURN (bye_packet, 00677 RTCP_BYE_Packet(ssrc_list, 00678 sizeof(ssrc_list)/sizeof(ssrc_list[0]), 00679 "Got bored."), 00680 -1); 00681 } 00682 else 00683 { 00684 unsigned char length = (unsigned char)(value.length() & 0xFF); 00685 sdes.add_item (my_ssrc, sdes_type, length, value.c_str ()); 00686 } 00687 00688 // create the message block 00689 char *cp_ptr; 00690 char *sdes_ptr; 00691 char *bye_ptr = 0; 00692 ACE_UINT16 cp_length; 00693 ACE_UINT16 sdes_length; 00694 ACE_UINT16 bye_length = 0; 00695 cp->get_packet_data (&cp_ptr, cp_length); 00696 sdes.get_packet_data (&sdes_ptr, sdes_length); 00697 if (bye_packet) 00698 bye_packet->get_packet_data(&bye_ptr, bye_length); 00699 00700 ACE_Message_Block mb (cp_length + sdes_length + bye_length); 00701 00702 ACE_OS::memcpy (mb.wr_ptr (), cp_ptr, cp_length); 00703 mb.wr_ptr (cp_length); 00704 ACE_OS::memcpy (mb.wr_ptr (), sdes_ptr, sdes_length); 00705 mb.wr_ptr (sdes_length); 00706 if (bye_length) 00707 { 00708 ACE_OS::memcpy (mb.wr_ptr (), bye_ptr, bye_length); 00709 mb.wr_ptr (bye_length); 00710 } 00711 00712 // send the report 00713 this->protocol_object_->send_frame (&mb); 00714 00715 this->packet_size_ = cp_length + sdes_length + bye_length; 00716 00717 delete cp; 00718 if (bye_packet) 00719 delete bye_packet; 00720 00721 return 0; 00722 }
TAO_AV_RTP_State* TAO_AV_RTCP_Callback::state | ( | void | ) |
void TAO_AV_RTCP_Callback::ts_offset | ( | ACE_UINT32 | offset | ) |
Definition at line 811 of file RTCP.cpp.
References timestamp_offset_.
Referenced by TAO_AV_RTCP_Object::ts_offset().
00812 { 00813 this->timestamp_offset_ = offset; 00814 }
int TAO_AV_RTCP_Callback::avg_rtcp_size_ [protected] |
ACE_Hash_Map_Manager<ACE_UINT32, RTCP_Channel_In*, ACE_Null_Mutex> TAO_AV_RTCP_Callback::inputs_ [protected] |
Definition at line 181 of file RTCP.h.
Referenced by get_timeout(), receive_control_frame(), receive_frame(), and send_report().
int TAO_AV_RTCP_Callback::is_initial_timeout_ [protected] |
RTCP_Channel_Out TAO_AV_RTCP_Callback::output_ [protected] |
Definition at line 182 of file RTCP.h.
Referenced by send_frame(), send_report(), and TAO_AV_RTCP_Callback().
int TAO_AV_RTCP_Callback::packet_size_ [protected] |
int TAO_AV_RTCP_Callback::sdes_count_ [protected] |
int TAO_AV_RTCP_Callback::timeout_ [protected] |
int TAO_AV_RTCP_Callback::timestamp_offset_ [protected] |