系列文章:
Nginx rtmp 推流(publish) 解析_fdsafwagdagadg6576的专栏-CSDN博客
Nginx rtmp 拉流播放(play)_fdsafwagdagadg6576的专栏-CSDN博客
Nginx rtmp 拉流(转发pull)_fdsafwagdagadg6576的专栏-CSDN博客
Nginx rtmp 转推_fdsafwagdagadg6576的专栏-CSDN博客
Nginx rtmp 点播流程_fdsafwagdagadg6576的专栏-CSDN博客
直播场景涉及relay,live 模块,点播使用play模块
static ngx_command_t ngx_rtmp_play_commands[] = {
//一项为 "play",点播业务的nginx.conf中,就配置了该命令.因此先看该模块是如何解析 play 配置项的:
{ ngx_string("play"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
ngx_rtmp_play_url,
NGX_RTMP_APP_CONF_OFFSET,
0,
NULL },
......
}
点播模块入口是ngx_rtmp_play_url
上图是点播的整个信令交互流程.下面是audio,video数据流发送过程.
点播可以播放mp4,flv两种格式。可以播放本地和网络两种路径文件.
本例以播放本地flv文件为例:
3.1 初始化
3.2 发送流程图
先发送metadata,后发送audio,video数据。
ngx_rtmp_play_send 是点播发送的核心函数(直播是ngx_rtmp_live_av).
发送的核心是循环调用ngx_rtmp_play_send,读取一个flv文件tag,发送一个,然后再读取再发送,直到发送全部完成。
3.3 seek
绿色发送接口即3.2
//点播的最后一个调用就是在该函数中循环的,直到全部发送文件完成后,才返回.
static void//发送给player
ngx_rtmp_play_send(ngx_event_t *e)
{
...
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
ts = 0;
//==1调用flv,mp4封装的send函数(ngx_rtmp_flv_send,ngx_rtmp_mp4_send).时间戳是在那里设置的
rc = ctx->fmt->send(s, &ctx->file, &ts);
......
if (rc == NGX_OK) {
//===2 每发送完成一次,就将其放入到 ngx_posted_events 延迟队列中====
然后由下一次 ngx_process_events_and_timers 函数中的循环调用到它 */
ngx_post_event(e, &ngx_posted_events);
return;
}
//===3 end====
ngx_rtmp_send_stream_eof(s, NGX_RTMP_MSID);
ngx_rtmp_send_play_status(s, "NetStream.Play.Complete", "status", ts, 0);
ngx_rtmp_send_status(s, "NetStream.Play.Stop", "status", "Stopped");
}
ngx_process_events_and_timers(ngx_cycle_t *cycle)
{
ngx_event_process_posted(cycle, &ngx_posted_accept_events);
....
}
void //就是遍历event的队列,调用event的handler函数。
ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted)
{
ngx_queue_t *q;
ngx_event_t *ev;
while (!ngx_queue_empty(posted)) {
q = ngx_queue_head(posted);
ev = ngx_queue_data(q, ngx_event_t, queue);
ngx_delete_posted_event(ev);
//添加accept or read handler callback
ev->handler(ev);
}
}
流程:
1) ngx_read_file:按照flv tag 读取
2) ngx_rtmp_prepare_message: 按照rtmp协议打包
3) ngx_rtmp_send_message:发送rtmp audio,video
4 ) 将发送事件放入event queue
5) 从queue中取出发送event ,执行handler(callback)函数ngx_rtmp_play_send
上述流程实现了,循环读取发送flv 文件
读取mp4文件,需要了解Mp4格式。
读取网络路径文件,待续.