improved frame timing & added meta files

This commit is contained in:
Roman Arutyunyan 2012-03-20 03:52:39 +04:00
parent b9ee8dbe09
commit 1e9a7e6efc
10 changed files with 120 additions and 54 deletions

8
AUTHORS Normal file
View file

@ -0,0 +1,8 @@
Project author:
Roman Arutyunyan
Moscow, Russia
Contacts:
arut@qip.ru
arutyunyan.roman@gmail.com

22
LICENSE Normal file
View file

@ -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.

37
README
View file

@ -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

15
TODO
View file

@ -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)

View file

@ -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,

View file

@ -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;
}

View file

@ -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;

View file

@ -20,7 +20,7 @@ rtmp {
listen 1935;
wait_key_frame on;
# wait_key_frame on;
chunk_size 128;

View file

@ -5,14 +5,14 @@
<div id="container">Loading the player ...</div>
<script type="text/javascript">
jwplayer("container").setup({
image: "http://10.31.1.78/showme.jpg",
modes: [
{ type: "flash",
src: "/jwplayer/player.swf",
config: {
file: "video.mp4",
streamer: "rtmp://10.31.1.78/helo",
provider: "rtmp"
bufferlength: 3,
file: "livepresentation",
streamer: "rtmp://192.168.0.100/helo",
provider: "rtmp",
}
}
]

View file

@ -1,7 +1,5 @@
<a href="index.html">Play</a> | <b>Record</b>
<br/>
<html lang="en">
<head>
<script src="jwplayer_old/swfobject.js"></script>
<script type="text/javascript">
var flashvars =