Skip to content
This repository
  • 14 commits
  • 11 files changed
  • 0 comments
  • 1 contributor
118 ngx_rtmp_cmd_module.c
@@ -1003,71 +1003,17 @@ ngx_rtmp_cmd_pause_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
1003 1003 static ngx_int_t
1004 1004 ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v)
1005 1005 {
1006   - ngx_rtmp_header_t h;
1007   -
1008   - static double trans;
1009   -
1010   - static ngx_rtmp_amf_elt_t out_inf[] = {
1011   -
1012   - { NGX_RTMP_AMF_STRING,
1013   - ngx_string("code"),
1014   - "NetStream.Pause.Notify", 0 },
1015   -
1016   - { NGX_RTMP_AMF_STRING,
1017   - ngx_string("level"),
1018   - "status", 0 },
1019   -
1020   - { NGX_RTMP_AMF_STRING,
1021   - ngx_string("description"),
1022   - "Paused.", 0 },
1023   - };
1024   -
1025   - static ngx_rtmp_amf_elt_t out_elts[] = {
1026   -
1027   - { NGX_RTMP_AMF_STRING,
1028   - ngx_null_string,
1029   - "onStatus", 0 },
1030   -
1031   - { NGX_RTMP_AMF_NUMBER,
1032   - ngx_null_string,
1033   - &trans, 0 },
1034   -
1035   - { NGX_RTMP_AMF_NULL,
1036   - ngx_null_string,
1037   - NULL, 0 },
1038   -
1039   - { NGX_RTMP_AMF_OBJECT,
1040   - ngx_null_string,
1041   - out_inf, sizeof(out_inf) },
1042   - };
1043   -
1044 1006 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
1045   - "pause: state='%i' position=%i",
1046   - v->pause, (ngx_int_t) v->position);
1047   -
1048   - /* send onStatus reply */
1049   - ngx_memzero(&h, sizeof(h));
1050   - h.type = NGX_RTMP_MSG_AMF_CMD;
1051   - h.csid = NGX_RTMP_CSID_AMF;
1052   - h.msid = NGX_RTMP_MSID;
  1007 + "pause: state='%i' position=%i",
  1008 + v->pause, (ngx_int_t) v->position);
1053 1009
1054 1010 if (v->pause) {
1055   - out_inf[0].data = "NetStream.Pause.Notify";
1056   - out_inf[2].data = "Paused.";
1057   - return ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_MSID) != NGX_OK
1058   - || ngx_rtmp_send_amf(s, &h, out_elts,
1059   - sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
1060   - ? NGX_ERROR
1061   - : NGX_OK;
  1011 + return ngx_rtmp_send_status(s, "NetStream.Pause.Notify", "status",
  1012 + "Paused");
  1013 + } else {
  1014 + return ngx_rtmp_send_status(s, "NetStream.Unpause.Notify", "status",
  1015 + "Unpaused");
1062 1016 }
1063   -
1064   - out_inf[0].data = "NetStream.Unpause.Notify";
1065   - out_inf[2].data = "Unpaused.";
1066   - return ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_MSID) != NGX_OK
1067   - || ngx_rtmp_send_amf(s, &h, out_elts,
1068   - sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
1069   - ? NGX_ERROR
1070   - : NGX_OK;
1071 1017 }
1072 1018
1073 1019
@@ -1124,57 +1070,13 @@ ngx_rtmp_cmd_seek_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
1124 1070 static ngx_int_t
1125 1071 ngx_rtmp_cmd_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v)
1126 1072 {
1127   - ngx_rtmp_header_t h;
1128   -
1129   - static double trans;
1130   -
1131   - static ngx_rtmp_amf_elt_t out_inf[] = {
1132   -
1133   - { NGX_RTMP_AMF_STRING,
1134   - ngx_string("code"),
1135   - "NetStream.Play.Reset", 0 },
1136   -
1137   - { NGX_RTMP_AMF_STRING,
1138   - ngx_string("level"),
1139   - "status", 0 },
1140   -
1141   - { NGX_RTMP_AMF_STRING,
1142   - ngx_string("description"),
1143   - "Paused.", 0 },
1144   - };
1145   -
1146   - static ngx_rtmp_amf_elt_t out_elts[] = {
1147   -
1148   - { NGX_RTMP_AMF_STRING,
1149   - ngx_null_string,
1150   - "onStatus", 0 },
1151   -
1152   - { NGX_RTMP_AMF_NUMBER,
1153   - ngx_null_string,
1154   - &trans, 0 },
1155   -
1156   - { NGX_RTMP_AMF_NULL,
1157   - ngx_null_string,
1158   - NULL, 0 },
1159   -
1160   - { NGX_RTMP_AMF_OBJECT,
1161   - ngx_null_string,
1162   - out_inf, sizeof(out_inf) },
1163   - };
1164   -
1165 1073 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
1166   - "seek: offset=%i", (ngx_int_t) v->offset);
1167   -
1168   - /* send onStatus reply */
1169   - ngx_memzero(&h, sizeof(h));
1170   - h.type = NGX_RTMP_MSG_AMF_CMD;
1171   - h.csid = NGX_RTMP_CSID_AMF;
1172   - h.msid = NGX_RTMP_MSID;
  1074 + "seek: offset=%i", (ngx_int_t) v->offset);
1173 1075
1174 1076 return (ngx_rtmp_send_user_stream_eof(s, NGX_RTMP_MSID) != NGX_OK
1175 1077 || ngx_rtmp_send_user_stream_begin(s, NGX_RTMP_MSID) != NGX_OK
1176   - || ngx_rtmp_send_amf(s, &h, out_elts,
1177   - sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK)
  1078 + || ngx_rtmp_send_status(s, "NetStream.Seek.Notify", "status",
  1079 + "Seeking"))
