# HG changeset patch
# User Tracey Jaquith <tracey(a)archive.org>
# Date 1623797180 0
# Tue Jun 15 22:46:20 2021 +0000
# Node ID 1879d49fe0cf739f48287b5a38a83d3a1adab939
# Parent 5f765427c17ac8cf753967387562201cf4f78dc4
Add optional "mp4_exact_start" nginx config off/on to show video between keyframes.
archive.org has been using mod_h264_streaming with a similar "exact start" patch from me since 2013.
We just moved to nginx mp4 module and are using this patch.
The technique is to find the video keyframe just before the desired "start" time, and send
that down the wire so video playback can start immediately.
Next calculate how many video samples are between the keyframe and desired "start" time
and update the STTS atom where those samples move the duration from (typically) 1001 to 1.
This way, initial unwanted video frames play at ~1/30,000s -- so visually the
video & audio start playing immediately.
You can see an example before/after here (nginx binary built with mp4 module + patch):
https://pi.archive.org/0/items/CSPAN_20160425_022500_2011_White_House_Corre…https://pi.archive.org/0/items/CSPAN_20160425_022500_2011_White_House_Corre…
Tested on linux and macosx.
(this is me: https://github.com/traceypooh )
diff -r 5f765427c17a -r 1879d49fe0cf src/http/modules/ngx_http_mp4_module.c
--- a/src/http/modules/ngx_http_mp4_module.c Tue Jun 01 17:37:51 2021 +0300
+++ b/src/http/modules/ngx_http_mp4_module.c Tue Jun 15 22:46:20 2021 +0000
@@ -43,6 +43,7 @@
typedef struct {
size_t buffer_size;
size_t max_buffer_size;
+ ngx_flag_t exact_start;
} ngx_http_mp4_conf_t;
@@ -340,6 +341,13 @@
offsetof(ngx_http_mp4_conf_t, max_buffer_size),
NULL },
+ { ngx_string("mp4_exact_start"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_mp4_conf_t, exact_start),
+ NULL },
+
ngx_null_command
};
@@ -2156,6 +2164,83 @@
static ngx_int_t
+ngx_http_mp4_exact_start_video(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak)
+{
+ uint32_t n, speedup_samples, current_count;
+ ngx_uint_t sample_keyframe, start_sample_exact;
+ ngx_mp4_stts_entry_t *entry, *entries_array;
+ ngx_buf_t *data;
+
+ data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
+
+ // Find the keyframe just before the desired start time - so that we can emit an mp4
+ // where the first frame is a keyframe. We'll "speed up" the first frames to 1000x
+ // normal speed (typically), so they won't be noticed. But this way, perceptively,
+ // playback of the _video_ track can start immediately
+ // (and not have to wait until the keyframe _after_ the desired starting time frame).
+ start_sample_exact = trak->start_sample;
+ for (n = 0; n < trak->sync_samples_entries; n++) {
+ // each element of array is the sample number of a keyframe
+ // sync samples starts from 1 -- so subtract 1
+ sample_keyframe = ngx_mp4_get_32value(trak->stss_data_buf.pos + (n * 4)) - 1;
+ if (sample_keyframe <= trak->start_sample) {
+ start_sample_exact = sample_keyframe;
+ }
+ if (sample_keyframe >= trak->start_sample) {
+ break;
+ }
+ }
+
+ if (start_sample_exact < trak->start_sample) {
+ // We're going to prepend an entry with duration=1 for the frames we want to "not see".
+ // MOST of the time (eg: constant video framerate),
+ // we're taking a single element entry array and making it two.
+ speedup_samples = trak->start_sample - start_sample_exact;
+
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
+ "exact trak start_sample move %l to %l (speed up %d samples)\n",
+ trak->start_sample, start_sample_exact, speedup_samples);
+
+ entries_array = ngx_palloc(mp4->request->pool,
+ (1 + trak->time_to_sample_entries) * sizeof(ngx_mp4_stts_entry_t));
+ if (entries_array == NULL) {
+ return NGX_ERROR;
+ }
+ entry = &(entries_array[1]);
+ ngx_memcpy(entry, (ngx_mp4_stts_entry_t *)data->pos,
+ trak->time_to_sample_entries * sizeof(ngx_mp4_stts_entry_t));
+
+ current_count = ngx_mp4_get_32value(entry->count);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
+ "exact split in 2 video STTS entry from count:%d", current_count);
+
+ if (current_count <= speedup_samples) {
+ return NGX_ERROR;
+ }
+
+ ngx_mp4_set_32value(entry->count, current_count - speedup_samples);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
+ "exact split new[1]: count:%d duration:%d",
+ ngx_mp4_get_32value(entry->count),
+ ngx_mp4_get_32value(entry->duration));
+ entry--;
+ ngx_mp4_set_32value(entry->count, speedup_samples);
+ ngx_mp4_set_32value(entry->duration, 1);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
+ "exact split new[0]: count:%d duration:1",
+ ngx_mp4_get_32value(entry->count));
+
+ data->pos = (u_char *) entry;
+ trak->time_to_sample_entries++;
+ trak->start_sample = start_sample_exact;
+ data->last = (u_char *) (entry + trak->time_to_sample_entries);
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
{
@@ -2164,6 +2249,8 @@
ngx_buf_t *data;
ngx_uint_t start_sample, entries, start_sec;
ngx_mp4_stts_entry_t *entry, *end;
+ ngx_http_mp4_conf_t *conf;
+
if (start) {
start_sec = mp4->start;
@@ -2238,6 +2325,10 @@
"start_sample:%ui, new count:%uD",
trak->start_sample, count - rest);
+ conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
+ if (conf->exact_start) {
+ ngx_http_mp4_exact_start_video(mp4, trak);
+ }
} else {
ngx_mp4_set_32value(entry->count, rest);
data->last = (u_char *) (entry + 1);
@@ -3590,6 +3681,7 @@
conf->buffer_size = NGX_CONF_UNSET_SIZE;
conf->max_buffer_size = NGX_CONF_UNSET_SIZE;
+ conf->exact_start = NGX_CONF_UNSET;
return conf;
}
Hi,
I am trying to run the test suite, but it seems that, no matter how I build
Nginx, it systematically fails.
It seems that, most (all?) of the time, tests fail because Nginx returns
403 error codes, e.g.:
./ssi_waited.t ............................. 1/3
# Failed test 'waited non-active'
# at ./ssi_waited.t line 60.
# 'HTTP/1.1 403 Forbidden
# Server: nginx/1.21.0
# Date: Sat, 03 Jul 2021 08:06:00 GMT
# Content-Type: text/html
# Connection: close
#
# <html>
# <head><title>403 Forbidden</title></head>
# <body>
# <center><h1>403 Forbidden</h1></center>
# <hr><center>nginx/1.21.0</center>
# </body>
# </html>
# '
# doesn't match '(?^m:^xFIRSTxWAITEDxSECONDx$)'
The runtime configuration is the default one from nginx-1.20.1.tar.gz
(conf/nginx.conf).
I must be doing something wrong with the build or run time configuration,
but I cannot pinpoint what. Any idea?
Best,
Hugo
--
Hugo Lefeuvre (hle) | www.owl.eu.com
RSA4096_ 360B 03B3 BF27 4F4D 7A3F D5E8 14AA 1EB8 A247 3DFD
ed25519_ 37B2 6D38 0B25 B8A2 6B9F 3A65 A36F 5357 5F2D DC4C
# HG changeset patch
# User Alexey Radkov <alexey.radkov(a)gmail.com>
# Date 1629395487 -10800
# Thu Aug 19 20:51:27 2021 +0300
# Node ID a1065b2252855730ed8e5368c88fe41a7ff5a698
# Parent 13d0c1d26d47c203b1874ca1ffdb7a9ba7fd2d77
Avoid unnecessary restriction on nohash http variables.
When I use variables with long names albeit being tagged as
NGX_HTTP_VARIABLE_NOHASH, Nginx says "could not build variables_hash,
you should increase variables_hash_bucket_size: 64". It seems that this is
an unnecessary restriction, as soon as the hash gets only built for variables
with names[n].key.data == NULL (note that other pieces in ngx_hash_init()
where the macro NGX_HASH_ELT_SIZE is used, are always guarded with this
condition). This fix puts this same condition into the only unguarded piece:
when testing against the hash_bucket_size.
The issue arises after assignment of key[n].key.data = NULL without symmetric
assignment of key[n].key.len in ngx_http_variables_init_vars(): after this,
the key[n].key comes to an inconsistent state. Perhaps this was made
intentionally, as hash initialization in other places seems to follow the
same pattern (for instance, see how ngx_hash_init() gets called from
ngx_http_upstream_hide_headers_hash()).
Without this fix, I must put in the config "variables_hash_bucket_size 128;"
even if the long-named variables are nohash.
diff -r 13d0c1d26d47 -r a1065b225285 src/core/ngx_hash.c
--- a/src/core/ngx_hash.c Fri Aug 13 03:57:47 2021 -0400
+++ b/src/core/ngx_hash.c Thu Aug 19 20:51:27 2021 +0300
@@ -274,6 +274,9 @@
}
for (n = 0; n < nelts; n++) {
+ if (names[n].key.data == NULL) {
+ continue;
+ }
if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
{
ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
Hello!
On Tue, Sep 18, 2018 at 08:12:20AM -0400, Thomas Ward wrote:
> Downstream in Ubuntu, it has been proposed to demote pcre3 and
> use pcre2 instead as it is newer.
> https://trac.nginx.org/nginx/ticket/720 shows it was marked 4
> years ago that NGINX does not support pcre2. Are there any
> plans to use pcre2 instead of pcre3?
There are no immediate plans.
When we last checked, there were no problems with PCRE, but PCRE2
wasn't available in most distributions we support, making the
switch mostly meaningless.
Also, it looks like PCRE2 is still not supported even by Exim,
which is the parent project of PCRE and PCRE2:
https://bugs.exim.org/show_bug.cgi?id=1878
As such, adding PCRE2 support to nginx looks premature.
--
Maxim Dounin
http://mdounin.ru/
Hello,
I want to write a module for an nginx that runs on a device with a private
IP address and behind NAT, connects to a remote server and adds the newly
created connection to the list of connections handled by nginx. At this
point the remote server will invert the connection and start making
requests.
I tried studying the documentation on nginx.org, but I am not able to get
an idea about how to achieve this.
Can you please give me a suggestion about how to do it?
Thank you,
Ottavio
--
Non c'è più forza nella normalità, c'è solo monotonia
details: https://hg.nginx.org/nginx/rev/bfbc52374adc
branches:
changeset: 7918:bfbc52374adc
user: Maxim Dounin <mdounin(a)mdounin.ru>
date: Tue Aug 31 18:13:46 2021 +0300
description:
nginx-1.21.2-RELEASE
diffstat:
docs/xml/nginx/changes.xml | 107 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 107 insertions(+), 0 deletions(-)
diffs (117 lines):
diff -r f0ab1db646d5 -r bfbc52374adc docs/xml/nginx/changes.xml
--- a/docs/xml/nginx/changes.xml Tue Aug 31 17:54:54 2021 +0300
+++ b/docs/xml/nginx/changes.xml Tue Aug 31 18:13:46 2021 +0300
@@ -5,6 +5,113 @@
<change_log title="nginx">
+<changes ver="1.21.2" date="2021-08-31">
+
+<change type="change">
+<para lang="ru">
+теперь nginx возвращает ошибку,
+если в запросе по протоколу HTTP/1.0 присутствует
+строка заголовка "Transfer-Encoding".
+</para>
+<para lang="en">
+now nginx rejects HTTP/1.0 requests
+with the "Transfer-Encoding" header line.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+экспортные шифры больше не поддерживаются.
+</para>
+<para lang="en">
+export ciphers are no longer supported.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+совместимость с OpenSSL 3.0.
+</para>
+<para lang="en">
+OpenSSL 3.0 compatibility.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+теперь серверу аутентификации почтового прокси-сервера
+передаются строки заголовка "Auth-SSL-Protocol" и "Auth-SSL-Cipher".<br/>
+Спасибо Rob Mueller.
+</para>
+<para lang="en">
+the "Auth-SSL-Protocol" and "Auth-SSL-Cipher" header lines
+are now passed to the mail proxy authentication server.<br/>
+Thanks to Rob Mueller.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+API для обработки тела запроса
+теперь позволяет буферизировать обрабатываемые данные.
+</para>
+<para lang="en">
+request body filters API
+now permits buffering of the data being processed.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+SSL-соединения к бэкендам в модуле stream
+могли зависать после SSL handshake.
+</para>
+<para lang="en">
+backend SSL connections in the stream module
+might hang after an SSL handshake.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+уровень безопасности, доступный в OpenSSL 1.1.0 и новее,
+не учитывался при загрузке сертификатов сервера,
+если был задан через "@SECLEVEL=N" в директиве ssl_ciphers.
+</para>
+<para lang="en">
+the security level, which is available in OpenSSL 1.1.0 or newer,
+did not affect loading of the server certificates
+when set with "@SECLEVEL=N" in the "ssl_ciphers" directive.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+SSL-соединения с gRPC-бэкендами могли зависать,
+если использовались методы select, poll или /dev/poll.
+</para>
+<para lang="en">
+SSL connections with gRPC backends might hang
+if select, poll, or /dev/poll methods were used.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при использовании HTTP/2
+тело запроса всегда записывалось на диск,
+если в запросе не было строки заголовка "Content-Length".
+</para>
+<para lang="en">
+when using HTTP/2
+client request body was always written to disk
+if the "Content-Length" header line was not present in the request.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="1.21.1" date="2021-07-06">
<change type="change">