Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: arut/nginx-rtmp-module
base: 5824635938
...
head fork: arut/nginx-rtmp-module
compare: v0.7.2
  • 14 commits
  • 11 files changed
  • 0 commit comments
  • 1 contributor
118 ngx_rtmp_cmd_module.c
View
@@ -1003,71 +1003,17 @@ ngx_rtmp_cmd_pause_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
static ngx_int_t
ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
{
- ngx_rtmp_header_t h;
-
- static double trans;
-
- static ngx_rtmp_amf_elt_t out_inf[] = {
-
- { NGX_RTMP_AMF_STRING,
- ngx_string("code"),
- "NetStream.Pause.Notify", 0 },
-
- { NGX_RTMP_AMF_STRING,
- ngx_string("level"),
- "status", 0 },
-
- { NGX_RTMP_AMF_STRING,
- ngx_string("description"),
- "Paused.", 0 },
- };
-
- static ngx_rtmp_amf_elt_t out_elts[] = {
-
- { NGX_RTMP_AMF_STRING,
- ngx_null_string,
- "onStatus", 0 },
-
- { NGX_RTMP_AMF_NUMBER,
- ngx_null_string,
- &trans, 0 },
-
- { NGX_RTMP_AMF_NULL,
- ngx_null_string,
- NULL, 0 },
-
- { NGX_RTMP_AMF_OBJECT,
- ngx_null_string,
- out_inf, sizeof(out_inf) },
- };
-
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "pause: state='%i' position=%i",
- v->pause, (ngx_int_t) v->position);
-
- /* send onStatus reply */
- ngx_memzero(&h, sizeof(h));
- h.type = NGX_RTMP_MSG_AMF_CMD;
- h.csid = NGX_RTMP_CSID_AMF;
- h.msid = NGX_RTMP_MSID;
+ "pause: state='%i' position=%i",
+ v->pause, (ngx_int_t) v->position);
if (v->pause) {
- out_inf[0].data = "NetStream.Pause.Notify";
- out_inf[2].data = "Paused.";
- return ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_MSID) != NGX_OK
- || ngx_rtmp_send_amf(s, &h, out_elts,
- sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
- ? NGX_ERROR
- : NGX_OK;
+ return ngx_rtmp_send_status(s, "NetStream.Pause.Notify", "status",
+ "Paused");
+ } else {
+ return ngx_rtmp_send_status(s, "NetStream.Unpause.Notify", "status",
+ "Unpaused");
}
-
- out_inf[0].data = "NetStream.Unpause.Notify";
- out_inf[2].data = "Unpaused.";
- return ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_MSID) != NGX_OK
- || ngx_rtmp_send_amf(s, &h, out_elts,
- sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
- ? NGX_ERROR
- : NGX_OK;
}
@@ -1124,57 +1070,13 @@ ngx_rtmp_cmd_seek_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
static ngx_int_t
ngx_rtmp_cmd_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v)
{
- ngx_rtmp_header_t h;
-
- static double trans;
-
- static ngx_rtmp_amf_elt_t out_inf[] = {
-
- { NGX_RTMP_AMF_STRING,
- ngx_string("code"),
- "NetStream.Play.Reset", 0 },
-
- { NGX_RTMP_AMF_STRING,
- ngx_string("level"),
- "status", 0 },
-
- { NGX_RTMP_AMF_STRING,
- ngx_string("description"),
- "Paused.", 0 },
- };
-
- static ngx_rtmp_amf_elt_t out_elts[] = {
-
- { NGX_RTMP_AMF_STRING,
- ngx_null_string,
- "onStatus", 0 },
-
- { NGX_RTMP_AMF_NUMBER,
- ngx_null_string,
- &trans, 0 },
-
- { NGX_RTMP_AMF_NULL,
- ngx_null_string,
- NULL, 0 },
-
- { NGX_RTMP_AMF_OBJECT,
- ngx_null_string,
- out_inf, sizeof(out_inf) },
- };
-
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "seek: offset=%i", (ngx_int_t) v->offset);
-
- /* send onStatus reply */
- ngx_memzero(&h, sizeof(h));
- h.type = NGX_RTMP_MSG_AMF_CMD;
- h.csid = NGX_RTMP_CSID_AMF;
- h.msid = NGX_RTMP_MSID;
+ "seek: offset=%i", (ngx_int_t) v->offset);
return (ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_MSID) != NGX_OK
|| ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_MSID) != NGX_OK
- || ngx_rtmp_send_amf(s, &h, out_elts,
- sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
+ || ngx_rtmp_send_status(s, "NetStream.Seek.Notify", "status",
+ "Seeking"))
? NGX_ERROR
: NGX_OK;
}
39 ngx_rtmp_flv_module.c
View
@@ -13,10 +13,12 @@ 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,
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);
-static ngx_int_t ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f,
+static ngx_int_t ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_flv_seek(ngx_rtmp_session_t *s, ngx_file_t *f,
ngx_uint_t offset);
static ngx_int_t ngx_rtmp_flv_stop(ngx_rtmp_session_t *s, ngx_file_t *f);
-static ngx_int_t ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f,
+ ngx_uint_t *ts);
typedef struct {
@@ -42,6 +44,7 @@ typedef struct {
#define NGX_RTMP_FLV_BUFFER (1024*1024)
#define NGX_RTMP_FLV_DEFAULT_BUFLEN 1000
+#define NGX_RTMP_FLV_BUFLEN_ADDON 1000
#define NGX_RTMP_FLV_TAG_HEADER 11
#define NGX_RTMP_FLV_DATA_OFFSET 13
@@ -389,7 +392,7 @@ ngx_rtmp_flv_read_meta(ngx_rtmp_session_t *s, ngx_file_t *f)
static ngx_int_t
-ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f)
+ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t *ts)
{
ngx_rtmp_flv_ctx_t *ctx;
uint32_t last_timestamp;
@@ -524,7 +527,8 @@ ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f)
return NGX_OK;
}
- buflen = (s->buflen ? s->buflen : NGX_RTMP_FLV_DEFAULT_BUFLEN);
+ buflen = (s->buflen ? s->buflen + NGX_RTMP_FLV_BUFLEN_ADDON:
+ NGX_RTMP_FLV_DEFAULT_BUFLEN);
end_timestamp = (ngx_current_msec - ctx->epoch) +
ctx->start_timestamp + buflen;
@@ -567,7 +571,28 @@ ngx_rtmp_flv_init(ngx_rtmp_session_t *s, ngx_file_t *f)
static ngx_int_t
-ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
+ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f)
+{
+ ngx_rtmp_flv_ctx_t *ctx;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_flv_module);
+
+ if (ctx == NULL) {
+ return NGX_OK;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "flv: start");
+
+ ctx->offset = -1;
+ ctx->msg_mask = 0;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_flv_seek(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
{
ngx_rtmp_flv_ctx_t *ctx;
@@ -578,9 +603,10 @@ ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "flv: start timestamp=%ui", timestamp);
+ "flv: seek timestamp=%ui", timestamp);
ctx->start_timestamp = timestamp;
+ ctx->epoch = ngx_current_msec;
ctx->offset = -1;
ctx->msg_mask = 0;
@@ -635,6 +661,7 @@ ngx_rtmp_flv_postconfiguration(ngx_conf_t *cf)
fmt->init = ngx_rtmp_flv_init;
fmt->start = ngx_rtmp_flv_start;
+ fmt->seek = ngx_rtmp_flv_seek;
fmt->stop = ngx_rtmp_flv_stop;
fmt->send = ngx_rtmp_flv_send;
22 ngx_rtmp_live_module.c
View
@@ -202,18 +202,20 @@ ngx_rtmp_live_join(ngx_rtmp_session_t *s, u_char *name,
}
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module);
- if (ctx == NULL) {
- ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_live_ctx_t));
- ctx->session = s;
- ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_live_module);
- }
-
- if (ctx->stream) {
+ if (ctx && ctx->stream) {
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log,
0, "live: already joined");
return;
}
+ if (ctx == NULL) {
+ ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_live_ctx_t));
+ ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_live_module);
+ }
+
+ ngx_memzero(ctx, sizeof(*ctx));
+ ctx->session = s;
+
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"live: join '%s'", name);
@@ -378,6 +380,12 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ctx->last_audio = ch.timestamp;
last_offset = offsetof(ngx_rtmp_live_ctx_t, last_audio);
}
+
+ if ((ctx->msg_mask & (1 << h->type)) == 0) {
+ lh.timestamp = ch.timestamp;
+ ctx->msg_mask |= (1 << h->type);
+ }
+
lh.csid = ch.csid;
diff_timestamp = ch.timestamp - lh.timestamp;
157 ngx_rtmp_mp4_module.c
View
@@ -9,12 +9,15 @@
static ngx_int_t ngx_rtmp_mp4_postconfiguration(ngx_conf_t *cf);
-static ngx_int_t ngx_rtmp_mp4_init(ngx_rtmp_session_t *s, ngx_file_t *f);
-static ngx_int_t ngx_rtmp_mp4_done(ngx_rtmp_session_t *s, ngx_file_t *f);
-static ngx_int_t ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f,
- ngx_uint_t offset);
-static ngx_int_t ngx_rtmp_mp4_stop(ngx_rtmp_session_t *s, ngx_file_t *f);
-static ngx_int_t ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_mp4_init(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_mp4_done(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_mp4_seek(ngx_rtmp_session_t *s, ngx_file_t *f,
+ ngx_uint_t offset);
+static ngx_int_t ngx_rtmp_mp4_stop(ngx_rtmp_session_t *s, ngx_file_t *f);
+static ngx_int_t ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f,
+ ngx_uint_t *ts);
+static ngx_int_t ngx_rtmp_mp4_reset(ngx_rtmp_session_t *s);
#pragma pack(push,4)
@@ -193,6 +196,7 @@ ngx_rtmp_mp4_from_rtmp_timestamp(ngx_rtmp_mp4_track_t *t, uint32_t ts)
#define NGX_RTMP_MP4_DEFAULT_BUFLEN 1000
+#define NGX_RTMP_MP4_BUFLEN_ADDON 1000
static u_char ngx_rtmp_mp4_buffer[1024*1024];
@@ -876,7 +880,7 @@ ngx_rtmp_mp4_parse_stsc(ngx_rtmp_session_t *s, u_char *pos, u_char *last)
t->chunks = (ngx_rtmp_mp4_chunks_t *) pos;
- if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->times->entry_count) *
+ if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->chunks->entry_count) *
sizeof(t->chunks->entries[0])
<= last)
{
@@ -1236,7 +1240,8 @@ ngx_rtmp_mp4_seek_time(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t,
return NGX_ERROR;
}
- cr->time_count = (timestamp - cr->timestamp) / ngx_rtmp_r32(te->sample_delta);
+ cr->time_count = (timestamp - cr->timestamp) /
+ ngx_rtmp_r32(te->sample_delta);
cr->timestamp += ngx_rtmp_r32(te->sample_delta) * cr->time_count;
cr->pos += cr->time_count;
@@ -1519,13 +1524,20 @@ static ngx_int_t
ngx_rtmp_mp4_seek_size(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
{
ngx_rtmp_mp4_cursor_t *cr;
+ ngx_uint_t pos;
cr = &t->cursor;
+ if (cr->chunk_count > cr->pos) {
+ return NGX_ERROR;
+ }
+
if (t->sizes) {
if (t->sizes->sample_size) {
cr->size = ngx_rtmp_r32(t->sizes->sample_size);
+ cr->offset += cr->size * cr->chunk_count;
+
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui seek size fix=%uz",
t->id, cr->size);
@@ -1542,6 +1554,10 @@ ngx_rtmp_mp4_seek_size(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
return NGX_ERROR;
}
+ for (pos = 1; pos <= cr->chunk_count; ++pos) {
+ cr->offset += ngx_rtmp_r32(t->sizes->entries[cr->pos - pos]);
+ }
+
cr->size_pos = cr->pos;
cr->size = ngx_rtmp_r32(t->sizes->entries[cr->size_pos]);
@@ -1620,6 +1636,7 @@ ngx_rtmp_mp4_seek_key(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
{
ngx_rtmp_mp4_cursor_t *cr;
uint32_t *ke;
+ ngx_int_t dpos;
cr = &t->cursor;
@@ -1628,7 +1645,7 @@ ngx_rtmp_mp4_seek_key(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
}
while (cr->key_pos < ngx_rtmp_r32(t->keys->entry_count)) {
- if (ngx_rtmp_r32(t->keys->entries[cr->key_pos]) >= cr->pos) {
+ if (ngx_rtmp_r32(t->keys->entries[cr->key_pos]) > cr->pos) {
break;
}
@@ -1644,7 +1661,18 @@ ngx_rtmp_mp4_seek_key(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
}
ke = &t->keys->entries[cr->key_pos];
- cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));
+ /*cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));*/
+
+ /* distance to the next keyframe */
+ dpos = ngx_rtmp_r32(*ke) - cr->pos - 1;
+ cr->key = 1;
+
+ /* TODO: range version needed */
+ for (; dpos > 0; --dpos) {
+ ngx_rtmp_mp4_next_time(s, t);
+ }
+
+/* cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));*/
ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui seek key[%ui/%uD][%ui/%uD]=%s",
@@ -1921,7 +1949,7 @@ ngx_rtmp_mp4_seek_track(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t,
static ngx_int_t
-ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f)
+ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t *ts)
{
ngx_rtmp_mp4_ctx_t *ctx;
ngx_buf_t in_buf;
@@ -1956,12 +1984,14 @@ ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f)
return rc;
}
- buflen = (s->buflen ? s->buflen : NGX_RTMP_MP4_DEFAULT_BUFLEN);
+ buflen = (s->buflen ? s->buflen + NGX_RTMP_MP4_BUFLEN_ADDON:
+ NGX_RTMP_MP4_DEFAULT_BUFLEN);
t = ctx->tracks;
sched = 0;
active = 0;
+ last_timestamp = 0;
end_timestamp = ctx->start_timestamp +
(ngx_current_msec - ctx->epoch) + buflen;
@@ -2123,7 +2153,17 @@ ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f)
return sched;
}
- return active ? NGX_OK : NGX_DONE;
+ if (active) {
+ return NGX_OK;
+ }
+
+ if (ts) {
+ *ts = last_timestamp;
+ }
+
+ /*ngx_rtmp_mp4_reset(s);*/
+
+ return NGX_DONE;
}
@@ -2227,9 +2267,10 @@ ngx_rtmp_mp4_done(ngx_rtmp_session_t *s, ngx_file_t *f)
static ngx_int_t
-ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
+ngx_rtmp_mp4_seek(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
{
ngx_rtmp_mp4_ctx_t *ctx;
+ ngx_rtmp_mp4_track_t *t;
ngx_uint_t n;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
@@ -2239,17 +2280,84 @@ ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: start timestamp=%ui", timestamp);
+ "mp4: seek timestamp=%ui", timestamp);
+
+ for (n = 0; n < ctx->ntracks; ++n) {
+ t = &ctx->tracks[n];
+
+ if (t->type != NGX_RTMP_MSG_VIDEO) {
+ continue;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "mp4: track#%ui seek video", n);
+
+ ngx_rtmp_mp4_seek_track(s, t, timestamp);
+
+ timestamp = ngx_rtmp_mp4_to_rtmp_timestamp(t, t->cursor.timestamp);
+
+ break;
+ }
for (n = 0; n < ctx->ntracks; ++n) {
+ t = &ctx->tracks[n];
+
+ if (t->type == NGX_RTMP_MSG_VIDEO) {
+ continue;
+ }
+
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"mp4: track#%ui seek", n);
ngx_rtmp_mp4_seek_track(s, &ctx->tracks[n], timestamp);
}
- ctx->epoch = ngx_current_msec;
ctx->start_timestamp = timestamp;
+ ctx->epoch = ngx_current_msec;
+
+ return ngx_rtmp_mp4_reset(s);
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f)
+{
+ ngx_rtmp_mp4_ctx_t *ctx;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
+
+ if (ctx == NULL) {
+ return NGX_OK;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "mp4: start timestamp=%uD", ctx->start_timestamp);
+
+ ctx->epoch = ngx_current_msec;
+
+ return NGX_OK;/*ngx_rtmp_mp4_reset(s);*/
+}
+
+
+static ngx_int_t
+ngx_rtmp_mp4_reset(ngx_rtmp_session_t *s)
+{
+ ngx_rtmp_mp4_ctx_t *ctx;
+ ngx_rtmp_mp4_cursor_t *cr;
+ ngx_rtmp_mp4_track_t *t;
+ ngx_uint_t n;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
+
+ if (ctx == NULL) {
+ return NGX_OK;
+ }
+
+ t = &ctx->tracks[0];
+ for (n = 0; n < ctx->ntracks; ++n, ++t) {
+ cr = &t->cursor;
+ cr->not_first = 0;
+ }
return NGX_OK;
}
@@ -2258,10 +2366,20 @@ ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
static ngx_int_t
ngx_rtmp_mp4_stop(ngx_rtmp_session_t *s, ngx_file_t *f)
{
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "mp4: stop");
+ ngx_rtmp_mp4_ctx_t *ctx;
- return NGX_OK;
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
+
+ if (ctx == NULL) {
+ return NGX_OK;
+ }
+
+ ctx->start_timestamp += (ngx_current_msec - ctx->epoch);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "mp4: stop timestamp=%uD", ctx->start_timestamp);
+
+ return NGX_OK;/*ngx_rtmp_mp4_reset(s);*/
}
@@ -2294,6 +2412,7 @@ ngx_rtmp_mp4_postconfiguration(ngx_conf_t *cf)
fmt->init = ngx_rtmp_mp4_init;
fmt->done = ngx_rtmp_mp4_done;
+ fmt->seek = ngx_rtmp_mp4_seek;
fmt->start = ngx_rtmp_mp4_start;
fmt->stop = ngx_rtmp_mp4_stop;
fmt->send = ngx_rtmp_mp4_send;
150 ngx_rtmp_netcall_module.c
View
@@ -55,14 +55,14 @@ static ngx_command_t ngx_rtmp_netcall_commands[] = {
{ ngx_string("netcall_timeout"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
- NGX_RTMP_SRV_CONF_OFFSET,
+ NGX_RTMP_APP_CONF_OFFSET,
offsetof(ngx_rtmp_netcall_app_conf_t, timeout),
NULL },
{ ngx_string("netcall_buffer"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
- NGX_RTMP_SRV_CONF_OFFSET,
+ NGX_RTMP_APP_CONF_OFFSET,
offsetof(ngx_rtmp_netcall_app_conf_t, bufsize),
NULL },
@@ -491,58 +491,76 @@ ngx_rtmp_netcall_send(ngx_event_t *wev)
ngx_chain_t *
-ngx_rtmp_netcall_http_format_header(ngx_int_t method, ngx_str_t *uri,
- ngx_str_t *host, ngx_pool_t *pool,
- size_t content_length,
- ngx_str_t *content_type)
+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, ngx_pool_t *pool,
+ ngx_str_t *content_type)
{
- ngx_chain_t *cl;
+ ngx_chain_t *al, *bl, *ret;
ngx_buf_t *b;
- const char *method_s;
+ size_t content_length;
+ static const char *methods[2] = { "GET", "POST" };
+ static const char rq_tmpl[] = " HTTP/1.0\r\n"
+ "Host: %V\r\n"
+ "Content-Type: %V\r\n"
+ "Connection: Close\r\n"
+ "Content-Length: %uz\r\n"
+ "\r\n";
- static char rq_tmpl[] =
- "%s %V HTTP/1.0\r\n"
- "Host: %V\r\n"
- "Content-Type: %V\r\n"
- "Connection: Close\r\n"
- "Content-Length: %uz\r\n"
- "\r\n"
- ;
+ content_length = 0;
+ for (al = body; al; al = al->next) {
+ b = al->buf;
+ content_length += (b->last - b->pos);
+ }
- cl = ngx_alloc_chain_link(pool);
- if (cl == NULL) {
+ /* create first buffer */
+
+ al = ngx_alloc_chain_link(pool);
+ if (al == NULL) {
return NULL;
}
-
- b = ngx_create_temp_buf(pool, sizeof(rq_tmpl)
- + sizeof("POST") - 1 /* longest method */
- + uri->len
- + host->len
- + content_type->len
- + 5);
+ b = ngx_create_temp_buf(pool, sizeof("POST") + /* longest method + 1 */
+ uri->len);
if (b == NULL) {
return NULL;
}
- cl->buf = b;
- cl->next = NULL;
+ b->last = ngx_snprintf(b->last, b->end - b->last, "%s %V",
+ methods[method], uri);
+
+ al->buf = b;
- switch (method) {
- case NGX_RTMP_NETCALL_HTTP_GET:
- method_s = "GET";
- break;
- case NGX_RTMP_NETCALL_HTTP_POST:
- method_s = "POST";
- break;
- default:
- return NULL;
+ ret = al;
+
+ if (args) {
+ *b->last++ = '?';
+ al->next = args;
+ for (al = args; al->next; al = al->next);
}
+ /* create second buffer */
+
+ bl = ngx_alloc_chain_link(pool);
+ if (bl == NULL) {
+ return NULL;
+ }
+
+ b = ngx_create_temp_buf(pool, sizeof(rq_tmpl) + host->len +
+ content_type->len + NGX_OFF_T_LEN);
+ if (b == NULL) {
+ return NULL;
+ }
+
+ bl->buf = b;
+
b->last = ngx_snprintf(b->last, b->end - b->last, rq_tmpl,
- method_s, uri, host, content_type, content_length);
+ host, content_type, content_length);
- return cl;
+ al->next = bl;
+ bl->next = body;
+
+ return ret;
}
@@ -551,6 +569,9 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
{
ngx_chain_t *cl;
ngx_buf_t *b;
+ ngx_str_t *addr_text;
+
+ addr_text = &s->connection->addr_text;
cl = ngx_alloc_chain_link(pool);
if (cl == NULL) {
@@ -562,7 +583,8 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
sizeof("&flashver=") - 1 + s->flashver.len * 3 +
sizeof("&swfurl=") - 1 + s->swf_url.len * 3 +
sizeof("&tcurl=") - 1 + s->tc_url.len * 3 +
- sizeof("&pageurl=") - 1 + s->page_url.len * 3
+ sizeof("&pageurl=") - 1 + s->page_url.len * 3 +
+ sizeof("&addr=") - 1 + addr_text->len * 3
);
if (b == NULL) {
@@ -570,29 +592,35 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
}
cl->buf = b;
+ cl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*)"app=", sizeof("app=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, s->app.data, s->app.len, 0);
-
- b->last = ngx_cpymem(b->last, (u_char*)"&flashver=",
- sizeof("&flashver=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, s->flashver.data,
- s->flashver.len, 0);
-
- 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,
- s->swf_url.len, 0);
-
- 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,
- s->tc_url.len, 0);
-
- 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,
- s->page_url.len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "app=", sizeof("app=") - 1);
+ 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=",
+ sizeof("&flashver=") - 1);
+ 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=",
+ sizeof("&swfurl=") - 1);
+ 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=",
+ sizeof("&tcurl=") - 1);
+ 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=",
+ sizeof("&pageurl=") - 1);
+ 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,
+ addr_text->len, NGX_ESCAPE_ARGS);
return cl;
}
10 ngx_rtmp_netcall_module.h
View
@@ -20,8 +20,8 @@ typedef ngx_int_t (*ngx_rtmp_netcall_sink_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 1
-#define NGX_RTMP_NETCALL_HTTP_POST 2
+#define NGX_RTMP_NETCALL_HTTP_GET 0
+#define NGX_RTMP_NETCALL_HTTP_POST 1
/* If handle is NULL then netcall is created detached
@@ -51,9 +51,9 @@ ngx_int_t ngx_rtmp_netcall_create(ngx_rtmp_session_t *s,
/* HTTP handling */
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_header(ngx_int_t method,
- ngx_str_t *uri, ngx_str_t *host, ngx_pool_t *pool,
- size_t content_length, ngx_str_t *content_type);
+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,
+ ngx_pool_t *pool, ngx_str_t *content_type);
ngx_chain_t * ngx_rtmp_netcall_http_skip_header(ngx_chain_t *in);
321 ngx_rtmp_notify_module.c
View
@@ -20,6 +20,8 @@ static ngx_rtmp_record_done_pt next_record_done;
static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_rtmp_notify_method(ngx_conf_t *cf, ngx_command_t *cmd,
+ 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,
@@ -50,6 +52,7 @@ enum {
typedef struct {
ngx_url_t *url[NGX_RTMP_NOTIFY_MAX];
ngx_flag_t active;
+ ngx_uint_t method;
} ngx_rtmp_notify_app_conf_t;
@@ -111,6 +114,13 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
0,
NULL },
+ { ngx_string("notify_method"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
+ ngx_rtmp_notify_method,
+ NGX_RTMP_APP_CONF_OFFSET,
+ 0,
+ NULL },
+
ngx_null_command
};
@@ -158,6 +168,8 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf)
nacf->url[n] = NGX_CONF_UNSET_PTR;
}
+ nacf->method = NGX_CONF_UNSET;
+
return nacf;
}
@@ -180,35 +192,57 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
prev->active = 1;
}
+ ngx_conf_merge_uint_value(conf->method, prev->method,
+ NGX_RTMP_NETCALL_HTTP_POST);
+
return NGX_CONF_OK;
}
static ngx_chain_t *
-ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
- ngx_pool_t *pool)
+ngx_rtmp_notify_create_request(ngx_rtmp_session_t *s, ngx_pool_t *pool,
+ ngx_uint_t url_idx, ngx_chain_t *args)
{
- ngx_rtmp_publish_t *v = arg;
-
- ngx_rtmp_notify_app_conf_t *nacf;
- ngx_chain_t *hl, *cl, *pl;
- ngx_buf_t *b;
- ngx_str_t *addr_text;
- ngx_url_t *url;
- size_t name_len, type_len, args_len;
+ ngx_rtmp_notify_app_conf_t *nacf;
+ ngx_chain_t *al, *bl, *cl;
+ ngx_url_t *url;
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
- /* common variables */
- cl = ngx_rtmp_netcall_http_format_session(s, pool);
+ url = nacf->url[url_idx];
- if (cl == NULL) {
+ al = ngx_rtmp_netcall_http_format_session(s, pool);
+ if (al == NULL) {
return NULL;
}
- /* publish variables */
- pl = ngx_alloc_chain_link(pool);
+ al->next = args;
+
+ bl = NULL;
+
+ if (nacf->method == NGX_RTMP_NETCALL_HTTP_POST) {
+ cl = al;
+ al = bl;
+ bl = cl;
+ }
+
+ return ngx_rtmp_netcall_http_format_request(nacf->method, &url->host,
+ &url->uri, al, bl, pool,
+ &ngx_rtmp_notify_urlencoded);
+}
+
+
+static ngx_chain_t *
+ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
+ ngx_pool_t *pool)
+{
+ ngx_rtmp_publish_t *v = arg;
+
+ ngx_chain_t *pl;
+ ngx_buf_t *b;
+ size_t name_len, type_len, args_len;
+ pl = ngx_alloc_chain_link(pool);
if (pl == NULL) {
return NULL;
}
@@ -216,54 +250,36 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
name_len = ngx_strlen(v->name);
type_len = ngx_strlen(v->type);
args_len = ngx_strlen(v->args);
- addr_text = &s->connection->addr_text;
b = ngx_create_temp_buf(pool,
- sizeof("&call=publish") +
- sizeof("&addr=") + addr_text->len *3 +
- sizeof("&name=") + name_len * 3 +
- sizeof("&type=") + type_len * 3 +
- 1 + args_len);
+ sizeof("&call=publish") +
+ sizeof("&name=") + name_len * 3 +
+ sizeof("&type=") + type_len * 3 +
+ 1 + args_len);
if (b == NULL) {
return NULL;
}
pl->buf = b;
+ pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*)"&call=publish",
- sizeof("&call=publish") - 1);
-
- b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
- b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
- addr_text->len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
+ sizeof("&call=publish") - 1);
- b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
+ b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
+ NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*)"&type=", sizeof("&type=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, v->type, type_len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&type=", sizeof("&type=") - 1);
+ b->last = (u_char*) ngx_escape_uri(b->last, v->type, type_len,
+ NGX_ESCAPE_ARGS);
if (args_len) {
*b->last++ = '&';
- b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len);
+ b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
}
- /* HTTP header */
- url = nacf->url[NGX_RTMP_NOTIFY_PUBLISH];
- hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
- &url->uri, &url->host,
- pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
- &ngx_rtmp_notify_urlencoded);
-
- if (hl == NULL) {
- return NULL;
- }
-
- hl->next = cl;
- cl->next = pl;
- pl->next = NULL;
-
- return hl;
+ return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PUBLISH, pl);
}
@@ -273,80 +289,48 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
{
ngx_rtmp_play_t *v = arg;
- ngx_rtmp_notify_app_conf_t *nacf;
- ngx_chain_t *hl, *cl, *pl;
+ ngx_chain_t *pl;
ngx_buf_t *b;
- ngx_str_t *addr_text;
- ngx_url_t *url;
size_t name_len, args_len;
- nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
-
- /* common variables */
- cl = ngx_rtmp_netcall_http_format_session(s, pool);
-
- if (cl == NULL) {
- return NULL;
- }
-
- /* play variables */
pl = ngx_alloc_chain_link(pool);
-
if (pl == NULL) {
return NULL;
}
name_len = ngx_strlen(v->name);
args_len = ngx_strlen(v->args);
- addr_text = &s->connection->addr_text;
b = ngx_create_temp_buf(pool,
- sizeof("&call=play") +
- sizeof("&addr=") + addr_text->len * 3 +
- sizeof("&name=") + name_len * 3 +
- sizeof("&start=&duration=&reset=") + NGX_OFF_T_LEN * 3
- + 1 + args_len);
+ sizeof("&call=play") +
+ sizeof("&name=") + name_len * 3 +
+ sizeof("&start=&duration=&reset=") +
+ NGX_OFF_T_LEN * 3 + 1 + args_len);
if (b == NULL) {
return NULL;
}
pl->buf = b;
+ pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*)"&call=play",
- sizeof("&call=play") - 1);
-
- b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
- b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
- addr_text->len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
+ sizeof("&call=play") - 1);
- b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
+ b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
+ NGX_ESCAPE_ARGS);
b->last = ngx_snprintf(b->last, b->end - b->last,
- "&start=%uD&duration=%uD&reset=%d",
- (uint32_t)v->start, (uint32_t)v->duration, v->reset & 1);
+ "&start=%uD&duration=%uD&reset=%d",
+ (uint32_t) v->start, (uint32_t) v->duration,
+ v->reset & 1);
if (args_len) {
*b->last++ = '&';
- b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len);
- }
-
- /* HTTP header */
- url = nacf->url[NGX_RTMP_NOTIFY_PLAY];
- hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
- &url->uri, &url->host,
- pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
- &ngx_rtmp_notify_urlencoded);
-
- if (hl == NULL) {
- return NULL;
+ b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
}
- hl->next = cl;
- cl->next = pl;
- pl->next = NULL;
-
- return hl;
+ return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PLAY, pl);
}
@@ -356,23 +340,14 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
{
ngx_rtmp_notify_done_t *ds = arg;
- ngx_chain_t *hl, *cl, *pl;
+ ngx_chain_t *pl;
ngx_buf_t *b;
size_t cbname_len, name_len, args_len;
- ngx_str_t *addr_text;
ngx_rtmp_notify_ctx_t *ctx;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
- /* common variables */
- cl = ngx_rtmp_netcall_http_format_session(s, pool);
-
- if (cl == NULL) {
- return NULL;
- }
-
pl = ngx_alloc_chain_link(pool);
-
if (pl == NULL) {
return NULL;
}
@@ -380,51 +355,33 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
cbname_len = ngx_strlen(ds->cbname);
name_len = ctx ? ngx_strlen(ctx->name) : 0;
args_len = ctx ? ngx_strlen(ctx->args) : 0;
- addr_text = &s->connection->addr_text;
b = ngx_create_temp_buf(pool,
- sizeof("&call=") + cbname_len +
- sizeof("&addr=") + addr_text->len * 3 +
- sizeof("&name=") + name_len * 3
- + 1 + args_len);
+ sizeof("&call=") + cbname_len +
+ sizeof("&name=") + name_len * 3 +
+ 1 + args_len);
if (b == NULL) {
return NULL;
}
pl->buf = b;
+ pl->next = NULL;
- b->last = ngx_cpymem(b->last, (u_char*)"&call=", sizeof("&call=") - 1);
+ b->last = ngx_cpymem(b->last, (u_char*) "&call=", sizeof("&call=") - 1);
b->last = ngx_cpymem(b->last, ds->cbname, cbname_len);
- b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
- b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
- addr_text->len, 0);
-
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, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
+ b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
+ NGX_ESCAPE_ARGS);
}
if (args_len) {
*b->last++ = '&';
- b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len);
+ b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
}
- /* HTTP header */
- hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
- &ds->url->uri, &ds->url->host,
- pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
- &ngx_rtmp_notify_urlencoded);
-
- if (hl == NULL) {
- return NULL;
- }
-
- hl->next = cl;
- cl->next = pl;
- pl->next = NULL;
-
- return hl;
+ return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_DONE, pl);
}
@@ -434,88 +391,57 @@ ngx_rtmp_notify_record_done_create(ngx_rtmp_session_t *s, void *arg,
{
ngx_rtmp_record_done_t *v = arg;
- ngx_rtmp_notify_app_conf_t *nacf;
ngx_rtmp_notify_ctx_t *ctx;
- ngx_chain_t *hl, *cl, *pl;
+ ngx_chain_t *pl;
ngx_buf_t *b;
- ngx_str_t *addr_text;
- ngx_url_t *url;
size_t name_len, args_len;
- nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
-
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
- /* common variables */
- cl = ngx_rtmp_netcall_http_format_session(s, pool);
-
- if (cl == NULL) {
- return NULL;
- }
-
- /* publish variables */
pl = ngx_alloc_chain_link(pool);
-
if (pl == NULL) {
return NULL;
}
name_len = ngx_strlen(ctx->name);
args_len = ngx_strlen(ctx->args);
- addr_text = &s->connection->addr_text;
b = ngx_create_temp_buf(pool,
sizeof("&call=record_done") +
sizeof("&recorder=") + v->recorder.len +
- sizeof("&addr=") + addr_text->len *3 +
sizeof("&name=") + name_len * 3 +
sizeof("&path=") + v->path.len * 3 +
- + 1 + args_len);
+ 1 + args_len);
if (b == NULL) {
return NULL;
}
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, 0);
+ b->last = (u_char*) ngx_escape_uri(b->last, v->recorder.data,
+ v->recorder.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,
- addr_text->len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
+ b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
+ NGX_ESCAPE_ARGS);
- b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0);
-
- b->last = ngx_cpymem(b->last, (u_char*)"&path=", sizeof("&path=") - 1);
- b->last = (u_char*)ngx_escape_uri(b->last, v->path.data, v->path.len, 0);
+ b->last = ngx_cpymem(b->last, (u_char*) "&path=", sizeof("&path=") - 1);
+ b->last = (u_char*) ngx_escape_uri(b->last, v->path.data, v->path.len,
+ NGX_ESCAPE_ARGS);
if (args_len) {
*b->last++ = '&';
- b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len);
+ b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
}
- /* HTTP header */
- url = nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE];
- hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
- &url->uri, &url->host,
- pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
- &ngx_rtmp_notify_urlencoded);
-
- if (hl == NULL) {
- return NULL;
- }
-
- hl->next = cl;
- cl->next = pl;
- pl->next = NULL;
-
- return hl;
+ return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_RECORD_DONE,
+ pl);
}
@@ -800,7 +726,8 @@ ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_url_t *url)
static char *
ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_rtmp_notify_app_conf_t *nacf;
+ ngx_rtmp_notify_app_conf_t *nacf = conf;
+
ngx_str_t *url, *name;
ngx_url_t *u;
size_t add;
@@ -835,8 +762,6 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- nacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_notify_module);
-
n = 0;
switch (name->len) {
@@ -871,6 +796,34 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
+static char *
+ngx_rtmp_notify_method(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_rtmp_notify_app_conf_t *nacf = conf;
+
+ ngx_str_t *value;
+
+ value = cf->args->elts;
+ value++;
+
+ if (value->len == sizeof("get") - 1 &&
+ ngx_strncasecmp(value->data, (u_char *) "get", value->len) == 0)
+ {
+ nacf->method = NGX_RTMP_NETCALL_HTTP_GET;
+
+ } else if (value->len == sizeof("post") - 1 &&
+ ngx_strncasecmp(value->data, (u_char *) "post", value->len) == 0)
+ {
+ nacf->method = NGX_RTMP_NETCALL_HTTP_POST;
+
+ } else {
+ return "got unexpected method";
+ }
+
+ return NGX_CONF_OK;
+}
+
+
static ngx_int_t
ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
{
110 ngx_rtmp_play_module.c
View
@@ -22,10 +22,18 @@ 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,
void *parent, void *child);
-static ngx_int_t ngx_rtmp_play_init(ngx_rtmp_session_t *s);
-static ngx_int_t ngx_rtmp_play_done(ngx_rtmp_session_t *s);
-static ngx_int_t ngx_rtmp_play_start(ngx_rtmp_session_t *s, double timestamp);
-static ngx_int_t ngx_rtmp_play_stop(ngx_rtmp_session_t *s);
+
+static ngx_int_t ngx_rtmp_play_do_init(ngx_rtmp_session_t *s);
+static ngx_int_t ngx_rtmp_play_do_done(ngx_rtmp_session_t *s);
+static ngx_int_t ngx_rtmp_play_do_start(ngx_rtmp_session_t *s);
+static ngx_int_t ngx_rtmp_play_do_stop(ngx_rtmp_session_t *s);
+static ngx_int_t ngx_rtmp_play_do_seek(ngx_rtmp_session_t *s,
+ ngx_uint_t timestamp);
+
+static ngx_int_t ngx_rtmp_play_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v);
+static ngx_int_t ngx_rtmp_play_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v);
+static ngx_int_t ngx_rtmp_play_pause(ngx_rtmp_session_t *s,
+ ngx_rtmp_pause_t *v);
static void ngx_rtmp_play_send(ngx_event_t *e);
static ngx_int_t ngx_rtmp_play_open(ngx_rtmp_session_t *s, double start);
static ngx_int_t ngx_rtmp_play_remote_handle(ngx_rtmp_session_t *s,
@@ -140,6 +148,7 @@ ngx_rtmp_play_send(ngx_event_t *e)
ngx_rtmp_session_t *s = e->data;
ngx_rtmp_play_ctx_t *ctx;
ngx_int_t rc;
+ ngx_uint_t ts;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
@@ -147,7 +156,9 @@ ngx_rtmp_play_send(ngx_event_t *e)
return;
}
- rc = ctx->fmt->send(s, &ctx->file);
+ ts = 0;
+
+ rc = ctx->fmt->send(s, &ctx->file, &ts);
if (rc > 0) {
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@@ -179,13 +190,14 @@ ngx_rtmp_play_send(ngx_event_t *e)
ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_MSID);
- ngx_rtmp_send_play_status(s, "NetStream.Play.Complete", "status", 0, 0);
+ ngx_rtmp_send_play_status(s, "NetStream.Play.Complete", "status", ts, 0);
+
ngx_rtmp_send_status(s, "NetStream.Play.Stop", "status", "Stopped");
}
static ngx_int_t
-ngx_rtmp_play_init(ngx_rtmp_session_t *s)
+ngx_rtmp_play_do_init(ngx_rtmp_session_t *s)
{
ngx_rtmp_play_ctx_t *ctx;
@@ -206,7 +218,7 @@ ngx_rtmp_play_init(ngx_rtmp_session_t *s)
static ngx_int_t
-ngx_rtmp_play_done(ngx_rtmp_session_t *s)
+ngx_rtmp_play_do_done(ngx_rtmp_session_t *s)
{
ngx_rtmp_play_ctx_t *ctx;
@@ -227,10 +239,9 @@ ngx_rtmp_play_done(ngx_rtmp_session_t *s)
static ngx_int_t
-ngx_rtmp_play_start(ngx_rtmp_session_t *s, double timestamp)
+ngx_rtmp_play_do_start(ngx_rtmp_session_t *s)
{
ngx_rtmp_play_ctx_t *ctx;
- ngx_uint_t ts;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
@@ -238,27 +249,53 @@ ngx_rtmp_play_start(ngx_rtmp_session_t *s, double timestamp)
return NGX_ERROR;
}
- ngx_rtmp_play_stop(s);
+ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "play: start");
+
+ if (ctx->fmt && ctx->fmt->start &&
+ ctx->fmt->start(s, &ctx->file) != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ ngx_post_event((&ctx->send_evt), &ngx_posted_events);
+
+ ctx->playing = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_play_do_seek(ngx_rtmp_session_t *s, ngx_uint_t timestamp)
+{
+ ngx_rtmp_play_ctx_t *ctx;
+
+ ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
- ts = (timestamp > 0 ? (ngx_uint_t) timestamp : 0);
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "play: start timestamp=%ui", ts);
+ "play: seek timestamp=%ui", timestamp);
- if (ctx->fmt && ctx->fmt->start &&
- ctx->fmt->start(s, &ctx->file, ts) != NGX_OK)
+ if (ctx->fmt && ctx->fmt->seek &&
+ ctx->fmt->seek(s, &ctx->file, timestamp) != NGX_OK)
{
return NGX_ERROR;
}
- ngx_post_event((&ctx->send_evt), &ngx_posted_events);
+ if (ctx->playing) {
+ ngx_post_event((&ctx->send_evt), &ngx_posted_events);
+ }
return NGX_OK;
}
static ngx_int_t
-ngx_rtmp_play_stop(ngx_rtmp_session_t *s)
+ngx_rtmp_play_do_stop(ngx_rtmp_session_t *s)
{
ngx_rtmp_play_ctx_t *ctx;
@@ -285,6 +322,8 @@ ngx_rtmp_play_stop(ngx_rtmp_session_t *s)
return NGX_ERROR;
}
+ ctx->playing = 0;
+
return NGX_OK;
}
@@ -303,9 +342,9 @@ ngx_rtmp_play_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"play: close_stream");
- ngx_rtmp_play_stop(s);
+ ngx_rtmp_play_do_stop(s);
- ngx_rtmp_play_done(s);
+ ngx_rtmp_play_do_done(s);
if (ctx->file.fd != NGX_INVALID_FILE) {
ngx_close_file(ctx->file.fd);
@@ -327,10 +366,7 @@ ngx_rtmp_play_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v)
goto next;
}
- ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "play: seek offset=%f", v->offset);
-
- ngx_rtmp_play_start(s, v->offset);
+ ngx_rtmp_play_do_seek(s, v->offset);
next:
return next_seek(s, v);
@@ -353,9 +389,9 @@ ngx_rtmp_play_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
(ngx_int_t) v->pause, v->position);
if (v->pause) {
- ngx_rtmp_play_stop(s);
+ ngx_rtmp_play_do_stop(s);
} else {
- ngx_rtmp_play_start(s, v->position);
+ ngx_rtmp_play_do_start(s); /*TODO: v->position? */
}
next:
@@ -534,11 +570,15 @@ ngx_rtmp_play_open(ngx_rtmp_session_t *s, double start)
ngx_rtmp_send_user_recorded(s, 1);
- if (ngx_rtmp_play_init(s) != NGX_OK) {
+ if (ngx_rtmp_play_do_init(s) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_rtmp_play_do_seek(s, start < 0 ? 0 : start) != NGX_OK) {
return NGX_ERROR;
}
- if (ngx_rtmp_play_start(s, start) != NGX_OK) {
+ if (ngx_rtmp_play_do_start(s) != NGX_OK) {
return NGX_ERROR;
}
@@ -553,7 +593,6 @@ ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
ngx_rtmp_play_app_conf_t *pacf;
ngx_rtmp_play_ctx_t *ctx;
- ngx_chain_t *hl;
ngx_str_t *addr_text, uri;
u_char *p;
size_t args_len, len;
@@ -585,7 +624,8 @@ ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
p = ngx_cpymem(p, ctx->name.data, ctx->name.len);
p = ngx_cpymem(p, (u_char*)"?addr=", sizeof("&addr=") -1);
- p = (u_char*)ngx_escape_uri(p, addr_text->data, addr_text->len, 0);
+ p = (u_char*)ngx_escape_uri(p, addr_text->data, addr_text->len,
+ NGX_ESCAPE_ARGS);
if (args_len) {
*p++ = '&';
p = (u_char *) ngx_cpymem(p, v->args, args_len);
@@ -593,15 +633,9 @@ ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
uri.len = p - uri.data;
- /* HTTP header */
- hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_GET,
- &uri, &pacf->url->host, pool, 0, &text_plain);
-
- if (hl == NULL) {
- return NULL;
- }
-
- return hl;
+ return ngx_rtmp_netcall_http_format_request(NGX_RTMP_NETCALL_HTTP_GET,
+ &pacf->url->host, &uri,
+ NULL, NULL, pool, &text_plain);
}
6 ngx_rtmp_play_module.h
View
@@ -15,11 +15,13 @@ typedef ngx_int_t (*ngx_rtmp_play_init_pt) (ngx_rtmp_session_t *s,
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,
+ ngx_file_t *f);
+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);
typedef ngx_int_t (*ngx_rtmp_play_send_pt) (ngx_rtmp_session_t *s,
- ngx_file_t *f);
+ ngx_file_t *f, ngx_uint_t *ts);
typedef struct {
@@ -30,6 +32,7 @@ typedef struct {
ngx_rtmp_play_init_pt init;
ngx_rtmp_play_done_pt done;
ngx_rtmp_play_start_pt start;
+ ngx_rtmp_play_seek_pt seek;
ngx_rtmp_play_stop_pt stop;
ngx_rtmp_play_send_pt send;
} ngx_rtmp_play_fmt_t;
@@ -39,6 +42,7 @@ typedef struct {
ngx_file_t file;
ngx_rtmp_play_fmt_t *fmt;
ngx_event_t send_evt;
+ unsigned playing:1;
ngx_uint_t ncrs;
ngx_str_t name;
} ngx_rtmp_play_ctx_t;
1  ngx_rtmp_send.c
View
@@ -399,6 +399,7 @@ ngx_rtmp_send_play_status(ngx_rtmp_session_t *s, char *code, char* level,
h.type = NGX_RTMP_MSG_AMF_META;
h.csid = NGX_RTMP_CSID_AMF;
h.msid = NGX_RTMP_MSID;
+ h.timestamp = duration;
return ngx_rtmp_send_amf(s, &h, out_elts,
sizeof(out_elts) / sizeof(out_elts[0]));
45 ngx_rtmp_stat_module.c
View
@@ -100,6 +100,44 @@ ngx_module_t ngx_rtmp_stat_module = {
#define NGX_RTMP_STAT_BUFSIZE 256
+/* ngx_escape_html does not escape characters out of ASCII range
+ * which are bad for xslt */
+
+static void *
+ngx_rtmp_stat_escape(ngx_http_request_t *r, void *data, size_t len)
+{
+ u_char *p, *np;
+ void *new_data;
+ size_t n;
+
+ p = data;
+
+ for (n = 0; n < len; ++n, ++p) {
+ if (*p < 0x20 || *p >= 0x7f) {
+ break;
+ }
+ }
+
+ if (n == len) {
+ return data;
+ }
+
+ new_data = ngx_palloc(r->pool, len);
+ if (new_data == NULL) {
+ return NULL;
+ }
+
+ p = data;
+ np = new_data;
+
+ for (n = 0; n < len; ++n, ++p, ++np) {
+ *np = (*p < 0x20 || *p >= 0x7f) ? (u_char) ' ' : *p;
+ }
+
+ return new_data;
+}
+
+
static void
ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll,
void *data, size_t len, ngx_uint_t escape)
@@ -112,6 +150,13 @@ ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll,
return;
}
+ if (escape) {
+ data = ngx_rtmp_stat_escape(r, data, len);
+ if (data == NULL) {
+ return;