1178 1080 ? NGX_ERROR
1179 1081 : NGX_OK;
1180 1082 }
39 ngx_rtmp_flv_module.c
@@ -13,10 +13,12 @@ static void ngx_rtmp_flv_read_meta(ngx_rtmp_session_t *s, ngx_file_t *f);
13 13 static ngx_int_t ngx_rtmp_flv_timestamp_to_offset(ngx_rtmp_session_t *s,
14 14 ngx_file_t *f, ngx_int_t timestamp);
15 15 static ngx_int_t ngx_rtmp_flv_init(ngx_rtmp_session_t *s, ngx_file_t *f);
16   -static ngx_int_t ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f,
  16 +static ngx_int_t ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f);
  17 +static ngx_int_t ngx_rtmp_flv_seek(ngx_rtmp_session_t *s, ngx_file_t *f,
17 18 ngx_uint_t offset);
18 19 static ngx_int_t ngx_rtmp_flv_stop(ngx_rtmp_session_t *s, ngx_file_t *f);
19   -static ngx_int_t ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f);
  20 +static ngx_int_t ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f,
  21 + ngx_uint_t *ts);
20 22
21 23
22 24 typedef struct {
@@ -42,6 +44,7 @@ typedef struct {
42 44
43 45 #define NGX_RTMP_FLV_BUFFER (1024*1024)
44 46 #define NGX_RTMP_FLV_DEFAULT_BUFLEN 1000
  47 +#define NGX_RTMP_FLV_BUFLEN_ADDON 1000
45 48 #define NGX_RTMP_FLV_TAG_HEADER 11
46 49 #define NGX_RTMP_FLV_DATA_OFFSET 13
47 50
@@ -389,7 +392,7 @@ ngx_rtmp_flv_read_meta(ngx_rtmp_session_t *s, ngx_file_t *f)
389 392
390 393
391 394 static ngx_int_t
392   -ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f)
  395 +ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t *ts)
393 396 {
394 397 ngx_rtmp_flv_ctx_t *ctx;
395 398 uint32_t last_timestamp;
@@ -524,7 +527,8 @@ ngx_rtmp_flv_send(ngx_rtmp_session_t *s, ngx_file_t *f)
524 527 return NGX_OK;
525 528 }
526 529
527   - buflen = (s->buflen ? s->buflen : NGX_RTMP_FLV_DEFAULT_BUFLEN);
  530 + buflen = (s->buflen ? s->buflen + NGX_RTMP_FLV_BUFLEN_ADDON:
  531 + NGX_RTMP_FLV_DEFAULT_BUFLEN);
528 532 end_timestamp = (ngx_current_msec - ctx->epoch) +
529 533 ctx->start_timestamp + buflen;
530 534
@@ -567,7 +571,28 @@ ngx_rtmp_flv_init(ngx_rtmp_session_t *s, ngx_file_t *f)
567 571
568 572
569 573 static ngx_int_t
570   -ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
  574 +ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f)
  575 +{
  576 + ngx_rtmp_flv_ctx_t *ctx;
  577 +
  578 + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_flv_module);
  579 +
  580 + if (ctx == NULL) {
  581 + return NGX_OK;
  582 + }
  583 +
  584 + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
  585 + "flv: start");
  586 +
  587 + ctx->offset = -1;
  588 + ctx->msg_mask = 0;
  589 +
  590 + return NGX_OK;
  591 +}
  592 +
  593 +
  594 +static ngx_int_t
  595 +ngx_rtmp_flv_seek(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
571 596 {
572 597 ngx_rtmp_flv_ctx_t *ctx;
573 598
@@ -578,9 +603,10 @@ ngx_rtmp_flv_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
578 603 }
579 604
580 605 ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
581   - "flv: start timestamp=%ui", timestamp);
  606 + "flv: seek timestamp=%ui", timestamp);
582 607
583 608 ctx->start_timestamp = timestamp;
  609 + ctx->epoch = ngx_current_msec;
584 610 ctx->offset = -1;
585 611 ctx->msg_mask = 0;
586 612
@@ -635,6 +661,7 @@ ngx_rtmp_flv_postconfiguration(ngx_conf_t *cf)
635 661
636 662 fmt->init = ngx_rtmp_flv_init;
637 663 fmt->start = ngx_rtmp_flv_start;
  664 + fmt->seek = ngx_rtmp_flv_seek;
638 665 fmt->stop = ngx_rtmp_flv_stop;
639 666 fmt->send = ngx_rtmp_flv_send;
640 667
22 ngx_rtmp_live_module.c
@@ -202,18 +202,20 @@ ngx_rtmp_live_join(ngx_rtmp_session_t *s, u_char *name,
202 202 }
203 203
204 204 ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module);
205   - if (ctx == NULL) {
206   - ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_live_ctx_t));
207   - ctx->session = s;
208   - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_live_module);
209   - }
210   -
211   - if (ctx->stream) {
  205 + if (ctx && ctx->stream) {
212 206 ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log,
213 207 0, "live: already joined");
214 208 return;
215 209 }
216 210
  211 + if (ctx == NULL) {
  212 + ctx = ngx_palloc(s->connection->pool, sizeof(ngx_rtmp_live_ctx_t));
  213 + ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_live_module);
  214 + }
  215 +
  216 + ngx_memzero(ctx, sizeof(*ctx));
  217 + ctx->session = s;
  218 +
217 219 ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
218 220 "live: join '%s'", name);
219 221
@@ -378,6 +380,12 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
378 380 ctx->last_audio = ch.timestamp;
379 381 last_offset = offsetof(ngx_rtmp_live_ctx_t, last_audio);
380 382 }
  383 +
  384 + if ((ctx->msg_mask & (1 << h->type)) == 0) {
  385 + lh.timestamp = ch.timestamp;
  386 + ctx->msg_mask |= (1 << h->type);
  387 + }
  388 +
