diff --git a/.travis.yml b/.travis.yml
index 8380572..2eacb18 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,5 +7,5 @@ install:
- cd nginx-1.12.2
script:
- - ./configure --add-module=../nginx-http-flv-module && make
- - ./configure --add-dynamic-module=../nginx-http-flv-module && make
+ - ./configure --add-module=../nginx-http-flv-module && make -j 8
+ - ./configure --add-dynamic-module=../nginx-http-flv-module && make -j 8
diff --git a/AUTHORS b/AUTHORS
index 58a763c..2a42e38 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -19,3 +19,26 @@ Project author:
Contacts:
huzilong_007@163.com
huzilong@kingsoft.com
+
+ han4235
+ Suzhou, China
+
+ Contacts:
+ https://github.com/han4235
+
+ plainheart
+ Zhengzhou, China
+
+ Contacts:
+ https://github.com/plainheart
+
+ HeyJupiter:
+ Seattle, US
+
+ Contacts:
+ https://github.com/HeyJupiter
+
+ Vladimir Vainer
+
+ Contacts:
+ https://github.com/ferreus
diff --git a/README.CN.md b/README.CN.md
index a3deb9e..f235b58 100644
--- a/README.CN.md
+++ b/README.CN.md
@@ -4,18 +4,35 @@
基于[nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module)的流媒体服务器。
+[English README](https://github.com/winshining/nginx-http-flv-module/blob/master/README.md)。
+
+如果您喜欢这个模块,可以通过赞赏来支持我的工作,非常感谢!
+
+
+
+### 感谢
+
+* Igor Sysoev,[NGINX](http://nginx.org)的作者。
+
+* Roman Arutyunyan,[nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module)的作者。
+
+* 贡献者,详情见[AUTHORS](https://github.com/winshining/nginx-http-flv-module/blob/master/AUTHORS)。
+
# 功能
* [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module)提供的所有功能。
* nginx-http-flv-module的其他功能与[nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module)的对比:
-| 功能 | nginx-http-flv-module | nginx-rtmp-module | 备注 |
-| :--------------: | :-------------------: | :---------------: | :--------------------------: |
-| HTTP-FLV (播放) | √ | x | 支持HTTPS-FLV和chunked回复 |
-| GOP缓存 | √ | x | 仅适用于H.264视频和AAC音频 |
-| 虚拟主机 | √ | x | |
-| 省略`listen`配置 | √ | x | |
+| 功能 | nginx-http-flv-module | nginx-rtmp-module | 备注 |
+| :--------------: | :-------------------: | :---------------: | :------------------------------------: |
+| HTTP-FLV (播放) | √ | x | 支持HTTPS-FLV和chunked回复 |
+| GOP缓存 | √ | x | 仅适用于H.264视频和AAC音频 |
+| 虚拟主机 | √ | x | |
+| 省略`listen`配置 | √ | 见备注 | 配置中必须有一个`listen` |
+| 纯音频支持 | √ | 见备注 | `wait_video`或`wait_key`开启后无法工作 |
+| 定时打印访问记录 | √ | x | |
+| JSON风格的stat | √ | x | |
# 支持的系统
@@ -25,17 +42,21 @@
* [VLC](http://www.videolan.org) (RTMP & HTTP-FLV)/[OBS](https://obsproject.com) (RTMP & HTTP-FLV)/[JW Player](https://www.jwplayer.com) (RTMP)/[flv.js](https://github.com/Bilibili/flv.js) (HTTP-FLV).
+## 注意
+
+[flv.js](https://github.com/Bilibili/flv.js)只能运行在支持[Media Source Extensions](https://www.w3.org/TR/media-source)的浏览器上。
+
# 依赖
* 在类Unix系统上,需要GNU make,用于调用编译器来编译软件。
-* 在类Unix系统上,需要GCC/在Windows上,需要MSVC,用于编译软件。
+* 在类Unix系统上,需要GCC。或者在Windows上,需要MSVC,用于编译软件。
* 在类Unix系统上,需要GDB,用于调试软件(可选)。
-* FFmpeg,用于发布媒体流。
+* [FFmpeg](http://ffmpeg.org)或者[OBS](https://obsproject.com),用于发布媒体流。
-* VLC播放器(推荐),用于播放媒体流。
+* [VLC](http://www.videolan.org)(推荐)或者[flv.js](https://github.com/Bilibili/flv.js)(推荐),用于播放媒体流。
* 如果NGINX要支持正则表达式,需要PCRE库。
@@ -101,6 +122,10 @@ nginx-http-flv-module包含了[nginx-rtmp-module](https://github.com/arut/nginx-
http://example.com[:port]/dir?[port=xxx&]app=myapp&stream=mystream
+### 注意
+
+如果使用[ffplay](http://www.ffmpeg.org/ffplay.html)命令行方式播放流,那么**必须**为上述的url加上引号,否则url中的参数会被丢弃(有些不太智能的shell会把"&"解释为"后台运行")。
+
参数`dir`用于匹配http配置块中的location块(更多详情见下文)。
**HTTP默认端口**为**80**, 如果使用了其他端口,必须指定`:port`。
@@ -161,18 +186,32 @@ nginx-http-flv-module包含了[nginx-rtmp-module](https://github.com/arut/nginx-
http://example.com[:port]/dir/streamname.mpd
+# 示例图片
+
+## RTMP ([JW Player](https://www.jwplayer.com)) & HTTP-FLV ([VLC](http://www.videolan.org))
+
+
+
+## HTTP-FLV ([flv.js](https://github.com/Bilibili/flv.js))
+
+
+
+# nginx-http-flv-module的安装包
+
+详情见[nginx-http-flv-module-packages](https://github.com/winshining/nginx-http-flv-module-packages)。
+
# nginx.conf实例
## 注意
配置项`rtmp_auto_push`,`rtmp_auto_push_reconnect`和`rtmp_socket_dir`在Windows上不起作用,除了Windows 10 17063以及后续版本之外,因为多进程模式的`relay`需要Unix domain socket的支持,详情请参考[Unix domain socket on Windows 10](https://blogs.msdn.microsoft.com/commandline/2017/12/19/af_unix-comes-to-windows)。
-最好将配置项`worker_processes`设置为1,因为`ngx_rtmp_stat_module`在多进程模式下每次只能获取一个进程的统计数据。如果统计数据不重要,那么可以将它设置为大于1的数字,最好与CPU的核心数保持一致。
+最好将配置项`worker_processes`设置为1,因为`ngx_rtmp_stat_module`和`ngx_rtmp_control_module`在多进程模式下有问题,另外,`vhost`功能在多进程模式下还不能完全正确运行,等待修复。
- worker_processes 4; #运行在Windows上时,设置为1,因为Windows不支持Unix domain socket
+ worker_processes 1; #运行在Windows上时,设置为1,因为Windows不支持Unix domain socket
#worker_processes auto; #1.3.8和1.2.5以及之后的版本
- worker_cpu_affinity 0001 0010 0100 1000; #只能用于FreeBSD和Linux
+ #worker_cpu_affinity 0001 0010 0100 1000; #只能用于FreeBSD和Linux
#worker_cpu_affinity auto; #1.9.10以及之后的版本
error_log logs/error.log error;
@@ -180,7 +219,8 @@ nginx-http-flv-module包含了[nginx-rtmp-module](https://github.com/arut/nginx-
#如果此模块被编译为动态模块并且要使用与RTMP相关的功
#能时,必须指定下面的配置项并且它必须位于events配置
#项之前,否则NGINX启动时不会加载此模块或者加载失败
- #load_module modules/ngx_rtmp_module.so;
+
+ #load_module modules/ngx_http_flv_live_module.so;
events {
worker_connections 1024;
@@ -239,6 +279,14 @@ nginx-http-flv-module包含了[nginx-rtmp-module](https://github.com/arut/nginx-
root /var/www/rtmp; #指定stat.xsl的位置
}
+ #如果需要JSON风格的stat, 不用指定stat.xsl
+ #但是需要指定一个新的配置项rtmp_stat_format
+
+ #location /stat {
+ # rtmp_stat all;
+ # rtmp_stat_format json;
+ #}
+
location /control {
rtmp_control all; #rtmp控制模块的配置
}
@@ -250,9 +298,13 @@ nginx-http-flv-module包含了[nginx-rtmp-module](https://github.com/arut/nginx-
rtmp_socket_dir /tmp;
rtmp {
- out_queue 4096;
- out_cork 8;
- max_streams 64;
+ out_queue 4096;
+ out_cork 8;
+ max_streams 128;
+ timeout 15s;
+
+ log_interval 5s; #log模块在access.log中记录日志的间隔时间,对调试非常有用
+ log_size 1m; #log模块用来记录日志的缓冲区大小
server {
listen 1935;
@@ -296,4 +348,3 @@ nginx-http-flv-module包含了[nginx-rtmp-module](https://github.com/arut/nginx-
}
}
}
-
diff --git a/README.md b/README.md
index 3197bd6..21c437b 100644
--- a/README.md
+++ b/README.md
@@ -4,18 +4,35 @@
Media streaming server based on [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module).
+[中文说明](https://github.com/winshining/nginx-http-flv-module/blob/master/README.CN.md).
+
+Donate if you like this module. Many thanks to you!
+
+
+
+### Appreciation
+
+* Igor Sysoev, the creator of [NGINX](http://nginx.org).
+
+* Roman Arutyunyan, who created [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module).
+
+* Contributors, refer to [AUTHORS](https://github.com/winshining/nginx-http-flv-module/blob/master/AUTHORS) for details.
+
# Features
* All features [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module) provides.
* Other features provided by nginx-http-flv-module vs [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module):
-| Features | nginx-http-flv-module | nginx-rtmp-module | remarks |
-| :---------------------: | :-------------------: | :---------------: | :----------------------------------------: |
-| HTTP-FLV (subscribe) | √ | x | HTTPS-FLV and chunked response supported |
-| GOP cache | √ | x | Only for H.264 video and AAC audio |
-| VHOST | √ | x | |
-| omit `listen` directive | √ | x | |
+| Features | nginx-http-flv-module | nginx-rtmp-module | Remarks |
+| :---------------------: | :-------------------: | :---------------: | :---------------------------------------------: |
+| HTTP-FLV (subscribe) | √ | x | HTTPS-FLV and chunked response supported |
+| GOP cache | √ | x | Only for H.264 video and AAC audio |
+| VHOST | √ | x | |
+| Omit `listen` directive | √ | See remarks | There MUST be at least one `listen` directive |
+| Audio-only support | √ | See remarks | Won't work if `wait_video` or `wait_key` is on |
+| Timing log for access | √ | x | |
+| JSON style stat | √ | x | |
# Systems supported
@@ -25,17 +42,21 @@ Media streaming server based on [nginx-rtmp-module](https://github.com/arut/ngin
* [VLC](http://www.videolan.org) (RTMP & HTTP-FLV)/[OBS](https://obsproject.com) (RTMP & HTTP-FLV)/[JW Player](https://www.jwplayer.com) (RTMP)/[flv.js](https://github.com/Bilibili/flv.js) (HTTP-FLV).
+## Note
+
+[flv.js](https://github.com/Bilibili/flv.js) can only run with browsers that support [Media Source Extensions](https://www.w3.org/TR/media-source).
+
# Prerequisites
* GNU make for activating compiler on Unix-like systems to compile software.
-* GCC for compiling on Unix-like systems/MSVC for compiling on Windows.
+* GCC for compilation on Unix-like systems or MSVC for compilation on Windows.
-* GDB for debuging on Unix-like systems.
+* GDB for debug on Unix-like systems.
-* FFmpeg for publishing media streams.
+* [FFmpeg](http://ffmpeg.org) or [OBS](https://obsproject.com) for publishing media streams.
-* VLC player (recommended) for playing media streams.
+* [VLC](http://www.videolan.org) (recommended) or [flv.js](https://github.com/Bilibili/flv.js) (recommended) for playing media streams.
* PCRE for NGINX if regular expressions needed.
@@ -51,7 +72,7 @@ nginx-http-flv-module has all features that [nginx-rtmp-module](https://github.c
## On Windows
-Build steps please refer to [Building nginx on the Win32 platform with Visual C](http://nginx.org/en/docs/howto_build_on_win32.html), and don't forget to add `--add-module=/path/to/nginx-http-flv-module` in `Run configure script` step.
+For details of build steps, please refer to [Building nginx on the Win32 platform with Visual C](http://nginx.org/en/docs/howto_build_on_win32.html), and don't forget to add `--add-module=/path/to/nginx-http-flv-module` in `Run configure script` step.
## On Unix-like systems
@@ -81,7 +102,7 @@ If the module is compiled as a dynamic module, the [NGINX](http://nginx.org) ver
# Usage
-For details about usages of [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module), please refer to [README.md](https://github.com/arut/nginx-rtmp-module/blob/master/README.md).
+For details of usages of [nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module), please refer to [README.md](https://github.com/arut/nginx-rtmp-module/blob/master/README.md).
## Publish
@@ -101,6 +122,10 @@ The **default port for RTMP** is **1935**, if some other ports were used, `:port
http://example.com[:port]/dir?[port=xxx&]app=myapp&stream=mystream
+### Note
+
+If [ffplay](http://www.ffmpeg.org/ffplay.html) is used in command line to play the stream, the url above **MUST** be enclosed by quotation marks, or arguments in url will be discarded (some shells not so smart will interpret "&" as "run in background").
+
The `dir` is used to match location blocks in http block (see below for details).
The **default port for HTTP** is **80**, if some other ports were used, `:port` must be specified.
@@ -141,7 +166,7 @@ And `listen` directive specified in `rtmp` block is:
}
}
-Then the url of play based on HTTP is:
+Then the url of playback based on HTTP is:
http://example.com:8080/live?port=1985&app=myapp&stream=mystream
@@ -161,18 +186,32 @@ Since some players don't support HTTP chunked transmission, it's better to speci
http://example.com[:port]/dir/streamname.mpd
+# Sample Pictures
+
+## RTMP ([JW Player](https://www.jwplayer.com)) & HTTP-FLV ([VLC](http://www.videolan.org))
+
+
+
+## HTTP-FLV ([flv.js](https://github.com/Bilibili/flv.js))
+
+
+
+# Packages for nginx-http-flv-module
+
+Please refer to [nginx-http-flv-module-packages](https://github.com/winshining/nginx-http-flv-module-packages).
+
# Example nginx.conf
## Note
The directives `rtmp_auto_push`, `rtmp_auto_push_reconnect` and `rtmp_socket_dir` will not function on Windows except on Windows 10 17063 and later versions, because `relay` in multiple processes mode needs help of Unix domain socket, please refer to [Unix domain socket on Windows 10](https://blogs.msdn.microsoft.com/commandline/2017/12/19/af_unix-comes-to-windows) for details.
-The directive `worker_processes` of value 1 is preferable to other values, because `ngx_rtmp_stat_module` can only get the statistics of one process at a time in multi-processes mode. If the statistics is unimportant, it can be set as number greater than 1, it is better to set it as the number of CPU cores.
+The directive `worker_processes` of value 1 is preferable to other values, because there are something wrong with `ngx_rtmp_stat_module` and `ngx_rtmp_control_module` in multi-processes mode, in addtion, `vhost` feature is not perfect in multi-processes mode yet, wating to be fixed.
- worker_processes 4; #should be 1 for Windows, for it doesn't support Unix domain socket
+ worker_processes 1; #should be 1 for Windows, for it doesn't support Unix domain socket
#worker_processes auto; #from versions 1.3.8 and 1.2.5
- worker_cpu_affinity 0001 0010 0100 1000; #only available on FreeBSD and Linux
+ #worker_cpu_affinity 0001 0010 0100 1000; #only available on FreeBSD and Linux
#worker_cpu_affinity auto; #from version 1.9.10
error_log logs/error.log error;
@@ -181,7 +220,8 @@ The directive `worker_processes` of value 1 is preferable to other values, becau
#to RTMP are needed, the command below MUST be specified and MUST be
#located before events directive, otherwise the module won't be loaded
#or will be loaded unsuccessfully when NGINX is started
- #load_module modules/ngx_rtmp_module.so;
+
+ #load_module modules/ngx_http_flv_live_module.so;
events {
worker_connections 1024;
@@ -240,6 +280,14 @@ The directive `worker_processes` of value 1 is preferable to other values, becau
root /var/www/rtmp; #specify in where stat.xsl located
}
+ #if JSON style stat needed, no need to specify
+ #stat.xsl but a new directive rtmp_stat_format
+
+ #location /stat {
+ # rtmp_stat all;
+ # rtmp_stat_format json;
+ #}
+
location /control {
rtmp_control all; #configuration of control module of rtmp
}
@@ -251,9 +299,13 @@ The directive `worker_processes` of value 1 is preferable to other values, becau
rtmp_socket_dir /tmp;
rtmp {
- out_queue 4096;
- out_cork 8;
- max_streams 64;
+ out_queue 4096;
+ out_cork 8;
+ max_streams 128;
+ timeout 15s;
+
+ log_interval 5s; #interval used by log module to log in access.log, it is very useful for debug
+ log_size 1m; #buffer size used by log module to log in access.log
server {
listen 1935;
@@ -297,4 +349,3 @@ The directive `worker_processes` of value 1 is preferable to other values, becau
}
}
}
-
diff --git a/config b/config
index 0d48832..28ca924 100644
--- a/config
+++ b/config
@@ -1,4 +1,4 @@
-ngx_addon_name="ngx_http_flv_module"
+ngx_addon_name="ngx_http_flv_live_module"
RTMP_CORE_MODULES=" \
ngx_rtmp_module \
@@ -9,6 +9,7 @@ RTMP_CORE_MODULES=" \
ngx_rtmp_record_module \
ngx_rtmp_gop_cache_module \
ngx_rtmp_live_module \
+ ngx_rtmp_flv_live_index_module \
ngx_rtmp_play_module \
ngx_rtmp_flv_module \
ngx_rtmp_mp4_module \
@@ -44,14 +45,12 @@ RTMP_DEPS=" \
$ngx_addon_dir/ngx_rtmp_netcall_module.h \
$ngx_addon_dir/ngx_rtmp_play_module.h \
$ngx_addon_dir/ngx_rtmp_record_module.h \
- $ngx_addon_dir/ngx_rtmp_notify_module.h \
$ngx_addon_dir/ngx_rtmp_gop_cache_module.h \
$ngx_addon_dir/ngx_rtmp_relay_module.h \
$ngx_addon_dir/ngx_rtmp_streams.h \
$ngx_addon_dir/ngx_rtmp_bitop.h \
$ngx_addon_dir/ngx_rtmp_proxy_protocol.h \
$ngx_addon_dir/ngx_rtmp_variables.h \
- $ngx_addon_dir/ngx_rtmp_script.h \
$ngx_addon_dir/hls/ngx_rtmp_mpegts.h \
$ngx_addon_dir/dash/ngx_rtmp_mp4.h \
"
@@ -74,6 +73,7 @@ RTMP_CORE_SRCS=" \
$ngx_addon_dir/ngx_rtmp_record_module.c \
$ngx_addon_dir/ngx_rtmp_gop_cache_module.c \
$ngx_addon_dir/ngx_rtmp_live_module.c \
+ $ngx_addon_dir/ngx_rtmp_flv_live_index_module.c \
$ngx_addon_dir/ngx_rtmp_play_module.c \
$ngx_addon_dir/ngx_rtmp_flv_module.c \
$ngx_addon_dir/ngx_rtmp_mp4_module.c \
@@ -88,7 +88,6 @@ RTMP_CORE_SRCS=" \
$ngx_addon_dir/ngx_rtmp_bitop.c \
$ngx_addon_dir/ngx_rtmp_proxy_protocol.c \
$ngx_addon_dir/ngx_rtmp_variables.c \
- $ngx_addon_dir/ngx_rtmp_script.c \
$ngx_addon_dir/ngx_rtmp_parse.c \
$ngx_addon_dir/hls/ngx_rtmp_hls_module.c \
$ngx_addon_dir/dash/ngx_rtmp_dash_module.c \
@@ -108,11 +107,21 @@ if [ -f auto/module ] ; then
ngx_module_deps=$RTMP_DEPS
if [ $ngx_module_link = DYNAMIC ] ; then
- ngx_module_name="$RTMP_CORE_MODULES $RTMP_HTTP_MODULES"
+ ngx_module_name="$ngx_addon_name $RTMP_CORE_MODULES $RTMP_HTTP_MODULES"
ngx_module_srcs="$RTMP_CORE_SRCS $RTMP_HTTP_SRCS"
. auto/module
+ dynamic_modules=`eval echo '$'"${ngx_module}_MODULES" | sed -e "s/ \{0,\}$ngx_addon_name//"`
+ eval ${ngx_module}_MODULES=\"$dynamic_modules\"
+ unset dynamic_modules
+
+ order_modules=`eval echo '$'"${ngx_module}_ORDER"`
+ if [ -n "$order_modules" ]
+ then
+ eval ${ngx_module}_ORDER=\"`echo "$order_modules" | sed -e "s/ \{0,\}$ngx_addon_name//"`\"
+ unset order_modules
+ fi
else
ngx_module_type=CORE
ngx_module_name=$RTMP_CORE_MODULES
diff --git a/dash/ngx_rtmp_dash_module.c b/dash/ngx_rtmp_dash_module.c
index 4d7e595..4d282fa 100644
--- a/dash/ngx_rtmp_dash_module.c
+++ b/dash/ngx_rtmp_dash_module.c
@@ -597,12 +597,12 @@ ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t)
while (left > 0) {
n = ngx_read_fd(t->fd, buffer, ngx_min(sizeof(buffer), left));
- if (n == NGX_ERROR) {
+ if (n == 0 || n == NGX_ERROR) {
break;
}
n = ngx_write_fd(fd, buffer, (size_t) n);
- if (n == NGX_ERROR) {
+ if (n == 0 || n == NGX_ERROR) {
break;
}
diff --git a/hls/ngx_rtmp_hls_module.h b/hls/ngx_rtmp_hls_module.h
index c0c52f4..b2e01d6 100644
--- a/hls/ngx_rtmp_hls_module.h
+++ b/hls/ngx_rtmp_hls_module.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) Winshining
+ * Copyright (C) Winshining
*/
diff --git a/ngx_http_flv_live_module.c b/ngx_http_flv_live_module.c
index 3a8cc09..23479b3 100644
--- a/ngx_http_flv_live_module.c
+++ b/ngx_http_flv_live_module.c
@@ -7,10 +7,7 @@
#include
#include
#include "ngx_http_flv_live_module.h"
-#include "ngx_rtmp_relay_module.h"
-#include "ngx_rtmp_notify_module.h"
#include "ngx_rtmp_bandwidth.h"
-#include "ngx_rtmp_gop_cache_module.h"
static ngx_rtmp_play_pt next_play;
@@ -20,7 +17,7 @@ static ngx_rtmp_close_stream_pt next_close_stream;
static ngx_int_t ngx_http_flv_live_init(ngx_conf_t *cf);
static void *ngx_http_flv_live_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_flv_live_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
+ void *parent, void *child);
static ngx_int_t ngx_http_flv_live_handler(ngx_http_request_t *r);
@@ -28,16 +25,29 @@ static void ngx_http_flv_live_cleanup(void *data);
static ngx_int_t ngx_http_flv_live_init_process(ngx_cycle_t *cycle);
static void ngx_http_flv_live_send_tail(ngx_rtmp_session_t *s);
+static ngx_int_t ngx_http_flv_live_send_message(ngx_rtmp_session_t *s,
+ ngx_chain_t *out, ngx_uint_t priority);
static ngx_chain_t *ngx_http_flv_live_meta_message(ngx_rtmp_session_t *,
- ngx_chain_t *in);
+ ngx_chain_t *in);
static ngx_chain_t *ngx_http_flv_live_append_message(ngx_rtmp_session_t *s,
- ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh, ngx_chain_t *in);
+ ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh, ngx_chain_t *in);
static void ngx_http_flv_live_free_message(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
+ ngx_chain_t *in);
+static ngx_int_t ngx_http_flv_live_join(ngx_rtmp_session_t *s, u_char *name,
+ unsigned int publisher);
+static ngx_chain_t *ngx_http_flv_live_append_shared_bufs(
+ ngx_rtmp_core_srv_conf_t *cscf, ngx_rtmp_header_t *h, ngx_chain_t *in,
+ ngx_flag_t chunked);
+
static void ngx_http_flv_live_close_http_request(ngx_rtmp_session_t *s);
static ngx_int_t ngx_http_flv_live_headers_filter(ngx_rtmp_session_t *s);
static ngx_int_t ngx_http_flv_live_header_filter(ngx_rtmp_session_t *s);
+#if (nginx_version <= 1003014)
+static void ngx_http_do_free_request(ngx_http_request_t *r, ngx_int_t rc);
+static void ngx_http_do_log_request(ngx_http_request_t *r);
+#endif
+
typedef struct ngx_http_header_val_s ngx_http_header_val_t;
@@ -57,7 +67,9 @@ struct ngx_http_header_val_s {
ngx_str_t key;
ngx_http_set_header_pt handler;
ngx_uint_t offset;
+#if (nginx_version >= 1007005)
ngx_uint_t always; /* unsigned always:1 */
+#endif
};
@@ -69,7 +81,9 @@ typedef enum {
typedef struct {
ngx_http_expires_t expires;
time_t expires_time;
+#if (nginx_version >= 1007009)
ngx_http_complex_value_t *expires_value;
+#endif
ngx_array_t *headers;
} ngx_http_headers_conf_t;
@@ -182,28 +196,23 @@ static ngx_int_t ngx_http_flv_live_init_handlers(ngx_cycle_t *cycle);
static ngx_int_t ngx_http_flv_live_request(ngx_rtmp_session_t *s,
- ngx_rtmp_header_t *h, ngx_chain_t *in);
+ ngx_rtmp_header_t *h, ngx_chain_t *in);
-static ngx_int_t ngx_http_flv_live_play(ngx_rtmp_session_t *s,
- ngx_rtmp_play_t *v);
-static ngx_int_t ngx_http_flv_live_close_stream(ngx_rtmp_session_t *s,
- ngx_rtmp_close_stream_t *v);
static void ngx_http_flv_live_free_request(ngx_rtmp_session_t *s);
-static void ngx_http_flv_live_play_handler(ngx_event_t *ev);
static void ngx_http_flv_live_read_handler(ngx_event_t *rev);
static void ngx_http_flv_live_write_handler(ngx_event_t *wev);
static ngx_int_t ngx_http_flv_live_preprocess(ngx_http_request_t *r,
- ngx_rtmp_connection_t *rconn);
+ ngx_rtmp_connection_t *rconn);
static ngx_rtmp_session_t *ngx_http_flv_live_init_connection(
- ngx_http_request_t *r, ngx_rtmp_connection_t *rconn);
+ ngx_http_request_t *r, ngx_rtmp_connection_t *rconn);
static ngx_rtmp_session_t *ngx_http_flv_live_init_session(
- ngx_http_request_t *r, ngx_rtmp_addr_conf_t *add_conf);
+ ngx_http_request_t *r, ngx_rtmp_addr_conf_t *add_conf);
static ngx_int_t ngx_http_flv_live_connect_init(ngx_rtmp_session_t *s,
- ngx_str_t *app, ngx_str_t *stream);
+ ngx_str_t *app, ngx_str_t *stream);
static ngx_http_module_t ngx_http_flv_live_module_ctx = {
@@ -226,13 +235,6 @@ static ngx_command_t ngx_http_flv_live_commands[] = {
offsetof(ngx_http_flv_live_conf_t, flv_live),
NULL },
- { ngx_string("poll_interval"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_flv_live_conf_t, poll_interval),
- NULL },
-
ngx_null_command
};
@@ -253,7 +255,7 @@ ngx_module_t ngx_http_flv_live_module = {
};
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
@@ -273,7 +275,7 @@ ngx_http_flv_live_init(ngx_conf_t *cf)
}
-void *
+static void *
ngx_http_flv_live_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_flv_live_conf_t *conf;
@@ -284,13 +286,12 @@ ngx_http_flv_live_create_loc_conf(ngx_conf_t *cf)
}
conf->flv_live = NGX_CONF_UNSET;
- conf->poll_interval = NGX_CONF_UNSET_MSEC;
return (void *) conf;
}
-char *
+static char *
ngx_http_flv_live_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child)
{
@@ -298,16 +299,6 @@ ngx_http_flv_live_merge_loc_conf(ngx_conf_t *cf,
ngx_http_flv_live_conf_t *conf = child;
ngx_conf_merge_value(conf->flv_live, prev->flv_live, 0);
- ngx_conf_merge_msec_value(conf->poll_interval, prev->poll_interval, 20);
-
- if (conf->poll_interval == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid value \"%ui\" in \"poll_interval\" directive, "
- "it must be greater than 0",
- conf->poll_interval);
-
- return NGX_CONF_ERROR;
- }
return NGX_CONF_OK;
}
@@ -328,17 +319,17 @@ ngx_http_flv_live_init_handlers(ngx_cycle_t *cycle)
h = ngx_array_push(&cmcf->events[NGX_HTTP_FLV_LIVE_REQUEST]);
*h = ngx_http_flv_live_request;
- next_play = ngx_rtmp_play;
- ngx_rtmp_play = ngx_http_flv_live_play;
+ next_play = http_flv_live_next_play;
+ next_close_stream = http_flv_live_next_close_stream;
- next_close_stream = ngx_rtmp_close_stream;
- ngx_rtmp_close_stream = ngx_http_flv_live_close_stream;
+ http_flv_live_next_play = NULL;
+ http_flv_live_next_close_stream = NULL;
return NGX_OK;
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_init_process(ngx_cycle_t *cycle)
{
return ngx_http_flv_live_init_handlers(cycle);
@@ -512,7 +503,7 @@ ngx_http_flv_live_send_header(ngx_rtmp_session_t *s)
/**
* for adding non-standard HTTP headers
**/
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_headers_filter(ngx_rtmp_session_t *s)
{
ngx_str_t value;
@@ -554,9 +545,11 @@ ngx_http_flv_live_headers_filter(ngx_rtmp_session_t *s)
h = conf->headers->elts;
for (i = 0; i < conf->headers->nelts; i++) {
+#if (nginx_version >= 1007005)
if (!safe_status && !h[i].always) {
continue;
}
+#endif
if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
return NGX_ERROR;
@@ -572,7 +565,7 @@ ngx_http_flv_live_headers_filter(ngx_rtmp_session_t *s)
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_header_filter(ngx_rtmp_session_t *s)
{
u_char *p;
@@ -884,7 +877,8 @@ ngx_http_flv_live_header_filter(ngx_rtmp_session_t *s)
"%*s", (size_t) (b->last - b->pos), b->pos);
/* the end of HTTP header */
- *b->last++ = CR; *b->last++ = LF;
+ *b->last++ = CR;
+ *b->last++ = LF;
r->header_size = b->last - b->pos;
@@ -905,7 +899,7 @@ ngx_http_flv_live_header_filter(ngx_rtmp_session_t *s)
}
-void
+static void
ngx_http_flv_live_send_tail(ngx_rtmp_session_t *s)
{
ngx_rtmp_core_srv_conf_t *cscf;
@@ -930,13 +924,13 @@ ngx_http_flv_live_send_tail(ngx_rtmp_session_t *s)
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_send_message(ngx_rtmp_session_t *s,
- ngx_chain_t *out, ngx_uint_t priority)
+ ngx_chain_t *out, ngx_uint_t priority)
{
ngx_uint_t nmsg;
- nmsg = (s->out_last - s->out_pos) % s->out_queue + 1;
+ nmsg = (s->out_last + s->out_queue - s->out_pos) % s->out_queue + 1;
if (priority > 3) {
priority = 3;
@@ -946,13 +940,9 @@ ngx_http_flv_live_send_message(ngx_rtmp_session_t *s,
* Note we always leave 1 slot free */
if (nmsg + priority * s->out_queue / 4 >= s->out_queue) {
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv live: HTTP drop message bufs='%ui', priority='%ui'",
+ "flv live: HTTP drop message bufs=%ui, priority=%ui",
nmsg, priority);
- if (s->gop_cache.out[s->out_last].set) {
- ngx_rtmp_gop_cache_exec_handler(s, s->out_last, out);
- }
-
return NGX_AGAIN;
}
@@ -962,7 +952,7 @@ ngx_http_flv_live_send_message(ngx_rtmp_session_t *s,
ngx_rtmp_acquire_shared_chain(out);
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv live: HTTP send nmsg='%ui', priority='%ui' '#%ui'",
+ "flv live: HTTP send nmsg=%ui, priority=%ui #%ui",
nmsg, priority, s->out_last);
if (priority && s->out_buffer && nmsg < s->out_cork) {
@@ -977,24 +967,30 @@ ngx_http_flv_live_send_message(ngx_rtmp_session_t *s,
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_request(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
- ngx_chain_t *in)
+ ngx_chain_t *in)
{
static ngx_rtmp_play_t v;
+ ngx_int_t rc;
ngx_http_request_t *r;
ngx_http_flv_live_ctx_t *ctx;
r = s->data;
ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
- if (ngx_http_flv_live_connect_init(s, &ctx->app, &ctx->stream) != NGX_OK)
- {
- s->wait_notify_connect = 0;
+ rc = ngx_http_flv_live_connect_init(s, &ctx->app, &ctx->stream);
+ if (rc != NGX_OK) {
return NGX_ERROR;
}
+ if (s->notify_connect) {
+ r->main->count++;
+
+ return NGX_OK;
+ }
+
ngx_memzero(&v, sizeof(ngx_rtmp_play_t));
ngx_memcpy(v.name, ctx->stream.data, ngx_min(ctx->stream.len,
@@ -1003,26 +999,18 @@ ngx_http_flv_live_request(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
sizeof(v.args) - 1));
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "flv live: name='%s' args='%s' start='%i' duration='%i' "
- "reset='%i' silent='%i'",
+ "flv live: name='%s' args='%s' start=%i duration=%i "
+ "reset=%i silent=%i",
v.name, v.args, (ngx_int_t) v.start,
(ngx_int_t) v.duration, (ngx_int_t) v.reset,
(ngx_int_t) v.silent);
- if (s->wait_notify_connect) {
- ngx_memzero(&ctx->play, sizeof(ngx_event_t));
- ctx->play.handler = ngx_http_flv_live_play_handler;
- ctx->play.log = s->connection->log;
- ctx->play.data = s->connection;
-
+ rc = ngx_rtmp_play(s, &v);
+ if (rc == NGX_OK && s->notify_play) {
r->main->count++;
-
- ngx_http_flv_live_play_handler(&ctx->play);
-
- return NGX_OK;
}
- return ngx_rtmp_play(s, &v);
+ return rc;
}
@@ -1064,17 +1052,14 @@ ngx_http_flv_live_set_status(ngx_rtmp_session_t *s, unsigned active)
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_join(ngx_rtmp_session_t *s, u_char *name,
- unsigned int publisher)
+ unsigned int publisher)
{
ngx_rtmp_live_ctx_t *ctx;
ngx_rtmp_live_stream_t **stream;
ngx_rtmp_live_app_conf_t *lacf;
- ngx_rtmp_relay_app_conf_t *racf;
- ngx_flag_t create;
-
/* only for subscribers */
if (publisher) {
return NGX_DECLINED;
@@ -1101,52 +1086,21 @@ ngx_http_flv_live_join(ngx_rtmp_session_t *s, u_char *name,
ngx_memzero(ctx, sizeof(*ctx));
ctx->session = s;
- create = 0;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"flv live: join '%s'", name);
- racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module);
- if (racf && racf->pulls.nelts) {
- create = 1;
- }
-
- stream = ngx_rtmp_live_get_stream(s, name,
- lacf->idle_streams || s->wait_notify_play || create);
+ stream = ngx_rtmp_live_get_stream(s, name, lacf->idle_streams);
if (stream == NULL ||
- !(publisher || (*stream)->publishing || lacf->idle_streams ||
- s->wait_notify_play || create))
+ !(publisher || (*stream)->publishing || lacf->idle_streams))
{
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"flv live: stream not found");
- s->wait_notify_play = 0;
return NGX_ERROR;
}
- if ((*stream)->pub_ctx == NULL || !(*stream)->pub_ctx->publishing) {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "flv live: stream not publishing, check relay pulls");
-
- do {
- if (s->wait_notify_play) {
- break;
- }
-
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "flv live: no on_play, check relay pulls");
-
- /* check if there are some pulls */
- if (!create) {
- ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "flv live: no on_play or relay pull, quit");
-
- return NGX_ERROR;
- }
- } while (0);
- }
-
ctx->stream = *stream;
ctx->publishing = publisher;
ctx->next = (*stream)->ctx;
@@ -1177,42 +1131,32 @@ ngx_int_t
ngx_http_flv_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
{
ngx_rtmp_live_app_conf_t *lacf;
- ngx_rtmp_notify_app_conf_t *nacf;
ngx_http_request_t *r;
- lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module);
- if (lacf == NULL || !lacf->live) {
+ r = s->data;
+ if (r == NULL) {
goto next;
}
- nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
- if (!s->relay && nacf && nacf->url[NGX_RTMP_NOTIFY_PLAY]) {
- s->wait_notify_play = 1;
- }
-
- r = s->data;
- if (r == NULL) {
+ lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module);
+ if (lacf == NULL || !lacf->live) {
goto next;
}
r->main->count++;
#if (nginx_version >= 1013001)
- /**
- * when playing from pull, the downstream requests on the most
- * of time return before the upstream requests, flv.js always
- * sends HTTP header 'Connection: keep-alive', but Nginx has
- * deleted r->blocked in ngx_http_finalize_request, that causes
- * ngx_http_set_keepalive to run the cleanup handlers to close
+ /**
+ * when playing from pull, the downstream requests on the most
+ * of time return before the upstream requests, flv.js always
+ * sends HTTP header 'Connection: keep-alive', but Nginx has
+ * deleted r->blocked in ngx_http_finalize_request, that causes
+ * ngx_http_set_keepalive to run the cleanup handlers to close
* the connection between downstream and server, so play fails
**/
r->keepalive = 0;
#endif
- if (s->wait_notify_play) {
- goto next;
- }
-
/* join stream as a subscriber */
if (ngx_http_flv_live_join(s, v->name, 0) == NGX_ERROR) {
@@ -1221,16 +1165,8 @@ ngx_http_flv_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
return NGX_ERROR;
}
- if (ngx_rtmp_process_request_line(s, v->name, v->args,
- (const u_char *) "flv live play") != NGX_OK)
- {
- r->main->count--;
-
- return NGX_ERROR;
- }
-
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv live play: name='%s' start='%uD' duration='%uD' reset='%d'",
+ "flv live play: name='%s' start=%uD duration=%uD reset=%d",
v->name, (uint32_t) v->start,
(uint32_t) v->duration, (uint32_t) v->reset);
@@ -1257,7 +1193,7 @@ ngx_http_flv_live_close_http_request(ngx_rtmp_session_t *s)
ngx_int_t
ngx_http_flv_live_close_stream(ngx_rtmp_session_t *s,
- ngx_rtmp_close_stream_t *v)
+ ngx_rtmp_close_stream_t *v)
{
ngx_rtmp_live_ctx_t *ctx, **cctx, *unlink;
ngx_http_request_t *r;
@@ -1337,6 +1273,7 @@ ngx_http_flv_live_close_stream(ngx_rtmp_session_t *s,
ctx->stream = NULL;
ngx_http_flv_live_free_request(s);
+ s->connection->destroyed = 1;
break;
} else {
@@ -1345,16 +1282,17 @@ ngx_http_flv_live_close_stream(ngx_rtmp_session_t *s,
}
}
- /**
- * close only http requests here, the other
- * requests were left for next_clost_stream
+ /**
+ * close only http requests here, the other
+ * requests were left for next_clost_stream
**/
next:
- if (s->wait_notify_connect || s->wait_notify_play) {
+ if (s->notify_connect || s->notify_play) {
r = s->data;
if (r) {
ngx_http_flv_live_free_request(s);
+ s->connection->destroyed = 1;
}
}
@@ -1367,7 +1305,6 @@ ngx_http_flv_live_free_request(ngx_rtmp_session_t *s)
{
ngx_http_request_t *r;
ngx_http_cleanup_t **cln;
- ngx_http_flv_live_ctx_t *ctx;
r = s->data;
if (r) {
@@ -1380,12 +1317,11 @@ ngx_http_flv_live_free_request(ngx_rtmp_session_t *s)
cln = &(*cln)->next;
}
- ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
- if (ctx && ctx->play.timer_set) {
- ngx_del_timer(&ctx->play);
- }
-
+#if (nginx_version <= 1003014)
+ ngx_http_do_free_request(r, 0);
+#else
ngx_http_free_request(r, 0);
+#endif
#if (NGX_HTTP_SSL)
if (r->connection->ssl) {
@@ -1399,56 +1335,115 @@ ngx_http_flv_live_free_request(ngx_rtmp_session_t *s)
}
-void
-ngx_http_flv_live_play_handler(ngx_event_t *ev)
+#if (nginx_version <= 1003014)
+static void
+ngx_http_do_free_request(ngx_http_request_t *r, ngx_int_t rc)
{
- static ngx_rtmp_play_t v;
+ ngx_log_t *log;
+ ngx_pool_t *pool;
+ struct linger linger;
+ ngx_http_cleanup_t *cln;
+ ngx_http_log_ctx_t *ctx;
+ ngx_http_core_loc_conf_t *clcf;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_rtmp_session_t *s;
- ngx_http_flv_live_ctx_t *ctx;
- ngx_http_flv_live_conf_t *hfcf;
+ log = r->connection->log;
- c = ev->data;
- if (c->destroyed) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
+
+ if (r->pool == NULL) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
return;
}
- r = c->data;
- ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
- s = ctx->s;
+ cln = r->cleanup;
+ r->cleanup = NULL;
+
+ while (cln) {
+ if (cln->handler) {
+ cln->handler(cln->data);
+ }
- if (ev->timer_set) {
- ngx_del_timer(ev);
+ cln = cln->next;
}
- if (!s->wait_notify_connect) {
- ngx_memzero(&v, sizeof(ngx_rtmp_play_t));
+#if (NGX_STAT_STUB)
- ngx_memcpy(v.name, ctx->stream.data, ngx_min(ctx->stream.len,
- sizeof(v.name) - 1));
- ngx_memcpy(v.args, s->args.data, ngx_min(s->args.len,
- sizeof(v.args) - 1));
+ if (r->stat_reading) {
+ (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
+ }
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "flv live: name='%s' args='%s' start='%i' duration='%i' "
- "reset='%i' silent='%i'",
- v.name, v.args, (ngx_int_t) v.start,
- (ngx_int_t) v.duration, (ngx_int_t) v.reset,
- (ngx_int_t) v.silent);
+ if (r->stat_writing) {
+ (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
+ }
- r->main->count--;
+#endif
- ngx_rtmp_play(s, &v);
- } else {
- hfcf = ngx_http_get_module_loc_conf(r, ngx_http_flv_live_module);
- ngx_add_timer(ev, hfcf->poll_interval);
+ if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
+ r->headers_out.status = rc;
+ }
+
+ log->action = "logging request";
+
+ ngx_http_do_log_request(r);
+
+ log->action = "closing request";
+
+ if (r->connection->timedout) {
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (clcf->reset_timedout_connection) {
+ linger.l_onoff = 1;
+ linger.l_linger = 0;
+
+ if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
+ (const void *) &linger, sizeof(struct linger)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
+ "setsockopt(SO_LINGER) failed");
+ }
+ }
}
+
+ /* the various request strings were allocated from r->pool */
+ ctx = log->data;
+ ctx->request = NULL;
+
+ r->request_line.len = 0;
+
+ r->connection->destroyed = 1;
+
+ /*
+ * Setting r->pool to NULL will increase probability to catch double close
+ * of request since the request object is allocated from its own pool.
+ */
+
+ pool = r->pool;
+ r->pool = NULL;
+
+ ngx_destroy_pool(pool);
}
-void
+static void
+ngx_http_do_log_request(ngx_http_request_t *r)
+{
+ ngx_uint_t i, n;
+ ngx_http_handler_pt *log_handler;
+ ngx_http_core_main_conf_t *cmcf;
+
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
+ n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
+
+ for (i = 0; i < n; i++) {
+ log_handler[i](r);
+ }
+}
+#endif
+
+
+static void
ngx_http_flv_live_read_handler(ngx_event_t *rev)
{
ngx_connection_t *c;
@@ -1459,29 +1454,34 @@ ngx_http_flv_live_read_handler(ngx_event_t *rev)
u_char buf[NGX_BUFF_MAX_SIZE];
c = rev->data;
- r = c->data;
if (c->destroyed) {
return;
}
+ r = c->data;
ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
s = ctx->s;
- n = c->recv(c, buf, sizeof(buf));
+ for ( ;; ) {
+ n = c->recv(c, buf, sizeof(buf));
+
+ if (n == NGX_AGAIN) {
+ ngx_add_timer(c->read, s->timeout);
- if (n == NGX_AGAIN) {
- ngx_add_timer(c->read, s->timeout);
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
+ ngx_rtmp_finalize_session(s);
+ }
- if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
+ break;
+ } else if (n == 0 || n == -1) {
ngx_rtmp_finalize_session(s);
+ break;
}
- } else {
- ngx_rtmp_finalize_session(s);
}
}
-void
+static void
ngx_http_flv_live_write_handler(ngx_event_t *wev)
{
ngx_connection_t *c;
@@ -1492,15 +1492,14 @@ ngx_http_flv_live_write_handler(ngx_event_t *wev)
ngx_http_flv_live_ctx_t *ctx;
c = wev->data;
- r = c->data;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
- s = ctx->s;
-
if (c->destroyed) {
return;
}
+ r = c->data;
+ ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
+ s = ctx->s;
+
if (wev->timedout) {
ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
"flv live: client timed out");
@@ -1542,14 +1541,8 @@ ngx_http_flv_live_write_handler(ngx_event_t *wev)
if (s->out_bpos == s->out_chain->buf->last) {
s->out_chain = s->out_chain->next;
if (s->out_chain == NULL) {
- if (s->gop_cache.out[s->out_pos].set) {
- ngx_rtmp_gop_cache_exec_handler(s, s->out_pos,
- s->out[s->out_pos]);
- } else {
- cscf = ngx_rtmp_get_module_srv_conf(s,
- ngx_rtmp_core_module);
- ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
- }
+ cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
+ ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
s->out[s->out_pos] = NULL;
++s->out_pos;
s->out_pos %= s->out_queue;
@@ -1570,7 +1563,7 @@ ngx_http_flv_live_write_handler(ngx_event_t *wev)
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_preprocess(ngx_http_request_t *r,
ngx_rtmp_connection_t *rconn)
{
@@ -1601,9 +1594,9 @@ ngx_http_flv_live_preprocess(ngx_http_request_t *r,
ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module);
- /**
- * if requested args are escaped, for example, urls in the
- * history list of vlc for Android (or all mobile platforms)
+ /**
+ * if requested args are escaped, for example, urls in the
+ * history list of vlc for Android (or all mobile platforms)
**/
if (r->args.len == 0 && r->uri.len) {
ngx_http_split_args(r, &r->uri, &r->args);
@@ -1632,10 +1625,24 @@ ngx_http_flv_live_preprocess(ngx_http_request_t *r,
for (n = 0; n < ngx_cycle->listening.nelts; ++n, ++ls) {
if (ls->handler == ngx_rtmp_init_connection) {
local_sockaddr = r->connection->local_sockaddr;
- sa_family = ls->sockaddr->sa_family;
+ sa_family = local_sockaddr->sa_family;
- if (local_sockaddr->sa_family != sa_family) {
- continue;
+ if (sa_family != ls->sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+ if (ls->sockaddr->sa_family == AF_INET6) {
+ if (ls->ipv6only) {
+#endif
+ continue;
+#if (NGX_HAVE_INET6)
+ } else {
+ if (local_sockaddr->sa_family != AF_INET) {
+ continue;
+ }
+
+ sa_family = AF_INET6;
+ }
+ }
+#endif
}
switch (sa_family) {
@@ -1811,13 +1818,19 @@ ngx_http_flv_live_init_connection(ngx_http_request_t *r,
c->write->handler = ngx_http_flv_live_write_handler;
c->read->handler = ngx_http_flv_live_read_handler;
+ if (c->write->active) {
+ if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) != NGX_OK) {
+ return NULL;
+ }
+ }
+
return s;
}
-ngx_rtmp_session_t *
+static ngx_rtmp_session_t *
ngx_http_flv_live_init_session(ngx_http_request_t *r,
- ngx_rtmp_addr_conf_t *addr_conf)
+ ngx_rtmp_addr_conf_t *addr_conf)
{
ngx_rtmp_session_t *s;
ngx_rtmp_core_srv_conf_t *cscf;
@@ -1829,7 +1842,7 @@ ngx_http_flv_live_init_session(ngx_http_request_t *r,
s = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_session_t));
if (s == NULL) {
/* let other handlers process */
- return NULL;
+ goto failed;
}
s->rtmp_connection = c->data;
@@ -1843,7 +1856,7 @@ ngx_http_flv_live_init_session(ngx_http_request_t *r,
ctx = ngx_palloc(c->pool, sizeof(ngx_rtmp_error_log_ctx_t));
if (ctx == NULL) {
- return NULL;
+ goto failed;
}
ctx->client = &c->addr_text;
@@ -1858,12 +1871,12 @@ ngx_http_flv_live_init_session(ngx_http_request_t *r,
s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_rtmp_max_module);
if (s->ctx == NULL) {
- return NULL;
+ goto failed;
}
s->out_pool = ngx_create_pool(4096, c->log);
if (s->out_pool == NULL) {
- return NULL;
+ goto failed;
}
s->out = ngx_pcalloc(s->out_pool, sizeof(ngx_chain_t *)
@@ -1871,21 +1884,12 @@ ngx_http_flv_live_init_session(ngx_http_request_t *r,
addr_conf->default_server->ctx->srv_conf
[ngx_rtmp_core_module.ctx_index])->out_queue);
if (s->out == NULL) {
- return NULL;
- }
-
- s->gop_cache.out = ngx_pcalloc(s->out_pool,
- sizeof(ngx_rtmp_gop_cache_free_t)
- * ((ngx_rtmp_core_srv_conf_t *)
- addr_conf->default_server->ctx->srv_conf
- [ngx_rtmp_core_module.ctx_index])->out_queue);
- if (s->gop_cache.out == NULL) {
- return NULL;
+ goto failed;
}
s->in_streams_pool = ngx_create_pool(4096, c->log);
if (s->in_streams_pool == NULL) {
- return NULL;
+ goto failed;
}
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
@@ -1895,7 +1899,7 @@ ngx_http_flv_live_init_session(ngx_http_request_t *r,
s->in_streams = ngx_pcalloc(s->in_streams_pool, sizeof(ngx_rtmp_stream_t)
* cscf->max_streams);
if (s->in_streams == NULL) {
- return NULL;
+ goto failed;
}
#if (nginx_version >= 1007005)
@@ -1905,26 +1909,38 @@ ngx_http_flv_live_init_session(ngx_http_request_t *r,
s->epoch = ngx_current_msec;
s->timeout = cscf->timeout;
s->buflen = cscf->buflen;
- s->gop_cache.count = 0;
ngx_rtmp_set_chunk_size(s, NGX_RTMP_DEFAULT_CHUNK_SIZE);
if (ngx_rtmp_fire_event(s, NGX_RTMP_CONNECT, NULL, NULL) != NGX_OK) {
- return NULL;
+ goto failed;
}
s->data = (void *) r;
return s;
+
+failed:
+ if (s->out_pool) {
+ ngx_destroy_pool(s->out_pool);
+ s->out_pool = NULL;
+ }
+
+ if (s->in_streams_pool) {
+ ngx_destroy_pool(s->in_streams_pool);
+ s->in_streams_pool = NULL;
+ }
+
+ return NULL;
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_connect_init(ngx_rtmp_session_t *s, ngx_str_t *app,
- ngx_str_t *stream)
+ ngx_str_t *stream)
{
ngx_rtmp_connect_t v;
ngx_http_request_t *r;
- ngx_rtmp_notify_srv_conf_t *nscf;
+ u_char name[NGX_RTMP_MAX_NAME];
r = s->data;
@@ -1949,6 +1965,15 @@ ngx_http_flv_live_connect_init(ngx_rtmp_session_t *s, ngx_str_t *app,
#undef NGX_RTMP_SET_STRPAR
+ ngx_memzero(name, NGX_RTMP_MAX_NAME);
+ ngx_memcpy(name, stream->data, stream->len);
+
+ if (ngx_rtmp_process_request_line(s, name, v.args,
+ (const u_char *) "flv live connect") != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
if (ngx_rtmp_process_virtual_host(s) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"flv live: failed to process virtual host");
@@ -1956,11 +1981,6 @@ ngx_http_flv_live_connect_init(ngx_rtmp_session_t *s, ngx_str_t *app,
return NGX_ERROR;
}
- nscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_notify_module);
- if (nscf && nscf->url[NGX_RTMP_NOTIFY_CONNECT]) {
- s->wait_notify_connect = 1;
- }
-
s->stream.len = stream->len;
s->stream.data = ngx_pstrdup(s->connection->pool, stream);
@@ -1968,7 +1988,7 @@ ngx_http_flv_live_connect_init(ngx_rtmp_session_t *s, ngx_str_t *app,
}
-ngx_chain_t *
+static ngx_chain_t *
ngx_http_flv_live_meta_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
{
ngx_rtmp_core_srv_conf_t *cscf;
@@ -1982,7 +2002,6 @@ ngx_http_flv_live_meta_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
r = s->data;
if (r == NULL || (r->connection && r->connection->destroyed)) {
- ngx_rtmp_free_shared_chain(cscf, in);
return NULL;
}
@@ -1993,9 +2012,9 @@ ngx_http_flv_live_meta_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
}
-ngx_chain_t *
+static ngx_chain_t *
ngx_http_flv_live_append_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
- ngx_rtmp_header_t *lh, ngx_chain_t *in)
+ ngx_rtmp_header_t *lh, ngx_chain_t *in)
{
ngx_rtmp_core_srv_conf_t *cscf;
ngx_http_request_t *r;
@@ -2007,7 +2026,6 @@ ngx_http_flv_live_append_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
r = s->data;
if (r == NULL || (r->connection && r->connection->destroyed)) {
- ngx_rtmp_free_shared_chain(cscf, in);
return NULL;
}
@@ -2022,9 +2040,9 @@ ngx_http_flv_live_append_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
* |Reserved(2b)+Filter(1b)+TagType(5b)|DataLength(3B)|TimeStamp(3B)|
* TimeStampExt(1B)|StreamID(3B)|Data(DataLengthB)|PreviousTagSize|
*/
-ngx_chain_t *
+static ngx_chain_t *
ngx_http_flv_live_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
- ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_flag_t chunked)
+ ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_flag_t chunked)
{
ngx_chain_t *tag, *chunk_head, *chunk_tail, chunk,
*iter, *last_in, **tail, prev_tag_size;
@@ -2158,7 +2176,7 @@ ngx_http_flv_live_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
}
-void
+static void
ngx_http_flv_live_free_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
{
ngx_rtmp_core_srv_conf_t *cscf;
@@ -2199,9 +2217,7 @@ ngx_http_flv_live_close_session_handler(ngx_rtmp_session_t *s)
}
while (s->out_pos != s->out_last) {
- if (!s->gop_cache.out[s->out_pos].set) {
- ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
- }
+ ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
s->out_pos++;
s->out_pos %= s->out_queue;
@@ -2231,7 +2247,7 @@ ngx_http_flv_live_cleanup(void *data)
}
-ngx_int_t
+static ngx_int_t
ngx_http_flv_live_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
@@ -2241,6 +2257,15 @@ ngx_http_flv_live_handler(ngx_http_request_t *r)
ngx_rtmp_session_t *s;
ngx_rtmp_connection_t *rconn;
+ if (ngx_exiting || ngx_terminate) {
+ return NGX_HTTP_CLOSE;
+ }
+
+ hfcf = ngx_http_get_module_loc_conf(r, ngx_http_flv_live_module);
+ if (!hfcf->flv_live) {
+ return NGX_DECLINED;
+ }
+
if (!(r->method & (NGX_HTTP_GET))) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"flv live: HTTP method was not \"GET\"");
@@ -2259,11 +2284,6 @@ ngx_http_flv_live_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- hfcf = ngx_http_get_module_loc_conf(r, ngx_http_flv_live_module);
- if (!hfcf->flv_live) {
- return NGX_DECLINED;
- }
-
rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK) {
@@ -2317,4 +2337,3 @@ ngx_http_flv_live_handler(ngx_http_request_t *r)
return NGX_OK;
}
-
diff --git a/ngx_http_flv_live_module.h b/ngx_http_flv_live_module.h
index fbc6690..e0f3ada 100644
--- a/ngx_http_flv_live_module.h
+++ b/ngx_http_flv_live_module.h
@@ -21,6 +21,10 @@
extern ngx_module_t ngx_rtmp_module;
+ngx_rtmp_play_pt http_flv_live_next_play;
+ngx_rtmp_close_stream_pt http_flv_live_next_close_stream;
+
+
#define ngx_rtmp_cycle_get_module_main_conf(cycle, module) \
(cycle->conf_ctx[ngx_rtmp_module.index] ? \
((ngx_rtmp_conf_ctx_t *) cycle->conf_ctx[ngx_rtmp_module.index]) \
@@ -36,14 +40,11 @@ typedef struct ngx_http_flv_live_ctx_s {
ngx_str_t app;
ngx_str_t port;
ngx_str_t stream;
-
- ngx_event_t play;
} ngx_http_flv_live_ctx_t;
typedef struct ngx_http_flv_live_conf_s {
ngx_flag_t flv_live;
- ngx_msec_t poll_interval;
} ngx_http_flv_live_conf_t;
@@ -54,28 +55,24 @@ typedef struct {
ngx_chain_t *rpkt;
ngx_int_t (*send_message_pt)(ngx_rtmp_session_t *s,
- ngx_chain_t *out, ngx_uint_t priority);
+ ngx_chain_t *out, ngx_uint_t priority);
ngx_chain_t *(*meta_message_pt)(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
+ ngx_chain_t *in);
ngx_chain_t *(*append_message_pt)(ngx_rtmp_session_t *s,
- ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh,
- ngx_chain_t *in);
+ ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh,
+ ngx_chain_t *in);
void (*free_message_pt)(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
+ ngx_chain_t *in);
} ngx_rtmp_live_proc_handler_t;
-ngx_int_t ngx_http_flv_live_join(ngx_rtmp_session_t *s, u_char *name,
- unsigned int publisher);
+ngx_int_t ngx_http_flv_live_play(ngx_rtmp_session_t *s,
+ ngx_rtmp_play_t *v);
+ngx_int_t ngx_http_flv_live_close_stream(ngx_rtmp_session_t *s,
+ ngx_rtmp_close_stream_t *v);
+
ngx_int_t ngx_http_flv_live_send_header(ngx_rtmp_session_t *s);
void ngx_http_flv_live_set_status(ngx_rtmp_session_t *s, unsigned active);
-ngx_chain_t *ngx_http_flv_live_append_shared_bufs(
- ngx_rtmp_core_srv_conf_t *cscf,
- ngx_rtmp_header_t *h,
- ngx_chain_t *in,
- ngx_flag_t chunked);
-ngx_int_t ngx_http_flv_live_send_message(ngx_rtmp_session_t *s,
- ngx_chain_t *out, ngx_uint_t priority);
#endif
diff --git a/ngx_rtmp.c b/ngx_rtmp.c
index 44465f5..2c564ad 100644
--- a/ngx_rtmp.c
+++ b/ngx_rtmp.c
@@ -777,7 +777,7 @@ ngx_rtmp_init_listening(ngx_conf_t *cf, ngx_rtmp_conf_port_t *port)
break;
}
-#if (NGX_HAVE_REUSEPORT)
+#if (nginx_version >= 1009001 && nginx_version <= 1015001)
if (ngx_clone_listening(cf, ls) != NGX_OK) {
return NGX_ERROR;
}
@@ -1321,12 +1321,6 @@ ngx_rtmp_set_virtual_server(ngx_rtmp_session_t *s, ngx_str_t *host)
cscf->ctx->srv_conf[ngx_rtmp_core_module
.ctx_index])->out_queue);
- s->gop_cache.out = ngx_pcalloc(s->out_pool,
- sizeof(ngx_rtmp_gop_cache_free_t)
- * ((ngx_rtmp_core_srv_conf_t *)
- cscf->ctx->srv_conf[ngx_rtmp_core_module
- .ctx_index])->out_queue);
-
s->out_queue = cscf->out_queue;
}
diff --git a/ngx_rtmp.h b/ngx_rtmp.h
index fa9e0e6..036a1ee 100644
--- a/ngx_rtmp.h
+++ b/ngx_rtmp.h
@@ -25,7 +25,6 @@ typedef struct ngx_rtmp_virtual_names_s ngx_rtmp_virtual_names_t;
#include "ngx_rtmp_variables.h"
-#include "ngx_rtmp_script.h"
#if (NGX_WIN32)
@@ -265,20 +264,6 @@ typedef struct {
#endif
-typedef void (*free_message_pt)(ngx_rtmp_session_t *s, ngx_chain_t *in);
-
-typedef struct {
- free_message_pt free;
- ngx_flag_t set;
-} ngx_rtmp_gop_cache_free_t;
-
-
-typedef struct {
- ngx_rtmp_gop_cache_free_t *out;
- ngx_uint_t count;
-} ngx_rtmp_gop_cache_handler_t;
-
-
struct ngx_rtmp_session_s {
uint32_t signature; /* "RTMP" */ /* <-- FIXME wtf */
@@ -368,9 +353,7 @@ struct ngx_rtmp_session_s {
u_char *port_end;
unsigned keepalive:1;
- unsigned lingering_close:1;
- unsigned valid_application:1;
unsigned valid_unparsed_uri:1;
#if (NGX_PCRE)
@@ -379,9 +362,6 @@ struct ngx_rtmp_session_s {
u_char *captures_data;
#endif
- size_t limit_rate;
- size_t limit_rate_after;
-
ngx_rtmp_connection_t *rtmp_connection;
ngx_rtmp_session_t *publisher;
@@ -393,10 +373,8 @@ struct ngx_rtmp_session_s {
ngx_pool_t *out_temp_pool;
unsigned server_changed:1;
- unsigned wait_notify_connect:1;
- unsigned wait_notify_play:1;
-
- ngx_rtmp_gop_cache_handler_t gop_cache;
+ unsigned notify_connect:1;
+ unsigned notify_play:1;
/* input stream 0 (reserved by RTMP spec)
* is used as free chain link */
@@ -509,7 +487,6 @@ struct ngx_rtmp_core_srv_conf_s {
size_t connection_pool_size;
ngx_flag_t merge_slashes;
- ngx_flag_t listen_parsed;
unsigned listen:1;
#if (NGX_PCRE)
@@ -535,25 +512,12 @@ typedef struct {
ngx_rtmp_regex_t *regex;
#endif
- unsigned noname:1; /* "if () {}" block or limit_except */
- unsigned named:1;
-
size_t send_lowat;
- size_t postpone_output;
- size_t limit_rate;
- size_t limit_rate_after;
- size_t sendfile_max_chunk;
ngx_msec_t send_timeout;
- ngx_msec_t keepalive_timeout;
- ngx_msec_t lingering_time;
- ngx_msec_t lingering_timeout;
ngx_msec_t resolver_timeout;
ngx_resolver_t *resolver;
-
- ngx_flag_t tcp_nopush;
- ngx_flag_t tcp_nodelay;
} ngx_rtmp_core_app_conf_t;
diff --git a/ngx_rtmp_auto_push_module.c b/ngx_rtmp_auto_push_module.c
index 60c85d7..255cf55 100644
--- a/ngx_rtmp_auto_push_module.c
+++ b/ngx_rtmp_auto_push_module.c
@@ -121,7 +121,7 @@ ngx_module_t ngx_rtmp_auto_push_index_module = {
};
-#define NGX_RTMP_AUTO_PUSH_SOCKNAME "nginx-rtmp"
+#define NGX_RTMP_AUTO_PUSH_SOCKNAME "nginx-http-flv"
static ngx_int_t
diff --git a/ngx_rtmp_cmd_module.c b/ngx_rtmp_cmd_module.c
index befb7ad..ac3c9b7 100644
--- a/ngx_rtmp_cmd_module.c
+++ b/ngx_rtmp_cmd_module.c
@@ -339,7 +339,6 @@ ngx_rtmp_cmd_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v)
{
/* found app! */
s->app_conf = (*cacfp)->app_conf;
- s->valid_application = 1;
break;
}
}
@@ -352,10 +351,6 @@ ngx_rtmp_cmd_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v)
object_encoding = v->object_encoding;
- if (s->wait_notify_connect) {
- s->wait_notify_connect = 0;
- }
-
return ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK ||
ngx_rtmp_send_bandwidth(s, cscf->ack_window,
NGX_RTMP_LIMIT_DYNAMIC) != NGX_OK ||
diff --git a/ngx_rtmp_cmd_module.h b/ngx_rtmp_cmd_module.h
index 075f1bd..be448f2 100644
--- a/ngx_rtmp_cmd_module.h
+++ b/ngx_rtmp_cmd_module.h
@@ -25,7 +25,7 @@ typedef struct {
double trans;
u_char app[NGX_RTMP_MAX_NAME];
u_char args[NGX_RTMP_MAX_ARGS];
- u_char flashver[32];
+ u_char flashver[64];
u_char swf_url[NGX_RTMP_MAX_URL];
u_char tc_url[NGX_RTMP_MAX_URL];
double acodecs;
diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c
index 2502517..b320079 100644
--- a/ngx_rtmp_codec_module.c
+++ b/ngx_rtmp_codec_module.c
@@ -303,7 +303,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
ftype = (fmt & 0xf0) >> 4;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: ftype='%uD'", ftype);
+ "codec: ftype=%uD", ftype);
if (ftype != NGX_RTMP_FRAME_IDR) {
return NGX_ERROR;
@@ -315,7 +315,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: htype='%uD'", htype);
+ "codec: htype=%uD", htype);
/* proceed only with PICT */
if (htype != 1) {
@@ -361,7 +361,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
nal_bytes = ctx->avc_nal_bytes;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: nal_bytes='%uD'", nal_bytes);
+ "codec: nal_bytes=%uD", nal_bytes);
left = NGX_RTMP_SPS_MAX_LENGTH;
@@ -374,11 +374,11 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
ngx_rtmp_rmemcpy(&len, &rlen, nal_bytes);
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: len='%uD'", len);
+ "codec: len=%uD", len);
if (len == 0) {
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: skip, len='%uD'", len);
+ "codec: skip, len=%uD", len);
continue;
}
@@ -388,7 +388,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: src_nal_type='%uD'", src_nal_type);
+ "codec: src_nal_type=%uD", src_nal_type);
/**
* +---------------+
@@ -400,7 +400,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
nal_type = src_nal_type & 0x1f;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: nal_type='%uD'", nal_type);
+ "codec: nal_type=%uD", nal_type);
if (!(nal_type >= NGX_RTMP_NALU_SPS
&& nal_type <= NGX_RTMP_NALU_PPS))
@@ -410,7 +410,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: skip non-sps or non-pps, nal_type='%uD'", nal_type);
+ "codec: skip non-sps or non-pps, nal_type=%uD", nal_type);
continue;
}
@@ -443,7 +443,7 @@ ngx_rtmp_codec_parse_avc_header_in_keyframe(ngx_rtmp_session_t *s,
has_sps = 1;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: has_sps='%uD'", has_sps);
+ "codec: has_sps=%uD", has_sps);
}
return (has_sps == 1) ? NGX_OK : NGX_ERROR;
@@ -887,7 +887,7 @@ ngx_rtmp_codec_reconstruct_meta(ngx_rtmp_session_t *s)
{ NGX_RTMP_AMF_STRING,
ngx_string("Server"),
- "NGINX RTMP (https://github.com/winshining/nginx-http-flv-module)", 0 },
+ "NGINX HTTP-FLV (https://github.com/winshining/nginx-http-flv-module)", 0 },
{ NGX_RTMP_AMF_NUMBER,
ngx_string("width"),
diff --git a/ngx_rtmp_core_module.c b/ngx_rtmp_core_module.c
index 21b5777..a745955 100644
--- a/ngx_rtmp_core_module.c
+++ b/ngx_rtmp_core_module.c
@@ -45,8 +45,6 @@ static char *ngx_rtmp_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_rtmp_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
static char *ngx_rtmp_core_pool_size(ngx_conf_t *cf, void *post, void *data);
-static char *ngx_rtmp_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
static ngx_conf_post_t ngx_rtmp_core_lowat_post =
@@ -193,20 +191,6 @@ static ngx_command_t ngx_rtmp_core_commands[] = {
offsetof(ngx_rtmp_core_srv_conf_t, buflen),
NULL },
- { ngx_string("tcp_nopush"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, tcp_nopush),
- NULL },
-
- { ngx_string("tcp_nodelay"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, tcp_nodelay),
- NULL },
-
{ ngx_string("send_timeout"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -221,52 +205,6 @@ static ngx_command_t ngx_rtmp_core_commands[] = {
offsetof(ngx_rtmp_core_app_conf_t, send_lowat),
&ngx_rtmp_core_lowat_post },
- { ngx_string("postpone_output"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, postpone_output),
- NULL },
-
- { ngx_string("limit_rate"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF
- /*|NGX_RTMP_LIF_CONF*/
- |NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, limit_rate),
- NULL },
-
- { ngx_string("limit_rate_after"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF
- /*|NGX_RTMP_LIF_CONF*/
- |NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, limit_rate_after),
- NULL },
-
- { ngx_string("keepalive_timeout"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE12,
- ngx_rtmp_core_keepalive,
- NGX_RTMP_APP_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("lingering_time"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, lingering_time),
- NULL },
-
- { ngx_string("lingering_timeout"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_RTMP_APP_CONF_OFFSET,
- offsetof(ngx_rtmp_core_app_conf_t, lingering_timeout),
- NULL },
-
{ ngx_string("resolver"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
ngx_rtmp_core_resolver,
@@ -526,16 +464,8 @@ ngx_rtmp_core_create_app_conf(ngx_conf_t *cf)
return NULL;
}
- conf->tcp_nopush = NGX_CONF_UNSET;
- conf->tcp_nodelay = NGX_CONF_UNSET;
conf->send_timeout = NGX_CONF_UNSET_MSEC;
conf->send_lowat = NGX_CONF_UNSET_SIZE;
- conf->postpone_output = NGX_CONF_UNSET_SIZE;
- conf->limit_rate = NGX_CONF_UNSET_SIZE;
- conf->limit_rate_after = NGX_CONF_UNSET_SIZE;
- conf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
- conf->lingering_time = NGX_CONF_UNSET_MSEC;
- conf->lingering_timeout = NGX_CONF_UNSET_MSEC;
conf->resolver_timeout = NGX_CONF_UNSET_MSEC;
return conf;
@@ -548,23 +478,9 @@ ngx_rtmp_core_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_rtmp_core_app_conf_t *prev = parent;
ngx_rtmp_core_app_conf_t *conf = child;
- ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
- ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
-
ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
- ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
- 1460);
- ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
- ngx_conf_merge_size_value(conf->limit_rate_after, prev->limit_rate_after,
- 0);
- ngx_conf_merge_msec_value(conf->keepalive_timeout,
- prev->keepalive_timeout, 75000);
- ngx_conf_merge_msec_value(conf->lingering_time,
- prev->lingering_time, 30000);
- ngx_conf_merge_msec_value(conf->lingering_timeout,
- prev->lingering_timeout, 5000);
ngx_conf_merge_msec_value(conf->resolver_timeout,
prev->resolver_timeout, 30000);
@@ -1135,33 +1051,6 @@ ngx_rtmp_core_pool_size(ngx_conf_t *cf, void *post, void *data)
}
-static char *
-ngx_rtmp_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_rtmp_core_app_conf_t *cacf = conf;
-
- ngx_str_t *value;
-
- if (cacf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- cacf->keepalive_timeout = ngx_parse_time(&value[1], 0);
-
- if (cacf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
- return "invalid value";
- }
-
- if (cf->args->nelts == 2) {
- return NGX_CONF_OK;
- }
-
- return NGX_CONF_OK;
-}
-
-
static char *
ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
diff --git a/ngx_rtmp_eval.c b/ngx_rtmp_eval.c
index b02c44c..356af8a 100644
--- a/ngx_rtmp_eval.c
+++ b/ngx_rtmp_eval.c
@@ -166,8 +166,12 @@ ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, ngx_str_t *out,
case '\\':
state = ESCAPE;
continue;
+ default:
+ break;
}
+ /* fall through */
+
case ESCAPE:
ngx_rtmp_eval_append(&b, &c, 1, log);
state = NORMAL;
diff --git a/ngx_rtmp_flv_live_index_module.c b/ngx_rtmp_flv_live_index_module.c
new file mode 100644
index 0000000..30a12d8
--- /dev/null
+++ b/ngx_rtmp_flv_live_index_module.c
@@ -0,0 +1,65 @@
+
+/*
+ * Copyright (C) Winshining
+ */
+
+#include
+#include
+#include "ngx_http_flv_live_module.h"
+
+
+static ngx_rtmp_play_pt next_play;
+static ngx_rtmp_close_stream_pt next_close_stream;
+
+
+static ngx_int_t ngx_rtmp_flv_live_index_postconfiguration(ngx_conf_t *cf);
+
+
+static ngx_rtmp_module_t ngx_rtmp_flv_live_module_ctx = {
+ NULL,
+ ngx_rtmp_flv_live_index_postconfiguration, /* postconfiguration */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+
+static ngx_command_t ngx_rtmp_flv_live_index_commands[] = {
+ ngx_null_command
+};
+
+
+ngx_module_t ngx_rtmp_flv_live_index_module = {
+ NGX_MODULE_V1,
+ &ngx_rtmp_flv_live_module_ctx,
+ ngx_rtmp_flv_live_index_commands,
+ NGX_RTMP_MODULE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_int_t
+ngx_rtmp_flv_live_index_postconfiguration(ngx_conf_t *cf)
+{
+ next_play = ngx_rtmp_play;
+ ngx_rtmp_play = ngx_http_flv_live_play;
+
+ next_close_stream = ngx_rtmp_close_stream;
+ ngx_rtmp_close_stream = ngx_http_flv_live_close_stream;
+
+ http_flv_live_next_play = next_play;
+ http_flv_live_next_close_stream = next_close_stream;
+
+ return NGX_OK;
+}
+
diff --git a/ngx_rtmp_gop_cache_module.c b/ngx_rtmp_gop_cache_module.c
index febbc6b..9b0d856 100644
--- a/ngx_rtmp_gop_cache_module.c
+++ b/ngx_rtmp_gop_cache_module.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) Gnolizuh
* Copyright (C) Winshining
+ * Copyright (C) HeyJupiter
*/
@@ -31,7 +32,6 @@ static void ngx_rtmp_gop_cache_update(ngx_rtmp_session_t *s);
static void ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
ngx_rtmp_header_t *ch, ngx_chain_t *frame);
static void ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s);
-static void ngx_rtmp_gop_cache_init_handler(ngx_rtmp_session_t *s);
static ngx_int_t ngx_rtmp_gop_cache_av(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_gop_cache_publish(ngx_rtmp_session_t *s,
@@ -42,58 +42,15 @@ static ngx_int_t ngx_rtmp_gop_cache_close_stream(ngx_rtmp_session_t *s,
ngx_rtmp_close_stream_t *v);
-static ngx_chain_t *ngx_rtmp_gop_cache_append_shared_bufs(
- ngx_rtmp_gop_cache_ctx_t *ctx, ngx_chain_t *head, ngx_chain_t *in);
-static ngx_chain_t *ngx_rtmp_gop_cache_alloc_shared_buf(
- ngx_rtmp_gop_cache_ctx_t *ctx);
-static void ngx_rtmp_gop_cache_free_shared_chain(ngx_rtmp_gop_cache_ctx_t *ctx,
- ngx_chain_t *in);
-
-static ngx_chain_t *ngx_hfl_gop_cache_meta_message(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
-static ngx_chain_t *ngx_hfl_gop_cache_append_message(ngx_rtmp_session_t *s,
- ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh, ngx_chain_t *in);
-static ngx_chain_t *ngx_hfl_gop_cache_append_shared_bufs(
- ngx_rtmp_gop_cache_ctx_t *ctx, ngx_rtmp_header_t *h, ngx_chain_t *in,
- ngx_flag_t chunked);
-static void ngx_hfl_gop_cache_free_message(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
-
-
-static ngx_chain_t *ngx_rl_gop_cache_meta_message(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
-static ngx_chain_t *ngx_rl_gop_cache_append_message(ngx_rtmp_session_t *s,
- ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh, ngx_chain_t *in);
-static void ngx_rl_gop_cache_free_message(ngx_rtmp_session_t *s,
- ngx_chain_t *in);
-
-
static ngx_int_t ngx_rtmp_gop_cache_postconfiguration(ngx_conf_t *cf);
static void *ngx_rtmp_gop_cache_create_app_conf(ngx_conf_t *cf);
static char *ngx_rtmp_gop_cache_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
-static ngx_rtmp_gop_cache_proc_handler_t ngx_rl_gop_cache_proc_handler = {
- ngx_rtmp_live_send_message,
- ngx_rl_gop_cache_meta_message,
- ngx_rl_gop_cache_append_message,
- ngx_rl_gop_cache_free_message
-};
-
-static ngx_rtmp_gop_cache_proc_handler_t ngx_hfl_gop_cache_proc_handler = {
- ngx_http_flv_live_send_message,
- ngx_hfl_gop_cache_meta_message,
- ngx_hfl_gop_cache_append_message,
- ngx_hfl_gop_cache_free_message
-};
-
-ngx_rtmp_gop_cache_proc_handler_t *ngx_rtmp_gop_cache_proc_handlers[] = {
- &ngx_rl_gop_cache_proc_handler,
- &ngx_hfl_gop_cache_proc_handler
-};
-
-extern ngx_module_t ngx_http_flv_live_module;
+extern ngx_rtmp_live_proc_handler_t *ngx_rtmp_live_proc_handlers
+ [NGX_RTMP_PROTOCOL_HTTP + 1];
+extern ngx_module_t ngx_http_flv_live_module;
static ngx_command_t ngx_rtmp_gop_cache_commands[] = {
@@ -224,15 +181,21 @@ static ngx_rtmp_gop_frame_t *
ngx_rtmp_gop_cache_free_frame(ngx_rtmp_session_t *s,
ngx_rtmp_gop_frame_t *frame)
{
+ ngx_rtmp_core_srv_conf_t *cscf;
ngx_rtmp_gop_cache_ctx_t *ctx;
+ cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
+ if (cscf == NULL) {
+ return NULL;
+ }
+
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
if (ctx == NULL) {
return NULL;
}
if (frame->frame) {
- ngx_rtmp_gop_cache_free_shared_chain(ctx, frame->frame);
+ ngx_rtmp_free_shared_chain(cscf, frame->frame);
frame->frame = NULL;
}
@@ -243,8 +206,8 @@ ngx_rtmp_gop_cache_free_frame(ngx_rtmp_session_t *s,
}
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop free frame: type='%s' video_frame_in_cache='%uD' "
- "audio_frame_in_cache='%uD'",
+ "gop free frame: type='%s' video_frame_in_cache=%uD "
+ "audio_frame_in_cache=%uD",
frame->h.type == NGX_RTMP_MSG_VIDEO ? "video" : "audio",
ctx->video_frame_in_all, ctx->audio_frame_in_all);
@@ -288,10 +251,10 @@ ngx_rtmp_gop_cache_link_frame(ngx_rtmp_session_t *s,
ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"gop link frame: type='%s' "
- "ctx->video_frame_in_all='%uD' "
- "ctx->audio_frame_in_all='%uD' "
- "cache->video_frame_in_this='%uD' "
- "cache->audio_frame_in_this='%uD'",
+ "ctx->video_frame_in_all=%uD "
+ "ctx->audio_frame_in_all=%uD "
+ "cache->video_frame_in_this=%uD "
+ "cache->audio_frame_in_this=%uD",
frame->h.type == NGX_RTMP_MSG_VIDEO ? "video" : "audio",
ctx->video_frame_in_all, ctx->audio_frame_in_all,
cache->video_frame_in_this, cache->audio_frame_in_this);
@@ -356,7 +319,7 @@ ngx_rtmp_gop_cache_alloc_cache(ngx_rtmp_session_t *s)
ctx->gop_cache_count++;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop alloc cache: gop_cache_count='%uD'", ctx->gop_cache_count);
+ "gop alloc cache: gop_cache_count=%uD", ctx->gop_cache_count);
return NGX_OK;
}
@@ -388,7 +351,7 @@ ngx_rtmp_gop_cache_free_cache(ngx_rtmp_session_t *s,
ctx->gop_cache_count--;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop free cache: gop_cache_count='%uD'", ctx->gop_cache_count);
+ "gop free cache: gop_cache_count=%uD", ctx->gop_cache_count);
return cache->next;
}
@@ -409,19 +372,18 @@ ngx_rtmp_gop_cache_cleanup(ngx_rtmp_session_t *s)
ngx_rtmp_gop_cache_free_cache(s, cache);
}
- if (ctx->pool) {
- ngx_destroy_pool(ctx->pool);
- ctx->pool = NULL;
- }
-
ctx->video_seq_header = NULL;
ctx->audio_seq_header = NULL;
ctx->meta = NULL;
- ctx->cache_tail = ctx->cache_head = NULL;
+ if (ctx->cache_head) {
+ ctx->cache_head->next = ctx->free_cache;
+ ctx->free_cache = ctx->cache_head;
+ ctx->cache_head = NULL;
+ }
+
+ ctx->cache_tail = NULL;
ctx->gop_cache_count = 0;
- ctx->free_cache = NULL;
- ctx->free_frame = NULL;
ctx->video_frame_in_all = 0;
ctx->audio_frame_in_all = 0;
}
@@ -464,6 +426,7 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
{
ngx_rtmp_gop_cache_ctx_t *ctx;
ngx_rtmp_codec_ctx_t *codec_ctx;
+ ngx_rtmp_core_srv_conf_t *cscf;
ngx_rtmp_gop_cache_app_conf_t *gacf;
ngx_rtmp_gop_frame_t *gf;
@@ -472,6 +435,11 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
return;
}
+ cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
+ if (cscf == NULL) {
+ return;
+ }
+
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
if (ctx == NULL) {
return;
@@ -486,7 +454,7 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
// drop video when not H.264
if (codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264) {
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "drop video non-H.264 encode type timestamp='%uD'",
+ "drop video non-H.264 encode type timestamp=%uD",
ch->timestamp);
return;
@@ -495,7 +463,7 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
// drop non-IDR
if (prio != NGX_RTMP_VIDEO_KEY_FRAME && ctx->cache_head == NULL) {
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "drop video non-keyframe timestamp='%uD'",
+ "drop video non-keyframe timestamp=%uD",
ch->timestamp);
return;
@@ -505,7 +473,7 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
// pure audio
if (ctx->video_frame_in_all == 0 && ch->type == NGX_RTMP_MSG_AUDIO) {
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "drop audio frame timestamp='%uD'",
+ "drop audio frame timestamp=%uD",
ch->timestamp);
return;
@@ -525,10 +493,10 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
gf->h = *ch;
gf->prio = prio;
gf->next = NULL;
- gf->frame = ngx_rtmp_gop_cache_append_shared_bufs(ctx, NULL, frame);
+ gf->frame = ngx_rtmp_append_shared_bufs(cscf, NULL, frame);
if (ngx_rtmp_gop_cache_link_frame(s, gf) != NGX_OK) {
- ngx_rtmp_gop_cache_free_shared_chain(ctx, gf->frame);
+ ngx_rtmp_free_shared_chain(cscf, gf->frame);
return;
}
@@ -538,9 +506,9 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
> gacf->gop_max_frame_count)
{
ngx_log_error(NGX_LOG_WARN, s->connection->log, 0,
- "gop cache: video_frame_in_cache='%uD' "
- "audio_frame_in_cache='%uD' max_video_count='%uD' "
- "max_audio_count='%uD' gop_max_frame_count='%uD'",
+ "gop cache: video_frame_in_cache=%uD "
+ "audio_frame_in_cache=%uD max_video_count=%uD "
+ "max_audio_count=%uD gop_max_frame_count=%uD",
ctx->video_frame_in_all, ctx->audio_frame_in_all,
gacf->gop_max_video_count, gacf->gop_max_audio_count,
gacf->gop_max_frame_count);
@@ -552,7 +520,7 @@ ngx_rtmp_gop_cache_frame(ngx_rtmp_session_t *s, ngx_uint_t prio,
ngx_rtmp_gop_cache_update(s);
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop cache: cache packet type='%s' timestamp='%uD'",
+ "gop cache: cache packet type='%s' timestamp=%uD",
gf->h.type == NGX_RTMP_MSG_AUDIO ? "audio" : "video",
gf->h.timestamp);
}
@@ -574,8 +542,9 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
uint32_t delta;
ngx_int_t csidx;
ngx_rtmp_live_chunk_stream_t *cs;
- ngx_rtmp_gop_cache_proc_handler_t *handler;
+ ngx_rtmp_live_proc_handler_t *handler;
ngx_http_request_t *r;
+ ngx_flag_t error;
lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module);
if (lacf == NULL) {
@@ -598,7 +567,7 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
pub_ctx = ctx->stream->pub_ctx;
rs = pub_ctx->session;
s->publisher = rs;
- handler = ngx_rtmp_gop_cache_proc_handlers[ctx->protocol];
+ handler = ngx_rtmp_live_proc_handlers[ctx->protocol];
gctx = ngx_rtmp_get_module_ctx(rs, ngx_rtmp_gop_cache_module);
if (gctx == NULL) {
@@ -606,9 +575,13 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
}
for (cache = gctx->cache_head; cache; cache = cache->next) {
+ if (s->connection == NULL || s->connection->destroyed) {
+ return;
+ }
+
if (ctx->protocol == NGX_RTMP_PROTOCOL_HTTP) {
r = s->data;
- if (r == NULL || (r->connection && r->connection->destroyed)) {
+ if (r == NULL) {
return;
}
@@ -622,6 +595,7 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
if (meta == NULL && meta_version != gctx->meta_version) {
meta = handler->meta_message_pt(s, gctx->meta);
if (meta == NULL) {
+ ngx_rtmp_finalize_session(s);
return;
}
}
@@ -635,8 +609,6 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"gop cache send: meta");
- ngx_rtmp_gop_cache_init_handler(s);
-
if (handler->send_message_pt(s, meta, 0) == NGX_ERROR) {
ngx_rtmp_finalize_session(s);
return;
@@ -647,6 +619,10 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
}
for (gf = cache->frame_head; gf; gf = gf->next) {
+ if (s->connection == NULL || s->connection->destroyed) {
+ return;
+ }
+
csidx = !(lacf->interleave || gf->h.type == NGX_RTMP_MSG_VIDEO);
cs = &ctx->cs[csidx];
@@ -658,6 +634,7 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
}
delta = ch.timestamp - lh.timestamp;
+ error = 0;
if (!cs->active) {
switch (gf->h.type) {
@@ -671,14 +648,13 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
if (header) {
apkt = handler->append_message_pt(s, &lh, NULL, header);
if (apkt == NULL) {
- return;
+ error = 1;
+ goto next;
}
-
- ngx_rtmp_gop_cache_init_handler(s);
}
if (apkt && handler->send_message_pt(s, apkt, 0) != NGX_OK) {
- continue;
+ goto next;
}
cs->timestamp = lh.timestamp;
@@ -688,29 +664,29 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
pkt = handler->append_message_pt(s, &ch, &lh, gf->frame);
if (pkt == NULL) {
- return;
+ error = 1;
+ goto next;
}
- ngx_rtmp_gop_cache_init_handler(s);
-
if (handler->send_message_pt(s, pkt, gf->prio) != NGX_OK) {
++pub_ctx->ndropped;
cs->dropped += delta;
- ngx_rtmp_finalize_session(s);
- return;
+ goto next;
}
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop cache send: tag type='%s' prio='%d' ctimestamp='%uD' "
- "ltimestamp='%uD'",
+ "gop cache send: tag type='%s' prio=%d ctimestamp=%uD "
+ "ltimestamp=%uD",
gf->h.type == NGX_RTMP_MSG_AUDIO ? "audio" : "video",
gf->prio, ch.timestamp, lh.timestamp);
cs->timestamp += delta;
s->current_time = cs->timestamp;
+ next:
+
if (pkt) {
handler->free_message_pt(s, pkt);
pkt = NULL;
@@ -720,25 +696,12 @@ ngx_rtmp_gop_cache_send(ngx_rtmp_session_t *s)
handler->free_message_pt(s, apkt);
apkt = NULL;
}
- }
- }
-}
-
-static void
-ngx_rtmp_gop_cache_init_handler(ngx_rtmp_session_t *s)
-{
- ngx_rtmp_live_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module);
-
- s->gop_cache.out[s->out_last].set = 1;
- s->gop_cache.count++;
-
- if (ctx->protocol == NGX_RTMP_PROTOCOL_RTMP) {
- s->gop_cache.out[s->out_last].free = ngx_rl_gop_cache_free_message;
- } else {
- s->gop_cache.out[s->out_last].free = ngx_hfl_gop_cache_free_message;
+ if (error) {
+ ngx_rtmp_finalize_session(s);
+ return;
+ }
+ }
}
}
@@ -750,10 +713,10 @@ ngx_rtmp_gop_cache_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_live_ctx_t *ctx;
ngx_rtmp_gop_cache_app_conf_t *gacf;
ngx_rtmp_live_app_conf_t *lacf;
+ ngx_rtmp_live_chunk_stream_t *cs;
ngx_rtmp_header_t ch;
ngx_uint_t prio;
ngx_uint_t csidx;
- ngx_rtmp_live_chunk_stream_t *cs;
gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_cache_module);
if (gacf == NULL || !gacf->gop_cache) {
@@ -803,18 +766,12 @@ ngx_rtmp_gop_cache_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
{
ngx_rtmp_gop_cache_app_conf_t *gacf;
ngx_rtmp_gop_cache_ctx_t *ctx;
- ngx_rtmp_core_srv_conf_t *cscf;
gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_cache_module);
if (gacf == NULL || !gacf->gop_cache) {
goto next;
}
- cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
- if (cscf == NULL) {
- goto next;
- }
-
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"gop cache publish: name='%s' type='%s'",
v->name, v->type);
@@ -837,8 +794,6 @@ ngx_rtmp_gop_cache_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
}
}
- ctx->chunk_size = cscf->chunk_size;
-
next:
return next_publish(s, v);
}
@@ -848,8 +803,6 @@ static ngx_int_t
ngx_rtmp_gop_cache_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
{
ngx_rtmp_gop_cache_app_conf_t *gacf;
- ngx_rtmp_gop_cache_ctx_t *ctx;
- ngx_rtmp_core_srv_conf_t *cscf;
#ifdef NGX_DEBUG
ngx_msec_t start, end;
#endif
@@ -859,39 +812,15 @@ ngx_rtmp_gop_cache_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
goto next;
}
- cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
- if (cscf == NULL) {
- goto next;
- }
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- ctx = ngx_palloc(s->connection->pool,
- sizeof(ngx_rtmp_gop_cache_ctx_t));
- ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_gop_cache_module);
- }
-
- ngx_memzero(ctx, sizeof(*ctx));
-
- if (ctx->pool == NULL) {
- ctx->pool = ngx_create_pool(NGX_GOP_CACHE_POOL_CREATE_SIZE,
- s->connection->log);
- if (ctx->pool == NULL) {
- return NGX_ERROR;
- }
- }
-
- ctx->chunk_size = cscf->chunk_size;
-
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop cache play: name='%s' start='%i' duration='%i' reset='%d'",
+ "gop cache play: name='%s' start=%i duration=%i reset=%d",
v->name, (ngx_int_t) v->start,
(ngx_int_t) v->duration, (ngx_uint_t) v->reset);
#ifdef NGX_DEBUG
start = ngx_current_msec;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop cache send: start_time='%uD'", start);
+ "gop cache send: start_time=%uD", start);
#endif
ngx_rtmp_gop_cache_send(s);
@@ -899,10 +828,10 @@ ngx_rtmp_gop_cache_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
#ifdef NGX_DEBUG
end = ngx_current_msec;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop cache send: end_time='%uD'", end);
+ "gop cache send: end_time=%uD", end);
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "gop cache send: delta_time='%uD'", end - start);
+ "gop cache send: delta_time=%uD", end - start);
#endif
next:
@@ -925,12 +854,6 @@ ngx_rtmp_gop_cache_close_stream(ngx_rtmp_session_t *s,
}
if (ctx->publishing == 0) {
- gctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (gctx && gctx->pool) {
- ngx_destroy_pool(gctx->pool);
- gctx->pool = NULL;
- }
-
goto next;
}
@@ -946,377 +869,18 @@ ngx_rtmp_gop_cache_close_stream(ngx_rtmp_session_t *s,
ngx_rtmp_gop_cache_cleanup(s);
-next:
- return next_close_stream(s, v);
-}
-
-
-static ngx_chain_t *
-ngx_rtmp_gop_cache_append_shared_bufs(ngx_rtmp_gop_cache_ctx_t *ctx,
- ngx_chain_t *head, ngx_chain_t *in)
-{
- ngx_chain_t *l, **ll;
- u_char *p;
- size_t size;
-
- ll = &head;
- p = in->buf->pos;
- l = head;
-
- if (l) {
- for(; l->next; l = l->next);
- ll = &l->next;
- }
-
- for ( ;; ) {
-
- if (l == NULL || l->buf->last == l->buf->end) {
- l = ngx_rtmp_gop_cache_alloc_shared_buf(ctx);
- if (l == NULL || l->buf == NULL) {
- break;
- }
-
- *ll = l;
- ll = &l->next;
- }
-
- while (l->buf->end - l->buf->last >= in->buf->last - p) {
- l->buf->last = ngx_cpymem(l->buf->last, p,
- in->buf->last - p);
- in = in->next;
- if (in == NULL) {
- goto done;
- }
- p = in->buf->pos;
- }
-
- size = l->buf->end - l->buf->last;
- l->buf->last = ngx_cpymem(l->buf->last, p, size);
- p += size;
- }
-
-done:
- *ll = NULL;
-
- return head;
-}
-
-
-static ngx_chain_t *
-ngx_rtmp_gop_cache_alloc_shared_buf(ngx_rtmp_gop_cache_ctx_t *ctx)
-{
- u_char *p;
- ngx_chain_t *out;
- ngx_buf_t *b;
- size_t size;
-
- if (ctx->free) {
- out = ctx->free;
- ctx->free = out->next;
-
- } else {
-
- size = ctx->chunk_size + NGX_RTMP_MAX_CHUNK_HEADER;
-
- p = ngx_pcalloc(ctx->pool, NGX_RTMP_REFCOUNT_BYTES
- + sizeof(ngx_chain_t)
- + sizeof(ngx_buf_t)
- + size);
- if (p == NULL) {
- return NULL;
- }
-
- p += NGX_RTMP_REFCOUNT_BYTES;
- out = (ngx_chain_t *)p;
-
- p += sizeof(ngx_chain_t);
- out->buf = (ngx_buf_t *)p;
-
- p += sizeof(ngx_buf_t);
- out->buf->start = p;
- out->buf->end = p + size;
- }
-
- out->next = NULL;
- b = out->buf;
- b->pos = b->last = b->start + NGX_RTMP_MAX_CHUNK_HEADER;
- b->memory = 1;
-
- /* buffer has refcount =1 when created! */
- ngx_rtmp_ref_set(out, 1);
-
- return out;
-}
-
-
-static void
-ngx_rtmp_gop_cache_free_shared_chain(ngx_rtmp_gop_cache_ctx_t *ctx,
- ngx_chain_t *in)
-{
- ngx_chain_t *cl;
-
- if (ngx_rtmp_ref_put(in)) {
- return;
- }
-
- for (cl = in; ; cl = cl->next) {
- if (cl->next == NULL) {
- cl->next = ctx->free;
- ctx->free = in;
- return;
- }
- }
-}
-
-
-static ngx_chain_t *
-ngx_hfl_gop_cache_meta_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
-{
- ngx_rtmp_gop_cache_ctx_t *ctx;
- ngx_http_request_t *r;
- ngx_rtmp_header_t ch;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- return NULL;
- }
-
- r = s->data;
- if (r == NULL || (r->connection && r->connection->destroyed)) {
- ngx_rtmp_gop_cache_free_shared_chain(ctx, in);
- return NULL;
- }
-
- ch.timestamp = 0;
- ch.type = NGX_RTMP_MSG_AMF_META;
-
- return ngx_hfl_gop_cache_append_message(s, &ch, NULL, in);
-}
-
-
-static ngx_chain_t *
-ngx_hfl_gop_cache_append_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
- ngx_rtmp_header_t *lh, ngx_chain_t *in)
-{
- ngx_rtmp_gop_cache_ctx_t *ctx;
- ngx_http_request_t *r;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- return NULL;
- }
-
- r = s->data;
- if (r == NULL || (r->connection && r->connection->destroyed)) {
- ngx_rtmp_gop_cache_free_shared_chain(ctx, in);
- return NULL;
- }
-
- return ngx_hfl_gop_cache_append_shared_bufs(ctx, h, in, r->chunked);
-}
-
-
-static ngx_chain_t *
-ngx_hfl_gop_cache_append_shared_bufs(ngx_rtmp_gop_cache_ctx_t *ctx,
- ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_flag_t chunked)
-{
- ngx_chain_t *tag, *ch, *ct, chunk, *iter, *last_in, **tail,
- prev_tag_size;
- u_char *pos, *p,
-#if !(NGX_WIN32)
- chunk_item[ngx_strlen("0000000000000000" CRLF) + 1];
-#else
- chunk_item[19];
-#endif
- uint32_t data_size, size;
- off_t tag_size;
- ngx_buf_t prev_tag_size_buf, chunk_buf;
-
- for (data_size = 0, iter = in, last_in = iter; iter; iter = iter->next) {
- last_in = iter;
- data_size += (iter->buf->last - iter->buf->pos);
- }
-
- tail = &last_in->next;
- *tail = &prev_tag_size;
-
- tag_size = data_size + NGX_FLV_TAG_HEADER_SIZE;
-
- prev_tag_size.buf = &prev_tag_size_buf;
- prev_tag_size.next = NULL;
-
- prev_tag_size_buf.start = (u_char *) &size;
- prev_tag_size_buf.end = prev_tag_size_buf.start + sizeof(uint32_t);
- prev_tag_size_buf.pos = prev_tag_size_buf.start;
- prev_tag_size_buf.last = prev_tag_size_buf.end;
-
- pos = prev_tag_size_buf.pos;
- p = (u_char *) &tag_size;
- *pos++ = p[3];
- *pos++ = p[2];
- *pos++ = p[1];
- *pos++ = p[0];
-
- tag = ngx_rtmp_gop_cache_append_shared_bufs(ctx, NULL, in);
- if (tag == NULL) {
- return NULL;
- }
-
- /* it links to the local variable, unlink it */
- *tail = NULL;
-
- tag->buf->pos -= NGX_FLV_TAG_HEADER_SIZE;
- pos = tag->buf->pos;
-
- /* type, 5bits */
- *pos++ = (u_char) (h->type & 0x1f);
-
- /* data length, 3B */
- p = (u_char *) &data_size;
- *pos++ = p[2];
- *pos++ = p[1];
- *pos++ = p[0];
-
- /* timestamp, 3B + ext, 1B */
- p = (u_char *) &h->timestamp;
- *pos++ = p[2];
- *pos++ = p[1];
- *pos++ = p[0];
- *pos++ = p[3];
-
- /* streamId, 3B, always be 0 */
- *pos++ = 0;
- *pos++ = 0;
- *pos++ = 0;
-
- /* add chunk header and tail */
- if (chunked) {
- /* 4 is the size of previous tag size itself */
- *ngx_sprintf(chunk_item, "%xO" CRLF, tag_size + 4) = 0;
-
- chunk_buf.start = chunk_item;
- chunk_buf.pos = chunk_buf.start;
- chunk_buf.end = chunk_buf.start + ngx_strlen(chunk_item);
- chunk_buf.last = chunk_buf.end;
-
- chunk.buf = &chunk_buf;
- chunk.next = NULL;
-
- ch = ngx_rtmp_gop_cache_append_shared_bufs(ctx, NULL, &chunk);
- if (ch == NULL) {
- return NULL;
- }
-
- for (iter = tag, last_in = iter; iter; iter = iter->next) {
- last_in = iter;
- }
-
- /* save the memory, very likely */
-#if !(NGX_WIN32)
- if (__builtin_expect(last_in->buf->last + 2 <= last_in->buf->end, 1)) {
-#else
- if (last_in->buf->last + 2 <= last_in->buf->end) {
-#endif
- *last_in->buf->last++ = CR;
- *last_in->buf->last++ = LF;
- } else {
- *ngx_sprintf(chunk_item, CRLF) = 0;
- chunk_buf.start = chunk_item;
- chunk_buf.pos = chunk_buf.start;
- chunk_buf.end = chunk_buf.start + ngx_strlen(chunk_item);
- chunk_buf.last = chunk_buf.end;
-
- chunk.buf = &chunk_buf;
- chunk.next = NULL;
-
- ct = ngx_rtmp_gop_cache_append_shared_bufs(ctx, NULL, &chunk);
- if (ct == NULL) {
- return NULL;
- }
-
- tail = &last_in->next;
- *tail = ct;
- }
-
- ch->next = tag;
-
- return ch;
- }
-
- return tag;
-}
-
-
-static void
-ngx_hfl_gop_cache_free_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
-{
- ngx_rtmp_gop_cache_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- return;
- }
-
- ngx_rtmp_gop_cache_free_shared_chain(ctx, in);
-}
-
-
-static ngx_chain_t *
-ngx_rl_gop_cache_meta_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
-{
- ngx_rtmp_gop_cache_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- return NULL;
- }
-
- return ngx_rtmp_gop_cache_append_shared_bufs(ctx, NULL, in);
-}
-
-
-static ngx_chain_t *
-ngx_rl_gop_cache_append_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
- ngx_rtmp_header_t *lh, ngx_chain_t *in)
-{
- ngx_rtmp_gop_cache_ctx_t *ctx;
- ngx_chain_t *pkt;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- return NULL;
+ gctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
+ if (gctx == NULL) {
+ goto next;
}
- pkt = ngx_rtmp_gop_cache_append_shared_bufs(ctx, NULL, in);
- if (pkt != NULL) {
- ngx_rtmp_prepare_message(s, h, lh, pkt);
+ if (gctx->pool) {
+ ngx_destroy_pool(gctx->pool);
+ gctx->pool = NULL;
}
- return pkt;
-}
-
-
-static void
-ngx_rl_gop_cache_free_message(ngx_rtmp_session_t *s, ngx_chain_t *in)
-{
- ngx_rtmp_gop_cache_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_cache_module);
- if (ctx == NULL) {
- return;
- }
-
- ngx_rtmp_gop_cache_free_shared_chain(ctx, in);
-}
-
-
-void
-ngx_rtmp_gop_cache_exec_handler(ngx_rtmp_session_t *s, size_t pos,
- ngx_chain_t *in)
-{
- s->gop_cache.out[pos].set = 0;
- s->gop_cache.out[pos].free(s, in);
- s->gop_cache.count--;
+next:
+ return next_close_stream(s, v);
}
diff --git a/ngx_rtmp_gop_cache_module.h b/ngx_rtmp_gop_cache_module.h
index cebf141..7e8d18b 100644
--- a/ngx_rtmp_gop_cache_module.h
+++ b/ngx_rtmp_gop_cache_module.h
@@ -54,7 +54,6 @@ typedef struct ngx_rtmp_gop_cache_ctx_s {
ngx_chain_t *free;
ngx_uint_t meta_version;
- ngx_int_t chunk_size;
size_t gop_cache_count;
size_t video_frame_in_all;
@@ -62,19 +61,5 @@ typedef struct ngx_rtmp_gop_cache_ctx_s {
} ngx_rtmp_gop_cache_ctx_t;
-typedef struct {
- ngx_int_t (*send_message_pt)(ngx_rtmp_session_t *s, ngx_chain_t *out,
- ngx_uint_t priority);
- ngx_chain_t *(*meta_message_pt)(ngx_rtmp_session_t *s, ngx_chain_t *in);
- ngx_chain_t *(*append_message_pt)(ngx_rtmp_session_t *s,
- ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh, ngx_chain_t *in);
- void (*free_message_pt)(ngx_rtmp_session_t *s, ngx_chain_t *in);
-} ngx_rtmp_gop_cache_proc_handler_t;
-
-
-void ngx_rtmp_gop_cache_exec_handler(ngx_rtmp_session_t *s, size_t pos,
- ngx_chain_t *in);
-
-
#endif
diff --git a/ngx_rtmp_handler.c b/ngx_rtmp_handler.c
index 9a98623..0ed7758 100644
--- a/ngx_rtmp_handler.c
+++ b/ngx_rtmp_handler.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) Roman Arutyunyan
- * Copyright (C) Winshining
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Winshining
*/
@@ -10,7 +10,6 @@
#include "ngx_rtmp.h"
#include "ngx_rtmp_amf.h"
#include "ngx_rtmp_cmd_module.h"
-#include "ngx_rtmp_gop_cache_module.h"
static void ngx_rtmp_recv(ngx_event_t *rev);
@@ -553,14 +552,8 @@ ngx_rtmp_send(ngx_event_t *wev)
if (s->out_bpos == s->out_chain->buf->last) {
s->out_chain = s->out_chain->next;
if (s->out_chain == NULL) {
- if (s->gop_cache.out[s->out_pos].set) {
- ngx_rtmp_gop_cache_exec_handler(s, s->out_pos,
- s->out[s->out_pos]);
- } else {
- cscf = ngx_rtmp_get_module_srv_conf(s,
- ngx_rtmp_core_module);
- ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
- }
+ cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
+ ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
++s->out_pos;
s->out_pos %= s->out_queue;
if (s->out_pos == s->out_last) {
@@ -729,10 +722,8 @@ ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out,
ngx_uint_t priority)
{
ngx_uint_t nmsg;
- ssize_t delta;
- delta = s->out_last - s->out_pos;
- nmsg = (delta >= 0 ? delta : -delta) % s->out_queue + 1;
+ nmsg = (s->out_last + s->out_queue - s->out_pos) % s->out_queue + 1;
if (priority > 3) {
priority = 3;
@@ -745,10 +736,6 @@ ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out,
"RTMP drop message bufs=%ui, priority=%ui",
nmsg, priority);
- if (s->gop_cache.out[s->out_last].set) {
- ngx_rtmp_gop_cache_exec_handler(s, s->out_last, out);
- }
-
return NGX_AGAIN;
}
diff --git a/ngx_rtmp_init.c b/ngx_rtmp_init.c
index c6660c4..ef32d1a 100644
--- a/ngx_rtmp_init.c
+++ b/ngx_rtmp_init.c
@@ -12,11 +12,8 @@
static void ngx_rtmp_close_connection(ngx_connection_t *c);
-
static void ngx_rtmp_process_unix_socket(ngx_rtmp_connection_t *rconn);
-extern ngx_module_t ngx_rtmp_auto_push_module;
-
void
ngx_rtmp_init_connection(ngx_connection_t *c)
@@ -167,8 +164,7 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
s = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_session_t));
if (s == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
s->rtmp_connection = c->data;
@@ -183,8 +179,7 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
ctx = ngx_palloc(c->pool, sizeof(ngx_rtmp_error_log_ctx_t));
if (ctx == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
ctx->client = &c->addr_text;
@@ -199,14 +194,12 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_rtmp_max_module);
if (s->ctx == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
s->out_pool = ngx_create_pool(4096, c->log);
if (s->out_pool == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
s->out = ngx_pcalloc(s->out_pool, sizeof(ngx_chain_t *)
@@ -214,24 +207,12 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
addr_conf->default_server->ctx->srv_conf
[ngx_rtmp_core_module.ctx_index])->out_queue);
if (s->out == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
- }
-
- s->gop_cache.out = ngx_pcalloc(s->out_pool,
- sizeof(ngx_rtmp_gop_cache_free_t)
- * ((ngx_rtmp_core_srv_conf_t *)
- addr_conf->default_server->ctx->srv_conf
- [ngx_rtmp_core_module.ctx_index])->out_queue);
- if (s->gop_cache.out == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
s->in_streams_pool = ngx_create_pool(4096, c->log);
if (s->in_streams_pool == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
@@ -241,8 +222,7 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
s->in_streams = ngx_pcalloc(s->in_streams_pool, sizeof(ngx_rtmp_stream_t)
* cscf->max_streams);
if (s->in_streams == NULL) {
- ngx_rtmp_close_connection(c);
- return NULL;
+ goto failed;
}
#if (nginx_version >= 1007005)
@@ -252,7 +232,6 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
s->epoch = ngx_current_msec;
s->timeout = cscf->timeout;
s->buflen = cscf->buflen;
- s->gop_cache.count = 0;
ngx_rtmp_set_chunk_size(s, NGX_RTMP_DEFAULT_CHUNK_SIZE);
@@ -262,6 +241,20 @@ ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
}
return s;
+
+failed:
+ if (s->out_pool) {
+ ngx_destroy_pool(s->out_pool);
+ s->out_pool = NULL;
+ }
+
+ if (s->in_streams_pool) {
+ ngx_destroy_pool(s->in_streams_pool);
+ s->in_streams_pool = NULL;
+ }
+
+ ngx_rtmp_close_connection(c);
+ return NULL;
}
@@ -346,9 +339,7 @@ ngx_rtmp_close_session_handler(ngx_event_t *e)
ngx_rtmp_free_handshake_buffers(s);
while (s->out_pos != s->out_last) {
- if (!s->gop_cache.out[s->out_pos].set) {
- ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
- }
+ ngx_rtmp_free_shared_chain(cscf, s->out[s->out_pos]);
s->out_pos++;
s->out_pos %= s->out_queue;
diff --git a/ngx_rtmp_live_module.c b/ngx_rtmp_live_module.c
index 16a1234..c40d76c 100644
--- a/ngx_rtmp_live_module.c
+++ b/ngx_rtmp_live_module.c
@@ -11,7 +11,6 @@
#include "ngx_rtmp_live_module.h"
#include "ngx_rtmp_cmd_module.h"
#include "ngx_rtmp_codec_module.h"
-#include "ngx_rtmp_gop_cache_module.h"
#include "ngx_http_flv_live_module.h"
@@ -32,7 +31,8 @@ static char *ngx_rtmp_live_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd,
static void ngx_rtmp_live_start(ngx_rtmp_session_t *s);
static void ngx_rtmp_live_stop(ngx_rtmp_session_t *s);
-
+static ngx_int_t ngx_rtmp_live_send_message(ngx_rtmp_session_t *s,
+ ngx_chain_t *in, ngx_uint_t priority);
static ngx_chain_t *ngx_rtmp_live_meta_message(ngx_rtmp_session_t *s,
ngx_chain_t *in);
static ngx_chain_t *ngx_rtmp_live_append_message(ngx_rtmp_session_t *s,
@@ -59,7 +59,6 @@ ngx_rtmp_live_proc_handler_t ngx_rtmp_live_proc_handler = {
extern ngx_rtmp_live_proc_handler_t *ngx_rtmp_live_proc_handlers
[NGX_RTMP_PROTOCOL_HTTP + 1];
extern ngx_module_t ngx_http_flv_live_module;
-extern ngx_module_t ngx_rtmp_gop_cache_module;
static ngx_command_t ngx_rtmp_live_commands[] = {
@@ -804,7 +803,6 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_live_proc_handler_t *handler;
ngx_rtmp_live_ctx_t *ctx, *pctx;
ngx_rtmp_codec_ctx_t *codec_ctx;
- ngx_rtmp_gop_cache_ctx_t *gctx;
ngx_chain_t *header, *coheader;
ngx_rtmp_live_app_conf_t *lacf;
ngx_rtmp_session_t *ss;
@@ -961,14 +959,6 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ss = pctx->session;
cs = &pctx->cs[csidx];
- if (ss->gop_cache.count == 0) {
- gctx = ngx_rtmp_get_module_ctx(ss, ngx_rtmp_gop_cache_module);
- if (gctx && gctx->pool) {
- ngx_destroy_pool(gctx->pool);
- gctx->pool = NULL;
- }
- }
-
handler = ngx_rtmp_live_proc_handlers[pctx->protocol];
/* send metadata */
@@ -1026,20 +1016,22 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
continue;
}
- if (lacf->wait_video && h->type == NGX_RTMP_MSG_AUDIO &&
- !pctx->cs[0].active)
- {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0,
- "live: waiting for video");
- continue;
- }
+ if (codec_ctx->video_codec_id) {
+ if (lacf->wait_video && h->type == NGX_RTMP_MSG_AUDIO &&
+ !pctx->cs[0].active)
+ {
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0,
+ "live: waiting for video");
+ continue;
+ }
- if (lacf->wait_key && prio != NGX_RTMP_VIDEO_KEY_FRAME &&
- (lacf->interleave || h->type == NGX_RTMP_MSG_VIDEO))
- {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0,
- "live: skip non-key");
- continue;
+ if (lacf->wait_key && prio != NGX_RTMP_VIDEO_KEY_FRAME &&
+ (lacf->interleave || h->type == NGX_RTMP_MSG_VIDEO))
+ {
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0,
+ "live: skip non-key");
+ continue;
+ }
}
if (header || coheader) {
@@ -1188,6 +1180,7 @@ static ngx_int_t
ngx_rtmp_live_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in, ngx_rtmp_amf_elt_t *out_elts, ngx_uint_t out_elts_size)
{
+ ngx_rtmp_live_proc_handler_t *handler;
ngx_rtmp_live_ctx_t *ctx, *pctx;
ngx_chain_t *data, *rpkt;
ngx_rtmp_core_srv_conf_t *cscf;
@@ -1200,6 +1193,7 @@ ngx_rtmp_live_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_uint_t peers;
uint32_t delta;
ngx_rtmp_live_chunk_stream_t *cs;
+ ngx_http_request_t *r;
#ifdef NGX_DEBUG
u_char *msg_type;
@@ -1264,7 +1258,6 @@ ngx_rtmp_live_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
delta = ch.timestamp - cs->timestamp;
rpkt = ngx_rtmp_append_shared_bufs(cscf, data, in);
- ngx_rtmp_prepare_message(s, &ch, NULL, rpkt);
for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) {
if (pctx == ctx || pctx->paused) {
@@ -1272,11 +1265,35 @@ ngx_rtmp_live_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
}
ss = pctx->session;
+ handler = ngx_rtmp_live_proc_handlers[pctx->protocol];
+ if (pctx->protocol == NGX_RTMP_PROTOCOL_HTTP) {
+ r = ss->data;
+ if (r == NULL || (r->connection && r->connection->destroyed)) {
+ continue;
+ }
- if (ngx_rtmp_send_message(ss, rpkt, prio) != NGX_OK) {
- ++pctx->ndropped;
- cs->dropped += delta;
- continue;
+ handler->meta = handler->append_message_pt(ss, &ch, NULL, rpkt);
+ if (handler->meta == NULL) {
+ continue;
+ }
+
+ if (handler->send_message_pt(ss, handler->meta, 0) != NGX_OK) {
+ ++pctx->ndropped;
+ cs->dropped += delta;
+ handler->free_message_pt(ss, handler->meta);
+ handler->meta = NULL;
+ continue;
+ }
+
+ handler->free_message_pt(ss, handler->meta);
+ handler->meta = NULL;
+ } else {
+ ngx_rtmp_prepare_message(s, &ch, NULL, rpkt);
+ if (ngx_rtmp_send_message(ss, rpkt, prio) != NGX_OK) {
+ ++pctx->ndropped;
+ cs->dropped += delta;
+ continue;
+ }
}
cs->timestamp += delta;
@@ -1504,16 +1521,8 @@ ngx_rtmp_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
/* request from http */
r = s->data;
if (r) {
- if (s->wait_notify_play) {
- if (ngx_http_flv_live_join(s, v->name, 0) == NGX_ERROR) {
- r->main->count--;
-
- return NGX_ERROR;
- }
-
- s->wait_notify_play = 0;
- }
-
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ "live: play from HTTP");
goto next;
}
}
diff --git a/ngx_rtmp_live_module.h b/ngx_rtmp_live_module.h
index ea30d35..39591e1 100644
--- a/ngx_rtmp_live_module.h
+++ b/ngx_rtmp_live_module.h
@@ -86,8 +86,6 @@ extern ngx_module_t ngx_rtmp_live_module;
ngx_rtmp_live_stream_t **ngx_rtmp_live_get_stream(ngx_rtmp_session_t *s,
u_char *name, int create);
-ngx_int_t ngx_rtmp_live_send_message(ngx_rtmp_session_t *s, ngx_chain_t *in,
- ngx_uint_t priority);
#endif /* _NGX_RTMP_LIVE_H_INCLUDED_ */
diff --git a/ngx_rtmp_log_module.c b/ngx_rtmp_log_module.c
index e609eec..38cb49b 100644
--- a/ngx_rtmp_log_module.c
+++ b/ngx_rtmp_log_module.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) Roman Arutyunyan
+ * Copyright (C) Winshining
*/
@@ -70,7 +71,8 @@ typedef struct {
typedef struct {
ngx_array_t *logs; /* ngx_rtmp_log_t */
ngx_uint_t off;
- time_t interval;
+ ngx_msec_t interval;
+ size_t size;
} ngx_rtmp_log_app_conf_t;
@@ -81,6 +83,7 @@ typedef struct {
typedef struct {
+ u_char *line;
ngx_event_t ev;
unsigned play:1;
unsigned publish:1;
@@ -112,11 +115,19 @@ static ngx_command_t ngx_rtmp_log_commands[] = {
{
ngx_string("log_interval"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_sec_slot,
+ ngx_conf_set_msec_slot,
NGX_RTMP_APP_CONF_OFFSET,
offsetof(ngx_rtmp_log_app_conf_t, interval),
NULL
},
+ {
+ ngx_string("log_size"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_log_app_conf_t, size),
+ NULL
+ },
ngx_null_command
};
@@ -588,7 +599,8 @@ ngx_rtmp_log_create_app_conf(ngx_conf_t *cf)
return NULL;
}
- lacf->interval = NGX_CONF_UNSET;
+ lacf->interval = NGX_CONF_UNSET_MSEC;
+ lacf->size = NGX_CONF_UNSET_SIZE;
return lacf;
}
@@ -603,7 +615,8 @@ ngx_rtmp_log_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_rtmp_log_fmt_t *fmt;
ngx_rtmp_log_t *log;
- ngx_conf_merge_sec_value(conf->interval, prev->interval, 0);
+ ngx_conf_merge_msec_value(conf->interval, prev->interval, 0);
+ ngx_conf_merge_size_value(conf->size, prev->size, 1 * 1024 * 1024);
if (conf->logs || conf->off) {
return NGX_OK;
@@ -920,6 +933,13 @@ ngx_rtmp_log_set_names(ngx_rtmp_session_t *s, u_char *name, u_char *args)
return NULL;
}
+ ctx->line = ngx_pcalloc(s->connection->pool, lacf->size);
+ if (ctx->line == NULL) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "failed to allocate buffer for log line");
+ return NULL;
+ }
+
if (lacf->interval) {
ctx->ev.handler = ngx_rtmp_log_split_output_handler;
ctx->ev.log = s->connection->log;
@@ -1032,8 +1052,9 @@ ngx_rtmp_log_flush(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_log_app_conf_t *lacf;
ngx_rtmp_log_t *log;
ngx_rtmp_log_op_t *op;
+ ngx_rtmp_log_ctx_t *ctx;
ngx_uint_t n, i;
- u_char *line, *p;
+ u_char *p;
size_t len;
if (s->auto_pushed || s->relay) {
@@ -1045,6 +1066,11 @@ ngx_rtmp_log_flush(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
return NGX_OK;
}
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module);
+ if (ctx == NULL) {
+ return NGX_OK;
+ }
+
log = lacf->logs->elts;
for (i = 0; i < lacf->logs->nelts; ++i, ++log) {
@@ -1057,25 +1083,28 @@ ngx_rtmp_log_flush(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
len = 0;
op = log->format->ops->elts;
for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
- len += op->getlen(s, op);
+ if (len + NGX_LINEFEED_SIZE <= lacf->size) {
+ len += op->getlen(s, op);
+ } else {
+ break;
+ }
}
len += NGX_LINEFEED_SIZE;
- line = ngx_palloc(s->connection->pool, len);
- if (line == NULL) {
- return NGX_OK;
- }
-
- p = line;
+ p = ctx->line;
op = log->format->ops->elts;
for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
- p = op->getdata(s, p, op);
+ if (p + NGX_LINEFEED_SIZE <= ctx->line + lacf->size) {
+ p = op->getdata(s, p, op);
+ } else {
+ break;
+ }
}
ngx_linefeed(p);
- ngx_rtmp_log_write(s, log, line, p - line);
+ ngx_rtmp_log_write(s, log, ctx->line, p - ctx->line);
}
return NGX_OK;
@@ -1090,7 +1119,7 @@ ngx_rtmp_log_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_log_t *log;
ngx_rtmp_log_op_t *op;
ngx_uint_t n, i;
- u_char *line, *p;
+ u_char *p;
ngx_rtmp_log_ctx_t *ctx;
size_t len;
@@ -1103,6 +1132,11 @@ ngx_rtmp_log_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
return NGX_OK;
}
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module);
+ if (ctx == NULL) {
+ return NGX_OK;
+ }
+
log = lacf->logs->elts;
for (i = 0; i < lacf->logs->nelts; ++i, ++log) {
@@ -1115,25 +1149,28 @@ ngx_rtmp_log_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
len = 0;
op = log->format->ops->elts;
for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
- len += op->getlen(s, op);
+ if (len + NGX_LINEFEED_SIZE <= lacf->size) {
+ len += op->getlen(s, op);
+ } else {
+ break;
+ }
}
len += NGX_LINEFEED_SIZE;
- line = ngx_palloc(s->connection->pool, len);
- if (line == NULL) {
- return NGX_OK;
- }
-
- p = line;
+ p = ctx->line;
op = log->format->ops->elts;
for (n = 0; n < log->format->ops->nelts; ++n, ++op) {
- p = op->getdata(s, p, op);
+ if (p + NGX_LINEFEED_SIZE <= ctx->line + lacf->size) {
+ p = op->getdata(s, p, op);
+ } else {
+ break;
+ }
}
ngx_linefeed(p);
- ngx_rtmp_log_write(s, log, line, p - line);
+ ngx_rtmp_log_write(s, log, ctx->line, p - ctx->line);
}
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module);
diff --git a/ngx_rtmp_netcall_module.c b/ngx_rtmp_netcall_module.c
index f772c72..0925248 100644
--- a/ngx_rtmp_netcall_module.c
+++ b/ngx_rtmp_netcall_module.c
@@ -47,6 +47,7 @@ typedef struct ngx_rtmp_netcall_session_s {
typedef struct {
+ ngx_uint_t nb_cs;
ngx_rtmp_netcall_session_t *cs;
} ngx_rtmp_netcall_ctx_t;
@@ -198,6 +199,11 @@ ngx_rtmp_netcall_create(ngx_rtmp_session_t *s, ngx_rtmp_netcall_init_t *ci)
return NGX_ERROR;
}
ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_netcall_module);
+ } else {
+ /* I don't know why? But it works! */
+ if (ctx->nb_cs == 0) {
+ ctx->cs = NULL;
+ }
}
/* Create netcall pool, connection, session.
@@ -271,6 +277,7 @@ ngx_rtmp_netcall_create(ngx_rtmp_session_t *s, ngx_rtmp_netcall_init_t *ci)
if (!cs->detached) {
cs->next = ctx->cs;
ctx->cs = cs;
+ ctx->nb_cs++;
}
ngx_rtmp_netcall_send(cc->write);
@@ -318,6 +325,7 @@ ngx_rtmp_netcall_close(ngx_connection_t *cc)
for(css = &ctx->cs; *css; css = &((*css)->next)) {
if (*css == cs) {
*css = cs->next;
+ ctx->nb_cs--;
break;
}
}
diff --git a/ngx_rtmp_notify_module.c b/ngx_rtmp_notify_module.c
index 9aa58b9..f28e015 100644
--- a/ngx_rtmp_notify_module.c
+++ b/ngx_rtmp_notify_module.c
@@ -1,18 +1,19 @@
/*
* Copyright (C) Roman Arutyunyan
+ * Copyright (C) Winshining
*/
#include
#include
#include
+#include
#include "ngx_rtmp.h"
#include "ngx_rtmp_cmd_module.h"
#include "ngx_rtmp_netcall_module.h"
#include "ngx_rtmp_record_module.h"
#include "ngx_rtmp_relay_module.h"
-#include "ngx_rtmp_notify_module.h"
static ngx_rtmp_connect_pt next_connect;
@@ -48,6 +49,42 @@ ngx_str_t ngx_rtmp_notify_urlencoded =
#define NGX_RTMP_NOTIFY_PLAYING 0x02
+enum {
+ NGX_RTMP_NOTIFY_CONNECT,
+ NGX_RTMP_NOTIFY_DISCONNECT,
+ NGX_RTMP_NOTIFY_SRV_MAX
+};
+
+
+enum {
+ NGX_RTMP_NOTIFY_PLAY,
+ NGX_RTMP_NOTIFY_PUBLISH,
+ NGX_RTMP_NOTIFY_PLAY_DONE,
+ NGX_RTMP_NOTIFY_PUBLISH_DONE,
+ NGX_RTMP_NOTIFY_DONE,
+ NGX_RTMP_NOTIFY_RECORD_DONE,
+ NGX_RTMP_NOTIFY_UPDATE,
+ NGX_RTMP_NOTIFY_APP_MAX
+};
+
+
+typedef struct {
+ ngx_url_t *url[NGX_RTMP_NOTIFY_APP_MAX];
+ ngx_flag_t active;
+ ngx_uint_t method;
+ ngx_msec_t update_timeout;
+ ngx_flag_t update_strict;
+ ngx_flag_t relay_redirect;
+ ngx_flag_t no_resolve;
+} ngx_rtmp_notify_app_conf_t;
+
+
+typedef struct {
+ ngx_url_t *url[NGX_RTMP_NOTIFY_SRV_MAX];
+ ngx_uint_t method;
+} ngx_rtmp_notify_srv_conf_t;
+
+
typedef struct {
ngx_uint_t flags;
u_char name[NGX_RTMP_MAX_NAME];
@@ -157,6 +194,13 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
offsetof(ngx_rtmp_notify_app_conf_t, relay_redirect),
NULL },
+ { ngx_string("notify_no_resolve"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_notify_app_conf_t, no_resolve),
+ NULL },
+
ngx_null_command
};
@@ -208,6 +252,7 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf)
nacf->update_timeout = NGX_CONF_UNSET_MSEC;
nacf->update_strict = NGX_CONF_UNSET;
nacf->relay_redirect = NGX_CONF_UNSET;
+ nacf->no_resolve = NGX_CONF_UNSET;
return nacf;
}
@@ -237,6 +282,7 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
30000);
ngx_conf_merge_value(conf->update_strict, prev->update_strict, 0);
ngx_conf_merge_value(conf->relay_redirect, prev->relay_redirect, 0);
+ ngx_conf_merge_value(conf->no_resolve, prev->no_resolve, 1);
return NGX_CONF_OK;
}
@@ -926,11 +972,13 @@ static ngx_int_t
ngx_rtmp_notify_connect_handle(ngx_rtmp_session_t *s,
void *arg, ngx_chain_t *in)
{
- ngx_rtmp_connect_t *v = arg;
- ngx_int_t rc;
- u_char app[NGX_RTMP_MAX_NAME];
+ ngx_rtmp_connect_t *v = arg;
+ ngx_http_request_t *r;
+ ngx_int_t rc;
+ u_char app[NGX_RTMP_MAX_NAME];
- static ngx_str_t location = ngx_string("location");
+ static ngx_rtmp_play_t p;
+ static ngx_str_t location = ngx_string("location");
rc = ngx_rtmp_notify_parse_http_retcode(s, in);
if (rc == NGX_ERROR) {
@@ -950,7 +998,22 @@ ngx_rtmp_notify_connect_handle(ngx_rtmp_session_t *s,
}
}
- return next_connect(s, v);
+ rc = next_connect(s, v);
+ if (rc == NGX_OK && s->notify_connect) {
+ r = s->data;
+ if (r) {
+ ngx_memzero(&p, sizeof(ngx_rtmp_play_t));
+ ngx_memcpy(p.name, s->stream.data, s->stream.len);
+ ngx_memcpy(p.args, s->args.data, s->args.len);
+ r->main->count--;
+
+ rc = ngx_rtmp_play(s, &p);
+ }
+ }
+
+ s->notify_connect = 0;
+
+ return rc;
}
@@ -1033,7 +1096,7 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s,
u->url.len = rc - 7;
u->default_port = 1935;
u->uri_part = 1;
- u->no_resolve = 1; /* want ip here */
+ u->no_resolve = nacf->no_resolve; /* want ip here */
if (ngx_parse_url(s->connection->pool, u) != NGX_OK) {
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
@@ -1059,10 +1122,20 @@ ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s,
ngx_rtmp_relay_target_t target;
ngx_url_t *u;
ngx_rtmp_notify_app_conf_t *nacf;
+ ngx_http_request_t *r;
u_char name[NGX_RTMP_MAX_NAME];
static ngx_str_t location = ngx_string("location");
+ if (s->notify_play) {
+ s->notify_play = 0;
+
+ r = s->data;
+ if (r) {
+ r->main->count--;
+ }
+ }
+
rc = ngx_rtmp_notify_parse_http_retcode(s, in);
if (rc == NGX_ERROR) {
ngx_rtmp_notify_clear_flag(s, NGX_RTMP_NOTIFY_PLAYING);
@@ -1112,7 +1185,7 @@ ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s,
u->url.len = rc - 7;
u->default_port = 1935;
u->uri_part = 1;
- u->no_resolve = (s->wait_notify_play ? 0 : 1); /* want ip here */
+ u->no_resolve = nacf->no_resolve; /* want ip here */
if (ngx_parse_url(s->connection->pool, u) != NGX_OK) {
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
@@ -1164,14 +1237,12 @@ ngx_rtmp_notify_update_handle(ngx_rtmp_session_t *s,
static void
ngx_rtmp_notify_update(ngx_event_t *e)
{
- ngx_connection_t *c;
ngx_rtmp_session_t *s;
ngx_rtmp_notify_app_conf_t *nacf;
ngx_rtmp_netcall_init_t ci;
ngx_url_t *url;
- c = e->data;
- s = c->data;
+ s = e->data;
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
@@ -1240,7 +1311,7 @@ ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
e = &ctx->update_evt;
- e->data = s->connection;
+ e->data = s;
e->log = s->connection->log;
e->handler = ngx_rtmp_notify_update;
@@ -1281,6 +1352,8 @@ ngx_rtmp_notify_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v)
ci.arg = v;
ci.argsize = sizeof(*v);
+ s->notify_connect = 1;
+
return ngx_rtmp_netcall_create(s, &ci);
next:
@@ -1398,6 +1471,8 @@ ngx_rtmp_notify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
ci.arg = v;
ci.argsize = sizeof(*v);
+ s->notify_play = 1;
+
return ngx_rtmp_netcall_create(s, &ci);
next:
diff --git a/ngx_rtmp_notify_module.h b/ngx_rtmp_notify_module.h
deleted file mode 100644
index ce1aa90..0000000
--- a/ngx_rtmp_notify_module.h
+++ /dev/null
@@ -1,49 +0,0 @@
-
-/*
- * Copyright (C) Winshining
- */
-
-#ifndef _NGX_RTMP_NOTIFY_H_INCLUDED_
-#define _NGX_RTMP_NOTIFY_H_INCLUDED_
-
-
-enum {
- NGX_RTMP_NOTIFY_CONNECT,
- NGX_RTMP_NOTIFY_DISCONNECT,
- NGX_RTMP_NOTIFY_SRV_MAX
-};
-
-
-enum {
- NGX_RTMP_NOTIFY_PLAY,
- NGX_RTMP_NOTIFY_PUBLISH,
- NGX_RTMP_NOTIFY_PLAY_DONE,
- NGX_RTMP_NOTIFY_PUBLISH_DONE,
- NGX_RTMP_NOTIFY_DONE,
- NGX_RTMP_NOTIFY_RECORD_DONE,
- NGX_RTMP_NOTIFY_UPDATE,
- NGX_RTMP_NOTIFY_APP_MAX
-};
-
-
-typedef struct {
- ngx_url_t *url[NGX_RTMP_NOTIFY_APP_MAX];
- ngx_flag_t active;
- ngx_uint_t method;
- ngx_msec_t update_timeout;
- ngx_flag_t update_strict;
- ngx_flag_t relay_redirect;
-} ngx_rtmp_notify_app_conf_t;
-
-
-typedef struct {
- ngx_url_t *url[NGX_RTMP_NOTIFY_SRV_MAX];
- ngx_uint_t method;
-} ngx_rtmp_notify_srv_conf_t;
-
-
-extern ngx_module_t ngx_rtmp_notify_module;
-
-
-#endif
-
diff --git a/ngx_rtmp_parse.c b/ngx_rtmp_parse.c
index 9017ff9..617a0c8 100644
--- a/ngx_rtmp_parse.c
+++ b/ngx_rtmp_parse.c
@@ -1,8 +1,8 @@
/*
* Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- * Copyright (C) Winshining
+ * Copyright (C) Nginx, Inc.
+ * Copyright (C) Winshining
*/
diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c
index b5128eb..3da4626 100644
--- a/ngx_rtmp_relay_module.c
+++ b/ngx_rtmp_relay_module.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) Roman Arutyunyan
+ * Copyright (C) Winshining
*/
@@ -337,6 +338,9 @@ ngx_rtmp_relay_create_connection(ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name,
ngx_int_t rc;
ngx_str_t v, *uri;
u_char *first, *last, *p;
+#if (NGX_HAVE_UNIX_DOMAIN)
+ u_char *client;
+#endif
racf = ngx_rtmp_get_module_app_conf(cctx, ngx_rtmp_relay_module);
@@ -461,7 +465,25 @@ ngx_rtmp_relay_create_connection(ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name,
}
c = pc->connection;
c->pool = pool;
- c->addr_text = rctx->url;
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+ if (addr->sockaddr->sa_family == AF_UNIX) {
+ client = ngx_pcalloc(pool, rctx->url.len + 8);
+ if (client == NULL) {
+ goto clear;
+ }
+
+ *ngx_cpymem(client, rctx->url.data,
+ ngx_strlen(rctx->url.data)) = 0;
+
+ p = (u_char *) ngx_strchr(client, '.');
+ *ngx_snprintf(p + 1, client + rctx->url.len + 8 - (p + 1), "%i",
+ ngx_process_slot) = 0;
+
+ c->addr_text.data = client;
+ c->addr_text.len = ngx_strlen(client);
+ }
+#endif
addr_conf = ngx_pcalloc(pool, sizeof(ngx_rtmp_addr_conf_t));
if (addr_conf == NULL) {
@@ -1441,7 +1463,7 @@ static void
ngx_rtmp_relay_close(ngx_rtmp_session_t *s)
{
ngx_rtmp_relay_app_conf_t *racf;
- ngx_rtmp_relay_ctx_t *ctx, **cctx;
+ ngx_rtmp_relay_ctx_t *ctx, **cctx, **next;
ngx_uint_t hash;
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module);
@@ -1511,12 +1533,17 @@ ngx_rtmp_relay_close(ngx_rtmp_session_t *s)
ngx_del_timer(&ctx->push_evt);
}
- for (cctx = &ctx->play; *cctx; cctx = &(*cctx)->next) {
+ for (cctx = &ctx->play; *cctx; /* cctx = &(*cctx)->next */) {
(*cctx)->publish = NULL;
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, (*cctx)->session->connection->log,
0, "relay: play disconnect orphan app='%V' name='%V'",
&(*cctx)->app, &(*cctx)->name);
+
+ next = &(*cctx)->next;
+
ngx_rtmp_finalize_session((*cctx)->session);
+
+ cctx = next;
}
ctx->publish = NULL;
diff --git a/ngx_rtmp_script.c b/ngx_rtmp_script.c
deleted file mode 100644
index 86a4fc7..0000000
--- a/ngx_rtmp_script.c
+++ /dev/null
@@ -1,1257 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- * Copyright (C) Winshining
- */
-
-
-#include
-#include
-#include "ngx_rtmp.h"
-
-
-static ngx_int_t ngx_rtmp_script_init_arrays(ngx_rtmp_script_compile_t *sc);
-static ngx_int_t ngx_rtmp_script_done(ngx_rtmp_script_compile_t *sc);
-static ngx_int_t ngx_rtmp_script_add_copy_code(ngx_rtmp_script_compile_t *sc,
- ngx_str_t *value, ngx_uint_t last);
-static ngx_int_t ngx_rtmp_script_add_var_code(ngx_rtmp_script_compile_t *sc,
- ngx_str_t *name);
-static ngx_int_t ngx_rtmp_script_add_args_code(ngx_rtmp_script_compile_t *sc);
-#if (NGX_PCRE)
-static ngx_int_t ngx_rtmp_script_add_capture_code(ngx_rtmp_script_compile_t *sc,
- ngx_uint_t n);
-#endif
-static ngx_int_t
- ngx_rtmp_script_add_full_name_code(ngx_rtmp_script_compile_t *sc);
-static size_t ngx_rtmp_script_full_name_len_code(ngx_rtmp_script_engine_t *e);
-static void ngx_rtmp_script_full_name_code(ngx_rtmp_script_engine_t *e);
-
-
-#define ngx_rtmp_script_exit (u_char *) &ngx_rtmp_script_exit_code
-
-static uintptr_t ngx_rtmp_script_exit_code = (uintptr_t) NULL;
-
-
-void
-ngx_rtmp_script_flush_complex_value(ngx_rtmp_session_t *s,
- ngx_rtmp_complex_value_t *val)
-{
- ngx_uint_t *index;
-
- index = val->flushes;
-
- if (index) {
- while (*index != (ngx_uint_t) -1) {
-
- if (s->variables[*index].no_cacheable) {
- s->variables[*index].valid = 0;
- s->variables[*index].not_found = 0;
- }
-
- index++;
- }
- }
-}
-
-
-ngx_int_t
-ngx_rtmp_complex_value(ngx_rtmp_session_t *s, ngx_rtmp_complex_value_t *val,
- ngx_str_t *value)
-{
- size_t len;
- ngx_rtmp_script_code_pt code;
- ngx_rtmp_script_len_code_pt lcode;
- ngx_rtmp_script_engine_t e;
-
- if (val->lengths == NULL) {
- *value = val->value;
- return NGX_OK;
- }
-
- ngx_rtmp_script_flush_complex_value(s, val);
-
- ngx_memzero(&e, sizeof(ngx_rtmp_script_engine_t));
-
- e.ip = val->lengths;
- e.request = s;
- e.flushed = 1;
-
- len = 0;
-
- while (*(uintptr_t *) e.ip) {
- lcode = *(ngx_rtmp_script_len_code_pt *) e.ip;
- len += lcode(&e);
- }
-
- value->len = len;
- value->data = ngx_pnalloc(s->connection->pool, len);
- if (value->data == NULL) {
- return NGX_ERROR;
- }
-
- e.ip = val->values;
- e.pos = value->data;
- e.buf = *value;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_rtmp_script_code_pt *) e.ip;
- code((ngx_rtmp_script_engine_t *) &e);
- }
-
- *value = e.buf;
-
- return NGX_OK;
-}
-
-
-ngx_int_t
-ngx_rtmp_compile_complex_value(ngx_rtmp_compile_complex_value_t *ccv)
-{
- ngx_str_t *v;
- ngx_uint_t i, n, nv, nc;
- ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
- ngx_rtmp_script_compile_t sc;
-
- v = ccv->value;
-
- nv = 0;
- nc = 0;
-
- for (i = 0; i < v->len; i++) {
- if (v->data[i] == '$') {
- if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
- nc++;
-
- } else {
- nv++;
- }
- }
- }
-
- if ((v->len == 0 || v->data[0] != '$')
- && (ccv->conf_prefix || ccv->root_prefix))
- {
- if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ccv->conf_prefix = 0;
- ccv->root_prefix = 0;
- }
-
- ccv->complex_value->value = *v;
- ccv->complex_value->flushes = NULL;
- ccv->complex_value->lengths = NULL;
- ccv->complex_value->values = NULL;
-
- if (nv == 0 && nc == 0) {
- return NGX_OK;
- }
-
- n = nv + 1;
-
- if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- n = nv * (2 * sizeof(ngx_rtmp_script_copy_code_t)
- + sizeof(ngx_rtmp_script_var_code_t))
- + sizeof(uintptr_t);
-
- if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
- return NGX_ERROR;
- }
-
- n = (nv * (2 * sizeof(ngx_rtmp_script_copy_code_t)
- + sizeof(ngx_rtmp_script_var_code_t))
- + sizeof(uintptr_t)
- + v->len
- + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
- return NGX_ERROR;
- }
-
- pf = &flushes;
- pl = &lengths;
- pv = &values;
-
- ngx_memzero(&sc, sizeof(ngx_rtmp_script_compile_t));
-
- sc.cf = ccv->cf;
- sc.source = v;
- sc.flushes = &pf;
- sc.lengths = &pl;
- sc.values = &pv;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
- sc.zero = ccv->zero;
- sc.conf_prefix = ccv->conf_prefix;
- sc.root_prefix = ccv->root_prefix;
-
- if (ngx_rtmp_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (flushes.nelts) {
- ccv->complex_value->flushes = flushes.elts;
- ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
- }
-
- ccv->complex_value->lengths = lengths.elts;
- ccv->complex_value->values = values.elts;
-
- return NGX_OK;
-}
-
-
-char *
-ngx_rtmp_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- char *p = conf;
-
- ngx_str_t *value;
- ngx_rtmp_complex_value_t **cv;
- ngx_rtmp_compile_complex_value_t ccv;
-
- cv = (ngx_rtmp_complex_value_t **) (p + cmd->offset);
-
- if (*cv != NULL) {
- return "duplicate";
- }
-
- *cv = ngx_palloc(cf->pool, sizeof(ngx_rtmp_complex_value_t));
- if (*cv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- ngx_memzero(&ccv, sizeof(ngx_rtmp_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = *cv;
-
- if (ngx_rtmp_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-ngx_int_t
-ngx_rtmp_test_predicates(ngx_rtmp_session_t *s, ngx_array_t *predicates)
-{
- ngx_str_t val;
- ngx_uint_t i;
- ngx_rtmp_complex_value_t *cv;
-
- if (predicates == NULL) {
- return NGX_OK;
- }
-
- cv = predicates->elts;
-
- for (i = 0; i < predicates->nelts; i++) {
- if (ngx_rtmp_complex_value(s, &cv[i], &val) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (val.len && (val.len != 1 || val.data[0] != '0')) {
- return NGX_DECLINED;
- }
- }
-
- return NGX_OK;
-}
-
-
-char *
-ngx_rtmp_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- char *p = conf;
-
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_array_t **a;
- ngx_rtmp_complex_value_t *cv;
- ngx_rtmp_compile_complex_value_t ccv;
-
- a = (ngx_array_t **) (p + cmd->offset);
-
- if (*a == NGX_CONF_UNSET_PTR) {
- *a = ngx_array_create(cf->pool, 1, sizeof(ngx_rtmp_complex_value_t));
- if (*a == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- value = cf->args->elts;
-
- for (i = 1; i < cf->args->nelts; i++) {
- cv = ngx_array_push(*a);
- if (cv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_rtmp_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[i];
- ccv.complex_value = cv;
-
- if (ngx_rtmp_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-ngx_uint_t
-ngx_rtmp_script_variables_count(ngx_str_t *value)
-{
- ngx_uint_t i, n;
-
- for (n = 0, i = 0; i < value->len; i++) {
- if (value->data[i] == '$') {
- n++;
- }
- }
-
- return n;
-}
-
-
-ngx_int_t
-ngx_rtmp_script_compile(ngx_rtmp_script_compile_t *sc)
-{
- u_char ch;
- ngx_str_t name;
- ngx_uint_t i, bracket;
-
- if (ngx_rtmp_script_init_arrays(sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- for (i = 0; i < sc->source->len; /* void */ ) {
-
- name.len = 0;
-
- if (sc->source->data[i] == '$') {
-
- if (++i == sc->source->len) {
- goto invalid_variable;
- }
-
- if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
-#if (NGX_PCRE)
- ngx_uint_t n;
-
- n = sc->source->data[i] - '0';
-
- if (sc->captures_mask & ((ngx_uint_t) 1 << n)) {
- sc->dup_capture = 1;
- }
-
- sc->captures_mask |= (ngx_uint_t) 1 << n;
-
- if (ngx_rtmp_script_add_capture_code(sc, n) != NGX_OK) {
- return NGX_ERROR;
- }
-
- i++;
-
- continue;
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
- "using variable \"$%c\" requires "
- "PCRE library", sc->source->data[i]);
- return NGX_ERROR;
-#endif
- }
-
- if (sc->source->data[i] == '{') {
- bracket = 1;
-
- if (++i == sc->source->len) {
- goto invalid_variable;
- }
-
- name.data = &sc->source->data[i];
-
- } else {
- bracket = 0;
- name.data = &sc->source->data[i];
- }
-
- for ( /* void */ ; i < sc->source->len; i++, name.len++) {
- ch = sc->source->data[i];
-
- if (ch == '}' && bracket) {
- i++;
- bracket = 0;
- break;
- }
-
- if ((ch >= 'A' && ch <= 'Z')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= '0' && ch <= '9')
- || ch == '_')
- {
- continue;
- }
-
- break;
- }
-
- if (bracket) {
- ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
- "the closing bracket in \"%V\" "
- "variable is missing", &name);
- return NGX_ERROR;
- }
-
- if (name.len == 0) {
- goto invalid_variable;
- }
-
- sc->variables++;
-
- if (ngx_rtmp_script_add_var_code(sc, &name) != NGX_OK) {
- return NGX_ERROR;
- }
-
- continue;
- }
-
- if (sc->source->data[i] == '?' && sc->compile_args) {
- sc->args = 1;
- sc->compile_args = 0;
-
- if (ngx_rtmp_script_add_args_code(sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- i++;
-
- continue;
- }
-
- name.data = &sc->source->data[i];
-
- while (i < sc->source->len) {
-
- if (sc->source->data[i] == '$') {
- break;
- }
-
- if (sc->source->data[i] == '?') {
-
- sc->args = 1;
-
- if (sc->compile_args) {
- break;
- }
- }
-
- i++;
- name.len++;
- }
-
- sc->size += name.len;
-
- if (ngx_rtmp_script_add_copy_code(sc, &name, (i == sc->source->len))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- return ngx_rtmp_script_done(sc);
-
-invalid_variable:
-
- ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
-
- return NGX_ERROR;
-}
-
-
-u_char *
-ngx_rtmp_script_run(ngx_rtmp_session_t *s, ngx_str_t *value,
- void *code_lengths, size_t len, void *code_values)
-{
- ngx_uint_t i;
- ngx_rtmp_script_code_pt code;
- ngx_rtmp_script_len_code_pt lcode;
- ngx_rtmp_script_engine_t e;
- ngx_rtmp_core_main_conf_t *cmcf;
-
- cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module);
-
- for (i = 0; i < cmcf->variables.nelts; i++) {
- if (s->variables[i].no_cacheable) {
- s->variables[i].valid = 0;
- s->variables[i].not_found = 0;
- }
- }
-
- ngx_memzero(&e, sizeof(ngx_rtmp_script_engine_t));
-
- e.ip = code_lengths;
- e.request = s;
- e.flushed = 1;
-
- while (*(uintptr_t *) e.ip) {
- lcode = *(ngx_rtmp_script_len_code_pt *) e.ip;
- len += lcode(&e);
- }
-
-
- value->len = len;
- value->data = ngx_pnalloc(s->connection->pool, len);
- if (value->data == NULL) {
- return NULL;
- }
-
- e.ip = code_values;
- e.pos = value->data;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_rtmp_script_code_pt *) e.ip;
- code((ngx_rtmp_script_engine_t *) &e);
- }
-
- return e.pos;
-}
-
-
-void
-ngx_rtmp_script_flush_no_cacheable_variables(ngx_rtmp_session_t *s,
- ngx_array_t *indices)
-{
- ngx_uint_t n, *index;
-
- if (indices) {
- index = indices->elts;
- for (n = 0; n < indices->nelts; n++) {
- if (s->variables[index[n]].no_cacheable) {
- s->variables[index[n]].valid = 0;
- s->variables[index[n]].not_found = 0;
- }
- }
- }
-}
-
-
-static ngx_int_t
-ngx_rtmp_script_init_arrays(ngx_rtmp_script_compile_t *sc)
-{
- ngx_uint_t n;
-
- if (sc->flushes && *sc->flushes == NULL) {
- n = sc->variables ? sc->variables : 1;
- *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
- if (*sc->flushes == NULL) {
- return NGX_ERROR;
- }
- }
-
- if (*sc->lengths == NULL) {
- n = sc->variables * (2 * sizeof(ngx_rtmp_script_copy_code_t)
- + sizeof(ngx_rtmp_script_var_code_t))
- + sizeof(uintptr_t);
-
- *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
- if (*sc->lengths == NULL) {
- return NGX_ERROR;
- }
- }
-
- if (*sc->values == NULL) {
- n = (sc->variables * (2 * sizeof(ngx_rtmp_script_copy_code_t)
- + sizeof(ngx_rtmp_script_var_code_t))
- + sizeof(uintptr_t)
- + sc->source->len
- + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- *sc->values = ngx_array_create(sc->cf->pool, n, 1);
- if (*sc->values == NULL) {
- return NGX_ERROR;
- }
- }
-
- sc->variables = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_rtmp_script_done(ngx_rtmp_script_compile_t *sc)
-{
- ngx_str_t zero;
- uintptr_t *code;
-
- if (sc->zero) {
-
- zero.len = 1;
- zero.data = (u_char *) "\0";
-
- if (ngx_rtmp_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- if (sc->conf_prefix || sc->root_prefix) {
- if (ngx_rtmp_script_add_full_name_code(sc) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- if (sc->complete_lengths) {
- code = ngx_rtmp_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- if (sc->complete_values) {
- code = ngx_rtmp_script_add_code(*sc->values, sizeof(uintptr_t),
- &sc->main);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- return NGX_OK;
-}
-
-
-void *
-ngx_rtmp_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
-{
- if (*codes == NULL) {
- *codes = ngx_array_create(pool, 256, 1);
- if (*codes == NULL) {
- return NULL;
- }
- }
-
- return ngx_array_push_n(*codes, size);
-}
-
-
-void *
-ngx_rtmp_script_add_code(ngx_array_t *codes, size_t size, void *code)
-{
- u_char *elts, **p;
- void *new;
-
- elts = codes->elts;
-
- new = ngx_array_push_n(codes, size);
- if (new == NULL) {
- return NULL;
- }
-
- if (code) {
- if (elts != codes->elts) {
- p = code;
- *p += (u_char *) codes->elts - elts;
- }
- }
-
- return new;
-}
-
-
-static ngx_int_t
-ngx_rtmp_script_add_copy_code(ngx_rtmp_script_compile_t *sc, ngx_str_t *value,
- ngx_uint_t last)
-{
- u_char *p;
- size_t size, len, zero;
- ngx_rtmp_script_copy_code_t *code;
-
- zero = (sc->zero && last);
- len = value->len + zero;
-
- code = ngx_rtmp_script_add_code(*sc->lengths,
- sizeof(ngx_rtmp_script_copy_code_t), NULL);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = (ngx_rtmp_script_code_pt) ngx_rtmp_script_copy_len_code;
- code->len = len;
-
- size = (sizeof(ngx_rtmp_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- code = ngx_rtmp_script_add_code(*sc->values, size, &sc->main);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = ngx_rtmp_script_copy_code;
- code->len = len;
-
- p = ngx_cpymem((u_char *) code + sizeof(ngx_rtmp_script_copy_code_t),
- value->data, value->len);
-
- if (zero) {
- *p = '\0';
- sc->zero = 0;
- }
-
- return NGX_OK;
-}
-
-
-size_t
-ngx_rtmp_script_copy_len_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_script_copy_code_t *code;
-
- code = (ngx_rtmp_script_copy_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_copy_code_t);
-
- return code->len;
-}
-
-
-void
-ngx_rtmp_script_copy_code(ngx_rtmp_script_engine_t *e)
-{
- u_char *p;
- ngx_rtmp_script_copy_code_t *code;
-
- code = (ngx_rtmp_script_copy_code_t *) e->ip;
-
- p = e->pos;
-
- if (!e->skip) {
- e->pos = ngx_copy(p, e->ip + sizeof(ngx_rtmp_script_copy_code_t),
- code->len);
- }
-
- e->ip += sizeof(ngx_rtmp_script_copy_code_t)
- + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
-
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script copy: \"%*s\"", e->pos - p, p);
-}
-
-
-static ngx_int_t
-ngx_rtmp_script_add_var_code(ngx_rtmp_script_compile_t *sc, ngx_str_t *name)
-{
- ngx_int_t index, *p;
- ngx_rtmp_script_var_code_t *code;
-
- index = ngx_rtmp_get_variable_index(sc->cf, name);
-
- if (index == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (sc->flushes) {
- p = ngx_array_push(*sc->flushes);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- *p = index;
- }
-
- code = ngx_rtmp_script_add_code(*sc->lengths,
- sizeof(ngx_rtmp_script_var_code_t), NULL);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = (ngx_rtmp_script_code_pt) ngx_rtmp_script_copy_var_len_code;
- code->index = (uintptr_t) index;
-
- code = ngx_rtmp_script_add_code(*sc->values,
- sizeof(ngx_rtmp_script_var_code_t),
- &sc->main);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = ngx_rtmp_script_copy_var_code;
- code->index = (uintptr_t) index;
-
- return NGX_OK;
-}
-
-
-size_t
-ngx_rtmp_script_copy_var_len_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_variable_value_t *value;
- ngx_rtmp_script_var_code_t *code;
-
- code = (ngx_rtmp_script_var_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_var_code_t);
-
- if (e->flushed) {
- value = ngx_rtmp_get_indexed_variable(e->request, code->index);
-
- } else {
- value = ngx_rtmp_get_flushed_variable(e->request, code->index);
- }
-
- if (value && !value->not_found) {
- return value->len;
- }
-
- return 0;
-}
-
-
-void
-ngx_rtmp_script_copy_var_code(ngx_rtmp_script_engine_t *e)
-{
- u_char *p;
- ngx_rtmp_variable_value_t *value;
- ngx_rtmp_script_var_code_t *code;
-
- code = (ngx_rtmp_script_var_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_var_code_t);
-
- if (!e->skip) {
-
- if (e->flushed) {
- value = ngx_rtmp_get_indexed_variable(e->request, code->index);
-
- } else {
- value = ngx_rtmp_get_flushed_variable(e->request, code->index);
- }
-
- if (value && !value->not_found) {
- p = e->pos;
- e->pos = ngx_copy(p, value->data, value->len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP,
- e->request->connection->log, 0,
- "rtmp script var: \"%*s\"", e->pos - p, p);
- }
- }
-}
-
-
-static ngx_int_t
-ngx_rtmp_script_add_args_code(ngx_rtmp_script_compile_t *sc)
-{
- uintptr_t *code;
-
- code = ngx_rtmp_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) ngx_rtmp_script_mark_args_code;
-
- code = ngx_rtmp_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) ngx_rtmp_script_start_args_code;
-
- return NGX_OK;
-}
-
-
-size_t
-ngx_rtmp_script_mark_args_code(ngx_rtmp_script_engine_t *e)
-{
- e->is_args = 1;
- e->ip += sizeof(uintptr_t);
-
- return 1;
-}
-
-
-void
-ngx_rtmp_script_start_args_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script args");
-
- e->is_args = 1;
- e->args = e->pos;
- e->ip += sizeof(uintptr_t);
-}
-
-
-#if (NGX_PCRE)
-
-static ngx_int_t
-ngx_rtmp_script_add_capture_code(ngx_rtmp_script_compile_t *sc, ngx_uint_t n)
-{
- ngx_rtmp_script_copy_capture_code_t *code;
-
- code = ngx_rtmp_script_add_code(*sc->lengths,
- sizeof(ngx_rtmp_script_copy_capture_code_t),
- NULL);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = (ngx_rtmp_script_code_pt)
- ngx_rtmp_script_copy_capture_len_code;
- code->n = 2 * n;
-
-
- code = ngx_rtmp_script_add_code(*sc->values,
- sizeof(ngx_rtmp_script_copy_capture_code_t),
- &sc->main);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = ngx_rtmp_script_copy_capture_code;
- code->n = 2 * n;
-
- if (sc->ncaptures < n) {
- sc->ncaptures = n;
- }
-
- return NGX_OK;
-}
-
-
-size_t
-ngx_rtmp_script_copy_capture_len_code(ngx_rtmp_script_engine_t *e)
-{
- int *cap;
- u_char *p;
- ngx_uint_t n;
- ngx_rtmp_session_t *s;
- ngx_rtmp_script_copy_capture_code_t *code;
-
- s = e->request;
-
- code = (ngx_rtmp_script_copy_capture_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_copy_capture_code_t);
-
- n = code->n;
-
- if (n < s->ncaptures) {
-
- cap = s->captures;
-
- if ((e->is_args || e->quote)
- && (e->request->quoted_uri || e->request->plus_in_uri))
- {
- p = s->captures_data;
-
- return cap[n + 1] - cap[n]
- + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
- NGX_ESCAPE_ARGS);
- } else {
- return cap[n + 1] - cap[n];
- }
- }
-
- return 0;
-}
-
-
-void
-ngx_rtmp_script_copy_capture_code(ngx_rtmp_script_engine_t *e)
-{
- int *cap;
- u_char *p, *pos;
- ngx_uint_t n;
- ngx_rtmp_session_t *s;
- ngx_rtmp_script_copy_capture_code_t *code;
-
- s = e->request;
-
- code = (ngx_rtmp_script_copy_capture_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_copy_capture_code_t);
-
- n = code->n;
-
- pos = e->pos;
-
- if (n < s->ncaptures) {
-
- cap = s->captures;
- p = s->captures_data;
-
- if ((e->is_args || e->quote)
- && (e->request->quoted_uri || e->request->plus_in_uri))
- {
- e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
- cap[n + 1] - cap[n],
- NGX_ESCAPE_ARGS);
- } else {
- e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script capture: \"%*s\"", e->pos - pos, pos);
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_rtmp_script_add_full_name_code(ngx_rtmp_script_compile_t *sc)
-{
- ngx_rtmp_script_full_name_code_t *code;
-
- code = ngx_rtmp_script_add_code(*sc->lengths,
- sizeof(ngx_rtmp_script_full_name_code_t),
- NULL);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = (ngx_rtmp_script_code_pt) ngx_rtmp_script_full_name_len_code;
- code->conf_prefix = sc->conf_prefix;
-
- code = ngx_rtmp_script_add_code(*sc->values,
- sizeof(ngx_rtmp_script_full_name_code_t),
- &sc->main);
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- code->code = ngx_rtmp_script_full_name_code;
- code->conf_prefix = sc->conf_prefix;
-
- return NGX_OK;
-}
-
-
-static size_t
-ngx_rtmp_script_full_name_len_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_script_full_name_code_t *code;
-
- code = (ngx_rtmp_script_full_name_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_full_name_code_t);
-
- return code->conf_prefix ? ngx_cycle->conf_prefix.len:
- ngx_cycle->prefix.len;
-}
-
-
-static void
-ngx_rtmp_script_full_name_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_script_full_name_code_t *code;
-
- ngx_str_t value;
-
-#if (nginx_version >= 1005003)
- ngx_str_t *prefix;
-#endif
-
- code = (ngx_rtmp_script_full_name_code_t *) e->ip;
-
- value.data = e->buf.data;
- value.len = e->pos - e->buf.data;
-
-#if (nginx_version >= 1005003)
- prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
- (ngx_str_t *) &ngx_cycle->prefix;
-
- if (ngx_get_full_name(e->request->connection->pool, prefix,
- &value) != NGX_OK)
-#else
- if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value,
- code->conf_prefix) != NGX_OK)
-#endif
- {
- e->ip = ngx_rtmp_script_exit;
- e->status = NGX_RTMP_INTERNAL_SERVER_ERROR;
- return;
- }
-
- e->buf = value;
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script fullname: \"%V\"", &value);
-
- e->ip += sizeof(ngx_rtmp_script_full_name_code_t);
-}
-
-
-void
-ngx_rtmp_script_complex_value_code(ngx_rtmp_script_engine_t *e)
-{
- size_t len;
- ngx_rtmp_script_engine_t le;
- ngx_rtmp_script_len_code_pt lcode;
- ngx_rtmp_script_complex_value_code_t *code;
-
- code = (ngx_rtmp_script_complex_value_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_complex_value_code_t);
-
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script complex value");
-
- ngx_memzero(&le, sizeof(ngx_rtmp_script_engine_t));
-
- le.ip = code->lengths->elts;
- le.line = e->line;
- le.request = e->request;
- le.quote = e->quote;
-
- for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
- lcode = *(ngx_rtmp_script_len_code_pt *) le.ip;
- }
-
- e->buf.len = len;
- e->buf.data = ngx_pnalloc(e->request->connection->pool, len);
- if (e->buf.data == NULL) {
- e->ip = ngx_rtmp_script_exit;
- return;
- }
-
- e->pos = e->buf.data;
-
- e->sp->len = e->buf.len;
- e->sp->data = e->buf.data;
- e->sp++;
-}
-
-
-void
-ngx_rtmp_script_value_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_script_value_code_t *code;
-
- code = (ngx_rtmp_script_value_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_value_code_t);
-
- e->sp->len = code->text_len;
- e->sp->data = (u_char *) code->text_data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script value: \"%v\"", e->sp);
-
- e->sp++;
-}
-
-
-void
-ngx_rtmp_script_set_var_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_session_t *s;
- ngx_rtmp_script_var_code_t *code;
-
- code = (ngx_rtmp_script_var_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_var_code_t);
-
- s = e->request;
-
- e->sp--;
-
- s->variables[code->index].len = e->sp->len;
- s->variables[code->index].valid = 1;
- s->variables[code->index].no_cacheable = 0;
- s->variables[code->index].not_found = 0;
- s->variables[code->index].data = e->sp->data;
-
-#if (NGX_DEBUG)
- {
- ngx_rtmp_variable_t *v;
- ngx_rtmp_core_main_conf_t *cmcf;
-
- cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module);
-
- v = cmcf->variables.elts;
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script set $%V", &v[code->index].name);
- }
-#endif
-}
-
-
-void
-ngx_rtmp_script_var_set_handler_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_script_var_handler_code_t *code;
-
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script set var handler");
-
- code = (ngx_rtmp_script_var_handler_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_var_handler_code_t);
-
- e->sp--;
-
- code->handler(e->request, e->sp, code->data);
-}
-
-
-void
-ngx_rtmp_script_var_code(ngx_rtmp_script_engine_t *e)
-{
- ngx_rtmp_variable_value_t *value;
- ngx_rtmp_script_var_code_t *code;
-
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script var");
-
- code = (ngx_rtmp_script_var_code_t *) e->ip;
-
- e->ip += sizeof(ngx_rtmp_script_var_code_t);
-
- value = ngx_rtmp_get_flushed_variable(e->request, code->index);
-
- if (value && !value->not_found) {
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->request->connection->log, 0,
- "rtmp script var: \"%v\"", value);
-
- *e->sp = *value;
- e->sp++;
-
- return;
- }
-
- *e->sp = ngx_rtmp_variable_null_value;
- e->sp++;
-}
-
-
-void
-ngx_rtmp_script_nop_code(ngx_rtmp_script_engine_t *e)
-{
- e->ip += sizeof(uintptr_t);
-}
-
diff --git a/ngx_rtmp_script.h b/ngx_rtmp_script.h
deleted file mode 100644
index fa21a41..0000000
--- a/ngx_rtmp_script.h
+++ /dev/null
@@ -1,216 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- * Copyright (C) Winshining
- */
-
-
-#ifndef _NGX_RTMP_SCRIPT_H_INCLUDED_
-#define _NGX_RTMP_SCRIPT_H_INCLUDED_
-
-
-#include
-#include
-#include "ngx_rtmp.h"
-
-
-typedef struct {
- u_char *ip;
- u_char *pos;
- ngx_rtmp_variable_value_t *sp;
-
- ngx_str_t buf;
- ngx_str_t line;
-
- /* the start of the rewritten arguments */
- u_char *args;
-
- unsigned flushed:1;
- unsigned skip:1;
- unsigned quote:1;
- unsigned is_args:1;
- unsigned log:1;
-
- ngx_int_t status;
- ngx_rtmp_session_t *request;
-} ngx_rtmp_script_engine_t;
-
-
-typedef struct {
- ngx_conf_t *cf;
- ngx_str_t *source;
-
- ngx_array_t **flushes;
- ngx_array_t **lengths;
- ngx_array_t **values;
-
- ngx_uint_t variables;
- ngx_uint_t ncaptures;
- ngx_uint_t captures_mask;
- ngx_uint_t size;
-
- void *main;
-
- unsigned compile_args:1;
- unsigned complete_lengths:1;
- unsigned complete_values:1;
- unsigned zero:1;
- unsigned conf_prefix:1;
- unsigned root_prefix:1;
-
- unsigned dup_capture:1;
- unsigned args:1;
-} ngx_rtmp_script_compile_t;
-
-
-typedef struct {
- ngx_str_t value;
- ngx_uint_t *flushes;
- void *lengths;
- void *values;
-} ngx_rtmp_complex_value_t;
-
-
-typedef struct {
- ngx_conf_t *cf;
- ngx_str_t *value;
- ngx_rtmp_complex_value_t *complex_value;
-
- unsigned zero:1;
- unsigned conf_prefix:1;
- unsigned root_prefix:1;
-} ngx_rtmp_compile_complex_value_t;
-
-
-typedef void (*ngx_rtmp_script_code_pt) (ngx_rtmp_script_engine_t *e);
-typedef size_t (*ngx_rtmp_script_len_code_pt) (ngx_rtmp_script_engine_t *e);
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- uintptr_t len;
-} ngx_rtmp_script_copy_code_t;
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- uintptr_t index;
-} ngx_rtmp_script_var_code_t;
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- ngx_rtmp_set_variable_pt handler;
- uintptr_t data;
-} ngx_rtmp_script_var_handler_code_t;
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- uintptr_t n;
-} ngx_rtmp_script_copy_capture_code_t;
-
-
-#if (NGX_PCRE)
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- ngx_rtmp_regex_t *regex;
- ngx_array_t *lengths;
- uintptr_t size;
- uintptr_t status;
- uintptr_t next;
-
- unsigned test:1;
- unsigned negative_test:1;
- unsigned uri:1;
- unsigned args:1;
-
- /* add the s->args to the new arguments */
- unsigned add_args:1;
-
- unsigned redirect:1;
- unsigned break_cycle:1;
-
- ngx_str_t name;
-} ngx_rtmp_script_regex_code_t;
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
-
- unsigned uri:1;
- unsigned args:1;
-
- /* add the s->args to the new arguments */
- unsigned add_args:1;
-
- unsigned redirect:1;
-} ngx_rtmp_script_regex_end_code_t;
-
-#endif
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- uintptr_t conf_prefix;
-} ngx_rtmp_script_full_name_code_t;
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- ngx_array_t *lengths;
-} ngx_rtmp_script_complex_value_code_t;
-
-
-typedef struct {
- ngx_rtmp_script_code_pt code;
- uintptr_t value;
- uintptr_t text_len;
- uintptr_t text_data;
-} ngx_rtmp_script_value_code_t;
-
-
-void ngx_rtmp_script_flush_complex_value(ngx_rtmp_session_t *s,
- ngx_rtmp_complex_value_t *val);
-ngx_int_t ngx_rtmp_complex_value(ngx_rtmp_session_t *s,
- ngx_rtmp_complex_value_t *val, ngx_str_t *value);
-ngx_int_t ngx_rtmp_compile_complex_value(ngx_rtmp_compile_complex_value_t *ccv);
-char *ngx_rtmp_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-ngx_int_t ngx_rtmp_test_predicates(ngx_rtmp_session_t *s,
- ngx_array_t *predicates);
-char *ngx_rtmp_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-ngx_uint_t ngx_rtmp_script_variables_count(ngx_str_t *value);
-ngx_int_t ngx_rtmp_script_compile(ngx_rtmp_script_compile_t *sc);
-u_char *ngx_rtmp_script_run(ngx_rtmp_session_t *s, ngx_str_t *value,
- void *code_lengths, size_t reserved, void *code_values);
-void ngx_rtmp_script_flush_no_cacheable_variables(ngx_rtmp_session_t *s,
- ngx_array_t *indices);
-
-void *ngx_rtmp_script_start_code(ngx_pool_t *pool, ngx_array_t **codes,
- size_t size);
-void *ngx_rtmp_script_add_code(ngx_array_t *codes, size_t size, void *code);
-
-size_t ngx_rtmp_script_copy_len_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_copy_code(ngx_rtmp_script_engine_t *e);
-size_t ngx_rtmp_script_copy_var_len_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_copy_var_code(ngx_rtmp_script_engine_t *e);
-size_t ngx_rtmp_script_copy_capture_len_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_copy_capture_code(ngx_rtmp_script_engine_t *e);
-size_t ngx_rtmp_script_mark_args_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_start_args_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_complex_value_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_value_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_set_var_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_var_set_handler_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_var_code(ngx_rtmp_script_engine_t *e);
-void ngx_rtmp_script_nop_code(ngx_rtmp_script_engine_t *e);
-
-
-#endif /* _NGX_RTMP_SCRIPT_H_INCLUDED_ */
diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c
index 326a811..b31fde3 100644
--- a/ngx_rtmp_stat_module.c
+++ b/ngx_rtmp_stat_module.c
@@ -32,6 +32,9 @@ static time_t start_time;
#define NGX_RTMP_STAT_CLIENTS 0x04
#define NGX_RTMP_STAT_PLAY 0x08
+#define NGX_RTMP_STAT_FORMAT_XML 0x01
+#define NGX_RTMP_STAT_FORMAT_JSON 0x02
+
/*
* global: stat-{bufs-{total,free,used}, total bytes in/out, bw in/out} - cscf
*/
@@ -40,6 +43,7 @@ static time_t start_time;
typedef struct {
ngx_uint_t stat;
ngx_str_t stylesheet;
+ ngx_uint_t format;
} ngx_rtmp_stat_loc_conf_t;
@@ -51,6 +55,11 @@ static ngx_conf_bitmask_t ngx_rtmp_stat_masks[] = {
{ ngx_null_string, 0 }
};
+static ngx_conf_bitmask_t ngx_rtmp_stat_format_masks[] = {
+ { ngx_string("xml"), NGX_RTMP_STAT_FORMAT_XML },
+ { ngx_string("json"), NGX_RTMP_STAT_FORMAT_JSON },
+ { ngx_null_string, 0 }
+};
static ngx_command_t ngx_rtmp_stat_commands[] = {
@@ -67,6 +76,13 @@ static ngx_command_t ngx_rtmp_stat_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_rtmp_stat_loc_conf_t, stylesheet),
NULL },
+
+ { ngx_string("rtmp_stat_format"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_rtmp_stat,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_rtmp_stat_loc_conf_t, format),
+ ngx_rtmp_stat_format_masks },
ngx_null_command
};
@@ -158,6 +174,7 @@ ngx_rtmp_stat_escape(ngx_http_request_t *r, void *data, size_t len)
return new_data;
}
+
#if (NGX_WIN32)
/*
* Fix broken MSVC memcpy optimization for 4-byte data
@@ -166,6 +183,7 @@ ngx_rtmp_stat_escape(ngx_http_request_t *r, void *data, size_t len)
__declspec(noinline)
#endif
+
static void
ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll,
void *data, size_t len, ngx_uint_t escape)
@@ -255,28 +273,47 @@ ngx_rtmp_stat_bw(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_bandwidth_t *bw, char *name,
ngx_uint_t flags)
{
- u_char buf[NGX_INT64_LEN + 9];
+ u_char buf[NGX_INT64_LEN + 9];
+ ngx_rtmp_stat_loc_conf_t *slcf;
+
+ slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
ngx_rtmp_update_bandwidth(bw, 0);
if (flags & NGX_RTMP_STAT_BW) {
- NGX_RTMP_STAT_L("%uLbandwidth * 8)
- - buf);
- NGX_RTMP_STAT_CS(name);
- NGX_RTMP_STAT_L(">\r\n");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("%uLbandwidth * 8)
+ - buf);
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT_L(">\r\n");
+ } else {
+ NGX_RTMP_STAT_L("\"bw_");
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "\":%uL,",
+ bw->bandwidth * 8)
+ - buf);
+ }
}
if (flags & NGX_RTMP_STAT_BYTES) {
- NGX_RTMP_STAT_L("%uLbytes)
- - buf);
- NGX_RTMP_STAT_CS(name);
- NGX_RTMP_STAT_L(">\r\n");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("%uLbytes)
+ - buf);
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT_L(">\r\n");
+ } else {
+ NGX_RTMP_STAT_L("\"bytes_");
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "\":%uL,",
+ bw->bytes)
+ - buf);
+ }
}
}
@@ -323,46 +360,81 @@ ngx_rtmp_stat_dump_pool(ngx_http_request_t *r, ngx_chain_t ***lll,
#endif
-
static void
ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_session_t *s)
{
- u_char buf[NGX_INT_T_LEN];
+ u_char buf[NGX_INT_T_LEN];
+ ngx_rtmp_stat_loc_conf_t *slcf;
+
+ slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
#ifdef NGX_RTMP_POOL_DEBUG
ngx_rtmp_stat_dump_pool(r, lll, s->connection->pool);
#endif
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui",
- (ngx_uint_t) s->connection->number) - buf);
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ES(&s->connection->addr_text);
- NGX_RTMP_STAT_L("");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui",
+ (ngx_uint_t) s->connection->number) - buf);
+ NGX_RTMP_STAT_L("");
+
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ES(&s->connection->addr_text);
+ NGX_RTMP_STAT_L("");
+
+ NGX_RTMP_STAT_L("");
+
+ if (s->flashver.len) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ES(&s->flashver);
+ NGX_RTMP_STAT_L("");
+ }
- NGX_RTMP_STAT_L("");
+ if (s->page_url.len) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ES(&s->page_url);
+ NGX_RTMP_STAT_L("");
+ }
- if (s->flashver.len) {
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ES(&s->flashver);
- NGX_RTMP_STAT_L("");
- }
+ if (s->swf_url.len) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ES(&s->swf_url);
+ NGX_RTMP_STAT_L("");
+ }
+ } else {
+ NGX_RTMP_STAT_L("\"id\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui",
+ (ngx_uint_t) s->connection->number) - buf);
+
+ NGX_RTMP_STAT_L(",\"address\":\"");
+ NGX_RTMP_STAT_ES(&s->connection->addr_text);
+
+ NGX_RTMP_STAT_L("\",\"time\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%i",
+ (ngx_int_t) (ngx_current_msec - s->epoch)) - buf);
+ NGX_RTMP_STAT_L(",");
+
+ if (s->flashver.len) {
+ NGX_RTMP_STAT_L("\"flashver\":\"");
+ NGX_RTMP_STAT_ES(&s->flashver);
+ NGX_RTMP_STAT_L("\",");
+ }
- if (s->page_url.len) {
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ES(&s->page_url);
- NGX_RTMP_STAT_L("");
- }
+ if (s->page_url.len) {
+ NGX_RTMP_STAT_L("\"pageurl\":\"");
+ NGX_RTMP_STAT_ES(&s->page_url);
+ NGX_RTMP_STAT_L("\",");
+ }
- if (s->swf_url.len) {
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ES(&s->swf_url);
- NGX_RTMP_STAT_L("");
+ if (s->swf_url.len) {
+ NGX_RTMP_STAT_L("\"swfurl\":\"");
+ NGX_RTMP_STAT_ES(&s->swf_url);
+ NGX_RTMP_STAT_L("\",");
+ }
}
}
@@ -417,6 +489,7 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_session_t *s;
ngx_int_t n;
ngx_uint_t nclients, total_nclients;
+ ngx_uint_t f;
u_char buf[NGX_INT_T_LEN];
u_char bbuf[NGX_INT32_LEN];
ngx_rtmp_stat_loc_conf_t *slcf;
@@ -428,22 +501,48 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll,
slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
- NGX_RTMP_STAT_L("\r\n");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("\"live\":{");
+ NGX_RTMP_STAT_L("\"streams\":[");
+ }
total_nclients = 0;
for (n = 0; n < lacf->nbuckets; ++n) {
for (stream = lacf->streams[n]; stream; stream = stream->next) {
- NGX_RTMP_STAT_L("\r\n");
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ECS(stream->name);
- NGX_RTMP_STAT_L("\r\n");
+
+ if(total_nclients > 0) {
+ NGX_RTMP_STAT_L(",");
+ }
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("{");
+ }
- NGX_RTMP_STAT_L("");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ECS(stream->name);
+ NGX_RTMP_STAT_L("\r\n");
+
+ NGX_RTMP_STAT_L("");
+ } else {
+ NGX_RTMP_STAT_L("\"name\":\"");
+ NGX_RTMP_STAT_ECS(stream->name);
+ NGX_RTMP_STAT_L("\",");
+
+ NGX_RTMP_STAT_L("\"time\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%i",
+ (ngx_int_t) (ngx_current_msec - stream->epoch))
+ - buf);
+ NGX_RTMP_STAT_L(",");
+ }
ngx_rtmp_stat_bw(r, lll, &stream->bw_in, "in",
NGX_RTMP_STAT_BW_BYTES);
@@ -456,148 +555,316 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll,
nclients = 0;
codec = NULL;
+
+ if (slcf->stat & NGX_RTMP_STAT_CLIENTS && slcf->format & NGX_RTMP_STAT_FORMAT_JSON) {
+ NGX_RTMP_STAT_L("\"clients\":[");
+ }
+
for (ctx = stream->ctx; ctx; ctx = ctx->next, ++nclients) {
s = ctx->session;
if (slcf->stat & NGX_RTMP_STAT_CLIENTS) {
- NGX_RTMP_STAT_L("");
-
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ } else {
+ NGX_RTMP_STAT_L("{");
+ }
+
ngx_rtmp_stat_client(r, lll, s);
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%ui", ctx->ndropped) - buf);
- NGX_RTMP_STAT_L("");
-
- NGX_RTMP_STAT_L("");
- if (!lacf->interleave) {
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", ctx->ndropped) - buf);
+ NGX_RTMP_STAT_L("");
+
+ NGX_RTMP_STAT_L("");
+ if (!lacf->interleave) {
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", ctx->cs[1].timestamp -
+ ctx->cs[0].timestamp) - bbuf);
+ }
+ NGX_RTMP_STAT_L("");
+
+ NGX_RTMP_STAT_L("");
NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
- "%D", ctx->cs[1].timestamp -
- ctx->cs[0].timestamp) - bbuf);
- }
- NGX_RTMP_STAT_L("");
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
- "%D", s->current_time) - bbuf);
- NGX_RTMP_STAT_L("");
-
- if (ctx->publishing) {
- NGX_RTMP_STAT_L("");
+ "%D", s->current_time) - bbuf);
+ NGX_RTMP_STAT_L("");
+
+ if (ctx->publishing) {
+ NGX_RTMP_STAT_L("");
+ }
+
+ if (ctx->active) {
+ NGX_RTMP_STAT_L("");
+ }
+ } else {
+ NGX_RTMP_STAT_L("\"dropped\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", ctx->ndropped) - buf);
+
+ NGX_RTMP_STAT_L(",\"avsync\":");
+ if (!lacf->interleave) {
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", ctx->cs[1].timestamp -
+ ctx->cs[0].timestamp) - bbuf);
+ }
+
+ NGX_RTMP_STAT_L(",\"timestamp\":");
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", s->current_time) - bbuf);
+
+ NGX_RTMP_STAT_L(",\"publishing\":");
+ if (ctx->publishing) {
+ NGX_RTMP_STAT_L("true");
+ } else {
+ NGX_RTMP_STAT_L("false");
+ }
+
+ NGX_RTMP_STAT_L(",\"active\":");
+ if (ctx->active) {
+ NGX_RTMP_STAT_L("true");
+ } else {
+ NGX_RTMP_STAT_L("false");
+ }
}
-
- if (ctx->active) {
- NGX_RTMP_STAT_L("");
+
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("}");
+ if(ctx->next) {
+ NGX_RTMP_STAT_L(",");
+ }
}
-
- NGX_RTMP_STAT_L("\r\n");
}
if (ctx->publishing) {
codec = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
}
}
total_nclients += nclients;
-
+
+ if (slcf->stat & NGX_RTMP_STAT_CLIENTS && slcf->format & NGX_RTMP_STAT_FORMAT_JSON) {
+ NGX_RTMP_STAT_L("],");
+ }
+
if (codec) {
- NGX_RTMP_STAT_L("");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_L("");
-
- NGX_RTMP_STAT_L("");
+ "%ui", codec->height) - buf);
+ NGX_RTMP_STAT_L(",\"frame_rate\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->frame_rate) - buf);
- NGX_RTMP_STAT_L("\r\n");
- }
+ cname = ngx_rtmp_get_video_codec_name(codec->video_codec_id);
+ if (*cname) {
+ NGX_RTMP_STAT_L(",\"codec\":\"");
+ NGX_RTMP_STAT_ECS(cname);
+ }
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%ui", nclients) - buf);
- NGX_RTMP_STAT_L("\r\n");
+ if (codec->avc_profile) {
+ NGX_RTMP_STAT_L("\",\"profile\":\"");
+ NGX_RTMP_STAT_CS(ngx_rtmp_stat_get_avc_profile(codec->avc_profile));
- if (stream->publishing) {
- NGX_RTMP_STAT_L("\r\n");
- }
+ }
+ if (codec->avc_compat) {
+ NGX_RTMP_STAT_L("\",\"compat\":\"");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->avc_compat) - buf);
+ }
+ if (codec->avc_level) {
+ NGX_RTMP_STAT_L("\",\"level\":\"");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%.1f", codec->avc_level / 10.) - buf);
+ }
+ NGX_RTMP_STAT_L("\"");
- if (stream->active) {
- NGX_RTMP_STAT_L("\r\n");
+
+ NGX_RTMP_STAT_L("}, \"audio\": {");
+ cname = ngx_rtmp_get_audio_codec_name(codec->audio_codec_id);
+ f = 0;
+ if (*cname) {
+ f = 1;
+ NGX_RTMP_STAT_L("\"codec\":\"");
+ NGX_RTMP_STAT_ECS(cname);
+ }
+ if (codec->aac_profile) {
+ if(f == 1) NGX_RTMP_STAT_L("\",");
+ f = 2;
+ NGX_RTMP_STAT_L("\"profile\":\"");
+ NGX_RTMP_STAT_CS(
+ ngx_rtmp_stat_get_aac_profile(codec->aac_profile,
+ codec->aac_sbr,
+ codec->aac_ps));
+ }
+ if (codec->aac_chan_conf) {
+ if(f >= 1) NGX_RTMP_STAT_L("\",");
+ f = 3;
+ NGX_RTMP_STAT_L("\"channels\":\"");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->aac_chan_conf) - buf);
+ } else if (codec->audio_channels) {
+ if(f >= 1) NGX_RTMP_STAT_L("\",");
+ f = 3;
+ NGX_RTMP_STAT_L("\"channels\":\"");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->audio_channels) - buf);
+ }
+ if (codec->sample_rate) {
+ if(f >= 1) NGX_RTMP_STAT_L("\",");
+ f = 4;
+ NGX_RTMP_STAT_L("\"sample_rate\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->sample_rate) - buf);
+ }
+ if (f >= 1 && f <= 3) {
+ NGX_RTMP_STAT_L("\"");
+ }
+ NGX_RTMP_STAT_L("}");
+
+ NGX_RTMP_STAT_L("}");
+ }
}
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", nclients) - buf);
+ NGX_RTMP_STAT_L("\r\n");
- NGX_RTMP_STAT_L("\r\n");
- }
- }
+ if (stream->publishing) {
+ NGX_RTMP_STAT_L("\r\n");
+ }
+
+ if (stream->active) {
+ NGX_RTMP_STAT_L("\r\n");
+ }
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%ui", total_nclients) - buf);
- NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ if(codec) {
+ NGX_RTMP_STAT_L(",");
+ }
+ NGX_RTMP_STAT_L("\"nclients\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", nclients) - buf);
+
+ NGX_RTMP_STAT_L(",\"publishing\":");
+ if (stream->publishing) {
+ NGX_RTMP_STAT_L("true");
+ } else {
+ NGX_RTMP_STAT_L("false");
+ }
+
+ NGX_RTMP_STAT_L(",\"active\":");
+ if (stream->active) {
+ NGX_RTMP_STAT_L("true");
+ } else {
+ NGX_RTMP_STAT_L("false");
+ }
- NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("}");
+ }
+ }
+ }
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", total_nclients) - buf);
+ NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("],\"nclients\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", total_nclients) - buf);
+ NGX_RTMP_STAT_L("}");
+ }
+
}
@@ -617,21 +884,33 @@ ngx_rtmp_stat_play(ngx_http_request_t *r, ngx_chain_t ***lll,
}
slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
-
- NGX_RTMP_STAT_L("\r\n");
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("\"play\":{");
+ NGX_RTMP_STAT_L("\"streams\":[");
+ }
total_nclients = 0;
for (n = 0; n < pacf->nbuckets; ++n) {
for (ctx = pacf->ctx[n]; ctx; ) {
- NGX_RTMP_STAT_L("\r\n");
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ECS(ctx->name);
- NGX_RTMP_STAT_L("\r\n");
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ECS(ctx->name);
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("{\"name\":\"");
+ NGX_RTMP_STAT_ECS(ctx->name);
+ NGX_RTMP_STAT_L("\",\"clients\":[");
+ }
nclients = 0;
sctx = ctx;
for (; ctx; ctx = ctx->next) {
+
if (ngx_strcmp(ctx->name, sctx->name)) {
break;
}
@@ -640,36 +919,65 @@ ngx_rtmp_stat_play(ngx_http_request_t *r, ngx_chain_t ***lll,
s = ctx->session;
if (slcf->stat & NGX_RTMP_STAT_CLIENTS) {
- NGX_RTMP_STAT_L("");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
- ngx_rtmp_stat_client(r, lll, s);
+ ngx_rtmp_stat_client(r, lll, s);
+
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", s->current_time) - bbuf);
+ NGX_RTMP_STAT_L("");
+
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("{");
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
- "%D", s->current_time) - bbuf);
- NGX_RTMP_STAT_L("");
+ ngx_rtmp_stat_client(r, lll, s);
- NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("\"timestamp\":");
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", s->current_time) - bbuf);
+
+ NGX_RTMP_STAT_L("}");
+ if(ctx->next) {
+ NGX_RTMP_STAT_L(",");
+ }
+ }
}
}
total_nclients += nclients;
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%ui", nclients) - buf);
- NGX_RTMP_STAT_L("\r\n");
-
- NGX_RTMP_STAT_L("\r\n");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", nclients) - buf);
+ NGX_RTMP_STAT_L("\r\n");
+
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("],");
+ NGX_RTMP_STAT_L("\"active\":true,");
+ NGX_RTMP_STAT_L("\"nclients\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", nclients) - buf);
+ NGX_RTMP_STAT_L("}");
+ }
}
}
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%ui", total_nclients) - buf);
- NGX_RTMP_STAT_L("\r\n");
-
- NGX_RTMP_STAT_L("\r\n");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", total_nclients) - buf);
+ NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("],\"nclients\":");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", total_nclients) - buf);
+ NGX_RTMP_STAT_L("}");
+ }
}
@@ -678,13 +986,25 @@ ngx_rtmp_stat_application(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_core_app_conf_t *cacf)
{
ngx_rtmp_stat_loc_conf_t *slcf;
-
- NGX_RTMP_STAT_L("\r\n");
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT_ES(&cacf->name);
- NGX_RTMP_STAT_L("\r\n");
-
+
slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT_ES(&cacf->name);
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("{");
+ NGX_RTMP_STAT_L("\"name\":\"");
+ NGX_RTMP_STAT_ES(&cacf->name);
+
+ if (slcf->stat & NGX_RTMP_STAT_LIVE || slcf->stat & NGX_RTMP_STAT_PLAY) {
+ NGX_RTMP_STAT_L("\",");
+ } else {
+ NGX_RTMP_STAT_L("\"");
+ }
+ }
if (slcf->stat & NGX_RTMP_STAT_LIVE) {
ngx_rtmp_stat_live(r, lll,
@@ -696,7 +1016,11 @@ ngx_rtmp_stat_application(ngx_http_request_t *r, ngx_chain_t ***lll,
cacf->app_conf[ngx_rtmp_play_module.ctx_index]);
}
- NGX_RTMP_STAT_L("\r\n");
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("}");
+ }
}
@@ -706,8 +1030,15 @@ ngx_rtmp_stat_server(ngx_http_request_t *r, ngx_chain_t ***lll,
{
ngx_rtmp_core_app_conf_t **cacf;
size_t n;
-
- NGX_RTMP_STAT_L("\r\n");
+ ngx_rtmp_stat_loc_conf_t *slcf;
+
+ slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("[");
+ }
#ifdef NGX_RTMP_POOL_DEBUG
ngx_rtmp_stat_dump_pool(r, lll, cscf->pool);
@@ -716,9 +1047,17 @@ ngx_rtmp_stat_server(ngx_http_request_t *r, ngx_chain_t ***lll,
cacf = cscf->applications.elts;
for (n = 0; n < cscf->applications.nelts; ++n, ++cacf) {
ngx_rtmp_stat_application(r, lll, *cacf);
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_JSON && n < cscf->applications.nelts-1) {
+ NGX_RTMP_STAT_L(",");
+ }
+ }
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("]");
}
-
- NGX_RTMP_STAT_L("\r\n");
}
@@ -735,9 +1074,14 @@ ngx_rtmp_stat_handler(ngx_http_request_t *r)
static u_char nbuf[NGX_INT_T_LEN];
slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
+
if (slcf->stat == 0) {
return NGX_DECLINED;
}
+
+ if (slcf->format == 0) {
+ slcf->format = NGX_RTMP_STAT_FORMAT_XML;
+ }
cmcf = ngx_rtmp_core_main_conf;
if (cmcf == NULL) {
@@ -747,59 +1091,111 @@ ngx_rtmp_stat_handler(ngx_http_request_t *r)
cl = NULL;
ll = &cl;
lll = ≪
+
+ if (slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ if (slcf->stylesheet.len) {
+ NGX_RTMP_STAT_L("stylesheet);
+ NGX_RTMP_STAT_L("\" ?>\r\n");
+ }
- NGX_RTMP_STAT_L("\r\n");
- if (slcf->stylesheet.len) {
- NGX_RTMP_STAT_L("stylesheet);
- NGX_RTMP_STAT_L("\" ?>\r\n");
+ NGX_RTMP_STAT_L("\r\n");
+
+ #ifdef NGINX_VERSION
+ NGX_RTMP_STAT_L("" NGINX_VERSION "\r\n");
+ #endif
+
+ #ifdef NGINX_RTMP_VERSION
+ NGX_RTMP_STAT_L(""
+ NGINX_RTMP_VERSION
+ "\r\n");
+ #endif
+
+ #ifdef NGX_COMPILER
+ NGX_RTMP_STAT_L("" NGX_COMPILER "\r\n");
+ #endif
+ NGX_RTMP_STAT_L("" __DATE__ " " __TIME__ "\r\n");
+
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf),
+ "%ui", (ngx_uint_t) ngx_getpid()) - nbuf);
+ NGX_RTMP_STAT_L("\r\n");
+
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(tbuf, ngx_snprintf(tbuf, sizeof(tbuf),
+ "%T", ngx_cached_time->sec - start_time) - tbuf);
+ NGX_RTMP_STAT_L("\r\n");
+
+ NGX_RTMP_STAT_L("");
+ NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf),
+ "%ui", ngx_rtmp_naccepted) - nbuf);
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("{\"http-flv\":{");
+
+ #ifdef NGINX_VERSION
+ NGX_RTMP_STAT_L("\"nginx_version\":\"" NGINX_VERSION "\",");
+ #endif
+
+ #ifdef NGINX_RTMP_VERSION
+ NGX_RTMP_STAT_L("\"nginx_http_flv_version\":\""
+ NGINX_RTMP_VERSION
+ "\",");
+ #endif
+
+ #ifdef NGX_COMPILER
+ NGX_RTMP_STAT_L("\"compiler\":\"" NGX_COMPILER "\",");
+ #endif
+ NGX_RTMP_STAT_L("\"built\":\"" __DATE__ " " __TIME__ "\",");
+
+ NGX_RTMP_STAT_L("\"pid\":");
+ NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf),
+ "%ui", (ngx_uint_t) ngx_getpid()) - nbuf);
+ NGX_RTMP_STAT_L(",");
+
+ NGX_RTMP_STAT_L("\"uptime\":");
+ NGX_RTMP_STAT(tbuf, ngx_snprintf(tbuf, sizeof(tbuf),
+ "%T", ngx_cached_time->sec - start_time) - tbuf);
+ NGX_RTMP_STAT_L(",");
+
+ NGX_RTMP_STAT_L("\"naccepted\":");
+ NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf),
+ "%ui", ngx_rtmp_naccepted) - nbuf);
+ NGX_RTMP_STAT_L(",");
}
- NGX_RTMP_STAT_L("\r\n");
-
-#ifdef NGINX_VERSION
- NGX_RTMP_STAT_L("" NGINX_VERSION "\r\n");
-#endif
-
-#ifdef NGINX_RTMP_VERSION
- NGX_RTMP_STAT_L("" NGINX_RTMP_VERSION "\r\n");
-#endif
-
-#ifdef NGX_COMPILER
- NGX_RTMP_STAT_L("" NGX_COMPILER "\r\n");
-#endif
- NGX_RTMP_STAT_L("" __DATE__ " " __TIME__ "\r\n");
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf),
- "%ui", (ngx_uint_t) ngx_getpid()) - nbuf);
- NGX_RTMP_STAT_L("\r\n");
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(tbuf, ngx_snprintf(tbuf, sizeof(tbuf),
- "%T", ngx_cached_time->sec - start_time) - tbuf);
- NGX_RTMP_STAT_L("\r\n");
-
- NGX_RTMP_STAT_L("");
- NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf),
- "%ui", ngx_rtmp_naccepted) - nbuf);
- NGX_RTMP_STAT_L("\r\n");
-
ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_in, "in", NGX_RTMP_STAT_BW_BYTES);
ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_out, "out", NGX_RTMP_STAT_BW_BYTES);
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_JSON) {
+ NGX_RTMP_STAT_L("\"servers\":[");
+ }
cscf = cmcf->servers.elts;
for (n = 0; n < cmcf->servers.nelts; ++n, ++cscf) {
ngx_rtmp_stat_server(r, lll, *cscf);
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_JSON && n < cmcf->servers.nelts-1) {
+ NGX_RTMP_STAT_L(",");
+ }
}
-
- NGX_RTMP_STAT_L("\r\n");
-
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ NGX_RTMP_STAT_L("\r\n");
+ } else {
+ NGX_RTMP_STAT_L("]}}");
+ }
+
len = 0;
for (l = cl; l; l = l->next) {
len += (l->buf->last - l->buf->pos);
}
- ngx_str_set(&r->headers_out.content_type, "text/xml");
+
+ if(slcf->format & NGX_RTMP_STAT_FORMAT_XML) {
+ ngx_str_set(&r->headers_out.content_type, "text/xml");
+ } else {
+ ngx_str_set(&r->headers_out.content_type, "application/json");
+ }
r->headers_out.content_length_n = len;
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
diff --git a/ngx_rtmp_variables.c b/ngx_rtmp_variables.c
index d5f546e..9632329 100644
--- a/ngx_rtmp_variables.c
+++ b/ngx_rtmp_variables.c
@@ -1,8 +1,8 @@
/*
* Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- * Copyright (C) Winshining
+ * Copyright (C) Nginx, Inc.
+ * Copyright (C) Winshining
*/
@@ -16,10 +16,6 @@ static ngx_rtmp_variable_t *ngx_rtmp_add_prefix_variable(ngx_conf_t *cf,
static ngx_int_t ngx_rtmp_variable_request(ngx_rtmp_session_t *s,
ngx_rtmp_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_rtmp_variable_request_get_size(ngx_rtmp_session_t *s,
- ngx_rtmp_variable_value_t *v, uintptr_t data);
-static void ngx_rtmp_variable_request_set_size(ngx_rtmp_session_t *s,
- ngx_rtmp_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_rtmp_variable_argument(ngx_rtmp_session_t *s,
ngx_rtmp_variable_value_t *v, uintptr_t data);
@@ -112,11 +108,6 @@ static ngx_rtmp_variable_t ngx_rtmp_core_variables[] = {
ngx_rtmp_variable_request_id,
0, 0, 0 },
- { ngx_string("limit_rate"), ngx_rtmp_variable_request_set_size,
- ngx_rtmp_variable_request_get_size,
- offsetof(ngx_rtmp_session_t, limit_rate),
- NGX_RTMP_VAR_CHANGEABLE|NGX_RTMP_VAR_NOCACHEABLE, 0 },
-
{ ngx_string("connection"), NULL,
ngx_rtmp_variable_connection, 0, 0, 0 },
@@ -515,54 +506,6 @@ ngx_rtmp_variable_request(ngx_rtmp_session_t *s, ngx_rtmp_variable_value_t *v,
}
-static ngx_int_t
-ngx_rtmp_variable_request_get_size(ngx_rtmp_session_t *s,
- ngx_rtmp_variable_value_t *v, uintptr_t data)
-{
- size_t *sp;
-
- sp = (size_t *) ((char *) s + data);
-
- v->data = ngx_pnalloc(s->connection->pool, NGX_SIZE_T_LEN);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- return NGX_OK;
-}
-
-
-static void
-ngx_rtmp_variable_request_set_size(ngx_rtmp_session_t *s,
- ngx_rtmp_variable_value_t *v, uintptr_t data)
-{
- ssize_t size, *sp;
- ngx_str_t val;
-
- val.len = v->len;
- val.data = v->data;
-
- size = ngx_parse_size(&val);
-
- if (size == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "invalid size \"%V\"", &val);
- return;
- }
-
- sp = (ssize_t *) ((char *) size + data);
-
- *sp = size;
-
- return;
-}
-
-
ngx_int_t
ngx_rtmp_arg(ngx_rtmp_session_t *s, u_char *name, size_t len, ngx_str_t *value)
{
diff --git a/ngx_rtmp_variables.h b/ngx_rtmp_variables.h
index 6cd34dc..9730966 100644
--- a/ngx_rtmp_variables.h
+++ b/ngx_rtmp_variables.h
@@ -1,8 +1,8 @@
/*
* Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- * Copyright (C) Winshining
+ * Copyright (C) Nginx, Inc.
+ * Copyright (C) Winshining
*/
diff --git a/ngx_rtmp_version.h b/ngx_rtmp_version.h
index 4511349..1654931 100644
--- a/ngx_rtmp_version.h
+++ b/ngx_rtmp_version.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) Roman Arutyunyan
- * Copyright (C) Winshining
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Winshining
*/
@@ -9,8 +9,8 @@
#define _NGX_RTMP_VERSION_H_INCLUDED_
-#define nginx_rtmp_version 1002003
-#define NGINX_RTMP_VERSION "1.2.3"
+#define nginx_rtmp_version 1002005
+#define NGINX_RTMP_VERSION "1.2.5"
#endif /* _NGX_RTMP_VERSION_H_INCLUDED_ */
diff --git a/samples/flv.js.png b/samples/flv.js.png
new file mode 100644
index 0000000..69fc85e
Binary files /dev/null and b/samples/flv.js.png differ
diff --git a/samples/jwplayer_vlc.png b/samples/jwplayer_vlc.png
new file mode 100644
index 0000000..26f410f
Binary files /dev/null and b/samples/jwplayer_vlc.png differ
diff --git a/stat.xsl b/stat.xsl
index 2e1a4ce..c0935e7 100644
--- a/stat.xsl
+++ b/stat.xsl
@@ -13,24 +13,24 @@
- RTMP statistics
+ HTTP-FLV statistics
-
+
Generated by
- nginx-http-flv-module ,
- nginx ,
- pid ,
- built
+ nginx-http-flv-module ,
+ nginx ,
+ pid ,
+ built
-
+
- RTMP |
+ HTTP-FLV |
#clients |
Video |
Audio |
@@ -78,7 +78,7 @@
|
-
+
|