[-]
[+]
|
Changed |
nginx.spec
|
|
[-]
[+]
|
Deleted |
nginx-rtmp-module-1.0.5.tar.bz2/TODO
^
|
@@ -1,5 +0,0 @@
-- mpeg-dash
-- akamai auth
-- manual recorder custom file name
-- bandwidth control (per-app & total)
-- multiple streams per connection
|
[-]
[+]
|
Deleted |
nginx-rtmp-module-1.0.5.tar.bz2/hls/README.md
^
|
@@ -1 +0,0 @@
-HLS is now a part of rtmp module
|
[-]
[+]
|
Deleted |
nginx-rtmp-module-1.0.5.tar.bz2/ngx_rtmp_enotify_module.c
^
|
@@ -1,589 +0,0 @@
-/*
- * Copyright (c) 2012 Roman Arutyunyan
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include "ngx_rtmp.h"
-#include "ngx_rtmp_eval.h"
-#include "ngx_rtmp_cmd_module.h"
-#include "ngx_rtmp_record_module.h"
-
-#include <stdlib.h>
-#ifdef NGX_LINUX
-#include <unistd.h>
-#endif
-
-
-static ngx_rtmp_publish_pt next_publish;
-static ngx_rtmp_play_pt next_play;
-static ngx_rtmp_close_stream_pt next_close_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,
- void *conf);
-static ngx_int_t ngx_rtmp_enotify_postconfiguration(ngx_conf_t *cf);
-static void * ngx_rtmp_enotify_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_enotify_merge_app_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-
-#define NGX_RTMP_ENOTIFY_PUBLISHING 0x01
-#define NGX_RTMP_ENOTIFY_PLAYING 0x02
-
-
-enum {
- NGX_RTMP_ENOTIFY_PUBLISH,
- NGX_RTMP_ENOTIFY_PLAY,
- NGX_RTMP_ENOTIFY_PUBLISH_DONE,
- NGX_RTMP_ENOTIFY_PLAY_DONE,
- NGX_RTMP_ENOTIFY_RECORD_DONE,
- NGX_RTMP_ENOTIFY_MAX
-};
-
-
-typedef struct {
- ngx_str_t cmd;
- ngx_array_t args; /* ngx_str_t */
-} ngx_rtmp_enotify_conf_t;
-
-
-typedef struct {
- ngx_rtmp_enotify_conf_t *event[NGX_RTMP_ENOTIFY_MAX];
- ngx_flag_t active;
-} ngx_rtmp_enotify_app_conf_t;
-
-
-typedef struct {
- ngx_uint_t flags;
- u_char name[NGX_RTMP_MAX_NAME];
- u_char args[NGX_RTMP_MAX_ARGS];
- ngx_str_t path;
- ngx_str_t recorder;
-} ngx_rtmp_enotify_ctx_t;
-
-
-static ngx_command_t ngx_rtmp_enotify_commands[] = {
-
- { ngx_string("exec_publish"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
- ngx_rtmp_enotify_on_event,
- NGX_RTMP_APP_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("exec_play"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
- ngx_rtmp_enotify_on_event,
- NGX_RTMP_APP_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("exec_publish_done"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
- ngx_rtmp_enotify_on_event,
- NGX_RTMP_APP_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("exec_play_done"),
- NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
- ngx_rtmp_enotify_on_event,
- NGX_RTMP_APP_CONF_OFFSET,
- 0,
- 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
-};
-
-
-static ngx_rtmp_module_t ngx_rtmp_enotify_module_ctx = {
- NULL, /* preconfiguration */
- ngx_rtmp_enotify_postconfiguration, /* postconfiguration */
- NULL, /* create main configuration */
- NULL, /* init main configuration */
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
- ngx_rtmp_enotify_create_app_conf, /* create app configuration */
- ngx_rtmp_enotify_merge_app_conf /* merge app configuration */
-};
-
-
-ngx_module_t ngx_rtmp_enotify_module = {
- NGX_MODULE_V1,
- &ngx_rtmp_enotify_module_ctx, /* module context */
- ngx_rtmp_enotify_commands, /* module directives */
- NGX_RTMP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static void
-ngx_rtmp_enotify_eval_astr(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e,
- ngx_str_t *ret)
-{
- ngx_rtmp_enotify_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_enotify_module);
- if (ctx == NULL) {
- ret->len = 0;
- return;
- }
-
- ret->data = (u_char *) ctx + e->offset;
- ret->len = ngx_strlen(ret->data);
-}
-
-
-static void
-ngx_rtmp_enotify_eval_str(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e,
- ngx_str_t *ret)
-{
- ngx_rtmp_enotify_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_enotify_module);
- if (ctx == NULL) {
- ret->len = 0;
- return;
- }
-
- *ret = *(ngx_str_t *) ((u_char *) ctx + e->offset);
-}
-
-
-static ngx_rtmp_eval_t ngx_rtmp_enotify_eval[] = {
-
- { ngx_string("name"),
- ngx_rtmp_enotify_eval_astr,
- offsetof(ngx_rtmp_enotify_ctx_t, name) },
-
- { ngx_string("args"),
- ngx_rtmp_enotify_eval_astr,
- offsetof(ngx_rtmp_enotify_ctx_t, args) },
-
- { ngx_string("path"),
- ngx_rtmp_enotify_eval_str,
- offsetof(ngx_rtmp_enotify_ctx_t, path) },
-
- { ngx_string("recorder"),
- ngx_rtmp_enotify_eval_str,
- offsetof(ngx_rtmp_enotify_ctx_t, recorder) },
-
- ngx_rtmp_null_eval
-};
-
-
-static ngx_rtmp_eval_t * ngx_rtmp_enotify_eval_p[] = {
- ngx_rtmp_eval_session,
- ngx_rtmp_enotify_eval,
- NULL
-};
-
-
-static void *
-ngx_rtmp_enotify_create_app_conf(ngx_conf_t *cf)
-{
- ngx_rtmp_enotify_app_conf_t *enacf;
- ngx_uint_t n;
-
- enacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_enotify_app_conf_t));
- if (enacf == NULL) {
- return NULL;
- }
-
- for (n = 0; n < NGX_RTMP_ENOTIFY_MAX; ++n) {
- enacf->event[n] = NGX_CONF_UNSET_PTR;
- }
-
- return enacf;
-}
-
-
-static char *
-ngx_rtmp_enotify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_rtmp_enotify_app_conf_t *prev = parent;
- ngx_rtmp_enotify_app_conf_t *conf = child;
- ngx_uint_t n;
-
- for (n = 0; n < NGX_RTMP_ENOTIFY_MAX; ++n) {
- ngx_conf_merge_ptr_value(conf->event[n], prev->event[n], NULL);
- if (conf->event[n]) {
- conf->active = 1;
- }
- }
-
- if (conf->active) {
- prev->active = 1;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_rtmp_enotify_exec(ngx_rtmp_session_t *s, ngx_rtmp_enotify_conf_t *ec)
-{
-#if !(NGX_WIN32)
- int pid, fd, maxfd;
- ngx_str_t a, *arg_in;
- char **args, **arg_out;
- ngx_uint_t n;
-
- pid = fork();
-
- switch (pid) {
- case -1:
- ngx_log_error(NGX_LOG_INFO, s->connection->log, ngx_errno,
- "enotify: fork failed");
- return NGX_ERROR;
-
- case 0:
- /* child */
-
- /* close all descriptors */
- maxfd = sysconf(_SC_OPEN_MAX);
- for (fd = 0; fd < maxfd; ++fd) {
- close(fd);
- }
-
- fd = open("/dev/null", O_RDWR);
-
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
-
- args = ngx_palloc(s->connection->pool,
- (ec->args.nelts + 2) * sizeof(char *));
- if (args == NULL) {
- exit(1);
- }
-
- arg_in = ec->args.elts;
- arg_out = args;
-
- *arg_out++ = (char *) ec->cmd.data;
-
- for (n = 0; n < ec->args.nelts; ++n, ++arg_in) {
-
- ngx_rtmp_eval(s, arg_in, ngx_rtmp_enotify_eval_p, &a);
-
- if (ngx_rtmp_eval_streams(&a) != NGX_DONE) {
- continue;
- }
-
- *arg_out++ = (char *) a.data;
- }
-
- *arg_out = NULL;
-
- if (execvp((char *) ec->cmd.data, args) == -1) {
- exit(1);
- }
-
- break;
-
- default:
- /* parent */
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "enotify: child '%V' started pid=%ui",
- &ec->cmd, (ngx_uint_t)pid);
- break;
- }
-#endif /* NGX_WIN32 */
-
- return NGX_OK;
-}
-
-
-static void
-ngx_rtmp_enotify_init(ngx_rtmp_session_t *s,
- u_char name[NGX_RTMP_MAX_NAME], u_char args[NGX_RTMP_MAX_ARGS],
- ngx_uint_t flags)
-{
- ngx_rtmp_enotify_ctx_t *ctx;
- ngx_rtmp_enotify_app_conf_t *enacf;
-
- enacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_enotify_module);
-
- if (!enacf->active) {
- return;
- }
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_enotify_module);
-
- if (ctx == NULL) {
- ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_enotify_ctx_t));
- if (ctx == NULL) {
- return;
- }
-
- ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_enotify_module);
- }
-
- ngx_memcpy(ctx->name, name, NGX_RTMP_MAX_NAME);
- ngx_memcpy(ctx->args, args, NGX_RTMP_MAX_ARGS);
-
- ctx->flags |= flags;
-}
-
-
-static ngx_int_t
-ngx_rtmp_enotify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_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) {
- goto next;
- }
-
- ngx_rtmp_enotify_init(s, v->name, v->args, NGX_RTMP_ENOTIFY_PUBLISHING);
-
- ec = enacf->event[NGX_RTMP_ENOTIFY_PUBLISH];
-
- if (ec == NULL) {
- goto next;
- }
-
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "enotify: publish '%V'", &ec->cmd);
-
- ngx_rtmp_enotify_exec(s, ec);
-
-next:
- return next_publish(s, v);
-}
-
-
-static ngx_int_t
-ngx_rtmp_enotify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_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) {
- goto next;
- }
-
- ngx_rtmp_enotify_init(s, v->name, v->args, NGX_RTMP_ENOTIFY_PLAYING);
-
- ec = enacf->event[NGX_RTMP_ENOTIFY_PLAY];
-
- if (ec == NULL) {
- goto next;
- }
-
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "enotify: play '%V'", &ec->cmd);
-
- ngx_rtmp_enotify_exec(s, ec);
-
-next:
- return next_play(s, v);
-}
-
-
-static ngx_int_t
-ngx_rtmp_enotify_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t
- *v)
-{
- ngx_rtmp_enotify_ctx_t *ctx;
- ngx_rtmp_enotify_app_conf_t *enacf;
- ngx_rtmp_enotify_conf_t *ec;
-
- if (s->auto_pushed) {
- goto next;
- }
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_enotify_module);
-
- if (ctx == NULL) {
- goto next;
- }
-
- enacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_enotify_module);
-
- if (enacf == NULL) {
- goto next;
- }
-
- if (enacf->event[NGX_RTMP_ENOTIFY_PUBLISH_DONE] &&
- (ctx->flags & NGX_RTMP_ENOTIFY_PUBLISHING))
- {
- ec = enacf->event[NGX_RTMP_ENOTIFY_PUBLISH_DONE];
-
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "enotify: publish_done '%V'", &ec->cmd);
-
- ngx_rtmp_enotify_exec(s, ec);
- }
-
- if (enacf->event[NGX_RTMP_ENOTIFY_PLAY_DONE] &&
- (ctx->flags & NGX_RTMP_ENOTIFY_PLAYING))
- {
- ec = enacf->event[NGX_RTMP_ENOTIFY_PLAY_DONE];
-
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "enotify: play_done '%V'", &ec->cmd);
-
- ngx_rtmp_enotify_exec(s, ec);
- }
-
- ctx->flags = 0;
-
-next:
- return next_close_stream(s, v);
-}
-
-
-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;
- ngx_rtmp_enotify_ctx_t *ctx;
-
- 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_error(NGX_LOG_INFO, s->connection->log, 0,
- "enotify: record_done %V recorder=%V path='%V'",
- &ec->cmd, &v->recorder, &v->path);
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_enotify_module);
- if (ctx == NULL) {
- goto next;
- }
-
- ctx->recorder = v->recorder;
- ctx->path = v->path;
-
- ngx_rtmp_enotify_exec(s, ec);
-
-next:
- return next_record_done(s, v);
-}
-
-
-static char *
-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_conf_t *ec;
- ngx_str_t *name, *value, *s;
- size_t nargs;
- ngx_uint_t n;
-
- value = cf->args->elts;
- name = &value[0];
-
- ec = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_enotify_conf_t));
-
- if (ec == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ec->cmd = value[1];
-
- nargs = cf->args->nelts - 2;
-
- if (nargs) {
- if (ngx_array_init(&ec->args, cf->pool, nargs, sizeof(ngx_str_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- s = ngx_array_push_n(&ec->args, nargs);
- for (n = 2; n < cf->args->nelts; ++n, ++s) {
- *s = value[n];
- }
- }
-
- enacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_enotify_module);
-
- n = 0;
-
- switch (name->len) {
- case sizeof("exec_play") - 1:
- n = NGX_RTMP_ENOTIFY_PLAY;
- break;
-
- case sizeof("exec_publish") - 1:
- n = NGX_RTMP_ENOTIFY_PUBLISH;
- 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;
- break;
- }
-
- enacf->event[n] = ec;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_rtmp_enotify_postconfiguration(ngx_conf_t *cf)
-{
- next_publish = ngx_rtmp_publish;
- ngx_rtmp_publish = ngx_rtmp_enotify_publish;
-
- next_play = ngx_rtmp_play;
- ngx_rtmp_play = ngx_rtmp_enotify_play;
-
- next_close_stream = ngx_rtmp_close_stream;
- ngx_rtmp_close_stream = ngx_rtmp_enotify_close_stream;
-
- next_record_done = ngx_rtmp_record_done;
- ngx_rtmp_record_done = ngx_rtmp_enotify_record_done;
-
- return NGX_OK;
-}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/LICENSE
^
|
@@ -2,13 +2,13 @@
All rights reserved.
Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
+ list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
+ and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/README.md
^
|
@@ -1,4 +1,4 @@
-# NGINX-based RTMP server
+# NGINX-based Media Streaming Server
## nginx-rtmp-module
@@ -22,9 +22,9 @@
### Features
-* Live streaming of video/audio
+* RTMP/HLS/MPEG-DASH live streaming
-* Video on demand FLV/MP4,
+* RTMP Video on demand FLV/MP4,
playing from local filesystem or HTTP
* Stream relay support for distributed
@@ -36,8 +36,6 @@
* Online transcoding with FFmpeg
-* HLS (HTTP Live Streaming) support
-
* HTTP callbacks (publish/play/record/update etc)
* Running external programs on certain events (exec)
@@ -49,9 +47,9 @@
level for faster streaming and low
memory footprint
-* Proved to work with Wirecast,FMS,Wowza,
- JWPlayer,FlowPlayer,StrobeMediaPlayback,
- ffmpeg,avconv,rtmpdump,flvstreamer
+* Proved to work with Wirecast, FMS, Wowza,
+ JWPlayer, FlowPlayer, StrobeMediaPlayback,
+ ffmpeg, avconv, rtmpdump, flvstreamer
and many more
* Statistics in XML/XSL in machine- & human-
@@ -63,14 +61,20 @@
cd to NGINX source directory & run this:
- ./configure --add-module=<path-to-nginx-rtmp-module>
+ ./configure --add-module=/path/to/nginx-rtmp-module
make
make install
Several versions of nginx (1.3.14 - 1.5.0) require http_ssl_module to be
added as well:
- ./configure --add-module=<path-to-nginx-rtmp-module> --with-http_ssl_module
+ ./configure --add-module=/path/to/nginx-rtmp-module --with-http_ssl_module
+
+For building debug version of nginx add `--with-debug`
+
+ ./configure --add-module=/path/to-nginx/rtmp-module --with-debug
+
+[Read more about debug log](https://github.com/arut/nginx-rtmp-module/wiki/Debug-log)
### Windows limitations
@@ -146,7 +150,8 @@
#
# Multiple exec lines can be specified.
- exec ffmpeg -re -i rtmp://localhost:1935/$app/$name -vcodec flv -acodec copy -s 32x32 -f flv rtmp://localhost:1935/small/${name};
+ exec ffmpeg -re -i rtmp://localhost:1935/$app/$name -vcodec flv -acodec copy -s 32x32
+ -f flv rtmp://localhost:1935/small/${name};
}
application small {
@@ -158,14 +163,15 @@
live on;
# Stream from local webcam
- exec_static ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an -f flv rtmp://localhost:1935/webcam/mystream;
+ exec_static ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an
+ -f flv rtmp://localhost:1935/webcam/mystream;
}
application mypush {
live on;
# Every stream published here
- # is automatically pushed to
+ # is automatically pushed to
# these two machines
push rtmp1.example.com;
push rtmp2.example.com:1934;
@@ -178,7 +184,7 @@
# and play locally
pull rtmp://rtmp3.example.com pageUrl=www.example.com/index.html;
}
-
+
application mystaticpull {
live on;
@@ -201,8 +207,8 @@
live on;
- # The following notifications receive all
- # the session variables as well as
+ # The following notifications receive all
+ # the session variables as well as
# particular call arguments in HTTP POST
# request
@@ -218,7 +224,7 @@
on_done http://localhost:8080/done;
# All above mentioned notifications receive
- # standard connect() arguments as well as
+ # standard connect() arguments as well as
# play/publish ones. If any arguments are sent
# with GET-style syntax to play & publish
# these are also included.
@@ -247,8 +253,8 @@
# profile (see ffmpeg example).
# This example creates RTMP stream from movie ready for HLS:
#
- # ffmpeg -loglevel verbose -re -i movie.avi -vcodec libx264
- # -vprofile baseline -acodec libmp3lame -ar 44100 -ac 1
+ # ffmpeg -loglevel verbose -re -i movie.avi -vcodec libx264
+ # -vprofile baseline -acodec libmp3lame -ar 44100 -ac 1
# -f flv rtmp://localhost:1935/hls/movie
#
# If you need to transcode live stream use 'exec' feature.
@@ -256,10 +262,16 @@
application hls {
live on;
hls on;
- hls_path /tmp/app;
- hls_fragment 5s;
+ hls_path /tmp/hls;
}
+ # MPEG-DASH is similar to HLS
+
+ application dash {
+ live on;
+ dash on;
+ dash_path /tmp/dash;
+ }
}
}
@@ -292,10 +304,15 @@
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
- alias /tmp/app;
- expires -1;
+ root /tmp;
+ add_header Cache-Control no-cache;
}
+ location /dash {
+ # Serve DASH fragments
+ root /tmp;
+ add_header Cache-Control no-cache;
+ }
}
}
@@ -305,14 +322,9 @@
rtmp_auto_push on;
rtmp {
-
server {
-
listen 1935;
- chunk_size 4000;
-
- # TV mode: one publisher, many subscribers
application mytv {
live on;
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/config
^
|
@@ -1,6 +1,6 @@
ngx_addon_name="ngx_rtmp_module"
-CORE_MODULES="$CORE_MODULES
+CORE_MODULES="$CORE_MODULES
ngx_rtmp_module \
ngx_rtmp_core_module \
ngx_rtmp_cmd_module \
@@ -15,11 +15,11 @@
ngx_rtmp_relay_module \
ngx_rtmp_exec_module \
ngx_rtmp_auto_push_module \
- ngx_rtmp_enotify_module \
ngx_rtmp_notify_module \
ngx_rtmp_log_module \
ngx_rtmp_limit_module \
ngx_rtmp_hls_module \
+ ngx_rtmp_dash_module \
"
@@ -36,13 +36,16 @@
$ngx_addon_dir/ngx_rtmp_codec_module.h \
$ngx_addon_dir/ngx_rtmp_eval.h \
$ngx_addon_dir/ngx_rtmp.h \
+ $ngx_addon_dir/ngx_rtmp_version.h \
$ngx_addon_dir/ngx_rtmp_live_module.h \
$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_relay_module.h \
$ngx_addon_dir/ngx_rtmp_streams.h \
+ $ngx_addon_dir/ngx_rtmp_bitop.h \
$ngx_addon_dir/hls/ngx_rtmp_mpegts.h \
+ $ngx_addon_dir/dash/ngx_rtmp_mp4.h \
"
@@ -72,12 +75,14 @@
$ngx_addon_dir/ngx_rtmp_bandwidth.c \
$ngx_addon_dir/ngx_rtmp_exec_module.c \
$ngx_addon_dir/ngx_rtmp_auto_push_module.c \
- $ngx_addon_dir/ngx_rtmp_enotify_module.c \
$ngx_addon_dir/ngx_rtmp_notify_module.c \
$ngx_addon_dir/ngx_rtmp_log_module.c \
$ngx_addon_dir/ngx_rtmp_limit_module.c \
+ $ngx_addon_dir/ngx_rtmp_bitop.c \
$ngx_addon_dir/hls/ngx_rtmp_hls_module.c \
+ $ngx_addon_dir/dash/ngx_rtmp_dash_module.c \
$ngx_addon_dir/hls/ngx_rtmp_mpegts.c \
+ $ngx_addon_dir/dash/ngx_rtmp_mp4.c \
"
CFLAGS="$CFLAGS -I$ngx_addon_dir"
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/dash
^
|
+(directory)
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/dash/ngx_rtmp_dash_module.c
^
|
@@ -0,0 +1,1528 @@
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_rtmp.h>
+#include <ngx_rtmp_codec_module.h>
+#include "ngx_rtmp_live_module.h"
+#include "ngx_rtmp_mp4.h"
+
+
+static ngx_rtmp_publish_pt next_publish;
+static ngx_rtmp_close_stream_pt next_close_stream;
+static ngx_rtmp_stream_begin_pt next_stream_begin;
+static ngx_rtmp_stream_eof_pt next_stream_eof;
+
+
+static ngx_int_t ngx_rtmp_dash_postconfiguration(ngx_conf_t *cf);
+static void * ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf);
+static char * ngx_rtmp_dash_merge_app_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+static ngx_int_t ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s);
+
+
+#define NGX_RTMP_DASH_BUFSIZE (1024*1024)
+#define NGX_RTMP_DASH_MAX_MDAT (10*1024*1024)
+#define NGX_RTMP_DASH_MAX_SAMPLES 1024
+#define NGX_RTMP_DASH_DIR_ACCESS 0744
+
+
+typedef struct {
+ uint32_t timestamp;
+ uint32_t duration;
+} ngx_rtmp_dash_frag_t;
+
+
+typedef struct {
+ ngx_uint_t id;
+ ngx_uint_t opened;
+ ngx_uint_t mdat_size;
+ ngx_uint_t sample_count;
+ ngx_uint_t sample_mask;
+ ngx_fd_t fd;
+ char type;
+ uint32_t earliest_pres_time;
+ uint32_t latest_pres_time;
+ ngx_rtmp_mp4_sample_t samples[NGX_RTMP_DASH_MAX_SAMPLES];
+} ngx_rtmp_dash_track_t;
+
+
+typedef struct {
+ ngx_str_t playlist;
+ ngx_str_t playlist_bak;
+ ngx_str_t name;
+ ngx_str_t stream;
+ ngx_time_t start_time;
+
+ ngx_uint_t nfrags;
+ ngx_uint_t frag;
+ ngx_rtmp_dash_frag_t *frags; /* circular 2 * winfrags + 1 */
+
+ unsigned opened:1;
+ unsigned has_video:1;
+ unsigned has_audio:1;
+
+ ngx_file_t video_file;
+ ngx_file_t audio_file;
+
+ ngx_uint_t id;
+
+ ngx_rtmp_dash_track_t audio;
+ ngx_rtmp_dash_track_t video;
+} ngx_rtmp_dash_ctx_t;
+
+
+typedef struct {
+ ngx_str_t path;
+ ngx_msec_t playlen;
+} ngx_rtmp_dash_cleanup_t;
+
+
+typedef struct {
+ ngx_flag_t dash;
+ ngx_msec_t fraglen;
+ ngx_msec_t playlen;
+ ngx_flag_t nested;
+ ngx_str_t path;
+ ngx_uint_t winfrags;
+ ngx_flag_t cleanup;
+ ngx_path_t *slot;
+} ngx_rtmp_dash_app_conf_t;
+
+
+static ngx_command_t ngx_rtmp_dash_commands[] = {
+
+ { ngx_string("dash"),
+ 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_dash_app_conf_t, dash),
+ NULL },
+
+ { ngx_string("dash_fragment"),
+ 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_dash_app_conf_t, fraglen),
+ NULL },
+
+ { ngx_string("dash_path"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_dash_app_conf_t, path),
+ NULL },
+
+ { ngx_string("dash_playlist_length"),
+ 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_dash_app_conf_t, playlen),
+ NULL },
+
+ { ngx_string("dash_cleanup"),
+ 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_dash_app_conf_t, cleanup),
+ NULL },
+
+ { ngx_string("dash_nested"),
+ 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_dash_app_conf_t, nested),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_rtmp_module_t ngx_rtmp_dash_module_ctx = {
+ NULL, /* preconfiguration */
+ ngx_rtmp_dash_postconfiguration, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_rtmp_dash_create_app_conf, /* create location configuration */
+ ngx_rtmp_dash_merge_app_conf, /* merge location configuration */
+};
+
+
+ngx_module_t ngx_rtmp_dash_module = {
+ NGX_MODULE_V1,
+ &ngx_rtmp_dash_module_ctx, /* module context */
+ ngx_rtmp_dash_commands, /* module directives */
+ NGX_RTMP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_rtmp_dash_frag_t *
+ngx_rtmp_dash_get_frag(ngx_rtmp_session_t *s, ngx_int_t n)
+{
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ return &ctx->frags[(ctx->frag + n) % (dacf->winfrags * 2 + 1)];
+}
+
+
+static void
+ngx_rtmp_dash_next_frag(ngx_rtmp_session_t *s)
+{
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ if (ctx->nfrags == dacf->winfrags) {
+ ctx->frag++;
+ } else {
+ ctx->nfrags++;
+ }
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_rename_file(u_char *src, u_char *dst)
+{
+ /* rename file with overwrite */
+
+#if (NGX_WIN32)
+ return MoveFileEx((LPCTSTR) src, (LPCTSTR) dst, MOVEFILE_REPLACE_EXISTING);
+#else
+ return ngx_rename_file(src, dst);
+#endif
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
+{
+ char *sep;
+ u_char *p, *last;
+ ssize_t n;
+ ngx_fd_t fd;
+ struct tm tm;
+ ngx_str_t noname, *name;
+ ngx_uint_t i;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+ ngx_rtmp_dash_frag_t *f;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ static u_char buffer[NGX_RTMP_DASH_BUFSIZE];
+ static u_char start_time[sizeof("1970-09-28T12:00:00+06:00")];
+ static u_char end_time[sizeof("1970-09-28T12:00:00+06:00")];
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ if (dacf == NULL || ctx == NULL || codec_ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (ctx->id == 0) {
+ ngx_rtmp_dash_write_init_segments(s);
+ }
+
+ fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY,
+ NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: open failed: '%V'", &ctx->playlist_bak);
+ return NGX_ERROR;
+ }
+
+
+#define NGX_RTMP_DASH_MANIFEST_HEADER \
+ "<?xml version=\"1.0\"?>\n" \
+ "<MPD\n" \
+ " type=\"dynamic\"\n" \
+ " xmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n" \
+ " availabilityStartTime=\"%s\"\n" \
+ " availabilityEndTime=\"%s\"\n" \
+ " minimumUpdatePeriod=\"PT%uiS\"\n" \
+ " minBufferTime=\"PT%uiS\"\n" \
+ " timeShiftBufferDepth=\"PT0H0M0.00S\"\n" \
+ " suggestedPresentationDelay=\"PT%uiS\"\n" \
+ " profiles=\"urn:hbbtv:dash:profile:isoff-live:2012," \
+ "urn:mpeg:dash:profile:isoff-live:2011\"\n" \
+ " xmlns:xsi=\"http://www.w3.org/2011/XMLSchema-instance\"\n" \
+ " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\">\n" \
+ " <Period start=\"PT0S\" id=\"dash\">\n"
+
+
+#define NGX_RTMP_DASH_MANIFEST_VIDEO \
+ " <AdaptationSet\n" \
+ " id=\"1\"\n" \
+ " segmentAlignment=\"true\"\n" \
+ " maxWidth=\"%ui\"\n" \
+ " maxHeight=\"%ui\"\n" \
+ " maxFrameRate=\"%ui\">\n" \
+ " <Representation\n" \
+ " id=\"%V_H264\"\n" \
+ " mimeType=\"video/mp4\"\n" \
+ " codecs=\"avc1.%02uxi%02uxi%02uxi\"\n" \
+ " width=\"%ui\"\n" \
+ " height=\"%ui\"\n" \
+ " frameRate=\"%ui\"\n" \
+ " sar=\"1:1\"\n" \
+ " startWithSAP=\"1\"\n" \
+ " bandwidth=\"%ui\">\n" \
+ " <SegmentTemplate\n" \
+ " presentationTimeOffset=\"0\"\n" \
+ " timescale=\"1000\"\n" \
+ " media=\"%V%s$Time$.m4v\"\n" \
+ " initialization=\"%V%sinit.m4v\">\n" \
+ " <SegmentTimeline>\n"
+
+
+#define NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER \
+ " </SegmentTimeline>\n" \
+ " </SegmentTemplate>\n" \
+ " </Representation>\n" \
+ " </AdaptationSet>\n"
+
+
+#define NGX_RTMP_DASH_MANIFEST_TIME \
+ " <S t=\"%uD\" d=\"%uD\"/>\n"
+
+
+#define NGX_RTMP_DASH_MANIFEST_AUDIO \
+ " <AdaptationSet\n" \
+ " id=\"2\"\n" \
+ " segmentAlignment=\"true\">\n" \
+ " <AudioChannelConfiguration\n" \
+ " schemeIdUri=\"urn:mpeg:dash:" \
+ "23003:3:audio_channel_configuration:2011\"\n" \
+ " value=\"1\"/>\n" \
+ " <Representation\n" \
+ " id=\"%V_AAC\"\n" \
+ " mimeType=\"audio/mp4\"\n" \
+ " codecs=\"mp4a.%s\"\n" \
+ " audioSamplingRate=\"%ui\"\n" \
+ " startWithSAP=\"1\"\n" \
+ " bandwidth=\"%ui\">\n" \
+ " <SegmentTemplate\n" \
+ " presentationTimeOffset=\"0\"\n" \
+ " timescale=\"1000\"\n" \
+ " media=\"%V%s$Time$.m4a\"\n" \
+ " initialization=\"%V%sinit.m4a\">\n" \
+ " <SegmentTimeline>\n"
+
+
+#define NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER \
+ " </SegmentTimeline>\n" \
+ " </SegmentTemplate>\n" \
+ " </Representation>\n" \
+ " </AdaptationSet>\n"
+
+
+#define NGX_RTMP_DASH_MANIFEST_FOOTER \
+ " </Period>\n" \
+ "</MPD>\n"
+
+ ngx_libc_localtime(ctx->start_time.sec +
+ ngx_rtmp_dash_get_frag(s, 0)->timestamp / 1000, &tm);
+
+ *ngx_sprintf(start_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
+ tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec,
+ ctx->start_time.gmtoff < 0 ? '-' : '+',
+ ngx_abs(ctx->start_time.gmtoff / 60),
+ ngx_abs(ctx->start_time.gmtoff % 60)) = 0;
+
+ ngx_libc_localtime(ctx->start_time.sec +
+ (ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->timestamp +
+ ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->duration) /
+ 1000, &tm);
+
+ *ngx_sprintf(end_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
+ tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec,
+ ctx->start_time.gmtoff < 0 ? '-' : '+',
+ ngx_abs(ctx->start_time.gmtoff / 60),
+ ngx_abs(ctx->start_time.gmtoff % 60)) = 0;
+
+ last = buffer + sizeof(buffer);
+
+ p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_HEADER,
+ start_time,
+ end_time,
+ (ngx_uint_t) (dacf->fraglen / 1000),
+ (ngx_uint_t) (dacf->fraglen / 1000),
+ (ngx_uint_t) (dacf->fraglen / 500));
+
+ n = ngx_write_fd(fd, buffer, p - buffer);
+
+ ngx_str_null(&noname);
+
+ name = (dacf->nested ? &noname : &ctx->name);
+ sep = (dacf->nested ? "" : "-");
+
+ if (ctx->has_video) {
+ p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_VIDEO,
+ codec_ctx->width,
+ codec_ctx->height,
+ codec_ctx->frame_rate,
+ &ctx->name,
+ codec_ctx->avc_profile,
+ codec_ctx->avc_compat,
+ codec_ctx->avc_level,
+ codec_ctx->width,
+ codec_ctx->height,
+ codec_ctx->frame_rate,
+ (ngx_uint_t) (codec_ctx->video_data_rate * 1000),
+ name, sep,
+ name, sep);
+
+ for (i = 0; i < ctx->nfrags; i++) {
+ f = ngx_rtmp_dash_get_frag(s, i);
+ p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME,
+ f->timestamp, f->duration);
+ }
+
+ p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER);
+
+ n = ngx_write_fd(fd, buffer, p - buffer);
+ }
+
+ if (ctx->has_audio) {
+ p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_AUDIO,
+ &ctx->name,
+ codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC ?
+ "40.2" : "6b",
+ codec_ctx->sample_rate,
+ (ngx_uint_t) (codec_ctx->audio_data_rate * 1000),
+ name, sep,
+ name, sep);
+
+ for (i = 0; i < ctx->nfrags; i++) {
+ f = ngx_rtmp_dash_get_frag(s, i);
+ p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME,
+ f->timestamp, f->duration);
+ }
+
+ p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER);
+
+ n = ngx_write_fd(fd, buffer, p - buffer);
+ }
+
+ p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_FOOTER);
+ n = ngx_write_fd(fd, buffer, p - buffer);
+
+ if (n < 0) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: write failed: '%V'", &ctx->playlist_bak);
+ ngx_close_file(fd);
+ return NGX_ERROR;
+ }
+
+ ngx_close_file(fd);
+
+ if (ngx_rtmp_dash_rename_file(ctx->playlist_bak.data, ctx->playlist.data)
+ == NGX_FILE_ERROR)
+ {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: rename failed: '%V'->'%V'",
+ &ctx->playlist_bak, &ctx->playlist);
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s)
+{
+ ngx_fd_t fd;
+ ngx_int_t rc;
+ ngx_buf_t b;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+
+ static u_char buffer[NGX_RTMP_DASH_BUFSIZE];
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ if (ctx == NULL || codec_ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ /* init video */
+
+ *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4v") = 0;
+
+ fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
+ NGX_FILE_DEFAULT_ACCESS);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: error creating video init file");
+ return NGX_ERROR;
+ }
+
+ b.start = buffer;
+ b.end = b.start + sizeof(buffer);
+ b.pos = b.last = b.start;
+
+ ngx_rtmp_mp4_write_ftyp(&b);
+ ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_VIDEO_TRACK);
+
+ rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start));
+ if (rc == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: writing video init failed");
+ }
+
+ ngx_close_file(fd);
+
+ /* init audio */
+
+ *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4a") = 0;
+
+ fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
+ NGX_FILE_DEFAULT_ACCESS);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: error creating dash audio init file");
+ return NGX_ERROR;
+ }
+
+ b.pos = b.last = b.start;
+
+ ngx_rtmp_mp4_write_ftyp(&b);
+ ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_AUDIO_TRACK);
+
+ rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start));
+ if (rc == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: writing audio init failed");
+ }
+
+ ngx_close_file(fd);
+
+ return NGX_OK;
+}
+
+
+static void
+ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t)
+{
+ u_char *pos, *pos1;
+ size_t left;
+ ssize_t n;
+ ngx_fd_t fd;
+ ngx_buf_t b;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_frag_t *f;
+
+ static u_char buffer[NGX_RTMP_DASH_BUFSIZE];
+
+ if (!t->opened) {
+ return;
+ }
+
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: close fragment id=%ui, type=%c, pts=%uD",
+ t->id, t->type, t->earliest_pres_time);
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ b.start = buffer;
+ b.end = buffer + sizeof(buffer);
+ b.pos = b.last = b.start;
+
+ ngx_rtmp_mp4_write_styp(&b);
+
+ pos = b.last;
+ b.last += 44; /* leave room for sidx */
+
+ ngx_rtmp_mp4_write_moof(&b, t->earliest_pres_time, t->sample_count,
+ t->samples, t->sample_mask, t->id);
+ pos1 = b.last;
+ b.last = pos;
+
+ ngx_rtmp_mp4_write_sidx(&b, t->mdat_size + 8 + (pos1 - (pos + 44)),
+ t->earliest_pres_time, t->latest_pres_time);
+ b.last = pos1;
+ ngx_rtmp_mp4_write_mdat(&b, t->mdat_size + 8);
+
+ /* move the data down to make room for the headers */
+
+ f = ngx_rtmp_dash_get_frag(s, ctx->nfrags);
+
+ *ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uD.m4%c",
+ f->timestamp, t->type) = 0;
+
+ fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR,
+ NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: error creating dash temp video file");
+ goto done;
+ }
+
+ if (ngx_write_fd(fd, b.pos, (size_t) (b.last - b.pos)) == NGX_ERROR) {
+ goto done;
+ }
+
+ left = (size_t) t->mdat_size;
+
+#if (NGX_WIN32)
+ if (SetFilePointer(t->fd, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "dash: SetFilePointer error");
+ goto done;
+ }
+#else
+ if (lseek(t->fd, 0, SEEK_SET) == -1) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: lseek error");
+ goto done;
+ }
+#endif
+
+ while (left > 0) {
+
+ n = ngx_read_fd(t->fd, buffer, ngx_min(sizeof(buffer), left));
+ if (n == NGX_ERROR) {
+ break;
+ }
+
+ n = ngx_write_fd(fd, buffer, (size_t) n);
+ if (n == NGX_ERROR) {
+ break;
+ }
+
+ left -= n;
+ }
+
+done:
+
+ if (fd != NGX_INVALID_FILE) {
+ ngx_close_file(fd);
+ }
+
+ ngx_close_file(t->fd);
+
+ t->fd = NGX_INVALID_FILE;
+ t->opened = 0;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_close_fragments(ngx_rtmp_session_t *s)
+{
+ ngx_rtmp_dash_ctx_t *ctx;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+ if (ctx == NULL || !ctx->opened) {
+ return NGX_OK;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: close fragments");
+
+ ngx_rtmp_dash_close_fragment(s, &ctx->video);
+ ngx_rtmp_dash_close_fragment(s, &ctx->audio);
+
+ ngx_rtmp_dash_next_frag(s);
+
+ ngx_rtmp_dash_write_playlist(s);
+
+ ctx->id++;
+ ctx->opened = 0;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_open_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t,
+ ngx_uint_t id, char type)
+{
+ ngx_rtmp_dash_ctx_t *ctx;
+
+ if (t->opened) {
+ return NGX_OK;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: open fragment id=%ui, type='%c'", id, type);
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ *ngx_sprintf(ctx->stream.data + ctx->stream.len, "raw.m4%c", type) = 0;
+
+ t->fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR,
+ NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
+
+ if (t->fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: error creating fragment file");
+ return NGX_ERROR;
+ }
+
+ t->id = id;
+ t->type = type;
+ t->sample_count = 0;
+ t->earliest_pres_time = 0;
+ t->latest_pres_time = 0;
+ t->mdat_size = 0;
+ t->opened = 1;
+
+ if (type == 'v') {
+ t->sample_mask = NGX_RTMP_MP4_SAMPLE_SIZE|
+ NGX_RTMP_MP4_SAMPLE_DURATION|
+ NGX_RTMP_MP4_SAMPLE_DELAY|
+ NGX_RTMP_MP4_SAMPLE_KEY;
+ } else {
+ t->sample_mask = NGX_RTMP_MP4_SAMPLE_SIZE|
+ NGX_RTMP_MP4_SAMPLE_DURATION;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_open_fragments(ngx_rtmp_session_t *s)
+{
+ ngx_rtmp_dash_ctx_t *ctx;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: open fragments");
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ if (ctx->opened) {
+ return NGX_OK;
+ }
+
+ ngx_rtmp_dash_open_fragment(s, &ctx->video, ctx->id, 'v');
+
+ ngx_rtmp_dash_open_fragment(s, &ctx->audio, ctx->id, 'a');
+
+ ctx->opened = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_ensure_directory(ngx_rtmp_session_t *s)
+{
+ size_t len;
+ ngx_file_info_t fi;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ static u_char path[NGX_MAX_PATH + 1];
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+
+ *ngx_snprintf(path, sizeof(path) - 1, "%V", &dacf->path) = 0;
+
+ if (ngx_file_info(path, &fi) == NGX_FILE_ERROR) {
+
+ if (ngx_errno != NGX_ENOENT) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: " ngx_file_info_n " failed on '%V'",
+ &dacf->path);
+ return NGX_ERROR;
+ }
+
+ /* ENOENT */
+
+ if (ngx_create_dir(path, NGX_RTMP_DASH_DIR_ACCESS) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: " ngx_create_dir_n " failed on '%V'",
+ &dacf->path);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: directory '%V' created", &dacf->path);
+
+ } else {
+
+ if (!ngx_is_dir(&fi)) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "dash: '%V' exists and is not a directory",
+ &dacf->path);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: directory '%V' exists", &dacf->path);
+ }
+
+ if (!dacf->nested) {
+ return NGX_OK;
+ }
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ len = dacf->path.len;
+ if (dacf->path.data[len - 1] == '/') {
+ len--;
+ }
+
+ *ngx_snprintf(path, sizeof(path) - 1, "%*s/%V", len, dacf->path.data,
+ &ctx->name) = 0;
+
+ if (ngx_file_info(path, &fi) != NGX_FILE_ERROR) {
+
+ if (ngx_is_dir(&fi)) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: directory '%s' exists", path);
+ return NGX_OK;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "dash: '%s' exists and is not a directory", path);
+
+ return NGX_ERROR;
+ }
+
+ if (ngx_errno != NGX_ENOENT) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: " ngx_file_info_n " failed on '%s'", path);
+ return NGX_ERROR;
+ }
+
+ /* NGX_ENOENT */
+
+ if (ngx_create_dir(path, NGX_RTMP_DASH_DIR_ACCESS) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: " ngx_create_dir_n " failed on '%s'", path);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: directory '%s' created", path);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
+{
+ u_char *p;
+ size_t len;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_frag_t *f;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ if (dacf == NULL || !dacf->dash || dacf->path.len == 0) {
+ goto next;
+ }
+
+ if (s->auto_pushed) {
+ goto next;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: publish: name='%s' type='%s'", v->name, v->type);
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ if (ctx == NULL) {
+ ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_dash_ctx_t));
+ if (ctx == NULL) {
+ goto next;
+ }
+ ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_dash_module);
+
+ } else {
+ if (ctx->opened) {
+ goto next;
+ }
+
+ f = ctx->frags;
+ ngx_memzero(ctx, sizeof(ngx_rtmp_dash_ctx_t));
+ ctx->frags = f;
+ }
+
+ if (ctx->frags == NULL) {
+ ctx->frags = ngx_pcalloc(s->connection->pool,
+ sizeof(ngx_rtmp_dash_frag_t) *
+ (dacf->winfrags * 2 + 1));
+ if (ctx->frags == NULL) {
+ return NGX_ERROR;
+ }
+ }
+
+ ctx->id = 0;
+
+ if (ngx_strstr(v->name, "..")) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "dash: bad stream name: '%s'", v->name);
+ return NGX_ERROR;
+ }
+
+ ctx->name.len = ngx_strlen(v->name);
+ ctx->name.data = ngx_palloc(s->connection->pool, ctx->name.len + 1);
+
+ if (ctx->name.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ngx_cpymem(ctx->name.data, v->name, ctx->name.len) = 0;
+
+ len = dacf->path.len + 1 + ctx->name.len + sizeof(".mpd");
+ if (dacf->nested) {
+ len += sizeof("/index") - 1;
+ }
+
+ ctx->playlist.data = ngx_palloc(s->connection->pool, len);
+ p = ngx_cpymem(ctx->playlist.data, dacf->path.data, dacf->path.len);
+
+ if (p[-1] != '/') {
+ *p++ = '/';
+ }
+
+ p = ngx_cpymem(p, ctx->name.data, ctx->name.len);
+
+ /*
+ * ctx->stream holds initial part of stream file path
+ * however the space for the whole stream path
+ * is allocated
+ */
+
+ ctx->stream.len = p - ctx->playlist.data + 1;
+ ctx->stream.data = ngx_palloc(s->connection->pool,
+ ctx->stream.len + NGX_INT32_LEN +
+ sizeof(".m4x"));
+
+ ngx_memcpy(ctx->stream.data, ctx->playlist.data, ctx->stream.len - 1);
+ ctx->stream.data[ctx->stream.len - 1] = (dacf->nested ? '/' : '-');
+
+ if (dacf->nested) {
+ p = ngx_cpymem(p, "/index.mpd", sizeof("/index.mpd") - 1);
+ } else {
+ p = ngx_cpymem(p, ".mpd", sizeof(".mpd") - 1);
+ }
+
+ ctx->playlist.len = p - ctx->playlist.data;
+
+ *p = 0;
+
+ /* playlist bak (new playlist) path */
+
+ ctx->playlist_bak.data = ngx_palloc(s->connection->pool,
+ ctx->playlist.len + sizeof(".bak"));
+ p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data,
+ ctx->playlist.len);
+ p = ngx_cpymem(p, ".bak", sizeof(".bak") - 1);
+
+ ctx->playlist_bak.len = p - ctx->playlist_bak.data;
+
+ *p = 0;
+
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: playlist='%V' playlist_bak='%V' stream_pattern='%V'",
+ &ctx->playlist, &ctx->playlist_bak, &ctx->stream);
+
+ ctx->start_time = *ngx_cached_time;
+
+ if (ngx_rtmp_dash_ensure_directory(s) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+next:
+ return next_publish(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
+{
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+
+ if (dacf == NULL || !dacf->dash || ctx == NULL) {
+ goto next;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "dash: delete stream");
+
+ ngx_rtmp_dash_close_fragments(s);
+
+next:
+ return next_close_stream(s, v);
+}
+
+
+static void
+ngx_rtmp_dash_update_fragments(ngx_rtmp_session_t *s, ngx_int_t boundary,
+ uint32_t timestamp)
+{
+ int32_t d;
+ ngx_int_t hit;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_dash_frag_t *f;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+ f = ngx_rtmp_dash_get_frag(s, ctx->nfrags);
+
+ d = (int32_t) (timestamp - f->timestamp);
+
+ if (d >= 0) {
+
+ f->duration = timestamp - f->timestamp;
+ hit = (f->duration >= dacf->fraglen);
+
+ } else {
+
+ /* sometimes clients generate slightly unordered frames */
+
+ hit = (-d > 1000);
+ }
+
+ if (ctx->has_video && !hit) {
+ boundary = 0;
+ }
+
+ if (!ctx->has_video && ctx->has_audio) {
+ boundary = hit;
+ }
+
+ if (ctx->audio.mdat_size >= NGX_RTMP_DASH_MAX_MDAT) {
+ boundary = 1;
+ }
+
+ if (ctx->video.mdat_size >= NGX_RTMP_DASH_MAX_MDAT) {
+ boundary = 1;
+ }
+
+ if (!ctx->opened) {
+ boundary = 1;
+ }
+
+ if (boundary) {
+ ngx_rtmp_dash_close_fragments(s);
+ ngx_rtmp_dash_open_fragments(s);
+
+ f = ngx_rtmp_dash_get_frag(s, ctx->nfrags);
+ f->timestamp = timestamp;
+ }
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_append(ngx_rtmp_session_t *s, ngx_chain_t *in,
+ ngx_rtmp_dash_track_t *t, ngx_int_t key, uint32_t timestamp, uint32_t delay)
+{
+ u_char *p;
+ size_t size, bsize;
+ ngx_rtmp_mp4_sample_t *smpl;
+
+ static u_char buffer[NGX_RTMP_DASH_BUFSIZE];
+
+ p = buffer;
+ size = 0;
+
+ for (; in && size < sizeof(buffer); in = in->next) {
+
+ bsize = (size_t) (in->buf->last - in->buf->pos);
+ if (size + bsize > sizeof(buffer)) {
+ bsize = (size_t) (sizeof(buffer) - size);
+ }
+
+ p = ngx_cpymem(p, in->buf->pos, bsize);
+ size += bsize;
+ }
+
+ ngx_rtmp_dash_update_fragments(s, key, timestamp);
+
+ if (t->sample_count == 0) {
+ t->earliest_pres_time = timestamp;
+ }
+
+ t->latest_pres_time = timestamp;
+
+ if (t->sample_count < NGX_RTMP_DASH_MAX_SAMPLES) {
+
+ if (ngx_write_fd(t->fd, buffer, size) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: " ngx_write_fd_n " failed");
+ return NGX_ERROR;
+ }
+
+ smpl = &t->samples[t->sample_count];
+
+ smpl->delay = delay;
+ smpl->size = (uint32_t) size;
+ smpl->duration = 0;
+ smpl->timestamp = timestamp;
+ smpl->key = (key ? 1 : 0);
+
+ if (t->sample_count > 0) {
+ smpl = &t->samples[t->sample_count - 1];
+ smpl->duration = timestamp - smpl->timestamp;
+ }
+
+ t->sample_count++;
+ t->mdat_size += (ngx_uint_t) size;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ ngx_chain_t *in)
+{
+ u_char htype;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ if (dacf == NULL || !dacf->dash || ctx == NULL ||
+ codec_ctx == NULL || h->mlen < 2)
+ {
+ return NGX_OK;
+ }
+
+ /* Only AAC is supported */
+
+ if (codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC ||
+ codec_ctx->aac_header == NULL)
+ {
+ return NGX_OK;
+ }
+
+ if (in->buf->last - in->buf->pos < 2) {
+ return NGX_ERROR;
+ }
+
+ /* skip AAC config */
+
+ htype = in->buf->pos[1];
+ if (htype != 1) {
+ return NGX_OK;
+ }
+
+ ctx->has_audio = 1;
+
+ /* skip RTMP & AAC headers */
+
+ in->buf->pos += 2;
+
+ return ngx_rtmp_dash_append(s, in, &ctx->audio, 0, h->timestamp, 0);
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ ngx_chain_t *in)
+{
+ u_char *p;
+ uint8_t ftype, htype;
+ uint32_t delay;
+ ngx_rtmp_dash_ctx_t *ctx;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+ ngx_rtmp_dash_app_conf_t *dacf;
+
+ dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ if (dacf == NULL || !dacf->dash || ctx == NULL || codec_ctx == NULL ||
+ codec_ctx->avc_header == NULL || h->mlen < 5)
+ {
+ return NGX_OK;
+ }
+
+ /* Only H264 is supported */
+
+ if (codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264) {
+ return NGX_OK;
+ }
+
+ if (in->buf->last - in->buf->pos < 5) {
+ return NGX_ERROR;
+ }
+
+ ftype = (in->buf->pos[0] & 0xf0) >> 4;
+
+ /* skip AVC config */
+
+ htype = in->buf->pos[1];
+ if (htype != 1) {
+ return NGX_OK;
+ }
+
+ p = (u_char *) &delay;
+
+ p[0] = in->buf->pos[4];
+ p[1] = in->buf->pos[3];
+ p[2] = in->buf->pos[2];
+ p[3] = 0;
+
+ ctx->has_video = 1;
+
+ /* skip RTMP & H264 headers */
+
+ in->buf->pos += 5;
+
+ return ngx_rtmp_dash_append(s, in, &ctx->video, ftype == 1, h->timestamp,
+ delay);
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v)
+{
+ return next_stream_begin(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v)
+{
+ ngx_rtmp_dash_close_fragments(s);
+
+ return next_stream_eof(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_cleanup_dir(ngx_str_t *ppath, ngx_msec_t playlen)
+{
+ time_t mtime, max_age;
+ u_char *p;
+ u_char path[NGX_MAX_PATH + 1], mpd_path[NGX_MAX_PATH + 1];
+ ngx_dir_t dir;
+ ngx_err_t err;
+ ngx_str_t name, spath, mpd;
+ ngx_int_t nentries, nerased;
+ ngx_file_info_t fi;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
+ "dash: cleanup path='%V' playlen=%M", ppath, playlen);
+
+ if (ngx_open_dir(ppath, &dir) != NGX_OK) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, ngx_errno,
+ "dash: cleanup open dir failed '%V'", ppath);
+ return NGX_ERROR;
+ }
+
+ nentries = 0;
+ nerased = 0;
+
+ for ( ;; ) {
+ ngx_set_errno(0);
+
+ if (ngx_read_dir(&dir) == NGX_ERROR) {
+ err = ngx_errno;
+
+ if (ngx_close_dir(&dir) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
+ "dash: cleanup " ngx_close_dir_n " \"%V\" failed",
+ ppath);
+ }
+
+ if (err == NGX_ENOMOREFILES) {
+ return nentries - nerased;
+ }
+
+ ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, err,
+ "dash: cleanup " ngx_read_dir_n
+ " '%V' failed", ppath);
+ return NGX_ERROR;
+ }
+
+ name.data = ngx_de_name(&dir);
+ if (name.data[0] == '.') {
+ continue;
+ }
+
+ name.len = ngx_de_namelen(&dir);
+
+ p = ngx_snprintf(path, sizeof(path) - 1, "%V/%V", ppath, &name);
+ *p = 0;
+
+ spath.data = path;
+ spath.len = p - path;
+
+ nentries++;
+
+ if (!dir.valid_info && ngx_de_info(path, &dir) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
+ "dash: cleanup " ngx_de_info_n " \"%V\" failed",
+ &spath);
+
+ continue;
+ }
+
+ if (ngx_de_is_dir(&dir)) {
+
+ if (ngx_rtmp_dash_cleanup_dir(&spath, playlen) == 0) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
+ "dash: cleanup dir '%V'", &name);
+
+ /*
+ * null-termination gets spoiled in win32
+ * version of ngx_open_dir
+ */
+
+ *p = 0;
+
+ if (ngx_delete_dir(path) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno,
+ "dash: cleanup " ngx_delete_dir_n
+ " failed on '%V'", &spath);
+ } else {
+ nerased++;
+ }
+ }
+
+ continue;
+ }
+
+ if (!ngx_de_is_file(&dir)) {
+ continue;
+ }
+
+ if (name.len >= 8 && name.data[name.len - 8] == 'i' &&
+ name.data[name.len - 7] == 'n' &&
+ name.data[name.len - 6] == 'i' &&
+ name.data[name.len - 5] == 't' &&
+ name.data[name.len - 4] == '.' &&
+ name.data[name.len - 3] == 'm' &&
+ name.data[name.len - 2] == '4')
+ {
+ if (name.len == 8) {
+ ngx_str_set(&mpd, "index");
+ } else {
+ mpd.data = name.data;
+ mpd.len = name.len - 9;
+ }
+
+ p = ngx_snprintf(mpd_path, sizeof(mpd_path) - 1, "%V/%V.mpd",
+ ppath, &mpd);
+ *p = 0;
+
+ if (ngx_file_info(mpd_path, &fi) != NGX_FILE_ERROR) {
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
+ "dash: cleanup '%V' delayed, mpd exists '%s'",
+ &name, mpd_path);
+ continue;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
+ "dash: cleanup '%V' allowed, mpd missing '%s'",
+ &name, mpd_path);
+
+ max_age = 0;
+
+ } else if (name.len >= 4 && name.data[name.len - 4] == '.' &&
+ name.data[name.len - 3] == 'm' &&
+ name.data[name.len - 2] == '4' &&
+ name.data[name.len - 1] == 'v')
+ {
+ max_age = playlen / 500;
+
+ } else if (name.len >= 4 && name.data[name.len - 4] == '.' &&
+ name.data[name.len - 3] == 'm' &&
+ name.data[name.len - 2] == '4' &&
+ name.data[name.len - 1] == 'a')
+ {
+ max_age = playlen / 500;
+
+ } else if (name.len >= 4 && name.data[name.len - 4] == '.' &&
+ name.data[name.len - 3] == 'm' &&
+ name.data[name.len - 2] == 'p' &&
+ name.data[name.len - 1] == 'd')
+ {
+ max_age = playlen / 500;
+
+ } else if (name.len >= 4 && name.data[name.len - 4] == '.' &&
+ name.data[name.len - 3] == 'r' &&
+ name.data[name.len - 2] == 'a' &&
+ name.data[name.len - 1] == 'w')
+ {
+ max_age = playlen / 1000;
+
+ } else {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
+ "dash: cleanup skip unknown file type '%V'", &name);
+ continue;
+ }
+
+ mtime = ngx_de_mtime(&dir);
+ if (mtime + max_age > ngx_cached_time->sec) {
+ continue;
+ }
+
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
+ "dash: cleanup '%V' mtime=%T age=%T",
+ &name, mtime, ngx_cached_time->sec - mtime);
+
+ if (ngx_delete_file(path) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno,
+ "dash: cleanup " ngx_delete_file_n " failed on '%V'",
+ &spath);
+ continue;
+ }
+
+ nerased++;
+ }
+}
+
+
+static time_t
+ngx_rtmp_dash_cleanup(void *data)
+{
+ ngx_rtmp_dash_cleanup_t *cleanup = data;
+
+ ngx_rtmp_dash_cleanup_dir(&cleanup->path, cleanup->playlen);
+
+ return cleanup->playlen / 500;
+}
+
+
+static void *
+ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf)
+{
+ ngx_rtmp_dash_app_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dash_app_conf_t));
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ conf->dash = NGX_CONF_UNSET;
+ conf->fraglen = NGX_CONF_UNSET_MSEC;
+ conf->playlen = NGX_CONF_UNSET_MSEC;
+ conf->cleanup = NGX_CONF_UNSET;
+ conf->nested = NGX_CONF_UNSET;
+
+ return conf;
+}
+
+
+static char *
+ngx_rtmp_dash_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_rtmp_dash_app_conf_t *prev = parent;
+ ngx_rtmp_dash_app_conf_t *conf = child;
+ ngx_rtmp_dash_cleanup_t *cleanup;
+
+ ngx_conf_merge_value(conf->dash, prev->dash, 0);
+ ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000);
+ ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000);
+ ngx_conf_merge_value(conf->cleanup, prev->cleanup, 1);
+ ngx_conf_merge_value(conf->nested, prev->nested, 0);
+
+ if (conf->fraglen) {
+ conf->winfrags = conf->playlen / conf->fraglen;
+ }
+
+ /* schedule cleanup */
+
+ if (conf->dash && conf->path.len && conf->cleanup) {
+ if (conf->path.data[conf->path.len - 1] == '/') {
+ conf->path.len--;
+ }
+
+ cleanup = ngx_pcalloc(cf->pool, sizeof(*cleanup));
+ if (cleanup == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ cleanup->path = conf->path;
+ cleanup->playlen = conf->playlen;
+
+ conf->slot = ngx_pcalloc(cf->pool, sizeof(*conf->slot));
+ if (conf->slot == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->slot->manager = ngx_rtmp_dash_cleanup;
+ conf->slot->name = conf->path;
+ conf->slot->data = cleanup;
+ conf->slot->conf_file = cf->conf_file->file.name.data;
+ conf->slot->line = cf->conf_file->line;
+
+ if (ngx_add_path(cf, &conf->slot) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ ngx_conf_merge_str_value(conf->path, prev->path, "");
+
+ return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_dash_postconfiguration(ngx_conf_t *cf)
+{
+ ngx_rtmp_handler_pt *h;
+ ngx_rtmp_core_main_conf_t *cmcf;
+
+ cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
+
+ h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]);
+ *h = ngx_rtmp_dash_video;
+
+ h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]);
+ *h = ngx_rtmp_dash_audio;
+
+ next_publish = ngx_rtmp_publish;
+ ngx_rtmp_publish = ngx_rtmp_dash_publish;
+
+ next_close_stream = ngx_rtmp_close_stream;
+ ngx_rtmp_close_stream = ngx_rtmp_dash_close_stream;
+
+ next_stream_begin = ngx_rtmp_stream_begin;
+ ngx_rtmp_stream_begin = ngx_rtmp_dash_stream_begin;
+
+ next_stream_eof = ngx_rtmp_stream_eof;
+ ngx_rtmp_stream_eof = ngx_rtmp_dash_stream_eof;
+
+ return NGX_OK;
+}
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/dash/ngx_rtmp_mp4.c
^
|
@@ -0,0 +1,1167 @@
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include "ngx_rtmp_mp4.h"
+#include <ngx_rtmp_codec_module.h>
+
+
+static ngx_int_t
+ngx_rtmp_mp4_field_32(ngx_buf_t *b, uint32_t n)
+{
+ u_char bytes[4];
+
+ bytes[0] = ((uint32_t) n >> 24) & 0xFF;
+ bytes[1] = ((uint32_t) n >> 16) & 0xFF;
+ bytes[2] = ((uint32_t) n >> 8) & 0xFF;
+ bytes[3] = (uint32_t) n & 0xFF;
+
+ if (b->last + sizeof(bytes) > b->end) {
+ return NGX_ERROR;
+ }
+
+ b->last = ngx_cpymem(b->last, bytes, sizeof(bytes));
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_field_24(ngx_buf_t *b, uint32_t n)
+{
+ u_char bytes[3];
+
+ bytes[0] = ((uint32_t) n >> 16) & 0xFF;
+ bytes[1] = ((uint32_t) n >> 8) & 0xFF;
+ bytes[2] = (uint32_t) n & 0xFF;
+
+ if (b->last + sizeof(bytes) > b->end) {
+ return NGX_ERROR;
+ }
+
+ b->last = ngx_cpymem(b->last, bytes, sizeof(bytes));
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_field_16(ngx_buf_t *b, uint16_t n)
+{
+ u_char bytes[2];
+
+ bytes[0] = ((uint32_t) n >> 8) & 0xFF;
+ bytes[1] = (uint32_t) n & 0xFF;
+
+ if (b->last + sizeof(bytes) > b->end) {
+ return NGX_ERROR;
+ }
+
+ b->last = ngx_cpymem(b->last, bytes, sizeof(bytes));
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_field_8(ngx_buf_t *b, uint8_t n)
+{
+ u_char bytes[1];
+
+ bytes[0] = n & 0xFF;
+
+ if (b->last + sizeof(bytes) > b->end) {
+ return NGX_ERROR;
+ }
+
+ b->last = ngx_cpymem(b->last, bytes, sizeof(bytes));
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_put_descr(ngx_buf_t *b, int tag, size_t size)
+{
+ ngx_rtmp_mp4_field_8(b, (uint8_t) tag);
+ ngx_rtmp_mp4_field_8(b, size & 0x7F);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_data(ngx_buf_t *b, void *data, size_t n)
+{
+ if (b->last + n > b->end) {
+ return NGX_ERROR;
+ }
+
+ b->last = ngx_cpymem(b->last, (u_char *) data, n);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_box(ngx_buf_t *b, const char box[4])
+{
+ if (b->last + 4 > b->end) {
+ return NGX_ERROR;
+ }
+
+ b->last = ngx_cpymem(b->last, (u_char *) box, 4);
+
+ return NGX_OK;
+}
+
+
+static u_char *
+ngx_rtmp_mp4_start_box(ngx_buf_t *b, const char box[4])
+{
+ u_char *p;
+
+ p = b->last;
+
+ if (ngx_rtmp_mp4_field_32(b, 0) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_rtmp_mp4_box(b, box) != NGX_OK) {
+ return NULL;
+ }
+
+ return p;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_update_box_size(ngx_buf_t *b, u_char *p)
+{
+ u_char *curpos;
+
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ curpos = b->last;
+
+ b->last = p;
+
+ ngx_rtmp_mp4_field_32(b, (uint32_t) (curpos - p));
+
+ b->last = curpos;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_matrix(ngx_buf_t *buf, uint32_t a, uint32_t b, uint32_t c,
+ uint32_t d, uint32_t tx, uint32_t ty)
+{
+
+/*
+ * transformation matrix
+ * |a b u|
+ * |c d v|
+ * |tx ty w|
+ */
+
+ ngx_rtmp_mp4_field_32(buf, a << 16); /* 16.16 format */
+ ngx_rtmp_mp4_field_32(buf, b << 16); /* 16.16 format */
+ ngx_rtmp_mp4_field_32(buf, 0); /* u in 2.30 format */
+ ngx_rtmp_mp4_field_32(buf, c << 16); /* 16.16 format */
+ ngx_rtmp_mp4_field_32(buf, d << 16); /* 16.16 format */
+ ngx_rtmp_mp4_field_32(buf, 0); /* v in 2.30 format */
+ ngx_rtmp_mp4_field_32(buf, tx << 16); /* 16.16 format */
+ ngx_rtmp_mp4_field_32(buf, ty << 16); /* 16.16 format */
+ ngx_rtmp_mp4_field_32(buf, 1 << 30); /* w in 2.30 format */
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "ftyp");
+
+ /* major brand */
+ ngx_rtmp_mp4_box(b, "iso6");
+
+ /* minor version */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* compatible brands */
+ ngx_rtmp_mp4_box(b, "isom");
+ ngx_rtmp_mp4_box(b, "iso6");
+ ngx_rtmp_mp4_box(b, "dash");
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_rtmp_mp4_write_styp(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "styp");
+
+ /* major brand */
+ ngx_rtmp_mp4_box(b, "iso6");
+
+ /* minor version */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* compatible brands */
+ ngx_rtmp_mp4_box(b, "isom");
+ ngx_rtmp_mp4_box(b, "iso6");
+ ngx_rtmp_mp4_box(b, "dash");
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "mvhd");
+
+ /* version */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* creation time */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* modification time */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* timescale */
+ ngx_rtmp_mp4_field_32(b, 1000);
+
+ /* duration */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0x00010000);
+ ngx_rtmp_mp4_field_16(b, 0x0100);
+ ngx_rtmp_mp4_field_16(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ ngx_rtmp_mp4_write_matrix(b, 1, 0, 0, 1, 0, 0);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* next track id */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_tkhd(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ pos = ngx_rtmp_mp4_start_box(b, "tkhd");
+
+ /* version */
+ ngx_rtmp_mp4_field_8(b, 0);
+
+ /* flags: TrackEnabled */
+ ngx_rtmp_mp4_field_24(b, 0x0000000f);
+
+ /* creation time */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* modification time */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* track id */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* duration */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_16(b, ttype == NGX_RTMP_MP4_VIDEO_TRACK ? 0 : 0x0100);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ ngx_rtmp_mp4_write_matrix(b, 1, 0, 0, 1, 0, 0);
+
+ if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) {
+ ngx_rtmp_mp4_field_32(b, (uint32_t) codec_ctx->width << 16);
+ ngx_rtmp_mp4_field_32(b, (uint32_t) codec_ctx->height << 16);
+ } else {
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ }
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "mdhd");
+
+ /* version */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* creation time */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* modification time */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* time scale*/
+ ngx_rtmp_mp4_field_32(b, 1000);
+
+ /* duration */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* lanuguage */
+ ngx_rtmp_mp4_field_16(b, 0x15C7);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_hdlr(ngx_buf_t *b, ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "hdlr");
+
+ /* version and flags */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* pre defined */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) {
+ ngx_rtmp_mp4_box(b, "vide");
+ } else {
+ ngx_rtmp_mp4_box(b, "soun");
+ }
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) {
+ /* video handler string, NULL-terminated */
+ ngx_rtmp_mp4_data(b, "VideoHandler", sizeof("VideoHandler"));
+ } else {
+ /* sound handler string, NULL-terminated */
+ ngx_rtmp_mp4_data(b, "SoundHandler", sizeof("SoundHandler"));
+ }
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_vmhd(ngx_buf_t *b)
+{
+ /* size is always 20, apparently */
+ ngx_rtmp_mp4_field_32(b, 20);
+
+ ngx_rtmp_mp4_box(b, "vmhd");
+
+ /* version and flags */
+ ngx_rtmp_mp4_field_32(b, 0x01);
+
+ /* reserved (graphics mode=copy) */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_smhd(ngx_buf_t *b)
+{
+ /* size is always 16, apparently */
+ ngx_rtmp_mp4_field_32(b, 16);
+
+ ngx_rtmp_mp4_box(b, "smhd");
+
+ /* version and flags */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* reserved (balance normally=0) */
+ ngx_rtmp_mp4_field_16(b, 0);
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_dref(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "dref");
+
+ /* version and flags */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* entry count */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* url size */
+ ngx_rtmp_mp4_field_32(b, 0xc);
+
+ ngx_rtmp_mp4_box(b, "url ");
+
+ /* version and flags */
+ ngx_rtmp_mp4_field_32(b, 0x00000001);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_dinf(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "dinf");
+
+ ngx_rtmp_mp4_write_dref(b);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_avcc(ngx_rtmp_session_t *s, ngx_buf_t *b)
+{
+ u_char *pos, *p;
+ ngx_chain_t *in;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ if (codec_ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ in = codec_ctx->avc_header;
+ if (in == NULL) {
+ return NGX_ERROR;
+ }
+
+ pos = ngx_rtmp_mp4_start_box(b, "avcC");
+
+ /* assume config fits one chunk (highly probable) */
+
+ /*
+ * Skip:
+ * - flv fmt
+ * - H264 CONF/PICT (0x00)
+ * - 0
+ * - 0
+ * - 0
+ */
+
+ p = in->buf->pos + 5;
+
+ if (p < in->buf->last) {
+ ngx_rtmp_mp4_data(b, p, (size_t) (in->buf->last - p));
+ } else {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "dash: invalid avcc received");
+ }
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_video(ngx_rtmp_session_t *s, ngx_buf_t *b)
+{
+ u_char *pos;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ pos = ngx_rtmp_mp4_start_box(b, "avc1");
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ /* data reference index */
+ ngx_rtmp_mp4_field_16(b, 1);
+
+ /* codec stream version & revision */
+ ngx_rtmp_mp4_field_16(b, 0);
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* width & height */
+ ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->width);
+ ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->height);
+
+ /* horizontal & vertical resolutions 72 dpi */
+ ngx_rtmp_mp4_field_32(b, 0x00480000);
+ ngx_rtmp_mp4_field_32(b, 0x00480000);
+
+ /* data size */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* frame count */
+ ngx_rtmp_mp4_field_16(b, 1);
+
+ /* compressor name */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_16(b, 0x18);
+ ngx_rtmp_mp4_field_16(b, 0xffff);
+
+ ngx_rtmp_mp4_write_avcc(s, b);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_esds(ngx_rtmp_session_t *s, ngx_buf_t *b)
+{
+ size_t dsi_len;
+ u_char *pos, *dsi;
+ ngx_buf_t *db;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ if (codec_ctx == NULL || codec_ctx->aac_header == NULL) {
+ return NGX_ERROR;
+ }
+
+ db = codec_ctx->aac_header->buf;
+ if (db == NULL) {
+ return NGX_ERROR;
+ }
+
+ dsi = db->pos + 2;
+ if (dsi > db->last) {
+ return NGX_ERROR;
+ }
+
+ dsi_len = db->last - dsi;
+
+ pos = ngx_rtmp_mp4_start_box(b, "esds");
+
+ /* version */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+
+ /* ES Descriptor */
+
+ ngx_rtmp_mp4_put_descr(b, 0x03, 23 + dsi_len);
+
+ /* ES_ID */
+ ngx_rtmp_mp4_field_16(b, 1);
+
+ /* flags */
+ ngx_rtmp_mp4_field_8(b, 0);
+
+
+ /* DecoderConfig Descriptor */
+
+ ngx_rtmp_mp4_put_descr(b, 0x04, 15 + dsi_len);
+
+ /* objectTypeIndication: Audio ISO/IEC 14496-3 (AAC) */
+ ngx_rtmp_mp4_field_8(b, 0x40);
+
+ /* streamType: AudioStream */
+ ngx_rtmp_mp4_field_8(b, 0x15);
+
+ /* bufferSizeDB */
+ ngx_rtmp_mp4_field_24(b, 0);
+
+ /* maxBitrate */
+ ngx_rtmp_mp4_field_32(b, 0x0001F151);
+
+ /* avgBitrate */
+ ngx_rtmp_mp4_field_32(b, 0x0001F14D);
+
+
+ /* DecoderSpecificInfo Descriptor */
+
+ ngx_rtmp_mp4_put_descr(b, 0x05, dsi_len);
+ ngx_rtmp_mp4_data(b, dsi, dsi_len);
+
+
+ /* SL Descriptor */
+
+ ngx_rtmp_mp4_put_descr(b, 0x06, 1);
+ ngx_rtmp_mp4_field_8(b, 0x02);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_audio(ngx_rtmp_session_t *s, ngx_buf_t *b)
+{
+ u_char *pos;
+ ngx_rtmp_codec_ctx_t *codec_ctx;
+
+ codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ pos = ngx_rtmp_mp4_start_box(b, "mp4a");
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ /* data reference index */
+ ngx_rtmp_mp4_field_16(b, 1);
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* channel count */
+ ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->audio_channels);
+
+ /* sample size */
+ ngx_rtmp_mp4_field_16(b, (uint16_t) (codec_ctx->sample_size * 8));
+
+ /* reserved */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* time scale */
+ ngx_rtmp_mp4_field_16(b, 1000);
+
+ /* sample rate */
+ ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->sample_rate);
+
+ ngx_rtmp_mp4_write_esds(s, b);
+#if 0
+ /* tag size*/
+ ngx_rtmp_mp4_field_32(b, 8);
+
+ /* null tag */
+ ngx_rtmp_mp4_field_32(b, 0);
+#endif
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_stsd(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "stsd");
+
+ /* version & flags */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* entry count */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) {
+ ngx_rtmp_mp4_write_video(s, b);
+ } else {
+ ngx_rtmp_mp4_write_audio(s, b);
+ }
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_stts(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "stts");
+
+ ngx_rtmp_mp4_field_32(b, 0); /* version */
+ ngx_rtmp_mp4_field_32(b, 0); /* entry count */
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_stsc(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "stsc");
+
+ ngx_rtmp_mp4_field_32(b, 0); /* version */
+ ngx_rtmp_mp4_field_32(b, 0); /* entry count */
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_stsz(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "stsz");
+
+ ngx_rtmp_mp4_field_32(b, 0); /* version */
+ ngx_rtmp_mp4_field_32(b, 0); /* entry count */
+ ngx_rtmp_mp4_field_32(b, 0); /* moar zeros */
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_stco(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "stco");
+
+ ngx_rtmp_mp4_field_32(b, 0); /* version */
+ ngx_rtmp_mp4_field_32(b, 0); /* entry count */
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_stbl(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "stbl");
+
+ ngx_rtmp_mp4_write_stsd(s, b, ttype);
+ ngx_rtmp_mp4_write_stts(b);
+ ngx_rtmp_mp4_write_stsc(b);
+ ngx_rtmp_mp4_write_stsz(b);
+ ngx_rtmp_mp4_write_stco(b);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_minf(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "minf");
+
+ if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) {
+ ngx_rtmp_mp4_write_vmhd(b);
+ } else {
+ ngx_rtmp_mp4_write_smhd(b);
+ }
+
+ ngx_rtmp_mp4_write_dinf(b);
+ ngx_rtmp_mp4_write_stbl(s, b, ttype);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_mdia(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "mdia");
+
+ ngx_rtmp_mp4_write_mdhd(b);
+ ngx_rtmp_mp4_write_hdlr(b, ttype);
+ ngx_rtmp_mp4_write_minf(s, b, ttype);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+static ngx_int_t
+ngx_rtmp_mp4_write_trak(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "trak");
+
+ ngx_rtmp_mp4_write_tkhd(s, b, ttype);
+ ngx_rtmp_mp4_write_mdia(s, b, ttype);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_mvex(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "mvex");
+
+ ngx_rtmp_mp4_field_32(b, 0x20);
+
+ ngx_rtmp_mp4_box(b, "trex");
+
+ /* version & flags */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* track id */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* default sample description index */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* default sample duration */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* default sample size, 1024 for AAC */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* default sample flags, key on */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "moov");
+
+ ngx_rtmp_mp4_write_mvhd(b);
+ ngx_rtmp_mp4_write_mvex(b);
+ ngx_rtmp_mp4_write_trak(s, b, ttype);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "tfhd");
+
+ /* version & flags */
+ ngx_rtmp_mp4_field_32(b, 0x00020000);
+
+ /* track id */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, uint32_t earliest_pres_time)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "tfdt");
+
+ /* version == 1 aka 64 bit integer */
+ ngx_rtmp_mp4_field_32(b, 0x00000000);
+ ngx_rtmp_mp4_field_32(b, earliest_pres_time);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count,
+ ngx_rtmp_mp4_sample_t *samples, ngx_uint_t sample_mask, u_char *moof_pos)
+{
+ u_char *pos;
+ uint32_t i, offset, nitems, flags;
+
+ pos = ngx_rtmp_mp4_start_box(b, "trun");
+
+ nitems = 0;
+
+ /* data offset present */
+ flags = 0x01;
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_DURATION) {
+ nitems++;
+ flags |= 0x000100;
+ }
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_SIZE) {
+ nitems++;
+ flags |= 0x000200;
+ }
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_KEY) {
+ nitems++;
+ flags |= 0x000400;
+ }
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_DELAY) {
+ nitems++;
+ flags |= 0x000800;
+ }
+
+ offset = (pos - moof_pos) + 20 + (sample_count * nitems * 4) + 8;
+
+ ngx_rtmp_mp4_field_32(b, flags);
+ ngx_rtmp_mp4_field_32(b, sample_count);
+ ngx_rtmp_mp4_field_32(b, offset);
+
+ for (i = 0; i < sample_count; i++, samples++) {
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_DURATION) {
+ ngx_rtmp_mp4_field_32(b, samples->duration);
+ }
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_SIZE) {
+ ngx_rtmp_mp4_field_32(b, samples->size);
+ }
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_KEY) {
+ ngx_rtmp_mp4_field_32(b, samples->key ? 0x00000000 : 0x00010000);
+ }
+
+ if (sample_mask & NGX_RTMP_MP4_SAMPLE_DELAY) {
+ ngx_rtmp_mp4_field_32(b, samples->delay);
+ }
+ }
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_traf(ngx_buf_t *b, uint32_t earliest_pres_time,
+ uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples,
+ ngx_uint_t sample_mask, u_char *moof_pos)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "traf");
+
+ ngx_rtmp_mp4_write_tfhd(b);
+ ngx_rtmp_mp4_write_tfdt(b, earliest_pres_time);
+ ngx_rtmp_mp4_write_trun(b, sample_count, samples, sample_mask, moof_pos);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_write_mfhd(ngx_buf_t *b, uint32_t index)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "mfhd");
+
+ /* don't know what this is */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* fragment index. */
+ ngx_rtmp_mp4_field_32(b, index);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_rtmp_mp4_write_sidx(ngx_buf_t *b, ngx_uint_t reference_size,
+ uint32_t earliest_pres_time, uint32_t latest_pres_time)
+{
+ u_char *pos;
+ uint32_t duration;
+
+ duration = latest_pres_time - earliest_pres_time;
+
+ pos = ngx_rtmp_mp4_start_box(b, "sidx");
+
+ /* version */
+ ngx_rtmp_mp4_field_32(b, 0);
+
+ /* reference id */
+ ngx_rtmp_mp4_field_32(b, 1);
+
+ /* timescale */
+ ngx_rtmp_mp4_field_32(b, 1000);
+
+ /* earliest presentation time */
+ ngx_rtmp_mp4_field_32(b, earliest_pres_time);
+
+ /* first offset */
+ ngx_rtmp_mp4_field_32(b, duration); /*TODO*/
+
+ /* reserved */
+ ngx_rtmp_mp4_field_16(b, 0);
+
+ /* reference count = 1 */
+ ngx_rtmp_mp4_field_16(b, 1);
+
+ /* 1st bit is reference type, the rest is reference size */
+ ngx_rtmp_mp4_field_32(b, reference_size);
+
+ /* subsegment duration */
+ ngx_rtmp_mp4_field_32(b, duration);
+
+ /* first bit is startsWithSAP (=1), next 3 bits are SAP type (=001) */
+ ngx_rtmp_mp4_field_8(b, 0x90);
+
+ /* SAP delta time */
+ ngx_rtmp_mp4_field_24(b, 0);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time,
+ uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples,
+ ngx_uint_t sample_mask, uint32_t index)
+{
+ u_char *pos;
+
+ pos = ngx_rtmp_mp4_start_box(b, "moof");
+
+ ngx_rtmp_mp4_write_mfhd(b, index);
+ ngx_rtmp_mp4_write_traf(b, earliest_pres_time, sample_count, samples,
+ sample_mask, pos);
+
+ ngx_rtmp_mp4_update_box_size(b, pos);
+
+ return NGX_OK;
+}
+
+
+ngx_uint_t
+ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size)
+{
+ ngx_rtmp_mp4_field_32(b, size);
+
+ ngx_rtmp_mp4_box(b, "mdat");
+
+ return NGX_OK;
+}
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/dash/ngx_rtmp_mp4.h
^
|
@@ -0,0 +1,52 @@
+
+
+#ifndef _NGX_RTMP_MP4_H_INCLUDED_
+#define _NGX_RTMP_MP4_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_rtmp.h>
+
+
+#define NGX_RTMP_MP4_SAMPLE_SIZE 0x01
+#define NGX_RTMP_MP4_SAMPLE_DURATION 0x02
+#define NGX_RTMP_MP4_SAMPLE_DELAY 0x04
+#define NGX_RTMP_MP4_SAMPLE_KEY 0x08
+
+
+typedef struct {
+ uint32_t size;
+ uint32_t duration;
+ uint32_t delay;
+ uint32_t timestamp;
+ unsigned key:1;
+} ngx_rtmp_mp4_sample_t;
+
+
+typedef enum {
+ NGX_RTMP_MP4_FILETYPE_INIT,
+ NGX_RTMP_MP4_FILETYPE_SEG
+} ngx_rtmp_mp4_file_type_t;
+
+
+typedef enum {
+ NGX_RTMP_MP4_VIDEO_TRACK,
+ NGX_RTMP_MP4_AUDIO_TRACK
+} ngx_rtmp_mp4_track_type_t;
+
+
+ngx_int_t ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b);
+ngx_int_t ngx_rtmp_mp4_write_styp(ngx_buf_t *b);
+ngx_int_t ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b,
+ ngx_rtmp_mp4_track_type_t ttype);
+ngx_int_t ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time,
+ uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples,
+ ngx_uint_t sample_mask, uint32_t index);
+ngx_int_t ngx_rtmp_mp4_write_sidx(ngx_buf_t *b,
+ ngx_uint_t reference_size, uint32_t earliest_pres_time,
+ uint32_t latest_pres_time);
+ngx_uint_t ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size);
+
+
+#endif /* _NGX_RTMP_MP4_H_INCLUDED_ */
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/hls/ngx_rtmp_hls_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2013 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -21,7 +22,7 @@
void *conf);
static ngx_int_t ngx_rtmp_hls_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_rtmp_hls_flush_audio(ngx_rtmp_session_t *s);
@@ -121,21 +122,21 @@
{ ngx_string("timestamp"), NGX_RTMP_HLS_NAMING_TIMESTAMP },
{ ngx_string("system"), NGX_RTMP_HLS_NAMING_SYSTEM },
{ ngx_null_string, 0 }
-};
+};
static ngx_conf_enum_t ngx_rtmp_hls_slicing_slots[] = {
{ ngx_string("plain"), NGX_RTMP_HLS_SLICING_PLAIN },
{ ngx_string("aligned"), NGX_RTMP_HLS_SLICING_ALIGNED },
{ ngx_null_string, 0 }
-};
+};
static ngx_conf_enum_t ngx_rtmp_hls_type_slots[] = {
{ ngx_string("live"), NGX_RTMP_HLS_TYPE_LIVE },
{ ngx_string("event"), NGX_RTMP_HLS_TYPE_EVENT },
{ ngx_null_string, 0 }
-};
+};
static ngx_command_t ngx_rtmp_hls_commands[] = {
@@ -264,91 +265,36 @@
static ngx_rtmp_module_t ngx_rtmp_hls_module_ctx = {
- NULL, /* preconfiguration */
- ngx_rtmp_hls_postconfiguration, /* postconfiguration */
+ NULL, /* preconfiguration */
+ ngx_rtmp_hls_postconfiguration, /* postconfiguration */
- NULL, /* create main configuration */
- NULL, /* init main configuration */
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
- ngx_rtmp_hls_create_app_conf, /* create location configuration */
- ngx_rtmp_hls_merge_app_conf, /* merge location configuration */
+ ngx_rtmp_hls_create_app_conf, /* create location configuration */
+ ngx_rtmp_hls_merge_app_conf, /* merge location configuration */
};
ngx_module_t ngx_rtmp_hls_module = {
- NGX_MODULE_V1,
- &ngx_rtmp_hls_module_ctx, /* module context */
- ngx_rtmp_hls_commands, /* module directives */
- NGX_RTMP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
+ NGX_MODULE_V1,
+ &ngx_rtmp_hls_module_ctx, /* module context */
+ ngx_rtmp_hls_commands, /* module directives */
+ NGX_RTMP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
};
-static ngx_int_t
-ngx_rtmp_hls_create_parent_dir(ngx_rtmp_session_t *s)
-{
- ngx_rtmp_hls_app_conf_t *hacf;
- ngx_rtmp_hls_ctx_t *ctx;
- ngx_err_t err;
- size_t len;
- static u_char path[NGX_MAX_PATH + 1];
-
- hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
-
- if (hacf->path.len == 0) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "hls: creating target folder: '%V'", &hacf->path);
-
- if (ngx_create_dir(hacf->path.data, NGX_RTMP_HLS_DIR_ACCESS) != NGX_OK) {
- err = ngx_errno;
- if (err != NGX_EEXIST) {
- ngx_log_error(NGX_LOG_ERR, s->connection->log, err,
- "hls: error creating target folder: '%V'",
- &hacf->path);
- return NGX_ERROR;
- }
- }
-
- if (!hacf->nested) {
- return NGX_OK;
- }
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
-
- len = hacf->path.len;
- if (hacf->path.data[len - 1] == '/') {
- len--;
- }
-
- *ngx_snprintf(path, sizeof(path) - 1, "%*s/%V", len, hacf->path.data,
- &ctx->name) = 0;
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "hls: creating nested folder: '%s'", path);
-
- if (ngx_create_dir(path, NGX_RTMP_HLS_DIR_ACCESS) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
- "hls: error creating nested folder: '%s'", path);
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-
static ngx_rtmp_hls_frag_t *
ngx_rtmp_hls_get_frag(ngx_rtmp_session_t *s, ngx_int_t n)
{
@@ -409,7 +355,7 @@
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
- fd = ngx_open_file(ctx->var_playlist_bak.data, NGX_FILE_WRONLY,
+ fd = ngx_open_file(ctx->var_playlist_bak.data, NGX_FILE_WRONLY,
NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
if (fd == NGX_INVALID_FILE) {
@@ -458,7 +404,7 @@
}
p = ngx_slprintf(p, last, "%s", ".m3u8\n");
-
+
rc = ngx_write_fd(fd, buffer, p - buffer);
if (rc < 0) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
@@ -471,12 +417,12 @@
ngx_close_file(fd);
- rc = ngx_rtmp_hls_rename_file(ctx->var_playlist_bak.data,
- ctx->var_playlist.data);
-
- if (rc != NGX_OK) {
+ if (ngx_rtmp_hls_rename_file(ctx->var_playlist_bak.data,
+ ctx->var_playlist.data)
+ == NGX_FILE_ERROR)
+ {
ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
- "hls: rename failed: '%V'->'%V'",
+ "hls: rename failed: '%V'->'%V'",
&ctx->var_playlist_bak, &ctx->var_playlist);
return NGX_ERROR;
}
@@ -494,7 +440,6 @@
ngx_rtmp_hls_ctx_t *ctx;
ssize_t n;
ngx_rtmp_hls_app_conf_t *hacf;
- ngx_int_t nretry, rc;
ngx_rtmp_hls_frag_t *f;
ngx_uint_t i, max_frag;
ngx_str_t name_part;
@@ -504,26 +449,13 @@
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
- nretry = 0;
-
-retry:
-
- fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY,
+ fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY,
NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
if (fd == NGX_INVALID_FILE) {
-
- if (ngx_errno == NGX_ENOENT && nretry == 0 &&
- ngx_rtmp_hls_create_parent_dir(s) == NGX_OK)
- {
- nretry++;
- goto retry;
- }
-
ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
"hls: " ngx_open_file_n " failed: '%V'",
&ctx->playlist_bak);
-
return NGX_ERROR;
}
@@ -536,7 +468,7 @@
}
}
- p = ngx_snprintf(buffer, sizeof(buffer),
+ p = ngx_snprintf(buffer, sizeof(buffer),
"#EXTM3U\n"
"#EXT-X-VERSION:3\n"
"#EXT-X-MEDIA-SEQUENCE:%uL\n"
@@ -565,7 +497,7 @@
for (i = 0; i < ctx->nfrags; i++) {
f = ngx_rtmp_hls_get_frag(s, i);
- p = ngx_snprintf(buffer, sizeof(buffer),
+ p = ngx_snprintf(buffer, sizeof(buffer),
"%s"
"#EXTINF:%.3f,\n"
"%V%V%s%uL.ts\n",
@@ -589,11 +521,11 @@
ngx_close_file(fd);
- rc = ngx_rtmp_hls_rename_file(ctx->playlist_bak.data, ctx->playlist.data);
-
- if (rc != NGX_OK) {
+ if (ngx_rtmp_hls_rename_file(ctx->playlist_bak.data, ctx->playlist.data)
+ == NGX_FILE_ERROR)
+ {
ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
- "hls: rename failed: '%V'->'%V'",
+ "hls: rename failed: '%V'->'%V'",
&ctx->playlist_bak, &ctx->playlist);
return NGX_ERROR;
}
@@ -607,7 +539,7 @@
static ngx_int_t
-ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n,
+ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n,
ngx_chain_t **in)
{
u_char *last;
@@ -638,7 +570,7 @@
}
pn = last - *src;
-
+
if (dst) {
ngx_memcpy(dst, *src, pn);
dst = (u_char *)dst + pn;
@@ -709,7 +641,7 @@
* - version
* - profile
* - compatibility
- * - level
+ * - level
* - nal bytes
*/
@@ -725,7 +657,7 @@
nnals &= 0x1f; /* 5lsb */
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "h264: SPS number: %uz", nnals);
+ "hls: SPS number: %uz", nnals);
/* SPS */
for (n = 0; ; ++n) {
@@ -739,12 +671,12 @@
ngx_rtmp_rmemcpy(&len, &rlen, 2);
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "h264: header NAL length: %uz", (size_t) len);
+ "hls: header NAL length: %uz", (size_t) len);
/* AnnexB prefix */
if (out->end - out->last < 4) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "h264: too small buffer for header NAL size");
+ "hls: too small buffer for header NAL size");
return NGX_ERROR;
}
@@ -756,7 +688,7 @@
/* NAL body */
if (out->end - out->last < len) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "h264: too small buffer for header NAL");
+ "hls: too small buffer for header NAL");
return NGX_ERROR;
}
@@ -777,7 +709,7 @@
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "h264: PPS number: %uz", nnals);
+ "hls: PPS number: %uz", nnals);
}
return NGX_OK;
@@ -809,7 +741,7 @@
static ngx_int_t
-ngx_rtmp_hls_close_fragment(ngx_rtmp_session_t *s, ngx_int_t discont)
+ngx_rtmp_hls_close_fragment(ngx_rtmp_session_t *s)
{
ngx_rtmp_hls_ctx_t *ctx;
@@ -818,9 +750,8 @@
return NGX_OK;
}
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "hls: close fragment n=%uL, discont=%i",
- ctx->frag, discont);
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "hls: close fragment n=%uL", ctx->frag);
ngx_close_file(ctx->file.fd);
@@ -841,7 +772,6 @@
{
ngx_rtmp_hls_ctx_t *ctx;
ngx_rtmp_hls_frag_t *f;
- ngx_uint_t nretry;
uint64_t id;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
@@ -864,22 +794,10 @@
ngx_str_set(&ctx->file.name, "hls");
- nretry = 0;
-
-retry:
-
ctx->file.fd = ngx_open_file(ctx->stream.data, NGX_FILE_WRONLY,
NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
if (ctx->file.fd == NGX_INVALID_FILE) {
-
- if (ngx_errno == NGX_ENOENT && nretry == 0 &&
- ngx_rtmp_hls_create_parent_dir(s) == NGX_OK)
- {
- nretry++;
- goto retry;
- }
-
ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
"hls: error creating fragment file");
return NGX_ERROR;
@@ -895,7 +813,7 @@
ctx->opened = 1;
f = ngx_rtmp_hls_get_frag(s, ctx->nfrags);
-
+
ngx_memzero(f, sizeof(*f));
f->active = 1;
@@ -955,7 +873,7 @@
p = buffer;
end = buffer + ret;
-
+
for ( ;; ) {
last = ngx_strlchr(p, end, '\n');
@@ -1057,6 +975,103 @@
static ngx_int_t
+ngx_rtmp_hls_ensure_directory(ngx_rtmp_session_t *s)
+{
+ size_t len;
+ ngx_file_info_t fi;
+ ngx_rtmp_hls_ctx_t *ctx;
+ ngx_rtmp_hls_app_conf_t *hacf;
+
+ static u_char path[NGX_MAX_PATH + 1];
+
+ hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
+
+ *ngx_snprintf(path, sizeof(path) - 1, "%V", &hacf->path) = 0;
+
+ if (ngx_file_info(path, &fi) == NGX_FILE_ERROR) {
+
+ if (ngx_errno != NGX_ENOENT) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "hls: " ngx_file_info_n " failed on '%V'",
+ &hacf->path);
+ return NGX_ERROR;
+ }
+
+ /* ENOENT */
+
+ if (ngx_create_dir(path, NGX_RTMP_HLS_DIR_ACCESS) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "hls: " ngx_create_dir_n " failed on '%V'",
+ &hacf->path);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "hls: directory '%V' created", &hacf->path);
+
+ } else {
+
+ if (!ngx_is_dir(&fi)) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "hls: '%V' exists and is not a directory",
+ &hacf->path);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "hls: directory '%V' exists", &hacf->path);
+ }
+
+ if (!hacf->nested) {
+ return NGX_OK;
+ }
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
+
+ len = hacf->path.len;
+ if (hacf->path.data[len - 1] == '/') {
+ len--;
+ }
+
+ *ngx_snprintf(path, sizeof(path) - 1, "%*s/%V", len, hacf->path.data,
+ &ctx->name) = 0;
+
+ if (ngx_file_info(path, &fi) != NGX_FILE_ERROR) {
+
+ if (ngx_is_dir(&fi)) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "hls: directory '%s' exists", path);
+ return NGX_OK;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "hls: '%s' exists and is not a directory", path);
+
+ return NGX_ERROR;
+ }
+
+ if (ngx_errno != NGX_ENOENT) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "hls: " ngx_file_info_n " failed on '%s'", path);
+ return NGX_ERROR;
+ }
+
+ /* NGX_ENOENT */
+
+ if (ngx_create_dir(path, NGX_RTMP_HLS_DIR_ACCESS) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
+ "hls: " ngx_create_dir_n " failed on '%s'", path);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "hls: directory '%s' created", path);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_rtmp_hls_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
{
ngx_rtmp_hls_app_conf_t *hacf;
@@ -1120,7 +1135,7 @@
ctx->name.len = ngx_strlen(v->name);
ctx->name.data = ngx_palloc(s->connection->pool, ctx->name.len + 1);
-
+
if (ctx->name.data == NULL) {
return NGX_ERROR;
}
@@ -1141,9 +1156,11 @@
p = ngx_cpymem(p, ctx->name.data, ctx->name.len);
- /* ctx->stream_path holds initial part of stream file path
+ /*
+ * ctx->stream holds initial part of stream file path
* however the space for the whole stream path
- * is allocated */
+ * is allocated
+ */
ctx->stream.len = p - ctx->playlist.data + 1;
ctx->stream.data = ngx_palloc(s->connection->pool,
@@ -1182,7 +1199,7 @@
sizeof(".bak") - 1;
ctx->var_playlist_bak.data = ngx_palloc(s->connection->pool,
ctx->var_playlist_bak.len + 1);
-
+
pp = ngx_cpymem(ctx->var_playlist_bak.data,
ctx->var_playlist.data,
ctx->var_playlist.len);
@@ -1193,7 +1210,7 @@
}
}
}
-
+
/* playlist path */
@@ -1209,9 +1226,9 @@
/* playlist bak (new playlist) path */
- ctx->playlist_bak.data = ngx_palloc(s->connection->pool,
+ ctx->playlist_bak.data = ngx_palloc(s->connection->pool,
ctx->playlist.len + sizeof(".bak"));
- p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data,
+ p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data,
ctx->playlist.len);
p = ngx_cpymem(p, ".bak", sizeof(".bak") - 1);
@@ -1227,6 +1244,10 @@
ngx_rtmp_hls_restore_stream(s);
}
+ if (ngx_rtmp_hls_ensure_directory(s) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
next:
return next_publish(s, v);
}
@@ -1247,9 +1268,9 @@
}
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "hls: delete stream");
+ "hls: close stream");
- ngx_rtmp_hls_close_fragment(s, 1);
+ ngx_rtmp_hls_close_fragment(s);
next:
return next_close_stream(s, v);
@@ -1291,7 +1312,7 @@
if (*objtype > 4) {
- /*
+ /*
* Mark all extended profiles as LC
* to make Android as happy as possible.
*/
@@ -1326,22 +1347,24 @@
ngx_msec_t ts_frag_len;
ngx_int_t same_frag;
ngx_buf_t *b;
+ int64_t d;
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
-
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
-
f = NULL;
if (ctx->opened) {
-
f = ngx_rtmp_hls_get_frag(s, ctx->nfrags);
- f->duration = (ts - ctx->frag_ts) / 90000.;
+ d = (int64_t) (ts - ctx->frag_ts);
- if (f->duration * 1000 > hacf->max_fraglen) {
+ if (d > (int64_t) hacf->max_fraglen * 90 || d < -90000) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "hls: max fragment length reached");
+ "hls: max fragment length reached: %.3f sec, ",
+ f->duration);
boundary = 1;
+
+ } else {
+ f->duration = (ts - ctx->frag_ts) / 90000.;
}
}
@@ -1370,7 +1393,7 @@
}
if (boundary) {
- ngx_rtmp_hls_close_fragment(s, 0);
+ ngx_rtmp_hls_close_fragment(s);
ngx_rtmp_hls_open_fragment(s, ts, !f);
}
@@ -1397,9 +1420,9 @@
if (!ctx->opened) {
return NGX_OK;
}
-
+
b = ctx->aframe;
-
+
if (b == NULL || b->pos == b->last) {
return NGX_OK;
}
@@ -1430,7 +1453,7 @@
static ngx_int_t
-ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_hls_app_conf_t *hacf;
@@ -1448,15 +1471,15 @@
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
-
+
if (hacf == NULL || !hacf->hls || ctx == NULL ||
- codec_ctx == NULL || h->mlen < 2)
+ codec_ctx == NULL || h->mlen < 2)
{
return NGX_OK;
}
if (codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC ||
- codec_ctx->aac_header == NULL)
+ codec_ctx->aac_header == NULL || ngx_rtmp_is_codec_header(in))
{
return NGX_OK;
}
@@ -1490,7 +1513,7 @@
return NGX_OK;
}
- /*
+ /*
* start new fragment here if
* there's no video at all, otherwise
* do it in video handler
@@ -1535,7 +1558,7 @@
"hls: aac header error");
return NGX_OK;
}
-
+
/* we have 5 free bytes + 2 bytes of RTMP frame header */
p[0] = 0xff;
@@ -1591,41 +1614,7 @@
static ngx_int_t
-ngx_rtmp_hls_get_nal_bytes(ngx_rtmp_session_t *s)
-{
- ngx_rtmp_codec_ctx_t *codec_ctx;
- ngx_chain_t *cl;
- u_char *p;
- uint8_t nal_bytes;
-
- codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
-
- cl = codec_ctx->avc_header;
-
- p = cl->buf->pos;
-
- if (ngx_rtmp_hls_copy(s, NULL, &p, 9, &cl) != NGX_OK) {
- return NGX_ERROR;
- }
-
- /* NAL size length (1,2,4) */
- if (ngx_rtmp_hls_copy(s, &nal_bytes, &p, 1, &cl) != NGX_OK) {
- return NGX_ERROR;
- }
-
- nal_bytes &= 0x03; /* 2 lsb */
-
- ++nal_bytes;
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "hls: NAL bytes: %ui", (ngx_uint_t) nal_bytes);
-
- return nal_bytes;
-}
-
-
-static ngx_int_t
-ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_hls_app_conf_t *hacf;
@@ -1638,7 +1627,7 @@
uint32_t cts;
ngx_rtmp_mpegts_frame_t frame;
ngx_uint_t nal_bytes;
- ngx_int_t aud_sent, sps_pps_sent, rc, boundary;
+ ngx_int_t aud_sent, sps_pps_sent, boundary;
static u_char buffer[NGX_RTMP_HLS_BUFSIZE];
hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module);
@@ -1680,7 +1669,7 @@
if (htype != 1) {
return NGX_OK;
}
-
+
/* 3 bytes: decoder delay */
if (ngx_rtmp_hls_copy(s, &cts, &p, 3, &in) != NGX_OK) {
@@ -1696,15 +1685,8 @@
out.end = buffer + sizeof(buffer);
out.pos = out.start;
out.last = out.pos;
-
- rc = ngx_rtmp_hls_get_nal_bytes(s);
- if (rc < 0) {
- ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "hls: failed to parse NAL bytes");
- return NGX_OK;
- }
- nal_bytes = rc;
+ nal_bytes = codec_ctx->avc_nal_bytes;
aud_sent = 0;
sps_pps_sent = 0;
@@ -1811,14 +1793,15 @@
frame.sid = 0xe0;
frame.key = (ftype == 1);
- /*
+ /*
* start new fragment if
* - we have video key frame AND
- * - we have audio buffered or have no audio at all
+ * - we have audio buffered or have no audio at all or stream is closed
*/
b = ctx->aframe;
- boundary = frame.key && (codec_ctx->aac_header == NULL || b->last > b->pos);
+ boundary = frame.key && (codec_ctx->aac_header == NULL || !ctx->opened ||
+ (b && b->last > b->pos));
ngx_rtmp_hls_update_fragment(s, frame.dts, boundary, 1);
@@ -1840,30 +1823,9 @@
}
-static void
-ngx_rtmp_hls_discontinue(ngx_rtmp_session_t *s)
-{
- ngx_rtmp_hls_ctx_t *ctx;
-
- ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module);
-
- if (ctx == NULL || !ctx->opened) {
- return;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "hld: discontinue");
-
- ngx_close_file(ctx->file.fd);
- ctx->opened = 0;
-}
-
-
static ngx_int_t
ngx_rtmp_hls_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v)
{
- ngx_rtmp_hls_discontinue(s);
-
return next_stream_begin(s, v);
}
@@ -1871,7 +1833,9 @@
static ngx_int_t
ngx_rtmp_hls_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v)
{
- ngx_rtmp_hls_discontinue(s);
+ ngx_rtmp_hls_flush_audio(s);
+
+ ngx_rtmp_hls_close_fragment(s);
return next_stream_eof(s, v);
}
@@ -1919,7 +1883,7 @@
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, err,
"hls: cleanup " ngx_read_dir_n
- " \"%V\" failed", ppath);
+ " '%V' failed", ppath);
return NGX_ERROR;
}
@@ -1938,7 +1902,7 @@
nentries++;
- if (ngx_de_info(path, &dir) == NGX_FILE_ERROR) {
+ if (!dir.valid_info && ngx_de_info(path, &dir) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
"hls: cleanup " ngx_de_info_n " \"%V\" failed",
&spath);
@@ -1952,9 +1916,17 @@
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0,
"hls: cleanup dir '%V'", &name);
- if (ngx_delete_dir(spath.data) != NGX_OK) {
+ /*
+ * null-termination gets spoiled in win32
+ * version of ngx_open_dir
+ */
+
+ *p = 0;
+
+ if (ngx_delete_dir(path) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno,
- "hls: cleanup dir error '%V'", &spath);
+ "hls: cleanup " ngx_delete_dir_n
+ " failed on '%V'", &spath);
} else {
nerased++;
}
@@ -1996,9 +1968,10 @@
"hls: cleanup '%V' mtime=%T age=%T",
&name, mtime, ngx_cached_time->sec - mtime);
- if (ngx_delete_file(spath.data) != NGX_OK) {
+ if (ngx_delete_file(path) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno,
- "hls: cleanup error '%V'", &spath);
+ "hls: cleanup " ngx_delete_file_n " failed on '%V'",
+ &spath);
continue;
}
@@ -2113,7 +2086,6 @@
ngx_conf_merge_msec_value(conf->muxdelay, prev->muxdelay, 700);
ngx_conf_merge_msec_value(conf->sync, prev->sync, 2);
ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000);
- ngx_conf_merge_str_value(conf->path, prev->path, "");
ngx_conf_merge_value(conf->continuous, prev->continuous, 1);
ngx_conf_merge_value(conf->nested, prev->nested, 0);
ngx_conf_merge_uint_value(conf->naming, prev->naming,
@@ -2135,39 +2107,39 @@
/* schedule cleanup */
- if (conf->path.len == 0 || !conf->cleanup ||
- conf->type == NGX_RTMP_HLS_TYPE_EVENT)
+ if (conf->hls && conf->path.len && conf->cleanup &&
+ conf->type != NGX_RTMP_HLS_TYPE_EVENT)
{
- return NGX_CONF_OK;
- }
-
- if (conf->path.data[conf->path.len - 1] == '/') {
- conf->path.len--;
- }
+ if (conf->path.data[conf->path.len - 1] == '/') {
+ conf->path.len--;
+ }
- cleanup = ngx_pcalloc(cf->pool, sizeof(*cleanup));
- if (cleanup == NULL) {
- return NGX_CONF_ERROR;
- }
+ cleanup = ngx_pcalloc(cf->pool, sizeof(*cleanup));
+ if (cleanup == NULL) {
+ return NGX_CONF_ERROR;
+ }
- cleanup->path = conf->path;
- cleanup->playlen = conf->playlen;
+ cleanup->path = conf->path;
+ cleanup->playlen = conf->playlen;
- conf->slot = ngx_pcalloc(cf->pool, sizeof(*conf->slot));
- if (conf->slot == NULL) {
- return NGX_CONF_ERROR;
- }
+ conf->slot = ngx_pcalloc(cf->pool, sizeof(*conf->slot));
+ if (conf->slot == NULL) {
+ return NGX_CONF_ERROR;
+ }
- conf->slot->manager = ngx_rtmp_hls_cleanup;
- conf->slot->name = conf->path;
- conf->slot->data = cleanup;
- conf->slot->conf_file = cf->conf_file->file.name.data;
- conf->slot->line = cf->conf_file->line;
+ conf->slot->manager = ngx_rtmp_hls_cleanup;
+ conf->slot->name = conf->path;
+ conf->slot->data = cleanup;
+ conf->slot->conf_file = cf->conf_file->file.name.data;
+ conf->slot->line = cf->conf_file->line;
- if (ngx_add_path(cf, &conf->slot) != NGX_OK) {
- return NGX_CONF_ERROR;
+ if (ngx_add_path(cf, &conf->slot) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
}
+ ngx_conf_merge_str_value(conf->path, prev->path, "");
+
return NGX_CONF_OK;
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/hls/ngx_rtmp_mpegts.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2013 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -36,7 +37,7 @@
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-
+
/* TS */
0x47, 0x50, 0x01, 0x10, 0x00,
/* PSI */
@@ -131,7 +132,7 @@
ngx_log_debug6(NGX_LOG_DEBUG_HTTP, file->log, 0,
"mpegts: pid=%ui, sid=%ui, pts=%uL, "
"dts=%uL, key=%ui, size=%ui",
- f->pid, f->sid, f->pts, f->dts,
+ f->pid, f->sid, f->pts, f->dts,
(ngx_uint_t) f->key, (size_t) (b->last - b->pos));
first = 1;
@@ -188,7 +189,7 @@
*p++ = (u_char) flags;
*p++ = (u_char) header_size;
- p = ngx_rtmp_mpegts_write_pts(p, flags >> 6, f->pts +
+ p = ngx_rtmp_mpegts_write_pts(p, flags >> 6, f->pts +
NGX_RTMP_HLS_DELAY);
if (f->dts != f->pts) {
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/hls/ngx_rtmp_mpegts.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2013 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -21,12 +22,12 @@
ngx_rtmp_conf_addr_t *addr);
#endif
static ngx_int_t ngx_rtmp_cmp_conf_addrs(const void *one, const void *two);
-static ngx_int_t ngx_rtmp_init_events(ngx_conf_t *cf,
+static ngx_int_t ngx_rtmp_init_events(ngx_conf_t *cf,
ngx_rtmp_core_main_conf_t *cmcf);
-static ngx_int_t ngx_rtmp_init_event_handlers(ngx_conf_t *cf,
+static ngx_int_t ngx_rtmp_init_event_handlers(ngx_conf_t *cf,
ngx_rtmp_core_main_conf_t *cmcf);
-static char * ngx_rtmp_merge_applications(ngx_conf_t *cf,
- ngx_array_t *applications, void **app_conf, ngx_rtmp_module_t *module,
+static char * ngx_rtmp_merge_applications(ngx_conf_t *cf,
+ ngx_array_t *applications, void **app_conf, ngx_rtmp_module_t *module,
ngx_uint_t ctx_index);
@@ -246,7 +247,7 @@
/*ctx->app_conf = cscfp[s]->ctx->loc_conf;*/
- rv = module->merge_app_conf(cf,
+ rv = module->merge_app_conf(cf,
ctx->app_conf[mi],
cscfp[s]->ctx->app_conf[mi]);
if (rv != NGX_CONF_OK) {
@@ -342,7 +343,7 @@
}
cacf = (*cacfp)->app_conf[ngx_rtmp_core_module.ctx_index];
- rv = ngx_rtmp_merge_applications(cf, &cacf->applications,
+ rv = ngx_rtmp_merge_applications(cf, &cacf->applications,
(*cacfp)->app_conf,
module, ctx_index);
if (rv != NGX_CONF_OK) {
@@ -362,14 +363,14 @@
size_t n;
for(n = 0; n < NGX_RTMP_MAX_EVENT; ++n) {
- if (ngx_array_init(&cmcf->events[n], cf->pool, 1,
+ if (ngx_array_init(&cmcf->events[n], cf->pool, 1,
sizeof(ngx_rtmp_handler_pt)) != NGX_OK)
{
return NGX_ERROR;
}
}
- if (ngx_array_init(&cmcf->amf, cf->pool, 1,
+ if (ngx_array_init(&cmcf->amf, cf->pool, 1,
sizeof(ngx_rtmp_amf_handler_t)) != NGX_OK)
{
return NGX_ERROR;
@@ -432,7 +433,7 @@
for(n = 0; n < cmcf->amf.nelts; ++n, ++h) {
ha = cmcf->amf_arrays.elts;
for(m = 0; m < cmcf->amf_arrays.nelts; ++m, ++ha) {
- if (h->name.len == ha->key.len
+ if (h->name.len == ha->key.len
&& !ngx_strncmp(h->name.data, ha->key.data, ha->key.len))
{
break;
@@ -442,7 +443,7 @@
ha = ngx_array_push(&cmcf->amf_arrays);
ha->key = h->name;
ha->key_hash = ngx_hash_key_lc(ha->key.data, ha->key.len);
- ha->value = ngx_array_create(cf->pool, 1,
+ ha->value = ngx_array_create(cf->pool, 1,
sizeof(ngx_rtmp_handler_pt));
if (ha->value == NULL) {
return NGX_ERROR;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -220,6 +221,7 @@
ngx_msec_t epoch;
ngx_msec_t peer_epoch;
ngx_msec_t base_time;
+ uint32_t current_time;
/* ping */
ngx_event_t ping_evt;
@@ -305,7 +307,7 @@
ngx_int_t max_streams;
ngx_uint_t ack_window;
-
+
ngx_int_t chunk_size;
ngx_pool_t *pool;
ngx_chain_t *free;
@@ -342,7 +344,7 @@
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
void *(*create_srv_conf)(ngx_conf_t *cf);
- char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev,
+ char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev,
void *conf);
void *(*create_app_conf)(ngx_conf_t *cf);
@@ -388,7 +390,7 @@
#endif
void ngx_rtmp_init_connection(ngx_connection_t *c);
-ngx_rtmp_session_t * ngx_rtmp_init_session(ngx_connection_t *c,
+ngx_rtmp_session_t * ngx_rtmp_init_session(ngx_connection_t *c,
ngx_rtmp_addr_conf_t *addr_conf);
void ngx_rtmp_finalize_session(ngx_rtmp_session_t *s);
void ngx_rtmp_handshake(ngx_rtmp_session_t *s);
@@ -467,9 +469,9 @@
--ngx_rtmp_ref(b)
ngx_chain_t * ngx_rtmp_alloc_shared_buf(ngx_rtmp_core_srv_conf_t *cscf);
-void ngx_rtmp_free_shared_chain(ngx_rtmp_core_srv_conf_t *cscf,
+void ngx_rtmp_free_shared_chain(ngx_rtmp_core_srv_conf_t *cscf,
ngx_chain_t *in);
-ngx_chain_t * ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
+ngx_chain_t * ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
ngx_chain_t *head, ngx_chain_t *in);
#define ngx_rtmp_acquire_shared_chain(in) \
@@ -477,7 +479,7 @@
/* Sending messages */
-void ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+void ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_header_t *lh, ngx_chain_t *out);
ngx_int_t ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out,
ngx_uint_t priority);
@@ -492,64 +494,64 @@
#define NGX_RTMP_LIMIT_DYNAMIC 2
/* Protocol control messages */
-ngx_chain_t * ngx_rtmp_create_chunk_size(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_chunk_size(ngx_rtmp_session_t *s,
uint32_t chunk_size);
-ngx_chain_t * ngx_rtmp_create_abort(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_abort(ngx_rtmp_session_t *s,
uint32_t csid);
-ngx_chain_t * ngx_rtmp_create_ack(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_ack(ngx_rtmp_session_t *s,
uint32_t seq);
-ngx_chain_t * ngx_rtmp_create_ack_size(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_ack_size(ngx_rtmp_session_t *s,
uint32_t ack_size);
-ngx_chain_t * ngx_rtmp_create_bandwidth(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_bandwidth(ngx_rtmp_session_t *s,
uint32_t ack_size, uint8_t limit_type);
-ngx_int_t ngx_rtmp_send_chunk_size(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_chunk_size(ngx_rtmp_session_t *s,
uint32_t chunk_size);
-ngx_int_t ngx_rtmp_send_abort(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_abort(ngx_rtmp_session_t *s,
uint32_t csid);
-ngx_int_t ngx_rtmp_send_ack(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_ack(ngx_rtmp_session_t *s,
uint32_t seq);
-ngx_int_t ngx_rtmp_send_ack_size(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_ack_size(ngx_rtmp_session_t *s,
uint32_t ack_size);
-ngx_int_t ngx_rtmp_send_bandwidth(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_bandwidth(ngx_rtmp_session_t *s,
uint32_t ack_size, uint8_t limit_type);
/* User control messages */
-ngx_chain_t * ngx_rtmp_create_stream_begin(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_stream_begin(ngx_rtmp_session_t *s,
uint32_t msid);
-ngx_chain_t * ngx_rtmp_create_stream_eof(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_stream_eof(ngx_rtmp_session_t *s,
uint32_t msid);
-ngx_chain_t * ngx_rtmp_create_stream_dry(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_stream_dry(ngx_rtmp_session_t *s,
uint32_t msid);
-ngx_chain_t * ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s,
uint32_t msid, uint32_t buflen_msec);
-ngx_chain_t * ngx_rtmp_create_recorded(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_recorded(ngx_rtmp_session_t *s,
uint32_t msid);
ngx_chain_t * ngx_rtmp_create_ping_request(ngx_rtmp_session_t *s,
uint32_t timestamp);
-ngx_chain_t * ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s,
uint32_t timestamp);
-ngx_int_t ngx_rtmp_send_stream_begin(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_stream_begin(ngx_rtmp_session_t *s,
uint32_t msid);
-ngx_int_t ngx_rtmp_send_stream_eof(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_stream_eof(ngx_rtmp_session_t *s,
uint32_t msid);
-ngx_int_t ngx_rtmp_send_stream_dry(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_stream_dry(ngx_rtmp_session_t *s,
uint32_t msid);
-ngx_int_t ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s,
uint32_t msid, uint32_t buflen_msec);
-ngx_int_t ngx_rtmp_send_recorded(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_recorded(ngx_rtmp_session_t *s,
uint32_t msid);
ngx_int_t ngx_rtmp_send_ping_request(ngx_rtmp_session_t *s,
uint32_t timestamp);
-ngx_int_t ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s,
uint32_t timestamp);
/* AMF sender/receiver */
ngx_int_t ngx_rtmp_append_amf(ngx_rtmp_session_t *s,
- ngx_chain_t **first, ngx_chain_t **last,
+ ngx_chain_t **first, ngx_chain_t **last,
ngx_rtmp_amf_elt_t *elts, size_t nelts);
-ngx_int_t ngx_rtmp_receive_amf(ngx_rtmp_session_t *s, ngx_chain_t *in,
+ngx_int_t ngx_rtmp_receive_amf(ngx_rtmp_session_t *s, ngx_chain_t *in,
ngx_rtmp_amf_elt_t *elts, size_t nelts);
ngx_chain_t * ngx_rtmp_create_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_access_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -17,11 +18,11 @@
#define NGX_RTMP_ACCESS_PLAY 0x02
-static char * ngx_rtmp_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
+static char * ngx_rtmp_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_rtmp_access_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_access_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_access_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_access_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -330,7 +331,7 @@
#if (NGX_HAVE_INET6)
ngx_rtmp_access_rule6_t *rule6;
#endif
- size_t n;
+ size_t n;
ngx_uint_t flags;
ngx_memzero(&cidr, sizeof(ngx_cidr_t));
@@ -341,7 +342,7 @@
flags = 0;
if (cf->args->nelts == 2) {
-
+
flags = NGX_RTMP_ACCESS_PUBLISH | NGX_RTMP_ACCESS_PLAY;
} else {
@@ -355,7 +356,7 @@
continue;
}
-
+
if (value[n].len == sizeof("play") - 1 &&
ngx_strcmp(value[1].data, "play") == 0)
{
@@ -429,7 +430,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_access_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
{
if (s->auto_pushed) {
@@ -445,7 +446,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_access_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
{
if (ngx_rtmp_access(s, NGX_RTMP_ACCESS_PLAY) != NGX_OK) {
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_amf.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -88,7 +89,7 @@
}
ctx->offset = offset + n;
ctx->link = l;
-
+
#ifdef NGX_DEBUG
ngx_rtmp_amf_debug("read", ctx->log, (u_char*)op, on);
#endif
@@ -168,8 +169,8 @@
}
-static ngx_int_t
-ngx_rtmp_amf_read_object(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
+static ngx_int_t
+ngx_rtmp_amf_read_object(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
size_t nelts)
{
uint8_t type;
@@ -219,7 +220,7 @@
/* TODO: if we require array to be sorted on name
* then we could be able to use binary search */
- for(n = 0; n < nelts
+ for(n = 0; n < nelts
&& (len != elts[n].name.len
|| ngx_strncmp(name, elts[n].name.data, len));
++n);
@@ -238,8 +239,8 @@
}
-static ngx_int_t
-ngx_rtmp_amf_read_array(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
+static ngx_int_t
+ngx_rtmp_amf_read_array(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
size_t nelts)
{
uint32_t len;
@@ -261,8 +262,8 @@
}
-static ngx_int_t
-ngx_rtmp_amf_read_variant(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
+static ngx_int_t
+ngx_rtmp_amf_read_variant(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
size_t nelts)
{
uint8_t type;
@@ -298,8 +299,8 @@
}
-ngx_int_t
-ngx_rtmp_amf_read(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
+ngx_int_t
+ngx_rtmp_amf_read(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts,
size_t nelts)
{
void *data;
@@ -327,7 +328,7 @@
return NGX_ERROR;
}
type = type8;
- data = (elts &&
+ data = (elts &&
ngx_rtmp_amf_is_compatible_type(
(uint8_t) (elts->type & 0xff), (uint8_t) type))
? elts->data
@@ -392,18 +393,18 @@
}
case NGX_RTMP_AMF_OBJECT:
- if (ngx_rtmp_amf_read_object(ctx, data,
+ if (ngx_rtmp_amf_read_object(ctx, data,
data && elts ? elts->len / sizeof(ngx_rtmp_amf_elt_t) : 0
- ) != NGX_OK)
+ ) != NGX_OK)
{
return NGX_ERROR;
}
break;
case NGX_RTMP_AMF_ARRAY:
- if (ngx_rtmp_amf_read_array(ctx, data,
+ if (ngx_rtmp_amf_read_array(ctx, data,
data && elts ? elts->len / sizeof(ngx_rtmp_amf_elt_t) : 0
- ) != NGX_OK)
+ ) != NGX_OK)
{
return NGX_ERROR;
}
@@ -417,7 +418,7 @@
return NGX_ERROR;
}
break;
-
+
case NGX_RTMP_AMF_INT8:
if (ngx_rtmp_amf_get(ctx, data, 1) != NGX_OK) {
return NGX_ERROR;
@@ -454,7 +455,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_amf_write_object(ngx_rtmp_amf_ctx_t *ctx,
ngx_rtmp_amf_elt_t *elts, size_t nelts)
{
@@ -466,9 +467,9 @@
len = (uint16_t) elts[n].name.len;
- if (ngx_rtmp_amf_put(ctx,
- ngx_rtmp_amf_reverse_copy(buf,
- &len, 2), 2) != NGX_OK)
+ if (ngx_rtmp_amf_put(ctx,
+ ngx_rtmp_amf_reverse_copy(buf,
+ &len, 2), 2) != NGX_OK)
{
return NGX_ERROR;
}
@@ -490,7 +491,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_amf_write_array(ngx_rtmp_amf_ctx_t *ctx,
ngx_rtmp_amf_elt_t *elts, size_t nelts)
{
@@ -499,9 +500,9 @@
u_char buf[4];
len = nelts;
- if (ngx_rtmp_amf_put(ctx,
- ngx_rtmp_amf_reverse_copy(buf,
- &len, 4), 4) != NGX_OK)
+ if (ngx_rtmp_amf_put(ctx,
+ ngx_rtmp_amf_reverse_copy(buf,
+ &len, 4), 4) != NGX_OK)
{
return NGX_ERROR;
}
@@ -516,7 +517,7 @@
}
-ngx_int_t
+ngx_int_t
ngx_rtmp_amf_write(ngx_rtmp_amf_ctx_t *ctx,
ngx_rtmp_amf_elt_t *elts, size_t nelts)
{
@@ -544,9 +545,9 @@
switch(type) {
case NGX_RTMP_AMF_NUMBER:
- if (ngx_rtmp_amf_put(ctx,
- ngx_rtmp_amf_reverse_copy(buf,
- data, 8), 8) != NGX_OK)
+ if (ngx_rtmp_amf_put(ctx,
+ ngx_rtmp_amf_reverse_copy(buf,
+ data, 8), 8) != NGX_OK)
{
return NGX_ERROR;
}
@@ -563,9 +564,9 @@
len = (uint16_t) ngx_strlen((u_char*) data);
}
- if (ngx_rtmp_amf_put(ctx,
- ngx_rtmp_amf_reverse_copy(buf,
- &len, 2), 2) != NGX_OK)
+ if (ngx_rtmp_amf_put(ctx,
+ ngx_rtmp_amf_reverse_copy(buf,
+ &len, 2), 2) != NGX_OK)
{
return NGX_ERROR;
}
@@ -596,7 +597,7 @@
break;
case NGX_RTMP_AMF_ARRAY:
- if (ngx_rtmp_amf_write_array(ctx, data,
+ if (ngx_rtmp_amf_write_array(ctx, data,
elts[n].len / sizeof(ngx_rtmp_amf_elt_t)) != NGX_OK)
{
return NGX_ERROR;
@@ -611,8 +612,8 @@
case NGX_RTMP_AMF_INT16:
if (ngx_rtmp_amf_put(ctx,
- ngx_rtmp_amf_reverse_copy(buf,
- data, 2), 2) != NGX_OK)
+ ngx_rtmp_amf_reverse_copy(buf,
+ data, 2), 2) != NGX_OK)
{
return NGX_ERROR;
}
@@ -620,8 +621,8 @@
case NGX_RTMP_AMF_INT32:
if (ngx_rtmp_amf_put(ctx,
- ngx_rtmp_amf_reverse_copy(buf,
- data, 4), 4) != NGX_OK)
+ ngx_rtmp_amf_reverse_copy(buf,
+ data, 4), 4) != NGX_OK)
{
return NGX_ERROR;
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_amf.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_auto_push_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -18,9 +19,9 @@
static void * ngx_rtmp_auto_push_create_conf(ngx_cycle_t *cf);
static char * ngx_rtmp_auto_push_init_conf(ngx_cycle_t *cycle, void *conf);
#if (NGX_HAVE_UNIX_DOMAIN)
-static ngx_int_t ngx_rtmp_auto_push_publish(ngx_rtmp_session_t *s,
+static ngx_int_t ngx_rtmp_auto_push_publish(ngx_rtmp_session_t *s,
ngx_rtmp_publish_t *v);
-static ngx_int_t ngx_rtmp_auto_push_delete_stream(ngx_rtmp_session_t *s,
+static ngx_int_t ngx_rtmp_auto_push_delete_stream(ngx_rtmp_session_t *s,
ngx_rtmp_delete_stream_t *v);
#endif
@@ -101,7 +102,7 @@
#if (NGX_HAVE_UNIX_DOMAIN)
ngx_rtmp_auto_push_conf_t *apcf;
ngx_listening_t *ls, *lss;
- struct sockaddr_un *sun;
+ struct sockaddr_un *saun;
int reuseaddr;
ngx_socket_t s;
size_t n;
@@ -111,7 +112,7 @@
return NGX_OK;
}
- apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx,
+ apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_rtmp_auto_push_module);
if (apcf->auto_push == 0) {
return NGX_OK;
@@ -153,29 +154,29 @@
/* Disable unix socket client address extraction
* from accept call
* Nginx generates bad addr_text with this enabled */
- ls->addr_ntop = 0;
+ ls->addr_ntop = 0;
ls->socklen = sizeof(struct sockaddr_un);
- sun = ngx_pcalloc(cycle->pool, ls->socklen);
- ls->sockaddr = (struct sockaddr *) sun;
+ saun = ngx_pcalloc(cycle->pool, ls->socklen);
+ ls->sockaddr = (struct sockaddr *) saun;
if (ls->sockaddr == NULL) {
return NGX_ERROR;
}
- sun->sun_family = AF_UNIX;
- *ngx_snprintf((u_char *) sun->sun_path, sizeof(sun->sun_path),
- "%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i",
+ saun->sun_family = AF_UNIX;
+ *ngx_snprintf((u_char *) saun->sun_path, sizeof(saun->sun_path),
+ "%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i",
&apcf->socket_dir, ngx_process_slot)
= 0;
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0,
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0,
"auto_push: create socket '%s'",
- sun->sun_path);
+ saun->sun_path);
- if (ngx_file_info(sun->sun_path, &fi) != ENOENT) {
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0,
+ if (ngx_file_info(saun->sun_path, &fi) != ENOENT) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, cycle->log, 0,
"auto_push: delete existing socket '%s'",
- sun->sun_path);
- ngx_delete_file(sun->sun_path);
+ saun->sun_path);
+ ngx_delete_file(saun->sun_path);
}
ngx_str_set(&ls->addr_text, "worker_socket");
@@ -204,7 +205,7 @@
}
}
- if (bind(s, (struct sockaddr *) sun, sizeof(*sun)) == -1) {
+ if (bind(s, (struct sockaddr *) saun, sizeof(*saun)) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_nonblocking_n " worker_socket bind failed");
goto sock_error;
@@ -227,7 +228,7 @@
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_close_socket_n " worker_socket failed");
}
- ngx_delete_file(sun->sun_path);
+ ngx_delete_file(saun->sun_path);
return NGX_ERROR;
@@ -246,14 +247,14 @@
ngx_rtmp_auto_push_conf_t *apcf;
u_char path[NGX_MAX_PATH];
- apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx,
+ apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_rtmp_auto_push_module);
if (apcf->auto_push == 0) {
return;
}
*ngx_snprintf(path, sizeof(path),
- "%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i",
- &apcf->socket_dir, ngx_process_slot)
+ "%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i",
+ &apcf->socket_dir, ngx_process_slot)
= 0;
ngx_delete_file(path);
@@ -318,10 +319,10 @@
ngx_core_conf_t *ccf;
ngx_file_info_t fi;
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"auto_push: reconnect");
-
- apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
+
+ apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_rtmp_auto_push_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_auto_push_module);
if (ctx == NULL) {
@@ -365,7 +366,7 @@
ngx_memzero(&at.url, sizeof(at.url));
u = &at.url.url;
p = ngx_snprintf(path, sizeof(path) - 1,
- "unix:%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i",
+ "unix:%V/" NGX_RTMP_AUTO_PUSH_SOCKNAME ".%i",
&apcf->socket_dir, n);
*p = 0;
@@ -387,12 +388,12 @@
continue;
}
- p = ngx_snprintf(flash_ver, sizeof(flash_ver) - 1, "APSH %i,%i",
+ p = ngx_snprintf(flash_ver, sizeof(flash_ver) - 1, "APSH %i,%i",
(ngx_int_t) ngx_process_slot, (ngx_int_t) ngx_pid);
at.flash_ver.data = flash_ver;
at.flash_ver.len = p - flash_ver;
- ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"auto_push: connect slot=%i pid=%P socket='%s' name='%s'",
n, pid, path, ctx->name);
@@ -454,7 +455,7 @@
goto next;
}
- apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
+ apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_rtmp_auto_push_module);
if (apcf->auto_push == 0) {
goto next;
@@ -462,7 +463,7 @@
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_auto_push_module);
if (ctx == NULL) {
- ctx = ngx_palloc(s->connection->pool,
+ ctx = ngx_palloc(s->connection->pool,
sizeof(ngx_rtmp_auto_push_ctx_t));
if (ctx == NULL) {
goto next;
@@ -476,7 +477,7 @@
ctx->push_evt.log = s->connection->log;
ctx->push_evt.handler = ngx_rtmp_auto_push_reconnect;
- ctx->slots = ngx_pcalloc(s->connection->pool,
+ ctx->slots = ngx_pcalloc(s->connection->pool,
sizeof(ngx_int_t) * NGX_MAX_PROCESSES);
if (ctx->slots == NULL) {
goto next;
@@ -493,7 +494,7 @@
static ngx_int_t
-ngx_rtmp_auto_push_delete_stream(ngx_rtmp_session_t *s,
+ngx_rtmp_auto_push_delete_stream(ngx_rtmp_session_t *s,
ngx_rtmp_delete_stream_t *v)
{
ngx_rtmp_auto_push_conf_t *apcf;
@@ -501,7 +502,7 @@
ngx_rtmp_relay_ctx_t *rctx;
ngx_int_t slot;
- apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
+ apcf = (ngx_rtmp_auto_push_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_rtmp_auto_push_module);
if (apcf->auto_push == 0) {
goto next;
@@ -517,20 +518,20 @@
/* skip non-relays & publishers */
rctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module);
- if (rctx == NULL ||
+ if (rctx == NULL ||
rctx->tag != &ngx_rtmp_auto_push_module ||
- rctx->publish == NULL)
+ rctx->publish == NULL)
{
goto next;
}
slot = (ngx_process_t *) rctx->data - &ngx_processes[0];
- ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"auto_push: disconnect slot=%i app='%V' name='%V'",
slot, &rctx->app, &rctx->name);
- pctx = ngx_rtmp_get_module_ctx(rctx->publish->session,
+ pctx = ngx_rtmp_get_module_ctx(rctx->publish->session,
ngx_rtmp_auto_push_module);
if (pctx == NULL) {
goto next;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_bandwidth.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -8,11 +9,11 @@
#include "ngx_rtmp_bandwidth.h"
-void
+void
ngx_rtmp_update_bandwidth(ngx_rtmp_bandwidth_t *bw, uint32_t bytes)
{
if (ngx_cached_time->sec > bw->intl_end) {
- bw->bandwidth = ngx_cached_time->sec >
+ bw->bandwidth = ngx_cached_time->sec >
bw->intl_end + NGX_RTMP_BANDWIDTH_INTERVAL
? 0
: bw->intl_bytes / NGX_RTMP_BANDWIDTH_INTERVAL;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_bandwidth.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -12,7 +13,7 @@
/* Bandwidth update interval in seconds */
-#define NGX_RTMP_BANDWIDTH_INTERVAL 60
+#define NGX_RTMP_BANDWIDTH_INTERVAL 10
typedef struct {
@@ -28,4 +29,3 @@
#endif /* _NGX_RTMP_BANDWIDTH_H_INCLUDED_ */
-
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_bitop.c
^
|
@@ -0,0 +1,63 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include "ngx_rtmp_bitop.h"
+
+
+void
+ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, u_char *last)
+{
+ ngx_memzero(br, sizeof(ngx_rtmp_bit_reader_t));
+
+ br->pos = pos;
+ br->last = last;
+}
+
+
+uint64_t
+ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n)
+{
+ uint64_t v;
+ ngx_uint_t d;
+
+ v = 0;
+
+ while (n) {
+
+ if (br->pos >= br->last) {
+ br->err = 1;
+ return 0;
+ }
+
+ d = (br->offs + n > 8 ? (ngx_uint_t) (8 - br->offs) : n);
+
+ v <<= d;
+ v += (*br->pos >> (8 - br->offs - d)) & ((u_char) 0xff >> (8 - d));
+
+ br->offs += d;
+ n -= d;
+
+ if (br->offs == 8) {
+ br->pos++;
+ br->offs = 0;
+ }
+ }
+
+ return v;
+}
+
+
+uint64_t
+ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br)
+{
+ ngx_uint_t n;
+
+ for (n = 0; ngx_rtmp_bit_read(br, 1) == 0 && !br->err; n++);
+
+ return ((uint64_t) 1 << n) + ngx_rtmp_bit_read(br, n) - 1;
+}
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_bitop.h
^
|
@@ -0,0 +1,46 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ */
+
+
+#ifndef _NGX_RTMP_BITOP_H_INCLUDED_
+#define _NGX_RTMP_BITOP_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct {
+ u_char *pos;
+ u_char *last;
+ ngx_uint_t offs;
+ ngx_uint_t err;
+} ngx_rtmp_bit_reader_t;
+
+
+void ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos,
+ u_char *last);
+uint64_t ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n);
+uint64_t ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br);
+
+
+#define ngx_rtmp_bit_read_err(br) ((br)->err)
+
+#define ngx_rtmp_bit_read_eof(br) ((br)->pos == (br)->last)
+
+#define ngx_rtmp_bit_read_8(br) \
+ ((uint8_t) ngx_rtmp_bit_read(br, 8))
+
+#define ngx_rtmp_bit_read_16(br) \
+ ((uint16_t) ngx_rtmp_bit_read(br, 16))
+
+#define ngx_rtmp_bit_read_32(br) \
+ ((uint32_t) ngx_rtmp_bit_read(br, 32))
+
+#define ngx_rtmp_bit_read_64(br) \
+ ((uint64_t) ngx_rtmp_read(br, 64))
+
+
+#endif /* _NGX_RTMP_BITOP_H_INCLUDED_ */
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_cmd_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -93,8 +94,8 @@
};
-static void
-ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME],
+void
+ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME],
u_char args[NGX_RTMP_MAX_ARGS])
{
u_char *p;
@@ -119,11 +120,11 @@
static ngx_rtmp_amf_elt_t in_cmd[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("app"),
v.app, sizeof(v.app) },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("flashVer"),
v.flashver, sizeof(v.flashver) },
@@ -164,8 +165,8 @@
};
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
@@ -182,7 +183,7 @@
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"connect: app='%s' args='%s' flashver='%s' swf_url='%s' "
"tc_url='%s' page_url='%s' acodecs=%uD vcodecs=%uD "
- "object_encoding=%ui",
+ "object_encoding=%ui",
v.app, v.args, v.flashver, v.swf_url, v.tc_url, v.page_url,
(uint32_t)v.acodecs, (uint32_t)v.vcodecs,
(ngx_int_t)v.object_encoding);
@@ -206,10 +207,10 @@
static ngx_rtmp_amf_elt_t out_obj[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("fmsVer"),
NGX_RTMP_FMS_VERSION, 0 },
-
+
{ NGX_RTMP_AMF_NUMBER,
ngx_string("capabilities"),
&capabilities, 0 },
@@ -217,13 +218,13 @@
static ngx_rtmp_amf_elt_t out_inf[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("level"),
"status", 0 },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("code"),
- "NetConnection.Connect.Success", 0 },
+ "NetConnection.Connect.Success", 0 },
{ NGX_RTMP_AMF_STRING,
ngx_string("description"),
@@ -237,7 +238,7 @@
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
- ngx_null_string,
+ ngx_null_string,
"_result", 0 },
{ NGX_RTMP_AMF_NUMBER,
@@ -254,7 +255,7 @@
};
if (s->connected) {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"connect: duplicate connection");
return NGX_ERROR;
}
@@ -306,7 +307,7 @@
}
if (s->app_conf == NULL) {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"connect: application not found: '%V'", &s->app);
return NGX_ERROR;
}
@@ -314,12 +315,12 @@
object_encoding = v->object_encoding;
return ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK ||
- ngx_rtmp_send_bandwidth(s, cscf->ack_window,
+ ngx_rtmp_send_bandwidth(s, cscf->ack_window,
NGX_RTMP_LIMIT_DYNAMIC) != NGX_OK ||
ngx_rtmp_send_chunk_size(s, cscf->chunk_size) != NGX_OK ||
ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]))
- != NGX_OK ? NGX_ERROR : NGX_OK;
+ != NGX_OK ? NGX_ERROR : NGX_OK;
}
@@ -331,13 +332,13 @@
static ngx_rtmp_amf_elt_t in_elts[] = {
- { NGX_RTMP_AMF_NUMBER,
- ngx_null_string,
+ { NGX_RTMP_AMF_NUMBER,
+ ngx_null_string,
&v.trans, sizeof(v.trans) },
};
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
@@ -352,7 +353,7 @@
ngx_rtmp_cmd_create_stream(ngx_rtmp_session_t *s, ngx_rtmp_create_stream_t *v)
{
/* support one message stream per connection */
- static double stream;
+ static double stream;
static double trans;
ngx_rtmp_header_t h;
@@ -366,7 +367,7 @@
ngx_null_string,
&trans, 0 },
- { NGX_RTMP_AMF_NULL,
+ { NGX_RTMP_AMF_NULL,
ngx_null_string,
NULL, 0 },
@@ -402,7 +403,7 @@
&v.stream, 0 },
};
- if (ngx_rtmp_receive_amf(s, in, in_elts,
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
@@ -429,7 +430,7 @@
static ngx_rtmp_amf_elt_t in_elts[] = {
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_null_string,
NULL, 0 },
@@ -442,8 +443,8 @@
&v.stream, 0 },
};
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
@@ -475,7 +476,7 @@
/* transaction is always 0 */
{ NGX_RTMP_AMF_NUMBER,
- ngx_null_string,
+ ngx_null_string,
NULL, 0 },
{ NGX_RTMP_AMF_NULL,
@@ -493,8 +494,8 @@
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
@@ -524,7 +525,7 @@
static ngx_rtmp_amf_elt_t in_elts[] = {
/* transaction is always 0 */
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_null_string,
NULL, 0 },
@@ -551,7 +552,7 @@
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
@@ -562,8 +563,8 @@
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"play: 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,
+ v.name, v.args, (ngx_int_t) v.start,
+ (ngx_int_t) v.duration, (ngx_int_t) v.reset,
(ngx_int_t) v.silent);
return ngx_rtmp_play(s, &v);
@@ -578,6 +579,63 @@
static ngx_int_t
+ngx_rtmp_cmd_play2_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ ngx_chain_t *in)
+{
+ static ngx_rtmp_play_t v;
+ static ngx_rtmp_close_stream_t vc;
+
+ static ngx_rtmp_amf_elt_t in_obj[] = {
+
+ { NGX_RTMP_AMF_NUMBER,
+ ngx_string("start"),
+ &v.start, 0 },
+
+ { NGX_RTMP_AMF_STRING,
+ ngx_string("streamName"),
+ &v.name, sizeof(v.name) },
+ };
+
+ static ngx_rtmp_amf_elt_t in_elts[] = {
+
+ /* transaction is always 0 */
+ { NGX_RTMP_AMF_NUMBER,
+ ngx_null_string,
+ NULL, 0 },
+
+ { NGX_RTMP_AMF_NULL,
+ ngx_null_string,
+ NULL, 0 },
+
+ { NGX_RTMP_AMF_OBJECT,
+ ngx_null_string,
+ &in_obj, sizeof(in_obj) }
+ };
+
+ ngx_memzero(&v, sizeof(v));
+
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
+ {
+ return NGX_ERROR;
+ }
+
+ ngx_rtmp_cmd_fill_args(v.name, v.args);
+
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ "play2: name='%s' args='%s' start=%i",
+ v.name, v.args, (ngx_int_t) v.start);
+
+ ngx_memzero(&vc, sizeof(vc));
+
+ /* close_stream should be synchronous */
+ ngx_rtmp_close_stream(s, &vc);
+
+ return ngx_rtmp_play(s, &v);
+}
+
+
+static ngx_int_t
ngx_rtmp_cmd_pause_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
@@ -585,7 +643,7 @@
static ngx_rtmp_amf_elt_t in_elts[] = {
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_null_string,
NULL, 0 },
@@ -604,8 +662,8 @@
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
@@ -651,7 +709,7 @@
static ngx_rtmp_amf_elt_t in_elts[] = {
/* transaction is always 0 */
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_null_string,
NULL, 0 },
@@ -666,8 +724,8 @@
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
@@ -729,6 +787,7 @@
{ ngx_string("deleteStream"), ngx_rtmp_cmd_delete_stream_init },
{ ngx_string("publish"), ngx_rtmp_cmd_publish_init },
{ ngx_string("play"), ngx_rtmp_cmd_play_init },
+ { ngx_string("play2"), ngx_rtmp_cmd_play2_init },
{ ngx_string("seek"), ngx_rtmp_cmd_seek_init },
{ ngx_string("pause"), ngx_rtmp_cmd_pause_init },
{ ngx_string("pauseraw"), ngx_rtmp_cmd_pause_init },
@@ -745,7 +804,7 @@
cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
- /* redirect disconnects to deleteStream
+ /* redirect disconnects to deleteStream
* to free client modules from registering
* disconnect callback */
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_cmd_module.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -96,7 +97,11 @@
} ngx_rtmp_set_buflen_t;
-typedef ngx_int_t (*ngx_rtmp_connect_pt)(ngx_rtmp_session_t *s,
+void ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME],
+ u_char args[NGX_RTMP_MAX_ARGS]);
+
+
+typedef ngx_int_t (*ngx_rtmp_connect_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_connect_t *v);
typedef ngx_int_t (*ngx_rtmp_disconnect_pt)(ngx_rtmp_session_t *s);
typedef ngx_int_t (*ngx_rtmp_create_stream_pt)(ngx_rtmp_session_t *s,
@@ -105,13 +110,13 @@
ngx_rtmp_close_stream_t *v);
typedef ngx_int_t (*ngx_rtmp_delete_stream_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_delete_stream_t *v);
-typedef ngx_int_t (*ngx_rtmp_publish_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_publish_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_publish_t *v);
-typedef ngx_int_t (*ngx_rtmp_play_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_play_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_play_t *v);
-typedef ngx_int_t (*ngx_rtmp_seek_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_seek_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_seek_t *v);
-typedef ngx_int_t (*ngx_rtmp_pause_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_pause_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_pause_t *v);
typedef ngx_int_t (*ngx_rtmp_stream_begin_pt)(ngx_rtmp_session_t *s,
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_codec_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -8,6 +9,7 @@
#include "ngx_rtmp_codec_module.h"
#include "ngx_rtmp_live_module.h"
#include "ngx_rtmp_cmd_module.h"
+#include "ngx_rtmp_bitop.h"
#define NGX_RTMP_CODEC_META_OFF 0
@@ -16,7 +18,7 @@
static void * ngx_rtmp_codec_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_codec_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_codec_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf);
static ngx_int_t ngx_rtmp_codec_reconstruct_meta(ngx_rtmp_session_t *s);
@@ -24,6 +26,14 @@
ngx_rtmp_header_t *h, ngx_chain_t *in);
static ngx_int_t ngx_rtmp_codec_prepare_meta(ngx_rtmp_session_t *s,
uint32_t timestamp);
+static void ngx_rtmp_codec_parse_aac_header(ngx_rtmp_session_t *s,
+ ngx_chain_t *in);
+static void ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s,
+ ngx_chain_t *in);
+#if (NGX_DEBUG)
+static void ngx_rtmp_codec_dump_header(ngx_rtmp_session_t *s, const char *type,
+ ngx_chain_t *in);
+#endif
typedef struct {
@@ -36,7 +46,7 @@
{ ngx_string("on"), NGX_RTMP_CODEC_META_ON },
{ ngx_string("copy"), NGX_RTMP_CODEC_META_COPY },
{ ngx_null_string, 0 }
-};
+};
static ngx_command_t ngx_rtmp_codec_commands[] = {
@@ -80,7 +90,7 @@
};
-static const char *
+static const char *
audio_codecs[] = {
"",
"ADPCM",
@@ -102,7 +112,7 @@
};
-static const char *
+static const char *
video_codecs[] = {
"",
"Jpeg",
@@ -115,7 +125,7 @@
};
-u_char *
+u_char *
ngx_rtmp_get_audio_codec_name(ngx_uint_t id)
{
return (u_char *)(id < sizeof(audio_codecs) / sizeof(audio_codecs[0])
@@ -124,7 +134,7 @@
}
-u_char *
+u_char *
ngx_rtmp_get_video_codec_name(ngx_uint_t id)
{
return (u_char *)(id < sizeof(video_codecs) / sizeof(video_codecs[0])
@@ -148,7 +158,7 @@
static ngx_int_t
-ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_codec_ctx_t *ctx;
@@ -181,28 +191,20 @@
static ngx_int_t
-ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_core_srv_conf_t *cscf;
ngx_rtmp_codec_ctx_t *ctx;
ngx_chain_t **header;
uint8_t fmt;
- ngx_uint_t idx;
- u_char *p;
- static ngx_uint_t sample_rates[] =
+ static ngx_uint_t sample_rates[] =
{ 5512, 11025, 22050, 44100 };
- static ngx_uint_t aac_sample_rates[] =
- { 96000, 88200, 64000, 48000,
- 44100, 32000, 24000, 22050,
- 16000, 12000, 11025, 8000,
- 7350, 0, 0, 0 };
-
if (h->type != NGX_RTMP_MSG_AUDIO && h->type != NGX_RTMP_MSG_VIDEO) {
return NGX_OK;
}
-
+
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
if (ctx == NULL) {
ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_codec_ctx_t));
@@ -220,7 +222,7 @@
ctx->audio_channels = (fmt & 0x01) + 1;
ctx->sample_size = (fmt & 0x02) ? 2 : 1;
- if (ctx->aac_sample_rate == 0) {
+ if (ctx->sample_rate == 0) {
ctx->sample_rate = sample_rates[(fmt & 0x0c) >> 2];
}
} else {
@@ -239,64 +241,16 @@
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
header = NULL;
+
if (h->type == NGX_RTMP_MSG_AUDIO) {
if (ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) {
header = &ctx->aac_header;
-
- if (in->buf->last - in->buf->pos > 3) {
- p = in->buf->pos + 2;
-
- /* MPEG-4 Audio Specific Config
-
- 5 bits: object type
- if (object type == 31)
- 6 bits + 32: object type
- --->4 bits: frequency index
- if (frequency index == 15)
- 24 bits: frequency
- 4 bits: channel configuration
- var bits: AOT Specific Config
- */
-
- if ((p[0] >> 3) == 0x1f) {
- idx = (p[1] >> 1) & 0x0f;
- } else {
- idx = ((p[0] << 1) & 0x0f) | (p[1] >> 7);
- }
-
-#ifdef NGX_DEBUG
- {
- u_char buf[256], *p, *pp;
- u_char hex[] = "01234567890abcdef";
-
- for (pp = buf, p = in->buf->pos;
- p < in->buf->last && pp < buf + sizeof(buf) - 1;
- ++p)
- {
- *pp++ = hex[*p >> 4];
- *pp++ = hex[*p & 0x0f];
- }
-
- *pp = 0;
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: AAC header: %s", buf);
- }
-#endif
-
- ctx->aac_sample_rate = aac_sample_rates[idx];
- ctx->sample_rate = ctx->aac_sample_rate;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: AAC header arrived, sample_rate=%ui",
- ctx->aac_sample_rate);
+ ngx_rtmp_codec_parse_aac_header(s, in);
}
} else {
if (ctx->video_codec_id == NGX_RTMP_VIDEO_H264) {
header = &ctx->avc_header;
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "codec: AVC/H264 header arrived");
+ ngx_rtmp_codec_parse_avc_header(s, in);
}
}
@@ -314,6 +268,295 @@
}
+static void
+ngx_rtmp_codec_parse_aac_header(ngx_rtmp_session_t *s, ngx_chain_t *in)
+{
+ ngx_uint_t idx;
+ ngx_rtmp_codec_ctx_t *ctx;
+ ngx_rtmp_bit_reader_t br;
+
+ static ngx_uint_t aac_sample_rates[] =
+ { 96000, 88200, 64000, 48000,
+ 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000,
+ 7350, 0, 0, 0 };
+
+#if (NGX_DEBUG)
+ ngx_rtmp_codec_dump_header(s, "aac", in);
+#endif
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last);
+
+ ngx_rtmp_bit_read(&br, 16);
+
+ ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 5);
+ if (ctx->aac_profile == 31) {
+ ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 6) + 32;
+ }
+
+ idx = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4);
+ if (idx == 15) {
+ ctx->sample_rate = (ngx_uint_t) ngx_rtmp_bit_read(&br, 24);
+ } else {
+ ctx->sample_rate = aac_sample_rates[idx];
+ }
+
+ ctx->aac_chan_conf = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4);
+
+ if (ctx->aac_profile == 5 || ctx->aac_profile == 29) {
+
+ if (ctx->aac_profile == 29) {
+ ctx->aac_ps = 1;
+ }
+
+ ctx->aac_sbr = 1;
+
+ idx = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4);
+ if (idx == 15) {
+ ctx->sample_rate = (ngx_uint_t) ngx_rtmp_bit_read(&br, 24);
+ } else {
+ ctx->sample_rate = aac_sample_rates[idx];
+ }
+
+ ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 5);
+ if (ctx->aac_profile == 31) {
+ ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 6) + 32;
+ }
+ }
+
+ /* MPEG-4 Audio Specific Config
+
+ 5 bits: object type
+ if (object type == 31)
+ 6 bits + 32: object type
+ 4 bits: frequency index
+ if (frequency index == 15)
+ 24 bits: frequency
+ 4 bits: channel configuration
+
+ if (object_type == 5)
+ 4 bits: frequency index
+ if (frequency index == 15)
+ 24 bits: frequency
+ 5 bits: object type
+ if (object type == 31)
+ 6 bits + 32: object type
+
+ var bits: AOT Specific Config
+ */
+
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "codec: aac header profile=%ui, "
+ "sample_rate=%ui, chan_conf=%ui",
+ ctx->aac_profile, ctx->sample_rate, ctx->aac_chan_conf);
+}
+
+
+static void
+ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, ngx_chain_t *in)
+{
+ ngx_uint_t profile_idc, width, height, crop_left, crop_right,
+ crop_top, crop_bottom, frame_mbs_only, n, cf_idc,
+ num_ref_frames;
+ ngx_rtmp_codec_ctx_t *ctx;
+ ngx_rtmp_bit_reader_t br;
+
+#if (NGX_DEBUG)
+ ngx_rtmp_codec_dump_header(s, "avc", in);
+#endif
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
+
+ ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last);
+
+ ngx_rtmp_bit_read(&br, 48);
+
+ ctx->avc_profile = (ngx_uint_t) ngx_rtmp_bit_read_8(&br);
+ ctx->avc_compat = (ngx_uint_t) ngx_rtmp_bit_read_8(&br);
+ ctx->avc_level = (ngx_uint_t) ngx_rtmp_bit_read_8(&br);
+
+ /* nal bytes */
+ ctx->avc_nal_bytes = (ngx_uint_t) ((ngx_rtmp_bit_read_8(&br) & 0x03) + 1);
+
+ /* nnals */
+ if ((ngx_rtmp_bit_read_8(&br) & 0x1f) == 0) {
+ return;
+ }
+
+ /* nal size */
+ ngx_rtmp_bit_read(&br, 16);
+
+ /* nal type */
+ if (ngx_rtmp_bit_read_8(&br) != 0x67) {
+ return;
+ }
+
+ /* SPS */
+
+ /* profile idc */
+ profile_idc = (ngx_uint_t) ngx_rtmp_bit_read(&br, 8);
+
+ /* flags */
+ ngx_rtmp_bit_read(&br, 8);
+
+ /* level idc */
+ ngx_rtmp_bit_read(&br, 8);
+
+ /* SPS id */
+ ngx_rtmp_bit_read_golomb(&br);
+
+ if (profile_idc == 100 || profile_idc == 110 ||
+ profile_idc == 122 || profile_idc == 244 || profile_idc == 44 ||
+ profile_idc == 83 || profile_idc == 86 || profile_idc == 118)
+ {
+ /* chroma format idc */
+ cf_idc = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+
+ if (cf_idc == 3) {
+
+ /* separate color plane */
+ ngx_rtmp_bit_read(&br, 1);
+ }
+
+ /* bit depth luma - 8 */
+ ngx_rtmp_bit_read_golomb(&br);
+
+ /* bit depth chroma - 8 */
+ ngx_rtmp_bit_read_golomb(&br);
+
+ /* qpprime y zero transform bypass */
+ ngx_rtmp_bit_read(&br, 1);
+
+ /* seq scaling matrix present */
+ if (ngx_rtmp_bit_read(&br, 1)) {
+
+ for (n = 0; n < (cf_idc != 3 ? 8u : 12u); n++) {
+
+ /* seq scaling list present */
+ if (ngx_rtmp_bit_read(&br, 1)) {
+
+ /* TODO: scaling_list()
+ if (n < 6) {
+ } else {
+ }
+ */
+ }
+ }
+ }
+ }
+
+ /* log2 max frame num */
+ ngx_rtmp_bit_read_golomb(&br);
+
+ /* pic order cnt type */
+ switch (ngx_rtmp_bit_read_golomb(&br)) {
+ case 0:
+
+ /* max pic order cnt */
+ ngx_rtmp_bit_read_golomb(&br);
+ break;
+
+ case 1:
+
+ /* delta pic order alwys zero */
+ ngx_rtmp_bit_read(&br, 1);
+
+ /* offset for non-ref pic */
+ ngx_rtmp_bit_read_golomb(&br);
+
+ /* offset for top to bottom field */
+ ngx_rtmp_bit_read_golomb(&br);
+
+ /* num ref frames in pic order */
+ num_ref_frames = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+
+ for (n = 0; n < num_ref_frames; n++) {
+
+ /* offset for ref frame */
+ ngx_rtmp_bit_read_golomb(&br);
+ }
+ }
+
+ /* num ref frames */
+ ctx->avc_ref_frames = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+
+ /* gaps in frame num allowed */
+ ngx_rtmp_bit_read(&br, 1);
+
+ /* pic width in mbs - 1 */
+ width = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+
+ /* pic height in map units - 1 */
+ height = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+
+ /* frame mbs only flag */
+ frame_mbs_only = (ngx_uint_t) ngx_rtmp_bit_read(&br, 1);
+
+ if (!frame_mbs_only) {
+
+ /* mbs adaprive frame field */
+ ngx_rtmp_bit_read(&br, 1);
+ }
+
+ /* direct 8x8 inference flag */
+ ngx_rtmp_bit_read(&br, 1);
+
+ /* frame cropping */
+ if (ngx_rtmp_bit_read(&br, 1)) {
+
+ crop_left = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+ crop_right = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+ crop_top = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+ crop_bottom = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br);
+
+ } else {
+
+ crop_left = 0;
+ crop_right = 0;
+ crop_top = 0;
+ crop_bottom = 0;
+ }
+
+ ctx->width = (width + 1) * 16 - (crop_left + crop_right) * 2;
+ ctx->height = (2 - frame_mbs_only) * (height + 1) * 16 -
+ (crop_top + crop_bottom) * 2;
+
+ ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "codec: avc header "
+ "profile=%ui, compat=%ui, level=%ui, "
+ "nal_bytes=%ui, ref_frames=%ui, width=%ui, height=%ui",
+ ctx->avc_profile, ctx->avc_compat, ctx->avc_level,
+ ctx->avc_nal_bytes, ctx->avc_ref_frames,
+ ctx->width, ctx->height);
+}
+
+
+#if (NGX_DEBUG)
+static void
+ngx_rtmp_codec_dump_header(ngx_rtmp_session_t *s, const char *type,
+ ngx_chain_t *in)
+{
+ u_char buf[256], *p, *pp;
+ u_char hex[] = "0123456789abcdef";
+
+ for (pp = buf, p = in->buf->pos;
+ p < in->buf->last && pp < buf + sizeof(buf) - 1;
+ ++p)
+ {
+ *pp++ = hex[*p >> 4];
+ *pp++ = hex[*p & 0x0f];
+ }
+
+ *pp = 0;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "codec: %s header %s", type, buf);
+}
+#endif
+
+
static ngx_int_t
ngx_rtmp_codec_reconstruct_meta(ngx_rtmp_session_t *s)
{
@@ -340,47 +583,47 @@
ngx_string("Server"),
"NGINX RTMP (github.com/arut/nginx-rtmp-module)", 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("width"),
&v.width, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("height"),
&v.height, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("displayWidth"),
&v.width, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("displayHeight"),
&v.height, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("duration"),
&v.duration, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("framerate"),
&v.frame_rate, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("fps"),
&v.frame_rate, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("videodatarate"),
&v.video_data_rate, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("videocodecid"),
&v.video_codec_id, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("audiodatarate"),
&v.audio_data_rate, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("audiocodecid"),
&v.audio_codec_id, 0 },
@@ -395,11 +638,11 @@
static ngx_rtmp_amf_elt_t out_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
"onMetaData", 0 },
- { NGX_RTMP_AMF_OBJECT,
+ { NGX_RTMP_AMF_OBJECT,
ngx_null_string,
out_inf, sizeof(out_inf) },
};
@@ -427,7 +670,7 @@
ngx_memcpy(v.profile, ctx->profile, sizeof(ctx->profile));
ngx_memcpy(v.level, ctx->level, sizeof(ctx->level));
- rc = ngx_rtmp_append_amf(s, &ctx->meta, NULL, out_elts,
+ rc = ngx_rtmp_append_amf(s, &ctx->meta, NULL, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
if (rc != NGX_OK || ctx->meta == NULL) {
return NGX_ERROR;
@@ -437,8 +680,8 @@
}
-static ngx_int_t
-ngx_rtmp_codec_copy_meta(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+static ngx_int_t
+ngx_rtmp_codec_copy_meta(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_codec_ctx_t *ctx;
@@ -483,8 +726,8 @@
}
-static ngx_int_t
-ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+static ngx_int_t
+ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_codec_app_conf_t *cacf;
@@ -530,39 +773,39 @@
static ngx_rtmp_amf_elt_t in_inf[] = {
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("width"),
&v.width, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("height"),
&v.height, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("duration"),
&v.duration, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("framerate"),
&v.frame_rate, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("fps"),
&v.frame_rate, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("videodatarate"),
&v.video_data_rate, 0 },
- { NGX_RTMP_AMF_VARIANT,
+ { NGX_RTMP_AMF_VARIANT,
ngx_string("videocodecid"),
in_video_codec_id, sizeof(in_video_codec_id) },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("audiodatarate"),
&v.audio_data_rate, 0 },
- { NGX_RTMP_AMF_VARIANT,
+ { NGX_RTMP_AMF_VARIANT,
ngx_string("audiocodecid"),
in_audio_codec_id, sizeof(in_audio_codec_id) },
@@ -577,11 +820,11 @@
static ngx_rtmp_amf_elt_t in_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
NULL, 0 },
- { NGX_RTMP_AMF_OBJECT,
+ { NGX_RTMP_AMF_OBJECT,
ngx_null_string,
in_inf, sizeof(in_inf) },
};
@@ -598,13 +841,13 @@
/* use -1 as a sign of unchanged data;
* 0 is a valid value for uncompressed audio */
- v.audio_codec_id_n = -1;
+ v.audio_codec_id_n = -1;
/* FFmpeg sends a string in front of actal metadata; ignore it */
skip = !(in->buf->last > in->buf->pos
&& *in->buf->pos == NGX_RTMP_AMF_STRING);
- if (ngx_rtmp_receive_amf(s, in, in_elts + skip,
- sizeof(in_elts) / sizeof(in_elts[0]) - skip))
+ if (ngx_rtmp_receive_amf(s, in, in_elts + skip,
+ sizeof(in_elts) / sizeof(in_elts[0]) - skip))
{
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"codec: error parsing data frame");
@@ -629,9 +872,9 @@
"width=%ui height=%ui duration=%ui frame_rate=%ui "
"video=%s (%ui) audio=%s (%ui)",
ctx->width, ctx->height, ctx->duration, ctx->frame_rate,
- ngx_rtmp_get_video_codec_name(ctx->video_codec_id),
+ ngx_rtmp_get_video_codec_name(ctx->video_codec_id),
ctx->video_codec_id,
- ngx_rtmp_get_audio_codec_name(ctx->audio_codec_id),
+ ngx_rtmp_get_audio_codec_name(ctx->audio_codec_id),
ctx->audio_codec_id);
switch (cacf->meta) {
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_codec_module.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -57,7 +58,15 @@
ngx_uint_t video_codec_id;
ngx_uint_t audio_data_rate;
ngx_uint_t audio_codec_id;
- ngx_uint_t aac_sample_rate;
+ ngx_uint_t aac_profile;
+ ngx_uint_t aac_chan_conf;
+ ngx_uint_t aac_sbr;
+ ngx_uint_t aac_ps;
+ ngx_uint_t avc_profile;
+ ngx_uint_t avc_compat;
+ ngx_uint_t avc_level;
+ ngx_uint_t avc_nal_bytes;
+ ngx_uint_t avc_ref_frames;
ngx_uint_t sample_rate; /* 5512, 11025, 22050, 44100 */
ngx_uint_t sample_size; /* 1=8bit, 2=16bit */
ngx_uint_t audio_channels; /* 1, 2 */
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_control_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -13,26 +14,34 @@
static char *ngx_rtmp_control(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void * ngx_rtmp_control_create_loc_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_control_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-
-typedef struct {
- ngx_rtmp_core_main_conf_t *cmcf;
- ngx_rtmp_core_srv_conf_t *cscf;
- ngx_rtmp_core_app_conf_t *cacf;
-} ngx_rtmp_control_core_t;
+static char * ngx_rtmp_control_merge_loc_conf(ngx_conf_t *cf,
+ void *parent, void *child);
-typedef struct {
- ngx_rtmp_live_app_conf_t *lacf;
- ngx_rtmp_live_stream_t *ls;
-} ngx_rtmp_control_live_t;
+typedef const char * (*ngx_rtmp_control_handler_t)(ngx_http_request_t *r,
+ ngx_rtmp_session_t *);
#define NGX_RTMP_CONTROL_ALL 0xff
#define NGX_RTMP_CONTROL_RECORD 0x01
#define NGX_RTMP_CONTROL_DROP 0x02
+#define NGX_RTMP_CONTROL_REDIRECT 0x04
+
+
+enum {
+ NGX_RTMP_CONTROL_FILTER_CLIENT = 0,
+ NGX_RTMP_CONTROL_FILTER_PUBLISHER,
+ NGX_RTMP_CONTROL_FILTER_SUBSCRIBER
+};
+
+
+typedef struct {
+ ngx_uint_t count;
+ ngx_str_t path;
+ ngx_uint_t filter;
+ ngx_str_t method;
+ ngx_array_t sessions; /* ngx_rtmp_session_t * */
+} ngx_rtmp_control_ctx_t;
typedef struct {
@@ -44,8 +53,9 @@
{ ngx_string("all"), NGX_RTMP_CONTROL_ALL },
{ ngx_string("record"), NGX_RTMP_CONTROL_RECORD },
{ ngx_string("drop"), NGX_RTMP_CONTROL_DROP },
+ { ngx_string("redirect"), NGX_RTMP_CONTROL_REDIRECT },
{ ngx_null_string, 0 }
-};
+};
static ngx_command_t ngx_rtmp_control_commands[] = {
@@ -62,42 +72,42 @@
static ngx_http_module_t ngx_rtmp_control_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
- NULL, /* create main configuration */
- NULL, /* init main configuration */
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
- ngx_rtmp_control_create_loc_conf, /* create location configuration */
- ngx_rtmp_control_merge_loc_conf, /* merge location configuration */
+ ngx_rtmp_control_create_loc_conf, /* create location configuration */
+ ngx_rtmp_control_merge_loc_conf, /* merge location configuration */
};
ngx_module_t ngx_rtmp_control_module = {
- NGX_MODULE_V1,
- &ngx_rtmp_control_module_ctx, /* module context */
- ngx_rtmp_control_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
+ NGX_MODULE_V1,
+ &ngx_rtmp_control_module_ctx, /* module context */
+ ngx_rtmp_control_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_rtmp_control_output_error(ngx_http_request_t *r, const char *msg)
{
- size_t len;
- ngx_buf_t *b;
- ngx_chain_t cl;
+ size_t len;
+ ngx_buf_t *b;
+ ngx_chain_t cl;
len = ngx_strlen(msg);
@@ -124,58 +134,121 @@
static const char *
-ngx_rtmp_control_parse_core(ngx_http_request_t *r,
- ngx_rtmp_control_core_t *core)
+ngx_rtmp_control_record_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s)
{
- ngx_str_t srv, app;
- ngx_uint_t sn, n;
- ngx_rtmp_core_srv_conf_t **pcscf;
- ngx_rtmp_core_app_conf_t **pcacf;
+ ngx_int_t rc;
+ ngx_str_t rec;
+ ngx_uint_t rn;
+ ngx_rtmp_control_ctx_t *ctx;
+ ngx_rtmp_core_app_conf_t *cacf;
+ ngx_rtmp_record_app_conf_t *racf;
-
- core->cmcf = ngx_rtmp_core_main_conf;
- if (core->cmcf == NULL) {
- return "Missing main RTMP conf";
+ cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module);
+ racf = cacf->app_conf[ngx_rtmp_record_module.ctx_index];
+
+ if (ngx_http_arg(r, (u_char *) "rec", sizeof("rec") - 1, &rec) != NGX_OK) {
+ rec.len = 0;
}
- /* find server */
- sn = 0;
+ rn = ngx_rtmp_record_find(racf, &rec);
+ if (rn == NGX_CONF_UNSET_UINT) {
+ return "Recorder not found";
+ }
- if (ngx_http_arg(r, (u_char *) "srv", sizeof("srv") - 1, &srv) == NGX_OK) {
- sn = ngx_atoi(srv.data, srv.len);
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+
+ if (ctx->method.len == sizeof("start") - 1 &&
+ ngx_strncmp(ctx->method.data, "start", ctx->method.len) == 0)
+ {
+ rc = ngx_rtmp_record_open(s, rn, &ctx->path);
+
+ } else if (ctx->method.len == sizeof("stop") - 1 &&
+ ngx_strncmp(ctx->method.data, "stop", ctx->method.len) == 0)
+ {
+ rc = ngx_rtmp_record_close(s, rn, &ctx->path);
+
+ } else {
+ return "Undefined method";
}
- if (sn >= core->cmcf->servers.nelts) {
- return "Server index out of range";
+ if (rc == NGX_ERROR) {
+ return "Recorder error";
}
- pcscf = core->cmcf->servers.elts;
- pcscf += sn;
+ return NGX_CONF_OK;
+}
- core->cscf = *pcscf;
- /* find application */
- if (ngx_http_arg(r, (u_char *) "app", sizeof("app") - 1, &app) != NGX_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "rtmp_control: app not specified");
- return "Application not specified";
+static const char *
+ngx_rtmp_control_drop_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s)
+{
+ ngx_rtmp_control_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(s, ngx_rtmp_control_module);
+
+ ngx_rtmp_finalize_session(s);
+
+ ++ctx->count;
+
+ return NGX_CONF_OK;
+}
+
+
+static const char *
+ngx_rtmp_control_redirect_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s)
+{
+ ngx_str_t name;
+ ngx_rtmp_play_t vplay;
+ ngx_rtmp_publish_t vpublish;
+ ngx_rtmp_live_ctx_t *lctx;
+ ngx_rtmp_control_ctx_t *ctx;
+ ngx_rtmp_close_stream_t vc;
+
+ if (ngx_http_arg(r, (u_char *) "newname", sizeof("newname") - 1, &name)
+ != NGX_OK)
+ {
+ return "newname not specified";
}
- core->cacf = NULL;
+ if (name.len >= NGX_RTMP_MAX_NAME) {
+ name.len = NGX_RTMP_MAX_NAME - 1;
+ }
- pcacf = core->cscf->applications.elts;
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+ ctx->count++;
- for (n = 0; n < core->cscf->applications.nelts; ++n, ++pcacf) {
- if ((*pcacf)->name.len == app.len &&
- ngx_strncmp((*pcacf)->name.data, app.data, app.len) == 0)
- {
- core->cacf = *pcacf;
- break;
+ ngx_memzero(&vc, sizeof(ngx_rtmp_close_stream_t));
+
+ /* close_stream should be synchronous */
+ ngx_rtmp_close_stream(s, &vc);
+
+ lctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module);
+
+ if (lctx && lctx->publishing) {
+ /* publish */
+
+ ngx_memzero(&vpublish, sizeof(ngx_rtmp_publish_t));
+
+ ngx_memcpy(vpublish.name, name.data, name.len);
+
+ ngx_rtmp_cmd_fill_args(vpublish.name, vpublish.args);
+
+ if (ngx_rtmp_publish(s, &vpublish) != NGX_OK) {
+ return "publish failed";
}
- }
- if (core->cacf == NULL) {
- return "Application not found";
+ } else {
+ /* play */
+
+ ngx_memzero(&vplay, sizeof(ngx_rtmp_play_t));
+
+ ngx_memcpy(vplay.name, name.data, name.len);
+
+ ngx_rtmp_cmd_fill_args(vplay.name, vplay.args);
+
+ if (ngx_rtmp_play(s, &vplay) != NGX_OK) {
+ return "play failed";
+ }
}
return NGX_CONF_OK;
@@ -183,132 +256,220 @@
static const char *
-ngx_rtmp_control_parse_live(ngx_http_request_t *r,
- ngx_rtmp_control_core_t *core,
- ngx_rtmp_control_live_t *live)
+ngx_rtmp_control_walk_session(ngx_http_request_t *r,
+ ngx_rtmp_live_ctx_t *lctx)
{
- ngx_str_t name;
- size_t len;
+ ngx_str_t addr, *paddr;
+ ngx_rtmp_session_t *s, **ss;
+ ngx_rtmp_control_ctx_t *ctx;
- ngx_memzero(&name, sizeof(name));
- ngx_http_arg(r, (u_char *) "name", sizeof("name") - 1, &name);
+ s = lctx->session;
- live->lacf = core->cacf->app_conf[ngx_rtmp_live_module.ctx_index];
+ if (s == NULL || s->connection == NULL) {
+ return NGX_CONF_OK;
+ }
- /* find live stream by name */
- for (live->ls = live->lacf->streams[ngx_hash_key(name.data, name.len) %
- live->lacf->nbuckets];
- live->ls; live->ls = live->ls->next)
+ if (ngx_http_arg(r, (u_char *) "addr", sizeof("addr") - 1, &addr)
+ == NGX_OK)
{
- len = ngx_strlen(live->ls->name);
-
- if (name.len == len && ngx_strncmp(name.data, live->ls->name, name.len)
- == 0)
+ paddr = &s->connection->addr_text;
+ if (paddr->len != addr.len ||
+ ngx_strncmp(paddr->data, addr.data, addr.len))
{
- break;
+ return NGX_CONF_OK;
}
}
- if (live->ls == NULL) {
- return "Live stream not found";
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+
+ switch (ctx->filter) {
+ case NGX_RTMP_CONTROL_FILTER_PUBLISHER:
+ if (!lctx->publishing) {
+ return NGX_CONF_OK;
+ }
+ break;
+
+ case NGX_RTMP_CONTROL_FILTER_SUBSCRIBER:
+ if (lctx->publishing) {
+ return NGX_CONF_OK;
+ }
+ break;
+
+ case NGX_RTMP_CONTROL_FILTER_CLIENT:
+ break;
}
+ ss = ngx_array_push(&ctx->sessions);
+ if (ss == NULL) {
+ return "allocation error";
+ }
+
+ *ss = s;
+
return NGX_CONF_OK;
}
-/* /record arguments:
- * srv - server index (optional)
- * app - application name
- * name - stream name
- * rec - recorder name
- */
+static const char *
+ngx_rtmp_control_walk_stream(ngx_http_request_t *r,
+ ngx_rtmp_live_stream_t *ls)
+{
+ const char *s;
+ ngx_rtmp_live_ctx_t *lctx;
+ for (lctx = ls->ctx; lctx; lctx = lctx->next) {
+ s = ngx_rtmp_control_walk_session(r, lctx);
+ if (s != NGX_CONF_OK) {
+ return s;
+ }
+ }
-static ngx_int_t
-ngx_rtmp_control_record(ngx_http_request_t *r, ngx_str_t *method)
+ return NGX_CONF_OK;
+}
+
+
+static const char *
+ngx_rtmp_control_walk_app(ngx_http_request_t *r,
+ ngx_rtmp_core_app_conf_t *cacf)
{
- ngx_rtmp_control_core_t core;
- ngx_rtmp_control_live_t live;
- ngx_rtmp_record_app_conf_t *racf;
- ngx_rtmp_live_ctx_t *lctx;
- ngx_rtmp_session_t *s;
- ngx_chain_t cl;
- ngx_uint_t rn;
- ngx_str_t rec, path;
- ngx_buf_t *b;
- ngx_int_t rc;
- const char *msg;
+ size_t len;
+ ngx_str_t name;
+ const char *s;
+ ngx_uint_t n;
+ ngx_rtmp_live_stream_t *ls;
+ ngx_rtmp_live_app_conf_t *lacf;
- msg = ngx_rtmp_control_parse_core(r, &core);
- if (msg != NGX_CONF_OK) {
- goto error;
- }
+ lacf = cacf->app_conf[ngx_rtmp_live_module.ctx_index];
- msg = ngx_rtmp_control_parse_live(r, &core, &live);
- if (msg != NGX_CONF_OK) {
- goto error;
+ if (ngx_http_arg(r, (u_char *) "name", sizeof("name") - 1, &name) != NGX_OK)
+ {
+ for (n = 0; n < (ngx_uint_t) lacf->nbuckets; ++n) {
+ for (ls = lacf->streams[n]; ls; ls = ls->next) {
+ s = ngx_rtmp_control_walk_stream(r, ls);
+ if (s != NGX_CONF_OK) {
+ return s;
+ }
+ }
+ }
+
+ return NGX_CONF_OK;
}
- /* find publisher context */
- for (lctx = live.ls->ctx; lctx; lctx = lctx->next) {
- if (lctx->publishing) {
- break;
+ for (ls = lacf->streams[ngx_hash_key(name.data, name.len) % lacf->nbuckets];
+ ls; ls = ls->next)
+ {
+ len = ngx_strlen(ls->name);
+ if (name.len != len || ngx_strncmp(name.data, ls->name, name.len)) {
+ continue;
+ }
+
+ s = ngx_rtmp_control_walk_stream(r, ls);
+ if (s != NGX_CONF_OK) {
+ return s;
}
}
- if (lctx == NULL) {
- msg = "No publisher";
- goto error;
+ return NGX_CONF_OK;
+}
+
+
+static const char *
+ngx_rtmp_control_walk_server(ngx_http_request_t *r,
+ ngx_rtmp_core_srv_conf_t *cscf)
+{
+ ngx_str_t app;
+ ngx_uint_t n;
+ const char *s;
+ ngx_rtmp_core_app_conf_t **pcacf;
+
+ if (ngx_http_arg(r, (u_char *) "app", sizeof("app") - 1, &app) != NGX_OK) {
+ app.len = 0;
}
- s = lctx->session;
+ pcacf = cscf->applications.elts;
- /* find recorder */
- ngx_memzero(&rec, sizeof(rec));
- ngx_http_arg(r, (u_char *) "rec", sizeof("rec") - 1, &rec);
+ for (n = 0; n < cscf->applications.nelts; ++n, ++pcacf) {
+ if (app.len && ((*pcacf)->name.len != app.len ||
+ ngx_strncmp((*pcacf)->name.data, app.data, app.len)))
+ {
+ continue;
+ }
- racf = core.cacf->app_conf[ngx_rtmp_record_module.ctx_index];
+ s = ngx_rtmp_control_walk_app(r, *pcacf);
+ if (s != NGX_CONF_OK) {
+ return s;
+ }
+ }
- rn = ngx_rtmp_record_find(racf, &rec);
- if (rn == NGX_CONF_UNSET_UINT) {
- msg = "Recorder not found";
- goto error;
+ return NGX_CONF_OK;
+}
+
+
+static const char *
+ngx_rtmp_control_walk(ngx_http_request_t *r, ngx_rtmp_control_handler_t h)
+{
+ ngx_rtmp_core_main_conf_t *cmcf = ngx_rtmp_core_main_conf;
+
+ ngx_str_t srv;
+ ngx_uint_t sn, n;
+ const char *msg;
+ ngx_rtmp_session_t **s;
+ ngx_rtmp_control_ctx_t *ctx;
+ ngx_rtmp_core_srv_conf_t **pcscf;
+
+ sn = 0;
+ if (ngx_http_arg(r, (u_char *) "srv", sizeof("srv") - 1, &srv) == NGX_OK) {
+ sn = ngx_atoi(srv.data, srv.len);
}
- /* call the method */
- ngx_memzero(&path, sizeof(path));
+ if (sn >= cmcf->servers.nelts) {
+ return "Server index out of range";
+ }
- if (method->len == sizeof("start") - 1 &&
- ngx_strncmp(method->data, "start", method->len) == 0)
- {
- rc = ngx_rtmp_record_open(s, rn, &path);
+ pcscf = cmcf->servers.elts;
+ pcscf += sn;
- } else if (method->len == sizeof("stop") - 1 &&
- ngx_strncmp(method->data, "stop", method->len) == 0)
- {
- rc = ngx_rtmp_record_close(s, rn, &path);
+ msg = ngx_rtmp_control_walk_server(r, *pcscf);
+ if (msg != NGX_CONF_OK) {
+ return msg;
+ }
- } else {
- msg = "Undefined method";
- goto error;
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+
+ s = ctx->sessions.elts;
+ for (n = 0; n < ctx->sessions.nelts; n++) {
+ msg = h(r, s[n]);
+ if (msg != NGX_CONF_OK) {
+ return msg;
+ }
}
- if (rc == NGX_ERROR) {
- msg = "Recorder error";
+ return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_control_record(ngx_http_request_t *r, ngx_str_t *method)
+{
+ ngx_buf_t *b;
+ const char *msg;
+ ngx_chain_t cl;
+ ngx_rtmp_control_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER;
+
+ msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_record_handler);
+ if (msg != NGX_CONF_OK) {
goto error;
}
- if (rc == NGX_AGAIN) {
- /* already opened/closed */
- ngx_str_null(&path);
- r->header_only = 1;
- }
+ /* output record path */
r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = path.len;
+ r->headers_out.content_length_n = ctx->path.len;
- b = ngx_create_temp_buf(r->pool, path.len);
+ b = ngx_create_temp_buf(r->pool, ctx->path.len);
if (b == NULL) {
return NGX_ERROR;
}
@@ -316,9 +477,9 @@
ngx_memzero(&cl, sizeof(cl));
cl.buf = b;
- b->last = ngx_cpymem(b->pos, path.data, path.len);
+ b->last = ngx_cpymem(b->pos, ctx->path.data, ctx->path.len);
b->last_buf = 1;
-
+
ngx_http_send_header(r);
return ngx_http_output_filter(r, &cl);
@@ -331,66 +492,116 @@
static ngx_int_t
ngx_rtmp_control_drop(ngx_http_request_t *r, ngx_str_t *method)
{
- ngx_rtmp_control_core_t core;
- ngx_rtmp_control_live_t live;
- ngx_rtmp_live_ctx_t *lctx;
- ngx_str_t addr, *paddr;
- const char *msg;
- ngx_uint_t ndropped;
- size_t len;
- u_char *p;
- ngx_buf_t *b;
- ngx_chain_t cl;
+ size_t len;
+ u_char *p;
+ ngx_buf_t *b;
+ ngx_chain_t cl;
+ const char *msg;
+ ngx_rtmp_control_ctx_t *ctx;
- msg = ngx_rtmp_control_parse_core(r, &core);
- if (msg != NGX_CONF_OK) {
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+
+ if (ctx->method.len == sizeof("publisher") - 1 &&
+ ngx_memcmp(ctx->method.data, "publisher", ctx->method.len) == 0)
+ {
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER;
+
+ } else if (ctx->method.len == sizeof("subscriber") - 1 &&
+ ngx_memcmp(ctx->method.data, "subscriber", ctx->method.len)
+ == 0)
+ {
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_SUBSCRIBER;
+
+ } else if (method->len == sizeof("client") - 1 &&
+ ngx_memcmp(ctx->method.data, "client", ctx->method.len) == 0)
+ {
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_CLIENT;
+
+ } else {
+ msg = "Undefined filter";
goto error;
}
- msg = ngx_rtmp_control_parse_live(r, &core, &live);
+ msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_drop_handler);
if (msg != NGX_CONF_OK) {
goto error;
}
- ndropped = 0;
+ /* output count */
- if (method->len == sizeof("publisher") - 1 &&
- ngx_strncmp(method->data, "publisher", method->len) == 0)
- {
- for (lctx = live.ls->ctx; lctx; lctx = lctx->next) {
- if (lctx->publishing) {
- ngx_rtmp_finalize_session(lctx->session);
- ++ndropped;
- break;
- }
- }
+ len = NGX_INT_T_LEN;
- } else if (method->len == sizeof("client") - 1 &&
- ngx_strncmp(method->data, "client", method->len) == 0)
+ p = ngx_palloc(r->connection->pool, len);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ len = (size_t) (ngx_snprintf(p, len, "%ui", ctx->count) - p);
+
+ r->headers_out.status = NGX_HTTP_OK;
+ r->headers_out.content_length_n = len;
+
+ b = ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ b->start = b->pos = p;
+ b->end = b->last = p + len;
+ b->temporary = 1;
+ b->last_buf = 1;
+
+ ngx_memzero(&cl, sizeof(cl));
+ cl.buf = b;
+
+ ngx_http_send_header(r);
+
+ return ngx_http_output_filter(r, &cl);
+
+error:
+ return ngx_rtmp_control_output_error(r, msg);
+}
+
+
+static ngx_int_t
+ngx_rtmp_control_redirect(ngx_http_request_t *r, ngx_str_t *method)
+{
+ size_t len;
+ u_char *p;
+ ngx_buf_t *b;
+ ngx_chain_t cl;
+ const char *msg;
+ ngx_rtmp_control_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module);
+
+ if (ctx->method.len == sizeof("publisher") - 1 &&
+ ngx_memcmp(ctx->method.data, "publisher", ctx->method.len) == 0)
{
- ngx_memzero(&addr, sizeof(addr));
- ngx_http_arg(r, (u_char *) "addr", sizeof("addr") - 1, &addr);
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER;
- for (lctx = live.ls->ctx; lctx; lctx = lctx->next) {
- if (addr.len && lctx->session && lctx->session->connection) {
- paddr = &lctx->session->connection->addr_text;
- if (paddr->len != addr.len ||
- ngx_strncmp(paddr->data, addr.data, addr.len))
- {
- continue;
- }
- }
+ } else if (ctx->method.len == sizeof("subscriber") - 1 &&
+ ngx_memcmp(ctx->method.data, "subscriber", ctx->method.len)
+ == 0)
+ {
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_SUBSCRIBER;
- ngx_rtmp_finalize_session(lctx->session);
- ++ndropped;
- }
+ } else if (ctx->method.len == sizeof("client") - 1 &&
+ ngx_memcmp(ctx->method.data, "client", ctx->method.len) == 0)
+ {
+ ctx->filter = NGX_RTMP_CONTROL_FILTER_CLIENT;
} else {
- msg = "Undefined method";
+ msg = "Undefined filter";
goto error;
}
- /* output ndropped */
+ msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_redirect_handler);
+ if (msg != NGX_CONF_OK) {
+ goto error;
+ }
+
+ /* output count */
len = NGX_INT_T_LEN;
@@ -399,7 +610,7 @@
return NGX_ERROR;
}
- len = (size_t) (ngx_snprintf(p, len, "%ui", ndropped) - p);
+ len = (size_t) (ngx_snprintf(p, len, "%ui", ctx->count) - p);
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = len;
@@ -429,10 +640,11 @@
static ngx_int_t
ngx_rtmp_control_handler(ngx_http_request_t *r)
{
- ngx_rtmp_control_loc_conf_t *llcf;
- ngx_str_t section, method;
- u_char *p;
- ngx_uint_t n;
+ u_char *p;
+ ngx_str_t section, method;
+ ngx_uint_t n;
+ ngx_rtmp_control_ctx_t *ctx;
+ ngx_rtmp_control_loc_conf_t *llcf;
llcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_control_module);
if (llcf->control == 0) {
@@ -440,8 +652,9 @@
}
/* uri format: .../section/method?args */
- ngx_memzero(§ion, sizeof(section));
- ngx_memzero(&method, sizeof(method));
+
+ ngx_str_null(§ion);
+ ngx_str_null(&method);
for (n = r->uri.len; n; --n) {
p = &r->uri.data[n - 1];
@@ -464,6 +677,18 @@
"rtmp_control: section='%V' method='%V'",
§ion, &method);
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_rtmp_control_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_rtmp_control_module);
+
+ if (ngx_array_init(&ctx->sessions, r->pool, 1, sizeof(void *)) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ ctx->method = method;
#define NGX_RTMP_CONTROL_SECTION(flag, secname) \
if (llcf->control & NGX_RTMP_CONTROL_##flag && \
@@ -475,10 +700,10 @@
NGX_RTMP_CONTROL_SECTION(RECORD, record);
NGX_RTMP_CONTROL_SECTION(DROP, drop);
+ NGX_RTMP_CONTROL_SECTION(REDIRECT, redirect);
#undef NGX_RTMP_CONTROL_SECTION
-
return NGX_DECLINED;
}
@@ -486,7 +711,7 @@
static void *
ngx_rtmp_control_create_loc_conf(ngx_conf_t *cf)
{
- ngx_rtmp_control_loc_conf_t *conf;
+ ngx_rtmp_control_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_control_loc_conf_t));
if (conf == NULL) {
@@ -502,8 +727,8 @@
static char *
ngx_rtmp_control_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
- ngx_rtmp_control_loc_conf_t *prev = parent;
- ngx_rtmp_control_loc_conf_t *conf = child;
+ ngx_rtmp_control_loc_conf_t *prev = parent;
+ ngx_rtmp_control_loc_conf_t *conf = child;
ngx_conf_merge_bitmask_value(conf->control, prev->control, 0);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_core_module.c
^
|
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -30,7 +30,7 @@
static ngx_conf_deprecated_t ngx_conf_deprecated_so_keepalive = {
- ngx_conf_deprecated, "so_keepalive",
+ ngx_conf_deprecated, "so_keepalive",
"so_keepalive\" parameter of the \"listen"
};
@@ -260,10 +260,10 @@
ngx_conf_merge_value(conf->max_streams, prev->max_streams, 32);
ngx_conf_merge_value(conf->chunk_size, prev->chunk_size, 4096);
ngx_conf_merge_uint_value(conf->ack_window, prev->ack_window, 5000000);
- ngx_conf_merge_size_value(conf->max_message, prev->max_message,
+ ngx_conf_merge_size_value(conf->max_message, prev->max_message,
1 * 1024 * 1024);
ngx_conf_merge_size_value(conf->out_queue, prev->out_queue, 256);
- ngx_conf_merge_size_value(conf->out_cork, prev->out_cork,
+ ngx_conf_merge_size_value(conf->out_cork, prev->out_cork,
conf->out_queue / 8);
ngx_conf_merge_value(conf->play_time_fix, prev->play_time_fix, 1);
ngx_conf_merge_value(conf->publish_time_fix, prev->publish_time_fix, 1);
@@ -437,7 +437,7 @@
module = ngx_modules[i]->ctx;
if (module->create_app_conf) {
- ctx->app_conf[ngx_modules[i]->ctx_index] =
+ ctx->app_conf[ngx_modules[i]->ctx_index] =
module->create_app_conf(cf);
if (ctx->app_conf[ngx_modules[i]->ctx_index] == NULL) {
return NGX_CONF_ERROR;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_eval.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -12,17 +13,17 @@
static void
-ngx_rtmp_eval_session_str(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e,
- ngx_str_t *ret)
+ngx_rtmp_eval_session_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret)
{
- *ret = *(ngx_str_t *) ((u_char *) s + e->offset);
+ *ret = *(ngx_str_t *) ((u_char *) ctx + e->offset);
}
static void
-ngx_rtmp_eval_connection_str(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e,
- ngx_str_t *ret)
+ngx_rtmp_eval_connection_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret)
{
+ ngx_rtmp_session_t *s = ctx;
+
*ret = *(ngx_str_t *) ((u_char *) s->connection + e->offset);
}
@@ -58,15 +59,14 @@
static void
-ngx_rtmp_eval_append(ngx_rtmp_session_t *s, ngx_buf_t *b,
- void *data, size_t len)
+ngx_rtmp_eval_append(ngx_buf_t *b, void *data, size_t len, ngx_log_t *log)
{
size_t buf_len;
if (b->last + len > b->end) {
buf_len = 2 * (b->last - b->pos) + len;
- b->start = ngx_palloc(s->connection->pool, buf_len);
+ b->start = ngx_alloc(buf_len, log);
if (b->start == NULL) {
return;
}
@@ -81,8 +81,8 @@
static void
-ngx_rtmp_eval_append_var(ngx_rtmp_session_t *s, ngx_buf_t *b,
- ngx_rtmp_eval_t **e, ngx_str_t *name)
+ngx_rtmp_eval_append_var(void *ctx, ngx_buf_t *b, ngx_rtmp_eval_t **e,
+ ngx_str_t *name, ngx_log_t *log)
{
ngx_uint_t k;
ngx_str_t v;
@@ -91,10 +91,10 @@
for (; *e; ++e) {
for (k = 0, ee = *e; ee->handler; ++k, ++ee) {
if (ee->name.len == name->len &&
- ngx_memcmp(ee->name.data, name->data, name->len) == 0)
+ ngx_memcmp(ee->name.data, name->data, name->len) == 0)
{
- ee->handler(s, ee, &v);
- ngx_rtmp_eval_append(s, b, v.data, v.len);
+ ee->handler(ctx, ee, &v);
+ ngx_rtmp_eval_append(b, v.data, v.len, log);
}
}
}
@@ -102,8 +102,8 @@
ngx_int_t
-ngx_rtmp_eval(ngx_rtmp_session_t *s, ngx_str_t *in, ngx_rtmp_eval_t **e,
- ngx_str_t *out)
+ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, ngx_str_t *out,
+ ngx_log_t *log)
{
u_char c, *p;
ngx_str_t name;
@@ -117,8 +117,7 @@
SNAME
} state = NORMAL;
- b.pos = b.last = b.start = ngx_palloc(s->connection->pool,
- NGX_RTMP_EVAL_BUFLEN);
+ b.pos = b.last = b.start = ngx_alloc(NGX_RTMP_EVAL_BUFLEN, log);
if (b.pos == NULL) {
return NGX_ERROR;
}
@@ -137,7 +136,7 @@
}
name.len = p - name.data;
- ngx_rtmp_eval_append_var(s, &b, e, &name);
+ ngx_rtmp_eval_append_var(ctx, &b, e, &name, log);
state = NORMAL;
@@ -154,7 +153,7 @@
}
name.len = p - name.data;
- ngx_rtmp_eval_append_var(s, &b, e, &name);
+ ngx_rtmp_eval_append_var(ctx, &b, e, &name, log);
case NORMAL:
switch (c) {
@@ -168,7 +167,7 @@
}
case ESCAPE:
- ngx_rtmp_eval_append(s, &b, &c, 1);
+ ngx_rtmp_eval_append(&b, &c, 1, log);
state = NORMAL;
break;
@@ -178,11 +177,11 @@
if (state == NAME) {
p = &in->data[n];
name.len = p - name.data;
- ngx_rtmp_eval_append_var(s, &b, e, &name);
+ ngx_rtmp_eval_append_var(ctx, &b, e, &name, log);
}
c = 0;
- ngx_rtmp_eval_append(s, &b, &c, 1);
+ ngx_rtmp_eval_append(&b, &c, 1, log);
out->data = b.pos;
out->len = b.last - b.pos - 1;
@@ -247,7 +246,7 @@
}
if (*path == (u_char) '&') {
-
+
path++;
v = ngx_atoi(path, in->data + in->len - path);
if (v == NGX_ERROR) {
@@ -271,7 +270,7 @@
}
dup2(src, dst);
-
+
if (close_src) {
ngx_close_file(src);
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_eval.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -15,7 +16,7 @@
typedef struct ngx_rtmp_eval_s ngx_rtmp_eval_t;
-typedef void (* ngx_rtmp_eval_pt)(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e,
+typedef void (* ngx_rtmp_eval_pt)(void *ctx, ngx_rtmp_eval_t *e,
ngx_str_t *ret);
@@ -33,8 +34,8 @@
extern ngx_rtmp_eval_t ngx_rtmp_eval_session[];
-ngx_int_t ngx_rtmp_eval(ngx_rtmp_session_t *s, ngx_str_t *in,
- ngx_rtmp_eval_t **e, ngx_str_t *out);
+ngx_int_t ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e,
+ ngx_str_t *out, ngx_log_t *log);
ngx_int_t ngx_rtmp_eval_streams(ngx_str_t *in);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_exec_module.c
^
|
@@ -1,11 +1,13 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include "ngx_rtmp_cmd_module.h"
+#include "ngx_rtmp_record_module.h"
#include "ngx_rtmp_eval.h"
#include <stdlib.h>
@@ -16,7 +18,9 @@
#if !(NGX_WIN32)
static ngx_rtmp_publish_pt next_publish;
+static ngx_rtmp_play_pt next_play;
static ngx_rtmp_close_stream_pt next_close_stream;
+static ngx_rtmp_record_done_pt next_record_done;
#endif
@@ -25,11 +29,11 @@
static void * ngx_rtmp_exec_create_main_conf(ngx_conf_t *cf);
static char * ngx_rtmp_exec_init_main_conf(ngx_conf_t *cf, void *conf);
static void * ngx_rtmp_exec_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_exec_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_exec_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
-static char * ngx_rtmp_exec_exec(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char * ngx_rtmp_exec_exec_static(ngx_conf_t *cf, ngx_command_t *cmd,
+/*static char * ngx_rtmp_exec_block(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);*/
+static char * ngx_rtmp_exec_conf(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_rtmp_exec_kill_signal(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -39,21 +43,46 @@
#define NGX_RTMP_EXEC_KILL 0x02
+#define NGX_RTMP_EXEC_PUBLISHING 0x01
+#define NGX_RTMP_EXEC_PLAYING 0x02
+
+
+enum {
+ NGX_RTMP_EXEC_PUSH,
+ NGX_RTMP_EXEC_PULL,
+
+ NGX_RTMP_EXEC_PUBLISH,
+ NGX_RTMP_EXEC_PUBLISH_DONE,
+ NGX_RTMP_EXEC_PLAY,
+ NGX_RTMP_EXEC_PLAY_DONE,
+ NGX_RTMP_EXEC_RECORD_DONE,
+
+ NGX_RTMP_EXEC_MAX,
+
+ NGX_RTMP_EXEC_STATIC
+};
+
+
typedef struct {
+ ngx_str_t id;
+ ngx_uint_t type;
ngx_str_t cmd;
ngx_array_t args; /* ngx_str_t */
+ ngx_array_t names;
} ngx_rtmp_exec_conf_t;
typedef struct {
ngx_rtmp_exec_conf_t *conf;
ngx_log_t *log;
- ngx_rtmp_session_t *session; /* NULL for init execs */
+ ngx_rtmp_eval_t **eval;
+ void *eval_ctx;
unsigned active:1;
+ unsigned managed:1;
ngx_pid_t pid;
ngx_pid_t *save_pid;
int pipefd;
- ngx_connection_t dummy_conn; /*needed by ngx_xxx_event*/
+ ngx_connection_t dummy_conn; /*needed by ngx_xxx_event*/
ngx_event_t read_evt, write_evt;
ngx_event_t respawn_evt;
ngx_msec_t respawn_timeout;
@@ -62,23 +91,48 @@
typedef struct {
- ngx_array_t confs; /* ngx_rtmp_exec_conf_t */
- ngx_array_t execs; /* ngx_rtmp_exec_t */
+ ngx_array_t static_conf; /* ngx_rtmp_exec_conf_t */
+ ngx_array_t static_exec; /* ngx_rtmp_exec_t */
ngx_msec_t respawn_timeout;
ngx_int_t kill_signal;
+ ngx_log_t *log;
} ngx_rtmp_exec_main_conf_t;
+typedef struct ngx_rtmp_exec_pull_ctx_s ngx_rtmp_exec_pull_ctx_t;
+
+struct ngx_rtmp_exec_pull_ctx_s {
+ ngx_pool_t *pool;
+ ngx_uint_t counter;
+ ngx_str_t name;
+ ngx_str_t app;
+ ngx_array_t pull_exec; /* ngx_rtmp_exec_t */
+ ngx_rtmp_exec_pull_ctx_t *next;
+};
+
+
typedef struct {
- ngx_array_t confs; /* ngx_rtmp_exec_conf_t */
+ ngx_int_t active;
+ ngx_array_t conf[NGX_RTMP_EXEC_MAX];
+ /* ngx_rtmp_exec_conf_t */
ngx_flag_t respawn;
+ ngx_flag_t options;
+ ngx_uint_t nbuckets;
+ ngx_rtmp_exec_pull_ctx_t **pull;
} ngx_rtmp_exec_app_conf_t;
typedef struct {
+ ngx_uint_t flags;
+ ngx_str_t path; /* /tmp/rec/myfile-123.flv */
+ ngx_str_t filename; /* myfile-123.flv */
+ ngx_str_t basename; /* myfile-123 */
+ ngx_str_t dirname; /* /tmp/rec */
+ ngx_str_t recorder;
u_char name[NGX_RTMP_MAX_NAME];
u_char args[NGX_RTMP_MAX_ARGS];
- ngx_array_t execs;
+ ngx_array_t push_exec; /* ngx_rtmp_exec_t */
+ ngx_rtmp_exec_pull_ctx_t *pull;
} ngx_rtmp_exec_ctx_t;
@@ -90,21 +144,86 @@
static ngx_command_t ngx_rtmp_exec_commands[] = {
-
+/*
+ { ngx_string("exec_block"),
+ NGX_RTMP_APP_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
+ ngx_rtmp_exec_block,
+ NGX_RTMP_APP_CONF_OFFSET,
+ 0,
+ NULL },
+*/
{ ngx_string("exec"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
- ngx_rtmp_exec_exec,
+ ngx_rtmp_exec_conf,
NGX_RTMP_APP_CONF_OFFSET,
- 0,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PUSH * sizeof(ngx_array_t),
+ NULL },
+
+ { ngx_string("exec_push"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
+ ngx_rtmp_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PUSH * sizeof(ngx_array_t),
+ NULL },
+
+ { ngx_string("exec_pull"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
+ ngx_rtmp_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PULL * sizeof(ngx_array_t),
+ NULL },
+
+ { ngx_string("exec_publish"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
+ ngx_rtmp_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PUBLISH * sizeof(ngx_array_t),
+ NULL },
+
+ { ngx_string("exec_publish_done"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
+ ngx_rtmp_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PUBLISH_DONE * sizeof(ngx_array_t),
+ NULL },
+
+ { ngx_string("exec_play"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
+ ngx_rtmp_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PLAY * sizeof(ngx_array_t),
+ NULL },
+
+ { ngx_string("exec_play_done"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
+ ngx_rtmp_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_PLAY_DONE * sizeof(ngx_array_t),
+ 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_exec_conf,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_exec_app_conf_t, conf) +
+ NGX_RTMP_EXEC_RECORD_DONE * sizeof(ngx_array_t),
NULL },
{ ngx_string("exec_static"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE,
- ngx_rtmp_exec_exec_static,
+ ngx_rtmp_exec_conf,
NGX_RTMP_MAIN_CONF_OFFSET,
- 0,
+ offsetof(ngx_rtmp_exec_main_conf_t, static_conf),
NULL },
-
+
{ ngx_string("respawn"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
@@ -126,6 +245,13 @@
0,
NULL },
+ { ngx_string("exec_options"),
+ 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_exec_app_conf_t, options),
+ NULL },
+
ngx_null_command
};
@@ -159,10 +285,11 @@
static void
-ngx_rtmp_exec_eval_astr(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e,
- ngx_str_t *ret)
+ngx_rtmp_exec_eval_ctx_cstr(void *sctx, ngx_rtmp_eval_t *e, ngx_str_t *ret)
{
- ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_session_t *s = sctx;
+
+ ngx_rtmp_exec_ctx_t *ctx;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
if (ctx == NULL) {
@@ -175,23 +302,108 @@
}
-static ngx_rtmp_eval_t ngx_rtmp_exec_eval[] = {
+static void
+ngx_rtmp_exec_eval_ctx_str(void *sctx, ngx_rtmp_eval_t *e, ngx_str_t *ret)
+{
+ ngx_rtmp_session_t *s = sctx;
+
+ ngx_rtmp_exec_ctx_t *ctx;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
+ if (ctx == NULL) {
+ ret->len = 0;
+ return;
+ }
+
+ *ret = * (ngx_str_t *) ((u_char *) ctx + e->offset);
+}
+
+
+static void
+ngx_rtmp_exec_eval_pctx_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret)
+{
+ *ret = *(ngx_str_t *) ((u_char *) ctx + e->offset);
+}
+
+
+static ngx_rtmp_eval_t ngx_rtmp_exec_push_specific_eval[] = {
+
+ { ngx_string("name"),
+ ngx_rtmp_exec_eval_ctx_cstr,
+ offsetof(ngx_rtmp_exec_ctx_t, name) },
+
+ { ngx_string("args"),
+ ngx_rtmp_exec_eval_ctx_cstr,
+ offsetof(ngx_rtmp_exec_ctx_t, args) },
+
+ ngx_rtmp_null_eval
+};
+
+
+static ngx_rtmp_eval_t * ngx_rtmp_exec_push_eval[] = {
+ ngx_rtmp_eval_session,
+ ngx_rtmp_exec_push_specific_eval,
+ NULL
+};
+
+
+static ngx_rtmp_eval_t ngx_rtmp_exec_pull_specific_eval[] = {
+
+ { ngx_string("name"),
+ ngx_rtmp_exec_eval_pctx_str,
+ offsetof(ngx_rtmp_exec_pull_ctx_t, name) },
+
+ { ngx_string("app"),
+ ngx_rtmp_exec_eval_pctx_str,
+ offsetof(ngx_rtmp_exec_pull_ctx_t, app) },
+
+ ngx_rtmp_null_eval
+};
+
+
+static ngx_rtmp_eval_t * ngx_rtmp_exec_pull_eval[] = {
+ ngx_rtmp_exec_pull_specific_eval,
+ NULL
+};
+
+
+static ngx_rtmp_eval_t ngx_rtmp_exec_event_specific_eval[] = {
{ ngx_string("name"),
- ngx_rtmp_exec_eval_astr,
+ ngx_rtmp_exec_eval_ctx_cstr,
offsetof(ngx_rtmp_exec_ctx_t, name) },
{ ngx_string("args"),
- ngx_rtmp_exec_eval_astr,
+ ngx_rtmp_exec_eval_ctx_cstr,
offsetof(ngx_rtmp_exec_ctx_t, args) },
+ { ngx_string("path"),
+ ngx_rtmp_exec_eval_ctx_str,
+ offsetof(ngx_rtmp_exec_ctx_t, path) },
+
+ { ngx_string("filename"),
+ ngx_rtmp_exec_eval_ctx_str,
+ offsetof(ngx_rtmp_exec_ctx_t, filename) },
+
+ { ngx_string("basename"),
+ ngx_rtmp_exec_eval_ctx_str,
+ offsetof(ngx_rtmp_exec_ctx_t, basename) },
+
+ { ngx_string("dirname"),
+ ngx_rtmp_exec_eval_ctx_str,
+ offsetof(ngx_rtmp_exec_ctx_t, dirname) },
+
+ { ngx_string("recorder"),
+ ngx_rtmp_exec_eval_ctx_str,
+ offsetof(ngx_rtmp_exec_ctx_t, recorder) },
+
ngx_rtmp_null_eval
};
-static ngx_rtmp_eval_t * ngx_rtmp_exec_eval_p[] = {
+static ngx_rtmp_eval_t * ngx_rtmp_exec_event_eval[] = {
ngx_rtmp_eval_session,
- ngx_rtmp_exec_eval,
+ ngx_rtmp_exec_event_specific_eval,
NULL
};
@@ -209,7 +421,7 @@
emcf->respawn_timeout = NGX_CONF_UNSET_MSEC;
emcf->kill_signal = NGX_CONF_UNSET;
- if (ngx_array_init(&emcf->confs, cf->pool, 1,
+ if (ngx_array_init(&emcf->static_conf, cf->pool, 1,
sizeof(ngx_rtmp_exec_conf_t)) != NGX_OK)
{
return NULL;
@@ -237,23 +449,27 @@
}
#endif
- if (ngx_array_init(&emcf->execs, cf->pool, emcf->confs.nelts,
+ if (ngx_array_init(&emcf->static_exec, cf->pool,
+ emcf->static_conf.nelts,
sizeof(ngx_rtmp_exec_t)) != NGX_OK)
{
return NGX_CONF_ERROR;
}
- e = ngx_array_push_n(&emcf->execs, emcf->confs.nelts);
+ e = ngx_array_push_n(&emcf->static_exec, emcf->static_conf.nelts);
if (e == NULL) {
return NGX_CONF_ERROR;
}
- ec = emcf->confs.elts;
+ emcf->log = &cf->cycle->new_log;
+
+ ec = emcf->static_conf.elts;
- for (n = 0; n < emcf->confs.nelts; ++n, ++e, ++ec) {
+ for (n = 0; n < emcf->static_conf.nelts; n++, e++, ec++) {
ngx_memzero(e, sizeof(*e));
e->conf = ec;
- e->log = &cf->cycle->new_log;
+ e->managed = 1;
+ e->log = emcf->log;
e->respawn_timeout = emcf->respawn_timeout;
e->kill_signal = emcf->kill_signal;
}
@@ -273,14 +489,39 @@
}
eacf->respawn = NGX_CONF_UNSET;
+ eacf->options = NGX_CONF_UNSET;
+ eacf->nbuckets = NGX_CONF_UNSET_UINT;
- if (ngx_array_init(&eacf->confs, cf->pool, 1,
- sizeof(ngx_rtmp_exec_conf_t)) != NGX_OK)
- {
- return NULL;
+ return eacf;
+}
+
+
+static ngx_int_t
+ngx_rtmp_exec_merge_confs(ngx_array_t *conf, ngx_array_t *prev)
+{
+ size_t n;
+ ngx_rtmp_exec_conf_t *ec, *pec;
+
+ if (prev->nelts == 0) {
+ return NGX_OK;
}
- return eacf;
+ if (conf->nelts == 0) {
+ *conf = *prev;
+ return NGX_OK;
+ }
+
+ ec = ngx_array_push_n(conf, prev->nelts);
+ if (ec == NULL) {
+ return NGX_ERROR;
+ }
+
+ pec = prev->elts;
+ for (n = 0; n < prev->nelts; n++, ec++, pec++) {
+ *ec = *pec;
+ }
+
+ return NGX_OK;
}
@@ -289,22 +530,31 @@
{
ngx_rtmp_exec_app_conf_t *prev = parent;
ngx_rtmp_exec_app_conf_t *conf = child;
- size_t n;
- ngx_rtmp_exec_conf_t *ec, *pec;
+
+ ngx_uint_t n;
ngx_conf_merge_value(conf->respawn, prev->respawn, 1);
+ ngx_conf_merge_uint_value(conf->nbuckets, prev->nbuckets, 1024);
- if (prev->confs.nelts) {
- ec = ngx_array_push_n(&conf->confs, prev->confs.nelts);
- if (ec == NULL) {
+ for (n = 0; n < NGX_RTMP_EXEC_MAX; n++) {
+ if (ngx_rtmp_exec_merge_confs(&conf->conf[n], &prev->conf[n]) != NGX_OK)
+ {
return NGX_CONF_ERROR;
}
- pec = prev->confs.elts;
- for (n = 0; n < prev->confs.nelts; ++n, ++ec, ++pec) {
- *ec = *pec;
+
+ if (conf->conf[n].nelts) {
+ conf->active = 1;
+ prev->active = 1;
+ }
+ }
+
+ if (conf->conf[NGX_RTMP_EXEC_PULL].nelts > 0) {
+ conf->pull = ngx_pcalloc(cf->pool, sizeof(void *) * conf->nbuckets);
+ if (conf->pull == NULL) {
+ return NGX_CONF_ERROR;
}
}
-
+
return NGX_CONF_OK;
}
@@ -335,7 +585,7 @@
/* FreeBSD note:
* When worker is restarted, child process (ffmpeg) will
- * not be terminated if it's connected to another
+ * not be terminated if it's connected to another
* (still alive) worker. That leads to starting
* another instance of exec_static process.
* Need to kill previously started processes.
@@ -344,8 +594,8 @@
* when nginx worker is terminated.
*/
- e = emcf->execs.elts;
- for (n = 0; n < emcf->execs.nelts; ++n, ++e) {
+ e = emcf->static_exec.elts;
+ for (n = 0; n < emcf->static_exec.nelts; ++n, ++e) {
e->respawn_evt.data = e;
e->respawn_evt.log = e->log;
e->respawn_evt.handler = ngx_rtmp_exec_respawn;
@@ -358,14 +608,14 @@
#if !(NGX_WIN32)
-static void
+static void
ngx_rtmp_exec_respawn(ngx_event_t *ev)
{
ngx_rtmp_exec_run((ngx_rtmp_exec_t *) ev->data);
}
-static void
+static void
ngx_rtmp_exec_child_dead(ngx_event_t *ev)
{
ngx_connection_t *dummy_conn = ev->data;
@@ -373,9 +623,9 @@
e = dummy_conn->data;
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, e->log, 0,
- "exec: child %ui exited; %s", (ngx_int_t) e->pid,
- e->respawn_timeout == NGX_CONF_UNSET_MSEC ? "respawning" :
+ ngx_log_error(NGX_LOG_INFO, e->log, 0,
+ "exec: child %ui exited; %s", (ngx_int_t) e->pid,
+ e->respawn_timeout == NGX_CONF_UNSET_MSEC ? "respawning" :
"ignoring");
ngx_rtmp_exec_kill(e, 0);
@@ -415,9 +665,8 @@
return NGX_OK;
}
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0,
- "exec: terminating child %ui",
- (ngx_int_t) e->pid);
+ ngx_log_error(NGX_LOG_INFO, e->log, 0,
+ "exec: terminating child %ui", (ngx_int_t) e->pid);
e->active = 0;
close(e->pipefd);
@@ -444,63 +693,90 @@
static ngx_int_t
ngx_rtmp_exec_run(ngx_rtmp_exec_t *e)
{
- ngx_pid_t pid;
- int fd, maxfd;
- int pipefd[2];
- int ret;
- ngx_rtmp_exec_conf_t *ec;
- ngx_str_t *arg_in, a;
- char **args, **arg_out;
- ngx_uint_t n;
+ int fd, ret, maxfd, pipefd[2];
+ char **args, **arg_out;
+ ngx_pid_t pid;
+ ngx_str_t *arg_in, a;
+ ngx_uint_t n;
+ ngx_rtmp_exec_conf_t *ec;
ec = e->conf;
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0,
- "exec: starting child '%V'", &ec->cmd);
+ ngx_log_error(NGX_LOG_INFO, e->log, 0,
+ "exec: starting %s child '%V'",
+ e->managed ? "managed" : "unmanaged", &ec->cmd);
+
+ pipefd[0] = -1;
+ pipefd[1] = -1;
+
+ if (e->managed) {
+
+ if (e->active) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0,
+ "exec: already active '%V'", &ec->cmd);
+ return NGX_OK;
+ }
- if (e->active) {
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0,
- "exec: already active '%V'", &ec->cmd);
- return NGX_OK;
- }
+ if (pipe(pipefd) == -1) {
+ ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
+ "exec: pipe failed");
+ return NGX_ERROR;
+ }
- if (pipe(pipefd) == -1) {
- ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
- "exec: pipe failed");
- return NGX_ERROR;
- }
+ /* make pipe write end survive through exec */
- /* make pipe write end survive through exec */
- ret = fcntl(pipefd[1], F_GETFD);
- if (ret != -1) {
- ret &= ~FD_CLOEXEC;
- ret = fcntl(pipefd[1], F_SETFD, ret);
- }
- if (ret == -1) {
- close(pipefd[0]);
- close(pipefd[1]);
- ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
- "exec: fcntl failed");
- return NGX_ERROR;
+ ret = fcntl(pipefd[1], F_GETFD);
+
+ if (ret != -1) {
+ ret &= ~FD_CLOEXEC;
+ ret = fcntl(pipefd[1], F_SETFD, ret);
+ }
+
+ if (ret == -1) {
+
+ close(pipefd[0]);
+ close(pipefd[1]);
+
+ ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
+ "exec: fcntl failed");
+
+ return NGX_ERROR;
+ }
}
pid = fork();
+
switch (pid) {
+
case -1:
- close(pipefd[0]);
- close(pipefd[1]);
+
+ /* failure */
+
+ if (pipefd[0] != -1) {
+ close(pipefd[0]);
+ }
+
+ if (pipefd[1] != -1) {
+ close(pipefd[1]);
+ }
+
ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
"exec: fork failed");
+
return NGX_ERROR;
case 0:
+
/* child */
#if (NGX_LINUX)
- prctl(PR_SET_PDEATHSIG, e->kill_signal, 0, 0, 0);
+ if (e->managed) {
+ prctl(PR_SET_PDEATHSIG, e->kill_signal, 0, 0, 0);
+ }
#endif
/* close all descriptors but pipe write end */
+
maxfd = sysconf(_SC_OPEN_MAX);
for (fd = 0; fd < maxfd; ++fd) {
if (fd == pipefd[1]) {
@@ -510,7 +786,7 @@
close(fd);
}
- fd = open("/dev/null", O_RDWR);
+ fd = open("/dev/null", O_RDWR);
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
@@ -527,12 +803,12 @@
for (n = 0; n < ec->args.nelts; n++, ++arg_in) {
- if (e->session == NULL) {
+ if (e->eval == NULL) {
a = *arg_in;
} else {
- ngx_rtmp_eval(e->session, arg_in, ngx_rtmp_exec_eval_p, &a);
+ ngx_rtmp_eval(e->eval_ctx, arg_in, e->eval, &a, e->log);
}
-
+
if (ngx_rtmp_eval_streams(&a) != NGX_DONE) {
continue;
}
@@ -542,90 +818,355 @@
*arg_out = NULL;
+#if (NGX_DEBUG)
+ {
+ char **p;
+
+ for (p = args; *p; p++) {
+ ngx_write_fd(STDERR_FILENO, "'", 1);
+ ngx_write_fd(STDERR_FILENO, *p, strlen(*p));
+ ngx_write_fd(STDERR_FILENO, "' ", 2);
+ }
+
+ ngx_write_fd(STDERR_FILENO, "\n", 1);
+ }
+#endif
+
if (execvp((char *) ec->cmd.data, args) == -1) {
+ char *msg;
+
+ msg = strerror(errno);
+
+ ngx_write_fd(STDERR_FILENO, "execvp error: ", 14);
+ ngx_write_fd(STDERR_FILENO, msg, strlen(msg));
+ ngx_write_fd(STDERR_FILENO, "\n", 1);
+
exit(1);
}
break;
default:
+
/* parent */
- close(pipefd[1]);
- e->active = 1;
- e->pid = pid;
- e->pipefd = pipefd[0];
- if (e->save_pid) {
- *e->save_pid = pid;
- }
-
- e->dummy_conn.fd = e->pipefd;
- e->dummy_conn.data = e;
- e->dummy_conn.read = &e->read_evt;
- e->dummy_conn.write = &e->write_evt;
- e->read_evt.data = &e->dummy_conn;
- e->write_evt.data = &e->dummy_conn;
-
- e->read_evt.log = e->log;
- e->read_evt.handler = ngx_rtmp_exec_child_dead;
-
- if (ngx_add_event(&e->read_evt, NGX_READ_EVENT, 0) != NGX_OK) {
- ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
- "exec: failed to add child control event");
+
+ if (pipefd[1] != -1) {
+ close(pipefd[1]);
+ }
+
+ if (pipefd[0] != -1) {
+
+ e->active = 1;
+ e->pid = pid;
+ e->pipefd = pipefd[0];
+
+ if (e->save_pid) {
+ *e->save_pid = pid;
+ }
+
+ e->dummy_conn.fd = e->pipefd;
+ e->dummy_conn.data = e;
+ e->dummy_conn.read = &e->read_evt;
+ e->dummy_conn.write = &e->write_evt;
+ e->read_evt.data = &e->dummy_conn;
+ e->write_evt.data = &e->dummy_conn;
+
+ e->read_evt.log = e->log;
+ e->read_evt.handler = ngx_rtmp_exec_child_dead;
+
+ if (ngx_add_event(&e->read_evt, NGX_READ_EVENT, 0) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno,
+ "exec: failed to add child control event");
+ }
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, e->log, 0,
- "exec: child '%V' started pid=%i",
+ "exec: child '%V' started pid=%i",
&ec->cmd, (ngx_int_t) pid);
break;
}
+
return NGX_OK;
}
static ngx_int_t
-ngx_rtmp_exec_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
+ngx_rtmp_exec_init_ctx(ngx_rtmp_session_t *s, u_char name[NGX_RTMP_MAX_NAME],
+ u_char args[NGX_RTMP_MAX_ARGS], ngx_uint_t flags)
{
- ngx_rtmp_exec_app_conf_t *eacf;
- ngx_rtmp_exec_ctx_t *ctx;
- ngx_rtmp_exec_t *e;
- size_t n;
+ ngx_uint_t n;
+ ngx_array_t *push_conf;
+ ngx_rtmp_exec_t *e;
+ ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_exec_conf_t *ec;
+ ngx_rtmp_exec_app_conf_t *eacf;
+ ngx_rtmp_exec_main_conf_t *emcf;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
+
+ if (ctx != NULL) {
+ goto done;
+ }
+
+ ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_exec_ctx_t));
+
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_exec_module);
eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module);
- if (eacf == NULL) {
- goto next;
+
+ emcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_exec_module);
+
+ push_conf = &eacf->conf[NGX_RTMP_EXEC_PUSH];
+
+ if (push_conf->nelts > 0) {
+
+ if (ngx_array_init(&ctx->push_exec, s->connection->pool,
+ push_conf->nelts,
+ sizeof(ngx_rtmp_exec_t)) != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ e = ngx_array_push_n(&ctx->push_exec, push_conf->nelts);
+
+ if (e == NULL) {
+ return NGX_ERROR;
+ }
+
+ ec = push_conf->elts;
+
+ for (n = 0; n < push_conf->nelts; n++, e++, ec++) {
+ ngx_memzero(e, sizeof(*e));
+ e->conf = ec;
+ e->managed = 1;
+ e->log = s->connection->log;
+ e->eval = ngx_rtmp_exec_push_eval;
+ e->eval_ctx = s;
+ e->kill_signal = emcf->kill_signal;
+ e->respawn_timeout = (eacf->respawn ? emcf->respawn_timeout :
+ NGX_CONF_UNSET_MSEC);
+ }
}
+done:
+
+ ngx_memcpy(ctx->name, name, NGX_RTMP_MAX_NAME);
+ ngx_memcpy(ctx->args, args, NGX_RTMP_MAX_ARGS);
+
+ ctx->flags |= flags;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_exec_init_pull_ctx(ngx_rtmp_session_t *s,
+ u_char name[NGX_RTMP_MAX_NAME])
+{
+ size_t len;
+ ngx_uint_t n;
+ ngx_pool_t *pool;
+ ngx_array_t *pull_conf;
+ ngx_rtmp_exec_t *e;
+ ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_exec_conf_t *ec;
+ ngx_rtmp_exec_pull_ctx_t *pctx, **ppctx;
+ ngx_rtmp_exec_app_conf_t *eacf;
+ ngx_rtmp_exec_main_conf_t *emcf;
+
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
- if (ctx == NULL || ctx->execs.nelts == 0) {
- goto next;
+ if (ctx->pull != NULL) {
+ return NGX_OK;
}
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "exec: delete %uz command(s)", ctx->execs.nelts);
+ eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module);
+
+ pull_conf = &eacf->conf[NGX_RTMP_EXEC_PULL];
- e = ctx->execs.elts;
- for (n = 0; n < ctx->execs.nelts; ++n, ++e) {
- ngx_rtmp_exec_kill(e, e->kill_signal);
+ if (pull_conf->nelts == 0) {
+ return NGX_OK;
}
-next:
- return next_close_stream(s, v);
+ emcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_exec_module);
+
+ len = ngx_strlen(name);
+
+ ppctx = &eacf->pull[ngx_hash_key(name, len) % eacf->nbuckets];
+
+ for (; *ppctx; ppctx = &(*ppctx)->next) {
+ pctx = *ppctx;
+
+ if (pctx->name.len == len &&
+ ngx_strncmp(name, pctx->name.data, len) == 0)
+ {
+ goto done;
+ }
+ }
+
+ pool = ngx_create_pool(4096, emcf->log);
+ if (pool == NULL) {
+ return NGX_ERROR;
+ }
+
+ pctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_exec_pull_ctx_t));
+ if (pctx == NULL) {
+ goto error;
+ }
+
+ pctx->pool = pool;
+ pctx->name.len = len;
+ pctx->name.data = ngx_palloc(pool, len);
+
+ if (pctx->name.data == NULL) {
+ goto error;
+ }
+
+ ngx_memcpy(pctx->name.data, name, len);
+
+ pctx->app.len = s->app.len;
+ pctx->app.data = ngx_palloc(pool, s->app.len);
+
+ if (pctx->app.data == NULL) {
+ goto error;
+ }
+
+ ngx_memcpy(pctx->app.data, s->app.data, s->app.len);
+
+ if (ngx_array_init(&pctx->pull_exec, pool, pull_conf->nelts,
+ sizeof(ngx_rtmp_exec_t)) != NGX_OK)
+ {
+ goto error;
+ }
+
+ e = ngx_array_push_n(&pctx->pull_exec, pull_conf->nelts);
+ if (e == NULL) {
+ goto error;
+ }
+
+ ec = pull_conf->elts;
+ for (n = 0; n < pull_conf->nelts; n++, e++, ec++) {
+ ngx_memzero(e, sizeof(*e));
+ e->conf = ec;
+ e->managed = 1;
+ e->log = emcf->log;
+ e->eval = ngx_rtmp_exec_pull_eval;
+ e->eval_ctx = pctx;
+ e->kill_signal = emcf->kill_signal;
+ e->respawn_timeout = (eacf->respawn ? emcf->respawn_timeout :
+ NGX_CONF_UNSET_MSEC);
+ }
+
+ *ppctx = pctx;
+
+done:
+
+ ctx->pull = pctx;
+ ctx->pull->counter++;
+
+ return NGX_OK;
+
+error:
+
+ ngx_destroy_pool(pool);
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_rtmp_exec_filter(ngx_rtmp_session_t *s, ngx_rtmp_exec_conf_t *ec)
+{
+ size_t len;
+ ngx_str_t *v;
+ ngx_uint_t n;
+ ngx_rtmp_exec_ctx_t *ctx;
+
+ if (ec->names.nelts == 0) {
+ return NGX_OK;
+ }
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
+
+ len = ngx_strlen(ctx->name);
+
+ v = ec->names.elts;
+ for (n = 0; n < ec->names.nelts; n++, s++) {
+ if (v->len == len && ngx_strncmp(v->data, ctx->name, len) == 0) {
+ return NGX_OK;
+ }
+ }
+
+ return NGX_DECLINED;
+}
+
+
+static void
+ngx_rtmp_exec_unmanaged(ngx_rtmp_session_t *s, ngx_array_t *e, const char *op)
+{
+ ngx_uint_t n;
+ ngx_rtmp_exec_t en;
+ ngx_rtmp_exec_conf_t *ec;
+
+ if (e->nelts == 0) {
+ return;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "exec: %s %uz unmanaged command(s)", op, e->nelts);
+
+ ec = e->elts;
+ for (n = 0; n < e->nelts; n++, ec++) {
+ if (ngx_rtmp_exec_filter(s, ec) != NGX_OK) {
+ continue;
+ }
+
+ ngx_memzero(&en, sizeof(ngx_rtmp_exec_t));
+
+ en.conf = ec;
+ en.eval = ngx_rtmp_exec_event_eval;
+ en.eval_ctx = s;
+ en.log = s->connection->log;
+
+ ngx_rtmp_exec_run(&en);
+ }
+}
+
+
+static void
+ngx_rtmp_exec_managed(ngx_rtmp_session_t *s, ngx_array_t *e, const char *op)
+{
+ ngx_uint_t n;
+ ngx_rtmp_exec_t *en;
+
+ if (e->nelts == 0) {
+ return;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "exec: %s %uz managed command(s)", op, e->nelts);
+
+ en = e->elts;
+ for (n = 0; n < e->nelts; n++, en++) {
+ if (ngx_rtmp_exec_filter(s, en->conf) == NGX_OK) {
+ ngx_rtmp_exec_run(en);
+ }
+ }
}
static ngx_int_t
ngx_rtmp_exec_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
{
- ngx_rtmp_exec_main_conf_t *emcf;
- ngx_rtmp_exec_app_conf_t *eacf;
- ngx_rtmp_exec_t *e;
- ngx_rtmp_exec_conf_t *ec;
- ngx_rtmp_exec_ctx_t *ctx;
- size_t n;
+ ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_exec_app_conf_t *eacf;
- emcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_exec_module);
eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module);
- if (eacf == NULL || eacf->confs.nelts == 0) {
+
+ if (eacf == NULL || !eacf->active) {
goto next;
}
@@ -633,139 +1174,366 @@
goto next;
}
+ if (ngx_rtmp_exec_init_ctx(s, v->name, v->args, NGX_RTMP_EXEC_PUBLISHING)
+ != NGX_OK)
+ {
+ goto next;
+ }
+
+ ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PUBLISH], "publish");
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
+
+ ngx_rtmp_exec_managed(s, &ctx->push_exec, "push");
+
+next:
+ return next_publish(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_exec_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
+{
+ ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_exec_pull_ctx_t *pctx;
+ ngx_rtmp_exec_app_conf_t *eacf;
+
+ eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module);
+
+ if (eacf == NULL || !eacf->active) {
+ goto next;
+ }
+
+ if (ngx_rtmp_exec_init_ctx(s, v->name, v->args, NGX_RTMP_EXEC_PLAYING)
+ != NGX_OK)
+ {
+ goto next;
+ }
+
+ ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PLAY], "play");
+
+ if (ngx_rtmp_exec_init_pull_ctx(s, v->name) != NGX_OK) {
+ goto next;
+ }
+
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
+ pctx = ctx->pull;
+
+ if (pctx && pctx->counter == 1) {
+ ngx_rtmp_exec_managed(s, &pctx->pull_exec, "pull");
+ }
+
+next:
+ return next_play(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_exec_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
+{
+ size_t n;
+ ngx_rtmp_exec_t *e;
+ ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_exec_pull_ctx_t *pctx, **ppctx;
+ ngx_rtmp_exec_app_conf_t *eacf;
+
+ eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module);
+ if (eacf == NULL) {
+ goto next;
+ }
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
if (ctx == NULL) {
- ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_exec_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
+ goto next;
+ }
+
+ if (ctx->flags & NGX_RTMP_EXEC_PUBLISHING) {
+ ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PUBLISH_DONE],
+ "publish_done");
+ }
+
+ if (ctx->flags & NGX_RTMP_EXEC_PLAYING) {
+ ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PLAY_DONE],
+ "play_done");
+ }
+
+ ctx->flags = 0;
+
+ if (ctx->push_exec.nelts > 0) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "exec: delete %uz push command(s)",
+ ctx->push_exec.nelts);
+
+ e = ctx->push_exec.elts;
+ for (n = 0; n < ctx->push_exec.nelts; n++, e++) {
+ ngx_rtmp_exec_kill(e, e->kill_signal);
}
+ }
- ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_exec_module);
+ pctx = ctx->pull;
- if (ngx_array_init(&ctx->execs, s->connection->pool, eacf->confs.nelts,
- sizeof(ngx_rtmp_exec_t)) != NGX_OK)
- {
- return NGX_ERROR;
+ if (pctx && --pctx->counter == 0) {
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "exec: delete %uz pull command(s)",
+ pctx->pull_exec.nelts);
+
+ e = pctx->pull_exec.elts;
+ for (n = 0; n < pctx->pull_exec.nelts; n++, e++) {
+ ngx_rtmp_exec_kill(e, e->kill_signal);
}
- e = ngx_array_push_n(&ctx->execs, eacf->confs.nelts);
- if (e == NULL) {
- return NGX_ERROR;
+ ppctx = &eacf->pull[ngx_hash_key(pctx->name.data, pctx->name.len) %
+ eacf->nbuckets];
+
+ for (; *ppctx; ppctx = &(*ppctx)->next) {
+ if (pctx == *ppctx) {
+ *ppctx = pctx->next;
+ break;
+ }
}
- ec = eacf->confs.elts;
- for (n = 0; n < eacf->confs.nelts; ++n, ++e, ++ec) {
- ngx_memzero(e, sizeof(*e));
- e->conf = ec;
- e->log = s->connection->log;
- e->session = s;
- e->kill_signal = emcf->kill_signal;
- e->respawn_timeout = (eacf->respawn ? emcf->respawn_timeout :
- NGX_CONF_UNSET_MSEC);
+ ngx_destroy_pool(pctx->pool);
+ }
+
+ ctx->pull = NULL;
+
+next:
+ return next_close_stream(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_exec_record_done(ngx_rtmp_session_t *s, ngx_rtmp_record_done_t *v)
+{
+ u_char c;
+ ngx_uint_t ext, dir;
+ ngx_rtmp_exec_ctx_t *ctx;
+ ngx_rtmp_exec_app_conf_t *eacf;
+
+ if (s->auto_pushed) {
+ goto next;
+ }
+
+ eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module);
+ if (eacf == NULL || !eacf->active) {
+ goto next;
+ }
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module);
+ if (ctx == NULL) {
+ goto next;
+ }
+
+ ctx->recorder = v->recorder;
+ ctx->path = v->path;
+
+ ctx->dirname.data = ctx->path.data;
+ ctx->dirname.len = 0;
+
+ for (dir = ctx->path.len; dir > 0; dir--) {
+ c = ctx->path.data[dir - 1];
+ if (c == '/' || c == '\\') {
+ ctx->dirname.len = dir - 1;
+ break;
}
}
- ngx_memcpy(ctx->name, v->name, NGX_RTMP_MAX_NAME);
- ngx_memcpy(ctx->args, v->args, NGX_RTMP_MAX_ARGS);
+ ctx->filename.data = ctx->path.data + dir;
+ ctx->filename.len = ctx->path.len - dir;
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "exec: run %uz command(s)", ctx->execs.nelts);
+ ctx->basename = ctx->filename;
- e = ctx->execs.elts;
- for (n = 0; n < ctx->execs.nelts; ++n, ++e) {
- ngx_rtmp_exec_run(e);
+ for (ext = ctx->filename.len; ext > 0; ext--) {
+ if (ctx->filename.data[ext - 1] == '.') {
+ ctx->basename.len = ext - 1;
+ break;
+ }
}
+ ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_RECORD_DONE],
+ "record_done");
+
+ ngx_str_null(&v->recorder);
+ ngx_str_null(&v->path);
+
next:
- return next_publish(s, v);
+ return next_record_done(s, v);
}
#endif /* NGX_WIN32 */
static char *
-ngx_rtmp_exec_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ngx_rtmp_exec_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_str_t *value;
- ngx_rtmp_exec_app_conf_t *eacf;
- size_t n, nargs;
- ngx_str_t *s;
- ngx_rtmp_exec_conf_t *ec;
+ char *p = conf;
+
+ size_t n, nargs;
+ ngx_str_t *s, *value, v;
+ ngx_array_t *confs;
+ ngx_rtmp_exec_conf_t *ec;
+ ngx_rtmp_exec_app_conf_t *eacf;
+
+ confs = (ngx_array_t *) (p + cmd->offset);
eacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_exec_module);
+
+ if (confs->nalloc == 0 && ngx_array_init(confs, cf->pool, 1,
+ sizeof(ngx_rtmp_exec_conf_t))
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
value = cf->args->elts;
- ec = ngx_array_push(&eacf->confs);
+ ec = ngx_array_push(confs);
if (ec == NULL) {
return NGX_CONF_ERROR;
}
+ ngx_memzero(ec, sizeof(ngx_rtmp_exec_conf_t));
+
+ /* type is undefined for explicit execs */
+
+ ec->type = NGX_CONF_UNSET_UINT;
ec->cmd = value[1];
+ if (ngx_array_init(&ec->names, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
if (cf->args->nelts == 2) {
return NGX_CONF_OK;
}
nargs = cf->args->nelts - 2;
- if (ngx_array_init(&ec->args, cf->pool, nargs,
- sizeof(ngx_str_t)) != NGX_OK)
+ if (ngx_array_init(&ec->args, cf->pool, nargs, sizeof(ngx_str_t)) != NGX_OK)
{
return NGX_CONF_ERROR;
}
- s = ngx_array_push_n(&ec->args, nargs);
- for (n = 2; n < cf->args->nelts; ++n, ++s) {
- *s = value[n];
+ for (n = 2; n < cf->args->nelts; n++) {
+
+ v = value[n];
+
+ if (eacf->options == 1) {
+
+ if (v.len >= 5 && ngx_strncmp(v.data, "name=", 5) == 0) {
+
+ s = ngx_array_push(&ec->names);
+ if (s == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ v.data += 5;
+ v.len -= 5;
+
+ *s = v;
+
+ continue;
+ }
+ }
+
+ s = ngx_array_push(&ec->args);
+ if (s == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *s = v;
}
return NGX_CONF_OK;
}
-
+/*
static char *
-ngx_rtmp_exec_exec_static(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ngx_rtmp_exec_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_rtmp_exec_main_conf_t *emcf = conf;
-
+ char *rv;
ngx_str_t *value;
- size_t n, nargs;
- ngx_str_t *s;
- ngx_rtmp_exec_conf_t *ec;
+ ngx_conf_t save;
+ ngx_array_t *confs;
+ ngx_rtmp_conf_ctx_t *ctx, *pctx;
+ ngx_rtmp_exec_conf_t *ec, *eec;
+ ngx_rtmp_exec_app_conf_t *eacf;
+ ngx_rtmp_exec_main_conf_t *emcf;
value = cf->args->elts;
- ec = ngx_array_push(&emcf->confs);
+ eacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_exec_module);
+
+ emcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_exec_module);
+
+ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t));
+ if (ctx == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pctx = cf->ctx;
+
+ ctx->main_conf = pctx->main_conf;
+ ctx->srv_conf = pctx->srv_conf;
+
+ ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module);
+ if (ctx->app_conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ec = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_exec_conf_t));
if (ec == NULL) {
return NGX_CONF_ERROR;
}
- ec->cmd = value[1];
+ ec->id = value[1];
+ ec->type = NGX_CONF_UNSET_UINT;
- if (cf->args->nelts == 2) {
- return NGX_CONF_OK;
+ ctx->app_conf[ngx_rtmp_exec_module.ctx_index] = ec;
+
+ save = *cf;
+
+ cf->ctx = ctx;
+ cf->cmd_type = NGX_RTMP_EXEC_CONF;
+
+ rv = ngx_conf_parse(cf, NULL);
+ *cf= save;
+
+ switch (ec->type) {
+
+ case NGX_RTMP_EXEC_STATIC:
+ confs = &emcf->static_conf;
+ break;
+
+ case NGX_CONF_UNSET_UINT:
+ return "unspecified exec type";
+
+ default:
+ confs = &eacf->conf[ec->type];
}
- nargs = cf->args->nelts - 2;
- if (ngx_array_init(&ec->args, cf->pool, nargs,
- sizeof(ngx_str_t)) != NGX_OK)
+ if (confs->nalloc == 0 && ngx_array_init(confs, cf->pool, 1,
+ sizeof(ngx_rtmp_exec_conf_t))
+ != NGX_OK)
{
return NGX_CONF_ERROR;
}
- s = ngx_array_push_n(&ec->args, nargs);
- for (n = 2; n < cf->args->nelts; ++n, ++s) {
- *s = value[n];
+ eec = ngx_array_push(confs);
+ if (eec == NULL) {
+ return NGX_CONF_ERROR;
}
- return NGX_CONF_OK;
-}
+ *eec = *ec;
+ return rv;
+}
+*/
static char *
ngx_rtmp_exec_kill_signal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_rtmp_exec_main_conf_t *emcf = conf;
- ngx_str_t *value;
+
+ ngx_str_t *value;
value = cf->args->elts;
value++;
@@ -821,9 +1589,15 @@
next_publish = ngx_rtmp_publish;
ngx_rtmp_publish = ngx_rtmp_exec_publish;
+ next_play = ngx_rtmp_play;
+ ngx_rtmp_play = ngx_rtmp_exec_play;
+
next_close_stream = ngx_rtmp_close_stream;
ngx_rtmp_close_stream = ngx_rtmp_exec_close_stream;
+ next_record_done = ngx_rtmp_record_done;
+ ngx_rtmp_record_done = ngx_rtmp_exec_record_done;
+
#endif /* NGX_WIN32 */
return NGX_OK;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_flv_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -12,7 +13,7 @@
static ngx_int_t ngx_rtmp_flv_postconfiguration(ngx_conf_t *cf);
static void ngx_rtmp_flv_read_meta(ngx_rtmp_session_t *s, ngx_file_t *f);
-static ngx_int_t ngx_rtmp_flv_timestamp_to_offset(ngx_rtmp_session_t *s,
+static ngx_int_t ngx_rtmp_flv_timestamp_to_offset(ngx_rtmp_session_t *s,
ngx_file_t *f, ngx_int_t timestamp);
static ngx_int_t ngx_rtmp_flv_init(ngx_rtmp_session_t *s, ngx_file_t *f,
ngx_int_t aindex, ngx_int_t vindex);
@@ -121,29 +122,29 @@
static ngx_rtmp_amf_elt_t in_keyframes[] = {
- { NGX_RTMP_AMF_ARRAY | NGX_RTMP_AMF_CONTEXT,
+ { NGX_RTMP_AMF_ARRAY | NGX_RTMP_AMF_CONTEXT,
ngx_string("filepositions"),
&filepositions_ctx, 0 },
- { NGX_RTMP_AMF_ARRAY | NGX_RTMP_AMF_CONTEXT,
+ { NGX_RTMP_AMF_ARRAY | NGX_RTMP_AMF_CONTEXT,
ngx_string("times"),
×_ctx, 0 }
};
static ngx_rtmp_amf_elt_t in_inf[] = {
- { NGX_RTMP_AMF_OBJECT,
+ { NGX_RTMP_AMF_OBJECT,
ngx_string("keyframes"),
in_keyframes, sizeof(in_keyframes) }
};
static ngx_rtmp_amf_elt_t in_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
NULL, 0 },
- { NGX_RTMP_AMF_OBJECT,
+ { NGX_RTMP_AMF_OBJECT,
ngx_null_string,
in_inf, sizeof(in_inf) },
};
@@ -160,15 +161,15 @@
ngx_memzero(&filepositions_ctx, sizeof(filepositions_ctx));
ngx_memzero(×_ctx, sizeof(times_ctx));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"flv: init index error");
return NGX_OK;
}
- if (filepositions_ctx.link && ngx_rtmp_flv_fill_index(&filepositions_ctx,
+ if (filepositions_ctx.link && ngx_rtmp_flv_fill_index(&filepositions_ctx,
&ctx->filepositions)
!= NGX_OK)
{
@@ -210,7 +211,7 @@
static ngx_int_t
-ngx_rtmp_flv_timestamp_to_offset(ngx_rtmp_session_t *s, ngx_file_t *f,
+ngx_rtmp_flv_timestamp_to_offset(ngx_rtmp_session_t *s, ngx_file_t *f,
ngx_int_t timestamp)
{
ngx_rtmp_flv_ctx_t *ctx;
@@ -225,7 +226,7 @@
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv: lookup index start timestamp=%i",
+ "flv: lookup index start timestamp=%i",
timestamp);
if (ctx->meta_read == 0) {
@@ -234,7 +235,7 @@
}
if (timestamp <= 0 || ctx->filepositions.nelts == 0
- || ctx->times.nelts == 0)
+ || ctx->times.nelts == 0)
{
goto rewind;
}
@@ -264,7 +265,7 @@
index * 9 + 1) * 1000;
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv: lookup times index=%ui value=%ui",
+ "flv: lookup times index=%ui value=%ui",
index, (ngx_uint_t) v);
if (timestamp < v) {
@@ -274,7 +275,7 @@
if (index >= ctx->filepositions.nelts) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "flv: index out of bounds: %ui>=%ui",
+ "flv: index out of bounds: %ui>=%ui",
index, ctx->filepositions.nelts);
goto rewind;
}
@@ -294,16 +295,16 @@
ret = (ngx_uint_t) ngx_rtmp_flv_index_value(ngx_rtmp_flv_buffer);
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv: lookup index timestamp=%i offset=%ui",
+ "flv: lookup index timestamp=%i offset=%ui",
timestamp, ret);
return ret;
rewind:
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv: lookup index timestamp=%i offset=begin",
+ "flv: lookup index timestamp=%i offset=begin",
timestamp);
-
+
return NGX_RTMP_FLV_DATA_OFFSET;
}
@@ -329,9 +330,9 @@
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"flv: read meta");
-
+
/* read tag header */
- n = ngx_read_file(f, ngx_rtmp_flv_header, sizeof(ngx_rtmp_flv_header),
+ n = ngx_read_file(f, ngx_rtmp_flv_header, sizeof(ngx_rtmp_flv_header),
NGX_RTMP_FLV_DATA_OFFSET);
if (n != sizeof(ngx_rtmp_flv_header)) {
@@ -366,7 +367,7 @@
/* read metadata */
n = ngx_read_file(f, ngx_rtmp_flv_buffer, size,
- sizeof(ngx_rtmp_flv_header) +
+ sizeof(ngx_rtmp_flv_header) +
NGX_RTMP_FLV_DATA_OFFSET);
if (n != (ssize_t) size) {
@@ -425,7 +426,7 @@
"flv: read tag at offset=%i", ctx->offset);
/* read tag header */
- n = ngx_read_file(f, ngx_rtmp_flv_header,
+ n = ngx_read_file(f, ngx_rtmp_flv_header,
sizeof(ngx_rtmp_flv_header), ctx->offset);
if (n != sizeof(ngx_rtmp_flv_header)) {
@@ -471,7 +472,7 @@
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"flv: read tag type=%i size=%uD timestamp=%uD "
- "last_timestamp=%uD",
+ "last_timestamp=%uD",
(ngx_int_t) h.type,size, h.timestamp, last_timestamp);
lh = h;
@@ -479,13 +480,13 @@
if (size > sizeof(ngx_rtmp_flv_buffer)) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "flv: too big message: %D>%uz", size,
+ "flv: too big message: %D>%uz", size,
sizeof(ngx_rtmp_flv_buffer));
goto next;
}
/* read tag body */
- n = ngx_read_file(f, ngx_rtmp_flv_buffer, size,
+ n = ngx_read_file(f, ngx_rtmp_flv_buffer, size,
ctx->offset - size - 4);
if (n != (ssize_t) size) {
@@ -505,7 +506,7 @@
/* output chain */
out = ngx_rtmp_append_shared_bufs(cscf, NULL, &in);
- ngx_rtmp_prepare_message(s, &h, ctx->msg_mask & (1 << h.type) ?
+ ngx_rtmp_prepare_message(s, &h, ctx->msg_mask & (1 << h.type) ?
&lh : NULL, out);
rc = ngx_rtmp_send_message(s, out, 0);
ngx_rtmp_free_shared_chain(cscf, out);
@@ -541,6 +542,8 @@
h.timestamp > end_timestamp ? h.timestamp - end_timestamp : 0,
h.timestamp, end_timestamp, (ngx_int_t) buflen);
+ s->current_time = h.timestamp;
+
/* too much data sent; schedule timeout */
if (h.timestamp > end_timestamp) {
return h.timestamp - end_timestamp;
@@ -651,7 +654,7 @@
}
fmt = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_play_fmt_t));
-
+
if (fmt == NULL) {
return NGX_ERROR;
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_handler.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -24,7 +25,7 @@
#ifdef NGX_DEBUG
char*
-ngx_rtmp_message_type(uint8_t type)
+ngx_rtmp_message_type(uint8_t type)
{
static char* types[] = {
"?",
@@ -59,7 +60,7 @@
char*
-ngx_rtmp_user_message_type(uint16_t evt)
+ngx_rtmp_user_message_type(uint16_t evt)
{
static char* evts[] = {
"stream_begin",
@@ -98,14 +99,14 @@
static ngx_chain_t *
-ngx_rtmp_alloc_in_buf(ngx_rtmp_session_t *s)
+ngx_rtmp_alloc_in_buf(ngx_rtmp_session_t *s)
{
ngx_chain_t *cl;
ngx_buf_t *b;
size_t size;
if ((cl = ngx_alloc_chain_link(s->in_pool)) == NULL
- || (cl->buf = ngx_calloc_buf(s->in_pool)) == NULL)
+ || (cl->buf = ngx_calloc_buf(s->in_pool)) == NULL)
{
return NULL;
}
@@ -143,7 +144,7 @@
}
-static void
+static void
ngx_rtmp_ping(ngx_event_t *pev)
{
ngx_connection_t *c;
@@ -162,14 +163,14 @@
}
if (s->ping_active) {
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"ping: unresponded");
ngx_rtmp_finalize_session(s);
return;
}
if (cscf->busy) {
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"ping: not busy between pings");
ngx_rtmp_finalize_session(s);
return;
@@ -246,7 +247,7 @@
ngx_rtmp_finalize_set_chunk_size(s);
}
- } else {
+ } else {
if (old_pos) {
b->pos = b->last = b->start;
@@ -272,7 +273,7 @@
s->in_bytes += n;
if (s->ack_size && s->in_bytes - s->in_last_ack >= s->ack_size) {
-
+
s->in_last_ack = s->in_bytes;
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0,
@@ -347,7 +348,7 @@
if (fmt <= 2 ) {
if (b->last - p < 3)
continue;
- /* timestamp:
+ /* timestamp:
* big-endian 3b -> little-endian 4b */
pp = (u_char*)×tamp;
pp[2] = *p++;
@@ -361,7 +362,7 @@
if (b->last - p < 4)
continue;
/* size:
- * big-endian 3b -> little-endian 4b
+ * big-endian 3b -> little-endian 4b
* type:
* 1b -> 1b*/
pp = (u_char*)&h->mlen;
@@ -431,7 +432,7 @@
size = b->last - b->pos;
fsize = h->mlen - st->len;
- if (size < ngx_min(fsize, s->in_chunk_size))
+ if (size < ngx_min(fsize, s->in_chunk_size))
continue;
/* buffer is ready */
@@ -494,7 +495,7 @@
}
if (wev->timedout) {
- ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
"client timed out");
c->timedout = 1;
ngx_rtmp_finalize_session(s);
@@ -554,8 +555,8 @@
}
-void
-ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+void
+ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_header_t *lh, ngx_chain_t *out)
{
ngx_chain_t *l;
@@ -581,7 +582,7 @@
/* detect packet size */
mlen = 0;
- nbufs = 0;
+ nbufs = 0;
for(l = out; l; l = l->next) {
mlen += (l->buf->last - l->buf->pos);
++nbufs;
@@ -680,7 +681,7 @@
*p++ = pp[1];
*p++ = pp[0];
- /* This CONTRADICTS the standard
+ /* This CONTRADICTS the standard
* but that's the way flash client
* wants data to be encoded;
* ffmpeg complains */
@@ -699,7 +700,7 @@
ngx_int_t
-ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out,
+ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out,
ngx_uint_t priority)
{
ngx_uint_t nmsg;
@@ -710,7 +711,7 @@
priority = 3;
}
- /* drop packet?
+ /* drop packet?
* 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,
@@ -741,7 +742,7 @@
}
-ngx_int_t
+ngx_int_t
ngx_rtmp_receive_message(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in)
{
@@ -757,14 +758,14 @@
int nbufs;
ngx_chain_t *ch;
- for(nbufs = 1, ch = in;
- ch->next;
+ for(nbufs = 1, ch = in;
+ ch->next;
ch = ch->next, ++nbufs);
ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"RTMP recv %s (%d) csid=%D timestamp=%D "
"mlen=%D msid=%D nbufs=%d",
- ngx_rtmp_message_type(h->type), (int)h->type,
+ ngx_rtmp_message_type(h->type), (int)h->type,
h->csid, h->timestamp, h->mlen, h->msid, nbufs);
}
#endif
@@ -787,7 +788,7 @@
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"calling handler %d", n);
-
+
switch ((*evh)(s, h, in)) {
case NGX_ERROR:
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@@ -802,7 +803,7 @@
}
-ngx_int_t
+ngx_int_t
ngx_rtmp_set_chunk_size(ngx_rtmp_session_t *s, ngx_uint_t size)
{
ngx_rtmp_core_srv_conf_t *cscf;
@@ -847,7 +848,7 @@
bo = lo->buf;
if (bo->end - bo->last >= bi->last - bi->pos) {
- bo->last = ngx_cpymem(bo->last, bi->pos,
+ bo->last = ngx_cpymem(bo->last, bi->pos,
bi->last - bi->pos);
li = li->next;
if (li == fli) {
@@ -858,7 +859,7 @@
continue;
}
- bi->pos += (ngx_cpymem(bo->last, bi->pos,
+ bi->pos += (ngx_cpymem(bo->last, bi->pos,
bo->end - bo->last) - bo->last);
lo->next = ngx_rtmp_alloc_in_buf(s);
lo = lo->next;
@@ -873,13 +874,13 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_finalize_set_chunk_size(ngx_rtmp_session_t *s)
{
if (s->in_chunk_size_changing && s->in_old_pool) {
ngx_destroy_pool(s->in_old_pool);
s->in_old_pool = NULL;
- s->in_chunk_size_changing = 0;
+ s->in_chunk_size_changing = 0;
}
return NGX_OK;
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_handshake.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -33,27 +34,27 @@
/* Handshake keys */
-static u_char
+static u_char
ngx_rtmp_server_key[] = {
'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
- 'S', 'e', 'r', 'v', 'e', 'r', ' ',
+ 'S', 'e', 'r', 'v', 'e', 'r', ' ',
'0', '0', '1',
- 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1,
- 0x02, 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
+ 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1,
+ 0x02, 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
};
-static u_char
+static u_char
ngx_rtmp_client_key[] = {
'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
- 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ',
+ 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ',
'0', '0', '1',
- 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1,
- 0x02, 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
+ 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1,
+ 0x02, 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB,
0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
};
@@ -70,7 +71,7 @@
};
-#define NGX_RTMP_HANDSHAKE_KEYLEN SHA256_DIGEST_LENGTH
+#define NGX_RTMP_HANDSHAKE_KEYLEN SHA256_DIGEST_LENGTH
#define NGX_RTMP_HANDSHAKE_BUFSIZE 1537
@@ -88,7 +89,7 @@
#define NGX_RTMP_HANDSHAKE_CLIENT_DONE 10
-static ngx_str_t ngx_rtmp_server_full_key
+static ngx_str_t ngx_rtmp_server_full_key
= { sizeof(ngx_rtmp_server_key), ngx_rtmp_server_key };
static ngx_str_t ngx_rtmp_server_partial_key
= { 36, ngx_rtmp_server_key };
@@ -100,7 +101,7 @@
static ngx_int_t
-ngx_rtmp_make_digest(ngx_str_t *key, ngx_buf_t *src,
+ngx_rtmp_make_digest(ngx_str_t *key, ngx_buf_t *src,
u_char *skip, u_char *dst, ngx_log_t *log)
{
static HMAC_CTX hmac;
@@ -119,7 +120,7 @@
HMAC_Update(&hmac, src->pos, skip - src->pos);
}
if (src->last != skip + NGX_RTMP_HANDSHAKE_KEYLEN) {
- HMAC_Update(&hmac, skip + NGX_RTMP_HANDSHAKE_KEYLEN,
+ HMAC_Update(&hmac, skip + NGX_RTMP_HANDSHAKE_KEYLEN,
src->last - skip - NGX_RTMP_HANDSHAKE_KEYLEN);
}
} else {
@@ -159,7 +160,7 @@
static ngx_int_t
-ngx_rtmp_write_digest(ngx_buf_t *b, ngx_str_t *key, size_t base,
+ngx_rtmp_write_digest(ngx_buf_t *b, ngx_str_t *key, size_t base,
ngx_log_t *log)
{
size_t n, offs;
@@ -269,7 +270,7 @@
static ngx_int_t
-ngx_rtmp_handshake_parse_challenge(ngx_rtmp_session_t *s,
+ngx_rtmp_handshake_parse_challenge(ngx_rtmp_session_t *s,
ngx_str_t *peer_key, ngx_str_t *key)
{
ngx_buf_t *b;
@@ -278,8 +279,8 @@
b = s->hs_buf;
if (*b->pos != '\x03') {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "handshake: unexpected RTMP version: %i",
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ "handshake: unexpected RTMP version: %i",
(ngx_int_t)*b->pos);
return NGX_ERROR;
}
@@ -303,7 +304,7 @@
offs = ngx_rtmp_find_digest(b, peer_key, 8, s->connection->log);
}
if (offs == NGX_ERROR) {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"handshake: digest not found");
s->hs_old = 1;
return NGX_OK;
@@ -313,7 +314,7 @@
b->pos += offs;
b->last = b->pos + NGX_RTMP_HANDSHAKE_KEYLEN;
s->hs_digest = ngx_palloc(s->connection->pool, NGX_RTMP_HANDSHAKE_KEYLEN);
- if (ngx_rtmp_make_digest(key, b, NULL, s->hs_digest, s->connection->log)
+ if (ngx_rtmp_make_digest(key, b, NULL, s->hs_digest, s->connection->log)
!= NGX_OK)
{
return NGX_ERROR;
@@ -353,8 +354,8 @@
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"handshake: done");
- if (ngx_rtmp_fire_event(s, NGX_RTMP_HANDSHAKE_DONE,
- NULL, NULL) != NGX_OK)
+ if (ngx_rtmp_fire_event(s, NGX_RTMP_HANDSHAKE_DONE,
+ NULL, NULL) != NGX_OK)
{
ngx_rtmp_finalize_session(s);
return;
@@ -380,7 +381,7 @@
}
if (rev->timedout) {
- ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
"handshake: recv: client timed out");
c->timedout = 1;
ngx_rtmp_finalize_session(s);
@@ -422,25 +423,25 @@
switch (s->hs_stage) {
case NGX_RTMP_HANDSHAKE_SERVER_SEND_CHALLENGE:
- if (ngx_rtmp_handshake_parse_challenge(s,
+ if (ngx_rtmp_handshake_parse_challenge(s,
&ngx_rtmp_client_partial_key,
&ngx_rtmp_server_full_key) != NGX_OK)
{
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"handshake: error parsing challenge");
ngx_rtmp_finalize_session(s);
return;
}
if (s->hs_old) {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"handshake: old-style challenge");
s->hs_buf->pos = s->hs_buf->start;
s->hs_buf->last = s->hs_buf->end;
} else if (ngx_rtmp_handshake_create_challenge(s,
ngx_rtmp_server_version,
- &ngx_rtmp_server_partial_key) != NGX_OK)
+ &ngx_rtmp_server_partial_key) != NGX_OK)
{
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"handshake: error creating challenge");
ngx_rtmp_finalize_session(s);
return;
@@ -453,11 +454,11 @@
break;
case NGX_RTMP_HANDSHAKE_CLIENT_RECV_RESPONSE:
- if (ngx_rtmp_handshake_parse_challenge(s,
+ if (ngx_rtmp_handshake_parse_challenge(s,
&ngx_rtmp_server_partial_key,
&ngx_rtmp_client_full_key) != NGX_OK)
{
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"handshake: error parsing challenge");
ngx_rtmp_finalize_session(s);
return;
@@ -468,7 +469,7 @@
case NGX_RTMP_HANDSHAKE_CLIENT_SEND_RESPONSE:
if (ngx_rtmp_handshake_create_response(s) != NGX_OK) {
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"handshake: response error");
ngx_rtmp_finalize_session(s);
return;
@@ -495,7 +496,7 @@
}
if (wev->timedout) {
- ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
"handshake: send: client timed out");
c->timedout = 1;
ngx_rtmp_finalize_session(s);
@@ -538,12 +539,12 @@
switch (s->hs_stage) {
case NGX_RTMP_HANDSHAKE_SERVER_SEND_RESPONSE:
if (s->hs_old) {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"handshake: old-style response");
s->hs_buf->pos = s->hs_buf->start + 1;
s->hs_buf->last = s->hs_buf->end;
} else if (ngx_rtmp_handshake_create_response(s) != NGX_OK) {
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
"handshake: response error");
ngx_rtmp_finalize_session(s);
return;
@@ -602,9 +603,9 @@
s->hs_buf = ngx_rtmp_alloc_handshake_buffer(s);
s->hs_stage = NGX_RTMP_HANDSHAKE_CLIENT_SEND_CHALLENGE;
- if (ngx_rtmp_handshake_create_challenge(s,
+ if (ngx_rtmp_handshake_create_challenge(s,
ngx_rtmp_client_version,
- &ngx_rtmp_client_partial_key) != NGX_OK)
+ &ngx_rtmp_client_partial_key) != NGX_OK)
{
ngx_rtmp_finalize_session(s);
return;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_init.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -140,7 +141,7 @@
ngx_rtmp_core_srv_conf_t *cscf;
ngx_rtmp_error_log_ctx_t *ctx;
- s = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_session_t) +
+ s = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_session_t) +
sizeof(ngx_chain_t *) * ((ngx_rtmp_core_srv_conf_t *)
addr_conf->ctx-> srv_conf[ngx_rtmp_core_module
.ctx_index])->out_queue);
@@ -183,7 +184,7 @@
s->out_queue = cscf->out_queue;
s->out_cork = cscf->out_cork;
- s->in_streams = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_stream_t)
+ s->in_streams = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_stream_t)
* cscf->max_streams);
if (s->in_streams == NULL) {
ngx_rtmp_close_connection(c);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_limit_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2013 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -79,7 +80,7 @@
static ngx_int_t
-ngx_rtmp_limit_connect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_limit_connect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_limit_main_conf_t *lmcf;
@@ -117,7 +118,7 @@
static ngx_int_t
-ngx_rtmp_limit_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_limit_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_limit_main_conf_t *lmcf;
@@ -183,7 +184,7 @@
h = ngx_array_push(&cmcf->events[NGX_RTMP_CONNECT]);
*h = ngx_rtmp_limit_connect;
-
+
h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]);
*h = ngx_rtmp_limit_disconnect;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_live_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -20,7 +21,7 @@
static ngx_int_t ngx_rtmp_live_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_live_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static char *ngx_rtmp_live_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -93,6 +94,13 @@
offsetof(ngx_rtmp_live_app_conf_t, play_restart),
NULL },
+ { ngx_string("idle_streams"),
+ 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_live_app_conf_t, idle_streams),
+ NULL },
+
{ ngx_string("drop_idle_publisher"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
ngx_rtmp_live_set_msec_slot,
@@ -152,6 +160,7 @@
lacf->wait_video = NGX_CONF_UNSET;
lacf->publish_notify = NGX_CONF_UNSET;
lacf->play_restart = NGX_CONF_UNSET;
+ lacf->idle_streams = NGX_CONF_UNSET;
return lacf;
}
@@ -173,13 +182,14 @@
ngx_conf_merge_value(conf->wait_video, prev->wait_video, 0);
ngx_conf_merge_value(conf->publish_notify, prev->publish_notify, 0);
ngx_conf_merge_value(conf->play_restart, prev->play_restart, 0);
+ ngx_conf_merge_value(conf->idle_streams, prev->idle_streams, 1);
conf->pool = ngx_create_pool(4096, &cf->cycle->new_log);
if (conf->pool == NULL) {
return NGX_CONF_ERROR;
}
- conf->streams = ngx_pcalloc(cf->pool,
+ conf->streams = ngx_pcalloc(cf->pool,
sizeof(ngx_rtmp_live_stream_t *) * conf->nbuckets);
return NGX_CONF_OK;
@@ -243,7 +253,7 @@
*stream = ngx_palloc(lacf->pool, sizeof(ngx_rtmp_live_stream_t));
}
ngx_memzero(*stream, sizeof(ngx_rtmp_live_stream_t));
- ngx_memcpy((*stream)->name, name,
+ ngx_memcpy((*stream)->name, name,
ngx_min(sizeof((*stream)->name) - 1, len));
(*stream)->epoch = ngx_current_msec;
@@ -251,7 +261,7 @@
}
-static void
+static void
ngx_rtmp_live_idle(ngx_event_t *pev)
{
ngx_connection_t *c;
@@ -501,11 +511,22 @@
ctx->session = s;
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"live: join '%s'", name);
- stream = ngx_rtmp_live_get_stream(s, name, 1);
- if (stream == NULL) {
+ stream = ngx_rtmp_live_get_stream(s, name, publisher || lacf->idle_streams);
+
+ if (stream == NULL ||
+ !(publisher || (*stream)->publishing || lacf->idle_streams))
+ {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "live: stream not found");
+
+ ngx_rtmp_send_status(s, "NetStream.Play.StreamNotFound", "error",
+ "No such stream");
+
+ ngx_rtmp_finalize_session(s);
+
return;
}
@@ -545,7 +566,8 @@
static ngx_int_t
ngx_rtmp_live_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
{
- ngx_rtmp_live_ctx_t *ctx, **cctx;
+ ngx_rtmp_session_t *ss;
+ ngx_rtmp_live_ctx_t *ctx, **cctx, *pctx;
ngx_rtmp_live_stream_t **stream;
ngx_rtmp_live_app_conf_t *lacf;
@@ -586,6 +608,16 @@
if (ctx->publishing) {
ngx_rtmp_send_status(s, "NetStream.Unpublish.Success",
"status", "Stop publishing");
+ if (!lacf->idle_streams) {
+ for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) {
+ if (pctx->publishing == 0) {
+ ss = pctx->session;
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log, 0,
+ "live: no publisher");
+ ngx_rtmp_finalize_session(ss);
+ }
+ }
+ }
}
if (ctx->stream->ctx) {
@@ -661,7 +693,7 @@
}
static ngx_int_t
-ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_live_ctx_t *ctx, *pctx;
@@ -717,6 +749,8 @@
"live: %s packet timestamp=%uD",
type_s, h->timestamp);
+ s->current_time = h->timestamp;
+
peers = 0;
apkt = NULL;
aapkt = NULL;
@@ -749,7 +783,7 @@
lh.timestamp = cs->timestamp;
}
- clh = ch;
+ clh = lh;
clh.type = (h->type == NGX_RTMP_MSG_AUDIO ? NGX_RTMP_MSG_VIDEO :
NGX_RTMP_MSG_AUDIO);
@@ -916,6 +950,7 @@
cs->timestamp = lh.timestamp;
cs->active = 1;
+ ss->current_time = cs->timestamp;
} else {
@@ -937,6 +972,7 @@
cs->timestamp = ch.timestamp;
cs->active = 1;
+ ss->current_time = cs->timestamp;
++peers;
@@ -970,6 +1006,7 @@
cs->timestamp += delta;
++peers;
+ ss->current_time = cs->timestamp;
}
if (rpkt) {
@@ -991,6 +1028,11 @@
ngx_rtmp_update_bandwidth(&ctx->stream->bw_in, h->mlen);
ngx_rtmp_update_bandwidth(&ctx->stream->bw_out, h->mlen * peers);
+ ngx_rtmp_update_bandwidth(h->type == NGX_RTMP_MSG_AUDIO ?
+ &ctx->stream->bw_in_audio :
+ &ctx->stream->bw_in_video,
+ h->mlen);
+
return NGX_OK;
}
@@ -1046,7 +1088,7 @@
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"live: play: name='%s' start=%uD duration=%uD reset=%d",
- v->name, (uint32_t) v->start,
+ v->name, (uint32_t) v->start,
(uint32_t) v->duration, (uint32_t) v->reset);
/* join stream as subscriber */
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_live_module.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -47,6 +48,8 @@
ngx_rtmp_live_stream_t *next;
ngx_rtmp_live_ctx_t *ctx;
ngx_rtmp_bandwidth_t bw_in;
+ ngx_rtmp_bandwidth_t bw_in_audio;
+ ngx_rtmp_bandwidth_t bw_in_video;
ngx_rtmp_bandwidth_t bw_out;
ngx_msec_t epoch;
unsigned active:1;
@@ -67,6 +70,7 @@
ngx_flag_t wait_video;
ngx_flag_t publish_notify;
ngx_flag_t play_restart;
+ ngx_flag_t idle_streams;
ngx_msec_t buflen;
ngx_pool_t *pool;
ngx_rtmp_live_stream_t *free_streams;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_log_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2013 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -15,7 +16,7 @@
static ngx_int_t ngx_rtmp_log_postconfiguration(ngx_conf_t *cf);
static void *ngx_rtmp_log_create_main_conf(ngx_conf_t *cf);
static void * ngx_rtmp_log_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_log_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_log_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static char * ngx_rtmp_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -189,6 +190,26 @@
static size_t
+ngx_rtmp_log_var_msec_getlen(ngx_rtmp_session_t *s,
+ ngx_rtmp_log_op_t *op)
+{
+ return NGX_TIME_T_LEN + 4;
+}
+
+
+static u_char *
+ngx_rtmp_log_var_msec_getdata(ngx_rtmp_session_t *s, u_char *buf,
+ ngx_rtmp_log_op_t *op)
+{
+ ngx_time_t *tp;
+
+ tp = ngx_timeofday();
+
+ return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec);
+}
+
+
+static size_t
ngx_rtmp_log_var_session_string_getlen(ngx_rtmp_session_t *s,
ngx_rtmp_log_op_t *op)
{
@@ -430,6 +451,11 @@
ngx_rtmp_log_var_time_local_getdata,
0 },
+ { ngx_string("msec"),
+ ngx_rtmp_log_var_msec_getlen,
+ ngx_rtmp_log_var_msec_getdata,
+ 0 },
+
{ ngx_string("session_time"),
ngx_rtmp_log_var_session_time_getlen,
ngx_rtmp_log_var_session_time_getdata,
@@ -888,7 +914,7 @@
static ngx_int_t
-ngx_rtmp_log_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_log_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_log_app_conf_t *lacf;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_mp4_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -23,6 +24,9 @@
static ngx_int_t ngx_rtmp_mp4_reset(ngx_rtmp_session_t *s);
+#define NGX_RTMP_MP4_MAX_FRAMES 8
+
+
#pragma pack(push,4)
@@ -246,8 +250,8 @@
CloseHandle(*extra);
}
- /*
- * non-NULL result means map view handle is open
+ /*
+ * non-NULL result means map view handle is open
* and should be closed later
*/
@@ -323,21 +327,21 @@
u_char *last);
static ngx_int_t ngx_rtmp_mp4_parse_co64(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_avc1(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_avc1(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_avcC(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_avcC(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_mp4a(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_mp4a(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_mp4v(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_mp4v(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_esds(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_esds(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_mp3(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_mp3(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_nmos(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_nmos(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_spex(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_spex(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
@@ -356,7 +360,7 @@
{ ngx_rtmp_mp4_make_tag('m','d','h','d'), ngx_rtmp_mp4_parse_mdhd },
{ ngx_rtmp_mp4_make_tag('h','d','l','r'), ngx_rtmp_mp4_parse_hdlr },
{ ngx_rtmp_mp4_make_tag('m','i','n','f'), ngx_rtmp_mp4_parse },
- { ngx_rtmp_mp4_make_tag('s','t','b','l'), ngx_rtmp_mp4_parse },
+ { ngx_rtmp_mp4_make_tag('s','t','b','l'), ngx_rtmp_mp4_parse },
{ ngx_rtmp_mp4_make_tag('s','t','s','d'), ngx_rtmp_mp4_parse_stsd },
{ ngx_rtmp_mp4_make_tag('s','t','s','c'), ngx_rtmp_mp4_parse_stsc },
{ ngx_rtmp_mp4_make_tag('s','t','t','s'), ngx_rtmp_mp4_parse_stts },
@@ -366,28 +370,29 @@
{ ngx_rtmp_mp4_make_tag('s','t','z','2'), ngx_rtmp_mp4_parse_stz2 },
{ ngx_rtmp_mp4_make_tag('s','t','c','o'), ngx_rtmp_mp4_parse_stco },
{ ngx_rtmp_mp4_make_tag('c','o','6','4'), ngx_rtmp_mp4_parse_co64 },
- { ngx_rtmp_mp4_make_tag('a','v','c','1'), ngx_rtmp_mp4_parse_avc1 },
- { ngx_rtmp_mp4_make_tag('a','v','c','C'), ngx_rtmp_mp4_parse_avcC },
- { ngx_rtmp_mp4_make_tag('m','p','4','a'), ngx_rtmp_mp4_parse_mp4a },
- { ngx_rtmp_mp4_make_tag('m','p','4','v'), ngx_rtmp_mp4_parse_mp4v },
- { ngx_rtmp_mp4_make_tag('e','s','d','s'), ngx_rtmp_mp4_parse_esds },
- { ngx_rtmp_mp4_make_tag('.','m','p','3'), ngx_rtmp_mp4_parse_mp3 },
- { ngx_rtmp_mp4_make_tag('n','m','o','s'), ngx_rtmp_mp4_parse_nmos },
- { ngx_rtmp_mp4_make_tag('s','p','e','x'), ngx_rtmp_mp4_parse_spex }
+ { ngx_rtmp_mp4_make_tag('a','v','c','1'), ngx_rtmp_mp4_parse_avc1 },
+ { ngx_rtmp_mp4_make_tag('a','v','c','C'), ngx_rtmp_mp4_parse_avcC },
+ { ngx_rtmp_mp4_make_tag('m','p','4','a'), ngx_rtmp_mp4_parse_mp4a },
+ { ngx_rtmp_mp4_make_tag('m','p','4','v'), ngx_rtmp_mp4_parse_mp4v },
+ { ngx_rtmp_mp4_make_tag('e','s','d','s'), ngx_rtmp_mp4_parse_esds },
+ { ngx_rtmp_mp4_make_tag('.','m','p','3'), ngx_rtmp_mp4_parse_mp3 },
+ { ngx_rtmp_mp4_make_tag('n','m','o','s'), ngx_rtmp_mp4_parse_nmos },
+ { ngx_rtmp_mp4_make_tag('s','p','e','x'), ngx_rtmp_mp4_parse_spex },
+ { ngx_rtmp_mp4_make_tag('w','a','v','e'), ngx_rtmp_mp4_parse }
};
-static ngx_int_t ngx_rtmp_mp4_parse_descr(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_descr(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_es(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_es(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_dc(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_dc(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-static ngx_int_t ngx_rtmp_mp4_parse_ds(ngx_rtmp_session_t *s, u_char *pos,
+static ngx_int_t ngx_rtmp_mp4_parse_ds(ngx_rtmp_session_t *s, u_char *pos,
u_char *last);
-typedef ngx_int_t (*ngx_rtmp_mp4_descriptor_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_mp4_descriptor_pt)(ngx_rtmp_session_t *s,
u_char *pos, u_char *last);
typedef struct {
@@ -458,7 +463,7 @@
}
if (ctx->track && ctx->track->type &&
- (ctx->ntracks == 0 ||
+ (ctx->ntracks == 0 ||
ctx->tracks[0].type != ctx->tracks[ctx->ntracks].type))
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@@ -593,7 +598,7 @@
static ngx_int_t
-ngx_rtmp_mp4_parse_video(ngx_rtmp_session_t *s, u_char *pos, u_char *last,
+ngx_rtmp_mp4_parse_video(ngx_rtmp_session_t *s, u_char *pos, u_char *last,
ngx_int_t codec)
{
ngx_rtmp_mp4_ctx_t *ctx;
@@ -627,7 +632,7 @@
if (ngx_rtmp_mp4_parse(s, pos, last) != NGX_OK) {
return NGX_ERROR;
}
-
+
ctx->track->fhdr = (u_char) ctx->track->codec;
return NGX_OK;
@@ -640,6 +645,7 @@
{
ngx_rtmp_mp4_ctx_t *ctx;
u_char *p;
+ ngx_uint_t version;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
@@ -653,7 +659,11 @@
return NGX_ERROR;
}
- pos += 16;
+ pos += 8;
+
+ version = ngx_rtmp_r16(*(uint16_t *) pos);
+
+ pos += 8;
ctx->nchannels = ngx_rtmp_r16(*(uint16_t *) pos);
@@ -696,10 +706,24 @@
break;
}
- ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: audio settings codec=%i, nchannels==%ui, "
+ ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "mp4: audio settings version=%ui, codec=%i, nchannels==%ui, "
"sample_size=%ui, sample_rate=%ui",
- codec, ctx->nchannels, ctx->sample_size, ctx->sample_rate);
+ version, codec, ctx->nchannels, ctx->sample_size,
+ ctx->sample_rate);
+
+ switch (version) {
+ case 1:
+ pos += 16;
+ break;
+
+ case 2:
+ pos += 36;
+ }
+
+ if (pos > last) {
+ return NGX_ERROR;
+ }
if (ngx_rtmp_mp4_parse(s, pos, last) != NGX_OK) {
return NGX_ERROR;
@@ -822,7 +846,7 @@
}
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: decoder descriptor id=%i codec=%i",
+ "mp4: decoder descriptor id=%i codec=%i",
(ngx_int_t) id, *pc);
return ngx_rtmp_mp4_parse_descr(s, pos, last);
@@ -879,7 +903,7 @@
ngx_uint_t n, ndesc;
ngx_rtmp_mp4_descriptor_t *ds;
- ndesc = sizeof(ngx_rtmp_mp4_descriptors)
+ ndesc = sizeof(ngx_rtmp_mp4_descriptors)
/ sizeof(ngx_rtmp_mp4_descriptors[0]);
while (pos < last) {
@@ -916,7 +940,7 @@
}
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: descriptor%s tag=%i size=%uD",
+ "mp4: descriptor%s tag=%i size=%uD",
ds ? "" : " unhandled", (ngx_int_t) tag, size);
if (ds && ds->handler(s, pos, pos + size) != NGX_OK) {
@@ -995,12 +1019,12 @@
t->chunks = (ngx_rtmp_mp4_chunks_t *) pos;
- if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->chunks->entry_count) *
+ if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->chunks->entry_count) *
sizeof(t->chunks->entries[0])
<= last)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: chunks entries=%uD",
+ "mp4: chunks entries=%uD",
ngx_rtmp_r32(t->chunks->entry_count));
return NGX_OK;
}
@@ -1026,12 +1050,12 @@
t->times = (ngx_rtmp_mp4_times_t *) pos;
- if (pos + sizeof(*t->times) + ngx_rtmp_r32(t->times->entry_count) *
+ if (pos + sizeof(*t->times) + ngx_rtmp_r32(t->times->entry_count) *
sizeof(t->times->entries[0])
<= last)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: times entries=%uD",
+ "mp4: times entries=%uD",
ngx_rtmp_r32(t->times->entry_count));
return NGX_OK;
}
@@ -1057,12 +1081,12 @@
t->delays = (ngx_rtmp_mp4_delays_t *) pos;
- if (pos + sizeof(*t->delays) + ngx_rtmp_r32(t->delays->entry_count) *
+ if (pos + sizeof(*t->delays) + ngx_rtmp_r32(t->delays->entry_count) *
sizeof(t->delays->entries[0])
<= last)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: delays entries=%uD",
+ "mp4: delays entries=%uD",
ngx_rtmp_r32(t->delays->entry_count));
return NGX_OK;
}
@@ -1088,12 +1112,12 @@
t->keys = (ngx_rtmp_mp4_keys_t *) pos;
- if (pos + sizeof(*t->keys) + ngx_rtmp_r32(t->keys->entry_count) *
+ if (pos + sizeof(*t->keys) + ngx_rtmp_r32(t->keys->entry_count) *
sizeof(t->keys->entries[0])
<= last)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: keys entries=%uD",
+ "mp4: keys entries=%uD",
ngx_rtmp_r32(t->keys->entry_count));
return NGX_OK;
}
@@ -1121,7 +1145,7 @@
if (pos + sizeof(*t->sizes) <= last && t->sizes->sample_size) {
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: sizes size=%uD",
+ "mp4: sizes size=%uD",
ngx_rtmp_r32(t->sizes->sample_size));
return NGX_OK;
}
@@ -1132,7 +1156,7 @@
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: sizes entries=%uD",
+ "mp4: sizes entries=%uD",
ngx_rtmp_r32(t->sizes->sample_count));
return NGX_OK;
}
@@ -1163,8 +1187,8 @@
<= last)
{
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: sizes2 field_size=%uD entries=%uD",
- ngx_rtmp_r32(t->sizes2->field_size),
+ "mp4: sizes2 field_size=%uD entries=%uD",
+ ngx_rtmp_r32(t->sizes2->field_size),
ngx_rtmp_r32(t->sizes2->sample_count));
return NGX_OK;
}
@@ -1195,7 +1219,7 @@
<= last)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: offsets entries=%uD",
+ "mp4: offsets entries=%uD",
ngx_rtmp_r32(t->offsets->entry_count));
return NGX_OK;
}
@@ -1226,7 +1250,7 @@
<= last)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: offsets64 entries=%uD",
+ "mp4: offsets64 entries=%uD",
ngx_rtmp_r32(t->offsets64->entry_count));
return NGX_OK;
}
@@ -1257,7 +1281,7 @@
if (pos + size > last) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
- "mp4: too big box '%*s': size=%uz",
+ "mp4: too big box '%*s': size=%uz",
4, &tag, size);
return NGX_ERROR;
}
@@ -1266,7 +1290,7 @@
nboxes = sizeof(ngx_rtmp_mp4_boxes) / sizeof(ngx_rtmp_mp4_boxes[0]);
for (n = 0; n < nboxes && b->tag != tag; ++n, ++b);
-
+
if (n == nboxes) {
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: box unhandled '%*s'", 4, &tag);
@@ -1313,7 +1337,7 @@
ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui time[%ui] [%ui/%uD][%ui/%uD]=%uD t=%uD",
- t->id, cr->pos, cr->time_pos,
+ t->id, cr->pos, cr->time_pos,
ngx_rtmp_r32(t->times->entry_count),
cr->time_count, ngx_rtmp_r32(te->sample_count),
ngx_rtmp_r32(te->sample_delta),
@@ -1332,7 +1356,7 @@
static ngx_int_t
-ngx_rtmp_mp4_seek_time(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t,
+ngx_rtmp_mp4_seek_time(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t,
uint32_t timestamp)
{
ngx_rtmp_mp4_cursor_t *cr;
@@ -1349,7 +1373,7 @@
while (cr->time_pos < ngx_rtmp_r32(t->times->entry_count)) {
dt = ngx_rtmp_r32(te->sample_delta) * ngx_rtmp_r32(te->sample_count);
-
+
if (cr->timestamp + dt >= timestamp) {
if (te->sample_delta == 0) {
return NGX_ERROR;
@@ -1381,7 +1405,7 @@
ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui seek time[%ui] [%ui/%uD][%ui/%uD]=%uD "
"t=%uD",
- t->id, cr->pos, cr->time_pos,
+ t->id, cr->pos, cr->time_pos,
ngx_rtmp_r32(t->times->entry_count),
cr->time_count,
ngx_rtmp_r32(te->sample_count),
@@ -1424,7 +1448,7 @@
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui offset[%ui/%uD]=%O",
- t->id, cr->chunk,
+ t->id, cr->chunk,
ngx_rtmp_r32(t->offsets->entry_count),
cr->offset);
@@ -1478,7 +1502,7 @@
return NGX_ERROR;
}
-
+
ce = &t->chunks->entries[cr->chunk_pos];
cr->chunk_count++;
@@ -1537,8 +1561,8 @@
while (cr->chunk_pos + 1 < ngx_rtmp_r32(t->chunks->entry_count)) {
nce = ce + 1;
-
- dpos = (ngx_rtmp_r32(nce->first_chunk) -
+
+ dpos = (ngx_rtmp_r32(nce->first_chunk) -
ngx_rtmp_r32(ce->first_chunk)) *
ngx_rtmp_r32(ce->samples_per_chunk);
@@ -1559,7 +1583,7 @@
cr->chunk = ngx_rtmp_r32(ce->first_chunk) + dchunk;
cr->chunk_pos = (ngx_uint_t) (ce - t->chunks->entries);
- cr->chunk_count = (ngx_uint_t) (cr->pos - pos - dchunk *
+ cr->chunk_count = (ngx_uint_t) (cr->pos - pos - dchunk *
ngx_rtmp_r32(ce->samples_per_chunk));
ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@@ -1609,7 +1633,7 @@
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui size[%ui/%uD]=%uz",
- t->id, cr->size_pos,
+ t->id, cr->size_pos,
ngx_rtmp_r32(t->sizes->sample_count),
cr->size);
@@ -1678,7 +1702,7 @@
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui seek size[%ui/%uD]=%uz",
- t->id, cr->size_pos,
+ t->id, cr->size_pos,
ngx_rtmp_r32(t->sizes->sample_count),
cr->size);
@@ -1731,7 +1755,7 @@
return NGX_OK;
}
-
+
ke = &t->keys->entries[cr->key_pos];
cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));
@@ -1870,7 +1894,7 @@
while (cr->delay_pos < ngx_rtmp_r32(t->delays->entry_count)) {
dpos = ngx_rtmp_r32(de->sample_count);
-
+
if (pos + dpos > cr->pos) {
cr->delay_count = cr->pos - pos;
cr->delay = ngx_rtmp_r32(de->sample_offset);
@@ -1943,46 +1967,46 @@
static ngx_rtmp_amf_elt_t out_inf[] = {
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("width"),
&v.width, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("height"),
&v.height, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("displayWidth"),
&v.width, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("displayHeight"),
&v.height, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("duration"),
&v.duration, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("videocodecid"),
&v.video_codec_id, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("audiocodecid"),
&v.audio_codec_id, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("audiosamplerate"),
&v.audio_sample_rate, 0 },
};
static ngx_rtmp_amf_elt_t out_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
"onMetaData", 0 },
- { NGX_RTMP_AMF_OBJECT,
+ { NGX_RTMP_AMF_OBJECT,
ngx_null_string,
out_inf, sizeof(out_inf) },
};
@@ -2019,7 +2043,7 @@
}
out = NULL;
- rc = ngx_rtmp_append_amf(s, &out, NULL, out_elts,
+ rc = ngx_rtmp_append_amf(s, &out, NULL, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
if (rc != NGX_OK || out == NULL) {
return NGX_ERROR;
@@ -2071,15 +2095,16 @@
ngx_rtmp_header_t h, lh;
ngx_rtmp_core_srv_conf_t *cscf;
ngx_chain_t *out, in;
- ngx_rtmp_mp4_track_t *t;
- ngx_rtmp_mp4_cursor_t *cr;
- uint32_t buflen, end_timestamp, sched,
- timestamp, last_timestamp, rdelay;
+ ngx_rtmp_mp4_track_t *t, *cur_t;
+ ngx_rtmp_mp4_cursor_t *cr, *cur_cr;
+ uint32_t buflen, end_timestamp,
+ timestamp, last_timestamp, rdelay,
+ cur_timestamp;
ssize_t ret;
u_char fhdr[5];
size_t fhdr_size;
ngx_int_t rc;
- ngx_uint_t n, active;
+ ngx_uint_t n, counter;
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
@@ -2102,31 +2127,57 @@
buflen = (s->buflen ? s->buflen + NGX_RTMP_MP4_BUFLEN_ADDON:
NGX_RTMP_MP4_DEFAULT_BUFLEN);
- t = ctx->tracks;
-
- sched = 0;
- active = 0;
+ counter = 0;
last_timestamp = 0;
-
- end_timestamp = ctx->start_timestamp +
+ end_timestamp = ctx->start_timestamp +
(ngx_current_msec - ctx->epoch) + buflen;
- for (n = 0; n < ctx->ntracks; ++n, ++t) {
- cr = &t->cursor;
+ for ( ;; ) {
+ counter++;
+ if (counter > NGX_RTMP_MP4_MAX_FRAMES) {
+ return NGX_OK;
+ }
- if (!cr->valid) {
- continue;
+ timestamp = 0;
+ t = NULL;
+
+ for (n = 0; n < ctx->ntracks; n++) {
+ cur_t = &ctx->tracks[n];
+ cur_cr = &cur_t->cursor;
+
+ if (!cur_cr->valid) {
+ continue;
+ }
+
+ cur_timestamp = ngx_rtmp_mp4_to_rtmp_timestamp(cur_t,
+ cur_cr->timestamp);
+
+ if (t == NULL || cur_timestamp < timestamp) {
+ timestamp = cur_timestamp;
+ t = cur_t;
+ }
}
- timestamp = ngx_rtmp_mp4_to_rtmp_timestamp(t, cr->timestamp);
+ if (t == NULL) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "mp4: no track");
+ return NGX_DONE;
+ }
if (timestamp > end_timestamp) {
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: track#%ui ahead %uD > %uD",
- t->id, timestamp, end_timestamp);
- goto next;
+ "mp4: track#%ui ahead %uD > %uD",
+ t->id, timestamp, end_timestamp);
+
+ if (ts) {
+ *ts = last_timestamp;
+ }
+
+ return (uint32_t) (timestamp - end_timestamp);
}
+ cr = &t->cursor;
+
last_timestamp = ngx_rtmp_mp4_to_rtmp_timestamp(t, cr->last_timestamp);
ngx_memzero(&h, sizeof(h));
@@ -2150,7 +2201,7 @@
fhdr[0] = t->fhdr;
fhdr[1] = 0;
-
+
if (t->type == NGX_RTMP_MSG_VIDEO) {
fhdr[0] |= 0x10;
fhdr[2] = fhdr[3] = fhdr[4] = 0;
@@ -2186,8 +2237,8 @@
ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui read frame offset=%O, size=%uz, "
- "timestamp=%uD, last_timestamp=%uD",
- t->id, cr->offset, cr->size, timestamp,
+ "timestamp=%uD, last_timestamp=%uD",
+ t->id, cr->offset, cr->size, timestamp,
last_timestamp);
ngx_rtmp_mp4_buffer[0] = t->fhdr;
@@ -2204,7 +2255,7 @@
if (t->header) {
fhdr_size = 5;
-
+
rdelay = ngx_rtmp_mp4_to_rtmp_timestamp(t, cr->delay);
ngx_rtmp_mp4_buffer[1] = 1;
@@ -2222,18 +2273,18 @@
if (cr->size + fhdr_size > sizeof(ngx_rtmp_mp4_buffer)) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "mp4: track#%ui too big frame: %D>%uz",
+ "mp4: track#%ui too big frame: %D>%uz",
t->id, cr->size, sizeof(ngx_rtmp_mp4_buffer));
- continue;
+ goto next;
}
- ret = ngx_read_file(f, ngx_rtmp_mp4_buffer + fhdr_size,
+ ret = ngx_read_file(f, ngx_rtmp_mp4_buffer + fhdr_size,
cr->size, cr->offset);
if (ret != (ssize_t) cr->size) {
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"mp4: track#%ui could not read frame", t->id);
- continue;
+ goto next;
}
in.buf = &in_buf;
@@ -2241,7 +2292,7 @@
in_buf.last = ngx_rtmp_mp4_buffer + cr->size + fhdr_size;
out = ngx_rtmp_append_shared_bufs(cscf, NULL, &in);
-
+
ngx_rtmp_prepare_message(s, &h, cr->not_first ? &lh : NULL, out);
rc = ngx_rtmp_send_message(s, out, 0);
ngx_rtmp_free_shared_chain(cscf, out);
@@ -2250,35 +2301,13 @@
return NGX_AGAIN;
}
- if (ngx_rtmp_mp4_next(s, t) != NGX_OK) {
- continue;
- }
+ s->current_time = timestamp;
next:
- active = 1;
-
- if (timestamp > end_timestamp &&
- (sched == 0 || timestamp < end_timestamp + sched))
- {
- sched = (uint32_t) (timestamp - end_timestamp);
+ if (ngx_rtmp_mp4_next(s, t) != NGX_OK) {
+ return NGX_DONE;
}
}
-
- if (sched) {
- return sched;
- }
-
- if (active) {
- return NGX_OK;
- }
-
- if (ts) {
- *ts = last_timestamp;
- }
-
- /*ngx_rtmp_mp4_reset(s);*/
-
- return NGX_DONE;
}
@@ -2380,7 +2409,7 @@
return NGX_ERROR;
}
- return ngx_rtmp_mp4_parse(s, (u_char *) ctx->mmaped + page_offset,
+ return ngx_rtmp_mp4_parse(s, (u_char *) ctx->mmaped + page_offset,
(u_char *) ctx->mmaped + page_offset + size);
}
@@ -2543,7 +2572,7 @@
}
fmt = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_play_fmt_t));
-
+
if (fmt == NULL) {
return NGX_ERROR;
}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_netcall_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -10,7 +11,7 @@
static ngx_int_t ngx_rtmp_netcall_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_netcall_create_srv_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_netcall_merge_srv_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_netcall_merge_srv_conf(ngx_conf_t *cf,
void *parent, void *child);
static void ngx_rtmp_netcall_close(ngx_connection_t *cc);
@@ -131,7 +132,7 @@
static ngx_int_t
-ngx_rtmp_netcall_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_netcall_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_netcall_ctx_t *ctx;
@@ -149,7 +150,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_netcall_get_peer(ngx_peer_connection_t *pc, void *data)
{
ngx_rtmp_netcall_session_t *cs = data;
@@ -162,7 +163,7 @@
}
-static void
+static void
ngx_rtmp_netcall_free_peer(ngx_peer_connection_t *pc, void *data,
ngx_uint_t state)
{
@@ -191,7 +192,7 @@
/* get module context */
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_netcall_module);
if (ctx == NULL) {
- ctx = ngx_pcalloc(c->pool,
+ ctx = ngx_pcalloc(c->pool,
sizeof(ngx_rtmp_netcall_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
@@ -246,7 +247,7 @@
/* connect */
rc = ngx_event_connect_peer(pc);
if (rc != NGX_OK && rc != NGX_AGAIN ) {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"netcall: connection failed");
goto error;
}
@@ -258,7 +259,7 @@
cs->out = ci->create(s, ci->arg, pool);
if (cs->out == NULL) {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"netcall: creation failed");
ngx_close_connection(pc->connection);
goto error;
@@ -453,7 +454,7 @@
}
if (wev->timedout) {
- ngx_log_error(NGX_LOG_INFO, cc->log, NGX_ETIMEDOUT,
+ ngx_log_error(NGX_LOG_INFO, cc->log, NGX_ETIMEDOUT,
"netcall: client send timed out");
cc->timedout = 1;
ngx_rtmp_netcall_close(cc);
@@ -545,7 +546,7 @@
if (bl == NULL) {
return NULL;
}
-
+
b = ngx_create_temp_buf(pool, sizeof(rq_tmpl) + host->len +
content_type->len + NGX_SIZE_T_LEN);
if (b == NULL) {
@@ -582,7 +583,7 @@
sizeof("app=") - 1 + s->app.len * 3 +
sizeof("&flashver=") - 1 + s->flashver.len * 3 +
sizeof("&swfurl=") - 1 + s->swf_url.len * 3 +
- sizeof("&tcurl=") - 1 + s->tc_url.len * 3 +
+ sizeof("&tcurl=") - 1 + s->tc_url.len * 3 +
sizeof("&pageurl=") - 1 + s->page_url.len * 3 +
sizeof("&addr=") - 1 + addr_text->len * 3
);
@@ -598,35 +599,35 @@
b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
sizeof("&flashver=") - 1);
- b->last = (u_char*) ngx_escape_uri(b->last, s->flashver.data,
+ b->last = (u_char*) ngx_escape_uri(b->last, s->flashver.data,
s->flashver.len, NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
sizeof("&swfurl=") - 1);
- b->last = (u_char*) ngx_escape_uri(b->last, s->swf_url.data,
+ b->last = (u_char*) ngx_escape_uri(b->last, s->swf_url.data,
s->swf_url.len, NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
sizeof("&tcurl=") - 1);
- b->last = (u_char*) ngx_escape_uri(b->last, s->tc_url.data,
+ b->last = (u_char*) ngx_escape_uri(b->last, s->tc_url.data,
s->tc_url.len, NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
sizeof("&pageurl=") - 1);
- b->last = (u_char*) ngx_escape_uri(b->last, s->page_url.data,
+ b->last = (u_char*) ngx_escape_uri(b->last, s->page_url.data,
s->page_url.len, NGX_ESCAPE_ARGS);
b->last = ngx_cpymem(b->last, (u_char*) "&addr=", sizeof("&addr=") -1);
- b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
+ b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
addr_text->len, NGX_ESCAPE_ARGS);
return cl;
}
-ngx_chain_t *
+ngx_chain_t *
ngx_rtmp_netcall_http_skip_header(ngx_chain_t *in)
{
ngx_buf_t *b;
@@ -653,7 +654,7 @@
}
b = in->buf;
}
-
+
switch (*b->pos++) {
case '\r':
state = (state == lf) ? lfcr : normal;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_netcall_module.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -17,7 +18,7 @@
typedef ngx_int_t (*ngx_rtmp_netcall_filter_pt)(ngx_chain_t *in);
typedef ngx_int_t (*ngx_rtmp_netcall_sink_pt)(ngx_rtmp_session_t *s,
ngx_chain_t *in);
-typedef ngx_int_t (*ngx_rtmp_netcall_handle_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_netcall_handle_pt)(ngx_rtmp_session_t *s,
void *arg, ngx_chain_t *in);
#define NGX_RTMP_NETCALL_HTTP_GET 0
@@ -44,12 +45,12 @@
} ngx_rtmp_netcall_init_t;
-ngx_int_t ngx_rtmp_netcall_create(ngx_rtmp_session_t *s,
+ngx_int_t ngx_rtmp_netcall_create(ngx_rtmp_session_t *s,
ngx_rtmp_netcall_init_t *ci);
/* HTTP handling */
-ngx_chain_t * ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s,
+ngx_chain_t * ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s,
ngx_pool_t *pool);
ngx_chain_t * ngx_rtmp_netcall_http_format_request(ngx_int_t method,
ngx_str_t *host, ngx_str_t *uri, ngx_chain_t *args, ngx_chain_t *body,
@@ -58,8 +59,8 @@
/* Memcache handling */
-ngx_chain_t * ngx_rtmp_netcall_memcache_set(ngx_rtmp_session_t *s,
- ngx_pool_t *pool, ngx_str_t *key, ngx_str_t *value,
+ngx_chain_t * ngx_rtmp_netcall_memcache_set(ngx_rtmp_session_t *s,
+ ngx_pool_t *pool, ngx_str_t *key, ngx_str_t *value,
ngx_uint_t flags, ngx_uint_t sec);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_notify_module.c
^
|
@@ -1,10 +1,12 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_md5.h>
#include "ngx_rtmp.h"
#include "ngx_rtmp_cmd_module.h"
#include "ngx_rtmp_netcall_module.h"
@@ -28,16 +30,16 @@
void *conf);
static ngx_int_t ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static void *ngx_rtmp_notify_create_srv_conf(ngx_conf_t *cf);
static char *ngx_rtmp_notify_merge_srv_conf(ngx_conf_t *cf, void *parent,
void *child);
-static ngx_int_t ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname,
+static ngx_int_t ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname,
ngx_uint_t url_idx);
-ngx_str_t ngx_rtmp_notify_urlencoded =
+ngx_str_t ngx_rtmp_notify_urlencoded =
ngx_string("application/x-www-form-urlencoded");
@@ -347,7 +349,7 @@
static ngx_chain_t *
-ngx_rtmp_notify_connect_create(ngx_rtmp_session_t *s, void *arg,
+ngx_rtmp_notify_connect_create(ngx_rtmp_session_t *s, void *arg,
ngx_pool_t *pool)
{
ngx_rtmp_connect_t *v = arg;
@@ -368,7 +370,7 @@
}
/* these values are still missing in session
- * so we have to construct the request from
+ * so we have to construct the request from
* connection struct */
app_len = ngx_strlen(v->app);
@@ -385,7 +387,7 @@
sizeof("&app=") - 1 + app_len * 3 +
sizeof("&flashver=") - 1 + flashver_len * 3 +
sizeof("&swfurl=") - 1 + swf_url_len * 3 +
- sizeof("&tcurl=") - 1 + tc_url_len * 3 +
+ sizeof("&tcurl=") - 1 + tc_url_len * 3 +
sizeof("&pageurl=") - 1 + page_url_len * 3 +
sizeof("&addr=") - 1 + addr_text->len * 3 +
1 + args_len
@@ -402,31 +404,31 @@
b->last = (u_char*) ngx_escape_uri(b->last, v->app, app_len,
NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
sizeof("&flashver=") - 1);
b->last = (u_char*) ngx_escape_uri(b->last, v->flashver, flashver_len,
NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
sizeof("&swfurl=") - 1);
b->last = (u_char*) ngx_escape_uri(b->last, v->swf_url, swf_url_len,
NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
sizeof("&tcurl=") - 1);
b->last = (u_char*) ngx_escape_uri(b->last, v->tc_url, tc_url_len,
NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
+ b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
sizeof("&pageurl=") - 1);
b->last = (u_char*) ngx_escape_uri(b->last, v->page_url, page_url_len,
NGX_ESCAPE_ARGS);
b->last = ngx_cpymem(b->last, (u_char*) "&addr=", sizeof("&addr=") -1);
- b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
+ b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
addr_text->len, NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*) "&call=connect",
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=connect",
sizeof("&call=connect") - 1);
if (args_len) {
@@ -450,7 +452,7 @@
static ngx_chain_t *
-ngx_rtmp_notify_disconnect_create(ngx_rtmp_session_t *s, void *arg,
+ngx_rtmp_notify_disconnect_create(ngx_rtmp_session_t *s, void *arg,
ngx_pool_t *pool)
{
ngx_rtmp_notify_srv_conf_t *nscf;
@@ -476,7 +478,7 @@
pl->buf = b;
pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*) "&call=disconnect",
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=disconnect",
sizeof("&call=disconnect") - 1);
b->last = ngx_cpymem(b->last, (u_char*) "&app=", sizeof("&app=") - 1);
@@ -511,7 +513,7 @@
static ngx_chain_t *
-ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
+ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
ngx_pool_t *pool)
{
ngx_rtmp_publish_t *v = arg;
@@ -541,7 +543,7 @@
pl->buf = b;
pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
sizeof("&call=publish") - 1);
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
@@ -562,7 +564,7 @@
static ngx_chain_t *
-ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
+ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
ngx_pool_t *pool)
{
ngx_rtmp_play_t *v = arg;
@@ -580,7 +582,7 @@
args_len = ngx_strlen(v->args);
b = ngx_create_temp_buf(pool,
- sizeof("&call=play") +
+ sizeof("&call=play") +
sizeof("&name=") + name_len * 3 +
sizeof("&start=&duration=&reset=") +
NGX_INT32_LEN * 3 + 1 + args_len);
@@ -591,7 +593,7 @@
pl->buf = b;
pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
sizeof("&call=play") - 1);
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
@@ -613,7 +615,7 @@
static ngx_chain_t *
-ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
+ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
ngx_pool_t *pool)
{
ngx_rtmp_notify_done_t *ds = arg;
@@ -664,7 +666,7 @@
static ngx_chain_t *
-ngx_rtmp_notify_update_create(ngx_rtmp_session_t *s, void *arg,
+ngx_rtmp_notify_update_create(ngx_rtmp_session_t *s, void *arg,
ngx_pool_t *pool)
{
ngx_chain_t *pl;
@@ -694,6 +696,7 @@
b = ngx_create_temp_buf(pool,
sizeof("&call=update") + sfx.len +
sizeof("&time=") + NGX_TIME_T_LEN +
+ sizeof("×tamp=") + NGX_INT32_LEN +
sizeof("&name=") + name_len * 3 +
1 + args_len);
if (b == NULL) {
@@ -711,6 +714,10 @@
sizeof("&time=") - 1);
b->last = ngx_sprintf(b->last, "%T", ngx_cached_time->sec - ctx->start);
+ b->last = ngx_cpymem(b->last, (u_char *) "×tamp=",
+ sizeof("×tamp=") - 1);
+ b->last = ngx_sprintf(b->last, "%D", s->current_time);
+
if (name_len) {
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,
@@ -749,7 +756,7 @@
b = ngx_create_temp_buf(pool,
sizeof("&call=record_done") +
- sizeof("&recorder=") + v->recorder.len +
+ sizeof("&recorder=") + v->recorder.len +
sizeof("&name=") + name_len * 3 +
sizeof("&path=") + v->path.len * 3 +
1 + args_len);
@@ -760,10 +767,10 @@
pl->buf = b;
pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*) "&call=record_done",
+ 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=",
+ 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, NGX_ESCAPE_ARGS);
@@ -786,9 +793,9 @@
}
-static ngx_int_t
-ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
- ngx_chain_t *in)
+static ngx_int_t
+ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
+ ngx_chain_t *in)
{
ngx_buf_t *b;
ngx_int_t n;
@@ -826,7 +833,7 @@
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"notify: empty or broken HTTP response");
- /*
+ /*
* not enough data;
* it can happen in case of empty or broken reply
*/
@@ -835,8 +842,8 @@
}
-static ngx_int_t
-ngx_rtmp_notify_parse_http_header(ngx_rtmp_session_t *s,
+static ngx_int_t
+ngx_rtmp_notify_parse_http_header(ngx_rtmp_session_t *s,
ngx_chain_t *in, ngx_str_t *name, u_char *data, size_t len)
{
ngx_buf_t *b;
@@ -941,8 +948,8 @@
}
-static ngx_int_t
-ngx_rtmp_notify_connect_handle(ngx_rtmp_session_t *s,
+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;
@@ -973,8 +980,24 @@
}
-static ngx_int_t
-ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s,
+static void
+ngx_rtmp_notify_set_name(u_char *dst, size_t dst_len, u_char *src,
+ size_t src_len)
+{
+ u_char result[16], *p;
+ ngx_md5_t md5;
+
+ ngx_md5_init(&md5);
+ ngx_md5_update(&md5, src, src_len);
+ ngx_md5_final(result, &md5);
+
+ p = ngx_hex_dump(dst, result, ngx_min((dst_len - 1) / 2, 16));
+ *p = '\0';
+}
+
+
+static ngx_int_t
+ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s,
void *arg, ngx_chain_t *in)
{
ngx_rtmp_publish_t *v = arg;
@@ -1019,7 +1042,7 @@
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
if (nacf->relay_redirect) {
- *ngx_cpymem(v->name, name, rc) = 0;
+ ngx_rtmp_notify_set_name(v->name, NGX_RTMP_MAX_NAME, name, (size_t) rc);
}
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
@@ -1052,8 +1075,8 @@
}
-static ngx_int_t
-ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s,
+static ngx_int_t
+ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s,
void *arg, ngx_chain_t *in)
{
ngx_rtmp_play_t *v = arg;
@@ -1098,7 +1121,7 @@
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
if (nacf->relay_redirect) {
- *ngx_cpymem(v->name, name, rc) = 0;
+ ngx_rtmp_notify_set_name(v->name, NGX_RTMP_MAX_NAME, name, (size_t) rc);
}
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
@@ -1131,8 +1154,8 @@
}
-static ngx_int_t
-ngx_rtmp_notify_update_handle(ngx_rtmp_session_t *s,
+static ngx_int_t
+ngx_rtmp_notify_update_handle(ngx_rtmp_session_t *s,
void *arg, ngx_chain_t *in)
{
ngx_rtmp_notify_app_conf_t *nacf;
@@ -1142,7 +1165,7 @@
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
rc = ngx_rtmp_notify_parse_http_retcode(s, in);
-
+
if ((!nacf->update_strict && rc == NGX_ERROR) ||
(nacf->update_strict && rc != NGX_OK))
{
@@ -1164,7 +1187,7 @@
}
-static void
+static void
ngx_rtmp_notify_update(ngx_event_t *e)
{
ngx_connection_t *c;
@@ -1200,7 +1223,7 @@
static void
-ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
+ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
u_char name[NGX_RTMP_MAX_NAME], u_char args[NGX_RTMP_MAX_ARGS],
ngx_uint_t flags)
{
@@ -1539,7 +1562,7 @@
u->url.data = url->data + add;
u->default_port = 80;
u->uri_part = 1;
-
+
if (ngx_parse_url(cf->pool, u) != NGX_OK) {
if (u->err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_play_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -22,7 +23,7 @@
static void *ngx_rtmp_play_create_main_conf(ngx_conf_t *cf);
static ngx_int_t ngx_rtmp_play_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_play_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_play_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_play_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_rtmp_play_do_init(ngx_rtmp_session_t *s);
@@ -121,7 +122,7 @@
return NULL;
}
- if (ngx_array_init(&pmcf->fmts, cf->pool, 1,
+ if (ngx_array_init(&pmcf->fmts, cf->pool, 1,
sizeof(ngx_rtmp_play_fmt_t *))
!= NGX_OK)
{
@@ -715,8 +716,8 @@
* we should not move out of play directory */
for (p = v->name; *p; ++p) {
if (ngx_path_separator(p[0]) &&
- p[1] == '.' && p[2] == '.' &&
- ngx_path_separator(p[3]))
+ p[1] == '.' && p[2] == '.' &&
+ ngx_path_separator(p[3]))
{
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"play: bad name '%s'", v->name);
@@ -734,7 +735,7 @@
ctx->session = s;
ctx->aindex = ngx_rtmp_play_parse_index('a', v->args);
ctx->vindex = ngx_rtmp_play_parse_index('v', v->args);
-
+
ctx->file.log = s->connection->log;
ngx_memcpy(ctx->name, v->name, NGX_RTMP_MAX_NAME);
@@ -743,7 +744,7 @@
name.data = v->name;
pfmt = pmcf->fmts.elts;
-
+
for (n = 0; n < pmcf->fmts.nelts; ++n, ++pfmt) {
fmt = *pfmt;
@@ -764,7 +765,7 @@
}
if (name.len >= sfx->len &&
- ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len,
+ ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len,
sfx->len) == 0)
{
ctx->fmt = fmt;
@@ -784,7 +785,7 @@
sfx = &ctx->fmt->sfx;
if (name.len < sfx->len ||
- ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len,
+ ngx_strncasecmp(sfx->data, name.data + name.len - sfx->len,
sfx->len))
{
ctx->sfx = *sfx;
@@ -856,7 +857,7 @@
pe->root, v->name + ctx->pfx_size, &ctx->sfx);
*p = 0;
- ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN,
+ ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN,
NGX_FILE_DEFAULT_ACCESS);
if (ctx->file.fd == NGX_INVALID_FILE) {
@@ -993,7 +994,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_play_remote_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in)
{
ngx_rtmp_play_t *v = arg;
@@ -1021,7 +1022,7 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_play_remote_sink(ngx_rtmp_session_t *s, ngx_chain_t *in)
{
ngx_rtmp_play_ctx_t *ctx;
@@ -1045,7 +1046,7 @@
}
/* 10th header byte is HTTP response header */
if (++ctx->nheader == 10 && *b->pos != (u_char) '2') {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"play: remote HTTP response code: %cxx",
*b->pos);
return NGX_ERROR;
@@ -1068,7 +1069,7 @@
rc = ngx_write_fd(ctx->file.fd, b->pos, b->last - b->pos);
if (rc == NGX_ERROR) {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, ngx_errno,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, ngx_errno,
"play: error writing to temp file");
return NGX_ERROR;
}
@@ -1208,7 +1209,7 @@
if (pe->root == NULL) {
return NGX_CONF_ERROR;
}
-
+
*pe->root = value[n];
continue;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_play_module.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -13,13 +14,13 @@
#include "ngx_rtmp_cmd_module.h"
-typedef ngx_int_t (*ngx_rtmp_play_init_pt) (ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_play_init_pt) (ngx_rtmp_session_t *s,
ngx_file_t *f, ngx_int_t aindex, ngx_int_t vindex);
typedef ngx_int_t (*ngx_rtmp_play_done_pt) (ngx_rtmp_session_t *s,
ngx_file_t *f);
-typedef ngx_int_t (*ngx_rtmp_play_start_pt) (ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_play_start_pt) (ngx_rtmp_session_t *s,
ngx_file_t *f);
-typedef ngx_int_t (*ngx_rtmp_play_seek_pt) (ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_play_seek_pt) (ngx_rtmp_session_t *s,
ngx_file_t *f, ngx_uint_t offs);
typedef ngx_int_t (*ngx_rtmp_play_stop_pt) (ngx_rtmp_session_t *s,
ngx_file_t *f);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_receive.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -11,12 +12,12 @@
#include <string.h>
-ngx_int_t
+ngx_int_t
ngx_rtmp_protocol_message_handler(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in)
{
ngx_buf_t *b;
- u_char *p;
+ u_char *p;
uint32_t val;
uint8_t limit;
@@ -66,7 +67,7 @@
(void)limit;
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "receive bandwidth=%uD limit=%d",
+ "receive bandwidth=%uD limit=%d",
val, (int)limit);
/* receive window size =val
@@ -82,12 +83,12 @@
}
-ngx_int_t
+ngx_int_t
ngx_rtmp_user_message_handler(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_buf_t *b;
- u_char *p;
+ u_char *p;
uint16_t evt;
uint32_t val;
@@ -106,7 +107,7 @@
p[1] = b->pos[0];
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "RTMP recv user evt %s (%i)",
+ "RTMP recv user evt %s (%i)",
ngx_rtmp_user_message_type(evt), (ngx_int_t) evt);
p = (u_char *) &val;
@@ -255,7 +256,7 @@
}
-ngx_int_t
+ngx_int_t
ngx_rtmp_aggregate_message_handler(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
@@ -321,7 +322,7 @@
}
if (cl == NULL) {
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"RTMP error parsing aggregate");
return NGX_ERROR;
}
@@ -363,7 +364,7 @@
}
-ngx_int_t
+ngx_int_t
ngx_rtmp_amf_message_handler(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in)
{
@@ -378,14 +379,14 @@
static ngx_rtmp_amf_elt_t elts[] = {
{ NGX_RTMP_AMF_STRING,
- ngx_null_string,
+ ngx_null_string,
func, sizeof(func) },
};
/* AMF command names come with string type, but shared object names
* come without type */
- if (h->type == NGX_RTMP_MSG_AMF_SHARED ||
- h->type == NGX_RTMP_MSG_AMF3_SHARED)
+ if (h->type == NGX_RTMP_MSG_AMF_SHARED ||
+ h->type == NGX_RTMP_MSG_AMF3_SHARED)
{
elts[0].type |= NGX_RTMP_AMF_TYPELESS;
} else {
@@ -395,7 +396,7 @@
if ((h->type == NGX_RTMP_MSG_AMF3_SHARED ||
h->type == NGX_RTMP_MSG_AMF3_META ||
h->type == NGX_RTMP_MSG_AMF3_CMD)
- && in->buf->last > in->buf->pos)
+ && in->buf->last > in->buf->pos)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"AMF3 prefix: %ui", (ngx_int_t)*in->buf->pos);
@@ -410,8 +411,8 @@
act.log = s->connection->log;
memset(func, 0, sizeof(func));
- if (ngx_rtmp_amf_read(&act, elts,
- sizeof(elts) / sizeof(elts[0])) != NGX_OK)
+ if (ngx_rtmp_amf_read(&act, elts,
+ sizeof(elts) / sizeof(elts[0])) != NGX_OK)
{
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"AMF cmd failed");
@@ -424,14 +425,14 @@
len = ngx_strlen(func);
- ch = ngx_hash_find(&cmcf->amf_hash,
+ ch = ngx_hash_find(&cmcf->amf_hash,
ngx_hash_strlow(func, func, len), func, len);
if (ch && ch->nelts) {
ph = ch->elts;
for (n = 0; n < ch->nelts; ++n, ++ph) {
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "AMF func '%s' passed to handler %d/%d",
+ "AMF func '%s' passed to handler %d/%d",
func, n, ch->nelts);
switch ((*ph)(s, h, in)) {
case NGX_ERROR:
@@ -460,4 +461,4 @@
act.log = s->connection->log;
return ngx_rtmp_amf_read(&act, elts, nelts);
-}
+}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_record_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -25,9 +26,9 @@
void *conf);
static ngx_int_t ngx_rtmp_record_postconfiguration(ngx_conf_t *cf);
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);
-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_rec_ctx_t *rctx,
ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_int_t inc_nframes);
static ngx_int_t ngx_rtmp_record_av(ngx_rtmp_session_t *s,
@@ -38,7 +39,7 @@
ngx_rtmp_record_rec_ctx_t *rctx);
static ngx_int_t ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
ngx_rtmp_record_rec_ctx_t *rctx);
-static void 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_rec_ctx_t *rctx, ngx_str_t *path);
static ngx_int_t ngx_rtmp_record_init(ngx_rtmp_session_t *s);
@@ -220,7 +221,7 @@
ngx_conf_merge_value(conf->append, prev->append, 0);
ngx_conf_merge_value(conf->lock_file, prev->lock_file, 0);
ngx_conf_merge_value(conf->notify, prev->notify, 0);
- ngx_conf_merge_msec_value(conf->interval, prev->interval,
+ ngx_conf_merge_msec_value(conf->interval, prev->interval,
(ngx_msec_t) NGX_CONF_UNSET);
ngx_conf_merge_bitmask_value(conf->flags, prev->flags, 0);
ngx_conf_merge_ptr_value(conf->url, prev->url, NULL);
@@ -247,9 +248,9 @@
0x56, /* 'V' */
0x01, /* version = 1 */
0x05, /* 00000 1 0 1 = has audio & video */
- 0x00,
- 0x00,
- 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
0x09, /* header size */
0x00,
0x00,
@@ -291,7 +292,7 @@
ngx_rtmp_record_rec_ctx_t *rctx;
ngx_int_t rc;
- 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);
rctx = ngx_rtmp_record_get_node_ctx(s, n);
@@ -319,7 +320,7 @@
ngx_rtmp_record_rec_ctx_t *rctx;
ngx_int_t rc;
- 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);
rctx = ngx_rtmp_record_get_node_ctx(s, n);
@@ -384,7 +385,7 @@
p = pbuf;
l = pbuf + sizeof(pbuf) - 1;
- p = ngx_cpymem(p, rracf->path.data,
+ p = ngx_cpymem(p, rracf->path.data,
ngx_min(rracf->path.len, (size_t)(l - p - 1)));
*p++ = '/';
p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name),
@@ -392,7 +393,7 @@
/* append timestamp */
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));
}
@@ -400,7 +401,7 @@
ngx_libc_localtime(rctx->timestamp, &tm);
p += strftime((char *) p, l - p, (char *) rracf->suffix.data, &tm);
} else {
- p = ngx_cpymem(p, rracf->suffix.data,
+ p = ngx_cpymem(p, rracf->suffix.data,
ngx_min(rracf->suffix.len, (size_t)(l - p)));
}
@@ -408,7 +409,7 @@
path->data = pbuf;
path->len = p - pbuf;
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: %V path: '%V'", &rracf->id, path);
}
@@ -431,7 +432,7 @@
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_rec_ctx_t *rctx)
{
ngx_rtmp_record_app_conf_t *rracf;
@@ -449,7 +450,7 @@
return NGX_AGAIN;
}
- 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", &rracf->id);
ngx_memzero(rctx, sizeof(*rctx));
@@ -493,7 +494,7 @@
}
#endif
- 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 '%V'", &rracf->id, &path);
if (rracf->notify) {
@@ -719,7 +720,7 @@
return NGX_ERROR;
}
- 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",
racf->rec.nelts);
@@ -731,8 +732,8 @@
/* terminate name on /../ */
for (p = ctx->name; *p; ++p) {
if (ngx_path_separator(p[0]) &&
- p[1] == '.' && p[2] == '.' &&
- ngx_path_separator(p[3]))
+ p[1] == '.' && p[2] == '.' &&
+ ngx_path_separator(p[3]))
{
*p = 0;
break;
@@ -806,7 +807,7 @@
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", &rracf->id);
if (rracf->notify) {
@@ -832,14 +833,14 @@
static ngx_int_t
-ngx_rtmp_record_close_stream(ngx_rtmp_session_t *s,
+ngx_rtmp_record_close_stream(ngx_rtmp_session_t *s,
ngx_rtmp_close_stream_t *v)
{
if (s->auto_pushed) {
goto next;
}
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: close_stream");
ngx_rtmp_record_stop(s);
@@ -850,7 +851,7 @@
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_rec_ctx_t *rctx,
ngx_rtmp_header_t *h, ngx_chain_t *in,
ngx_int_t inc_nframes)
@@ -890,7 +891,7 @@
tag_size = (ph - hdr) + h->mlen;
if (ngx_write_file(&rctx->file, hdr, ph - hdr, rctx->file.offset)
- == NGX_ERROR)
+ == NGX_ERROR)
{
ngx_rtmp_record_notify_error(s, rctx);
@@ -910,7 +911,7 @@
continue;
}
- if (ngx_write_file(&rctx->file, in->buf->pos, in->buf->last
+ if (ngx_write_file(&rctx->file, in->buf->pos, in->buf->last
- in->buf->pos, rctx->file.offset)
== NGX_ERROR)
{
@@ -927,9 +928,9 @@
*ph++ = p[1];
*ph++ = p[0];
- if (ngx_write_file(&rctx->file, hdr, ph - hdr,
+ if (ngx_write_file(&rctx->file, hdr, ph - hdr,
rctx->file.offset)
- == NGX_ERROR)
+ == NGX_ERROR)
{
return NGX_ERROR;
}
@@ -961,7 +962,7 @@
static ngx_int_t
-ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_record_ctx_t *ctx;
@@ -1075,7 +1076,7 @@
if (!rctx->aac_header_sent && 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", &rracf->id);
ch.type = NGX_RTMP_MSG_AUDIO;
@@ -1083,7 +1084,7 @@
if (ngx_rtmp_record_write_frame(s, rctx, &ch,
codec_ctx->aac_header, 0)
- != NGX_OK)
+ != NGX_OK)
{
return NGX_OK;
}
@@ -1092,11 +1093,11 @@
}
/* AVC header */
- if (!rctx->avc_header_sent && codec_ctx->avc_header &&
+ if (!rctx->avc_header_sent && codec_ctx->avc_header &&
(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", &rracf->id);
ch.type = NGX_RTMP_MSG_VIDEO;
@@ -1104,7 +1105,7 @@
if (ngx_rtmp_record_write_frame(s, rctx, &ch,
codec_ctx->avc_header, 0)
- != NGX_OK)
+ != NGX_OK)
{
return NGX_OK;
}
@@ -1117,7 +1118,7 @@
if (codec_ctx && codec_ctx->video_codec_id == NGX_RTMP_VIDEO_H264 &&
!rctx->avc_header_sent)
{
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: %V skipping until H264 header", &rracf->id);
return NGX_OK;
}
@@ -1128,9 +1129,9 @@
{
rctx->video_key_sent = 1;
}
-
+
if (!rctx->video_key_sent) {
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: %V skipping until keyframe", &rracf->id);
return NGX_OK;
}
@@ -1139,7 +1140,7 @@
if (codec_ctx && codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC &&
!rctx->aac_header_sent)
{
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: %V skipping until AAC header", &rracf->id);
return NGX_OK;
}
@@ -1197,7 +1198,7 @@
module = ngx_modules[i]->ctx;
if (module->create_app_conf) {
- ctx->app_conf[ngx_modules[i]->ctx_index] =
+ ctx->app_conf[ngx_modules[i]->ctx_index] =
module->create_app_conf(cf);
if (ctx->app_conf[ngx_modules[i]->ctx_index] == NULL) {
return NGX_CONF_ERROR;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_record_module.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -68,7 +69,7 @@
* 'n' is record node index in config array.
* 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,
ngx_str_t *path);
ngx_int_t ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n,
ngx_str_t *path);
@@ -80,7 +81,7 @@
} ngx_rtmp_record_done_t;
-typedef ngx_int_t (*ngx_rtmp_record_done_pt)(ngx_rtmp_session_t *s,
+typedef ngx_int_t (*ngx_rtmp_record_done_pt)(ngx_rtmp_session_t *s,
ngx_rtmp_record_done_t *v);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_relay_module.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -18,11 +19,11 @@
static ngx_int_t ngx_rtmp_relay_init_process(ngx_cycle_t *cycle);
static ngx_int_t ngx_rtmp_relay_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_relay_create_app_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_relay_merge_app_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_relay_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
-static char * ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd,
+static char * ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static ngx_int_t ngx_rtmp_relay_publish(ngx_rtmp_session_t *s,
+static ngx_int_t ngx_rtmp_relay_publish(ngx_rtmp_session_t *s,
ngx_rtmp_publish_t *v);
static ngx_rtmp_relay_ctx_t * ngx_rtmp_relay_create_connection(
ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name,
@@ -106,7 +107,7 @@
NGX_RTMP_APP_CONF_OFFSET,
offsetof(ngx_rtmp_relay_app_conf_t, push_reconnect),
NULL },
-
+
{ ngx_string("pull_reconnect"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -201,14 +202,14 @@
ngx_rtmp_relay_app_conf_t *prev = parent;
ngx_rtmp_relay_app_conf_t *conf = child;
- conf->ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_relay_ctx_t *)
+ conf->ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_relay_ctx_t *)
* conf->nbuckets);
ngx_conf_merge_value(conf->session_relay, prev->session_relay, 0);
ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 5000);
- ngx_conf_merge_msec_value(conf->push_reconnect, prev->push_reconnect,
+ ngx_conf_merge_msec_value(conf->push_reconnect, prev->push_reconnect,
3000);
- ngx_conf_merge_msec_value(conf->pull_reconnect, prev->pull_reconnect,
+ ngx_conf_merge_msec_value(conf->pull_reconnect, prev->pull_reconnect,
3000);
return NGX_CONF_OK;
@@ -250,9 +251,9 @@
ngx_uint_t n;
ngx_rtmp_relay_target_t *target, **t;
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"relay: push reconnect");
-
+
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module);
@@ -272,7 +273,7 @@
for (pctx = ctx->play; pctx; pctx = pctx->next) {
if (pctx->tag == &ngx_rtmp_relay_module &&
- pctx->data == target)
+ pctx->data == target)
{
break;
}
@@ -289,7 +290,7 @@
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"relay: push reconnect failed name='%V' app='%V' "
"playpath='%V' url='%V'",
- &ctx->name, &target->app, &target->play_path,
+ &ctx->name, &target->app, &target->play_path,
&target->url.url);
if (!ctx->push_evt.timer_set) {
@@ -299,14 +300,14 @@
}
-static ngx_int_t
+static ngx_int_t
ngx_rtmp_relay_get_peer(ngx_peer_connection_t *pc, void *data)
{
return NGX_OK;
}
-static void
+static void
ngx_rtmp_relay_free_peer(ngx_peer_connection_t *pc, void *data,
ngx_uint_t state)
{
@@ -352,7 +353,7 @@
racf = ngx_rtmp_get_module_app_conf(cctx, ngx_rtmp_relay_module);
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, racf->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, racf->log, 0,
"relay: create remote context");
pool = NULL;
@@ -428,8 +429,8 @@
if (rctx->play_path.len == 0 && p != last) {
v.data = p;
v.len = last - p;
- if (ngx_rtmp_relay_copy_str(pool, &rctx->play_path, &v)
- != NGX_OK)
+ if (ngx_rtmp_relay_copy_str(pool, &rctx->play_path, &v)
+ != NGX_OK)
{
goto clear;
}
@@ -467,7 +468,7 @@
rc = ngx_event_connect_peer(pc);
if (rc != NGX_OK && rc != NGX_AGAIN ) {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, racf->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, racf->log, 0,
"relay: connection failed");
goto clear;
}
@@ -498,7 +499,7 @@
rctx->session = rs;
ngx_rtmp_set_ctx(rs, rctx, ngx_rtmp_relay_module);
ngx_str_set(&rs->flashver, "ngx-local-relay");
-
+
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_active, 1);
#endif
@@ -534,7 +535,7 @@
{
ngx_rtmp_relay_ctx_t *ctx;
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"relay: create local context");
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module);
@@ -555,8 +556,8 @@
return NULL;
}
- if (ngx_rtmp_relay_copy_str(s->connection->pool, &ctx->name, name)
- != NGX_OK)
+ if (ngx_rtmp_relay_copy_str(s->connection->pool, &ctx->name, name)
+ != NGX_OK)
{
return NULL;
}
@@ -590,7 +591,7 @@
cctx = &racf->ctx[hash % racf->nbuckets];
for (; *cctx; cctx = &(*cctx)->next) {
if ((*cctx)->name.len == name->len
- && !ngx_memcmp(name->data, (*cctx)->name.data,
+ && !ngx_memcmp(name->data, (*cctx)->name.data,
name->len))
{
break;
@@ -623,7 +624,7 @@
ngx_rtmp_relay_pull(ngx_rtmp_session_t *s, ngx_str_t *name,
ngx_rtmp_relay_target_t *target)
{
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"relay: create pull name='%V' app='%V' playpath='%V' url='%V'",
name, &target->app, &target->play_path, &target->url.url);
@@ -637,7 +638,7 @@
ngx_rtmp_relay_push(ngx_rtmp_session_t *s, ngx_str_t *name,
ngx_rtmp_relay_target_t *target)
{
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
"relay: create push name='%V' app='%V' playpath='%V' url='%V'",
name, &target->app, &target->play_path, &target->url.url);
@@ -690,7 +691,7 @@
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"relay: push failed name='%V' app='%V' "
"playpath='%V' url='%V'",
- &name, &target->app, &target->play_path,
+ &name, &target->app, &target->play_path,
&target->url.url);
if (!ctx->push_evt.timer_set) {
@@ -742,7 +743,7 @@
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"relay: pull failed name='%V' app='%V' "
"playpath='%V' url='%V'",
- &name, &target->app, &target->play_path,
+ &name, &target->app, &target->play_path,
&target->url.url);
}
@@ -764,7 +765,7 @@
ngx_memzero(&v, sizeof(ngx_rtmp_play_t));
v.silent = 1;
- *(ngx_cpymem(v.name, ctx->name.data,
+ *(ngx_cpymem(v.name, ctx->name.data,
ngx_min(sizeof(v.name) - 1, ctx->name.len))) = 0;
return ngx_rtmp_play(s, &v);
@@ -784,7 +785,7 @@
ngx_memzero(&v, sizeof(ngx_rtmp_publish_t));
v.silent = 1;
- *(ngx_cpymem(v.name, ctx->name.data,
+ *(ngx_cpymem(v.name, ctx->name.data,
ngx_min(sizeof(v.name) - 1, ctx->name.len))) = 0;
return ngx_rtmp_publish(s, &v);
@@ -800,23 +801,23 @@
static ngx_rtmp_amf_elt_t out_cmd[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("app"),
NULL, 0 }, /* <-- fill */
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("tcUrl"),
NULL, 0 }, /* <-- fill */
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("pageUrl"),
NULL, 0 }, /* <-- fill */
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("swfUrl"),
NULL, 0 }, /* <-- fill */
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("flashVer"),
NULL, 0 }, /* <-- fill */
@@ -832,7 +833,7 @@
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
- ngx_null_string,
+ ngx_null_string,
"connect", 0 },
{ NGX_RTMP_AMF_NUMBER,
@@ -873,7 +874,7 @@
out_cmd[1].data = ctx->tc_url.data;
out_cmd[1].len = ctx->tc_url.len;
} else {
- len = sizeof("rtmp://") - 1 + ctx->url.len +
+ len = sizeof("rtmp://") - 1 + ctx->url.len +
sizeof("/") - 1 + ctx->app.len;
p = ngx_palloc(s->connection->pool, len);
if (p == NULL) {
@@ -920,7 +921,7 @@
|| ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
? NGX_ERROR
- : NGX_OK;
+ : NGX_OK;
}
@@ -932,7 +933,7 @@
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
- ngx_null_string,
+ ngx_null_string,
"createStream", 0 },
{ NGX_RTMP_AMF_NUMBER,
@@ -964,7 +965,7 @@
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
- ngx_null_string,
+ ngx_null_string,
"publish", 0 },
{ NGX_RTMP_AMF_NUMBER,
@@ -1020,7 +1021,7 @@
static ngx_rtmp_amf_elt_t out_elts[] = {
{ NGX_RTMP_AMF_STRING,
- ngx_null_string,
+ ngx_null_string,
"play", 0 },
{ NGX_RTMP_AMF_NUMBER,
@@ -1078,7 +1079,7 @@
return ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
- || ngx_rtmp_send_set_buflen(s, NGX_RTMP_RELAY_MSID,
+ || ngx_rtmp_send_set_buflen(s, NGX_RTMP_RELAY_MSID,
racf->buflen) != NGX_OK
? NGX_ERROR
: NGX_OK;
@@ -1099,11 +1100,11 @@
static ngx_rtmp_amf_elt_t in_inf[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("level"),
&v.level, sizeof(v.level) },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("code"),
&v.code, sizeof(v.code) },
@@ -1134,13 +1135,13 @@
}
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
- ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"relay: _result: level='%s' code='%s' description='%s'",
v.level, v.code, v.desc);
@@ -1182,11 +1183,11 @@
static ngx_rtmp_amf_elt_t in_inf[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("level"),
&v.level, sizeof(v.level) },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("code"),
&v.code, sizeof(v.code) },
@@ -1217,13 +1218,13 @@
}
ngx_memzero(&v, sizeof(v));
- if (ngx_rtmp_receive_amf(s, in, in_elts,
- sizeof(in_elts) / sizeof(in_elts[0])))
+ if (ngx_rtmp_receive_amf(s, in, in_elts,
+ sizeof(in_elts) / sizeof(in_elts[0])))
{
return NGX_ERROR;
}
- ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"relay: _error: level='%s' code='%s' description='%s'",
v.level, v.code, v.desc);
@@ -1245,11 +1246,11 @@
static ngx_rtmp_amf_elt_t in_inf[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("level"),
&v.level, sizeof(v.level) },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("code"),
&v.code, sizeof(v.code) },
@@ -1288,14 +1289,14 @@
ngx_memzero(&v, sizeof(v));
if (h->type == NGX_RTMP_MSG_AMF_META) {
- ngx_rtmp_receive_amf(s, in, in_elts_meta,
+ ngx_rtmp_receive_amf(s, in, in_elts_meta,
sizeof(in_elts_meta) / sizeof(in_elts_meta[0]));
} else {
- ngx_rtmp_receive_amf(s, in, in_elts,
+ ngx_rtmp_receive_amf(s, in, in_elts,
sizeof(in_elts) / sizeof(in_elts[0]));
}
- ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"relay: onStatus: level='%s' code='%s' description='%s'",
v.level, v.code, v.desc);
@@ -1350,13 +1351,13 @@
}
}
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0,
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0,
"relay: play disconnect app='%V' name='%V'",
&ctx->app, &ctx->name);
/* push reconnect */
- if (s->relay && ctx->tag == &ngx_rtmp_relay_module &&
- !ctx->publish->push_evt.timer_set)
+ if (s->relay && ctx->tag == &ngx_rtmp_relay_module &&
+ !ctx->publish->push_evt.timer_set)
{
ngx_add_timer(&ctx->publish->push_evt, racf->push_reconnect);
}
@@ -1372,8 +1373,8 @@
#endif
if (ctx->publish->play == NULL && ctx->publish->session->relay) {
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP,
- ctx->publish->session->connection->log, 0,
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP,
+ ctx->publish->session->connection->log, 0,
"relay: publish disconnect empty app='%V' name='%V'",
&ctx->app, &ctx->name);
ngx_rtmp_finalize_session(ctx->publish->session);
@@ -1385,7 +1386,7 @@
}
/* publish end disconnect */
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0,
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0,
"relay: publish disconnect app='%V' name='%V'",
&ctx->app, &ctx->name);
@@ -1395,7 +1396,7 @@
for (cctx = &ctx->play; *cctx; cctx = &(*cctx)->next) {
(*cctx)->publish = NULL;
- ngx_log_debug2(NGX_LOG_DEBUG_RTMP, (*cctx)->session->connection->log,
+ ngx_log_debug2(NGX_LOG_DEBUG_RTMP, (*cctx)->session->connection->log,
0, "relay: play disconnect orphan app='%V' name='%V'",
&(*cctx)->app, &(*cctx)->name);
ngx_rtmp_finalize_session((*cctx)->session);
@@ -1471,7 +1472,7 @@
u->url.data += 7;
u->url.len -= 7;
}
-
+
if (ngx_parse_url(cf->pool, u) != NGX_OK) {
if (u->err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1621,7 +1622,7 @@
pcscf = cmcf->servers.elts;
for (n = 0; n < cmcf->servers.nelts; ++n, ++pcscf) {
-
+
cscf = *pcscf;
pcacf = cscf->applications.elts;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_relay_module.h
^
|
@@ -1,11 +1,12 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
#ifndef _NGX_RTMP_RELAY_H_INCLUDED_
#define _NGX_RTMP_RELAY_H_INCLUDED_
-
+
#include <ngx_config.h>
#include <ngx_core.h>
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_send.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -25,7 +26,7 @@
if (__l == NULL) { \
return NULL; \
} \
- __b = __l->buf;
+ __b = __l->buf;
#define NGX_RTMP_UCTL_START(s, type, utype) \
NGX_RTMP_USER_START(s, type); \
@@ -169,7 +170,7 @@
uint8_t limit_type)
{
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "create: bandwidth ack_size=%uD limit=%d",
+ "create: bandwidth ack_size=%uD limit=%d",
ack_size, (int)limit_type);
{
@@ -223,7 +224,7 @@
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"create: stream_end msid=%uD", msid);
-
+
{
NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_STREAM_EOF);
@@ -267,7 +268,7 @@
ngx_chain_t *
-ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s, uint32_t msid,
+ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s, uint32_t msid,
uint32_t buflen_msec)
{
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@@ -286,7 +287,7 @@
ngx_int_t
-ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s, uint32_t msid,
+ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s, uint32_t msid,
uint32_t buflen_msec)
{
return ngx_rtmp_send_shared_packet(s,
@@ -295,7 +296,7 @@
ngx_chain_t *
-ngx_rtmp_create_recorded(ngx_rtmp_session_t *s, uint32_t msid)
+ngx_rtmp_create_recorded(ngx_rtmp_session_t *s, uint32_t msid)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"create: recorded msid=%uD", msid);
@@ -311,7 +312,7 @@
ngx_int_t
-ngx_rtmp_send_recorded(ngx_rtmp_session_t *s, uint32_t msid)
+ngx_rtmp_send_recorded(ngx_rtmp_session_t *s, uint32_t msid)
{
return ngx_rtmp_send_shared_packet(s,
ngx_rtmp_create_recorded(s, msid));
@@ -319,7 +320,7 @@
ngx_chain_t *
-ngx_rtmp_create_ping_request(ngx_rtmp_session_t *s, uint32_t timestamp)
+ngx_rtmp_create_ping_request(ngx_rtmp_session_t *s, uint32_t timestamp)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"create: ping_request timestamp=%uD", timestamp);
@@ -335,7 +336,7 @@
ngx_int_t
-ngx_rtmp_send_ping_request(ngx_rtmp_session_t *s, uint32_t timestamp)
+ngx_rtmp_send_ping_request(ngx_rtmp_session_t *s, uint32_t timestamp)
{
return ngx_rtmp_send_shared_packet(s,
ngx_rtmp_create_ping_request(s, timestamp));
@@ -343,7 +344,7 @@
ngx_chain_t *
-ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp)
+ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp)
{
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"create: ping_response timestamp=%uD", timestamp);
@@ -359,14 +360,14 @@
ngx_int_t
-ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp)
+ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp)
{
return ngx_rtmp_send_shared_packet(s,
ngx_rtmp_create_ping_response(s, timestamp));
}
-static ngx_chain_t *
+static ngx_chain_t *
ngx_rtmp_alloc_amf_buf(void *arg)
{
return ngx_rtmp_alloc_shared_buf((ngx_rtmp_core_srv_conf_t *)arg);
@@ -378,7 +379,7 @@
/* NOTE: this function does not free shared bufs on error */
ngx_int_t
ngx_rtmp_append_amf(ngx_rtmp_session_t *s,
- ngx_chain_t **first, ngx_chain_t **last,
+ ngx_chain_t **first, ngx_chain_t **last,
ngx_rtmp_amf_elt_t *elts, size_t nelts)
{
ngx_rtmp_amf_ctx_t act;
@@ -462,26 +463,26 @@
static ngx_rtmp_amf_elt_t out_inf[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("level"),
NULL, 0 },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("code"),
NULL, 0 },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("description"),
NULL, 0 },
};
static ngx_rtmp_amf_elt_t out_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
"onStatus", 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_null_string,
&trans, 0 },
@@ -509,7 +510,7 @@
h.csid = NGX_RTMP_CSID_AMF;
h.msid = NGX_RTMP_MSID;
- return ngx_rtmp_create_amf(s, &h, out_elts,
+ return ngx_rtmp_create_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
}
@@ -532,26 +533,26 @@
static ngx_rtmp_amf_elt_t out_inf[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("code"),
NULL, 0 },
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_string("level"),
NULL, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("duration"),
&dduration, 0 },
- { NGX_RTMP_AMF_NUMBER,
+ { NGX_RTMP_AMF_NUMBER,
ngx_string("bytes"),
&dbytes, 0 },
};
static ngx_rtmp_amf_elt_t out_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
"onPlayStatus", 0 },
@@ -579,7 +580,7 @@
h.msid = NGX_RTMP_MSID;
h.timestamp = duration;
- return ngx_rtmp_create_amf(s, &h, out_elts,
+ return ngx_rtmp_create_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
}
@@ -602,7 +603,7 @@
static ngx_rtmp_amf_elt_t access_elts[] = {
- { NGX_RTMP_AMF_STRING,
+ { NGX_RTMP_AMF_STRING,
ngx_null_string,
"|RtmpSampleAccess", 0 },
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_shared.c
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
@@ -8,7 +9,7 @@
#include "ngx_rtmp.h"
-ngx_chain_t *
+ngx_chain_t *
ngx_rtmp_alloc_shared_buf(ngx_rtmp_core_srv_conf_t *cscf)
{
u_char *p;
@@ -24,7 +25,7 @@
size = cscf->chunk_size + NGX_RTMP_MAX_CHUNK_HEADER;
- p = ngx_pcalloc(cscf->pool, NGX_RTMP_REFCOUNT_BYTES
+ p = ngx_pcalloc(cscf->pool, NGX_RTMP_REFCOUNT_BYTES
+ sizeof(ngx_chain_t)
+ sizeof(ngx_buf_t)
+ size);
@@ -55,7 +56,7 @@
}
-void
+void
ngx_rtmp_free_shared_chain(ngx_rtmp_core_srv_conf_t *cscf, ngx_chain_t *in)
{
ngx_chain_t *cl;
@@ -75,7 +76,7 @@
ngx_chain_t *
-ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
+ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
ngx_chain_t *head, ngx_chain_t *in)
{
ngx_chain_t *l, **ll;
@@ -104,7 +105,7 @@
}
while (l->buf->end - l->buf->last >= in->buf->last - p) {
- l->buf->last = ngx_cpymem(l->buf->last, p,
+ l->buf->last = ngx_cpymem(l->buf->last, p,
in->buf->last - p);
in = in->next;
if (in == NULL) {
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_stat_module.c
^
|
@@ -1,12 +1,15 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
+#include <nginx.h>
#include "ngx_rtmp.h"
+#include "ngx_rtmp_version.h"
#include "ngx_rtmp_live_module.h"
#include "ngx_rtmp_play_module.h"
#include "ngx_rtmp_codec_module.h"
@@ -16,7 +19,7 @@
static char *ngx_rtmp_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_rtmp_stat_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_stat_create_loc_conf(ngx_conf_t *cf);
-static char * ngx_rtmp_stat_merge_loc_conf(ngx_conf_t *cf,
+static char * ngx_rtmp_stat_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -46,7 +49,7 @@
{ ngx_string("live"), NGX_RTMP_STAT_LIVE },
{ ngx_string("clients"), NGX_RTMP_STAT_CLIENTS },
{ ngx_null_string, 0 }
-};
+};
static ngx_command_t ngx_rtmp_stat_commands[] = {
@@ -70,33 +73,33 @@
static ngx_http_module_t ngx_rtmp_stat_module_ctx = {
- NULL, /* preconfiguration */
- ngx_rtmp_stat_postconfiguration, /* postconfiguration */
+ NULL, /* preconfiguration */
+ ngx_rtmp_stat_postconfiguration, /* postconfiguration */
- NULL, /* create main configuration */
- NULL, /* init main configuration */
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
- ngx_rtmp_stat_create_loc_conf, /* create location configuration */
- ngx_rtmp_stat_merge_loc_conf, /* merge location configuration */
+ ngx_rtmp_stat_create_loc_conf, /* create location configuration */
+ ngx_rtmp_stat_merge_loc_conf, /* merge location configuration */
};
ngx_module_t ngx_rtmp_stat_module = {
- NGX_MODULE_V1,
- &ngx_rtmp_stat_module_ctx, /* module context */
- ngx_rtmp_stat_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- ngx_rtmp_stat_init_process, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
+ NGX_MODULE_V1,
+ &ngx_rtmp_stat_module_ctx, /* module context */
+ ngx_rtmp_stat_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ ngx_rtmp_stat_init_process, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
};
@@ -106,7 +109,7 @@
static ngx_int_t
ngx_rtmp_stat_init_process(ngx_cycle_t *cycle)
{
- /*
+ /*
* HTTP process initializer is called
* after event module initializer
* so we can run posted events here
@@ -156,7 +159,7 @@
}
#if (NGX_WIN32)
-/*
+/*
* Fix broken MSVC memcpy optimization for 4-byte data
* when this function is inlined
*/
@@ -196,7 +199,7 @@
if (cl == NULL) {
return;
}
- b = ngx_create_temp_buf(r->pool,
+ b = ngx_create_temp_buf(r->pool,
ngx_max(NGX_RTMP_STAT_BUFSIZE, real_len));
if (b == NULL || b->pos == NULL) {
return;
@@ -242,34 +245,39 @@
#define NGX_RTMP_STAT_ECS(s) NGX_RTMP_STAT_E((s), ngx_strlen(s))
+#define NGX_RTMP_STAT_BW 0x01
+#define NGX_RTMP_STAT_BYTES 0x02
+#define NGX_RTMP_STAT_BW_BYTES 0x03
+
+
static void
ngx_rtmp_stat_bw(ngx_http_request_t *r, ngx_chain_t ***lll,
- ngx_rtmp_bandwidth_t *bw_in, ngx_rtmp_bandwidth_t *bw_out)
+ ngx_rtmp_bandwidth_t *bw, char *name,
+ ngx_uint_t flags)
{
- u_char buf[NGX_INT64_LEN + 1];
+ u_char buf[NGX_INT64_LEN + 9];
- ngx_rtmp_update_bandwidth(bw_in, 0);
- ngx_rtmp_update_bandwidth(bw_out, 0);
+ ngx_rtmp_update_bandwidth(bw, 0);
- NGX_RTMP_STAT_L("<in>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%uL", bw_in->bytes) - buf);
- NGX_RTMP_STAT_L("</in>\r\n");
-
- NGX_RTMP_STAT_L("<out>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%uL", bw_out->bytes) - buf);
- NGX_RTMP_STAT_L("</out>\r\n");
-
- NGX_RTMP_STAT_L("<bwin>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%uL", bw_in->bandwidth * 8) - buf);
- NGX_RTMP_STAT_L("</bwin>\r\n");
-
- NGX_RTMP_STAT_L("<bwout>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
- "%uL", bw_out->bandwidth * 8) - buf);
- NGX_RTMP_STAT_L("</bwout>\r\n");
+ if (flags & NGX_RTMP_STAT_BW) {
+ NGX_RTMP_STAT_L("<bw_");
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), ">%uL</bw_",
+ bw->bandwidth * 8)
+ - buf);
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT_L(">\r\n");
+ }
+
+ if (flags & NGX_RTMP_STAT_BYTES) {
+ NGX_RTMP_STAT_L("<bytes_");
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), ">%uL</bytes_",
+ bw->bytes)
+ - buf);
+ NGX_RTMP_STAT_CS(name);
+ NGX_RTMP_STAT_L(">\r\n");
+ }
}
@@ -297,7 +305,7 @@
static void
-ngx_rtmp_stat_dump_pool(ngx_http_request_t *r, ngx_chain_t ***lll,
+ngx_rtmp_stat_dump_pool(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_pool_t *pool)
{
ngx_uint_t nlarge, size;
@@ -359,8 +367,48 @@
}
+static char *
+ngx_rtmp_stat_get_aac_profile(ngx_uint_t p, ngx_uint_t sbr, ngx_uint_t ps) {
+ switch (p) {
+ case 1:
+ return "Main";
+ case 2:
+ if (ps) {
+ return "HEv2";
+ }
+ if (sbr) {
+ return "HE";
+ }
+ return "LC";
+ case 3:
+ return "SSR";
+ case 4:
+ return "LTP";
+ case 5:
+ return "SBR";
+ default:
+ return "";
+ }
+}
+
+
+static char *
+ngx_rtmp_stat_get_avc_profile(ngx_uint_t p) {
+ switch (p) {
+ case 66:
+ return "Baseline";
+ case 77:
+ return "Main";
+ case 100:
+ return "High";
+ default:
+ return "";
+ }
+}
+
+
static void
-ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll,
+ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_live_app_conf_t *lacf)
{
ngx_rtmp_live_stream_t *stream;
@@ -397,7 +445,14 @@
- buf);
NGX_RTMP_STAT_L("</time>");
- ngx_rtmp_stat_bw(r, lll, &stream->bw_in, &stream->bw_out);
+ ngx_rtmp_stat_bw(r, lll, &stream->bw_in, "in",
+ NGX_RTMP_STAT_BW_BYTES);
+ ngx_rtmp_stat_bw(r, lll, &stream->bw_out, "out",
+ NGX_RTMP_STAT_BW_BYTES);
+ ngx_rtmp_stat_bw(r, lll, &stream->bw_in_audio, "audio",
+ NGX_RTMP_STAT_BW);
+ ngx_rtmp_stat_bw(r, lll, &stream->bw_in_video, "video",
+ NGX_RTMP_STAT_BW);
nclients = 0;
codec = NULL;
@@ -409,18 +464,23 @@
ngx_rtmp_stat_client(r, lll, s);
NGX_RTMP_STAT_L("<dropped>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", ctx->ndropped) - buf);
NGX_RTMP_STAT_L("</dropped>");
NGX_RTMP_STAT_L("<avsync>");
if (!lacf->interleave) {
- NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
"%D", ctx->cs[1].timestamp -
ctx->cs[0].timestamp) - bbuf);
}
NGX_RTMP_STAT_L("</avsync>");
+ NGX_RTMP_STAT_L("<timestamp>");
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", s->current_time) - bbuf);
+ NGX_RTMP_STAT_L("</timestamp>");
+
if (ctx->publishing) {
NGX_RTMP_STAT_L("<publishing/>");
}
@@ -438,43 +498,85 @@
total_nclients += nclients;
if (codec) {
- NGX_RTMP_STAT_L("<meta><width>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT_L("<meta>");
+
+ NGX_RTMP_STAT_L("<video>");
+ NGX_RTMP_STAT_L("<width>");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", codec->width) - buf);
NGX_RTMP_STAT_L("</width><height>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", codec->height) - buf);
- NGX_RTMP_STAT_L("</height><framerate>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT_L("</height><frame_rate>");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", codec->frame_rate) - buf);
- NGX_RTMP_STAT_L("</framerate>");
+ NGX_RTMP_STAT_L("</frame_rate>");
+
cname = ngx_rtmp_get_video_codec_name(codec->video_codec_id);
if (*cname) {
- NGX_RTMP_STAT_L("<video>");
+ NGX_RTMP_STAT_L("<codec>");
NGX_RTMP_STAT_ECS(cname);
- NGX_RTMP_STAT_L("</video>");
+ NGX_RTMP_STAT_L("</codec>");
+ }
+ if (codec->avc_profile) {
+ NGX_RTMP_STAT_L("<profile>");
+ NGX_RTMP_STAT_CS(
+ ngx_rtmp_stat_get_avc_profile(codec->avc_profile));
+ NGX_RTMP_STAT_L("</profile>");
+ }
+ if (codec->avc_level) {
+ NGX_RTMP_STAT_L("<compat>");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->avc_compat) - buf);
+ NGX_RTMP_STAT_L("</compat>");
}
+ 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("</level>");
+ }
+ NGX_RTMP_STAT_L("</video>");
+
+ NGX_RTMP_STAT_L("<audio>");
cname = ngx_rtmp_get_audio_codec_name(codec->audio_codec_id);
if (*cname) {
- NGX_RTMP_STAT_L("<audio>");
+ NGX_RTMP_STAT_L("<codec>");
NGX_RTMP_STAT_ECS(cname);
- NGX_RTMP_STAT_L("</audio>");
+ NGX_RTMP_STAT_L("</codec>");
}
- if (*codec->profile) {
+ if (codec->aac_profile) {
NGX_RTMP_STAT_L("<profile>");
- NGX_RTMP_STAT_ECS(codec->profile);
+ NGX_RTMP_STAT_CS(
+ ngx_rtmp_stat_get_aac_profile(codec->aac_profile,
+ codec->aac_sbr,
+ codec->aac_ps));
NGX_RTMP_STAT_L("</profile>");
}
- if (*codec->level) {
- NGX_RTMP_STAT_L("<level>");
- NGX_RTMP_STAT_ECS(codec->level);
- NGX_RTMP_STAT_L("</level>");
+ if (codec->aac_chan_conf) {
+ NGX_RTMP_STAT_L("<channels>");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->aac_chan_conf) - buf);
+ NGX_RTMP_STAT_L("</channels>");
+ } else if (codec->audio_channels) {
+ NGX_RTMP_STAT_L("<channels>");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->audio_channels) - buf);
+ NGX_RTMP_STAT_L("</channels>");
+ }
+ if (codec->sample_rate) {
+ NGX_RTMP_STAT_L("<sample_rate>");
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ "%ui", codec->sample_rate) - buf);
+ NGX_RTMP_STAT_L("</sample_rate>");
}
+ NGX_RTMP_STAT_L("</audio>");
+
NGX_RTMP_STAT_L("</meta>\r\n");
}
NGX_RTMP_STAT_L("<nclients>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", nclients) - buf);
NGX_RTMP_STAT_L("</nclients>\r\n");
@@ -491,7 +593,7 @@
}
NGX_RTMP_STAT_L("<nclients>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", total_nclients) - buf);
NGX_RTMP_STAT_L("</nclients>\r\n");
@@ -500,13 +602,14 @@
static void
-ngx_rtmp_stat_play(ngx_http_request_t *r, ngx_chain_t ***lll,
+ngx_rtmp_stat_play(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_play_app_conf_t *pacf)
{
ngx_rtmp_play_ctx_t *ctx, *sctx;
ngx_rtmp_session_t *s;
ngx_uint_t n, nclients, total_nclients;
u_char buf[NGX_INT_T_LEN];
+ u_char bbuf[NGX_INT32_LEN];
ngx_rtmp_stat_loc_conf_t *slcf;
if (pacf->entries.nelts == 0) {
@@ -541,6 +644,11 @@
ngx_rtmp_stat_client(r, lll, s);
+ NGX_RTMP_STAT_L("<timestamp>");
+ NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf),
+ "%D", s->current_time) - bbuf);
+ NGX_RTMP_STAT_L("</timestamp>");
+
NGX_RTMP_STAT_L("</client>\r\n");
}
}
@@ -557,7 +665,7 @@
}
NGX_RTMP_STAT_L("<nclients>");
- NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
+ NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf),
"%ui", total_nclients) - buf);
NGX_RTMP_STAT_L("</nclients>\r\n");
@@ -566,7 +674,7 @@
static void
-ngx_rtmp_stat_application(ngx_http_request_t *r, ngx_chain_t ***lll,
+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;
@@ -579,12 +687,12 @@
slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module);
if (slcf->stat & NGX_RTMP_STAT_LIVE) {
- ngx_rtmp_stat_live(r, lll,
+ ngx_rtmp_stat_live(r, lll,
cacf->app_conf[ngx_rtmp_live_module.ctx_index]);
}
if (slcf->stat & NGX_RTMP_STAT_PLAY) {
- ngx_rtmp_stat_play(r, lll,
+ ngx_rtmp_stat_play(r, lll,
cacf->app_conf[ngx_rtmp_play_module.ctx_index]);
}
@@ -593,7 +701,7 @@
static void
-ngx_rtmp_stat_server(ngx_http_request_t *r, ngx_chain_t ***lll,
+ngx_rtmp_stat_server(ngx_http_request_t *r, ngx_chain_t ***lll,
ngx_rtmp_core_srv_conf_t *cscf)
{
ngx_rtmp_core_app_conf_t **cacf;
@@ -650,7 +758,11 @@
NGX_RTMP_STAT_L("<rtmp>\r\n");
#ifdef NGINX_VERSION
- NGX_RTMP_STAT_L("<version>" NGINX_VERSION "</version>\r\n");
+ NGX_RTMP_STAT_L("<nginx_version>" NGINX_VERSION "</nginx_version>\r\n");
+#endif
+
+#ifdef NGINX_RTMP_VERSION
+ NGX_RTMP_STAT_L("<nginx_rtmp_version>" NGINX_RTMP_VERSION "</nginx_rtmp_version>\r\n");
#endif
#ifdef NGX_COMPILER
@@ -673,7 +785,8 @@
"%ui", ngx_rtmp_naccepted) - nbuf);
NGX_RTMP_STAT_L("</naccepted>\r\n");
- ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_in, &ngx_rtmp_bw_out);
+ 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);
cscf = cmcf->servers.elts;
for (n = 0; n < cmcf->servers.nelts; ++n, ++cscf) {
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_streams.h
^
|
@@ -1,5 +1,6 @@
+
/*
- * Copyright (c) 2012 Roman Arutyunyan
+ * Copyright (C) Roman Arutyunyan
*/
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/ngx_rtmp_version.h
^
|
@@ -0,0 +1,15 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ */
+
+
+#ifndef _NGX_RTMP_VERSION_H_INCLUDED_
+#define _NGX_RTMP_VERSION_H_INCLUDED_
+
+
+#define nginx_rtmp_version 1001001
+#define NGINX_RTMP_VERSION "1.1.1"
+
+
+#endif /* _NGX_RTMP_VERSION_H_INCLUDED_ */
|
[-]
[+]
|
Changed |
nginx-rtmp-module-1.1.2.tar.bz2/stat.xsl
^
|
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
+
+<!--
+ Copyright (C) Roman Arutyunyan
+-->
+
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -11,8 +17,9 @@
<body>
<xsl:apply-templates select="rtmp"/>
<hr/>
- Generated by <a href='https://github.com/arut/nginx-rtmp-module'>NGINX RTMP module</a>,
- <a href="http://nginx.com">NGINX</a> <xsl:value-of select="/rtmp/version"/>,
+ Generated by <a href='https://github.com/arut/nginx-rtmp-module'>
+ nginx-rtmp-module</a> <xsl:value-of select="/rtmp/nginx_rtmp_version"/>,
+ <a href="http://nginx.org">nginx</a> <xsl:value-of select="/rtmp/nginx_version"/>,
pid <xsl:value-of select="/rtmp/pid"/>,
built <xsl:value-of select="/rtmp/built"/> <xsl:value-of select="/rtmp/compiler"/>
</body>
@@ -24,52 +31,58 @@
<tr bgcolor="#999999">
<th>RTMP</th>
<th>#clients</th>
+ <th colspan="4">Video</th>
+ <th colspan="4">Audio</th>
<th>In bytes</th>
<th>Out bytes</th>
- <th>Input bits/s</th>
- <th>Output bits/s</th>
- <th>Size</th>
- <th>Frame Rate</th>
- <th>Video</th>
- <th>Audio</th>
+ <th>In bits/s</th>
+ <th>Out bits/s</th>
<th>State</th>
<th>Time</th>
</tr>
<tr>
<td colspan="2">Accepted: <xsl:value-of select="naccepted"/></td>
+ <th bgcolor="#999999">codec</th>
+ <th bgcolor="#999999">bits/s</th>
+ <th bgcolor="#999999">size</th>
+ <th bgcolor="#999999">fps</th>
+ <th bgcolor="#999999">codec</th>
+ <th bgcolor="#999999">bits/s</th>
+ <th bgcolor="#999999">freq</th>
+ <th bgcolor="#999999">chan</th>
<td>
<xsl:call-template name="showsize">
- <xsl:with-param name="size" select="in"/>
+ <xsl:with-param name="size" select="bytes_in"/>
</xsl:call-template>
</td>
<td>
- <xsl:call-template name="showsize">
- <xsl:with-param name="size" select="out"/>
- </xsl:call-template>
- </td>
+ <xsl:call-template name="showsize">
+ <xsl:with-param name="size" select="bytes_out"/>
+ </xsl:call-template>
+ </td>
<td>
- <xsl:call-template name="showsize">
- <xsl:with-param name="size" select="bwin"/>
- <xsl:with-param name="bits" select="1"/>
- <xsl:with-param name="persec" select="1"/>
- </xsl:call-template>
- </td>
- <td>
- <xsl:call-template name="showsize">
- <xsl:with-param name="size" select="bwout"/>
- <xsl:with-param name="bits" select="1"/>
- <xsl:with-param name="persec" select="1"/>
- </xsl:call-template>
- </td>
- <td colspan="5"/>
- <td>
- <xsl:call-template name="showtime">
- <xsl:with-param name="time" select="/rtmp/uptime * 1000"/>
- </xsl:call-template>
- </td>
- </tr>
- <xsl:apply-templates select="server"/>
-</table>
+ <xsl:call-template name="showsize">
+ <xsl:with-param name="size" select="bw_in"/>
+ <xsl:with-param name="bits" select="1"/>
+ <xsl:with-param name="persec" select="1"/>
+ </xsl:call-template>
+ </td>
+ <td>
+ <xsl:call-template name="showsize">
+ <xsl:with-param name="size" select="bw_out"/>
+ <xsl:with-param name="bits" select="1"/>
+ <xsl:with-param name="persec" select="1"/>
+ </xsl:call-template>
+ </td>
+ <td/>
+ <td>
+ <xsl:call-template name="showtime">
+ <xsl:with-param name="time" select="/rtmp/uptime * 1000"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+ <xsl:apply-templates select="server"/>
+ </table>
</xsl:template>
<xsl:template match="server">
@@ -133,41 +146,61 @@
</td>
<td align="middle"> <xsl:value-of select="nclients"/> </td>
<td>
- <xsl:call-template name="showsize">
- <xsl:with-param name="size" select="in"/>
- </xsl:call-template>
+ <xsl:value-of select="meta/video/codec"/> <xsl:value-of select="meta/video/profile"/> <xsl:value-of select="meta/video/level"/>
</td>
<td>
<xsl:call-template name="showsize">
- <xsl:with-param name="size" select="out"/>
+ <xsl:with-param name="size" select="bw_video"/>
+ <xsl:with-param name="bits" select="1"/>
+ <xsl:with-param name="persec" select="1"/>
</xsl:call-template>
</td>
<td>
+ <xsl:apply-templates select="meta/video/width"/>
+ </td>
+ <td>
+ <xsl:value-of select="meta/video/frame_rate"/>
+ </td>
+ <td>
+ <xsl:value-of select="meta/audio/codec"/> <xsl:value-of select="meta/audio/profile"/>
+ </td>
+ <td>
<xsl:call-template name="showsize">
- <xsl:with-param name="size" select="bwin"/>
+ <xsl:with-param name="size" select="bw_audio"/>
<xsl:with-param name="bits" select="1"/>
<xsl:with-param name="persec" select="1"/>
</xsl:call-template>
</td>
<td>
+ <xsl:apply-templates select="meta/audio/sample_rate"/>
+ </td>
+ <td>
+ <xsl:value-of select="meta/audio/channels"/>
+ </td>
+ <td>
<xsl:call-template name="showsize">
- <xsl:with-param name="size" select="bwout"/>
- <xsl:with-param name="bits" select="1"/>
- <xsl:with-param name="persec" select="1"/>
+ <xsl:with-param name="size" select="bytes_in"/>
+ </xsl:call-template>
+ </td>
+ <td>
+ <xsl:call-template name="showsize">
+ <xsl:with-param name="size" select="bytes_out"/>
</xsl:call-template>
</td>
<td>
- <xsl:if test="meta/width > 0">
- <xsl:value-of select="meta/width"/>x<xsl:value-of select="meta/height"/>
- </xsl:if>
+ <xsl:call-template name="showsize">
+ <xsl:with-param name="size" select="bw_in"/>
+ <xsl:with-param name="bits" select="1"/>
+ <xsl:with-param name="persec" select="1"/>
+ </xsl:call-template>
</td>
- <td align="middle"><xsl:value-of select="meta/framerate"/></td>
<td>
- <xsl:value-of select="meta/video"/>
- <xsl:apply-templates select="meta/profile"/>
- <xsl:apply-templates select="meta/level"/>
+ <xsl:call-template name="showsize">
+ <xsl:with-param name="size" select="bw_out"/>
+ <xsl:with-param name="bits" select="1"/>
+ <xsl:with-param name="persec" select="1"/>
+ </xsl:call-template>
</td>
- <td><xsl:value-of select="meta/audio"/></td>
<td><xsl:call-template name="streamstate"/></td>
<td>
<xsl:call-template name="showtime">
@@ -179,7 +212,7 @@
<xsl:attribute name="id">
<xsl:value-of select="../../name"/>-<xsl:value-of select="name"/>
</xsl:attribute>
- <td colspan="12" ngcolor="#eeeeee">
+ <td colspan="16" ngcolor="#eeeeee">
<table cellspacing="1" cellpadding="5">
<tr>
<th>Id</th>
@@ -189,6 +222,7 @@
<th>Page URL</th>
<th>SWF URL</th>
<th>Dropped</th>
+ <th>Timestamp</th>
<th>A-V</th>
<th>Time</th>
</tr>
@@ -276,7 +310,15 @@
</xsl:attribute>
<td><xsl:value-of select="id"/></td>
<td><xsl:call-template name="clientstate"/></td>
- <td><xsl:value-of select="address"/></td>
+ <td>
+ <a target="_blank">
+ <xsl:attribute name="href">
+ http://apps.db.ripe.net/search/query.html?searchtext=<xsl:value-of select="address"/>
+ </xsl:attribute>
+ <xsl:attribute name="title">whois</xsl:attribute>
+ <xsl:value-of select="address"/>
+ </a>
+ </td>
<td><xsl:value-of select="flashver"/></td>
<td>
<a target="_blank">
@@ -288,6 +330,7 @@
</td>
<td><xsl:value-of select="swfurl"/></td>
<td><xsl:value-of select="dropped"/></td>
+ <td><xsl:value-of select="timestamp"/></td>
<td><xsl:value-of select="avsync"/></td>
<td>
<xsl:call-template name="showtime">
@@ -305,12 +348,8 @@
active
</xsl:template>
-<xsl:template match="profile">
- / <xsl:value-of select="."/>
-</xsl:template>
-
-<xsl:template match="level">
- / <xsl:value-of select="."/>
+<xsl:template match="width">
+ <xsl:value-of select="."/>x<xsl:value-of select="../height"/>
</xsl:template>
</xsl:stylesheet>
|
[-]
[+]
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/test/rtmp-publisher/RtmpPlayerLight.mxml
^
|
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:s="library://ns.adobe.com/flex/spark"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ minWidth="500" minHeight="350" creationComplete="init()">
+
+ <fx:Script>
+ <![CDATA[
+ import mx.controls.Alert;
+ import mx.core.FlexGlobals;
+ import flash.display.StageDisplayState;
+ import mx.managers.SystemManager;
+ import org.osmf.events.MediaPlayerStateChangeEvent;
+ import org.osmf.events.TimeEvent;
+ import org.osmf.media.MediaPlayerState;
+
+ private var streamer:String;
+ private var file:String;
+ private var videoEventsDisabled:Boolean;
+ private var previousVideoTime:Number;
+
+ private function fullscreenListener(event:MouseEvent):void {
+ try {
+ switch (stage.displayState) {
+ case StageDisplayState.FULL_SCREEN:
+ stage.displayState = StageDisplayState.NORMAL;
+ break;
+ default:
+ stage.displayState = StageDisplayState.FULL_SCREEN;
+ break;
+ }
+ } catch (err:SecurityError) {
+ Alert.show('Fullsceen error: ' + err);
+ }
+ }
+
+ private function resetVideo():void {
+ videoEventsDisabled = true;
+
+ try {
+ videoDisplay.source = "";
+ } catch (any:*) {}
+
+ setTimeout(resetVideoSource, 5000);
+ }
+
+ private function resetVideoSource():void {
+ videoEventsDisabled = false;
+ previousVideoTime = NaN;
+ videoDisplay.source = streamer + "/" + file;
+ }
+
+ protected function stateChangeListener(event:MediaPlayerStateChangeEvent):void {
+ if (videoEventsDisabled) {
+ return;
+ }
+
+ if (event.state == MediaPlayerState.PLAYBACK_ERROR) {
+ resetVideo();
+ }
+ }
+
+ protected function timeChangeListener(event:TimeEvent):void {
+ if (videoEventsDisabled) {
+ return;
+ }
+
+ if (isNaN(event.time) && !isNaN(previousVideoTime)) {
+ resetVideo();
+ } else {
+ previousVideoTime = event.time;
+ }
+ }
+
+ private function init():void {
+ videoDisplay.mx_internal::videoPlayer.bufferTime = 1;
+
+ streamer = FlexGlobals.topLevelApplication.parameters.streamer;
+ if(streamer == null) {
+ Alert.show('Missing flashvars: streamer');
+ return;
+ }
+
+ file = FlexGlobals.topLevelApplication.parameters.file;
+ if(file == null) {
+ Alert.show('Missing flashvars: file');
+ return;
+ }
+
+ videoDisplay.addEventListener(MouseEvent.DOUBLE_CLICK, fullscreenListener);
+ videoDisplay.addEventListener("MediaPlayerStateChange", stateChangeListener);
+ videoDisplay.addEventListener("currentTimeChange", timeChangeListener);
+
+ resetVideoSource();
+ }
+ ]]>
+ </fx:Script>
+ <s:BorderContainer x="0" y="0" width="100%" height="100%">
+ <s:VideoDisplay doubleClickEnabled="true" width="100%" height="100%" id="videoDisplay"></s:VideoDisplay>
+ </s:BorderContainer>
+</s:Application>
|
|
Added |
nginx-rtmp-module-1.1.2.tar.bz2/test/rtmp-publisher/RtmpPlayerLight.swf
^
|