From 80d7b1c905d0e43682c608e0f7a93a7d9f470cbc Mon Sep 17 00:00:00 2001 From: Peter Wright Date: Thu, 17 Jul 2014 13:07:49 +0000 Subject: [PATCH 001/166] Allow the filename on disk to use no suffix (or a different suffix from the format), as long as the format prefix is used (e.g. "mp4:test.mov") --- ngx_rtmp_play_module.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ngx_rtmp_play_module.c b/ngx_rtmp_play_module.c index acaa46c9a..1c06a926a 100644 --- a/ngx_rtmp_play_module.c +++ b/ngx_rtmp_play_module.c @@ -860,9 +860,23 @@ ngx_rtmp_play_next_entry(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); + /* try unsuffixed file name as fallback if adding suffix didn't work */ if (ctx->file.fd == NGX_INVALID_FILE) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, ngx_errno, - "play: error opening file '%s'", path); + "play: error opening file '%s', trying without suffix", + path); + + p = ngx_snprintf(path, NGX_MAX_PATH, "%V/%s", + pe->root, v->name + ctx->pfx_size); + *p = 0; + + ctx->file.fd = ngx_open_file(path, NGX_FILE_RDONLY, NGX_FILE_OPEN, + NGX_FILE_DEFAULT_ACCESS); + } + + if (ctx->file.fd == NGX_INVALID_FILE) { + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, ngx_errno, + "play: error opening fallback file '%s'", path); continue; } From 9ebfcc1978433b1d81066dd13360348c0d3342ef Mon Sep 17 00:00:00 2001 From: Bryan Berg Date: Sat, 6 Sep 2014 18:15:48 -0700 Subject: [PATCH 002/166] Parse scaling list from SPS This is required for the dimensions to be calcuated properly when streaming using the high profile (at least for the encoder I'm using). Without this, the scaling list isn't skipped over and the parsed dimensions are incorrect. When the dimensions are incorrect, the MPEG-DASH manifest is generated incorrectly. --- ngx_rtmp_codec_module.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c index ddc9273d2..0e2d7eced 100644 --- a/ngx_rtmp_codec_module.c +++ b/ngx_rtmp_codec_module.c @@ -359,7 +359,8 @@ ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, ngx_chain_t *in) { ngx_uint_t profile_idc, width, height, crop_left, crop_right, crop_top, crop_bottom, frame_mbs_only, n, cf_idc, - num_ref_frames; + num_ref_frames, sl_size, sl_index, sl_udelta; + ngx_int_t sl_last, sl_next, sl_delta; ngx_rtmp_codec_ctx_t *ctx; ngx_rtmp_bit_reader_t br; @@ -437,11 +438,34 @@ ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, ngx_chain_t *in) /* seq scaling list present */ if (ngx_rtmp_bit_read(&br, 1)) { - /* TODO: scaling_list() + /* scaling list */ if (n < 6) { + sl_size = 16; } else { + sl_size = 64; + } + + sl_last = 8; + sl_next = 8; + + for (sl_index = 0; sl_index < sl_size; sl_index++) { + + if (sl_next != 0) { + + /* convert to signed: (-1)**k+1 * ceil(k/2) */ + sl_udelta = ngx_rtmp_bit_read_golomb(&br); + sl_delta = (sl_udelta + 1) >> 1; + if ((sl_udelta & 1) == 0) { + sl_delta = -sl_delta; + } + + sl_next = (sl_last + sl_delta + 256) % 256; + + if (sl_next != 0) { + sl_last = sl_next; + } + } } - */ } } } From 2262649c1fb059add84656e913160c233e382344 Mon Sep 17 00:00:00 2001 From: Bryan Berg Date: Sun, 7 Sep 2014 12:35:10 -0700 Subject: [PATCH 003/166] Don't truncate framerate for MPEG-DASH When pushing 29.97fps RTMP streams, the manifest shows an incorrect frame rate of "29", not "30000/1001" as it should be. --- dash/ngx_rtmp_dash_module.c | 35 ++++++++++++++++++++++++++++++----- ngx_rtmp_codec_module.c | 4 ++-- ngx_rtmp_codec_module.h | 2 +- ngx_rtmp_stat_module.c | 2 +- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/dash/ngx_rtmp_dash_module.c b/dash/ngx_rtmp_dash_module.c index 88f55ef0d..b78f68298 100644 --- a/dash/ngx_rtmp_dash_module.c +++ b/dash/ngx_rtmp_dash_module.c @@ -221,7 +221,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) ngx_fd_t fd; struct tm tm; ngx_str_t noname, *name; - ngx_uint_t i; + ngx_uint_t i, frame_rate_num, frame_rate_denom; ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_codec_ctx_t *codec_ctx; ngx_rtmp_dash_frag_t *f; @@ -230,6 +230,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; static u_char start_time[sizeof("1970-09-28T12:00:00+06:00")]; static u_char end_time[sizeof("1970-09-28T12:00:00+06:00")]; + static u_char frame_rate[(NGX_INT_T_LEN * 2) + 2]; dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); @@ -277,14 +278,14 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) " segmentAlignment=\"true\"\n" \ " maxWidth=\"%ui\"\n" \ " maxHeight=\"%ui\"\n" \ - " maxFrameRate=\"%ui\">\n" \ + " maxFrameRate=\"%s\">\n" \ " \n" \ @@ -382,17 +383,41 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) sep = (dacf->nested ? "" : "-"); if (ctx->has_video) { + frame_rate_num = (ngx_uint_t) (codec_ctx->frame_rate * 1000.); + + if (frame_rate_num % 1000 == 0) { + *ngx_sprintf(frame_rate, "%ui", frame_rate_num / 1000) = 0; + } else { + frame_rate_denom = 1000; + switch (frame_rate_num) { + case 23976: + frame_rate_num = 24000; + frame_rate_denom = 1001; + break; + case 29970: + frame_rate_num = 30000; + frame_rate_denom = 1001; + break; + case 59940: + frame_rate_num = 60000; + frame_rate_denom = 1001; + break; + } + + *ngx_sprintf(frame_rate, "%ui/%ui", frame_rate_num, frame_rate_denom) = 0; + } + p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_VIDEO, codec_ctx->width, codec_ctx->height, - codec_ctx->frame_rate, + frame_rate, &ctx->name, codec_ctx->avc_profile, codec_ctx->avc_compat, codec_ctx->avc_level, codec_ctx->width, codec_ctx->height, - codec_ctx->frame_rate, + frame_rate, (ngx_uint_t) (codec_ctx->video_data_rate * 1000), name, sep, name, sep); diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c index ddc9273d2..bb1104418 100644 --- a/ngx_rtmp_codec_module.c +++ b/ngx_rtmp_codec_module.c @@ -857,7 +857,7 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ctx->width = (ngx_uint_t) v.width; ctx->height = (ngx_uint_t) v.height; ctx->duration = (ngx_uint_t) v.duration; - ctx->frame_rate = (ngx_uint_t) v.frame_rate; + ctx->frame_rate = v.frame_rate; ctx->video_data_rate = (ngx_uint_t) v.video_data_rate; ctx->video_codec_id = (ngx_uint_t) v.video_codec_id_n; ctx->audio_data_rate = (ngx_uint_t) v.audio_data_rate; @@ -869,7 +869,7 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "codec: data frame: " - "width=%ui height=%ui duration=%ui frame_rate=%ui " + "width=%ui height=%ui duration=%ui frame_rate=%.3f " "video=%s (%ui) audio=%s (%ui)", ctx->width, ctx->height, ctx->duration, ctx->frame_rate, ngx_rtmp_get_video_codec_name(ctx->video_codec_id), diff --git a/ngx_rtmp_codec_module.h b/ngx_rtmp_codec_module.h index ee48c1cd3..831f02bd1 100644 --- a/ngx_rtmp_codec_module.h +++ b/ngx_rtmp_codec_module.h @@ -53,7 +53,7 @@ typedef struct { ngx_uint_t width; ngx_uint_t height; ngx_uint_t duration; - ngx_uint_t frame_rate; + double frame_rate; ngx_uint_t video_data_rate; ngx_uint_t video_codec_id; ngx_uint_t audio_data_rate; diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 326a811e3..e6d62ce09 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -509,7 +509,7 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, "%ui", codec->height) - buf); NGX_RTMP_STAT_L(""); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), - "%ui", codec->frame_rate) - buf); + "%.3f", codec->frame_rate) - buf); NGX_RTMP_STAT_L(""); cname = ngx_rtmp_get_video_codec_name(codec->video_codec_id); From d99c069e8e134b1bc588c08689719dabae9f794c Mon Sep 17 00:00:00 2001 From: Alexey Plotnik Date: Mon, 22 Sep 2014 00:51:09 +1100 Subject: [PATCH 004/166] Add in/out traffice per client (because has no information about traffic itself) --- ngx_rtmp_stat_module.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 326a811e3..367499b19 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -364,6 +364,14 @@ ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, NGX_RTMP_STAT_ES(&s->swf_url); NGX_RTMP_STAT_L(""); } + + NGX_RTMP_STAT_L(""); + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) s->in_bytes) - buf); + NGX_RTMP_STAT_L(""); + + NGX_RTMP_STAT_L(""); + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) s->out_bytes) - buf); + NGX_RTMP_STAT_L(""); } From c54b413b438ea475a2c3dbca49512678f5ce23be Mon Sep 17 00:00:00 2001 From: Juarez Bochi Date: Tue, 8 Apr 2014 18:38:57 -0300 Subject: [PATCH 005/166] Add program datetime from system or stream timestamp --- hls/ngx_rtmp_hls_module.c | 103 ++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 10 deletions(-) diff --git a/hls/ngx_rtmp_hls_module.c b/hls/ngx_rtmp_hls_module.c index 7c573a35c..14b5da892 100644 --- a/hls/ngx_rtmp_hls_module.c +++ b/hls/ngx_rtmp_hls_module.c @@ -36,6 +36,7 @@ static ngx_int_t ngx_rtmp_hls_ensure_directory(ngx_rtmp_session_t *s, typedef struct { uint64_t id; uint64_t key_id; + ngx_str_t *datetime; double duration; unsigned active:1; unsigned discont:1; /* before */ @@ -101,6 +102,7 @@ typedef struct { ngx_flag_t nested; ngx_str_t path; ngx_uint_t naming; + ngx_uint_t datetime; ngx_uint_t slicing; ngx_uint_t type; ngx_path_t *slot; @@ -122,6 +124,11 @@ typedef struct { #define NGX_RTMP_HLS_NAMING_SYSTEM 3 +#define NGX_RTMP_HLS_DATETIME_NONE 1 +#define NGX_RTMP_HLS_DATETIME_SYSTEM 2 +#define NGX_RTMP_HLS_DATETIME_TIMESTAMP 3 + + #define NGX_RTMP_HLS_SLICING_PLAIN 1 #define NGX_RTMP_HLS_SLICING_ALIGNED 2 @@ -138,6 +145,14 @@ static ngx_conf_enum_t ngx_rtmp_hls_naming_slots[] = { }; +static ngx_conf_enum_t ngx_rtmp_hls_datetime_slots[] = { + { ngx_string("none"), NGX_RTMP_HLS_DATETIME_NONE }, + { ngx_string("system"), NGX_RTMP_HLS_DATETIME_SYSTEM }, + { ngx_string("timestamp"), NGX_RTMP_HLS_DATETIME_TIMESTAMP }, + { ngx_null_string, 0 } +}; + + static ngx_conf_enum_t ngx_rtmp_hls_slicing_slots[] = { { ngx_string("plain"), NGX_RTMP_HLS_SLICING_PLAIN }, { ngx_string("aligned"), NGX_RTMP_HLS_SLICING_ALIGNED }, @@ -224,6 +239,13 @@ static ngx_command_t ngx_rtmp_hls_commands[] = { offsetof(ngx_rtmp_hls_app_conf_t, naming), &ngx_rtmp_hls_naming_slots }, + { ngx_string("hls_datetime"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_hls_app_conf_t, datetime), + &ngx_rtmp_hls_datetime_slots }, + { ngx_string("hls_fragment_slicing"), NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, ngx_conf_set_enum_slot, @@ -533,11 +555,7 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) n = ngx_write_fd(fd, buffer, p - buffer); if (n < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "hls: " ngx_write_fd_n " failed: '%V'", - &ctx->playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; + goto write_err; } sep = hacf->nested ? (hacf->base_url.len ? "/" : "") : "-"; @@ -557,6 +575,14 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) for (i = 0; i < ctx->nfrags; i++) { f = ngx_rtmp_hls_get_frag(s, i); + if (i == 0 && f->datetime && f->datetime->len > 0) { + p = ngx_snprintf(buffer, sizeof(buffer), "#EXT-X-PROGRAM-DATE-TIME:%*s\n", + f->datetime->len, f->datetime->data); + n = ngx_write_fd(fd, buffer, p - buffer); + if (n < 0) { + goto write_err; + } + } p = buffer; end = p + sizeof(buffer); @@ -586,11 +612,7 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) n = ngx_write_fd(fd, buffer, p - buffer); if (n < 0) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "hls: " ngx_write_fd_n " failed '%V'", - &ctx->playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; + goto write_err; } } @@ -610,6 +632,13 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) } return NGX_OK; + +write_err: + ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, + "hls: " ngx_write_fd_n " failed '%V'", + &ctx->playlist_bak); + ngx_close_file(fd); + return NGX_ERROR; } @@ -815,6 +844,54 @@ ngx_rtmp_hls_get_fragment_id(ngx_rtmp_session_t *s, uint64_t ts) } +static ngx_str_t * +ngx_rtmp_hls_get_fragment_datetime(ngx_rtmp_session_t *s, uint64_t ts) +{ + ngx_rtmp_hls_ctx_t *ctx; + ngx_rtmp_hls_app_conf_t *hacf; + ngx_str_t *datetime; + ngx_tm_t tm; + uint64_t msec; + + datetime = (ngx_str_t *) ngx_pcalloc(s->connection->pool, sizeof(ngx_str_t)); + datetime->data = NULL; + datetime->len = 0; + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); + hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); + + switch (hacf->datetime) { + + case NGX_RTMP_HLS_DATETIME_TIMESTAMP: + /* Timestamps in RTMP are given as an integer number of milliseconds + * relative to an unspecified epoch, so we clear the last 32 bits + * from system time, and add the timestamp from RTMP. */ + msec = ngx_cached_time->sec * 1000 + ngx_cached_time->msec; + msec /= 4294967296; //2**32 + msec *= 4294967296; + msec += (ts / 90); + ngx_gmtime(msec / 1000, &tm); + + datetime->data = (u_char *) ngx_pcalloc(s->connection->pool, ngx_cached_http_log_iso8601.len * sizeof(u_char)); + (void) ngx_sprintf(datetime->data, "%4d-%02d-%02dT%02d:%02d:%02d-00:00", + tm.ngx_tm_year, tm.ngx_tm_mon, + tm.ngx_tm_mday, tm.ngx_tm_hour, + tm.ngx_tm_min, tm.ngx_tm_sec); + datetime->len = ngx_cached_http_log_iso8601.len; + return datetime; + + case NGX_RTMP_HLS_DATETIME_SYSTEM: + datetime->data = (u_char *) ngx_pcalloc(s->connection->pool, ngx_cached_http_log_iso8601.len * sizeof(u_char)); + ngx_cpymem(&datetime->data, (const void *) &ngx_cached_http_log_iso8601.data, ngx_cached_http_log_iso8601.len); + datetime->len = ngx_cached_http_log_iso8601.len; + return datetime; + + default: /* NGX_RTMP_HLS_DATETIME_NONE */ + return datetime; + } +} + + static ngx_int_t ngx_rtmp_hls_close_fragment(ngx_rtmp_session_t *s) { @@ -846,6 +923,7 @@ ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts, { uint64_t id; ngx_fd_t fd; + ngx_str_t *datetime; ngx_uint_t g; ngx_rtmp_hls_ctx_t *ctx; ngx_rtmp_hls_frag_t *f; @@ -870,6 +948,7 @@ ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts, } id = ngx_rtmp_hls_get_fragment_id(s, ts); + datetime = ngx_rtmp_hls_get_fragment_datetime(s, ts); if (hacf->granularity) { g = (ngx_uint_t) hacf->granularity; @@ -960,6 +1039,7 @@ ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts, f->discont = discont; f->id = id; f->key_id = ctx->key_id; + f->datetime = datetime; ctx->frag_ts = ts; @@ -2292,6 +2372,7 @@ ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf) conf->continuous = NGX_CONF_UNSET; conf->nested = NGX_CONF_UNSET; conf->naming = NGX_CONF_UNSET_UINT; + conf->datetime = NGX_CONF_UNSET_UINT; conf->slicing = NGX_CONF_UNSET_UINT; conf->type = NGX_CONF_UNSET_UINT; conf->max_audio_delay = NGX_CONF_UNSET_MSEC; @@ -2323,6 +2404,8 @@ ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->nested, prev->nested, 0); ngx_conf_merge_uint_value(conf->naming, prev->naming, NGX_RTMP_HLS_NAMING_SEQUENTIAL); + ngx_conf_merge_uint_value(conf->datetime, prev->datetime, + NGX_RTMP_HLS_DATETIME_NONE); ngx_conf_merge_uint_value(conf->slicing, prev->slicing, NGX_RTMP_HLS_SLICING_PLAIN); ngx_conf_merge_uint_value(conf->type, prev->type, From ad6c63c149c64ea1bc31ddc2d7453fe74eace368 Mon Sep 17 00:00:00 2001 From: Juarez Bochi Date: Wed, 9 Apr 2014 11:59:20 -0300 Subject: [PATCH 006/166] Fix the way date time is written to fd --- hls/ngx_rtmp_hls_module.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hls/ngx_rtmp_hls_module.c b/hls/ngx_rtmp_hls_module.c index 14b5da892..db1b948cd 100644 --- a/hls/ngx_rtmp_hls_module.c +++ b/hls/ngx_rtmp_hls_module.c @@ -576,12 +576,19 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) for (i = 0; i < ctx->nfrags; i++) { f = ngx_rtmp_hls_get_frag(s, i); if (i == 0 && f->datetime && f->datetime->len > 0) { - p = ngx_snprintf(buffer, sizeof(buffer), "#EXT-X-PROGRAM-DATE-TIME:%*s\n", - f->datetime->len, f->datetime->data); + p = ngx_snprintf(buffer, sizeof(buffer), "#EXT-X-PROGRAM-DATE-TIME:"); n = ngx_write_fd(fd, buffer, p - buffer); if (n < 0) { goto write_err; } + n = ngx_write_fd(fd, f->datetime->data, f->datetime->len); + if (n < 0) { + goto write_err; + } + n = ngx_write_fd(fd, "\n", 1); + if (n < 0) { + goto write_err; + } } p = buffer; From 2362acf45c8f69c2b8bda2dbd327d45c2587cdd4 Mon Sep 17 00:00:00 2001 From: Wing Date: Fri, 24 Oct 2014 01:34:12 +0800 Subject: [PATCH 007/166] fix 'volatile' qualifiers error --- ngx_rtmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngx_rtmp.c b/ngx_rtmp.c index c83e9e197..58c3a5535 100644 --- a/ngx_rtmp.c +++ b/ngx_rtmp.c @@ -838,7 +838,7 @@ static ngx_int_t ngx_rtmp_init_process(ngx_cycle_t *cycle) { #if (nginx_version >= 1007005) - ngx_queue_init(&ngx_rtmp_init_queue); + ngx_queue_init((ngx_queue_t*) &ngx_rtmp_init_queue); #endif return NGX_OK; } From 99433754df33f744800f8105dae1105e3fbc42f7 Mon Sep 17 00:00:00 2001 From: Wing Date: Fri, 24 Oct 2014 01:35:36 +0800 Subject: [PATCH 008/166] fix 'volatile' qualifiers error --- ngx_rtmp_stat_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 326a811e3..edad6a106 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -115,7 +115,7 @@ ngx_rtmp_stat_init_process(ngx_cycle_t *cycle) * so we can run posted events here */ - ngx_event_process_posted(cycle, &ngx_rtmp_init_queue); + ngx_event_process_posted(cycle, (ngx_queue_t*) &ngx_rtmp_init_queue); return NGX_OK; } From d069f36f86886f24155d94cb97608a9f9c5e2067 Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Mon, 27 Oct 2014 18:46:55 -0700 Subject: [PATCH 009/166] to avoid writing invalid metadata, don't overwrite metadata from previous @setDataFrame / onMetaData invocations unless the metadata has actually changed --- ngx_rtmp_codec_module.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c index ddc9273d2..59b069057 100644 --- a/ngx_rtmp_codec_module.c +++ b/ngx_rtmp_codec_module.c @@ -839,9 +839,17 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_memzero(&v, sizeof(v)); - /* use -1 as a sign of unchanged data; - * 0 is a valid value for uncompressed audio */ + /* use -1 as a sign of unchanged data */ + v.width = -1; + v.height = -1; + v.duration = -1; + v.frame_rate = -1; + v.video_data_rate = -1; + v.video_codec_id_n = -1; + v.audio_data_rate = -1; v.audio_codec_id_n = -1; + v.profile[0] = '\0'; + v.level[0] = '\0'; /* FFmpeg sends a string in front of actal metadata; ignore it */ skip = !(in->buf->last > in->buf->pos @@ -854,18 +862,17 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } - ctx->width = (ngx_uint_t) v.width; - ctx->height = (ngx_uint_t) v.height; - ctx->duration = (ngx_uint_t) v.duration; - ctx->frame_rate = (ngx_uint_t) v.frame_rate; - ctx->video_data_rate = (ngx_uint_t) v.video_data_rate; - ctx->video_codec_id = (ngx_uint_t) v.video_codec_id_n; - ctx->audio_data_rate = (ngx_uint_t) v.audio_data_rate; - ctx->audio_codec_id = (v.audio_codec_id_n == -1 - ? 0 : v.audio_codec_id_n == 0 + if (v.width != -1) ctx->width = (ngx_uint_t) v.width; + if (v.height != -1) ctx->height = (ngx_uint_t) v.height; + if (v.duration != -1) ctx->duration = (ngx_uint_t) v.duration; + if (v.frame_rate != -1) ctx->frame_rate = (ngx_uint_t) v.frame_rate; + if (v.video_data_rate != -1) ctx->video_data_rate = (ngx_uint_t) v.video_data_rate; + if (v.video_codec_id_n != -1) ctx->video_codec_id = (ngx_uint_t) v.video_codec_id_n; + if (v.audio_data_rate != -1) ctx->audio_data_rate = (ngx_uint_t) v.audio_data_rate; + if (v.audio_codec_id_n != -1) ctx->audio_codec_id = (v.audio_codec_id_n == 0 ? NGX_RTMP_AUDIO_UNCOMPRESSED : (ngx_uint_t) v.audio_codec_id_n); - ngx_memcpy(ctx->profile, v.profile, sizeof(v.profile)); - ngx_memcpy(ctx->level, v.level, sizeof(v.level)); + if (v.profile[0] != '\0') ngx_memcpy(ctx->profile, v.profile, sizeof(v.profile)); + if (v.level[0] != '\0') ngx_memcpy(ctx->level, v.level, sizeof(v.level)); ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "codec: data frame: " From 2a54c8e089a23df10ac3d393cf3f560dfa8045a7 Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Tue, 28 Oct 2014 19:28:35 -0700 Subject: [PATCH 010/166] Adobe Media Server and the like require that metadata is sent using @setDataFrame. As such, in the relay module, when propagating metadata to another server, we will use the @setDataFrame command. --- ngx_rtmp_relay_module.c | 151 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 4713f181d..155378ca7 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -8,6 +8,7 @@ #include #include "ngx_rtmp_relay_module.h" #include "ngx_rtmp_cmd_module.h" +#include "ngx_rtmp_codec_module.h" static ngx_rtmp_publish_pt next_publish; @@ -1231,12 +1232,150 @@ ngx_rtmp_relay_on_error(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } +static ngx_int_t +ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) +{ + ngx_rtmp_relay_ctx_t *ctx; + ngx_rtmp_codec_ctx_t *codec_ctx; + ngx_rtmp_header_t hdr; + + static struct { + double width; + double height; + double duration; + double frame_rate; + double video_data_rate; + double video_codec_id; + double audio_data_rate; + double audio_codec_id; + u_char profile[32]; + u_char level[32]; + } v; + + static ngx_rtmp_amf_elt_t out_inf[] = { + + { NGX_RTMP_AMF_STRING, + ngx_string("Server"), + "NGINX RTMP (github.com/arut/nginx-rtmp-module)", 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("width"), + &v.width, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("height"), + &v.height, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("displayWidth"), + &v.width, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("displayHeight"), + &v.height, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("duration"), + &v.duration, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("framerate"), + &v.frame_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("fps"), + &v.frame_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("videodatarate"), + &v.video_data_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("videocodecid"), + &v.video_codec_id, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("audiodatarate"), + &v.audio_data_rate, 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_string("audiocodecid"), + &v.audio_codec_id, 0 }, + + { NGX_RTMP_AMF_STRING, + ngx_string("profile"), + &v.profile, sizeof(v.profile) }, + + { NGX_RTMP_AMF_STRING, + ngx_string("level"), + &v.level, sizeof(v.level) } + }; + + static ngx_rtmp_amf_elt_t out_elts[] = { + + { NGX_RTMP_AMF_STRING, + ngx_null_string, + "@setDataFrame", 0 }, + + { NGX_RTMP_AMF_STRING, + ngx_null_string, + "onMetaData", 0 }, + + { NGX_RTMP_AMF_OBJECT, + ngx_null_string, + out_inf, sizeof(out_inf) } + }; + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); + if (ctx == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "relay: couldn't get relay context"); + return NGX_OK; + } + + /* we need to get the codec context from the incoming publisher in order to + * send the metadata along */ + codec_ctx = ngx_rtmp_get_module_ctx(ctx->publish->session, ngx_rtmp_codec_module); + if (codec_ctx == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "relay: couldn't get codec context"); + return NGX_OK; + } + + ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "relay: data frame from codec context: " + "width=%ui height=%ui duration=%ui frame_rate=%ui " + "video_codec_id=%ui audio_codec_id=%ui", + codec_ctx->width, codec_ctx->height, codec_ctx->duration, + codec_ctx->frame_rate, codec_ctx->video_codec_id, + codec_ctx->audio_codec_id); + + v.width = codec_ctx->width; + v.height = codec_ctx->height; + v.duration = codec_ctx->duration; + v.frame_rate = codec_ctx->frame_rate; + v.video_data_rate = codec_ctx->video_data_rate; + v.video_codec_id = codec_ctx->video_codec_id; + v.audio_data_rate = codec_ctx->audio_data_rate; + v.audio_codec_id = codec_ctx->audio_codec_id; + ngx_memcpy(v.profile, codec_ctx->profile, sizeof(codec_ctx->profile)); + ngx_memcpy(v.level, codec_ctx->level, sizeof(codec_ctx->level)); + + ngx_memzero(&hdr, sizeof(hdr)); + hdr.csid = NGX_RTMP_RELAY_CSID_AMF_INI; + hdr.msid = NGX_RTMP_RELAY_MSID; + hdr.type = NGX_RTMP_MSG_AMF_META; + + return ngx_rtmp_send_amf(s, &hdr, out_elts, + sizeof(out_elts) / sizeof(out_elts[0])); +} static ngx_int_t ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) { ngx_rtmp_relay_ctx_t *ctx; + static struct { double trans; u_char level[32]; @@ -1300,6 +1439,18 @@ ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, "relay: onStatus: level='%s' code='%s' description='%s'", v.level, v.code, v.desc); + /* when doing a push to Adobe Media Server, we have to use the + * @setDataFrame command to send the metadata + * see: http://help.adobe.com/en_US/adobemediaserver/devguide/WS5b3ccc516d4fbf351e63e3d11a0773d56e-7ff6Dev.2.3.html + */ + if (!ngx_strncasecmp(v.code, (u_char *)"NetStream.Publish.Start", + ngx_strlen("NetStream.Publish.Start"))) { + if (ngx_rtmp_relay_send_set_data_frame(s) != NGX_OK) { + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "relay: unable to send metadata via @setDataFrame"); + } + } + return NGX_OK; } From 1d21d68c3ccc483af14955c3b008d836c9592306 Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Thu, 30 Oct 2014 10:18:37 -0700 Subject: [PATCH 011/166] It's possible that we'll receive NetStream.Publish.Start _before_ the codec module has parsed the meta data. To handle that case, we'll also try to call @setDataFrame when we receive the @setDataFrame from the publisher. --- ngx_rtmp_relay_module.c | 82 ++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 155378ca7..09e4b23ec 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -1327,7 +1327,7 @@ ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) }; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); - if (ctx == NULL) { + if (ctx == NULL || !s->relay) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "relay: couldn't get relay context"); return NGX_OK; @@ -1335,14 +1335,15 @@ ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) /* we need to get the codec context from the incoming publisher in order to * send the metadata along */ - codec_ctx = ngx_rtmp_get_module_ctx(ctx->publish->session, ngx_rtmp_codec_module); + codec_ctx = ngx_rtmp_get_module_ctx(ctx->publish->session, + ngx_rtmp_codec_module); if (codec_ctx == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "relay: couldn't get codec context"); return NGX_OK; } - ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "relay: data frame from codec context: " "width=%ui height=%ui duration=%ui frame_rate=%ui " "video_codec_id=%ui audio_codec_id=%ui", @@ -1350,24 +1351,33 @@ ngx_rtmp_relay_send_set_data_frame(ngx_rtmp_session_t *s) codec_ctx->frame_rate, codec_ctx->video_codec_id, codec_ctx->audio_codec_id); - v.width = codec_ctx->width; - v.height = codec_ctx->height; - v.duration = codec_ctx->duration; - v.frame_rate = codec_ctx->frame_rate; - v.video_data_rate = codec_ctx->video_data_rate; - v.video_codec_id = codec_ctx->video_codec_id; - v.audio_data_rate = codec_ctx->audio_data_rate; - v.audio_codec_id = codec_ctx->audio_codec_id; - ngx_memcpy(v.profile, codec_ctx->profile, sizeof(codec_ctx->profile)); - ngx_memcpy(v.level, codec_ctx->level, sizeof(codec_ctx->level)); - - ngx_memzero(&hdr, sizeof(hdr)); - hdr.csid = NGX_RTMP_RELAY_CSID_AMF_INI; - hdr.msid = NGX_RTMP_RELAY_MSID; - hdr.type = NGX_RTMP_MSG_AMF_META; - - return ngx_rtmp_send_amf(s, &hdr, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); + /* we only want to send the metadata if the codec module has already + * parsed it -- is there a better way to check this? */ + if (codec_ctx->width > 0 && codec_ctx->height > 0) { + v.width = codec_ctx->width; + v.height = codec_ctx->height; + v.duration = codec_ctx->duration; + v.frame_rate = codec_ctx->frame_rate; + v.video_data_rate = codec_ctx->video_data_rate; + v.video_codec_id = codec_ctx->video_codec_id; + v.audio_data_rate = codec_ctx->audio_data_rate; + v.audio_codec_id = codec_ctx->audio_codec_id; + ngx_memcpy(v.profile, codec_ctx->profile, sizeof(codec_ctx->profile)); + ngx_memcpy(v.level, codec_ctx->level, sizeof(codec_ctx->level)); + + ngx_memzero(&hdr, sizeof(hdr)); + hdr.csid = NGX_RTMP_RELAY_CSID_AMF_INI; + hdr.msid = NGX_RTMP_RELAY_MSID; + hdr.type = NGX_RTMP_MSG_AMF_META; + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: sending @setDataFrame"); + + return ngx_rtmp_send_amf(s, &hdr, out_elts, + sizeof(out_elts) / sizeof(out_elts[0])); + } + + return NGX_OK; } static ngx_int_t @@ -1445,8 +1455,12 @@ ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, */ if (!ngx_strncasecmp(v.code, (u_char *)"NetStream.Publish.Start", ngx_strlen("NetStream.Publish.Start"))) { + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: sending metadata from NetStream.Publish.Start from player"); + if (ngx_rtmp_relay_send_set_data_frame(s) != NGX_OK) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "relay: unable to send metadata via @setDataFrame"); } } @@ -1454,6 +1468,26 @@ ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } +static ngx_int_t +ngx_rtmp_relay_on_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, + ngx_chain_t *in) +{ + /* when we receive onMetaData, the session (s) is our incoming publisher's + * session, so we need to send the @setDataFrame to our ctx->play->session */ + ngx_rtmp_relay_ctx_t *ctx; + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); + if (ctx == NULL || !ctx->play->session->relay) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: not sending metadata from @setDataFrame event from publisher"); + return NGX_OK; + } + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: sending metadata from @setDataFrame event from publisher"); + + return ngx_rtmp_relay_send_set_data_frame(ctx->play->session); +} static ngx_int_t ngx_rtmp_relay_handshake_done(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, @@ -1838,5 +1872,9 @@ ngx_rtmp_relay_postconfiguration(ngx_conf_t *cf) ngx_str_set(&ch->name, "onStatus"); ch->handler = ngx_rtmp_relay_on_status; + ch = ngx_array_push(&cmcf->amf); + ngx_str_set(&ch->name, "@setDataFrame"); + ch->handler = ngx_rtmp_relay_on_meta_data; + return NGX_OK; } From de42f3801d646ffca31942ff468463a3586244c5 Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Thu, 30 Oct 2014 15:17:51 -0700 Subject: [PATCH 012/166] Support for onTextData and onCuePoint in the data channel for the live module. --- ngx_rtmp_live_module.c | 152 +++++++++++++++++++++++++++++++++++++++++ ngx_rtmp_live_module.h | 3 +- ngx_rtmp_stat_module.c | 2 + 3 files changed, 156 insertions(+), 1 deletion(-) diff --git a/ngx_rtmp_live_module.c b/ngx_rtmp_live_module.c index 5bebb9e2a..298a280cd 100644 --- a/ngx_rtmp_live_module.c +++ b/ngx_rtmp_live_module.c @@ -357,6 +357,9 @@ ngx_rtmp_live_set_status(ngx_rtmp_session_t *s, ngx_chain_t *control, ctx->cs[1].active = 0; ctx->cs[1].dropped = 0; + + ctx->cs[2].active = 0; + ctx->cs[2].dropped = 0; } @@ -556,6 +559,7 @@ ngx_rtmp_live_join(ngx_rtmp_session_t *s, u_char *name, unsigned publisher) ctx->cs[0].csid = NGX_RTMP_CSID_VIDEO; ctx->cs[1].csid = NGX_RTMP_CSID_AUDIO; + ctx->cs[2].csid = NGX_RTMP_CSID_AMF; if (!ctx->publishing && ctx->stream->active) { ngx_rtmp_live_start(s); @@ -1036,6 +1040,145 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } +static ngx_int_t +ngx_rtmp_live_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, + ngx_chain_t *in, ngx_rtmp_amf_elt_t *out_elts, ngx_uint_t out_elts_size) +{ + ngx_rtmp_live_ctx_t *ctx, *pctx; + ngx_chain_t *data, *rpkt; + ngx_rtmp_core_srv_conf_t *cscf; + ngx_rtmp_live_app_conf_t *lacf; + ngx_rtmp_session_t *ss; + ngx_rtmp_header_t ch; + ngx_int_t rc; + ngx_uint_t prio; + ngx_uint_t peers; + uint32_t delta; + ngx_rtmp_live_chunk_stream_t *cs; + + u_char *msg_type; + + msg_type = (u_char *)out_elts[0].data; + + lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); + if (lacf == NULL) { + return NGX_ERROR; + } + + if (!lacf->live || in == NULL || in->buf == NULL) { + return NGX_OK; + } + + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); + if (ctx == NULL || ctx->stream == NULL) { + return NGX_OK; + } + + if (ctx->publishing == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "live: %s from non-publisher", msg_type); + return NGX_OK; + } + + /* drop the data packet if the stream is not active */ + if (!ctx->stream->active) { + return NGX_OK; + } + + ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "live: %s packet timestamp=%uD", + msg_type, h->timestamp); + + cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); + + cs = &ctx->cs[2]; + cs->active = 1; + + peers = 0; + prio = 0; + data = NULL; + rc = ngx_rtmp_append_amf(s, &data, NULL, out_elts, out_elts_size); + if (rc != NGX_OK) { + if (data) { + ngx_rtmp_free_shared_chain(cscf, data); + } + return NGX_ERROR; + } + + ngx_memzero(&ch, sizeof(ch)); + ch.timestamp = h->timestamp; + ch.msid = NGX_RTMP_MSID; + ch.csid = h->csid; + ch.type = NGX_RTMP_MSG_AMF_META; + + delta = ch.timestamp - cs->timestamp; + + rpkt = ngx_rtmp_append_shared_bufs(cscf, data, in); + ngx_rtmp_prepare_message(s, &ch, NULL, rpkt); + + for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) { + if (pctx == ctx || pctx->paused) { + continue; + } + + ss = pctx->session; + + if (ngx_rtmp_send_message(ss, rpkt, prio) != NGX_OK) { + ++pctx->ndropped; + cs->dropped += delta; + continue; + } + + cs->timestamp += delta; + ++peers; + ss->current_time = cs->timestamp; + } + + if (data) { + ngx_rtmp_free_shared_chain(cscf, data); + } + + if (rpkt) { + ngx_rtmp_free_shared_chain(cscf, rpkt); + } + + ngx_rtmp_update_bandwidth(&ctx->stream->bw_in, h->mlen); + ngx_rtmp_update_bandwidth(&ctx->stream->bw_out, h->mlen * peers); + ngx_rtmp_update_bandwidth(&ctx->stream->bw_in_data, h->mlen); + + return NGX_OK; +} + +static ngx_int_t +ngx_rtmp_live_on_cue_point(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, + ngx_chain_t *in) +{ + static ngx_rtmp_amf_elt_t out_elts[] = { + + { NGX_RTMP_AMF_STRING, + ngx_null_string, + "onCuePoint", 0 } + }; + + return ngx_rtmp_live_data(s, h, in, out_elts, + sizeof(out_elts) / sizeof(out_elts[0])); +} + +static ngx_int_t +ngx_rtmp_live_on_text_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, + ngx_chain_t *in) +{ + static ngx_rtmp_amf_elt_t out_elts[] = { + + { NGX_RTMP_AMF_STRING, + ngx_null_string, + "onTextData", 0 } + }; + + return ngx_rtmp_live_data(s, h, in, out_elts, + sizeof(out_elts) / sizeof(out_elts[0])); +} + static ngx_int_t ngx_rtmp_live_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) @@ -1118,6 +1261,7 @@ ngx_rtmp_live_postconfiguration(ngx_conf_t *cf) { ngx_rtmp_core_main_conf_t *cmcf; ngx_rtmp_handler_pt *h; + ngx_rtmp_amf_handler_t *ch; cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); @@ -1149,5 +1293,13 @@ ngx_rtmp_live_postconfiguration(ngx_conf_t *cf) next_stream_eof = ngx_rtmp_stream_eof; ngx_rtmp_stream_eof = ngx_rtmp_live_stream_eof; + ch = ngx_array_push(&cmcf->amf); + ngx_str_set(&ch->name, "onTextData"); + ch->handler = ngx_rtmp_live_on_text_data; + + ch = ngx_array_push(&cmcf->amf); + ngx_str_set(&ch->name, "onCuePoint"); + ch->handler = ngx_rtmp_live_on_cue_point; + return NGX_OK; } diff --git a/ngx_rtmp_live_module.h b/ngx_rtmp_live_module.h index 71eca36bc..1eb59d4db 100644 --- a/ngx_rtmp_live_module.h +++ b/ngx_rtmp_live_module.h @@ -33,7 +33,7 @@ struct ngx_rtmp_live_ctx_s { ngx_rtmp_live_stream_t *stream; ngx_rtmp_live_ctx_t *next; ngx_uint_t ndropped; - ngx_rtmp_live_chunk_stream_t cs[2]; + ngx_rtmp_live_chunk_stream_t cs[3]; ngx_uint_t meta_version; ngx_event_t idle_evt; unsigned active:1; @@ -50,6 +50,7 @@ struct ngx_rtmp_live_stream_s { ngx_rtmp_bandwidth_t bw_in; ngx_rtmp_bandwidth_t bw_in_audio; ngx_rtmp_bandwidth_t bw_in_video; + ngx_rtmp_bandwidth_t bw_in_data; ngx_rtmp_bandwidth_t bw_out; ngx_msec_t epoch; unsigned active:1; diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 326a811e3..84bd48a88 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -453,6 +453,8 @@ ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, NGX_RTMP_STAT_BW); ngx_rtmp_stat_bw(r, lll, &stream->bw_in_video, "video", NGX_RTMP_STAT_BW); + ngx_rtmp_stat_bw(r, lll, &stream->bw_in_data, "data", + NGX_RTMP_STAT_BW); nclients = 0; codec = NULL; From 17159755e568c8a7aef016612b8649201d33aebf Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Thu, 30 Oct 2014 18:13:45 -0700 Subject: [PATCH 013/166] Support for the data channel for the record module. --- ngx_rtmp_record_module.c | 30 ++++++++++++++++++++++-------- ngx_rtmp_record_module.h | 6 +++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/ngx_rtmp_record_module.c b/ngx_rtmp_record_module.c index e54a30b41..502055da9 100644 --- a/ngx_rtmp_record_module.c +++ b/ngx_rtmp_record_module.c @@ -31,9 +31,9 @@ static char * ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf, static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_int_t inc_nframes); -static ngx_int_t ngx_rtmp_record_av(ngx_rtmp_session_t *s, +static ngx_int_t ngx_rtmp_record_avd(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in); -static ngx_int_t ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, +static ngx_int_t ngx_rtmp_record_node_avd(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in); static ngx_int_t ngx_rtmp_record_node_open(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx); @@ -47,9 +47,13 @@ static ngx_int_t ngx_rtmp_record_init(ngx_rtmp_session_t *s); static ngx_conf_bitmask_t ngx_rtmp_record_mask[] = { { ngx_string("off"), NGX_RTMP_RECORD_OFF }, { ngx_string("all"), NGX_RTMP_RECORD_AUDIO | + NGX_RTMP_RECORD_VIDEO | + NGX_RTMP_RECORD_DATA }, + { ngx_string("av"), NGX_RTMP_RECORD_AUDIO | NGX_RTMP_RECORD_VIDEO }, { ngx_string("audio"), NGX_RTMP_RECORD_AUDIO }, { ngx_string("video"), NGX_RTMP_RECORD_VIDEO }, + { ngx_string("data"), NGX_RTMP_RECORD_DATA }, { ngx_string("keyframes"), NGX_RTMP_RECORD_KEYFRAMES }, { ngx_string("manual"), NGX_RTMP_RECORD_MANUAL }, { ngx_null_string, 0 } @@ -886,7 +890,8 @@ ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, if (h->type == NGX_RTMP_MSG_VIDEO) { rctx->video = 1; - } else { + } + if (h->type == NGX_RTMP_MSG_AUDIO) { rctx->audio = 1; } @@ -993,7 +998,7 @@ ngx_rtmp_record_get_chain_mlen(ngx_chain_t *in) static ngx_int_t -ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, +ngx_rtmp_record_avd(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) { ngx_rtmp_record_ctx_t *ctx; @@ -1009,7 +1014,7 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, rctx = ctx->rec.elts; for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) { - ngx_rtmp_record_node_av(s, rctx, h, in); + ngx_rtmp_record_node_avd(s, rctx, h, in); } return NGX_OK; @@ -1017,7 +1022,7 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, static ngx_int_t -ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, +ngx_rtmp_record_node_avd(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in) { ngx_time_t next; @@ -1079,6 +1084,12 @@ ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, return NGX_OK; } + if (h->type == NGX_RTMP_MSG_AMF_META && + (rracf->flags & NGX_RTMP_RECORD_DATA) == 0) + { + return NGX_OK; + } + if (h->type == NGX_RTMP_MSG_VIDEO && (rracf->flags & NGX_RTMP_RECORD_VIDEO) == 0 && ((rracf->flags & NGX_RTMP_RECORD_KEYFRAMES) == 0 || !keyframe)) @@ -1280,10 +1291,13 @@ ngx_rtmp_record_postconfiguration(ngx_conf_t *cf) cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_record_av; + *h = ngx_rtmp_record_avd; h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_record_av; + *h = ngx_rtmp_record_avd; + + h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AMF_META]); + *h = ngx_rtmp_record_avd; next_publish = ngx_rtmp_publish; ngx_rtmp_publish = ngx_rtmp_record_publish; diff --git a/ngx_rtmp_record_module.h b/ngx_rtmp_record_module.h index 6450dcbf9..aaac0abfa 100644 --- a/ngx_rtmp_record_module.h +++ b/ngx_rtmp_record_module.h @@ -16,9 +16,9 @@ #define NGX_RTMP_RECORD_OFF 0x01 #define NGX_RTMP_RECORD_AUDIO 0x02 #define NGX_RTMP_RECORD_VIDEO 0x04 -#define NGX_RTMP_RECORD_KEYFRAMES 0x08 -#define NGX_RTMP_RECORD_MANUAL 0x10 - +#define NGX_RTMP_RECORD_DATA 0x08 +#define NGX_RTMP_RECORD_KEYFRAMES 0x10 +#define NGX_RTMP_RECORD_MANUAL 0x20 typedef struct { ngx_str_t id; From 8f0f2e75c9948c576fb0f1e49397ef73f43b934d Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Thu, 30 Oct 2014 21:44:26 -0700 Subject: [PATCH 014/166] We need to loop through _all_ of the ctx->play sessions when sending @setDataFrame --- ngx_rtmp_relay_module.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 09e4b23ec..673f68766 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -1475,18 +1475,25 @@ ngx_rtmp_relay_on_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, /* when we receive onMetaData, the session (s) is our incoming publisher's * session, so we need to send the @setDataFrame to our ctx->play->session */ ngx_rtmp_relay_ctx_t *ctx; + ngx_rtmp_relay_ctx_t *pctx; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); - if (ctx == NULL || !ctx->play->session->relay) { - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "relay: not sending metadata from @setDataFrame event from publisher"); + if (ctx == NULL) { return NGX_OK; } ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "relay: sending metadata from @setDataFrame event from publisher"); + "relay: sending metadata from @setDataFrame invocation from publisher"); - return ngx_rtmp_relay_send_set_data_frame(ctx->play->session); + for (pctx = ctx->play; pctx; pctx = pctx->next) { + if (!pctx->session->relay) continue; + if (ngx_rtmp_relay_send_set_data_frame(pctx->session) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "relay: unable to send @setDataFrame to %V/%V", &pctx->url, &pctx->play_path); + } + } + + return NGX_OK; } static ngx_int_t From 459e730d34fa0f539cc85eccd01455568afd24b7 Mon Sep 17 00:00:00 2001 From: Jeffrey Wescott Date: Wed, 5 Nov 2014 10:15:44 -0800 Subject: [PATCH 015/166] don't send @setDataFrame unless we've already received NetStream.Publish.Start --- ngx_rtmp.h | 3 +++ ngx_rtmp_relay_module.c | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ngx_rtmp.h b/ngx_rtmp.h index b87e99e20..b7cb76db1 100644 --- a/ngx_rtmp.h +++ b/ngx_rtmp.h @@ -231,6 +231,9 @@ typedef struct { ngx_msec_t base_time; uint32_t current_time; + /* ready for publishing? */ + unsigned ready_for_publish:1; + /* ping */ ngx_event_t ping_evt; unsigned ping_active:1; diff --git a/ngx_rtmp_relay_module.c b/ngx_rtmp_relay_module.c index 673f68766..b5ef08d43 100644 --- a/ngx_rtmp_relay_module.c +++ b/ngx_rtmp_relay_module.c @@ -497,6 +497,7 @@ ngx_rtmp_relay_create_connection(ngx_rtmp_conf_ctx_t *cctx, ngx_str_t* name, } rs->app_conf = cctx->app_conf; rs->relay = 1; + rs->ready_for_publish = 0; rctx->session = rs; ngx_rtmp_set_ctx(rs, rctx, ngx_rtmp_relay_module); ngx_str_set(&rs->flashver, "ngx-local-relay"); @@ -1459,6 +1460,8 @@ ngx_rtmp_relay_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "relay: sending metadata from NetStream.Publish.Start from player"); + s->ready_for_publish = 1; + if (ngx_rtmp_relay_send_set_data_frame(s) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "relay: unable to send metadata via @setDataFrame"); @@ -1477,16 +1480,19 @@ ngx_rtmp_relay_on_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_rtmp_relay_ctx_t *ctx; ngx_rtmp_relay_ctx_t *pctx; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: got metadata from @setDataFrame invocation from publisher."); + ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module); if (ctx == NULL) { return NGX_OK; } - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "relay: sending metadata from @setDataFrame invocation from publisher"); - for (pctx = ctx->play; pctx; pctx = pctx->next) { - if (!pctx->session->relay) continue; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "relay: %ssending metadata from @setDataFrame invocation from publisher to %V/%V/%V", + (pctx->session->relay && pctx->session->ready_for_publish) ? "" : "not ", &pctx->url, &pctx->app, &pctx->play_path); + if (!pctx->session->relay || !pctx->session->ready_for_publish) continue; if (ngx_rtmp_relay_send_set_data_frame(pctx->session) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "relay: unable to send @setDataFrame to %V/%V", &pctx->url, &pctx->play_path); From 1d1d4fcac64529fcdc8c948483c06580e5369208 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Fri, 28 Nov 2014 19:15:54 +0100 Subject: [PATCH 016/166] Fix access to config field of ngx_rtmp_in{,6}_addr_t. Closes #290 --- ngx_rtmp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ngx_rtmp.h b/ngx_rtmp.h index b87e99e20..6fffbda9a 100644 --- a/ngx_rtmp.h +++ b/ngx_rtmp.h @@ -60,16 +60,16 @@ typedef struct { } ngx_rtmp_addr_conf_t; typedef struct { - in_addr_t addr; ngx_rtmp_addr_conf_t conf; + in_addr_t addr; } ngx_rtmp_in_addr_t; #if (NGX_HAVE_INET6) typedef struct { - struct in6_addr addr6; ngx_rtmp_addr_conf_t conf; + struct in6_addr addr6; } ngx_rtmp_in6_addr_t; #endif From cb36f9c23c94d2443d4b0311db08fe0d883a2d35 Mon Sep 17 00:00:00 2001 From: BeenWoo Date: Tue, 3 Feb 2015 15:37:46 +0800 Subject: [PATCH 017/166] Update ngx_rtmp_codec_module.c Some encoders send "setDataFrame" instead of "@setDataFrame", which makes rtmp module can't show correct video frame rate in stat page. --- ngx_rtmp_codec_module.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ngx_rtmp_codec_module.c b/ngx_rtmp_codec_module.c index ddc9273d2..f7e62ecbc 100644 --- a/ngx_rtmp_codec_module.c +++ b/ngx_rtmp_codec_module.c @@ -943,7 +943,15 @@ ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf) } ngx_str_set(&ch->name, "@setDataFrame"); ch->handler = ngx_rtmp_codec_meta_data; - + + // some encoders send setDataFrame instead of @setDataFrame + ch = ngx_array_push(&cmcf->amf); + if (ch == NULL) { + return NGX_ERROR; + } + ngx_str_set(&ch->name, "setDataFrame"); + ch->handler = ngx_rtmp_codec_meta_data; + ch = ngx_array_push(&cmcf->amf); if (ch == NULL) { return NGX_ERROR; From f62a0838064baf089ad9fe3c8f6f2ffe0775afb2 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 23 Mar 2015 22:30:37 +0300 Subject: [PATCH 018/166] fixed compilation with nginx 1.7.11 --- ngx_rtmp.c | 4 +++- ngx_rtmp.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ngx_rtmp.c b/ngx_rtmp.c index c83e9e197..192b6c949 100644 --- a/ngx_rtmp.c +++ b/ngx_rtmp.c @@ -32,7 +32,9 @@ static char * ngx_rtmp_merge_applications(ngx_conf_t *cf, static ngx_int_t ngx_rtmp_init_process(ngx_cycle_t *cycle); -#if (nginx_version >= 1007005) +#if (nginx_version >= 1007011) +ngx_queue_t ngx_rtmp_init_queue; +#elif (nginx_version >= 1007005) ngx_thread_volatile ngx_queue_t ngx_rtmp_init_queue; #else ngx_thread_volatile ngx_event_t *ngx_rtmp_init_queue; diff --git a/ngx_rtmp.h b/ngx_rtmp.h index b87e99e20..e6c34d988 100644 --- a/ngx_rtmp.h +++ b/ngx_rtmp.h @@ -607,7 +607,9 @@ extern ngx_rtmp_bandwidth_t ngx_rtmp_bw_in; extern ngx_uint_t ngx_rtmp_naccepted; -#if (nginx_version >= 1007005) +#if (nginx_version >= 1007011) +extern ngx_queue_t ngx_rtmp_init_queue; +#elif (nginx_version >= 1007005) extern ngx_thread_volatile ngx_queue_t ngx_rtmp_init_queue; #else extern ngx_thread_volatile ngx_event_t *ngx_rtmp_init_queue; From 955c7e6b6418ff629015b632c7e5a81310003535 Mon Sep 17 00:00:00 2001 From: Hannes Ljungberg Date: Fri, 27 Mar 2015 13:31:40 +0100 Subject: [PATCH 019/166] Remove unneeded space in EXT-X-PLAYLIST-TYPE tag --- hls/ngx_rtmp_hls_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hls/ngx_rtmp_hls_module.c b/hls/ngx_rtmp_hls_module.c index 7c573a35c..d1498c0e8 100644 --- a/hls/ngx_rtmp_hls_module.c +++ b/hls/ngx_rtmp_hls_module.c @@ -528,7 +528,7 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) ctx->frag, max_frag); if (hacf->type == NGX_RTMP_HLS_TYPE_EVENT) { - p = ngx_slprintf(p, end, "#EXT-X-PLAYLIST-TYPE: EVENT\n"); + p = ngx_slprintf(p, end, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); } n = ngx_write_fd(fd, buffer, p - buffer); From b92a262f4cbc0114b141123a17a7481ca1daff4b Mon Sep 17 00:00:00 2001 From: Anton Baranov Date: Wed, 8 Apr 2015 11:00:03 +0300 Subject: [PATCH 020/166] add Directive record_interval_size --- AUTHORS | 7 +++++++ ngx_rtmp_record_module.c | 18 ++++++++++++++++++ ngx_rtmp_record_module.h | 1 + 3 files changed, 26 insertions(+) diff --git a/AUTHORS b/AUTHORS index e169dff0e..21a5a5238 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,3 +6,10 @@ Project author: Contacts: arut@qip.ru arutyunyan.roman@gmail.com + +Fork author: + Anton Baranov + Kiev, Ukraine + + Contacts: + a.baranov@lanet.ua diff --git a/ngx_rtmp_record_module.c b/ngx_rtmp_record_module.c index e54a30b41..eb3053df9 100644 --- a/ngx_rtmp_record_module.c +++ b/ngx_rtmp_record_module.c @@ -105,6 +105,14 @@ static ngx_command_t ngx_rtmp_record_commands[] = { NGX_RTMP_APP_CONF_OFFSET, offsetof(ngx_rtmp_record_app_conf_t, lock_file), NULL }, + + { ngx_string("record_interval_size"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| + NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_record_app_conf_t, interval_size), + NULL }, { ngx_string("record_max_size"), NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| @@ -190,6 +198,7 @@ ngx_rtmp_record_create_app_conf(ngx_conf_t *cf) } racf->max_size = NGX_CONF_UNSET_SIZE; + racf->interval_size = NGX_CONF_UNSET_SIZE; racf->max_frames = NGX_CONF_UNSET_SIZE; racf->interval = NGX_CONF_UNSET_MSEC; racf->unique = NGX_CONF_UNSET; @@ -216,6 +225,7 @@ ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->path, prev->path, ""); ngx_conf_merge_str_value(conf->suffix, prev->suffix, ".flv"); ngx_conf_merge_size_value(conf->max_size, prev->max_size, 0); + ngx_conf_merge_size_value(conf->interval_size, prev->interval_size, 0); ngx_conf_merge_size_value(conf->max_frames, prev->max_frames, 0); ngx_conf_merge_value(conf->unique, prev->unique, 0); ngx_conf_merge_value(conf->append, prev->append, 0); @@ -975,6 +985,14 @@ ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, ngx_rtmp_record_node_close(s, rctx); } + /* watch size interval */ + if ((rracf->interval_size && rctx->file.offset >= (ngx_int_t) rracf->interval_size) || + (rracf->max_frames && rctx->nframes >= rracf->max_frames)) + { + ngx_rtmp_record_node_close(s, rctx); + ngx_rtmp_record_node_open(s, rctx); + } + return NGX_OK; } diff --git a/ngx_rtmp_record_module.h b/ngx_rtmp_record_module.h index 6450dcbf9..85b0335d1 100644 --- a/ngx_rtmp_record_module.h +++ b/ngx_rtmp_record_module.h @@ -25,6 +25,7 @@ typedef struct { ngx_uint_t flags; ngx_str_t path; size_t max_size; + size_t interval_size; size_t max_frames; ngx_msec_t interval; ngx_str_t suffix; From b053eca1f9696781edeac84b4b0635b884347545 Mon Sep 17 00:00:00 2001 From: Anton Baranov Date: Wed, 8 Apr 2015 11:06:54 +0300 Subject: [PATCH 021/166] add Directive record_interval_size --- ngx_rtmp_record_module.c | 34 +++++++++++++++++----------------- ngx_rtmp_record_module.h | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ngx_rtmp_record_module.c b/ngx_rtmp_record_module.c index eb3053df9..936f2a604 100644 --- a/ngx_rtmp_record_module.c +++ b/ngx_rtmp_record_module.c @@ -105,14 +105,14 @@ static ngx_command_t ngx_rtmp_record_commands[] = { NGX_RTMP_APP_CONF_OFFSET, offsetof(ngx_rtmp_record_app_conf_t, lock_file), NULL }, - - { ngx_string("record_interval_size"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, interval_size), - NULL }, + + { ngx_string("record_interval_size"), + NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| + NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_RTMP_APP_CONF_OFFSET, + offsetof(ngx_rtmp_record_app_conf_t, interval_size), + NULL }, { ngx_string("record_max_size"), NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| @@ -198,7 +198,7 @@ ngx_rtmp_record_create_app_conf(ngx_conf_t *cf) } racf->max_size = NGX_CONF_UNSET_SIZE; - racf->interval_size = NGX_CONF_UNSET_SIZE; + racf->interval_size = NGX_CONF_UNSET_SIZE; racf->max_frames = NGX_CONF_UNSET_SIZE; racf->interval = NGX_CONF_UNSET_MSEC; racf->unique = NGX_CONF_UNSET; @@ -225,7 +225,7 @@ ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->path, prev->path, ""); ngx_conf_merge_str_value(conf->suffix, prev->suffix, ".flv"); ngx_conf_merge_size_value(conf->max_size, prev->max_size, 0); - ngx_conf_merge_size_value(conf->interval_size, prev->interval_size, 0); + ngx_conf_merge_size_value(conf->interval_size, prev->interval_size, 0); ngx_conf_merge_size_value(conf->max_frames, prev->max_frames, 0); ngx_conf_merge_value(conf->unique, prev->unique, 0); ngx_conf_merge_value(conf->append, prev->append, 0); @@ -985,13 +985,13 @@ ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, ngx_rtmp_record_node_close(s, rctx); } - /* watch size interval */ - if ((rracf->interval_size && rctx->file.offset >= (ngx_int_t) rracf->interval_size) || - (rracf->max_frames && rctx->nframes >= rracf->max_frames)) - { - ngx_rtmp_record_node_close(s, rctx); - ngx_rtmp_record_node_open(s, rctx); - } + /* watch size interval */ + if ((rracf->interval_size && rctx->file.offset >= (ngx_int_t) rracf->interval_size) || + (rracf->max_frames && rctx->nframes >= rracf->max_frames)) + { + ngx_rtmp_record_node_close(s, rctx); + ngx_rtmp_record_node_open(s, rctx); + } return NGX_OK; } diff --git a/ngx_rtmp_record_module.h b/ngx_rtmp_record_module.h index 85b0335d1..2472af76c 100644 --- a/ngx_rtmp_record_module.h +++ b/ngx_rtmp_record_module.h @@ -25,7 +25,7 @@ typedef struct { ngx_uint_t flags; ngx_str_t path; size_t max_size; - size_t interval_size; + size_t interval_size; size_t max_frames; ngx_msec_t interval; ngx_str_t suffix; From 2c2e90b706667ecd17a47c7bdbcc70bdbe94d617 Mon Sep 17 00:00:00 2001 From: Anton Baranov Date: Wed, 8 Apr 2015 11:08:17 +0300 Subject: [PATCH 022/166] add Directive record_interval_size --- ngx_rtmp_record_module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngx_rtmp_record_module.h b/ngx_rtmp_record_module.h index 2472af76c..1b2a5a0e2 100644 --- a/ngx_rtmp_record_module.h +++ b/ngx_rtmp_record_module.h @@ -25,7 +25,7 @@ typedef struct { ngx_uint_t flags; ngx_str_t path; size_t max_size; - size_t interval_size; + size_t interval_size; size_t max_frames; ngx_msec_t interval; ngx_str_t suffix; From 809f09412406e8b11c79241446df822d0ebea11b Mon Sep 17 00:00:00 2001 From: itpp16 Date: Thu, 9 Apr 2015 12:47:32 +0200 Subject: [PATCH 023/166] Update ngx_rtmp_handler.c fixed compilation with nginx 1.7.12 --- ngx_rtmp_handler.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ngx_rtmp_handler.c b/ngx_rtmp_handler.c index ac78a6fde..4da885867 100644 --- a/ngx_rtmp_handler.c +++ b/ngx_rtmp_handler.c @@ -558,7 +558,11 @@ ngx_rtmp_send(ngx_event_t *wev) ngx_del_event(wev, NGX_WRITE_EVENT, 0); } +#if (nginx_version >= 1007012) + ngx_event_process_posted((ngx_cycle_t *) ngx_cycle,(ngx_queue_t *) &s->posted_dry_events); +#else ngx_event_process_posted((ngx_cycle_t *) ngx_cycle, &s->posted_dry_events); +#endif } From 6ce821727d0f4f96e8cc0a54c82ecc46e0e961e1 Mon Sep 17 00:00:00 2001 From: itpp16 Date: Thu, 9 Apr 2015 12:57:07 +0200 Subject: [PATCH 024/166] Update ngx_rtmp_play_module.c fixed compilation with nginx 1.7.12 --- ngx_rtmp_play_module.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ngx_rtmp_play_module.c b/ngx_rtmp_play_module.c index f6ea6c382..f01e2c5dc 100644 --- a/ngx_rtmp_play_module.c +++ b/ngx_rtmp_play_module.c @@ -291,7 +291,11 @@ ngx_rtmp_play_send(ngx_event_t *e) ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "play: send buffer full"); - ngx_post_event(e, &s->posted_dry_events); +#if (nginx_version >= 1007012) + ngx_post_event(e, (ngx_queue_t *) &s->posted_dry_events); // #ngxw +#else + ngx_post_event(e, &s->posted_dry_events); // #ngxw +#endif return; } From 48983747d3e8cd3c5ff77e0f173b653af36de06c Mon Sep 17 00:00:00 2001 From: itpp16 Date: Thu, 9 Apr 2015 12:58:46 +0200 Subject: [PATCH 025/166] Update ngx_rtmp_play_module.c --- ngx_rtmp_play_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ngx_rtmp_play_module.c b/ngx_rtmp_play_module.c index f01e2c5dc..e2414de45 100644 --- a/ngx_rtmp_play_module.c +++ b/ngx_rtmp_play_module.c @@ -292,9 +292,9 @@ ngx_rtmp_play_send(ngx_event_t *e) "play: send buffer full"); #if (nginx_version >= 1007012) - ngx_post_event(e, (ngx_queue_t *) &s->posted_dry_events); // #ngxw + ngx_post_event(e, (ngx_queue_t *) &s->posted_dry_events); #else - ngx_post_event(e, &s->posted_dry_events); // #ngxw + ngx_post_event(e, &s->posted_dry_events); #endif return; } From a4907e80ce33148e0bc8da35d8685376315977f6 Mon Sep 17 00:00:00 2001 From: Eugaulerss Date: Thu, 28 May 2015 16:47:23 +0800 Subject: [PATCH 026/166] Update ngx_rtmp_handler.c fixbug lost data when chunk_size changing, the frontier of stream data should by pointed by the pos and last of ngx_buf_t --- ngx_rtmp_handler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ngx_rtmp_handler.c b/ngx_rtmp_handler.c index ac78a6fde..ac4233256 100644 --- a/ngx_rtmp_handler.c +++ b/ngx_rtmp_handler.c @@ -868,6 +868,7 @@ ngx_rtmp_set_chunk_size(ngx_rtmp_session_t *s, ngx_uint_t size) bi->pos += (ngx_cpymem(bo->last, bi->pos, bo->end - bo->last) - bo->last); + bo->last = bo->end; lo->next = ngx_rtmp_alloc_in_buf(s); lo = lo->next; if (lo == NULL) { From 70c90bbac564f07e97a7ee6a3958c86ccd91dd77 Mon Sep 17 00:00:00 2001 From: Sellier Alexis Date: Tue, 2 Jun 2015 18:01:10 +0200 Subject: [PATCH 027/166] Display socket port number for each rtmp connection --- ngx_rtmp_stat_module.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/ngx_rtmp_stat_module.c b/ngx_rtmp_stat_module.c index 326a811e3..1704d220a 100644 --- a/ngx_rtmp_stat_module.c +++ b/ngx_rtmp_stat_module.c @@ -329,7 +329,10 @@ ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_session_t *s) { u_char buf[NGX_INT_T_LEN]; - + struct sockaddr_in *tmp; + struct sockaddr_in sa; + socklen_t len = sizeof(struct sockaddr); + #ifdef NGX_RTMP_POOL_DEBUG ngx_rtmp_stat_dump_pool(r, lll, s->connection->pool); #endif @@ -342,6 +345,24 @@ ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, NGX_RTMP_STAT_ES(&s->connection->addr_text); NGX_RTMP_STAT_L(""); + /* + ** Displays socket port number + */ + NGX_RTMP_STAT_L(""); + if (s->connection->listening) + { + tmp = (struct sockaddr_in *) s->connection->listening->sockaddr; + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", + (ngx_uint_t) ntohs(tmp->sin_port)) - buf); + } + else if (getsockname(s->connection->fd, (struct sockaddr *) &sa, &len) != -1) + { + NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", + (ngx_uint_t) ntohs(sa.sin_port)) - buf); + } + NGX_RTMP_STAT_L(""); + + NGX_RTMP_STAT_L("