首先进行RTP的初始化,函数为ortp_init(),标志位initialized设为TRUE,然后调用一个av_profile_init函数进行profile的初始化包括设置payload的各种类型,在这里就包含了第一个比较重要的结构体就是:
struct _RtpProfile
{
char *name;
PayloadType *payload[RTP_PROFILE_MAX_PAYLOADS];
};
然后市ortp_global_stats_reset()函数来对ortp中的全局的统计参数做一个reset。这里出现了第二个重要的结构体就是:
typedef struct rtp_stats
{
uint64_t packet_sent;
uint64_t sent; /* bytes sent */
uint64_t recv; /* bytes of payload received and delivered in time to the application */
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 */
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_init()中调用的是Init_random_number_generator()函数它主要完成一个随即数的初始化工作。至此ortp_init的工作就完成了。
接下去是scheduler的初始化这里出现了第三个重要的结构体:
struct _RtpScheduler {
RtpSession *list; /* list of scheduled sessions*/
SessionSet all_sessions; /* mask of scheduled sessions */
int all_max; /* the highest pos in the all mask */
SessionSet r_sessions; /* mask of sessions that have a recv event */
int r_max;
SessionSet w_sessions; /* mask of sessions that have a send event */
int w_max;
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;
其中首先调用rtp_scheduler_new()来分配内存然后把结构体的参数清零,再设置自定的初始值和一些互斥锁的参数。至此scheduler_init的内容初始化完成。
日志的初始化是由ortp_set_log_level_mask()函数如果你不想有日志功能那就不需要这一步了。
接下来就是一个很重要的函数就是rtp_session_new这个函数这个函数用来创建一个新的rtp会话。其中最重要的一个结构体就是:
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;
int ssrc;
WaitPoint wp;
int telephone_events_pt; /* the payload type used for telephony events */
} snd,rcv;
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;
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. */
/* 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 */
};
在这个函数里首先给rtpsession结构体分配内存然后调用rtp_session_init函数来初始化。在这个函数里首先设置好最大队列数,和模式。判断模式是只读还是只写还是只读只写,根据模式设置flag,设置随机数random,设置源的描述,信号的设置,互斥锁的设置,设置send payload和receive payload type,设置jitter(这个还不知道是干什么的),设置最大接受单元等等。
Rtp_Session_set_remote_addr函数来设置远端的地址对。首先判断socket是否等于负一,如果是的话说明还没有设置本地地址,所以要去设置本地地址调用的是rtp_session_set_local_addr函数.在这个函数里首先去创建RTP要用到的socket的族系列参数和RTCP需要用到的族系列参数。以及设置支持多播方式的TTL和LOOPBACK和DSCP的值。接着就是绑定socket
然后就是设置payload的类型值调用的是rtp_session_set_payload_type()