📄 rtp.cpp
字号:
/*
* 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.
*/
// RTP.cpp,v 5.19 2003/11/04 05:21:31 dhinton Exp
#include "RTP.h"
#include "RTCP.h"
#include "Nil.h"
#include "tao/debug.h"
#include "ace/OS_NS_arpa_inet.h"
#include "ace/OS_NS_strings.h"
// RTP_Packet
// Constructor for RTP packets received
RTP_Packet::RTP_Packet(char* buffer, int length)
{
// skip the standard header info
int index = 12;
memcpy(this->packet_, buffer, length);
for (int j=0; j<(int)this->cc(); j++)
{
this->host_byte_order_csrc_list_[j] = ntohl(*(ACE_UINT32*)&buffer[index]);
index+=4;
}
// ignore the header extension if there is one
if (this->ext())
{
index+=2;
int extension_data_size = ntohs(*(ACE_UINT16*)&buffer[index]);
index+=2;
index+=extension_data_size;
this->extension_bytes_ = 4 + extension_data_size;
}
else
this->extension_bytes_ = 0;
this->packet_size_ = length;
this->payload_size_ = length-index;
// This is necessary only for payload types that have 16 bit values to correct
// the network byte ordering.
if ((this->pt() == RTP_PT_L16_OTHER) ||
(this->pt() == RTP_PT_L16_STEREO) ||
(this->pt() == RTP_PT_L16_MONO))
{
for (int i=0; i < payload_size_; i+=2)
{
*(ACE_UINT16*)&this->host_byte_order_payload_[i] = ntohs(*(ACE_UINT16*)&this->packet_[index]);
index+=2;
}
}
else
for (int i=0; i<this->payload_size_; i++)
{
this->host_byte_order_payload_[i] = this->packet_[index];
index++;
}
}
RTP_Packet::RTP_Packet(unsigned char padding,
unsigned char marker,
unsigned char payload_type,
ACE_UINT32 seq_num,
ACE_UINT32 timestamp,
ACE_UINT32 ssrc,
unsigned char csrc_count,
ACE_UINT32 *csrc_list,
char *data,
ACE_UINT16 data_size)
:extension_bytes_(0)
{
//size of header (in octets) without contributing sources
ACE_UINT16 size = 3*4;
int index = 0;
if (data_size > RTP_MTU-12)
{
data_size = RTP_MTU-12;
ACE_DEBUG ((LM_DEBUG, "\n(%N,%l) RTP_Packet: Warning - packet truncated\n"));
}
if (csrc_count > 15)
csrc_count = 15; // Only 15 contributing sources can be specified.
if (csrc_list != 0)
for (unsigned char i=0; i<csrc_count; i++)
{
size+=4;
this->host_byte_order_csrc_list_[i] = csrc_list[i];
}
this->packet_size_ = size + data_size;
index = 0;
this->packet_[index] = ((RTP_VERSION & 0x3) << 6) |
((padding & 0x1) << 5) |
((0 & 0x1) << 4) | // extension bit
((csrc_count & 0xf));
index++;
this->packet_[index] = ((marker & 0x1) << 7 ) |
((payload_type & 0x7f));
index++;
*((ACE_UINT16*)&this->packet_[index]) = (ACE_UINT16)htons(seq_num);
index+=2;
*((ACE_UINT32*)&this->packet_[index]) = (ACE_UINT32)htonl(timestamp);
index+=4;
*((ACE_UINT32*)&this->packet_[index]) = htonl(ssrc);
index+=4;
for (int i=0; i<csrc_count; i++)
{
*((ACE_UINT32*)&this->packet_[index]) = htonl(this->host_byte_order_csrc_list_[i]);
index+=4;
}
memcpy (this->host_byte_order_payload_, data, data_size);
this->payload_size_ = data_size;
// Correct byte ordering for multi-byte payload types.
if ((this->pt() == RTP_PT_L16_OTHER) ||
(this->pt() == RTP_PT_L16_STEREO) ||
(this->pt() == RTP_PT_L16_MONO))
{
for (int i=0; i<this->payload_size_; i+=2)
{
*(ACE_UINT16*)&this->packet_[index] = htons(*(ACE_UINT16*)&data[i]);
index+=2;
}
}
else
for (int i=0; i<this->payload_size_; i++)
{
this->packet_[index] = data[i];
index++;
}
}
RTP_Packet::~RTP_Packet(void)
{
}
ACE_UINT16
RTP_Packet::packet_size(void)
{
return this->packet_size_;
}
ACE_UINT16
RTP_Packet::payload_size(void)
{
return this->payload_size_;
}
unsigned int
RTP_Packet::ver (void)
{
return ( this->packet_[0] & 0xC0 ) >> 6;
}
unsigned int
RTP_Packet::pad (void)
{
return ( this->packet_[0] & 0x20 ) >> 5;
}
unsigned int
RTP_Packet::ext (void)
{
return ( this->packet_[0] & 0x10 ) >> 4;
}
unsigned int
RTP_Packet::cc (void)
{
return ( this->packet_[0] & 0x0F ) ;
}
unsigned int
RTP_Packet::mrk (void)
{
return ( this->packet_[1] & 0x80 ) >> 7;
}
unsigned int
RTP_Packet::pt (void)
{
return ( this->packet_[1] & 0x7F ) ;
}
ACE_UINT16
RTP_Packet::sn (void)
{
return ntohs(*(ACE_UINT16*)(&this->packet_[2])) ;
}
ACE_UINT32
RTP_Packet::ts (void)
{
return ntohl(*(ACE_UINT32*)(&this->packet_[4])) ;
}
ACE_UINT32
RTP_Packet::ssrc (void)
{
return ntohl(*(ACE_UINT32*)(&this->packet_[8])) ;
}
unsigned int
RTP_Packet::ext_bytes (void)
{
return this->extension_bytes_;
}
void
RTP_Packet::get_frame_info (TAO_AV_frame_info *frame_info)
{
frame_info->timestamp = this->mrk();
frame_info->timestamp = this->ts();
frame_info->ssrc = this->ssrc();
frame_info->sequence_num = this->sn();
frame_info->format = this->pt();
}
int
RTP_Packet::is_valid (void)
{
// taken from RFC 1889 - Appendix A.1
// make sure the RTP version is correct
if (this->ver() != RTP_VERSION)
return 0;
// make sure the payload type is not SR or RR
if ((this->pt() == RTCP_PT_SR) || (this->pt() == RTCP_PT_RR))
return 0;
// if the p bit is set, the last octet of the packet must contain a valid
// octet count, in particular, less than the total packet length minus
// the header size.
if (this->pad() != 0)
if ((unsigned int)this->packet_[this->packet_size_] >=
(this->packet_size_ - (12 + this->cc() + this->extension_bytes_)))
return 0;
// If there is an extension, it is ignored (taken care of in constructor)
// The length of the packet must be consistent with CC and payload type (if
// payloads have a known length)
return 1;
}
void
RTP_Packet::get_csrc_list (ACE_UINT32 **csrc_list, ACE_UINT16 &length)
{
*csrc_list = this->host_byte_order_csrc_list_;
length = this->cc ();
}
void
RTP_Packet::get_payload (char **payload, ACE_UINT16 &length)
{
*payload = this->host_byte_order_payload_ ;
length = this->payload_size_;
}
void
RTP_Packet::get_packet_data (char **packet, ACE_UINT16 &length)
{
*packet = this->packet_;
length = this->packet_size_;
}
// TAO_AV_RTP_Object
int
TAO_AV_RTP_Object::handle_input (void)
{
TAO_AV_frame_info frame_info;
if (TAO_debug_level > 1)
ACE_DEBUG ((LM_DEBUG,
"\nTAO_AV_RTP_Object::handle_input\n"));
// Handles the incoming RTP packet input.
this->frame_.rd_ptr (this->frame_.base ());
int n = this->transport_->recv (this->frame_.rd_ptr (),
this->frame_.size ());
if (n == 0)
ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:connection closed\n"),-1);
if (n < 0)
{
if ((errno == EADDRNOTAVAIL) || (errno == ECONNRESET))
{
this->connection_gone_ = 1;
return -1;
}
else
ACE_ERROR_RETURN ( (LM_ERROR,"TAO_AV_RTP::handle_input:recv error\n"),-1);
}
this->frame_.wr_ptr (this->frame_.rd_ptr () + n);
ACE_Addr *addr = this->transport_->get_peer_addr ();
if(this->control_object_)
this->control_object_->handle_control_input (&this->frame_, *addr);
// Get payload that has been converted to host byte order
char *data_ptr;
ACE_UINT16 length;
RTP_Packet rtp_packet(this->frame_.rd_ptr (),
ACE_static_cast (int, this->frame_.length ()));
rtp_packet.get_frame_info (&frame_info);
rtp_packet.get_payload(&data_ptr, length);
this->frame_.rd_ptr (this->frame_.base ());
memcpy (this->frame_.rd_ptr (), data_ptr, length);
this->frame_.wr_ptr (this->frame_.rd_ptr() + length);
this->callback_->receive_frame (&this->frame_, &frame_info, *addr);
return 0;
}
int
TAO_AV_RTP_Object::send_frame (ACE_Message_Block *frame,
TAO_AV_frame_info *frame_info)
{
// ACE_Addr *addr = this->transport_->get_peer_addr ();
if (this->connection_gone_)
{
errno = ECONNRESET;
return -1;
}
int result = -1;
RTP_Packet *rtp_packet;
ACE_UINT32 csrc_count = 0; // Assume for now no mixers/translators
ACE_UINT32 *csrc_list = 0;
if (frame_info != 0)
{
if (frame_info->format != this->format_)
ACE_DEBUG ((LM_DEBUG,
"TAO_AV_RTP_Object::send_frame - error: format type mismatch"));
if (frame_info->ssrc != 0)
this->ssrc_ = frame_info->ssrc;
TAO_AV_RTCP_Object *rtcp_prot_obj = ACE_dynamic_cast (TAO_AV_RTCP_Object*,
this->control_object_);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -