mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-04-29 11:03:46 +02:00
Merge pull request #138 from sergey-dryabzhinsky/fix-121-dash-availabilityEndTime
Rewrite availabilityStart and publish time generation to DASH manifest
This commit is contained in:
commit
7db5ef0ea5
|
@ -81,11 +81,29 @@ typedef struct {
|
||||||
} ngx_rtmp_dash_cleanup_t;
|
} ngx_rtmp_dash_cleanup_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_RTMP_DASH_CLOCK_COMPENSATION_OFF 1
|
||||||
|
#define NGX_RTMP_DASH_CLOCK_COMPENSATION_NTP 2
|
||||||
|
#define NGX_RTMP_DASH_CLOCK_COMPENSATION_HTTP_HEAD 3
|
||||||
|
#define NGX_RTMP_DASH_CLOCK_COMPENSATION_HTTP_ISO 4
|
||||||
|
|
||||||
|
static ngx_conf_enum_t ngx_rtmp_dash_clock_compensation_type_slots[] = {
|
||||||
|
{ ngx_string("off"), NGX_RTMP_DASH_CLOCK_COMPENSATION_OFF },
|
||||||
|
{ ngx_string("ntp"), NGX_RTMP_DASH_CLOCK_COMPENSATION_NTP },
|
||||||
|
{ ngx_string("http_head"), NGX_RTMP_DASH_CLOCK_COMPENSATION_HTTP_HEAD },
|
||||||
|
{ ngx_string("http_iso"), NGX_RTMP_DASH_CLOCK_COMPENSATION_HTTP_ISO },
|
||||||
|
{ ngx_null_string, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_flag_t dash;
|
ngx_flag_t dash;
|
||||||
ngx_msec_t fraglen;
|
ngx_msec_t fraglen;
|
||||||
ngx_msec_t playlen;
|
ngx_msec_t playlen;
|
||||||
ngx_flag_t nested;
|
ngx_flag_t nested;
|
||||||
|
ngx_uint_t clock_compensation; // Try to compensate clock drift
|
||||||
|
// between client and server (on client side)
|
||||||
|
ngx_str_t clock_helper_uri; // Use uri to static file on HTTP server
|
||||||
|
// - same machine as RTMP/DASH)
|
||||||
|
// - or NTP server address
|
||||||
ngx_str_t path;
|
ngx_str_t path;
|
||||||
ngx_uint_t winfrags;
|
ngx_uint_t winfrags;
|
||||||
ngx_flag_t cleanup;
|
ngx_flag_t cleanup;
|
||||||
|
@ -137,6 +155,20 @@ static ngx_command_t ngx_rtmp_dash_commands[] = {
|
||||||
offsetof(ngx_rtmp_dash_app_conf_t, nested),
|
offsetof(ngx_rtmp_dash_app_conf_t, nested),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("dash_clock_compensation"),
|
||||||
|
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_dash_app_conf_t, clock_compensation),
|
||||||
|
&ngx_rtmp_dash_clock_compensation_type_slots },
|
||||||
|
|
||||||
|
{ ngx_string("dash_clock_helper_uri"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_str_slot,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
offsetof(ngx_rtmp_dash_app_conf_t, clock_helper_uri),
|
||||||
|
NULL },
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -225,7 +257,10 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
ngx_str_t noname, *name;
|
ngx_str_t noname, *name;
|
||||||
ngx_uint_t i, frame_rate_num, frame_rate_denom;
|
ngx_uint_t i, frame_rate_num, frame_rate_denom;
|
||||||
ngx_uint_t depth_msec;
|
ngx_uint_t depth_msec, depth_sec;
|
||||||
|
ngx_uint_t update_period, update_period_msec;
|
||||||
|
ngx_uint_t buffer_time, buffer_time_msec;
|
||||||
|
ngx_uint_t presentation_delay, presentation_delay_msec;
|
||||||
ngx_rtmp_dash_ctx_t *ctx;
|
ngx_rtmp_dash_ctx_t *ctx;
|
||||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||||
ngx_rtmp_dash_frag_t *f;
|
ngx_rtmp_dash_frag_t *f;
|
||||||
|
@ -236,7 +271,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
static u_char buffer[NGX_RTMP_DASH_BUFSIZE];
|
static u_char buffer[NGX_RTMP_DASH_BUFSIZE];
|
||||||
static u_char avaliable_time[NGX_RTMP_DASH_GMT_LENGTH];
|
static u_char avaliable_time[NGX_RTMP_DASH_GMT_LENGTH];
|
||||||
static u_char publish_time[NGX_RTMP_DASH_GMT_LENGTH];
|
static u_char publish_time[NGX_RTMP_DASH_GMT_LENGTH];
|
||||||
static u_char buffer_depth[sizeof("P00Y00M00DT00H00M00.00S")];
|
static u_char buffer_depth[sizeof("P00Y00M00DT00H00M00.000S")];
|
||||||
static u_char frame_rate[(NGX_INT_T_LEN * 2) + 2];
|
static u_char frame_rate[(NGX_INT_T_LEN * 2) + 2];
|
||||||
|
|
||||||
dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
|
dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
|
||||||
|
@ -267,17 +302,21 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
" type=\"dynamic\"\n" \
|
" type=\"dynamic\"\n" \
|
||||||
" xmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n" \
|
" xmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n" \
|
||||||
" availabilityStartTime=\"%s\"\n" \
|
" availabilityStartTime=\"%s\"\n" \
|
||||||
" publishTime=\"%s\"\n" \
|
" publishTime=\"%s\"\n" \
|
||||||
" minimumUpdatePeriod=\"PT%uiS\"\n" \
|
" minimumUpdatePeriod=\"PT%ui.%03uiS\"\n" \
|
||||||
" minBufferTime=\"PT%uiS\"\n" \
|
" minBufferTime=\"PT%ui.%03uiS\"\n" \
|
||||||
" timeShiftBufferDepth=\"%s\"\n" \
|
" timeShiftBufferDepth=\"%s\"\n" \
|
||||||
" suggestedPresentationDelay=\"PT%uiS\"\n" \
|
" suggestedPresentationDelay=\"PT%ui.%03uiS\"\n" \
|
||||||
" profiles=\"urn:hbbtv:dash:profile:isoff-live:2012," \
|
" profiles=\"urn:hbbtv:dash:profile:isoff-live:2012," \
|
||||||
"urn:mpeg:dash:profile:isoff-live:2011\"\n" \
|
"urn:mpeg:dash:profile:isoff-live:2011\"\n" \
|
||||||
" xmlns:xsi=\"http://www.w3.org/2011/XMLSchema-instance\"\n" \
|
" xmlns:xsi=\"http://www.w3.org/2011/XMLSchema-instance\"\n" \
|
||||||
" xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\">\n" \
|
" xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\">\n"
|
||||||
" <UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-head:2014\"\n" \
|
|
||||||
" value=\"http://vm2.dashif.org/dash/time.txt\" />" \
|
#define NGX_RTMP_DASH_MANIFEST_CLOCK \
|
||||||
|
" <UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:%s:2014\"\n" \
|
||||||
|
" value=\"%V\" />\n" \
|
||||||
|
|
||||||
|
#define NGX_RTMP_DASH_MANIFEST_PERIOD \
|
||||||
" <Period start=\"PT0S\" id=\"dash\">\n"
|
" <Period start=\"PT0S\" id=\"dash\">\n"
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,6 +324,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
" <AdaptationSet\n" \
|
" <AdaptationSet\n" \
|
||||||
" id=\"1\"\n" \
|
" id=\"1\"\n" \
|
||||||
" segmentAlignment=\"true\"\n" \
|
" segmentAlignment=\"true\"\n" \
|
||||||
|
" startWithSAP=\"1\"\n" \
|
||||||
" maxWidth=\"%ui\"\n" \
|
" maxWidth=\"%ui\"\n" \
|
||||||
" maxHeight=\"%ui\"\n" \
|
" maxHeight=\"%ui\"\n" \
|
||||||
" maxFrameRate=\"%s\">\n" \
|
" maxFrameRate=\"%s\">\n" \
|
||||||
|
@ -296,7 +336,6 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
" height=\"%ui\"\n" \
|
" height=\"%ui\"\n" \
|
||||||
" frameRate=\"%s\"\n" \
|
" frameRate=\"%s\"\n" \
|
||||||
" sar=\"1:1\"\n" \
|
" sar=\"1:1\"\n" \
|
||||||
" startWithSAP=\"1\"\n" \
|
|
||||||
" bandwidth=\"%ui\">\n" \
|
" bandwidth=\"%ui\">\n" \
|
||||||
" <SegmentTemplate\n" \
|
" <SegmentTemplate\n" \
|
||||||
" presentationTimeOffset=\"0\"\n" \
|
" presentationTimeOffset=\"0\"\n" \
|
||||||
|
@ -320,6 +359,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
#define NGX_RTMP_DASH_MANIFEST_AUDIO \
|
#define NGX_RTMP_DASH_MANIFEST_AUDIO \
|
||||||
" <AdaptationSet\n" \
|
" <AdaptationSet\n" \
|
||||||
" id=\"2\"\n" \
|
" id=\"2\"\n" \
|
||||||
|
" startWithSAP=\"1\"\n" \
|
||||||
" segmentAlignment=\"true\">\n" \
|
" segmentAlignment=\"true\">\n" \
|
||||||
" <AudioChannelConfiguration\n" \
|
" <AudioChannelConfiguration\n" \
|
||||||
" schemeIdUri=\"urn:mpeg:dash:" \
|
" schemeIdUri=\"urn:mpeg:dash:" \
|
||||||
|
@ -330,7 +370,6 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
" mimeType=\"audio/mp4\"\n" \
|
" mimeType=\"audio/mp4\"\n" \
|
||||||
" codecs=\"mp4a.%s\"\n" \
|
" codecs=\"mp4a.%s\"\n" \
|
||||||
" audioSamplingRate=\"%ui\"\n" \
|
" audioSamplingRate=\"%ui\"\n" \
|
||||||
" startWithSAP=\"1\"\n" \
|
|
||||||
" bandwidth=\"%ui\">\n" \
|
" bandwidth=\"%ui\">\n" \
|
||||||
" <SegmentTemplate\n" \
|
" <SegmentTemplate\n" \
|
||||||
" presentationTimeOffset=\"0\"\n" \
|
" presentationTimeOffset=\"0\"\n" \
|
||||||
|
@ -351,48 +390,110 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
||||||
" </Period>\n" \
|
" </Period>\n" \
|
||||||
"</MPD>\n"
|
"</MPD>\n"
|
||||||
|
|
||||||
ngx_libc_localtime(ctx->start_time.sec, &tm);
|
/**
|
||||||
|
* Availability time must be equal stream start time
|
||||||
|
* Cos segments time counting from it
|
||||||
|
*/
|
||||||
|
ngx_libc_gmtime(ctx->start_time.sec, &tm);
|
||||||
|
*ngx_sprintf(avaliable_time, "%4d-%02d-%02dT%02d:%02d:%02dZ",
|
||||||
|
tm.tm_year + 1900, tm.tm_mon + 1,
|
||||||
|
tm.tm_mday, tm.tm_hour,
|
||||||
|
tm.tm_min, tm.tm_sec
|
||||||
|
) = 0;
|
||||||
|
|
||||||
*ngx_sprintf(avaliable_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
/* Stream publish time */
|
||||||
tm.tm_year + 1900, tm.tm_mon + 1,
|
*ngx_sprintf(publish_time, "%s", avaliable_time) = 0;
|
||||||
tm.tm_mday, tm.tm_hour,
|
|
||||||
tm.tm_min, tm.tm_sec,
|
|
||||||
ctx->start_time.gmtoff < 0 ? '-' : '+',
|
|
||||||
ngx_abs(ctx->start_time.gmtoff / 60),
|
|
||||||
ngx_abs(ctx->start_time.gmtoff % 60)) = 0;
|
|
||||||
|
|
||||||
if (publish_time[0] == '\0'){
|
|
||||||
*ngx_sprintf(publish_time, "%s", avaliable_time) = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_libc_localtime(ctx->start_time.sec +
|
|
||||||
(ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->timestamp +
|
|
||||||
ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->duration) /
|
|
||||||
1000, &tm);
|
|
||||||
|
|
||||||
depth_msec = (ngx_uint_t) (
|
depth_sec = (ngx_uint_t) (
|
||||||
ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->timestamp +
|
ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->timestamp +
|
||||||
ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->duration -
|
ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->duration -
|
||||||
ngx_rtmp_dash_get_frag(s, 0)->timestamp);
|
ngx_rtmp_dash_get_frag(s, 0)->timestamp);
|
||||||
|
|
||||||
ngx_libc_gmtime((ngx_uint_t) (depth_msec / 1000), &tm);
|
depth_msec = depth_sec % 1000;
|
||||||
|
depth_sec -= depth_msec;
|
||||||
|
depth_sec /= 1000;
|
||||||
|
|
||||||
*ngx_sprintf(buffer_depth, "P%dY%02dM%02dDT%dH%02dM%02d.%02dS",
|
ngx_libc_gmtime(depth_sec, &tm);
|
||||||
|
|
||||||
|
*ngx_sprintf(buffer_depth, "P%dY%02dM%02dDT%dH%02dM%02d.%03dS",
|
||||||
tm.tm_year - 70, tm.tm_mon,
|
tm.tm_year - 70, tm.tm_mon,
|
||||||
tm.tm_mday - 1, tm.tm_hour,
|
tm.tm_mday - 1, tm.tm_hour,
|
||||||
tm.tm_min, tm.tm_sec,
|
tm.tm_min, tm.tm_sec,
|
||||||
(ngx_uint_t) ((depth_msec % 1000) / 10)) = 0;
|
depth_msec) = 0;
|
||||||
|
|
||||||
last = buffer + sizeof(buffer);
|
last = buffer + sizeof(buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate playlist minimal update period
|
||||||
|
* This should be more than biggest segment duration
|
||||||
|
* Cos segments rounded by keyframe/GOP.
|
||||||
|
* And that time not always equals to fragment length.
|
||||||
|
*/
|
||||||
|
update_period = dacf->fraglen;
|
||||||
|
|
||||||
|
for (i = 0; i < ctx->nfrags; i++) {
|
||||||
|
f = ngx_rtmp_dash_get_frag(s, i);
|
||||||
|
if (f->duration > update_period) {
|
||||||
|
update_period = f->duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reasonable delay for streaming
|
||||||
|
presentation_delay = update_period * 2 + 1000;
|
||||||
|
presentation_delay_msec = presentation_delay % 1000;
|
||||||
|
presentation_delay -= presentation_delay_msec;
|
||||||
|
presentation_delay /= 1000;
|
||||||
|
|
||||||
|
// Calculate msec part and seconds
|
||||||
|
update_period_msec = update_period % 1000;
|
||||||
|
update_period -= update_period_msec;
|
||||||
|
update_period /= 1000;
|
||||||
|
|
||||||
|
// Buffer length by default fragment length
|
||||||
|
buffer_time = dacf->fraglen;
|
||||||
|
buffer_time_msec = buffer_time % 1000;
|
||||||
|
buffer_time -= buffer_time_msec;
|
||||||
|
buffer_time /= 1000;
|
||||||
|
|
||||||
|
// Fill DASH header
|
||||||
p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_HEADER,
|
p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_HEADER,
|
||||||
|
// availabilityStartTime
|
||||||
avaliable_time,
|
avaliable_time,
|
||||||
|
// publishTime
|
||||||
publish_time,
|
publish_time,
|
||||||
(ngx_uint_t) (dacf->fraglen / 1000),
|
// minimumUpdatePeriod
|
||||||
(ngx_uint_t) (dacf->fraglen / 1000),
|
update_period, update_period_msec,
|
||||||
|
// minBufferTime
|
||||||
|
buffer_time, buffer_time_msec,
|
||||||
|
// timeShiftBufferDepth
|
||||||
buffer_depth,
|
buffer_depth,
|
||||||
(ngx_uint_t) (dacf->fraglen / 500),
|
// suggestedPresentationDelay
|
||||||
avaliable_time); /* UTCTiming value for shaka-player */
|
presentation_delay, presentation_delay_msec
|
||||||
|
);
|
||||||
|
|
||||||
|
/* UTCTiming value */
|
||||||
|
switch (dacf->clock_compensation) {
|
||||||
|
case NGX_RTMP_DASH_CLOCK_COMPENSATION_NTP:
|
||||||
|
p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_CLOCK,
|
||||||
|
"ntp",
|
||||||
|
&dacf->clock_helper_uri
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case NGX_RTMP_DASH_CLOCK_COMPENSATION_HTTP_HEAD:
|
||||||
|
p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_CLOCK,
|
||||||
|
"http-head",
|
||||||
|
&dacf->clock_helper_uri
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case NGX_RTMP_DASH_CLOCK_COMPENSATION_HTTP_ISO:
|
||||||
|
p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_CLOCK,
|
||||||
|
"http-iso",
|
||||||
|
&dacf->clock_helper_uri
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_PERIOD);
|
||||||
|
|
||||||
n = ngx_write_fd(fd, buffer, p - buffer);
|
n = ngx_write_fd(fd, buffer, p - buffer);
|
||||||
|
|
||||||
|
@ -1520,6 +1621,7 @@ ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf)
|
||||||
conf->playlen = NGX_CONF_UNSET_MSEC;
|
conf->playlen = NGX_CONF_UNSET_MSEC;
|
||||||
conf->cleanup = NGX_CONF_UNSET;
|
conf->cleanup = NGX_CONF_UNSET;
|
||||||
conf->nested = NGX_CONF_UNSET;
|
conf->nested = NGX_CONF_UNSET;
|
||||||
|
conf->clock_compensation = NGX_CONF_UNSET;
|
||||||
|
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
@ -1537,6 +1639,9 @@ ngx_rtmp_dash_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000);
|
ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000);
|
||||||
ngx_conf_merge_value(conf->cleanup, prev->cleanup, 1);
|
ngx_conf_merge_value(conf->cleanup, prev->cleanup, 1);
|
||||||
ngx_conf_merge_value(conf->nested, prev->nested, 0);
|
ngx_conf_merge_value(conf->nested, prev->nested, 0);
|
||||||
|
ngx_conf_merge_uint_value(conf->clock_compensation, prev->clock_compensation,
|
||||||
|
NGX_RTMP_DASH_CLOCK_COMPENSATION_OFF);
|
||||||
|
ngx_conf_merge_str_value(conf->clock_helper_uri, prev->clock_helper_uri, "");
|
||||||
|
|
||||||
if (conf->fraglen) {
|
if (conf->fraglen) {
|
||||||
conf->winfrags = conf->playlen / conf->fraglen;
|
conf->winfrags = conf->playlen / conf->fraglen;
|
||||||
|
|
|
@ -24,3 +24,6 @@
|
||||||
* [notify_send_redirect](directives.md#notify_send_redirect)
|
* [notify_send_redirect](directives.md#notify_send_redirect)
|
||||||
* Client Caching
|
* Client Caching
|
||||||
* [hls_allow_client_cache](directives.md#hls_allow_client_cache)
|
* [hls_allow_client_cache](directives.md#hls_allow_client_cache)
|
||||||
|
* Dash MPD generation
|
||||||
|
* [dash_clock_compensation](directives.md#dash_clock_compensation)
|
||||||
|
* [dash_clock_helper_uri](directives.md#dash_clock_helper_uri)
|
||||||
|
|
|
@ -110,6 +110,8 @@ Table of Contents
|
||||||
* [dash_playlist_length](#dash_playlist_length)
|
* [dash_playlist_length](#dash_playlist_length)
|
||||||
* [dash_nested](#dash_nested)
|
* [dash_nested](#dash_nested)
|
||||||
* [dash_cleanup](#dash_cleanup)
|
* [dash_cleanup](#dash_cleanup)
|
||||||
|
* [dash_clock_compensation](#dash_clock_compensation)
|
||||||
|
* [dash_clock_helper_uri](#dash_clock_helper_uri)
|
||||||
* [Access log](#access-log)
|
* [Access log](#access-log)
|
||||||
* [access_log](#access_log)
|
* [access_log](#access_log)
|
||||||
* [log_format](#log_format)
|
* [log_format](#log_format)
|
||||||
|
@ -1605,6 +1607,45 @@ Init fragments are deleted after stream manifest is deleted.
|
||||||
dash_cleanup off;
|
dash_cleanup off;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### dash\_clock_compensation
|
||||||
|
Syntax: `dash_clock_compensation off|ntp|http_head|http_iso`
|
||||||
|
Context: rtmp, server, application
|
||||||
|
Default: off
|
||||||
|
|
||||||
|
Toggles MPEG-DASH clock compentation element output into MPD.
|
||||||
|
In this mode nginx provides `UTCTiming` element for MPEG-DASH manifest.
|
||||||
|
Clock compensation provided by DASH-client if possible.
|
||||||
|
- ntp - use NTP protocol
|
||||||
|
- http_head - client must fetch header `Date` from URI (`dash_clock_helper_uri`)
|
||||||
|
- http_iso - client must fetch date in ISO format from URI (`dash_clock_helper_uri`)
|
||||||
|
|
||||||
|
Standard section: 4.7.2. Service Provider Requirements and Guidelines
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dash\_clock_compensation off;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### dash\_clock_helper_uri
|
||||||
|
Syntax: `dash_clock_helper_uri URI`
|
||||||
|
Context: rtmp, server, application
|
||||||
|
Default: none
|
||||||
|
|
||||||
|
URI helper resource for clock compensation for client.
|
||||||
|
Clock compensation type:
|
||||||
|
- ntp - address of NTP-server
|
||||||
|
- http\_head - full HTTP uri
|
||||||
|
- http\_iso - full HTTP uri
|
||||||
|
|
||||||
|
Standard section: 4.7.2. Service Provider Requirements and Guidelines
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dash\_clock\_helper_uri http://rtmp-server/static/time.txt;
|
||||||
|
|
||||||
|
_or_
|
||||||
|
|
||||||
|
dash\_clock\_helper_uri http://rtmp-server/lua/time-iso;
|
||||||
|
```
|
||||||
|
|
||||||
## Access log
|
## Access log
|
||||||
|
|
||||||
#### access_log
|
#### access_log
|
||||||
|
|
|
@ -900,7 +900,7 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||||
if (v.profile[0] != '\0') ngx_memcpy(ctx->profile, v.profile, sizeof(v.profile));
|
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));
|
if (v.level[0] != '\0') ngx_memcpy(ctx->level, v.level, sizeof(v.level));
|
||||||
|
|
||||||
ngx_log_debug8(NGX_LOG_DEBUG, s->connection->log, 0,
|
ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
"codec: data frame: "
|
"codec: data frame: "
|
||||||
"width=%ui height=%ui duration=%.3f frame_rate=%.3f "
|
"width=%ui height=%ui duration=%.3f frame_rate=%.3f "
|
||||||
"video=%s (%ui) audio=%s (%ui)",
|
"video=%s (%ui) audio=%s (%ui)",
|
||||||
|
@ -910,6 +910,12 @@ ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
||||||
ngx_rtmp_get_audio_codec_name(ctx->audio_codec_id),
|
ngx_rtmp_get_audio_codec_name(ctx->audio_codec_id),
|
||||||
ctx->audio_codec_id);
|
ctx->audio_codec_id);
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
|
"codec: data frame: "
|
||||||
|
"video_rate=%.3f audio_rate=%.3f ",
|
||||||
|
ctx->video_data_rate, ctx->audio_data_rate
|
||||||
|
);
|
||||||
|
|
||||||
switch (cacf->meta) {
|
switch (cacf->meta) {
|
||||||
case NGX_RTMP_CODEC_META_ON:
|
case NGX_RTMP_CODEC_META_ON:
|
||||||
return ngx_rtmp_codec_reconstruct_meta(s);
|
return ngx_rtmp_codec_reconstruct_meta(s);
|
||||||
|
|
Loading…
Reference in a new issue