Asterisk内核(下面就简称内核)提供了一系列RTP相关的API函数。在使用不同的RTP栈时,这些API为RTP使用模块提供一种统一的访问方式。这些API封装之后,任何使用RTP的模块,都感觉不到底层栈的差异。对于使用模块来说,每个RTP栈的行为都是一样的。
内核把一个RTP session称作一个RTP实例,一个实例由几部分组成:编解码(codec)信息、RTP引擎、RTP属性信息、地址信息。可以通过引擎名明确指定所使用的RTP栈,如果没有指定,会使用缺省的栈。调用方可以提供RTP所使用的地址,但底层RTP引擎可能会根据自身的配置,选择一个适当的地址。
RTP引擎(通常是以属于resource分类的模块),是介于内核和RTP栈之间的一层。内核提供一系列的回调接口来完成不同的事务(比如说音频输出),而RTP引擎则需要适配这些接口,即对RTP栈进行封装。
Glue是一个RTP实例和一个信道(channel)间绑定的内容。在执行远端桥接或本地桥接时,或者通道驱动需要通知远端改变RTP流的目的地时,它用来检索RTP实例。
RTP实例的统计数据,可以通调用ast_rtp_instance_get_stats这个API来检索。这要求使用中的RTP引擎填充一个数据结构,以携带所请求的统计项值。没有要求一个RTP引擎必须支持所有的统计项。
调用方可以改变RTP引擎和引核的行为,这需要设置RTP属性。比如说:有一个叫AST_RTP_PROPERTY_NAT的属性,它用来告诉RTP引擎:如果支持对称RTP就启用它。内核并不要求一个RTP引擎必须支持所有的属性。
编解码信息存储在一个独立的数据结构中,它拥有自己的一套API,用于添加、删除或信息检索。使用它们的模块,在RTP实例创建之后调用这些API,这样,载荷信息对RTP引擎来说就是可见的。
ast_rtp_instance,描述RTPSession的数据结构。
00048 /*! Structure that represents an RTP session (instance) */
00049 struct ast_rtp_instance {
00050 /*! Engine that is handling this RTP instance */
00051 struct ast_rtp_engine *engine;
00052 /*! Data unique to the RTP engine */
00053 void *data;
00054 /*! RTP properties that have been set and their value */
00055 int properties[AST_RTP_PROPERTY_MAX];
00056 /*! Address that we are expecting RTP to come in to */
00057 struct ast_sockaddr local_address;
........
};
ast_rtp_mime_type,在rtp_engine.c中,直接定义了一个数组,描述MIME媒体类型
00086 /*! The following array defines the MIME Media type (and subtype) for each
00087 of our codecs, or RTP-specific data type. */
00088 static struct ast_rtp_mime_type {
00089 struct ast_rtp_payload_type payload_type;
00090 char *type;
00091 char *subtype;
00092 unsigned int sample_rate;
00093 } ast_rtp_mime_types[];
ast_rtp_engine 描述具体RTP栈的数据结构,提供了内核与RTP栈交互的一系列接口定义。具体的RTP引擎实现,都要实例化里面的内容。
00313 /*! Structure that represents an RTP stack (engine) */
00314 struct ast_rtp_engine {
00315 /*! Name of the RTP engine, used when explicitly requested */
00316 const char *name;
00317 /*! Module this RTP engine came from, used for reference counting */
00318 struct ast_module *mod;
00319 /*! Callback for setting up a new RTP instance */
00320 int (*new)(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *sa, void *data);
00321 /*! Callback for destroying an RTP instance */
00322 int (*destroy)(struct ast_rtp_instance *instance);
00323 /*! Callback for writing out a frame */
00324 int (*write)(struct ast_rtp_instance *instance, struct ast_frame *frame);
00325 /*! Callback for stopping the RTP instance */
00326 void (*stop)(struct ast_rtp_instance *instance);
.......
};
ast_rtp_glue,描述RTP实例和具体信道间绑定的数据内容、内核与RTP使用模块间的接口定义,用到RTP的外围模块,都需要自己实现相关的接口:
00396 /*! Structure that represents the glue that binds an RTP instance to a channel */
00397 struct ast_rtp_glue {
00398 /*! Name of the channel driver that this glue is responsible for */
00399 const char *type;
00400 /*! Module that the RTP glue came from */
00401 struct ast_module *mod;
00402 /*!
00403 * \brief Callback for retrieving the RTP instance carrying audio
00404 * \note This function increases the reference count on the returned RTP instance.
00405 */
00406 enum ast_rtp_glue_result (*get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
00407 /*!
00408 * \brief Callback for retrieving the RTP instance carrying video
00409 * \note This function increases the reference count on the returned RTP instance.
00410 */
00411 enum ast_rtp_glue_result (*get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
00412 /*!
00413 * \brief Callback for retrieving the RTP instance carrying text
00414 * \note This function increases the reference count on the returned RTP instance.
00415 */
00416 enum ast_rtp_glue_result (*get_trtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
00417 /*! Callback for updating the destination that the remote side should send RTP to */
00418 int (*update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active);
00419 /*! Callback for retrieving codecs that the channel can do. Result returned in result_cap*/
00420 void (*get_codec)(struct ast_channel *chan, struct ast_format_cap *result_cap);
00421 /*! Linked list information */
00422 AST_RWLIST_ENTRY(ast_rtp_glue) entry;
00423 };
内核定义了两个链表,用来管理RTPengine和RTP glue
00080 /*! List of RTP engines that are currently registered */
00081 static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
00082
00083 /*! List of RTP glues */
00084 static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
内核提供了一个抽象的管理和调用接口,具体的RTP应用模块,与内核API交互,内核再通过ast_rtp_engine里定义的接口与FTP栈交互,如果要引入新的RTP栈,就要实现栈与内核间的一个引擎模块,实现这些接口的封装。1.8版本中,asterisk实现两个引擎模块:res_rtp_asterisk和res_rtp_multicast模块。