diff --git a/doc/README.md b/doc/README.md index 4d73dbb..318cca3 100644 --- a/doc/README.md +++ b/doc/README.md @@ -22,3 +22,5 @@ * Notify * [on_playlist](directives.md#on_playlist) * [notify_send_redirect](directives.md#notify_send_redirect) + * Client Caching + * [hls_allow_client_cache](directives.md#hls_allow_client_cache) diff --git a/doc/directives.md b/doc/directives.md index 5f46c39..e80cf13 100644 --- a/doc/directives.md +++ b/doc/directives.md @@ -98,6 +98,7 @@ Table of Contents * [hls_fragment_slicing](#hls_fragment_slicing) * [hls_variant](#hls_variant) * [hls_type](#hls_type) + * [hls_allow_client_cache](#hls_allow_client_cache) * [hls_keys](#hls_keys) * [hls_key_path](#hls_key_path) * [hls_key_url](#hls_key_url) @@ -1415,6 +1416,19 @@ is enough for the whole event. Default is `live`; hls_type event; ``` +#### hls_allow_client_cache +Syntax: `hls_allow_client_cache enabled|disabled` +Context: rtmp, server, application + +Enables (or disables) client cache with `#EXT-X-ALLOW-CACHE` playlist +directive. Setting value to enabled allows supported clients to +cache segments in a live DVR manner. Setting value to disabled explicitly +tells supported clients to never cache segments. +Unset by default (playlist directive will be absent). +```sh +hls_allow_client_cache enabled; +``` + #### hls_keys Syntax: `hls_keys on|off` Context: rtmp, server, application diff --git a/hls/ngx_rtmp_hls_module.c b/hls/ngx_rtmp_hls_module.c index a6888e8..d018811 100644 --- a/hls/ngx_rtmp_hls_module.c +++ b/hls/ngx_rtmp_hls_module.c @@ -110,6 +110,7 @@ typedef struct { ngx_msec_t max_audio_delay; size_t audio_buffer_size; ngx_flag_t cleanup; + ngx_uint_t allow_client_cache; ngx_array_t *variant; ngx_str_t base_url; ngx_int_t granularity; @@ -137,6 +138,9 @@ typedef struct { #define NGX_RTMP_HLS_TYPE_LIVE 1 #define NGX_RTMP_HLS_TYPE_EVENT 2 +#define NGX_RTMP_HLS_CACHE_DISABLED 1 +#define NGX_RTMP_HLS_CACHE_ENABLED 2 + static ngx_conf_enum_t ngx_rtmp_hls_naming_slots[] = { { ngx_string("sequential"), NGX_RTMP_HLS_NAMING_SEQUENTIAL }, @@ -167,6 +171,11 @@ static ngx_conf_enum_t ngx_rtmp_hls_type_slots[] = { { ngx_null_string, 0 } }; +static ngx_conf_enum_t ngx_rtmp_hls_cache[] = { + { ngx_string("enabled"), NGX_RTMP_HLS_CACHE_ENABLED }, + { ngx_string("disabled"), NGX_RTMP_HLS_CACHE_DISABLED }, + { ngx_null_string, 0 } +}; static ngx_command_t ngx_rtmp_hls_commands[] = { @@ -282,6 +291,13 @@ static ngx_command_t ngx_rtmp_hls_commands[] = { offsetof(ngx_rtmp_hls_app_conf_t, cleanup), NULL }, + { ngx_string("hls_allow_client_cache"), + 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, allow_client_cache), + &ngx_rtmp_hls_cache }, + { ngx_string("hls_variant"), NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, ngx_rtmp_hls_variant, @@ -564,6 +580,12 @@ ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) p = ngx_slprintf(p, end, "#EXT-X-PLAYLIST-TYPE:EVENT\n"); } + if (hacf->allow_client_cache == NGX_RTMP_HLS_CACHE_ENABLED) { + p = ngx_slprintf(p, end, "#EXT-X-ALLOW-CACHE:1\n"); + } else if (hacf->allow_client_cache == NGX_RTMP_HLS_CACHE_DISABLED) { + p = ngx_slprintf(p, end, "#EXT-X-ALLOW-CACHE:0\n"); + } + n = ngx_write_fd(fd, buffer, p - buffer); if (n < 0) { goto write_err; @@ -2440,6 +2462,7 @@ ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf) conf->max_audio_delay = NGX_CONF_UNSET_MSEC; conf->audio_buffer_size = NGX_CONF_UNSET_SIZE; conf->cleanup = NGX_CONF_UNSET; + conf->allow_client_cache = NGX_CONF_UNSET_UINT; conf->granularity = NGX_CONF_UNSET; conf->keys = NGX_CONF_UNSET; conf->frags_per_key = NGX_CONF_UNSET_UINT;