381 389 lh.csid = ch.csid;
382 390 diff_timestamp = ch.timestamp - lh.timestamp;
383 391
157 ngx_rtmp_mp4_module.c
@@ -9,12 +9,15 @@
9 9
10 10
11 11 static ngx_int_t ngx_rtmp_mp4_postconfiguration(ngx_conf_t *cf);
12   -static ngx_int_t ngx_rtmp_mp4_init(ngx_rtmp_session_t *s, ngx_file_t *f);
13   -static ngx_int_t ngx_rtmp_mp4_done(ngx_rtmp_session_t *s, ngx_file_t *f);
14   -static ngx_int_t ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f,
15   - ngx_uint_t offset);
16   -static ngx_int_t ngx_rtmp_mp4_stop(ngx_rtmp_session_t *s, ngx_file_t *f);
17   -static ngx_int_t ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f);
  12 +static ngx_int_t ngx_rtmp_mp4_init(ngx_rtmp_session_t *s, ngx_file_t *f);
  13 +static ngx_int_t ngx_rtmp_mp4_done(ngx_rtmp_session_t *s, ngx_file_t *f);
  14 +static ngx_int_t ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f);
  15 +static ngx_int_t ngx_rtmp_mp4_seek(ngx_rtmp_session_t *s, ngx_file_t *f,
  16 + ngx_uint_t offset);
  17 +static ngx_int_t ngx_rtmp_mp4_stop(ngx_rtmp_session_t *s, ngx_file_t *f);
  18 +static ngx_int_t ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f,
  19 + ngx_uint_t *ts);
  20 +static ngx_int_t ngx_rtmp_mp4_reset(ngx_rtmp_session_t *s);
18 21
19 22
20 23 #pragma pack(push,4)
@@ -193,6 +196,7 @@ ngx_rtmp_mp4_from_rtmp_timestamp(ngx_rtmp_mp4_track_t *t, uint32_t ts)
193 196
194 197
195 198 #define NGX_RTMP_MP4_DEFAULT_BUFLEN 1000
  199 +#define NGX_RTMP_MP4_BUFLEN_ADDON 1000
196 200
197 201
198 202 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)
876 880
877 881 t->chunks = (ngx_rtmp_mp4_chunks_t *) pos;
878 882
879   - if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->times->entry_count) *
  883 + if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->chunks->entry_count) *
