diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e169dff --- /dev/null +++ b/AUTHORS @@ -0,0 +1,8 @@ +Project author: + + Roman Arutyunyan + Moscow, Russia + + Contacts: + arut@qip.ru + arutyunyan.roman@gmail.com diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6c14fd7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012, Roman Arutyunyan +All rights reserved. + +Redistribution and use in source and binary forms, with or without +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. +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. + +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 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README b/README index afeca25..0073838 100644 --- a/README +++ b/README @@ -1 +1,36 @@ -This is an early version of module +==nginx-rtmp-module== + +NGINX-based RTMP server + +* Live streaming of video/audio + +* Advanced buffering techniques + to keep memory allocations at a minimum + level for faster streaming and low + memory footprint + +* Works with Flash RTMP clients as well as + ffmpeg/rtmpdump/flvstreamer etc + (see examples in test/ subdir) + + +Example nginx.conf: + + +rtmp { + + server { + + listen 1935; + + wait_key_frame on; + + chunk_size 128; + + max_buf 1000000; + + } +} + +(c) 2012 Roman Arutyunyan + diff --git a/TODO b/TODO index a1a02ef..370310f 100644 --- a/TODO +++ b/TODO @@ -1,22 +1,13 @@ -- implement chain-reuse for output +- add support of flv file streaming -- move shared bufs-related code to a separate .c +- compile in release configuration -- get rid of greedy send_chain +- add RTMP authorization - remove macros hell from ngx_rtmp_send.c -- packet dropping - -- l <-> cl - -- closing session on send error - causes crash because of double-freeing stack - - add max message size -- recognize amf-meta - - shortcuts for big-endian copy - implement loc confs (=fms apps) diff --git a/ngx_rtmp_broadcast_module.c b/ngx_rtmp_broadcast_module.c index cffe94a..d61c1f5 100644 --- a/ngx_rtmp_broadcast_module.c +++ b/ngx_rtmp_broadcast_module.c @@ -261,19 +261,28 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) { ngx_connection_t *c; - ngx_rtmp_broadcast_ctx_t *ctx, *cctx; + ngx_rtmp_broadcast_ctx_t *ctx, *cctx, *cnext; ngx_chain_t *out; ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_header_t sh; ngx_rtmp_session_t *ss; + ngx_rtmp_header_t sh; ngx_uint_t priority; + ngx_int_t rc; int keyframe; c = s->connection; cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_broadcast_module); - sh = *h; + memset(&sh, 0, sizeof(sh)); + sh.timestamp = h->timestamp + s->epoch; + sh.msid = NGX_RTMP_BROADCAST_MSID; + sh.type = h->type; + + ngx_log_debug4(NGX_LOG_DEBUG_RTMP, c->log, 0, + "av packet; peer_epoch=%uD; my_epoch=%uD timestamp=%uD; r=%uD", + s->peer_epoch, s->epoch, h->timestamp, sh.timestamp); + keyframe = 0; if (h->type == NGX_RTMP_MSG_VIDEO) { sh.csid = NGX_RTMP_BROADCAST_CSID_VIDEO; @@ -282,9 +291,12 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, keyframe = 1; } - } else { + } else if (h->type == NGX_RTMP_MSG_AUDIO) { sh.csid = NGX_RTMP_BROADCAST_CSID_AUDIO; priority = NGX_RTMP_AUDIO_FRAME; + + } else { + return NGX_OK; } if (ctx == NULL @@ -304,9 +316,11 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_rtmp_prepare_message(s, &sh, NULL, out); /* broadcast to all subscribers */ - for (cctx = *ngx_rtmp_broadcast_get_head(s); - cctx; cctx = cctx->next) - { + for (cctx = *ngx_rtmp_broadcast_get_head(s); cctx; cctx = cnext) { + /* session can die further in loop + * so save next ptr while it's not too late */ + cnext = cctx->next; + if (cctx != ctx && cctx->flags & NGX_RTMP_BROADCAST_SUBSCRIBER && cctx->stream.len == ctx->stream.len @@ -317,21 +331,19 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, /* if we have metadata check if the subscriber * has already received one */ - if (ctx->data_frame + if (ctx->data_frame && 0 && !(cctx->flags & NGX_RTMP_BROADCAST_DATA_FRAME)) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "sending data_frame"); - switch (ngx_rtmp_send_message(ss, ctx->data_frame, 0)) { - case NGX_OK: - cctx->flags |= NGX_RTMP_BROADCAST_DATA_FRAME; - break; - case NGX_AGAIN: - break; - default: - ngx_log_error(NGX_LOG_INFO, ss->connection->log, 0, - "error sending message"); + rc = ngx_rtmp_send_message(ss, ctx->data_frame, 0); + if (rc == NGX_ERROR) { + continue; + } + + if (rc == NGX_OK) { + cctx->flags |= NGX_RTMP_BROADCAST_DATA_FRAME; } } @@ -344,13 +356,13 @@ ngx_rtmp_broadcast_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, continue; } - if (ngx_rtmp_send_message(ss, out, priority) == NGX_OK) { - if (keyframe) { - cctx->flags |= NGX_RTMP_BROADCAST_KEYFRAME; - } - } else { - ngx_log_error(NGX_LOG_INFO, ss->connection->log, 0, - "error sending message"); + if (ngx_rtmp_send_message(ss, out, priority) == NGX_OK + && keyframe + && !(cctx->flags & NGX_RTMP_BROADCAST_KEYFRAME)) + { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "keyframe sent"); + cctx->flags |= NGX_RTMP_BROADCAST_KEYFRAME; } } } @@ -697,8 +709,8 @@ ngx_rtmp_broadcast_set_data_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, memset(&sh, 0, sizeof(sh)); sh.csid = NGX_RTMP_BROADCAST_CSID_AMF0; - sh.msid = h->msid; - sh.type = h->type; + sh.msid = NGX_RTMP_BROADCAST_MSID; + sh.type = NGX_RTMP_MSG_AMF0_META; ngx_rtmp_prepare_message(s, h, NULL, ctx->data_frame); @@ -715,7 +727,7 @@ ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, static double trans; static ngx_rtmp_amf0_elt_t in_elts[] = { - { NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) }, + { NGX_RTMP_AMF0_NUMBER, 0, &trans, sizeof(trans) }, }; static ngx_rtmp_amf0_elt_t out_elts[] = { @@ -733,9 +745,9 @@ ngx_rtmp_broadcast_ok(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, } memset(&sh, 0, sizeof(sh)); - sh.csid = NGX_RTMP_BROADCAST_CSID_AMF0; - sh.type = NGX_RTMP_MSG_AMF0_META; - sh.msid = h->msid; + sh.csid = h->csid;/*NGX_RTMP_BROADCAST_CSID_AMF0;*/ + sh.type = NGX_RTMP_MSG_AMF0_CMD; + sh.msid = 0;//NGX_RTMP_BROADCAST_MSID; /* send simple _result */ return ngx_rtmp_send_amf0(s, &sh, out_elts, diff --git a/ngx_rtmp_handler.c b/ngx_rtmp_handler.c index 18d9df2..00df18f 100644 --- a/ngx_rtmp_handler.c +++ b/ngx_rtmp_handler.c @@ -264,8 +264,8 @@ ngx_rtmp_get_timestamp() tod = ngx_timeofday(); - return (uint32_t)tod->sec * 1e3 - + (uint32_t)tod->msec / 1e3; + /* FIXME: divisor */ + return (uint32_t)(tod->sec * 1000 + tod->msec / 1000) % 0x00ffffff; } diff --git a/ngx_rtmp_receive.c b/ngx_rtmp_receive.c index e1d631b..94d9dfa 100644 --- a/ngx_rtmp_receive.c +++ b/ngx_rtmp_receive.c @@ -126,9 +126,9 @@ ngx_rtmp_user_message_handler(ngx_rtmp_session_t *s, p[2] = b->pos[7]; p[3] = b->pos[6]; - (void)arg; - /* use =val as stream id && arg as buflen in msec*/ + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, c->log, 0, + "msid=%uD buflen: %uD (msec)", val, arg); } break; diff --git a/test/nginx.conf b/test/nginx.conf index 30c7ad5..ef31102 100644 --- a/test/nginx.conf +++ b/test/nginx.conf @@ -20,7 +20,7 @@ rtmp { listen 1935; - wait_key_frame on; +# wait_key_frame on; chunk_size 128; diff --git a/test/www/index.html b/test/www/index.html index 7e6711a..c9f358d 100644 --- a/test/www/index.html +++ b/test/www/index.html @@ -5,14 +5,14 @@
Loading the player ...