一 hls(http live streaming)
hls协议包括两部分,1 m3u8文件(切片列表文件)更新。2 ts切片更新
二 nginx-hls模块
nginx hls模块集成在nginx-rtmp-module中。
相关配置如下:
rtmp {
server {
listen 1995;
ack_window 800000;
application live {//app名
live on;
hls on;//开启hls
hls_path /data/hls;//hls临时目录
hls_fragment 3s;//切片大小,以这个标准来,切片以GOP开始,当GOP大于这个配置的时候,切片为一个GOP大小
hls_max_fragment 10s;//绝对小于这个值,当这个值小于GOP的时候,会出现切片不是以I帧开始
}
application hls {
live on;
hls on;
hls_path temp/hls;
hls_fragment 3s;
hls_max_fragment 4s;
}
}
}
三 nginx-rtmp-module中的hls模块分析
相关回调接口
ngx_rtmp_hls_publish 发布流调用
ngx_rtmp_hls_stream_begin 流开始
ngx_rtmp_hls_stream_eof 流结束
ngx_rtmp_hls_video 视频帧
ngx_rtmp_hls_audio 音频帧
ngx_rtmp_hls_cleanup
ngx_rtmp_hls_publish:
主要创建临时目录,初始化直播m3u8文件名。
ngx_rtmp_hls_stream_eof 流结束,通过注册的回收函数
ngx_rtmp_hls_cleanup 删除hls临时目录。
ngx_rtmp_hls_video-->
ngx_rtmp_hls_update_fragment()//每次处理视频帧,尝试更新切片
{
if (ctx->opened) {//如果切片是打开状态
f = ngx_rtmp_hls_get_frag(s, ctx->nfrags);//获取切片信息
d = (int64_t) (ts - ctx->frag_ts);//当前duration
if (d > (int64_t) hacf->max_fraglen * 90 || d < -90000) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"hls: force fragment split: %.3f sec, ", d / 90000.);
force = 1;//强制关闭切片,切片过大
} else {//正常切片大小
f->duration = (ts - ctx->frag_ts) / 90000.;
discont = 0;
}
}
if (boundary || force) {//如果是切片的边界了,key frame
ngx_rtmp_hls_close_fragment(s);
ngx_rtmp_hls_open_fragment(s, ts, 0);
}
}
PS:我前面准备做一个统计所有ts切片总的duration的功能,于是在ngx_rtmp_hls_close_fragment之前每次把当前切片的
duration加起来,也就是f->duration。但是发现core了,后面意识到当流刚开始,第一次要生成切片的时候,open状态是关闭的,
所以在加duration的时候要判断f是否为空。这样也不会遗漏一个切片,因为每个切片都是在这里结束的。
ngx_rtmp_hls_copy:解析rtmp trunk
ngx_rtmp_mpegts_write_frame()
将数据写到ts切片中。
hls协议包括两部分,1 m3u8文件(切片列表文件)更新。2 ts切片更新
二 nginx-hls模块
nginx hls模块集成在nginx-rtmp-module中。
相关配置如下:
rtmp {
server {
listen 1995;
ack_window 800000;
application live {//app名
live on;
hls on;//开启hls
hls_path /data/hls;//hls临时目录
hls_fragment 3s;//切片大小,以这个标准来,切片以GOP开始,当GOP大于这个配置的时候,切片为一个GOP大小
hls_max_fragment 10s;//绝对小于这个值,当这个值小于GOP的时候,会出现切片不是以I帧开始
}
application hls {
live on;
hls on;
hls_path temp/hls;
hls_fragment 3s;
hls_max_fragment 4s;
}
}
}
三 nginx-rtmp-module中的hls模块分析
相关回调接口
ngx_rtmp_hls_publish 发布流调用
ngx_rtmp_hls_stream_begin 流开始
ngx_rtmp_hls_stream_eof 流结束
ngx_rtmp_hls_video 视频帧
ngx_rtmp_hls_audio 音频帧
ngx_rtmp_hls_cleanup
ngx_rtmp_hls_publish:
主要创建临时目录,初始化直播m3u8文件名。
ngx_rtmp_hls_stream_eof 流结束,通过注册的回收函数
ngx_rtmp_hls_cleanup 删除hls临时目录。
ngx_rtmp_hls_video-->
ngx_rtmp_hls_update_fragment()//每次处理视频帧,尝试更新切片
{
if (ctx->opened) {//如果切片是打开状态
f = ngx_rtmp_hls_get_frag(s, ctx->nfrags);//获取切片信息
d = (int64_t) (ts - ctx->frag_ts);//当前duration
if (d > (int64_t) hacf->max_fraglen * 90 || d < -90000) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"hls: force fragment split: %.3f sec, ", d / 90000.);
force = 1;//强制关闭切片,切片过大
} else {//正常切片大小
f->duration = (ts - ctx->frag_ts) / 90000.;
discont = 0;
}
}
if (boundary || force) {//如果是切片的边界了,key frame
ngx_rtmp_hls_close_fragment(s);
ngx_rtmp_hls_open_fragment(s, ts, 0);
}
}
PS:我前面准备做一个统计所有ts切片总的duration的功能,于是在ngx_rtmp_hls_close_fragment之前每次把当前切片的
duration加起来,也就是f->duration。但是发现core了,后面意识到当流刚开始,第一次要生成切片的时候,open状态是关闭的,
所以在加duration的时候要判断f是否为空。这样也不会遗漏一个切片,因为每个切片都是在这里结束的。
ngx_rtmp_hls_copy:解析rtmp trunk
ngx_rtmp_mpegts_write_frame()
将数据写到ts切片中。