880 884 sizeof(t->chunks->entries[0])
881 885 <= last)
882 886 {
@@ -1236,7 +1240,8 @@ ngx_rtmp_mp4_seek_time(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t,
1236 1240 return NGX_ERROR;
1237 1241 }
1238 1242
1239   - cr->time_count = (timestamp - cr->timestamp) / ngx_rtmp_r32(te->sample_delta);
  1243 + cr->time_count = (timestamp - cr->timestamp) /
  1244 + ngx_rtmp_r32(te->sample_delta);
1240 1245 cr->timestamp += ngx_rtmp_r32(te->sample_delta) * cr->time_count;
1241 1246 cr->pos += cr->time_count;
1242 1247
@@ -1519,13 +1524,20 @@ static ngx_int_t
1519 1524 ngx_rtmp_mp4_seek_size(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
1520 1525 {
1521 1526 ngx_rtmp_mp4_cursor_t *cr;
  1527 + ngx_uint_t pos;
1522 1528
1523 1529 cr = &t->cursor;
1524 1530
  1531 + if (cr->chunk_count > cr->pos) {
  1532 + return NGX_ERROR;
  1533 + }
  1534 +
1525 1535 if (t->sizes) {
1526 1536 if (t->sizes->sample_size) {
1527 1537 cr->size = ngx_rtmp_r32(t->sizes->sample_size);
1528 1538
  1539 + cr->offset += cr->size * cr->chunk_count;
  1540 +
1529 1541 ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
1530 1542 "mp4: track#%ui seek size fix=%uz",
1531 1543 t->id, cr->size);
@@ -1542,6 +1554,10 @@ ngx_rtmp_mp4_seek_size(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
1542 1554 return NGX_ERROR;
1543 1555 }
1544 1556
  1557 + for (pos = 1; pos <= cr->chunk_count; ++pos) {
  1558 + cr->offset += ngx_rtmp_r32(t->sizes->entries[cr->pos - pos]);
  1559 + }
  1560 +
1545 1561 cr->size_pos = cr->pos;
1546 1562 cr->size = ngx_rtmp_r32(t->sizes->entries[cr->size_pos]);
1547 1563
@@ -1620,6 +1636,7 @@ ngx_rtmp_mp4_seek_key(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
1620 1636 {
1621 1637 ngx_rtmp_mp4_cursor_t *cr;
1622 1638 uint32_t *ke;
  1639 + ngx_int_t dpos;
1623 1640
1624 1641 cr = &t->cursor;
1625 1642
@@ -1628,7 +1645,7 @@ ngx_rtmp_mp4_seek_key(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
1628 1645 }
1629 1646
1630 1647 while (cr->key_pos < ngx_rtmp_r32(t->keys->entry_count)) {
1631   - if (ngx_rtmp_r32(t->keys->entries[cr->key_pos]) >= cr->pos) {
  1648 + if (ngx_rtmp_r32(t->keys->entries[cr->key_pos]) > cr->pos) {
1632 1649 break;
1633 1650 }
1634 1651
@@ -1644,7 +1661,18 @@ ngx_rtmp_mp4_seek_key(ngx_rtmp_session_t *s, ngx_rtmp_mp4_track_t *t)
1644 1661 }
1645 1662
1646 1663 ke = &t->keys->entries[cr->key_pos];
1647   - cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));
  1664 + /*cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));*/
  1665 +
  1666 + /* distance to the next keyframe */
  1667 + dpos = ngx_rtmp_r32(*ke) - cr->pos - 1;
  1668 + cr->key = 1;
  1669 +
  1670 + /* TODO: range version needed */
  1671 + for (; dpos > 0; --dpos) {
  1672 + ngx_rtmp_mp4_next_time(s, t);
  1673 + }
  1674 +
  1675 +/* cr->key = (cr->pos + 1 == ngx_rtmp_r32(*ke));*/
1648 1676
1649 1677 ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
1650 1678 "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,
1921 1949
1922 1950
1923 1951 static ngx_int_t
1924   -ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f)
  1952 +ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t *ts)
1925 1953 {
1926 1954 ngx_rtmp_mp4_ctx_t *ctx;
1927 1955 ngx_buf_t in_buf;
@@ -1956,12 +1984,14 @@ ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f)
1956 1984 return rc;
1957 1985 }
1958 1986
1959   - buflen = (s->buflen ? s->buflen : NGX_RTMP_MP4_DEFAULT_BUFLEN);
  1987 + buflen = (s->buflen ? s->buflen + NGX_RTMP_MP4_BUFLEN_ADDON:
  1988 + NGX_RTMP_MP4_DEFAULT_BUFLEN);
1960 1989
1961 1990 t = ctx->tracks;
1962 1991
1963 1992 sched = 0;
1964 1993 active = 0;
  1994 + last_timestamp = 0;
1965 1995
1966 1996 end_timestamp = ctx->start_timestamp +
1967 1997 (ngx_current_msec - ctx->epoch) + buflen;
@@ -2123,7 +2153,17 @@ ngx_rtmp_mp4_send(ngx_rtmp_session_t *s, ngx_file_t *f)
2123 2153 return sched;
2124 2154 }
2125 2155
2126   - return active ? NGX_OK : NGX_DONE;
  2156 + if (active) {
  2157 + return NGX_OK;
  2158 + }
  2159 +
  2160 + if (ts) {
  2161 + *ts = last_timestamp;
  2162 + }
  2163 +
  2164 + /*ngx_rtmp_mp4_reset(s);*/
  2165 +
  2166 + return NGX_DONE;
2127 2167 }
2128 2168
2129 2169
@@ -2227,9 +2267,10 @@ ngx_rtmp_mp4_done(ngx_rtmp_session_t *s, ngx_file_t *f)
2227 2267
2228 2268
2229 2269 static ngx_int_t
2230   -ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
  2270 +ngx_rtmp_mp4_seek(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
2231 2271 {
2232 2272 ngx_rtmp_mp4_ctx_t *ctx;
  2273 + ngx_rtmp_mp4_track_t *t;
2233 2274 ngx_uint_t n;
2234 2275
2235 2276 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)
2239 2280 }
2240 2281
2241 2282 ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
2242   - "mp4: start timestamp=%ui", timestamp);
  2283 + "mp4: seek timestamp=%ui", timestamp);
  2284 +
  2285 + for (n = 0; n < ctx->ntracks; ++n) {
  2286 + t = &ctx->tracks[n];
  2287 +
  2288 + if (t->type != NGX_RTMP_MSG_VIDEO) {
  2289 + continue;
  2290 + }
  2291 +
  2292 + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
  2293 + "mp4: track#%ui seek video", n);
  2294 +
  2295 + ngx_rtmp_mp4_seek_track(s, t, timestamp);
  2296 +
  2297 + timestamp = ngx_rtmp_mp4_to_rtmp_timestamp(t, t->cursor.timestamp);
  2298 +
  2299 + break;
  2300 + }
2243 2301
2244 2302 for (n = 0; n < ctx->ntracks; ++n) {
  2303 + t = &ctx->tracks[n];
  2304 +
  2305 + if (t->type == NGX_RTMP_MSG_VIDEO) {
  2306 + continue;
  2307 + }
  2308 +
2245 2309 ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
2246 2310 "mp4: track#%ui seek", n);
2247 2311
2248 2312 ngx_rtmp_mp4_seek_track(s, &ctx->tracks[n], timestamp);
2249 2313 }
2250 2314
2251   - ctx->epoch = ngx_current_msec;
2252 2315 ctx->start_timestamp = timestamp;
  2316 + ctx->epoch = ngx_current_msec;
  2317 +
  2318 + return ngx_rtmp_mp4_reset(s);
  2319 +}
  2320 +
  2321 +
  2322 +static ngx_int_t
  2323 +ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f)
  2324 +{
  2325 + ngx_rtmp_mp4_ctx_t *ctx;
  2326 +
  2327 + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
  2328 +
  2329 + if (ctx == NULL) {
  2330 + return NGX_OK;
  2331 + }
  2332 +
  2333 + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
  2334 + "mp4: start timestamp=%uD", ctx->start_timestamp);
  2335 +
  2336 + ctx->epoch = ngx_current_msec;
  2337 +
  2338 + return NGX_OK;/*ngx_rtmp_mp4_reset(s);*/
  2339 +}
  2340 +
  2341 +
  2342 +static ngx_int_t
  2343 +ngx_rtmp_mp4_reset(ngx_rtmp_session_t *s)
  2344 +{
  2345 + ngx_rtmp_mp4_ctx_t *ctx;
  2346 + ngx_rtmp_mp4_cursor_t *cr;
  2347 + ngx_rtmp_mp4_track_t *t;
  2348 + ngx_uint_t n;
  2349 +
  2350 + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
  2351 +
  2352 + if (ctx == NULL) {
  2353 + return NGX_OK;
  2354 + }
  2355 +
  2356 + t = &ctx->tracks[0];
  2357 + for (n = 0; n < ctx->ntracks; ++n, ++t) {
  2358 + cr = &t->cursor;
  2359 + cr->not_first = 0;
  2360 + }
2253 2361
2254 2362 return NGX_OK;
2255 2363 }
@@ -2258,10 +2366,20 @@ ngx_rtmp_mp4_start(ngx_rtmp_session_t *s, ngx_file_t *f, ngx_uint_t timestamp)
2258 2366 static ngx_int_t
2259 2367 ngx_rtmp_mp4_stop(ngx_rtmp_session_t *s, ngx_file_t *f)
2260 2368 {
2261   - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
2262   - "mp4: stop");
  2369 + ngx_rtmp_mp4_ctx_t *ctx;
