一 头文件分析
从例子源码rtpsend.c看,主要的初始话步骤是:
ortp_init();
ortp_scheduler_init();
session=rtp_session_new(RTP_SESSION_SENDONLY);
这三步中涉及到了主要的结构体,具体如下:
1.1 ortp_init()涉及_RtpProfile和rtp_stats
void ortp_init()
{
static bool_t initialized=FALSE;
if (initialized) return;
initialized=TRUE;
#ifdef WIN32
win32_init_sockets();
#endif
av_profile_init(&av_profile);
ortp_global_stats_reset();//重置rtp_stats结构
init_random_number_generator();
ortp_message("oRTP-" ORTP_VERSION " initialized.");
}
主要涉及结构体:RtpProfile av_profile; RtpProfile在payloadtype.h中
/**
* The RTP profile is a table RTP_PROFILE_MAX_PAYLOADS entries to make the matching
* between RTP payload type number and the PayloadType that defines the type of
* media.
**/
/*这个结构是用于将RTP负载类型数字与具体的负载类型定义关联
例如,
rtp_profile_set_payload(&av_profile, 96, &payload_type_h264);
rtp_session_set_payload_type(session, 96);
就是将96与h264关联起来
*/
struct _RtpProfile
{
char *name;
PayloadType *payload[RTP_PROFILE_MAX_PAYLOADS];
};
ortp_global_stats_reset()涉及的结构体如下
typedef struct rtp_stats
{
uint64_t packet_sent;
/*发送的byte数*/
uint64_t sent; /* bytes sent */
/*接收到并及时发送给应用程序的负载的byte数,就是在ortp_global_stats_display()中显示的:
ortp-message- number of rtp bytes received=1500 bytes
ortp-message- number of incoming rtp bytes successfully delivered to the application=1400
即有部分数据没有发送给应用程序,我在开始做h264的收发时,上两个数目经常不一样,是我主要想搞清楚的地方.
*/
uint64_t recv; /* bytes of payload received and delivered in time to the application */
/*接收的负载byte数*/
uint64_t hw_recv; /* bytes of payload received */
/*接收的包的数目*/
uint64_t packet_recv; /* number of packets received */
/*当被查询时无法获得的包*/
uint64_t unavaillable; /* packets not availlable when they were queried */
/*接收太迟的包的数目*/
uint64_t outoftime; /* number of packets that were received too late */
/*累积丢失的包*/
uint64_t cum_packet_loss; /* cumulative number of packet lost */
/*接收到的看起来不像是RTP的东西*/
uint64_t bad; /* packets that did not appear to be RTP */
/*由于队列满而被丢弃的包的数目*/
uint64_t discarded; /* incoming packets discarded because the queue exceeds its max size */
} rtp_stats_t;
主要用于ortp对整个RTP过程的全局数据的统计,例如在源码中使用 ortp_global_stats_display() 就可以显示如下:
ortp-message-oRTP-stats:
Global statistics :
ortp-message- number of rtp packet sent=1430
ortp-message- number of rtp bytes sent=1687484 bytes
ortp-message- number of rtp packet received=0
ortp-message- number of rtp bytes received=0 bytes
ortp-message- number of incoming rtp bytes successfully delivered to the application=0
ortp-message- number of times the application queried a packet that didn't exist=0
ortp-message- number of rtp packet lost=0
ortp-message- number of rtp packets received too late=0
ortp-message- number of bad formatted rtp packets=0
ortp-message- number of packet discarded because of queue overflow=0
*/
1.2 ortp_scheduler_init()涉及RtpScheduler
ortp_scheduler_init(),对全局变量RtpScheduler *__ortp_scheduler初始化,RtpScheduler管理多个session的调度和收发的控制。
struct _RtpScheduler {
/* 以下部分设置的可能是想实现对session进行select管理*/
/*管理的session的列表*/
RtpSession *list; /* list of scheduled sessions*/
/*被管理session的标志*/
SessionSet all_sessions; /* mask of scheduled sessions */
/*所有标志中最高的位置*/
int all_max; /* the highest pos in the all mask */
/*有接收事件的session*/
SessionSet r_sessions; /* mask of sessions that have a recv event */
int r_max;
/*有发送事件的session*/
SessionSet w_sessions; /* mask of sessions that have a send event */
int w_max;
/*有错误事件的session*/
SessionSet e_sessions; /* mask of session that have error event */
int e_max;
int max_sessions; /* the number of position in the masks */
/* GMutex *unblock_select_mutex; */
ortp_cond_t unblock_select_cond;
ortp_mutex_t lock;
ortp_thread_t thread;
int thread_running;
struct _RtpTimer *timer;
/*从线程开始经过的毫秒*/
uint32_t time_; /*number of miliseconds elapsed since the start of the thread */
uint32_t timer_inc; /* the timer increment in milisec */
};
typedef struct _RtpScheduler RtpScheduler;
1.3 rtp_session_new(RTP_SESSION_SENDONLY)涉及_RtpSession
rtp_session_new创建一个新的rtp会话,对其初始化,首先设置好最大队列数和模式,判断读写模式,根据模式设置flag,设置随机数random,设置源的描述,信号的设置,互斥锁的设置,设置send payload和receive payload type,设置jitter(见),设置最大接受单元等等。。Session是在实际编程中最常操作的结构,如rtp_session_*主要都是对session的操作,具体结构解释如下:
/**
* An object representing a bi-directional RTP session.
* It holds sockets, jitter buffer, various counters (timestamp, sequence numbers...)
* Applications SHOULD NOT try to read things within the RtpSession object but use
* instead its public API (the rtp_session_* methods) where RtpSession is used as a
* pointer.
* rtp_session_new() allocates and initialize a RtpSession.
**/
struct _RtpSession
{
RtpSession *next; /* next RtpSession, when the session are enqueued by the scheduler */
int mask_pos; /* the position in the scheduler mask of RtpSession : do not move this field: it is part of the ABI since the session_set macros use it*/
struct {
RtpProfile *profile;
int pt;
unsigned int ssrc;
WaitPoint wp;
int telephone_events_pt; /* the payload type used for telephony events */
} snd,rcv;
unsigned int inc_ssrc_candidate;
int inc_same_ssrc_count;
int hw_recv_pt; /* recv payload type before jitter buffer */
int recv_buf_size;
RtpSignalTable on_ssrc_changed;
RtpSignalTable on_payload_type_changed;
RtpSignalTable on_telephone_event_packet;
RtpSignalTable on_telephone_event;
RtpSignalTable on_timestamp_jump;
RtpSignalTable on_network_error;
RtpSignalTable on_rtcp_bye;
struct _OList *signal_tables;
struct _OList *eventqs;
msgb_allocator_t allocator;
RtpStream rtp;
RtcpStream rtcp;
RtpSessionMode mode;
struct _RtpScheduler *sched;
uint32_t flags;
int dscp;
int multicast_ttl;
int multicast_loopback;
void * user_data;
/* FIXME: Should be a table for all session participants. */
struct timeval last_recv_time; /* Time of receiving the RTP/RTCP packet. */
mblk_t *pending;
/* telephony events extension */
mblk_t *current_tev; /* the pending telephony events */
mblk_t *sd;
queue_t contributing_sources;
bool_t symmetric_rtp;
bool_t permissive; /*use the permissive algorithm*/
bool_t use_connect; /* use connect() on the socket */
bool_t ssrc_set;
};