学习nginx-rtmp:replay push代码流程

来源:互联网 发布:淘宝网冬之恋羊绒线 编辑:程序博客网 时间:2024/05/13 09:52

1, 如何触发connect到push上游服务器的
h = ngx_array_push(&cmcf->events[NGX_RTMP_HANDSHAKE_DONE]);
*h = ngx_rtmp_relay_handshake_done;
在服务器有流push上来后,也就是NGX_RTMP_HANDSHAKE_DONE事件后,触发ngx_rtmp_relay_handshake_done,完成向上游的rtmp connect。
ngx_rtmp_relay_handshake_done---->ngx_rtmp_relay_send_connect--------->ngx_rtmp_send_chunk_size,ngx_rtmp_send_ack_size, ngx_rtmp_send_amf(connect)
2, 如何完成后续rtmp create, push的收发的
cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
ch = ngx_array_push(&cmcf->amf);
ngx_str_set(&ch->name, "_result");
ch->handler = ngx_rtmp_relay_on_result;//注册了与上游rtmp服务器的协议处理函数
在ngx_rtmp_relay_on_result函数中,处理了协议回调:
static ngx_int_t
ngx_rtmp_relay_on_result(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in){
......
switch ((ngx_int_t)v.trans) {
case NGX_RTMP_RELAY_CONNECT_TRANS://如果rtmp connect返回后,立马发送create_stream
return ngx_rtmp_relay_send_create_stream(s);
case NGX_RTMP_RELAY_CREATE_STREAM_TRANS://如果create_stream返回后,立马发送rtmp_publish
if (ctx->publish != ctx && !s->static_relay) {
if (ngx_rtmp_relay_send_publish(s) != NGX_OK) {
return NGX_ERROR;
}
//这个ngx_rtmp_relay_play_local函数比较有意思,就是从本地拉流一份。
//其实就是把对上游rtmp的session作为订阅者,放入这个application stream的订阅者列表中。
//然后本地的会在发送给所有订阅者列表循环中,把rtmp流发送给上游rtmp服务器
return ngx_rtmp_relay_play_local(s);
} else {
if (ngx_rtmp_relay_send_play(s) != NGX_OK) {
return NGX_ERROR;
}
return ngx_rtmp_relay_publish_local(s);
}

default:
return NGX_OK;
}
}
在函数ngx_rtmp_relay_play_local中,调用ngx_rtmp_play
static ngx_int_t ngx_rtmp_relay_play_local(ngx_rtmp_session_t *s)
{
......
return ngx_rtmp_play(s, &v);//这里的指针指向:ngx_rtmp_relay_play
}

static ngx_int_tngx_rtmp_relay_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
{
ngx_rtmp_relay_ctx_t *ctx;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module);

if (ctx && s->relay) {
goto next;//条件满足,其实意思就是,这个play不是去pull别人,是pull自己的流给上游,直接到next_play中去
}

next:
return next_play(s, v);//这里的next_play = ngx_rtmp_live_play
}

static ngx_int_t ngx_rtmp_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v){
........
/* join stream as subscriber */
ngx_rtmp_live_join(s, v->name, 0);//把上游rtmp服务器的session加入到这个流的订阅者中去
........
}
------------------------------------------------------------------------------------------------
关键数据结构:
typedef struct {
ngx_array_t pulls; /* ngx_rtmp_relay_target_t * */
ngx_array_t pushes; /* ngx_rtmp_relay_target_t * */
ngx_array_t static_pulls; /* ngx_rtmp_relay_target_t * */
ngx_array_t static_events; /* ngx_event_t * */
ngx_log_t *log;
ngx_uint_t nbuckets;
ngx_msec_t buflen;
ngx_flag_t session_relay;
ngx_msec_t push_reconnect;
ngx_msec_t pull_reconnect;
ngx_rtmp_relay_ctx_t **ctx;
} ngx_rtmp_relay_app_conf_t;//application下push和pull的配置信息
pulls, pushes: 成员就是ngx_rtmp_relay_target_t,主要保存url等信息

typedef struct {
ngx_url_t url;
ngx_str_t app;
ngx_str_t name;
ngx_str_t tc_url;
ngx_str_t page_url;
ngx_str_t swf_url;
ngx_str_t flash_ver;
ngx_str_t play_path;
ngx_int_t live;
ngx_int_t start;
ngx_int_t stop;

void *tag; /* usually module reference */
void *data; /* module-specific data */
ngx_uint_t counter; /* mutable connection counter */
} ngx_rtmp_relay_target_t;//目的url(push或pull)的相关信息

typedef structngx_rtmp_relay_ctx_s ngx_rtmp_relay_ctx_t;
struct ngx_rtmp_relay_ctx_s {//这个module的ctx信息,包含session
ngx_str_t name;
ngx_str_t url;
ngx_log_t log;
ngx_rtmp_session_t *session;
ngx_rtmp_relay_ctx_t *publish;
ngx_rtmp_relay_ctx_t *play;
ngx_rtmp_relay_ctx_t *next;
ngx_str_t app;
ngx_str_t tc_url;
ngx_str_t page_url;
ngx_str_t swf_url;
ngx_str_t flash_ver;
ngx_str_t play_path;
ngx_int_t live;
ngx_int_t start;
ngx_int_t stop;

ngx_event_t push_evt;
ngx_event_t *static_evt;
void *tag;
void *data;
};

typedef struct {//ngx_rtmp_session_t, 顾名思义,就是连接上游的session信息
uint32_t signature; /* "RTMP" */ /* <-- FIXME wtf */

ngx_event_t close;

void **ctx;
void **main_conf;
void **srv_conf;
void **app_conf;

ngx_str_t *addr_text;
int connected;

#if (nginx_version >= 1007005)
ngx_queue_t posted_dry_events;
#else
ngx_event_t *posted_dry_events;
#endif

/* client buffer time in msec */
uint32_t buflen;
uint32_t ack_size;

/* connection parameters */
ngx_str_t app;
ngx_str_t args;
ngx_str_t flashver;
ngx_str_t swf_url;
ngx_str_t tc_url;
uint32_t acodecs;
uint32_t vcodecs;
ngx_str_t page_url;

/* handshake data */
ngx_buf_t *hs_buf;
u_char *hs_digest;
unsigned hs_old:1;
ngx_uint_t hs_stage;

/* connection timestamps */
ngx_msec_t epoch;
ngx_msec_t peer_epoch;
ngx_msec_t base_time;
uint32_t current_time;

/* ping */
ngx_event_t ping_evt;
unsigned ping_active:1;
unsigned ping_reset:1;

/* auto-pushed? */
unsigned auto_pushed:1;
unsigned relay:1;
unsigned static_relay:1;

/* input stream 0 (reserved by RTMP spec)
* is used as free chain link */

ngx_rtmp_stream_t *in_streams;
uint32_t in_csid;
ngx_uint_t in_chunk_size;
ngx_pool_t *in_pool;
uint32_t in_bytes;
uint32_t in_last_ack;

ngx_pool_t *in_old_pool;
ngx_int_t in_chunk_size_changing;

ngx_connection_t *connection;

/* circular buffer of RTMP message pointers */
ngx_msec_t timeout;
uint32_t out_bytes;
size_t out_pos, out_last;
ngx_chain_t *out_chain;
u_char *out_bpos;
unsigned out_buffer:1;
size_t out_queue;
size_t out_cork;
ngx_chain_t *out[0];
} ngx_rtmp_session_t;
0 0
原创粉丝点击