00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "orbsvcs/AV/RTP.h"
00038 #include "orbsvcs/AV/RTCP.h"
00039
00040 #include "tao/debug.h"
00041 #include "ace/OS_NS_arpa_inet.h"
00042 #include "ace/OS_NS_strings.h"
00043
00044 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00045
00046
00047
00048
00049 RTP_Packet::RTP_Packet(char* buffer, int length)
00050 {
00051
00052 int index = 12;
00053
00054 ACE_OS::memcpy(this->packet_, buffer, length);
00055
00056 for (int j=0; j<(int)this->cc(); j++)
00057 {
00058 this->host_byte_order_csrc_list_[j] = ntohl(*(ACE_UINT32*)&buffer[index]);
00059 index+=4;
00060 }
00061
00062
00063 if (this->ext())
00064 {
00065 index+=2;
00066 int extension_data_size = ntohs(*(ACE_UINT16*)&buffer[index]);
00067 index+=2;
00068 index+=extension_data_size;
00069
00070 this->extension_bytes_ = 4 + extension_data_size;
00071 }
00072 else
00073 this->extension_bytes_ = 0;
00074
00075 this->packet_size_ = static_cast<ACE_UINT16> (length);
00076 this->payload_size_ = static_cast<ACE_UINT16> (length-index);
00077
00078
00079
00080 if ((this->pt() == RTP_PT_L16_OTHER) ||
00081 (this->pt() == RTP_PT_L16_STEREO) ||
00082 (this->pt() == RTP_PT_L16_MONO))
00083 {
00084 for (int i=0; i < payload_size_; i+=2)
00085 {
00086 *(ACE_UINT16*)&this->host_byte_order_payload_[i] = ntohs(*(ACE_UINT16*)&this->packet_[index]);
00087 index+=2;
00088 }
00089 }
00090 else
00091 for (int i=0; i<this->payload_size_; i++)
00092 {
00093 this->host_byte_order_payload_[i] = this->packet_[index];
00094 index++;
00095 }
00096 }
00097
00098 RTP_Packet::RTP_Packet(unsigned char padding,
00099 unsigned char marker,
00100 unsigned char payload_type,
00101 ACE_UINT32 seq_num,
00102 ACE_UINT32 timestamp,
00103 ACE_UINT32 ssrc,
00104 unsigned char csrc_count,
00105 ACE_UINT32 *csrc_list,
00106 char *data,
00107 ACE_UINT16 data_size)
00108 :extension_bytes_(0)
00109 {
00110
00111 ACE_UINT16 size = 3*4;
00112 int index = 0;
00113
00114 if (data_size > RTP_MTU-12)
00115 {
00116 data_size = RTP_MTU-12;
00117 ACE_DEBUG ((LM_DEBUG, "\n(%N,%l) RTP_Packet: Warning - packet truncated\n"));
00118 }
00119
00120 if (csrc_count > 15)
00121 csrc_count = 15;
00122
00123 if (csrc_list != 0)
00124 for (unsigned char i=0; i<csrc_count; i++)
00125 {
00126 size+=4;
00127 this->host_byte_order_csrc_list_[i] = csrc_list[i];
00128 }
00129
00130 this->packet_size_ = size + data_size;
00131
00132 index = 0;
00133 this->packet_[index] = ((RTP_VERSION & 0x3) << 6) |
00134 ((padding & 0x1) << 5) |
00135 ((0 & 0x1) << 4) |
00136 ((csrc_count & 0xf));
00137
00138 index++;
00139 this->packet_[index] = ((marker & 0x1) << 7 ) |
00140 ((payload_type & 0x7f));
00141 index++;
00142 *((ACE_UINT16*)&this->packet_[index]) = (ACE_UINT16)htons(static_cast<u_short> (seq_num));
00143 index+=2;
00144 *((ACE_UINT32*)&this->packet_[index]) = (ACE_UINT32)htonl(timestamp);
00145 index+=4;
00146 *((ACE_UINT32*)&this->packet_[index]) = htonl(ssrc);
00147 index+=4;
00148
00149 for (int i=0; i<csrc_count; i++)
00150 {
00151 *((ACE_UINT32*)&this->packet_[index]) = htonl(this->host_byte_order_csrc_list_[i]);
00152 index+=4;
00153 }
00154
00155 ACE_OS::memcpy (this->host_byte_order_payload_, data, data_size);
00156
00157 this->payload_size_ = data_size;
00158
00159
00160 if ((this->pt() == RTP_PT_L16_OTHER) ||
00161 (this->pt() == RTP_PT_L16_STEREO) ||
00162 (this->pt() == RTP_PT_L16_MONO))
00163 {
00164 for (int i=0; i<this->payload_size_; i+=2)
00165 {
00166 *(ACE_UINT16*)&this->packet_[index] = htons(*(ACE_UINT16*)&data[i]);
00167 index+=2;
00168 }
00169 }
00170 else
00171 for (int i=0; i<this->payload_size_; i++)
00172 {
00173 this->packet_[index] = data[i];
00174 index++;
00175 }
00176 }
00177
00178 RTP_Packet::~RTP_Packet(void)
00179 {
00180 }
00181
00182 ACE_UINT16
00183 RTP_Packet::packet_size(void)
00184 {
00185 return this->packet_size_;
00186 }
00187
00188 ACE_UINT16
00189 RTP_Packet::payload_size(void)
00190 {
00191 return this->payload_size_;
00192 }
00193
00194 unsigned int
00195 RTP_Packet::ver (void)
00196 {
00197 return ( this->packet_[0] & 0xC0 ) >> 6;
00198 }
00199
00200 unsigned int
00201 RTP_Packet::pad (void)
00202 {
00203 return ( this->packet_[0] & 0x20 ) >> 5;
00204 }
00205
00206 unsigned int
00207 RTP_Packet::ext (void)
00208 {
00209 return ( this->packet_[0] & 0x10 ) >> 4;
00210 }
00211
00212 unsigned int
00213 RTP_Packet::cc (void)
00214 {
00215 return ( this->packet_[0] & 0x0F ) ;
00216 }
00217
00218 unsigned int
00219 RTP_Packet::mrk (void)
00220 {
00221 return ( this->packet_[1] & 0x80 ) >> 7;
00222 }
00223
00224 unsigned int
00225 RTP_Packet::pt (void)
00226 {
00227 return ( this->packet_[1] & 0x7F ) ;
00228 }
00229
00230 ACE_UINT16
00231 RTP_Packet::sn (void)
00232 {
00233 return ntohs(*(ACE_UINT16*)(&this->packet_[2])) ;
00234 }
00235
00236 ACE_UINT32
00237 RTP_Packet::ts (void)
00238 {
00239 return ntohl(*(ACE_UINT32*)(&this->packet_[4])) ;
00240 }
00241
00242 ACE_UINT32
00243 RTP_Packet::ssrc (void)
00244 {
00245 return ntohl(*(ACE_UINT32*)(&this->packet_[8])) ;
00246 }
00247
00248 unsigned int
00249 RTP_Packet::ext_bytes (void)
00250 {
00251 return this->extension_bytes_;
00252 }
00253
00254 void
00255 RTP_Packet::get_frame_info (TAO_AV_frame_info *frame_info)
00256 {
00257 frame_info->timestamp = this->mrk();
00258 frame_info->timestamp = this->ts();
00259 frame_info->ssrc = this->ssrc();
00260 frame_info->sequence_num = this->sn();
00261 frame_info->format = static_cast<CORBA::Octet> (this->pt());
00262 }
00263
00264 int
00265 RTP_Packet::is_valid (void)
00266 {
00267
00268
00269
00270 if (this->ver() != RTP_VERSION)
00271 return 0;
00272
00273
00274 if ((this->pt() == RTCP_PT_SR) || (this->pt() == RTCP_PT_RR))
00275 return 0;
00276
00277
00278
00279
00280 if (this->pad() != 0)
00281 if ((unsigned int)this->packet_[this->packet_size_] >=
00282 (this->packet_size_ - (12 + this->cc() + this->extension_bytes_)))
00283 return 0;
00284
00285
00286
00287
00288
00289
00290 return 1;
00291 }
00292
00293 void
00294 RTP_Packet::get_csrc_list (ACE_UINT32 **csrc_list, ACE_UINT16 &length)
00295 {
00296 *csrc_list = this->host_byte_order_csrc_list_;
00297 length = static_cast<ACE_UINT16> (this->cc ());
00298 }
00299
00300 void
00301 RTP_Packet::get_payload (char **payload, ACE_UINT16 &length)
00302 {
00303 *payload = this->host_byte_order_payload_ ;
00304 length = this->payload_size_;
00305 }
00306
00307 void
00308 RTP_Packet::get_packet_data (char **packet, ACE_UINT16 &length)
00309 {
00310 *packet = this->packet_;
00311 length = this->packet_size_;
00312 }
00313
00314
00315
00316
00317 int
00318 TAO_AV_RTP_Object::handle_input (void)
00319 {
00320 TAO_AV_frame_info frame_info;
00321
00322 if (TAO_debug_level > 1)
00323 ACE_DEBUG ((LM_DEBUG,
00324 "\nTAO_AV_RTP_Object::handle_input\n"));
00325
00326
00327 this->frame_.rd_ptr (this->frame_.base ());
00328
00329 int n = this->transport_->recv (this->frame_.rd_ptr (),
00330 this->frame_.size ());
00331 if (n == 0)
00332 ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:connection closed\n"),-1);
00333 if (n < 0)
00334 {
00335 if ((errno == EADDRNOTAVAIL) || (errno == ECONNRESET))
00336 {
00337 this->connection_gone_ = 1;
00338 return -1;
00339 }
00340 else
00341 ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:recv error\n"),-1);
00342 }
00343
00344 this->frame_.wr_ptr (this->frame_.rd_ptr () + n);
00345 ACE_Addr *addr = this->transport_->get_peer_addr ();
00346
00347 if(this->control_object_)
00348 this->control_object_->handle_control_input (&this->frame_, *addr);
00349
00350
00351 char *data_ptr;
00352 ACE_UINT16 length;
00353 RTP_Packet rtp_packet(this->frame_.rd_ptr (),
00354 static_cast<int> (this->frame_.length ()));
00355
00356 rtp_packet.get_frame_info (&frame_info);
00357 rtp_packet.get_payload(&data_ptr, length);
00358
00359 this->frame_.rd_ptr (this->frame_.base ());
00360 ACE_OS::memcpy (this->frame_.rd_ptr (), data_ptr, length);
00361 this->frame_.wr_ptr (this->frame_.rd_ptr() + length);
00362
00363 this->callback_->receive_frame (&this->frame_, &frame_info, *addr);
00364
00365 return 0;
00366 }
00367
00368 int
00369 TAO_AV_RTP_Object::send_frame (ACE_Message_Block *frame,
00370 TAO_AV_frame_info *frame_info)
00371 {
00372
00373
00374 if (this->connection_gone_)
00375 {
00376 errno = ECONNRESET;
00377 return -1;
00378 }
00379
00380 int result = -1;
00381 RTP_Packet *rtp_packet;
00382 ACE_UINT32 csrc_count = 0;
00383 ACE_UINT32 *csrc_list = 0;
00384
00385 if (frame_info != 0)
00386 {
00387 if (frame_info->format != this->format_)
00388 ACE_DEBUG ((LM_DEBUG,
00389 "TAO_AV_RTP_Object::send_frame - error: format type mismatch"));
00390 if (frame_info->ssrc != 0)
00391 this->ssrc_ = frame_info->ssrc;
00392
00393 TAO_AV_RTCP_Object *rtcp_prot_obj = dynamic_cast<TAO_AV_RTCP_Object*> (this->control_object_);
00394
00395
00396 rtcp_prot_obj->ssrc(this->ssrc_);
00397
00398 ACE_NEW_RETURN (rtp_packet,
00399 RTP_Packet (0,
00400 frame_info->boundary_marker,
00401 static_cast<unsigned char> (this->format_),
00402 frame_info->sequence_num,
00403 frame_info->timestamp,
00404 this->ssrc_,
00405 static_cast<unsigned char> (csrc_count),
00406 csrc_list,
00407 frame->rd_ptr (),
00408 (ACE_UINT16)frame->length ()),
00409 -1);
00410
00411 frame_info->sequence_num ++;
00412 }
00413 else
00414 {
00415
00416
00417
00418
00419
00420
00421
00422 unsigned int samples_per_sec;
00423 double samples_per_usec;
00424
00425 switch (this->format_)
00426 {
00427 case RTP_PT_PCMU:
00428 case RTP_PT_CELP:
00429 case RTP_PT_G721:
00430 case RTP_PT_GSM:
00431 case RTP_PT_DVI:
00432 case RTP_PT_LPC:
00433 case RTP_PT_PCMA:
00434 case RTP_PT_G722:
00435 samples_per_sec = 8000;
00436 break;
00437 case RTP_PT_L16_STEREO:
00438 case RTP_PT_L16_MONO:
00439 samples_per_sec = 44100;
00440 break;
00441 default:
00442 samples_per_sec = 1000000;
00443 };
00444
00445 samples_per_usec = samples_per_sec/1000000.0;
00446
00447 ACE_Time_Value now = ACE_OS::gettimeofday();
00448
00449 ACE_UINT32 ts = (ACE_UINT32)
00450 (now.sec () * samples_per_sec +
00451 ((double)now.usec () * samples_per_usec) +
00452 this->timestamp_offset_);
00453
00454 ACE_NEW_RETURN (rtp_packet,
00455 RTP_Packet (0,
00456 0,
00457 static_cast<unsigned char> (this->format_),
00458 this->sequence_num_,
00459 ts,
00460 this->ssrc_,
00461 static_cast<unsigned char> (csrc_count),
00462 csrc_list,
00463 frame->rd_ptr (),
00464 (ACE_UINT16)frame->length ()),
00465 -1);
00466
00467 this->sequence_num_ ++;
00468 }
00469
00470 char *data_ptr;
00471 ACE_UINT16 data_length;
00472 rtp_packet->get_packet_data (&data_ptr, data_length);
00473
00474 ACE_Message_Block mb (data_ptr, data_length);
00475 mb.wr_ptr (data_length);
00476
00477 result = this->transport_->send (&mb);
00478 if (result < 0)
00479 ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::send_frame failed\n"),result);
00480
00481 TAO_AV_RTCP_Object *rtcp_prot_obj = dynamic_cast<TAO_AV_RTCP_Object*> (this->control_object_);
00482 if (rtcp_prot_obj)
00483 rtcp_prot_obj->handle_control_output (&mb);
00484
00485 delete rtp_packet;
00486
00487 return 0;
00488 }
00489
00490 int
00491 TAO_AV_RTP_Object::send_frame (const iovec *iov,
00492 int iovcnt,
00493 TAO_AV_frame_info *frame_info)
00494 {
00495 int result = -1;
00496 RTP_Packet *rtp_packet = 0;
00497 ACE_UINT32 csrc_count = 0;
00498 ACE_UINT32 *csrc_list = 0;
00499
00500 if (this->connection_gone_)
00501 {
00502 errno = ECONNRESET;
00503 return -1;
00504 }
00505
00506 if (frame_info != 0)
00507 {
00508 if (frame_info->format != this->format_)
00509 ACE_DEBUG ((LM_DEBUG,
00510 "TAO_AV_RTP_Object::send_frame - error: format type mismatch"));
00511 this->sequence_num_ = static_cast<ACE_UINT16> (frame_info->sequence_num);
00512 if (frame_info->ssrc != 0)
00513 this->ssrc_ = frame_info->ssrc;
00514
00515 TAO_AV_RTCP_Object *rtcp_prot_obj = dynamic_cast<TAO_AV_RTCP_Object*> (this->control_object_);
00516
00517
00518 rtcp_prot_obj->ssrc(this->ssrc_);
00519 ACE_UINT16 data_size = static_cast<ACE_UINT16> (iov[0].iov_len);
00520
00521 ACE_NEW_RETURN (rtp_packet,
00522 RTP_Packet (0,
00523 frame_info->boundary_marker,
00524 static_cast<unsigned char> (this->format_),
00525 frame_info->sequence_num,
00526 frame_info->timestamp,
00527 this->ssrc_,
00528 static_cast<unsigned char> (csrc_count),
00529 csrc_list,
00530 (char *)iov[0].iov_base,
00531 data_size),
00532 -1);
00533
00534 frame_info->sequence_num ++;
00535 }
00536 else
00537 {
00538
00539
00540
00541
00542
00543
00544
00545
00546 unsigned int samples_per_sec;
00547 double samples_per_usec;
00548
00549 switch (this->format_)
00550 {
00551 case RTP_PT_PCMU:
00552 case RTP_PT_CELP:
00553 case RTP_PT_G721:
00554 case RTP_PT_GSM:
00555 case RTP_PT_DVI:
00556 case RTP_PT_LPC:
00557 case RTP_PT_PCMA:
00558 case RTP_PT_G722:
00559 samples_per_sec = 8000;
00560 break;
00561 case RTP_PT_L16_STEREO:
00562 case RTP_PT_L16_MONO:
00563 samples_per_sec = 44100;
00564 break;
00565 default:
00566 samples_per_sec = 1000000;
00567 };
00568
00569 samples_per_usec = samples_per_sec/1000000.0;
00570
00571 ACE_Time_Value now = ACE_OS::gettimeofday();
00572
00573 ACE_UINT32 ts = (ACE_UINT32)
00574 (now.sec () * samples_per_sec +
00575 ((double)now.usec () * samples_per_usec) +
00576 this->timestamp_offset_);
00577 ACE_UINT16 data_size = static_cast<ACE_UINT16> (iov[0].iov_len);
00578
00579 ACE_NEW_RETURN (rtp_packet,
00580 RTP_Packet (0,
00581 0,
00582 static_cast<unsigned char> (this->format_),
00583 this->sequence_num_,
00584 ts,
00585 this->ssrc_,
00586 static_cast<unsigned char> (csrc_count),
00587 csrc_list,
00588 (char *)iov[0].iov_base,
00589 data_size),
00590 -1);
00591
00592 this->sequence_num_ ++;
00593 }
00594
00595 char *data_ptr;
00596 ACE_UINT16 data_length;
00597 rtp_packet->get_packet_data (&data_ptr, data_length);
00598
00599 iovec send_iov[ACE_IOV_MAX];
00600 send_iov [0].iov_base = data_ptr;
00601 send_iov [0].iov_len = data_length;
00602 for (int i=1;i<iovcnt; i++)
00603 send_iov [i] = iov [i];
00604 result = this->transport_->send (send_iov, iovcnt);
00605
00606 delete rtp_packet;
00607
00608 if (result < 0)
00609 ACE_ERROR_RETURN ((LM_ERROR,"TAO_AV_RTP::send_frame failed\n"),result);
00610
00611 return 0;
00612 }
00613
00614 int
00615 TAO_AV_RTP_Object::send_frame (const char*,
00616 size_t)
00617 {
00618 return 0;
00619 }
00620
00621
00622 TAO_AV_RTP_Object::TAO_AV_RTP_Object (TAO_AV_Callback *callback,
00623 TAO_AV_Transport *transport)
00624 :TAO_AV_Protocol_Object (callback,transport),
00625 control_object_ (0),
00626 connection_gone_ (0)
00627 {
00628 this->sequence_num_ = static_cast<ACE_UINT16> (ACE_OS::rand ());
00629 this->timestamp_offset_ = ACE_OS::rand ();
00630
00631 char buf [BUFSIZ];
00632 int result = ACE_OS::hostname (buf, BUFSIZ);
00633 unsigned long ipaddr = 0;
00634 if (result == 0)
00635 ipaddr = ACE_OS::inet_addr (buf);
00636 this->ssrc_ = TAO_AV_RTCP::alloc_srcid (ipaddr);
00637
00638 this->frame_.size (2 * this->transport_->mtu ());
00639 }
00640
00641 TAO_AV_RTP_Object::~TAO_AV_RTP_Object (void)
00642 {
00643 }
00644
00645 int
00646 TAO_AV_RTP_Object::destroy (void)
00647 {
00648 if(this->control_object_)
00649 this->control_object_->destroy ();
00650
00651 this->callback_->handle_destroy ();
00652 delete this;
00653
00654 return 0;
00655 }
00656
00657 int
00658 TAO_AV_RTP_Object::set_policies (const TAO_AV_PolicyList &policy_list)
00659 {
00660 this->policy_list_ = policy_list;
00661 CORBA::ULong const num_policies = this->policy_list_.length ();
00662 TAO_AV_Policy *policy = 0;
00663
00664 for (u_int i=0; i< num_policies;i++)
00665 {
00666 policy = this->policy_list_ [i];
00667 switch (policy->type ())
00668 {
00669 case TAO_AV_PAYLOAD_TYPE_POLICY:
00670 {
00671 TAO_AV_Payload_Type_Policy *payload_policy =
00672 static_cast<TAO_AV_Payload_Type_Policy *> (policy);
00673 if (payload_policy == 0)
00674 ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP_Object::send_frame:Payload policy not defined\n"),-1);
00675 this->format_ = payload_policy->value ();
00676 }
00677 break;
00678 case TAO_AV_SSRC_POLICY:
00679 {
00680 TAO_AV_SSRC_Policy *ssrc_policy =
00681 static_cast<TAO_AV_SSRC_Policy *> (policy);
00682 if (ssrc_policy == 0)
00683 ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP_Object::send_frame:SSRC policy not defined\n"),-1);
00684 this->ssrc_ = ssrc_policy->value ();;
00685 }
00686 break;
00687 default:
00688 break;
00689 }
00690 }
00691
00692 return 0;
00693 }
00694
00695 void
00696 TAO_AV_RTP_Object::control_object (TAO_AV_Protocol_Object *object)
00697 {
00698 this->control_object_ = object;
00699 TAO_AV_RTCP_Object *rtcp_prot_obj = dynamic_cast<TAO_AV_RTCP_Object*> (this->control_object_);
00700 rtcp_prot_obj->ssrc (this->ssrc_);
00701 rtcp_prot_obj->ts_offset (this->timestamp_offset_);
00702 }
00703
00704 int
00705 TAO_AV_RTP_Object::start (void)
00706 {
00707 this->control_object_->start ();
00708 return this->callback_->handle_start ();
00709 }
00710
00711 int
00712 TAO_AV_RTP_Object::stop (void)
00713 {
00714 this->control_object_->stop ();
00715 return this->callback_->handle_stop ();
00716 }
00717
00718
00719 TAO_AV_RTP_Flow_Factory::TAO_AV_RTP_Flow_Factory (void)
00720 {
00721 }
00722
00723 TAO_AV_RTP_Flow_Factory::~TAO_AV_RTP_Flow_Factory (void)
00724 {
00725 }
00726
00727 int
00728 TAO_AV_RTP_Flow_Factory::init (int ,
00729 char * [])
00730 {
00731 return 0;
00732 }
00733
00734 TAO_AV_Protocol_Object*
00735 TAO_AV_RTP_Flow_Factory::make_protocol_object (TAO_FlowSpec_Entry *entry,
00736 TAO_Base_StreamEndPoint *endpoint,
00737 TAO_AV_Flow_Handler *handler,
00738 TAO_AV_Transport *transport)
00739 {
00740 TAO_AV_Callback *callback = 0;
00741
00742 if( endpoint->get_callback (entry->flowname (), callback) ) {
00743 ACE_ERROR_RETURN ((LM_ERROR, "(%N,%l) Invalid callback\n"), 0);
00744 }
00745
00746 TAO_AV_Protocol_Object *object = 0;
00747 ACE_NEW_RETURN (object,
00748 TAO_AV_RTP_Object (callback,
00749 transport),
00750 0);
00751 callback->open (object,
00752 handler);
00753 endpoint->set_protocol_object (entry->flowname (),
00754 object);
00755
00756 endpoint->protocol_object_set ();
00757 return object;
00758 }
00759
00760 int
00761 TAO_AV_RTP_Flow_Factory::match_protocol (const char *flow_string)
00762 {
00763 if (ACE_OS::strncasecmp (flow_string,"RTP",3) == 0)
00764 {
00765 return 1;
00766 }
00767 return 0;
00768 }
00769
00770 const char *
00771 TAO_AV_RTP_Flow_Factory::control_flow_factory (void)
00772 {
00773 return "RTCP";
00774 }
00775
00776 TAO_END_VERSIONED_NAMESPACE_DECL
00777
00778 ACE_FACTORY_DEFINE (TAO_AV, TAO_AV_RTP_Flow_Factory)
00779 ACE_STATIC_SVC_DEFINE (TAO_AV_RTP_Flow_Factory,
00780 ACE_TEXT ("RTP_Flow_Factory"),
00781 ACE_SVC_OBJ_T,
00782 &ACE_SVC_NAME (TAO_AV_RTP_Flow_Factory),
00783 ACE_Service_Type::DELETE_THIS |
00784 ACE_Service_Type::DELETE_OBJ,
00785 0)