Nginx rtmp 点播流程

系列文章: 

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模块 

1 模块设置

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

2 流程图:

Nginx rtmp 点播流程_第1张图片

上图是点播的整个信令交互流程.下面是audio,video数据流发送过程.

3 audio,video 发送

点播可以播放mp4,flv两种格式。可以播放本地和网络两种路径文件.
本例以播放本地flv文件为例:
3.1  初始化

Nginx rtmp 点播流程_第2张图片

3.2 发送流程图

先发送metadata,后发送audio,video数据。
ngx_rtmp_play_send 是点播发送的核心函数(直播是ngx_rtmp_live_av).

Nginx rtmp 点播流程_第3张图片

发送的核心是循环调用ngx_rtmp_play_send,读取一个flv文件tag,发送一个,然后再读取再发送,直到发送全部完成。

 3.3 seek

Nginx rtmp 点播流程_第4张图片

绿色发送接口即3.2

4 源码分析

  • 发送audio,video
//点播的最后一个调用就是在该函数中循环的,直到全部发送文件完成后,才返回.
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格式。
读取网络路径文件,待续.

如果对您有所帮助,请随手点赞,谢谢

你可能感兴趣的:(nginx,nginx,运维,服务器,linux,rtmp)