2263 2370
2264   - return NGX_OK;
  2371 + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_mp4_module);
  2372 +
  2373 + if (ctx == NULL) {
  2374 + return NGX_OK;
  2375 + }
  2376 +
  2377 + ctx->start_timestamp += (ngx_current_msec - ctx->epoch);
  2378 +
  2379 + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
  2380 + "mp4: stop timestamp=%uD", ctx->start_timestamp);
  2381 +
  2382 + return NGX_OK;/*ngx_rtmp_mp4_reset(s);*/
2265 2383 }
2266 2384
2267 2385
@@ -2294,6 +2412,7 @@ ngx_rtmp_mp4_postconfiguration(ngx_conf_t *cf)
2294 2412
2295 2413 fmt->init = ngx_rtmp_mp4_init;
2296 2414 fmt->done = ngx_rtmp_mp4_done;
  2415 + fmt->seek = ngx_rtmp_mp4_seek;
2297 2416 fmt->start = ngx_rtmp_mp4_start;
2298 2417 fmt->stop = ngx_rtmp_mp4_stop;
2299 2418 fmt->send = ngx_rtmp_mp4_send;
150 ngx_rtmp_netcall_module.c
@@ -55,14 +55,14 @@ static ngx_command_t ngx_rtmp_netcall_commands[] = {
55 55 { ngx_string("netcall_timeout"),
56 56 NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
57 57 ngx_conf_set_msec_slot,
58   - NGX_RTMP_SRV_CONF_OFFSET,
  58 + NGX_RTMP_APP_CONF_OFFSET,
59 59 offsetof(ngx_rtmp_netcall_app_conf_t, timeout),
60 60 NULL },
61 61
62 62 { ngx_string("netcall_buffer"),
63 63 NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
64 64 ngx_conf_set_size_slot,
65   - NGX_RTMP_SRV_CONF_OFFSET,
  65 + NGX_RTMP_APP_CONF_OFFSET,
66 66 offsetof(ngx_rtmp_netcall_app_conf_t, bufsize),
67 67 NULL },
68 68
@@ -491,58 +491,76 @@ ngx_rtmp_netcall_send(ngx_event_t *wev)
491 491
492 492
493 493 ngx_chain_t *
494   -ngx_rtmp_netcall_http_format_header(ngx_int_t method, ngx_str_t *uri,
495   - ngx_str_t *host, ngx_pool_t *pool,
496   - size_t content_length,
497   - ngx_str_t *content_type)
  494 +ngx_rtmp_netcall_http_format_request(ngx_int_t method, ngx_str_t *host,
  495 + ngx_str_t *uri, ngx_chain_t *args,
  496 + ngx_chain_t *body, ngx_pool_t *pool,
  497 + ngx_str_t *content_type)
498 498 {
499   - ngx_chain_t *cl;
  499 + ngx_chain_t *al, *bl, *ret;
500 500 ngx_buf_t *b;
501   - const char *method_s;
  501 + size_t content_length;
  502 + static const char *methods[2] = { "GET", "POST" };
  503 + static const char rq_tmpl[] = " HTTP/1.0\r\n"
  504 + "Host: %V\r\n"
  505 + "Content-Type: %V\r\n"
  506 + "Connection: Close\r\n"
  507 + "Content-Length: %uz\r\n"
  508 + "\r\n";
502 509
503   - static char rq_tmpl[] =
504   - "%s %V HTTP/1.0\r\n"
505   - "Host: %V\r\n"
506   - "Content-Type: %V\r\n"
507   - "Connection: Close\r\n"
508   - "Content-Length: %uz\r\n"
509   - "\r\n"
510   - ;
  510 + content_length = 0;
  511 + for (al = body; al; al = al->next) {
  512 + b = al->buf;
  513 + content_length += (b->last - b->pos);
  514 + }
511 515
512   - cl = ngx_alloc_chain_link(pool);
513   - if (cl == NULL) {
  516 + /* create first buffer */
  517 +
  518 + al = ngx_alloc_chain_link(pool);
  519 + if (al == NULL) {
514 520 return NULL;
515 521 }
516   -
517   - b = ngx_create_temp_buf(pool, sizeof(rq_tmpl)
518   - + sizeof("POST") - 1 /* longest method */
519   - + uri->len
520   - + host->len
521   - + content_type->len
522   - + 5);
523 522
  523 + b = ngx_create_temp_buf(pool, sizeof("POST") + /* longest method + 1 */
  524 + uri->len);
524 525 if (b == NULL) {
525 526 return NULL;
526 527 }
527 528
528   - cl->buf = b;
529   - cl->next = NULL;
  529 + b->last = ngx_snprintf(b->last, b->end - b->last, "%s %V",
  530 + methods[method], uri);
  531 +
  532 + al->buf = b;
530 533
531   - switch (method) {
532   - case NGX_RTMP_NETCALL_HTTP_GET:
533   - method_s = "GET";
534   - break;
535   - case NGX_RTMP_NETCALL_HTTP_POST:
536   - method_s = "POST";
537   - break;
538   - default:
539   - return NULL;
  534 + ret = al;
  535 +
  536 + if (args) {
  537 + *b->last++ = '?';
  538 + al->next = args;
  539 + for (al = args; al->next; al = al->next);
540 540 }
541 541
  542 + /* create second buffer */
  543 +
  544 + bl = ngx_alloc_chain_link(pool);
  545 + if (bl == NULL) {
  546 + return NULL;
  547 + }
  548 +
  549 + b = ngx_create_temp_buf(pool, sizeof(rq_tmpl) + host->len +
  550 + content_type->len + NGX_OFF_T_LEN);
  551 + if (b == NULL) {
  552 + return NULL;
  553 + }
  554 +
  555 + bl->buf = b;
  556 +
542 557 b->last = ngx_snprintf(b->last, b->end - b->last, rq_tmpl,
543   - method_s, uri, host, content_type, content_length);
  558 + host, content_type, content_length);
544 559
545   - return cl;
  560 + al->next = bl;
  561 + bl->next = body;
  562 +
  563 + return ret;
546 564 }
547 565
548 566
@@ -551,6 +569,9 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
551 569 {
552 570 ngx_chain_t *cl;
553 571 ngx_buf_t *b;
  572 + ngx_str_t *addr_text;
  573 +
  574 + addr_text = &s->connection->addr_text;
554 575
555 576 cl = ngx_alloc_chain_link(pool);
556 577 if (cl == NULL) {
@@ -562,7 +583,8 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
562 583 sizeof("&flashver=") - 1 + s->flashver.len * 3 +
563 584 sizeof("&swfurl=") - 1 + s->swf_url.len * 3 +
564 585 sizeof("&tcurl=") - 1 + s->tc_url.len * 3 +
565   - sizeof("&pageurl=") - 1 + s->page_url.len * 3
  586 + sizeof("&pageurl=") - 1 + s->page_url.len * 3 +
  587 + sizeof("&addr=") - 1 + addr_text->len * 3
566 588 );
567 589
568 590 if (b == NULL) {
@@ -570,29 +592,35 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
570 592 }
571 593
572 594 cl->buf = b;
  595 + cl->next = NULL;
573 596
574   - b->last = ngx_cpymem(b->last, (u_char*)"app=", sizeof("app=") - 1);
575   - b->last = (u_char*)ngx_escape_uri(b->last, s->app.data, s->app.len, 0);
576   -
577   - b->last = ngx_cpymem(b->last, (u_char*)"&flashver=",
578   - sizeof("&flashver=") - 1);
579   - b->last = (u_char*)ngx_escape_uri(b->last, s->flashver.data,
580   - s->flashver.len, 0);
581   -
582   - b->last = ngx_cpymem(b->last, (u_char*)"&swfurl=",
583   - sizeof("&swfurl=") - 1);
584   - b->last = (u_char*)ngx_escape_uri(b->last, s->swf_url.data,
585   - s->swf_url.len, 0);
586   -
587   - b->last = ngx_cpymem(b->last, (u_char*)"&tcurl=",
588   - sizeof("&tcurl=") - 1);
589   - b->last = (u_char*)ngx_escape_uri(b->last, s->tc_url.data,
590   - s->tc_url.len, 0);
591   -
592   - b->last = ngx_cpymem(b->last, (u_char*)"&pageurl=",
593   - sizeof("&pageurl=") - 1);
594   - b->last = (u_char*)ngx_escape_uri(b->last, s->page_url.data,
595   - s->page_url.len, 0);
  597 + b->last = ngx_cpymem(b->last, (u_char*) "app=", sizeof("app=") - 1);
  598 + b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
  599 + NGX_ESCAPE_ARGS);
  600 +
  601 + b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
  602 + sizeof("&flashver=") - 1);
  603 + b->last = (u_char*) ngx_escape_uri(b->last, s->flashver.data,
  604 + s->flashver.len, NGX_ESCAPE_ARGS);
  605 +
  606 + b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
  607 + sizeof("&swfurl=") - 1);
  608 + b->last = (u_char*) ngx_escape_uri(b->last, s->swf_url.data,
  609 + s->swf_url.len, NGX_ESCAPE_ARGS);
  610 +
  611 + b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
  612 + sizeof("&tcurl=") - 1);
  613 + b->last = (u_char*) ngx_escape_uri(b->last, s->tc_url.data,
  614 + s->tc_url.len, NGX_ESCAPE_ARGS);
  615 +
  616 + b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
  617 + sizeof("&pageurl=") - 1);
  618 + b->last = (u_char*) ngx_escape_uri(b->last, s->page_url.data,
  619 + s->page_url.len, NGX_ESCAPE_ARGS);
  620 +
  621 + b->last = ngx_cpymem(b->last, (u_char*) "&addr=", sizeof("&addr=") -1);
  622 + b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
  623 + addr_text->len, NGX_ESCAPE_ARGS);
