mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-06-30 00:28:58 +02:00
added on_record_done & exec_record_done for recorder{} blocks; added new-style args to exec_* notifiers
This commit is contained in:
parent
6b0dddbcc0
commit
9a31ca9237
5
config
5
config
|
@ -5,11 +5,11 @@ CORE_MODULES="$CORE_MODULES
|
||||||
ngx_rtmp_core_module \
|
ngx_rtmp_core_module \
|
||||||
ngx_rtmp_cmd_module \
|
ngx_rtmp_cmd_module \
|
||||||
ngx_rtmp_access_module \
|
ngx_rtmp_access_module \
|
||||||
|
ngx_rtmp_record_module \
|
||||||
ngx_rtmp_live_module \
|
ngx_rtmp_live_module \
|
||||||
ngx_rtmp_play_module \
|
ngx_rtmp_play_module \
|
||||||
ngx_rtmp_flv_module \
|
ngx_rtmp_flv_module \
|
||||||
ngx_rtmp_mp4_module \
|
ngx_rtmp_mp4_module \
|
||||||
ngx_rtmp_record_module \
|
|
||||||
ngx_rtmp_netcall_module \
|
ngx_rtmp_netcall_module \
|
||||||
ngx_rtmp_relay_module \
|
ngx_rtmp_relay_module \
|
||||||
ngx_rtmp_exec_module \
|
ngx_rtmp_exec_module \
|
||||||
|
@ -33,15 +33,16 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
|
||||||
$ngx_addon_dir/ngx_rtmp_amf.c \
|
$ngx_addon_dir/ngx_rtmp_amf.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_send.c \
|
$ngx_addon_dir/ngx_rtmp_send.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_shared.c \
|
$ngx_addon_dir/ngx_rtmp_shared.c \
|
||||||
|
$ngx_addon_dir/ngx_rtmp_eval.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_receive.c \
|
$ngx_addon_dir/ngx_rtmp_receive.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_core_module.c \
|
$ngx_addon_dir/ngx_rtmp_core_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_cmd_module.c \
|
$ngx_addon_dir/ngx_rtmp_cmd_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_access_module.c \
|
$ngx_addon_dir/ngx_rtmp_access_module.c \
|
||||||
|
$ngx_addon_dir/ngx_rtmp_record_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_live_module.c \
|
$ngx_addon_dir/ngx_rtmp_live_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_play_module.c \
|
$ngx_addon_dir/ngx_rtmp_play_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_flv_module.c \
|
$ngx_addon_dir/ngx_rtmp_flv_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_mp4_module.c \
|
$ngx_addon_dir/ngx_rtmp_mp4_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_record_module.c \
|
|
||||||
$ngx_addon_dir/ngx_rtmp_netcall_module.c \
|
$ngx_addon_dir/ngx_rtmp_netcall_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_stat_module.c \
|
$ngx_addon_dir/ngx_rtmp_stat_module.c \
|
||||||
$ngx_addon_dir/ngx_rtmp_relay_module.c \
|
$ngx_addon_dir/ngx_rtmp_relay_module.c \
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#include <ngx_core.h>
|
#include <ngx_core.h>
|
||||||
#include "ngx_rtmp.h"
|
#include "ngx_rtmp.h"
|
||||||
|
|
||||||
|
#include "ngx_rtmp_eval.h"
|
||||||
#include "ngx_rtmp_cmd_module.h"
|
#include "ngx_rtmp_cmd_module.h"
|
||||||
|
#include "ngx_rtmp_record_module.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifdef HAVE_MALLOC_H
|
#ifdef HAVE_MALLOC_H
|
||||||
|
@ -22,6 +24,7 @@
|
||||||
static ngx_rtmp_publish_pt next_publish;
|
static ngx_rtmp_publish_pt next_publish;
|
||||||
static ngx_rtmp_play_pt next_play;
|
static ngx_rtmp_play_pt next_play;
|
||||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
||||||
|
static ngx_rtmp_record_done_pt next_record_done;
|
||||||
|
|
||||||
|
|
||||||
static char *ngx_rtmp_enotify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_rtmp_enotify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
@ -36,11 +39,14 @@ static char * ngx_rtmp_enotify_merge_app_conf(ngx_conf_t *cf,
|
||||||
#define NGX_RTMP_ENOTIFY_PLAYING 0x02
|
#define NGX_RTMP_ENOTIFY_PLAYING 0x02
|
||||||
|
|
||||||
|
|
||||||
#define NGX_RTMP_ENOTIFY_PUBLISH 0
|
enum {
|
||||||
#define NGX_RTMP_ENOTIFY_PLAY 1
|
NGX_RTMP_ENOTIFY_PUBLISH,
|
||||||
#define NGX_RTMP_ENOTIFY_PUBLISH_DONE 2
|
NGX_RTMP_ENOTIFY_PLAY,
|
||||||
#define NGX_RTMP_ENOTIFY_PLAY_DONE 3
|
NGX_RTMP_ENOTIFY_PUBLISH_DONE,
|
||||||
#define NGX_RTMP_ENOTIFY_MAX 4
|
NGX_RTMP_ENOTIFY_PLAY_DONE,
|
||||||
|
NGX_RTMP_ENOTIFY_RECORD_DONE,
|
||||||
|
NGX_RTMP_ENOTIFY_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -50,7 +56,7 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_rtmp_enotify_conf_t *events[NGX_RTMP_ENOTIFY_MAX];
|
ngx_rtmp_enotify_conf_t *event[NGX_RTMP_ENOTIFY_MAX];
|
||||||
ngx_flag_t active;
|
ngx_flag_t active;
|
||||||
} ngx_rtmp_enotify_app_conf_t;
|
} ngx_rtmp_enotify_app_conf_t;
|
||||||
|
|
||||||
|
@ -92,6 +98,14 @@ static ngx_command_t ngx_rtmp_enotify_commands[] = {
|
||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("exec_record_done"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_RTMP_REC_CONF|
|
||||||
|
NGX_CONF_1MORE,
|
||||||
|
ngx_rtmp_enotify_on_event,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,9 +160,8 @@ ngx_rtmp_enotify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
|
||||||
for (n = 0; n < NGX_RTMP_ENOTIFY_MAX; ++n) {
|
for (n = 0; n < NGX_RTMP_ENOTIFY_MAX; ++n) {
|
||||||
ngx_conf_merge_ptr_value(conf->events[n], prev->events[n], 0);
|
ngx_conf_merge_ptr_value(conf->event[n], prev->event[n], 0);
|
||||||
|
if (conf->event[n]) {
|
||||||
if (conf->events[n]) {
|
|
||||||
conf->active = 1;
|
conf->active = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,21 +170,13 @@ ngx_rtmp_enotify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
|
||||||
ngx_rtmp_exec_prepare_arg(ngx_rtmp_session_t *s, ngx_str_t *arg)
|
|
||||||
{
|
|
||||||
/*TODO*/
|
|
||||||
return (char *) arg->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_enotify_exec(ngx_rtmp_session_t *s, ngx_rtmp_enotify_conf_t *ec)
|
ngx_rtmp_enotify_exec(ngx_rtmp_session_t *s, ngx_rtmp_enotify_conf_t *ec)
|
||||||
{
|
{
|
||||||
#ifndef NGX_WIN32
|
#ifndef NGX_WIN32
|
||||||
ngx_rtmp_enotify_ctx_t *ctx;
|
ngx_rtmp_enotify_ctx_t *ctx;
|
||||||
int pid;
|
int pid;
|
||||||
ngx_str_t *arg;
|
ngx_str_t a, *arg;
|
||||||
char **args;
|
char **args;
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
|
||||||
|
@ -194,7 +199,8 @@ ngx_rtmp_enotify_exec(ngx_rtmp_session_t *s, ngx_rtmp_enotify_conf_t *ec)
|
||||||
arg = ec->args.elts;
|
arg = ec->args.elts;
|
||||||
args[0] = (char *)ec->cmd.data;
|
args[0] = (char *)ec->cmd.data;
|
||||||
for (n = 0; n < ec->args.nelts; ++n, ++arg) {
|
for (n = 0; n < ec->args.nelts; ++n, ++arg) {
|
||||||
args[n + 1] = ngx_rtmp_exec_prepare_arg(s, arg);
|
ngx_rtmp_eval(s, arg, ngx_rtmp_eval_session, &a);
|
||||||
|
args[n + 1] = (char *) a.data;
|
||||||
}
|
}
|
||||||
args[n + 1] = NULL;
|
args[n + 1] = NULL;
|
||||||
if (execvp((char *)ec->cmd.data, args) == -1) {
|
if (execvp((char *)ec->cmd.data, args) == -1) {
|
||||||
|
@ -265,7 +271,7 @@ ngx_rtmp_enotify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||||
|
|
||||||
ngx_rtmp_enotify_init(s, v->name, v->args, NGX_RTMP_ENOTIFY_PUBLISHING);
|
ngx_rtmp_enotify_init(s, v->name, v->args, NGX_RTMP_ENOTIFY_PUBLISHING);
|
||||||
|
|
||||||
ec = enacf->events[NGX_RTMP_ENOTIFY_PUBLISH];
|
ec = enacf->event[NGX_RTMP_ENOTIFY_PUBLISH];
|
||||||
|
|
||||||
if (ec == NULL) {
|
if (ec == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -299,7 +305,7 @@ ngx_rtmp_enotify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
|
||||||
|
|
||||||
ngx_rtmp_enotify_init(s, v->name, v->args, NGX_RTMP_ENOTIFY_PLAYING);
|
ngx_rtmp_enotify_init(s, v->name, v->args, NGX_RTMP_ENOTIFY_PLAYING);
|
||||||
|
|
||||||
ec = enacf->events[NGX_RTMP_ENOTIFY_PLAY];
|
ec = enacf->event[NGX_RTMP_ENOTIFY_PLAY];
|
||||||
|
|
||||||
if (ec == NULL) {
|
if (ec == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -342,10 +348,10 @@ ngx_rtmp_enotify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
||||||
"enotify: delete_stream %ui",
|
"enotify: delete_stream %ui",
|
||||||
ctx->flags);
|
ctx->flags);
|
||||||
|
|
||||||
if (enacf->events[NGX_RTMP_ENOTIFY_PUBLISH_DONE] &&
|
if (enacf->event[NGX_RTMP_ENOTIFY_PUBLISH_DONE] &&
|
||||||
(ctx->flags & NGX_RTMP_ENOTIFY_PUBLISHING))
|
(ctx->flags & NGX_RTMP_ENOTIFY_PUBLISHING))
|
||||||
{
|
{
|
||||||
ec = enacf->events[NGX_RTMP_ENOTIFY_PUBLISH_DONE];
|
ec = enacf->event[NGX_RTMP_ENOTIFY_PUBLISH_DONE];
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"enotify: publish_done '%V'", &ec->cmd);
|
"enotify: publish_done '%V'", &ec->cmd);
|
||||||
|
@ -353,10 +359,10 @@ ngx_rtmp_enotify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
||||||
ngx_rtmp_enotify_exec(s, ec);
|
ngx_rtmp_enotify_exec(s, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enacf->events[NGX_RTMP_ENOTIFY_PLAY_DONE] &&
|
if (enacf->event[NGX_RTMP_ENOTIFY_PLAY_DONE] &&
|
||||||
(ctx->flags & NGX_RTMP_ENOTIFY_PLAYING))
|
(ctx->flags & NGX_RTMP_ENOTIFY_PLAYING))
|
||||||
{
|
{
|
||||||
ec = enacf->events[NGX_RTMP_ENOTIFY_PLAY_DONE];
|
ec = enacf->event[NGX_RTMP_ENOTIFY_PLAY_DONE];
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"enotify: play_done '%V'", &ec->cmd);
|
"enotify: play_done '%V'", &ec->cmd);
|
||||||
|
@ -371,13 +377,41 @@ next:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_rtmp_enotify_record_done(ngx_rtmp_session_t *s, ngx_rtmp_record_done_t *v)
|
||||||
|
{
|
||||||
|
ngx_rtmp_enotify_app_conf_t *enacf;
|
||||||
|
ngx_rtmp_enotify_conf_t *ec;
|
||||||
|
|
||||||
|
if (s->auto_pushed) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
enacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_enotify_module);
|
||||||
|
if (enacf == NULL || enacf->event[NGX_RTMP_ENOTIFY_RECORD_DONE] == NULL) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ec = enacf->event[NGX_RTMP_ENOTIFY_RECORD_DONE];
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
|
"enotify: record_done %V recorder=%V path='%V'",
|
||||||
|
&ec->cmd, &v->recorder, &v->path);
|
||||||
|
|
||||||
|
ngx_rtmp_enotify_exec(s, ec);
|
||||||
|
|
||||||
|
next:
|
||||||
|
return next_record_done(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ngx_rtmp_enotify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_rtmp_enotify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
ngx_rtmp_enotify_app_conf_t *enacf;
|
ngx_rtmp_enotify_app_conf_t *enacf;
|
||||||
ngx_rtmp_enotify_conf_t *ec;
|
ngx_rtmp_enotify_conf_t *ec;
|
||||||
ngx_str_t *name, *value, *s;
|
ngx_str_t *name, *value, *s;
|
||||||
size_t len, nargs;
|
size_t nargs;
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
@ -408,29 +442,31 @@ ngx_rtmp_enotify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
|
||||||
enacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_enotify_module);
|
enacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_enotify_module);
|
||||||
|
|
||||||
len = name->len;
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
switch (name->data[6]) {
|
switch (name->len) {
|
||||||
|
case sizeof("exec_play") - 1:
|
||||||
case 'l': /* exec_pLay... */
|
|
||||||
if (len == sizeof("exec_play") - 1) {
|
|
||||||
n = NGX_RTMP_ENOTIFY_PLAY;
|
n = NGX_RTMP_ENOTIFY_PLAY;
|
||||||
} else {
|
|
||||||
n = NGX_RTMP_ENOTIFY_PLAY_DONE;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u': /* exec_pUblish... */
|
case sizeof("exec_publish") - 1:
|
||||||
if (len == sizeof("exec_publish") - 1) {
|
|
||||||
n = NGX_RTMP_ENOTIFY_PUBLISH;
|
n = NGX_RTMP_ENOTIFY_PUBLISH;
|
||||||
} else {
|
break;
|
||||||
|
|
||||||
|
case sizeof("exec_play_done") - 1:
|
||||||
|
n = NGX_RTMP_ENOTIFY_PLAY_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sizeof("exec_record_done") - 1:
|
||||||
|
n = NGX_RTMP_ENOTIFY_RECORD_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sizeof("exec_publish_done") - 1:
|
||||||
n = NGX_RTMP_ENOTIFY_PUBLISH_DONE;
|
n = NGX_RTMP_ENOTIFY_PUBLISH_DONE;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
enacf->events[n] = ec;
|
enacf->event[n] = ec;
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
@ -448,5 +484,8 @@ ngx_rtmp_enotify_postconfiguration(ngx_conf_t *cf)
|
||||||
next_delete_stream = ngx_rtmp_delete_stream;
|
next_delete_stream = ngx_rtmp_delete_stream;
|
||||||
ngx_rtmp_delete_stream = ngx_rtmp_enotify_delete_stream;
|
ngx_rtmp_delete_stream = ngx_rtmp_enotify_delete_stream;
|
||||||
|
|
||||||
|
next_record_done = ngx_rtmp_record_done;
|
||||||
|
ngx_rtmp_record_done = ngx_rtmp_enotify_record_done;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
|
|
||||||
#include "ngx_rtmp_cmd_module.h"
|
#include "ngx_rtmp_cmd_module.h"
|
||||||
#include "ngx_rtmp_netcall_module.h"
|
#include "ngx_rtmp_netcall_module.h"
|
||||||
|
#include "ngx_rtmp_record_module.h"
|
||||||
|
|
||||||
|
|
||||||
static ngx_rtmp_publish_pt next_publish;
|
static ngx_rtmp_publish_pt next_publish;
|
||||||
static ngx_rtmp_play_pt next_play;
|
static ngx_rtmp_play_pt next_play;
|
||||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
||||||
|
static ngx_rtmp_record_done_pt next_record_done;
|
||||||
|
|
||||||
|
|
||||||
static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
@ -29,12 +31,21 @@ static ngx_int_t ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname,
|
||||||
#define NGX_RTMP_NOTIFY_PUBLISHING 0x01
|
#define NGX_RTMP_NOTIFY_PUBLISHING 0x01
|
||||||
#define NGX_RTMP_NOTIFY_PLAYING 0x02
|
#define NGX_RTMP_NOTIFY_PLAYING 0x02
|
||||||
|
|
||||||
|
|
||||||
|
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_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_url_t *publish_url;
|
ngx_url_t *url[NGX_RTMP_NOTIFY_MAX];
|
||||||
ngx_url_t *play_url;
|
ngx_flag_t active;
|
||||||
ngx_url_t *publish_done_url;
|
|
||||||
ngx_url_t *play_done_url;
|
|
||||||
ngx_url_t *done_url;
|
|
||||||
} ngx_rtmp_notify_app_conf_t;
|
} ngx_rtmp_notify_app_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +99,14 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
|
||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("on_record_done"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_RTMP_REC_CONF|
|
||||||
|
NGX_CONF_TAKE1,
|
||||||
|
ngx_rtmp_notify_on_event,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,9 +158,14 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
{
|
{
|
||||||
ngx_rtmp_notify_app_conf_t *prev = parent;
|
ngx_rtmp_notify_app_conf_t *prev = parent;
|
||||||
ngx_rtmp_notify_app_conf_t *conf = child;
|
ngx_rtmp_notify_app_conf_t *conf = child;
|
||||||
|
ngx_uint_t n;
|
||||||
|
|
||||||
ngx_conf_merge_ptr_value(conf->publish_url, prev->publish_url, 0);
|
for (n = 0; n < NGX_RTMP_NOTIFY_MAX; ++n) {
|
||||||
ngx_conf_merge_ptr_value(conf->play_url, prev->play_url, 0);
|
ngx_conf_merge_ptr_value(conf->url[n], prev->url[n], 0);
|
||||||
|
if (conf->url[n]) {
|
||||||
|
conf->active = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
@ -211,8 +235,8 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP header */
|
/* HTTP header */
|
||||||
hl = ngx_rtmp_netcall_http_format_header(nacf->publish_url, pool,
|
hl = ngx_rtmp_netcall_http_format_header(nacf->url[NGX_RTMP_NOTIFY_PUBLISH],
|
||||||
cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
||||||
&ngx_rtmp_netcall_content_type_urlencoded);
|
&ngx_rtmp_netcall_content_type_urlencoded);
|
||||||
|
|
||||||
if (hl == NULL) {
|
if (hl == NULL) {
|
||||||
|
@ -291,8 +315,8 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP header */
|
/* HTTP header */
|
||||||
hl = ngx_rtmp_netcall_http_format_header(nacf->play_url, pool,
|
hl = ngx_rtmp_netcall_http_format_header(nacf->url[NGX_RTMP_NOTIFY_PLAY],
|
||||||
cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
||||||
&ngx_rtmp_netcall_content_type_urlencoded);
|
&ngx_rtmp_netcall_content_type_urlencoded);
|
||||||
|
|
||||||
if (hl == NULL) {
|
if (hl == NULL) {
|
||||||
|
@ -386,6 +410,94 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_chain_t *
|
||||||
|
ngx_rtmp_notify_record_done_create(ngx_rtmp_session_t *s, void *arg,
|
||||||
|
ngx_pool_t *pool)
|
||||||
|
{
|
||||||
|
ngx_rtmp_record_done_t *v = arg;
|
||||||
|
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
|
ngx_chain_t *hl, *cl, *pl;
|
||||||
|
ngx_buf_t *b;
|
||||||
|
ngx_str_t *addr_text;
|
||||||
|
size_t name_len, args_len;
|
||||||
|
|
||||||
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
/* common variables */
|
||||||
|
cl = ngx_rtmp_netcall_http_format_session(s, pool);
|
||||||
|
|
||||||
|
if (cl == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* publish variables */
|
||||||
|
pl = ngx_alloc_chain_link(pool);
|
||||||
|
|
||||||
|
if (pl == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_len = ngx_strlen(ctx->name);
|
||||||
|
args_len = ngx_strlen(ctx->args);
|
||||||
|
addr_text = &s->connection->addr_text;
|
||||||
|
|
||||||
|
b = ngx_create_temp_buf(pool,
|
||||||
|
sizeof("&call=record_done") +
|
||||||
|
sizeof("&recorder=") + v->recorder.len +
|
||||||
|
sizeof("&addr=") + addr_text->len +
|
||||||
|
sizeof("&name=") + name_len * 3 +
|
||||||
|
sizeof("&path=") + v->path.len * 3 +
|
||||||
|
+ 1 + args_len);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl->buf = b;
|
||||||
|
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char*)"&call=record_done",
|
||||||
|
sizeof("&call=record_done") - 1);
|
||||||
|
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char *)"&recorder=",
|
||||||
|
sizeof("&recorder=") - 1);
|
||||||
|
b->last = (u_char*)ngx_escape_uri(b->last, v->recorder.data,
|
||||||
|
v->recorder.len, 0);
|
||||||
|
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
|
||||||
|
b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
|
||||||
|
addr_text->len, 0);
|
||||||
|
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
|
||||||
|
b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0);
|
||||||
|
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char*)"&path=", sizeof("&path=") - 1);
|
||||||
|
b->last = (u_char*)ngx_escape_uri(b->last, v->path.data, v->path.len, 0);
|
||||||
|
|
||||||
|
if (args_len) {
|
||||||
|
*b->last++ = '&';
|
||||||
|
b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTTP header */
|
||||||
|
hl = ngx_rtmp_netcall_http_format_header(nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE],
|
||||||
|
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
||||||
|
&ngx_rtmp_netcall_content_type_urlencoded);
|
||||||
|
|
||||||
|
if (hl == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hl->next = cl;
|
||||||
|
cl->next = pl;
|
||||||
|
pl->next = NULL;
|
||||||
|
|
||||||
|
return hl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
|
ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
|
||||||
ngx_chain_t *in)
|
ngx_chain_t *in)
|
||||||
|
@ -457,10 +569,7 @@ ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
if (nacf->done_url == NULL &&
|
if (!nacf->active) {
|
||||||
nacf->play_done_url == NULL &&
|
|
||||||
nacf->publish_done_url == NULL)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,16 +609,17 @@ ngx_rtmp_notify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||||
|
|
||||||
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PUBLISHING);
|
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PUBLISHING);
|
||||||
|
|
||||||
if (nacf->publish_url == NULL) {
|
if (nacf->url[NGX_RTMP_NOTIFY_PUBLISH] == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"notify: publish '%V'", &nacf->publish_url->url);
|
"notify: publish '%V'",
|
||||||
|
&nacf->url[NGX_RTMP_NOTIFY_PUBLISH]);
|
||||||
|
|
||||||
ngx_memzero(&ci, sizeof(ci));
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
ci.url = nacf->publish_url;
|
ci.url = nacf->url[NGX_RTMP_NOTIFY_PUBLISH];
|
||||||
ci.create = ngx_rtmp_notify_publish_create;
|
ci.create = ngx_rtmp_notify_publish_create;
|
||||||
ci.handle = ngx_rtmp_notify_publish_handle;
|
ci.handle = ngx_rtmp_notify_publish_handle;
|
||||||
ci.arg = v;
|
ci.arg = v;
|
||||||
|
@ -540,16 +650,17 @@ ngx_rtmp_notify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
|
||||||
|
|
||||||
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PLAYING);
|
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PLAYING);
|
||||||
|
|
||||||
if (nacf->play_url == NULL) {
|
if (nacf->url[NGX_RTMP_NOTIFY_PLAY] == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"notify: play '%V'", &nacf->play_url->url);
|
"notify: play '%V'",
|
||||||
|
&nacf->url[NGX_RTMP_NOTIFY_PLAY]);
|
||||||
|
|
||||||
ngx_memzero(&ci, sizeof(ci));
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
ci.url = nacf->play_url;
|
ci.url = nacf->url[NGX_RTMP_NOTIFY_PLAY];
|
||||||
ci.create = ngx_rtmp_notify_play_create;
|
ci.create = ngx_rtmp_notify_play_create;
|
||||||
ci.handle = ngx_rtmp_notify_play_handle;
|
ci.handle = ngx_rtmp_notify_play_handle;
|
||||||
ci.arg = v;
|
ci.arg = v;
|
||||||
|
@ -563,8 +674,8 @@ next:
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_notify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
ngx_rtmp_notify_delete_stream(ngx_rtmp_session_t *s,
|
||||||
*v)
|
ngx_rtmp_delete_stream_t *v)
|
||||||
{
|
{
|
||||||
ngx_rtmp_notify_ctx_t *ctx;
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
@ -585,16 +696,22 @@ ngx_rtmp_notify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nacf->publish_done_url && (ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING)) {
|
if (nacf->url[NGX_RTMP_NOTIFY_PUBLISH_DONE] &&
|
||||||
ngx_rtmp_notify_done(s, "publish_done", nacf->publish_done_url);
|
(ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING))
|
||||||
|
{
|
||||||
|
ngx_rtmp_notify_done(s, "publish_done",
|
||||||
|
nacf->url[NGX_RTMP_NOTIFY_PUBLISH_DONE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nacf->play_done_url && (ctx->flags & NGX_RTMP_NOTIFY_PLAYING)) {
|
if (nacf->url[NGX_RTMP_NOTIFY_PLAY_DONE] &&
|
||||||
ngx_rtmp_notify_done(s, "play_done", nacf->play_done_url);
|
(ctx->flags & NGX_RTMP_NOTIFY_PLAYING))
|
||||||
|
{
|
||||||
|
ngx_rtmp_notify_done(s, "play_done",
|
||||||
|
nacf->url[NGX_RTMP_NOTIFY_PLAY_DONE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nacf->done_url && ctx->flags) {
|
if (nacf->url[NGX_RTMP_NOTIFY_DONE] && ctx->flags) {
|
||||||
ngx_rtmp_notify_done(s, "done", nacf->done_url);
|
ngx_rtmp_notify_done(s, "done", nacf->url[NGX_RTMP_NOTIFY_DONE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->flags = 0;
|
ctx->flags = 0;
|
||||||
|
@ -604,6 +721,39 @@ next:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_rtmp_notify_record_done(ngx_rtmp_session_t *s, ngx_rtmp_record_done_t *v)
|
||||||
|
{
|
||||||
|
ngx_rtmp_netcall_init_t ci;
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
|
||||||
|
if (s->auto_pushed) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
if (nacf == NULL || nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE] == NULL) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
|
"notify: record_done recorder=%V path='%V' url='%V'",
|
||||||
|
&v->recorder, &v->path,
|
||||||
|
&nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE]);
|
||||||
|
|
||||||
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
|
ci.url = nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE];
|
||||||
|
ci.create = ngx_rtmp_notify_record_done_create;
|
||||||
|
ci.arg = v;
|
||||||
|
|
||||||
|
ngx_rtmp_netcall_create(s, &ci);
|
||||||
|
|
||||||
|
next:
|
||||||
|
return next_record_done(s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_url_t *url)
|
ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_url_t *url)
|
||||||
{
|
{
|
||||||
|
@ -632,8 +782,9 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
ngx_str_t *url, *name;
|
ngx_str_t *url, *name;
|
||||||
ngx_url_t *u;
|
ngx_url_t *u;
|
||||||
size_t add, len;
|
size_t add;
|
||||||
ngx_str_t *value;
|
ngx_str_t *value;
|
||||||
|
ngx_uint_t n;
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
name = &value[0];
|
name = &value[0];
|
||||||
|
@ -665,30 +816,36 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
|
||||||
nacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_notify_module);
|
nacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
len = name->len;
|
n = 0;
|
||||||
|
|
||||||
switch (name->data[4]) {
|
switch (name->len) {
|
||||||
|
case sizeof("on_done") - 1: /* and on_play */
|
||||||
case 'l': /* on_pLay... */
|
if (name->data[3] == 'd') {
|
||||||
if (len == sizeof("on_play") - 1) {
|
n = NGX_RTMP_NOTIFY_DONE;
|
||||||
nacf->play_url = u;
|
|
||||||
} else {
|
} else {
|
||||||
nacf->play_done_url = u;
|
n = NGX_RTMP_NOTIFY_PLAY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u': /* on_pUblish... */
|
case sizeof("on_publish") - 1:
|
||||||
if (len == sizeof("on_publish") - 1) {
|
n = NGX_RTMP_NOTIFY_PUBLISH;
|
||||||
nacf->publish_url = u;
|
|
||||||
} else {
|
|
||||||
nacf->publish_done_url = u;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o': /* on_dOne */
|
case sizeof("on_play_done") - 1:
|
||||||
nacf->done_url = u;
|
n = NGX_RTMP_NOTIFY_PLAY_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sizeof("on_record_done") - 1:
|
||||||
|
n = NGX_RTMP_NOTIFY_RECORD_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sizeof("on_publish_done") - 1:
|
||||||
|
n = NGX_RTMP_NOTIFY_PUBLISH_DONE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nacf->url[n] = u;
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,6 +862,8 @@ ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
|
||||||
next_delete_stream = ngx_rtmp_delete_stream;
|
next_delete_stream = ngx_rtmp_delete_stream;
|
||||||
ngx_rtmp_delete_stream = ngx_rtmp_notify_delete_stream;
|
ngx_rtmp_delete_stream = ngx_rtmp_notify_delete_stream;
|
||||||
|
|
||||||
|
next_record_done = ngx_rtmp_record_done;
|
||||||
|
ngx_rtmp_record_done = ngx_rtmp_notify_record_done;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include "ngx_rtmp_record_module.h"
|
#include "ngx_rtmp_record_module.h"
|
||||||
|
|
||||||
|
|
||||||
|
ngx_rtmp_record_done_pt ngx_rtmp_record_done;
|
||||||
|
|
||||||
|
|
||||||
static ngx_rtmp_publish_pt next_publish;
|
static ngx_rtmp_publish_pt next_publish;
|
||||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
||||||
|
|
||||||
|
@ -25,18 +28,18 @@ static void * ngx_rtmp_record_create_app_conf(ngx_conf_t *cf);
|
||||||
static char * ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf,
|
static char * ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf,
|
||||||
void *parent, void *child);
|
void *parent, void *child);
|
||||||
static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
|
static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx,
|
ngx_rtmp_record_rec_ctx_t *rctx,
|
||||||
ngx_rtmp_header_t *h, ngx_chain_t *in);
|
ngx_rtmp_header_t *h, ngx_chain_t *in);
|
||||||
static ngx_int_t ngx_rtmp_record_av(ngx_rtmp_session_t *s,
|
static ngx_int_t ngx_rtmp_record_av(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_rtmp_record_node_av(ngx_rtmp_session_t *s,
|
static ngx_int_t ngx_rtmp_record_node_av(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in);
|
ngx_rtmp_record_rec_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in);
|
||||||
static ngx_int_t ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
static ngx_int_t ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx);
|
ngx_rtmp_record_rec_ctx_t *rctx);
|
||||||
static ngx_int_t ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
|
static ngx_int_t ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx);
|
ngx_rtmp_record_rec_ctx_t *rctx);
|
||||||
static u_char * ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
|
static void ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx);
|
ngx_rtmp_record_rec_ctx_t *rctx, ngx_str_t *path);
|
||||||
static ngx_int_t ngx_rtmp_record_init(ngx_rtmp_session_t *s);
|
static ngx_int_t ngx_rtmp_record_init(ngx_rtmp_session_t *s);
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_1MORE,
|
NGX_RTMP_REC_CONF|NGX_CONF_1MORE,
|
||||||
ngx_conf_set_bitmask_slot,
|
ngx_conf_set_bitmask_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.flags),
|
offsetof(ngx_rtmp_record_app_conf_t, flags),
|
||||||
ngx_rtmp_record_mask },
|
ngx_rtmp_record_mask },
|
||||||
|
|
||||||
{ ngx_string("record_path"),
|
{ ngx_string("record_path"),
|
||||||
|
@ -67,7 +70,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.path),
|
offsetof(ngx_rtmp_record_app_conf_t, path),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("record_suffix"),
|
{ ngx_string("record_suffix"),
|
||||||
|
@ -75,7 +78,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.suffix),
|
offsetof(ngx_rtmp_record_app_conf_t, suffix),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("record_unique"),
|
{ ngx_string("record_unique"),
|
||||||
|
@ -83,7 +86,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_flag_slot,
|
ngx_conf_set_flag_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.unique),
|
offsetof(ngx_rtmp_record_app_conf_t, unique),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("record_max_size"),
|
{ ngx_string("record_max_size"),
|
||||||
|
@ -91,7 +94,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_size_slot,
|
ngx_conf_set_size_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.max_size),
|
offsetof(ngx_rtmp_record_app_conf_t, max_size),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("record_max_frames"),
|
{ ngx_string("record_max_frames"),
|
||||||
|
@ -99,7 +102,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_size_slot,
|
ngx_conf_set_size_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.max_frames),
|
offsetof(ngx_rtmp_record_app_conf_t, max_frames),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("record_interval"),
|
{ ngx_string("record_interval"),
|
||||||
|
@ -107,7 +110,7 @@ static ngx_command_t ngx_rtmp_record_commands[] = {
|
||||||
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_msec_slot,
|
ngx_conf_set_msec_slot,
|
||||||
NGX_RTMP_APP_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_record_app_conf_t, def.interval),
|
offsetof(ngx_rtmp_record_app_conf_t, interval),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("on_record_done"),
|
{ ngx_string("on_record_done"),
|
||||||
|
@ -169,18 +172,15 @@ ngx_rtmp_record_create_app_conf(ngx_conf_t *cf)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
racf->def.max_size = NGX_CONF_UNSET;
|
racf->max_size = NGX_CONF_UNSET;
|
||||||
racf->def.max_frames = NGX_CONF_UNSET;
|
racf->max_frames = NGX_CONF_UNSET;
|
||||||
racf->def.interval = NGX_CONF_UNSET;
|
racf->interval = NGX_CONF_UNSET;
|
||||||
racf->def.unique = NGX_CONF_UNSET;
|
racf->unique = NGX_CONF_UNSET;
|
||||||
racf->def.url = NGX_CONF_UNSET_PTR;
|
racf->url = NGX_CONF_UNSET_PTR;
|
||||||
|
|
||||||
ngx_str_set(&racf->def.id, "default");
|
ngx_str_set(&racf->id, "default");
|
||||||
|
|
||||||
if (ngx_array_init(&racf->nodes, cf->pool, 1,
|
if (ngx_array_init(&racf->rec, cf->pool, 1, sizeof(void *)) != NGX_OK) {
|
||||||
sizeof(ngx_rtmp_record_node_t *))
|
|
||||||
!= NGX_OK)
|
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,25 +193,25 @@ ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_app_conf_t *prev = parent;
|
ngx_rtmp_record_app_conf_t *prev = parent;
|
||||||
ngx_rtmp_record_app_conf_t *conf = child;
|
ngx_rtmp_record_app_conf_t *conf = child;
|
||||||
ngx_rtmp_record_node_t **node;
|
ngx_rtmp_record_app_conf_t **rracf;
|
||||||
|
|
||||||
ngx_conf_merge_str_value(conf->def.path, prev->def.path, "");
|
ngx_conf_merge_str_value(conf->path, prev->path, "");
|
||||||
ngx_conf_merge_str_value(conf->def.suffix, prev->def.suffix, ".flv");
|
ngx_conf_merge_str_value(conf->suffix, prev->suffix, ".flv");
|
||||||
ngx_conf_merge_size_value(conf->def.max_size, prev->def.max_size, 0);
|
ngx_conf_merge_size_value(conf->max_size, prev->max_size, 0);
|
||||||
ngx_conf_merge_size_value(conf->def.max_frames, prev->def.max_frames, 0);
|
ngx_conf_merge_size_value(conf->max_frames, prev->max_frames, 0);
|
||||||
ngx_conf_merge_value(conf->def.unique, prev->def.unique, 0);
|
ngx_conf_merge_value(conf->unique, prev->unique, 0);
|
||||||
ngx_conf_merge_msec_value(conf->def.interval, prev->def.interval,
|
ngx_conf_merge_msec_value(conf->interval, prev->interval,
|
||||||
(ngx_msec_t) NGX_CONF_UNSET);
|
(ngx_msec_t) NGX_CONF_UNSET);
|
||||||
ngx_conf_merge_bitmask_value(conf->def.flags, prev->def.flags, 0);
|
ngx_conf_merge_bitmask_value(conf->flags, prev->flags, 0);
|
||||||
ngx_conf_merge_ptr_value(conf->def.url, prev->def.url, NULL);
|
ngx_conf_merge_ptr_value(conf->url, prev->url, NULL);
|
||||||
|
|
||||||
if (conf->def.flags) {
|
if (conf->flags) {
|
||||||
node = ngx_array_push(&conf->nodes);
|
rracf = ngx_array_push(&conf->rec);
|
||||||
if (node == NULL) {
|
if (rracf == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
*node = &conf->def;
|
*rracf = conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
|
@ -243,11 +243,11 @@ ngx_rtmp_record_write_header(ngx_file_t *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_rtmp_record_node_ctx_t *
|
static ngx_rtmp_record_rec_ctx_t *
|
||||||
ngx_rtmp_record_get_node_ctx(ngx_rtmp_session_t *s, ngx_uint_t n)
|
ngx_rtmp_record_get_node_ctx(ngx_rtmp_session_t *s, ngx_uint_t n)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
ngx_rtmp_record_ctx_t *ctx;
|
||||||
ngx_rtmp_record_node_ctx_t *nodes;
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
|
|
||||||
if (ngx_rtmp_record_init(s) != NGX_OK) {
|
if (ngx_rtmp_record_init(s) != NGX_OK) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -255,20 +255,20 @@ ngx_rtmp_record_get_node_ctx(ngx_rtmp_session_t *s, ngx_uint_t n)
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
||||||
|
|
||||||
if (n >= ctx->nodes.nelts) {
|
if (n >= ctx->rec.nelts) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes = ctx->nodes.elts;
|
rctx = ctx->rec.elts;
|
||||||
|
|
||||||
return &nodes[n];
|
return &rctx[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, u_char **path)
|
ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, ngx_str_t *path)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_node_ctx_t *rctx;
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: #%ui manual open", n);
|
"record: #%ui manual open", n);
|
||||||
|
@ -284,7 +284,7 @@ ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, u_char **path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
*path = ngx_rtmp_record_make_path(s, rctx);
|
ngx_rtmp_record_make_path(s, rctx, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
@ -292,9 +292,9 @@ ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, u_char **path)
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, u_char **path)
|
ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, ngx_str_t *path)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_node_ctx_t *rctx;
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: #%ui manual close", n);
|
"record: #%ui manual close", n);
|
||||||
|
@ -310,7 +310,7 @@ ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, u_char **path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
*path = ngx_rtmp_record_make_path(s, rctx);
|
ngx_rtmp_record_make_path(s, rctx, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
@ -318,68 +318,69 @@ ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, u_char **path)
|
||||||
|
|
||||||
|
|
||||||
/* This funcion returns pointer to a static buffer */
|
/* This funcion returns pointer to a static buffer */
|
||||||
static u_char *
|
static void
|
||||||
ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
|
ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx)
|
ngx_rtmp_record_rec_ctx_t *rctx, ngx_str_t *path)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
ngx_rtmp_record_ctx_t *ctx;
|
||||||
|
ngx_rtmp_record_app_conf_t *rracf;
|
||||||
u_char *p, *l;
|
u_char *p, *l;
|
||||||
ngx_rtmp_record_node_t *rc;
|
|
||||||
|
|
||||||
static u_char buf[NGX_TIME_T_LEN + 1];
|
static u_char buf[NGX_TIME_T_LEN + 1];
|
||||||
static u_char path[NGX_MAX_PATH + 1];
|
static u_char pbuf[NGX_MAX_PATH + 1];
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
||||||
|
|
||||||
rc = rctx->conf;
|
rracf = rctx->conf;
|
||||||
|
|
||||||
/* create file path */
|
/* create file path */
|
||||||
p = path;
|
p = pbuf;
|
||||||
l = path + sizeof(path) - 1;
|
l = pbuf + sizeof(pbuf) - 1;
|
||||||
|
|
||||||
p = ngx_cpymem(p, rc->path.data,
|
p = ngx_cpymem(p, rracf->path.data,
|
||||||
ngx_min(rc->path.len, (size_t)(l - p - 1)));
|
ngx_min(rracf->path.len, (size_t)(l - p - 1)));
|
||||||
*p++ = '/';
|
*p++ = '/';
|
||||||
p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name),
|
p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name),
|
||||||
(size_t)(l - p)), NGX_ESCAPE_URI_COMPONENT);
|
(size_t)(l - p)), NGX_ESCAPE_URI_COMPONENT);
|
||||||
|
|
||||||
/* append timestamp */
|
/* append timestamp */
|
||||||
if (rc->unique) {
|
if (rracf->unique) {
|
||||||
p = ngx_cpymem(p, buf, ngx_min(ngx_sprintf(buf, "-%T",
|
p = ngx_cpymem(p, buf, ngx_min(ngx_sprintf(buf, "-%T",
|
||||||
rctx->timestamp) - buf, l - p));
|
rctx->timestamp) - buf, l - p));
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ngx_cpymem(p, rc->suffix.data,
|
p = ngx_cpymem(p, rracf->suffix.data,
|
||||||
ngx_min(rc->suffix.len, (size_t)(l - p)));
|
ngx_min(rracf->suffix.len, (size_t)(l - p)));
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
path->data = pbuf;
|
||||||
"record: %V path: '%s'", &rc->id, path);
|
path->len = p - pbuf;
|
||||||
|
|
||||||
return path;
|
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
|
"record: %V path: '%V'", &rracf->id, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx)
|
ngx_rtmp_record_rec_ctx_t *rctx)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_node_t *rc;
|
ngx_rtmp_record_app_conf_t *rracf;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
u_char *path;
|
ngx_str_t path;
|
||||||
|
|
||||||
rc = rctx->conf;
|
rracf = rctx->conf;
|
||||||
|
|
||||||
if (rctx->file.fd != NGX_INVALID_FILE) {
|
if (rctx->file.fd != NGX_INVALID_FILE) {
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: %V opening", &rc->id);
|
"record: %V opening", &rracf->id);
|
||||||
|
|
||||||
rctx->timestamp = ngx_cached_time->sec;
|
rctx->timestamp = ngx_cached_time->sec;
|
||||||
|
|
||||||
path = ngx_rtmp_record_make_path(s, rctx);
|
ngx_rtmp_record_make_path(s, rctx, &path);
|
||||||
|
|
||||||
rctx->nframes = 0;
|
rctx->nframes = 0;
|
||||||
|
|
||||||
|
@ -388,7 +389,7 @@ ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
||||||
rctx->last = *ngx_cached_time;
|
rctx->last = *ngx_cached_time;
|
||||||
rctx->file.offset = 0;
|
rctx->file.offset = 0;
|
||||||
rctx->file.log = s->connection->log;
|
rctx->file.log = s->connection->log;
|
||||||
rctx->file.fd = ngx_open_file(path, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE,
|
rctx->file.fd = ngx_open_file(path.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE,
|
||||||
NGX_FILE_DEFAULT_ACCESS);
|
NGX_FILE_DEFAULT_ACCESS);
|
||||||
|
|
||||||
if (rctx->file.fd == NGX_INVALID_FILE) {
|
if (rctx->file.fd == NGX_INVALID_FILE) {
|
||||||
|
@ -396,15 +397,15 @@ ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
||||||
|
|
||||||
if (err != NGX_ENOENT) {
|
if (err != NGX_ENOENT) {
|
||||||
ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
|
ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
|
||||||
"record: %V failed to open file '%s'",
|
"record: %V failed to open file '%V'",
|
||||||
&rc->id, path);
|
&rracf->id, &path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: %V opened '%s'", &rc->id, path);
|
"record: %V opened '%V'", &rracf->id, &path);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -413,10 +414,9 @@ ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_record_init(ngx_rtmp_session_t *s)
|
ngx_rtmp_record_init(ngx_rtmp_session_t *s)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_app_conf_t *racf;
|
ngx_rtmp_record_app_conf_t *racf, **rracf;
|
||||||
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
ngx_rtmp_record_ctx_t *ctx;
|
||||||
ngx_rtmp_record_node_ctx_t *rctx;
|
|
||||||
ngx_rtmp_record_node_t **node;
|
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
||||||
|
@ -427,7 +427,7 @@ ngx_rtmp_record_init(ngx_rtmp_session_t *s)
|
||||||
|
|
||||||
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
|
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
|
||||||
|
|
||||||
if (racf == NULL || racf->nodes.nelts == 0) {
|
if (racf == NULL || racf->rec.nelts == 0) {
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,25 +439,25 @@ ngx_rtmp_record_init(ngx_rtmp_session_t *s)
|
||||||
|
|
||||||
ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_record_module);
|
ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_record_module);
|
||||||
|
|
||||||
if (ngx_array_init(&ctx->nodes, s->connection->pool, racf->nodes.nelts,
|
if (ngx_array_init(&ctx->rec, s->connection->pool, racf->rec.nelts,
|
||||||
sizeof(ngx_rtmp_record_node_ctx_t))
|
sizeof(ngx_rtmp_record_rec_ctx_t))
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = racf->nodes.elts;
|
rracf = racf->rec.elts;
|
||||||
|
|
||||||
rctx = ngx_array_push_n(&ctx->nodes, racf->nodes.nelts);
|
rctx = ngx_array_push_n(&ctx->rec, racf->rec.nelts);
|
||||||
|
|
||||||
if (rctx == NULL) {
|
if (rctx == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < racf->nodes.nelts; ++n, ++node, ++rctx) {
|
for (n = 0; n < racf->rec.nelts; ++n, ++rracf, ++rctx) {
|
||||||
ngx_memzero(rctx, sizeof(*rctx));
|
ngx_memzero(rctx, sizeof(*rctx));
|
||||||
|
|
||||||
rctx->conf = *node;
|
rctx->conf = *rracf;
|
||||||
rctx->file.fd = NGX_INVALID_FILE;
|
rctx->file.fd = NGX_INVALID_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +472,7 @@ ngx_rtmp_record_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
ngx_rtmp_record_ctx_t *ctx;
|
||||||
u_char *p;
|
u_char *p;
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
ngx_rtmp_record_node_ctx_t *rctx;
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
|
|
||||||
if (s->auto_pushed) {
|
if (s->auto_pushed) {
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -480,7 +480,7 @@ ngx_rtmp_record_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||||
|
|
||||||
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
|
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
|
||||||
|
|
||||||
if (racf == NULL || racf->nodes.nelts == 0) {
|
if (racf == NULL || racf->rec.nelts == 0) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ ngx_rtmp_record_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: publish %ui nodes",
|
"record: publish %ui nodes",
|
||||||
racf->nodes.nelts);
|
racf->rec.nelts);
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
||||||
|
|
||||||
|
@ -508,9 +508,9 @@ ngx_rtmp_record_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rctx = ctx->nodes.elts;
|
rctx = ctx->rec.elts;
|
||||||
|
|
||||||
for (n = 0; n < ctx->nodes.nelts; ++n, ++rctx) {
|
for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) {
|
||||||
if (rctx->conf->flags & (NGX_RTMP_RECORD_OFF|NGX_RTMP_RECORD_MANUAL)) {
|
if (rctx->conf->flags & (NGX_RTMP_RECORD_OFF|NGX_RTMP_RECORD_MANUAL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -523,127 +523,17 @@ next:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_chain_t *
|
|
||||||
ngx_rtmp_record_notify_create(ngx_rtmp_session_t *s, void *arg,
|
|
||||||
ngx_pool_t *pool)
|
|
||||||
{
|
|
||||||
ngx_rtmp_record_node_ctx_t *rctx = arg;
|
|
||||||
ngx_rtmp_record_node_t *rc;
|
|
||||||
|
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
|
||||||
ngx_chain_t *hl, *cl, *pl;
|
|
||||||
ngx_buf_t *b;
|
|
||||||
ngx_str_t *addr_text;
|
|
||||||
size_t path_len, name_len, args_len;
|
|
||||||
u_char *path;
|
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
|
||||||
|
|
||||||
rc = rctx->conf;
|
|
||||||
|
|
||||||
/* common variables */
|
|
||||||
cl = ngx_rtmp_netcall_http_format_session(s, pool);
|
|
||||||
|
|
||||||
if (cl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* publish variables */
|
|
||||||
pl = ngx_alloc_chain_link(pool);
|
|
||||||
|
|
||||||
if (pl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = ngx_rtmp_record_make_path(s, rctx);
|
|
||||||
|
|
||||||
path_len = ngx_strlen(path);
|
|
||||||
name_len = ngx_strlen(ctx->name);
|
|
||||||
args_len = ngx_strlen(ctx->args);
|
|
||||||
addr_text = &s->connection->addr_text;
|
|
||||||
|
|
||||||
b = ngx_create_temp_buf(pool,
|
|
||||||
sizeof("&call=record_done") +
|
|
||||||
sizeof("&recorder=") + rc->id.len +
|
|
||||||
sizeof("&addr=") + addr_text->len +
|
|
||||||
sizeof("&name=") + name_len * 3 +
|
|
||||||
sizeof("&path=") + path_len * 3 +
|
|
||||||
+ 1 + args_len);
|
|
||||||
if (b == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl->buf = b;
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&call=record_done",
|
|
||||||
sizeof("&call=record_done") - 1);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char *)"&recorder=",
|
|
||||||
sizeof("&recorder=") - 1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, rc->id.data, rc->id.len, 0);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
|
|
||||||
addr_text->len, 0);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&path=", sizeof("&path=") - 1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, path, path_len, 0);
|
|
||||||
|
|
||||||
if (args_len) {
|
|
||||||
*b->last++ = '&';
|
|
||||||
b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HTTP header */
|
|
||||||
hl = ngx_rtmp_netcall_http_format_header(rctx->conf->url, pool,
|
|
||||||
cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
|
||||||
&ngx_rtmp_netcall_content_type_urlencoded);
|
|
||||||
|
|
||||||
if (hl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hl->next = cl;
|
|
||||||
cl->next = pl;
|
|
||||||
pl->next = NULL;
|
|
||||||
|
|
||||||
return hl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
|
||||||
ngx_rtmp_record_notify(ngx_rtmp_session_t *s, ngx_rtmp_record_node_ctx_t *rctx)
|
|
||||||
{
|
|
||||||
ngx_rtmp_netcall_init_t ci;
|
|
||||||
ngx_rtmp_record_node_t *rc;
|
|
||||||
|
|
||||||
rc = rctx->conf;
|
|
||||||
|
|
||||||
if (rc->url == NULL) {
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memzero(&ci, sizeof(ci));
|
|
||||||
|
|
||||||
ci.url = rc->url;
|
|
||||||
ci.create = ngx_rtmp_record_notify_create;
|
|
||||||
ci.arg = rctx;
|
|
||||||
|
|
||||||
return ngx_rtmp_netcall_create(s, &ci);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
|
ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx)
|
ngx_rtmp_record_rec_ctx_t *rctx)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_node_t *rc;
|
ngx_rtmp_record_app_conf_t *rracf;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
|
void **app_conf;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_rtmp_record_done_t v;
|
||||||
|
|
||||||
rc = rctx->conf;
|
rracf = rctx->conf;
|
||||||
|
|
||||||
if (rctx->file.fd == NGX_INVALID_FILE) {
|
if (rctx->file.fd == NGX_INVALID_FILE) {
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
@ -652,15 +542,28 @@ ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
|
||||||
if (ngx_close_file(rctx->file.fd) == NGX_FILE_ERROR) {
|
if (ngx_close_file(rctx->file.fd) == NGX_FILE_ERROR) {
|
||||||
err = ngx_errno;
|
err = ngx_errno;
|
||||||
ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
|
ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
|
||||||
"record: %V error closing file", &rc->id);
|
"record: %V error closing file", &rracf->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
rctx->file.fd = NGX_INVALID_FILE;
|
rctx->file.fd = NGX_INVALID_FILE;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: %V closed", &rc->id);
|
"record: %V closed", &rracf->id);
|
||||||
|
|
||||||
return ngx_rtmp_record_notify(s, rctx);
|
app_conf = s->app_conf;
|
||||||
|
|
||||||
|
if (rracf->rec_conf) {
|
||||||
|
s->app_conf = rracf->rec_conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.recorder = rracf->id;
|
||||||
|
ngx_rtmp_record_make_path(s, rctx, &v.path);
|
||||||
|
|
||||||
|
rc = ngx_rtmp_record_done(s, &v);
|
||||||
|
|
||||||
|
s->app_conf = app_conf;
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,7 +572,7 @@ ngx_rtmp_record_delete_stream(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_delete_stream_t *v)
|
ngx_rtmp_delete_stream_t *v)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
ngx_rtmp_record_ctx_t *ctx;
|
||||||
ngx_rtmp_record_node_ctx_t *rctx;
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
||||||
|
@ -680,11 +583,11 @@ ngx_rtmp_record_delete_stream(ngx_rtmp_session_t *s,
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: delete_stream %ui nodes",
|
"record: delete_stream %ui nodes",
|
||||||
ctx->nodes.nelts);
|
ctx->rec.nelts);
|
||||||
|
|
||||||
rctx = ctx->nodes.elts;
|
rctx = ctx->rec.elts;
|
||||||
|
|
||||||
for (n = 0; n < ctx->nodes.nelts; ++n, ++rctx) {
|
for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) {
|
||||||
ngx_rtmp_record_node_close(s, rctx);
|
ngx_rtmp_record_node_close(s, rctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,17 +598,18 @@ next:
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
|
ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_node_ctx_t *rctx,
|
ngx_rtmp_record_rec_ctx_t *rctx,
|
||||||
ngx_rtmp_header_t *h, ngx_chain_t *in)
|
ngx_rtmp_header_t *h, ngx_chain_t *in)
|
||||||
{
|
{
|
||||||
u_char hdr[11], *p, *ph;
|
u_char hdr[11], *p, *ph;
|
||||||
uint32_t timestamp, tag_size;
|
uint32_t timestamp, tag_size;
|
||||||
ngx_rtmp_record_node_t *rc;
|
ngx_rtmp_record_app_conf_t *rracf;
|
||||||
|
|
||||||
rc = rctx->conf;
|
rracf = rctx->conf;
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: %V frame: mlen=%uD", &rc->id, h->mlen);
|
"record: %V frame: mlen=%uD",
|
||||||
|
&rracf->id, h->mlen);
|
||||||
|
|
||||||
timestamp = h->timestamp - rctx->epoch;
|
timestamp = h->timestamp - rctx->epoch;
|
||||||
|
|
||||||
|
@ -775,8 +679,8 @@ ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
|
||||||
++rctx->nframes;
|
++rctx->nframes;
|
||||||
|
|
||||||
/* watch max size */
|
/* watch max size */
|
||||||
if ((rc->max_size && rctx->file.offset >= (ngx_int_t) rc->max_size) ||
|
if ((rracf->max_size && rctx->file.offset >= (ngx_int_t) rracf->max_size) ||
|
||||||
(rc->max_frames && rctx->nframes >= rc->max_frames))
|
(rracf->max_frames && rctx->nframes >= rracf->max_frames))
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_node_close(s, rctx);
|
ngx_rtmp_record_node_close(s, rctx);
|
||||||
}
|
}
|
||||||
|
@ -803,7 +707,7 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||||
ngx_chain_t *in)
|
ngx_chain_t *in)
|
||||||
{
|
{
|
||||||
ngx_rtmp_record_ctx_t *ctx;
|
ngx_rtmp_record_ctx_t *ctx;
|
||||||
ngx_rtmp_record_node_ctx_t *rctx;
|
ngx_rtmp_record_rec_ctx_t *rctx;
|
||||||
ngx_uint_t n;
|
ngx_uint_t n;
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
|
||||||
|
@ -812,9 +716,9 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
rctx = ctx->nodes.elts;
|
rctx = ctx->rec.elts;
|
||||||
|
|
||||||
for (n = 0; n < ctx->nodes.nelts; ++n, ++rctx) {
|
for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) {
|
||||||
ngx_rtmp_record_node_av(s, rctx, h, in);
|
ngx_rtmp_record_node_av(s, rctx, h, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,30 +727,30 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_node_ctx_t *rctx,
|
ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx,
|
||||||
ngx_rtmp_header_t *h, ngx_chain_t *in)
|
ngx_rtmp_header_t *h, ngx_chain_t *in)
|
||||||
{
|
{
|
||||||
ngx_time_t next;
|
ngx_time_t next;
|
||||||
ngx_rtmp_header_t ch;
|
ngx_rtmp_header_t ch;
|
||||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||||
ngx_int_t keyframe;
|
ngx_int_t keyframe;
|
||||||
ngx_rtmp_record_node_t *rc;
|
ngx_rtmp_record_app_conf_t *rracf;
|
||||||
|
|
||||||
rc = rctx->conf;
|
rracf = rctx->conf;
|
||||||
|
|
||||||
if (rc->flags & NGX_RTMP_RECORD_OFF) {
|
if (rracf->flags & NGX_RTMP_RECORD_OFF) {
|
||||||
ngx_rtmp_record_node_close(s, rctx);
|
ngx_rtmp_record_node_close(s, rctx);
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyframe = (ngx_rtmp_get_video_frame_type(in) == NGX_RTMP_VIDEO_KEY_FRAME);
|
keyframe = (ngx_rtmp_get_video_frame_type(in) == NGX_RTMP_VIDEO_KEY_FRAME);
|
||||||
|
|
||||||
if (keyframe && (rc->flags & NGX_RTMP_RECORD_MANUAL) == 0) {
|
if (keyframe && (rracf->flags & NGX_RTMP_RECORD_MANUAL) == 0) {
|
||||||
|
|
||||||
if (rc->interval != (ngx_msec_t) NGX_CONF_UNSET) {
|
if (rracf->interval != (ngx_msec_t) NGX_CONF_UNSET) {
|
||||||
|
|
||||||
next = rctx->last;
|
next = rctx->last;
|
||||||
next.msec += rc->interval;
|
next.msec += rracf->interval;
|
||||||
next.sec += (next.msec / 1000);
|
next.sec += (next.msec / 1000);
|
||||||
next.msec %= 1000;
|
next.msec %= 1000;
|
||||||
|
|
||||||
|
@ -868,14 +772,14 @@ ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_node_ctx_t *rctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->type == NGX_RTMP_MSG_AUDIO &&
|
if (h->type == NGX_RTMP_MSG_AUDIO &&
|
||||||
(rc->flags & NGX_RTMP_RECORD_AUDIO) == 0)
|
(rracf->flags & NGX_RTMP_RECORD_AUDIO) == 0)
|
||||||
{
|
{
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->type == NGX_RTMP_MSG_VIDEO &&
|
if (h->type == NGX_RTMP_MSG_VIDEO &&
|
||||||
(rc->flags & NGX_RTMP_RECORD_VIDEO) == 0 &&
|
(rracf->flags & NGX_RTMP_RECORD_VIDEO) == 0 &&
|
||||||
((rc->flags & NGX_RTMP_RECORD_KEYFRAMES) == 0 || !keyframe))
|
((rracf->flags & NGX_RTMP_RECORD_KEYFRAMES) == 0 || !keyframe))
|
||||||
{
|
{
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -907,10 +811,10 @@ ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_node_ctx_t *rctx,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* AAC header */
|
/* AAC header */
|
||||||
if (codec_ctx->aac_header && (rc->flags & NGX_RTMP_RECORD_AUDIO))
|
if (codec_ctx->aac_header && (rracf->flags & NGX_RTMP_RECORD_AUDIO))
|
||||||
{
|
{
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: %V writing AAC header", &rc->id);
|
"record: %V writing AAC header", &rracf->id);
|
||||||
|
|
||||||
ch.type = NGX_RTMP_MSG_AUDIO;
|
ch.type = NGX_RTMP_MSG_AUDIO;
|
||||||
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->aac_header);
|
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->aac_header);
|
||||||
|
@ -924,10 +828,11 @@ ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_node_ctx_t *rctx,
|
||||||
|
|
||||||
/* AVC header */
|
/* AVC header */
|
||||||
if (codec_ctx->avc_header &&
|
if (codec_ctx->avc_header &&
|
||||||
(rc->flags & (NGX_RTMP_RECORD_VIDEO|NGX_RTMP_RECORD_KEYFRAMES)))
|
(rracf->flags & (NGX_RTMP_RECORD_VIDEO|
|
||||||
|
NGX_RTMP_RECORD_KEYFRAMES)))
|
||||||
{
|
{
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"record: %V writing AVC header", &rc->id);
|
"record: %V writing AVC header", &rracf->id);
|
||||||
|
|
||||||
ch.type = NGX_RTMP_MSG_VIDEO;
|
ch.type = NGX_RTMP_MSG_VIDEO;
|
||||||
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->avc_header);
|
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->avc_header);
|
||||||
|
@ -945,6 +850,13 @@ ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_node_ctx_t *rctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_rtmp_record_done_init(ngx_rtmp_session_t *s, ngx_rtmp_record_done_t *v)
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ngx_rtmp_notify_on_record_done(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_rtmp_notify_on_record_done(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
|
@ -983,7 +895,7 @@ ngx_rtmp_notify_on_record_done(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
|
||||||
racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_record_module);
|
racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_record_module);
|
||||||
|
|
||||||
racf->def.url = u;
|
racf->url = u;
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
@ -997,10 +909,11 @@ ngx_rtmp_record_recorder(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
ngx_str_t *value;
|
ngx_str_t *value;
|
||||||
ngx_conf_t save;
|
ngx_conf_t save;
|
||||||
ngx_rtmp_module_t *module;
|
ngx_rtmp_module_t *module;
|
||||||
ngx_rtmp_record_app_conf_t *racf, *rracf;
|
ngx_rtmp_record_app_conf_t *racf, **pracf, *rracf;
|
||||||
ngx_rtmp_record_node_t **prc, *rc;
|
|
||||||
ngx_rtmp_conf_ctx_t *ctx, *pctx;
|
ngx_rtmp_conf_ctx_t *ctx, *pctx;
|
||||||
|
|
||||||
|
value = cf->args->elts;
|
||||||
|
|
||||||
racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_record_module);
|
racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_record_module);
|
||||||
|
|
||||||
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t));
|
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t));
|
||||||
|
@ -1034,19 +947,17 @@ ngx_rtmp_record_recorder(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prc = ngx_array_push(&racf->nodes);
|
rracf = ctx->app_conf[ngx_rtmp_record_module.ctx_index];
|
||||||
if (prc == NULL) {
|
rracf->rec_conf = ctx->app_conf;
|
||||||
|
rracf->id = value[1];
|
||||||
|
|
||||||
|
pracf = ngx_array_push(&racf->rec);
|
||||||
|
|
||||||
|
if (pracf == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rracf = ctx->app_conf[ngx_rtmp_record_module.ctx_index];
|
*pracf = rracf;
|
||||||
|
|
||||||
rc = &rracf->def;
|
|
||||||
|
|
||||||
value = cf->args->elts;
|
|
||||||
rc->id = value[1];
|
|
||||||
|
|
||||||
*prc = rc;
|
|
||||||
|
|
||||||
save = *cf;
|
save = *cf;
|
||||||
cf->ctx = ctx;
|
cf->ctx = ctx;
|
||||||
|
@ -1054,9 +965,22 @@ ngx_rtmp_record_recorder(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
|
||||||
rv = ngx_conf_parse(cf, NULL);
|
rv = ngx_conf_parse(cf, NULL);
|
||||||
|
|
||||||
rvm = ngx_rtmp_record_merge_app_conf(cf, racf, rracf);
|
for (i = 0; ngx_modules[i]; i++) {
|
||||||
|
if (ngx_modules[i]->type != NGX_RTMP_MODULE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
module = ngx_modules[i]->ctx;
|
||||||
|
|
||||||
|
if (module->merge_app_conf) {
|
||||||
|
rvm = module->merge_app_conf(cf,
|
||||||
|
pctx->app_conf[ngx_modules[i]->ctx_index],
|
||||||
|
ctx->app_conf[ngx_modules[i]->ctx_index]);
|
||||||
|
|
||||||
if (rvm != NGX_CONF_OK) {
|
if (rvm != NGX_CONF_OK) {
|
||||||
return rvm;
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*cf= save;
|
*cf= save;
|
||||||
|
@ -1071,6 +995,8 @@ ngx_rtmp_record_postconfiguration(ngx_conf_t *cf)
|
||||||
ngx_rtmp_core_main_conf_t *cmcf;
|
ngx_rtmp_core_main_conf_t *cmcf;
|
||||||
ngx_rtmp_handler_pt *h;
|
ngx_rtmp_handler_pt *h;
|
||||||
|
|
||||||
|
ngx_rtmp_record_done = ngx_rtmp_record_done_init;
|
||||||
|
|
||||||
cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
|
cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
|
||||||
|
|
||||||
h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]);
|
h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]);
|
||||||
|
|
|
@ -27,27 +27,24 @@ typedef struct {
|
||||||
ngx_str_t suffix;
|
ngx_str_t suffix;
|
||||||
ngx_flag_t unique;
|
ngx_flag_t unique;
|
||||||
ngx_url_t *url;
|
ngx_url_t *url;
|
||||||
} ngx_rtmp_record_node_t;
|
|
||||||
|
|
||||||
|
void **rec_conf;
|
||||||
typedef struct {
|
ngx_array_t rec; /* ngx_rtmp_record_app_conf_t * */
|
||||||
ngx_rtmp_record_node_t def;
|
|
||||||
ngx_array_t nodes; /* ngx_rtmp_record_node_t * */
|
|
||||||
} ngx_rtmp_record_app_conf_t;
|
} ngx_rtmp_record_app_conf_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_rtmp_record_node_t *conf;
|
ngx_rtmp_record_app_conf_t *conf;
|
||||||
ngx_file_t file;
|
ngx_file_t file;
|
||||||
ngx_uint_t nframes;
|
ngx_uint_t nframes;
|
||||||
uint32_t epoch;
|
uint32_t epoch;
|
||||||
ngx_time_t last;
|
ngx_time_t last;
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
} ngx_rtmp_record_node_ctx_t;
|
} ngx_rtmp_record_rec_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_array_t nodes; /* ngx_rtmp_record_node_ctx_t */
|
ngx_array_t rec; /* ngx_rtmp_record_rec_ctx_t */
|
||||||
u_char name[NGX_RTMP_MAX_NAME];
|
u_char name[NGX_RTMP_MAX_NAME];
|
||||||
u_char args[NGX_RTMP_MAX_ARGS];
|
u_char args[NGX_RTMP_MAX_ARGS];
|
||||||
} ngx_rtmp_record_ctx_t;
|
} ngx_rtmp_record_ctx_t;
|
||||||
|
@ -55,12 +52,25 @@ typedef struct {
|
||||||
|
|
||||||
/* Manual recording control,
|
/* Manual recording control,
|
||||||
* 'n' is record node index in config array.
|
* 'n' is record node index in config array.
|
||||||
* Note: these functions return path as pointer to a static buffer */
|
* Note: these functions allocate path in static buffer */
|
||||||
|
|
||||||
ngx_int_t ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n,
|
ngx_int_t ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n,
|
||||||
u_char **path);
|
ngx_str_t *path);
|
||||||
ngx_int_t ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n,
|
ngx_int_t ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n,
|
||||||
u_char **path);
|
ngx_str_t *path);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_str_t recorder;
|
||||||
|
ngx_str_t path;
|
||||||
|
} ngx_rtmp_record_done_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef ngx_int_t (*ngx_rtmp_record_done_pt)(ngx_rtmp_session_t *s,
|
||||||
|
ngx_rtmp_record_done_t *v);
|
||||||
|
|
||||||
|
|
||||||
|
extern ngx_rtmp_record_done_pt ngx_rtmp_record_done;
|
||||||
|
|
||||||
|
|
||||||
extern ngx_module_t ngx_rtmp_record_module;
|
extern ngx_module_t ngx_rtmp_record_module;
|
||||||
|
|
Loading…
Reference in a new issue