Merge pull request #2 from jbochi/program-date-time

Program date time
This commit is contained in:
Sergey 2015-07-03 01:13:46 +03:00
commit 95471ae880

View file

@ -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,21 @@ 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:");
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;
end = p + sizeof(buffer);
@ -586,11 +619,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 +639,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 +851,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 +930,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_codec_ctx_t *codec_ctx;
@ -871,6 +956,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;
@ -963,6 +1049,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;
@ -2317,6 +2404,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;
@ -2348,6 +2436,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,