596 624
597 625 return cl;
598 626 }
10 ngx_rtmp_netcall_module.h
@@ -20,8 +20,8 @@ typedef ngx_int_t (*ngx_rtmp_netcall_sink_pt)(ngx_rtmp_session_t *s,
20 20 typedef ngx_int_t (*ngx_rtmp_netcall_handle_pt)(ngx_rtmp_session_t *s,
21 21 void *arg, ngx_chain_t *in);
22 22
23   -#define NGX_RTMP_NETCALL_HTTP_GET 1
24   -#define NGX_RTMP_NETCALL_HTTP_POST 2
  23 +#define NGX_RTMP_NETCALL_HTTP_GET 0
  24 +#define NGX_RTMP_NETCALL_HTTP_POST 1
25 25
26 26
27 27 /* 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,
51 51 /* HTTP handling */
52 52 ngx_chain_t * ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s,
53 53 ngx_pool_t *pool);
54   -ngx_chain_t * ngx_rtmp_netcall_http_format_header(ngx_int_t method,
55   - ngx_str_t *uri, ngx_str_t *host, ngx_pool_t *pool,
56   - size_t content_length, ngx_str_t *content_type);
  54 +ngx_chain_t * ngx_rtmp_netcall_http_format_request(ngx_int_t method,
  55 + ngx_str_t *host, ngx_str_t *uri, ngx_chain_t *args, ngx_chain_t *body,
  56 + ngx_pool_t *pool, ngx_str_t *content_type);
57 57 ngx_chain_t * ngx_rtmp_netcall_http_skip_header(ngx_chain_t *in);
58 58
59 59
321 ngx_rtmp_notify_module.c
@@ -20,6 +20,8 @@ static ngx_rtmp_record_done_pt next_record_done;
20 20
21 21 static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
22 22 void *conf);
  23 +static char *ngx_rtmp_notify_method(ngx_conf_t *cf, ngx_command_t *cmd,
  24 + void *conf);
23 25 static ngx_int_t ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf);
24 26 static void * ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf);
25 27 static char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
@@ -50,6 +52,7 @@ enum {
50 52 typedef struct {
51 53 ngx_url_t *url[NGX_RTMP_NOTIFY_MAX];
52 54 ngx_flag_t active;
  55 + ngx_uint_t method;
53 56 } ngx_rtmp_notify_app_conf_t;
54 57
55 58
@@ -111,6 +114,13 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
111 114 0,
112 115 NULL },
113 116
  117 + { ngx_string("notify_method"),
  118 + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
  119 + ngx_rtmp_notify_method,
  120 + NGX_RTMP_APP_CONF_OFFSET,
  121 + 0,
  122 + NULL },
  123 +
114 124 ngx_null_command
115 125 };
116 126
@@ -158,6 +168,8 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf)
158 168 nacf->url[n] = NGX_CONF_UNSET_PTR;
159 169 }
160 170
  171 + nacf->method = NGX_CONF_UNSET;
  172 +
161 173 return nacf;
162 174 }
163 175
@@ -180,35 +192,57 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
180 192 prev->active = 1;
181 193 }
182 194
  195 + ngx_conf_merge_uint_value(conf->method, prev->method,
  196 + NGX_RTMP_NETCALL_HTTP_POST);
  197 +
183 198 return NGX_CONF_OK;
184 199 }
185 200
186 201
187 202 static ngx_chain_t *
188   -ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
189   - ngx_pool_t *pool)
  203 +ngx_rtmp_notify_create_request(ngx_rtmp_session_t *s, ngx_pool_t *pool,
  204 + ngx_uint_t url_idx, ngx_chain_t *args)
190 205 {
191   - ngx_rtmp_publish_t *v = arg;
192   -
193   - ngx_rtmp_notify_app_conf_t *nacf;
194   - ngx_chain_t *hl, *cl, *pl;
195   - ngx_buf_t *b;
196   - ngx_str_t *addr_text;
197   - ngx_url_t *url;
198   - size_t name_len, type_len, args_len;
  206 + ngx_rtmp_notify_app_conf_t *nacf;
  207 + ngx_chain_t *al, *bl, *cl;
  208 + ngx_url_t *url;
199 209
200 210 nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
201 211
202   - /* common variables */
203   - cl = ngx_rtmp_netcall_http_format_session(s, pool);
  212 + url = nacf->url[url_idx];
204 213
205   - if (cl == NULL) {
  214 + al = ngx_rtmp_netcall_http_format_session(s, pool);
  215 + if (al == NULL) {
206 216 return NULL;
207 217 }
208 218
209   - /* publish variables */
210   - pl = ngx_alloc_chain_link(pool);
  219 + al->next = args;
  220 +
  221 + bl = NULL;
  222 +
  223 + if (nacf->method == NGX_RTMP_NETCALL_HTTP_POST) {
  224 + cl = al;
  225 + al = bl;
  226 + bl = cl;
  227 + }
  228 +
  229 + return ngx_rtmp_netcall_http_format_request(nacf->method, &url->host,
  230 + &url->uri, al, bl, pool,
  231 + &ngx_rtmp_notify_urlencoded);
  232 +}
  233 +
  234 +
  235 +static ngx_chain_t *
  236 +ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
  237 + ngx_pool_t *pool)
  238 +{
  239 + ngx_rtmp_publish_t *v = arg;
  240 +
  241 + ngx_chain_t *pl;
  242 + ngx_buf_t *b;
  243 + size_t name_len, type_len, args_len;
211 244
  245 + pl = ngx_alloc_chain_link(pool);
212 246 if (pl == NULL) {
213 247 return NULL;
214 248 }
@@ -216,54 +250,36 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
216 250 name_len = ngx_strlen(v->name);
217 251 type_len = ngx_strlen(v->type);
218 252 args_len = ngx_strlen(v->args);
219   - addr_text = &s->connection->addr_text;
220 253
221 254 b = ngx_create_temp_buf(pool,
222   - sizeof("&call=publish") +
223   - sizeof("&addr=") + addr_text->len *3 +
224   - sizeof("&name=") + name_len * 3 +
225   - sizeof("&type=") + type_len * 3 +
226   - 1 + args_len);
  255 + sizeof("&call=publish") +
  256 + sizeof("&name=") + name_len * 3 +
  257 + sizeof("&type=") + type_len * 3 +
  258 + 1 + args_len);
227 259 if (b == NULL) {
228 260 return NULL;
229 261 }
230 262
231 263 pl->buf = b;
  264 + pl->next = NULL;
232 265
233   - b->last = ngx_cpymem(b->last, (u_char*)"&call=publish",
234   - sizeof("&call=publish") - 1);
235   -
236   - b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
237   - b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
238   - addr_text->len, 0);
  266 + b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
  267 + sizeof("&call=publish") - 1);
239 268
240   - b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
241   - b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0);
  269 + b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
  270 + b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
  271 + NGX_ESCAPE_ARGS);
242 272
243   - b->last = ngx_cpymem(b->last, (u_char*)"&type=", sizeof("&type=") - 1);
244   - b->last = (u_char*)ngx_escape_uri(b->last, v->type, type_len, 0);
  273 + b->last = ngx_cpymem(b->last, (u_char*) "&type=", sizeof("&type=") - 1);
  274 + b->last = (u_char*) ngx_escape_uri(b->last, v->type, type_len,
  275 + NGX_ESCAPE_ARGS);
245 276
246 277 if (args_len) {
247 278 *b->last++ = '&';
248   - b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len);
  279 + b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
249 280 }
250 281
251   - /* HTTP header */
252   - url = nacf->url[NGX_RTMP_NOTIFY_PUBLISH];
253   - hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
254   - &url->uri, &url->host,
255   - pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
256   - &ngx_rtmp_notify_urlencoded);
257   -
258   - if (hl == NULL) {
259   - return NULL;
260   - }
261   -
262   - hl->next = cl;
263   - cl->next = pl;
264   - pl->next = NULL;
265   -
266   - return hl;
  282 + return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PUBLISH, pl);
267 283 }
268 284
269 285
@@ -273,80 +289,48 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
273 289 {
274 290 ngx_rtmp_play_t *v = arg;
275 291
276   - ngx_rtmp_notify_app_conf_t *nacf;
277   - ngx_chain_t *hl, *cl, *pl;
  292 + ngx_chain_t *pl;
278 293 ngx_buf_t *b;
279   - ngx_str_t *addr_text;
280   - ngx_url_t *url;
281 294 size_t name_len, args_len;
282 295
283   - nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
284   -
285   - /* common variables */
286   - cl = ngx_rtmp_netcall_http_format_session(s, pool);
287   -
288   - if (cl == NULL) {
289   - return NULL;
290   - }
291   -
292   - /* play variables */
293 296 pl = ngx_alloc_chain_link(pool);
294   -
295 297 if (pl == NULL) {
296 298 return NULL;
297 299 }
298 300
299 301 name_len = ngx_strlen(v->name);
300 302 args_len = ngx_strlen(v->args);
301   - addr_text = &s->connection->addr_text;
302 303
303 304 b = ngx_create_temp_buf(pool,
304   - sizeof("&call=play") +
305   - sizeof("&addr=") + addr_text->len * 3 +
306   - sizeof("&name=") + name_len * 3 +
307   - sizeof("&start=&duration=&reset=") + NGX_OFF_T_LEN * 3
308   - + 1 + args_len);
  305 + sizeof("&call=play") +
  306 + sizeof("&name=") + name_len * 3 +
  307 + sizeof("&start=&duration=&reset=") +
  308 + NGX_OFF_T_LEN * 3 + 1 + args_len);
309 309 if (b == NULL) {
310 310 return NULL;
311 311 }
312 312
313 313 pl->buf = b;
  314 + pl->next = NULL;
314 315
315   - b->last = ngx_cpymem(b->last, (u_char*)"&call=play",
316   - sizeof("&call=play") - 1);
317   -
318   - b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
319   - b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
320   - addr_text->len, 0);
  316 + b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
  317 + sizeof("&call=play") - 1);
321 318
322   - b->last = ngx_cpymem(b->last, (u_char*)"&name=", sizeof("&name=") - 1);
323   - b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0);
  319 + b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
  320 + b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
  321 + NGX_ESCAPE_ARGS);
324 322
325 323 b->last = ngx_snprintf(b->last, b->end - b->last,
326   - "&start=%uD&duration=%uD&reset=%d",
327   - (uint32_t)v->start, (uint32_t)v->duration, v->reset & 1);
  324 + "&start=%uD&duration=%uD&reset=%d",
  325 + (uint32_t) v->start, (uint32_t) v->duration,
  326 + v->reset & 1);
328 327
329 328 if (args_len) {
330 329 *b->last++ = '&';
331   - b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len);
332   - }
333   -
334   - /* HTTP header */
335   - url = nacf->url[NGX_RTMP_NOTIFY_PLAY];
336   - hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
337   - &url->uri, &url->host,
338   - pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
339   - &ngx_rtmp_notify_urlencoded);
340   -
341   - if (hl == NULL) {
342   - return NULL;
  330 + b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
343 331 }
344 332
345   - hl->next = cl;
346   - cl->next = pl;
347   - pl->next = NULL;
348   -
349   - return hl;
  333 + return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PLAY, pl);
350 334 }
351 335
352 336
@@ -356,23 +340,14 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
356 340 {
357 341 ngx_rtmp_notify_done_t *ds = arg;
358 342
359   - ngx_chain_t *hl, *cl, *pl;
  343 + ngx_chain_t *pl;
360 344 ngx_buf_t *b;
361 345 size_t cbname_len, name_len, args_len;
362   - ngx_str_t *addr_text;
363 346 ngx_rtmp_notify_ctx_t *ctx;
364 347
365 348 ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
366 349
367   - /* common variables */
368   - cl = ngx_rtmp_netcall_http_format_session(s, pool);
369   -
370   - if (cl == NULL) {
371   - return NULL;
372   - }
373   -
374 350 pl = ngx_alloc_chain_link(pool);
375   -
376 351 if (pl == NULL) {
377 352 return NULL;
378 353 }
@@ -380,51 +355,33 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
380 355 cbname_len = ngx_strlen(ds->cbname);
381 356 name_len = ctx ? ngx_strlen(ctx->name) : 0;
382 357 args_len = ctx ? ngx_strlen(ctx->args) : 0;
383   - addr_text = &s->connection->addr_text;
384