nginxtra 1.4.7.9 → 1.6.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/nginxtra +1 -1
- data/bin/nginxtra_rails +1 -1
- data/lib/nginxtra/version.rb +1 -1
- data/vendor/nginx/CHANGES +286 -19
- data/vendor/nginx/CHANGES.ru +296 -22
- data/vendor/nginx/auto/cc/clang +4 -3
- data/vendor/nginx/auto/cc/conf +23 -0
- data/vendor/nginx/auto/cc/msvc +1 -0
- data/vendor/nginx/auto/cc/name +1 -1
- data/vendor/nginx/auto/cc/owc +4 -4
- data/vendor/nginx/auto/cc/sunc +1 -1
- data/vendor/nginx/auto/endianness +2 -2
- data/vendor/nginx/auto/feature +1 -1
- data/vendor/nginx/auto/include +1 -1
- data/vendor/nginx/auto/lib/libatomic/make +3 -1
- data/vendor/nginx/auto/lib/openssl/conf +4 -0
- data/vendor/nginx/auto/lib/openssl/make +1 -1
- data/vendor/nginx/auto/lib/pcre/conf +5 -0
- data/vendor/nginx/auto/lib/pcre/make +11 -11
- data/vendor/nginx/auto/lib/pcre/makefile.bcc +4 -3
- data/vendor/nginx/auto/lib/pcre/makefile.msvc +2 -1
- data/vendor/nginx/auto/lib/pcre/makefile.owc +2 -1
- data/vendor/nginx/auto/lib/perl/make +1 -0
- data/vendor/nginx/auto/lib/test +1 -1
- data/vendor/nginx/auto/lib/zlib/make +22 -1
- data/vendor/nginx/auto/modules +8 -0
- data/vendor/nginx/auto/options +3 -0
- data/vendor/nginx/auto/os/darwin +1 -1
- data/vendor/nginx/auto/os/linux +32 -0
- data/vendor/nginx/auto/os/win32 +12 -1
- data/vendor/nginx/auto/sources +8 -2
- data/vendor/nginx/auto/types/sizeof +1 -1
- data/vendor/nginx/auto/types/typedef +1 -1
- data/vendor/nginx/auto/types/uintptr_t +1 -1
- data/vendor/nginx/auto/unix +13 -1
- data/vendor/nginx/conf/mime.types +11 -2
- data/vendor/nginx/conf/nginx.conf +3 -4
- data/vendor/nginx/contrib/README +6 -0
- data/vendor/nginx/contrib/vim/ftdetect/nginx.vim +4 -0
- data/vendor/nginx/contrib/vim/indent/nginx.vim +11 -0
- data/vendor/nginx/contrib/vim/syntax/nginx.vim +703 -0
- data/vendor/nginx/src/core/nginx.c +2 -7
- data/vendor/nginx/src/core/nginx.h +2 -2
- data/vendor/nginx/src/core/ngx_conf_file.c +8 -88
- data/vendor/nginx/src/core/ngx_conf_file.h +3 -3
- data/vendor/nginx/src/core/ngx_config.h +2 -2
- data/vendor/nginx/src/core/ngx_connection.c +100 -29
- data/vendor/nginx/src/core/ngx_connection.h +11 -0
- data/vendor/nginx/src/core/ngx_core.h +1 -0
- data/vendor/nginx/src/core/ngx_cycle.c +23 -99
- data/vendor/nginx/src/core/ngx_cycle.h +2 -0
- data/vendor/nginx/src/core/ngx_file.c +100 -8
- data/vendor/nginx/src/core/ngx_file.h +3 -0
- data/vendor/nginx/src/core/ngx_hash.c +6 -9
- data/vendor/nginx/src/core/ngx_inet.c +93 -5
- data/vendor/nginx/src/core/ngx_inet.h +4 -2
- data/vendor/nginx/src/core/ngx_list.c +1 -9
- data/vendor/nginx/src/core/ngx_log.c +132 -30
- data/vendor/nginx/src/core/ngx_log.h +5 -2
- data/vendor/nginx/src/core/ngx_open_file_cache.c +67 -1
- data/vendor/nginx/src/core/ngx_palloc.c +5 -2
- data/vendor/nginx/src/core/ngx_proxy_protocol.c +91 -0
- data/vendor/nginx/src/core/ngx_proxy_protocol.h +23 -0
- data/vendor/nginx/src/core/ngx_resolver.c +1080 -285
- data/vendor/nginx/src/core/ngx_resolver.h +33 -3
- data/vendor/nginx/src/core/ngx_slab.c +7 -2
- data/vendor/nginx/src/core/ngx_slab.h +2 -0
- data/vendor/nginx/src/core/ngx_string.c +78 -13
- data/vendor/nginx/src/core/ngx_string.h +2 -0
- data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +2 -2
- data/vendor/nginx/src/event/modules/ngx_epoll_module.c +13 -5
- data/vendor/nginx/src/event/modules/ngx_select_module.c +1 -1
- data/vendor/nginx/src/event/modules/ngx_win32_select_module.c +2 -2
- data/vendor/nginx/src/event/ngx_event.c +0 -1
- data/vendor/nginx/src/event/ngx_event.h +7 -6
- data/vendor/nginx/src/event/ngx_event_accept.c +6 -4
- data/vendor/nginx/src/event/ngx_event_connect.c +2 -2
- data/vendor/nginx/src/event/ngx_event_openssl.c +304 -13
- data/vendor/nginx/src/event/ngx_event_openssl.h +20 -1
- data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +35 -23
- data/vendor/nginx/src/event/ngx_event_pipe.c +15 -30
- data/vendor/nginx/src/http/modules/ngx_http_access_module.c +115 -35
- data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +1 -1
- data/vendor/nginx/src/http/modules/ngx_http_auth_request_module.c +444 -0
- data/vendor/nginx/src/http/modules/ngx_http_autoindex_module.c +2 -1
- data/vendor/nginx/src/http/modules/ngx_http_charset_filter_module.c +1 -1
- data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +1 -3
- data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +251 -36
- data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +9 -5
- data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +5 -3
- data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +1 -1
- data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +4 -0
- data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +8 -2
- data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +5 -1
- data/vendor/nginx/src/http/modules/ngx_http_map_module.c +3 -3
- data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +21 -10
- data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +669 -197
- data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +93 -60
- data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +13 -6
- data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +20 -1
- data/vendor/nginx/src/http/modules/ngx_http_referer_module.c +132 -74
- data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +18 -12
- data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +22 -20
- data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +121 -3
- data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +5 -0
- data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +3 -0
- data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +123 -91
- data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +29 -19
- data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +2 -5
- data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +215 -19
- data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +32 -6
- data/vendor/nginx/src/http/modules/perl/nginx.xs +4 -7
- data/vendor/nginx/src/http/modules/perl/ngx_http_perl_module.c +2 -2
- data/vendor/nginx/src/http/ngx_http.c +17 -7
- data/vendor/nginx/src/http/ngx_http_cache.h +4 -2
- data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +4 -2
- data/vendor/nginx/src/http/ngx_http_core_module.c +63 -50
- data/vendor/nginx/src/http/ngx_http_core_module.h +5 -0
- data/vendor/nginx/src/http/ngx_http_file_cache.c +115 -3
- data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -6
- data/vendor/nginx/src/http/ngx_http_parse.c +88 -10
- data/vendor/nginx/src/http/ngx_http_postpone_filter_module.c +2 -4
- data/vendor/nginx/src/http/ngx_http_request.c +116 -8
- data/vendor/nginx/src/http/ngx_http_request.h +5 -1
- data/vendor/nginx/src/http/ngx_http_request_body.c +7 -7
- data/vendor/nginx/src/http/ngx_http_script.c +6 -5
- data/vendor/nginx/src/http/ngx_http_spdy.c +889 -271
- data/vendor/nginx/src/http/ngx_http_spdy.h +51 -28
- data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +382 -167
- data/vendor/nginx/src/http/ngx_http_spdy_module.c +65 -8
- data/vendor/nginx/src/http/ngx_http_spdy_module.h +5 -0
- data/vendor/nginx/src/http/ngx_http_special_response.c +1 -1
- data/vendor/nginx/src/http/ngx_http_upstream.c +290 -114
- data/vendor/nginx/src/http/ngx_http_upstream.h +9 -5
- data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +32 -24
- data/vendor/nginx/src/http/ngx_http_variables.c +40 -6
- data/vendor/nginx/src/http/ngx_http_write_filter_module.c +12 -5
- data/vendor/nginx/src/mail/ngx_mail.c +4 -2
- data/vendor/nginx/src/mail/ngx_mail.h +2 -0
- data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +0 -1
- data/vendor/nginx/src/mail/ngx_mail_core_module.c +2 -1
- data/vendor/nginx/src/mail/ngx_mail_handler.c +17 -4
- data/vendor/nginx/src/mail/ngx_mail_parse.c +32 -2
- data/vendor/nginx/src/mail/ngx_mail_proxy_module.c +54 -7
- data/vendor/nginx/src/mail/ngx_mail_smtp_handler.c +50 -78
- data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +48 -11
- data/vendor/nginx/src/mail/ngx_mail_ssl_module.h +3 -0
- data/vendor/nginx/src/os/unix/ngx_channel.c +3 -1
- data/vendor/nginx/src/os/unix/ngx_darwin_config.h +1 -0
- data/vendor/nginx/src/os/unix/ngx_darwin_init.c +1 -1
- data/vendor/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +14 -16
- data/vendor/nginx/src/os/unix/ngx_errno.h +3 -0
- data/vendor/nginx/src/os/unix/ngx_files.h +10 -16
- data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +6 -0
- data/vendor/nginx/src/os/unix/ngx_freebsd_init.c +1 -1
- data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +1 -1
- data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.h +2 -2
- data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +17 -19
- data/vendor/nginx/src/os/unix/ngx_linux_config.h +8 -2
- data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +20 -22
- data/vendor/nginx/src/os/unix/ngx_posix_config.h +1 -0
- data/vendor/nginx/src/os/unix/ngx_process.c +5 -0
- data/vendor/nginx/src/os/unix/ngx_process_cycle.c +15 -3
- data/vendor/nginx/src/os/unix/ngx_readv_chain.c +2 -1
- data/vendor/nginx/src/os/unix/ngx_recv.c +4 -1
- data/vendor/nginx/src/os/unix/ngx_solaris_config.h +1 -0
- data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +14 -16
- metadata +8 -2
@@ -368,9 +368,11 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|
368
368
|
if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
|
369
369
|
goto failed;
|
370
370
|
}
|
371
|
+
|
372
|
+
r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
|
371
373
|
}
|
372
374
|
|
373
|
-
if (ctx->nomem) {
|
375
|
+
if (ctx->nomem || in == NULL) {
|
374
376
|
|
375
377
|
/* flush busy buffers */
|
376
378
|
|
@@ -620,8 +622,6 @@ ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
|
|
620
622
|
return NGX_ERROR;
|
621
623
|
}
|
622
624
|
|
623
|
-
r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
|
624
|
-
|
625
625
|
ctx->last_out = &ctx->out;
|
626
626
|
ctx->crc32 = crc32(0L, Z_NULL, 0);
|
627
627
|
ctx->flush = Z_NO_FLUSH;
|
@@ -854,6 +854,8 @@ ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
|
|
854
854
|
*ctx->last_out = cl;
|
855
855
|
ctx->last_out = &cl->next;
|
856
856
|
|
857
|
+
r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED;
|
858
|
+
|
857
859
|
return NGX_OK;
|
858
860
|
}
|
859
861
|
|
@@ -38,7 +38,7 @@ static ngx_conf_enum_t ngx_http_gzip_static[] = {
|
|
38
38
|
static ngx_command_t ngx_http_gzip_static_commands[] = {
|
39
39
|
|
40
40
|
{ ngx_string("gzip_static"),
|
41
|
-
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|
|
41
|
+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
42
42
|
ngx_conf_set_enum_slot,
|
43
43
|
NGX_HTTP_LOC_CONF_OFFSET,
|
44
44
|
offsetof(ngx_http_gzip_static_conf_t, enable),
|
@@ -478,7 +478,12 @@ ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in)
|
|
478
478
|
"image buf: %uz", size);
|
479
479
|
|
480
480
|
rest = ctx->image + ctx->length - p;
|
481
|
-
|
481
|
+
|
482
|
+
if (size > rest) {
|
483
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
484
|
+
"image filter: too big response");
|
485
|
+
return NGX_ERROR;
|
486
|
+
}
|
482
487
|
|
483
488
|
p = ngx_cpymem(p, b->pos, size);
|
484
489
|
b->pos += size;
|
@@ -567,7 +572,8 @@ ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
|
|
567
572
|
ngx_http_clean_header(r);
|
568
573
|
|
569
574
|
r->headers_out.status = NGX_HTTP_OK;
|
570
|
-
|
575
|
+
r->headers_out.content_type_len = sizeof("application/json") - 1;
|
576
|
+
ngx_str_set(&r->headers_out.content_type, "application/json");
|
571
577
|
r->headers_out.content_type_lowcase = NULL;
|
572
578
|
|
573
579
|
if (ctx == NULL) {
|
@@ -451,6 +451,8 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
|
|
451
451
|
|
452
452
|
node = ngx_slab_alloc_locked(ctx->shpool, size);
|
453
453
|
if (node == NULL) {
|
454
|
+
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
|
455
|
+
"could not allocate node%s", ctx->shpool->log_ctx);
|
454
456
|
return NGX_ERROR;
|
455
457
|
}
|
456
458
|
}
|
@@ -674,6 +676,8 @@ ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)
|
|
674
676
|
ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z",
|
675
677
|
&shm_zone->shm.name);
|
676
678
|
|
679
|
+
ctx->shpool->log_nomem = 0;
|
680
|
+
|
677
681
|
return NGX_OK;
|
678
682
|
}
|
679
683
|
|
@@ -912,7 +916,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|
912
916
|
continue;
|
913
917
|
}
|
914
918
|
|
915
|
-
if (
|
919
|
+
if (ngx_strcmp(value[i].data, "nodelay") == 0) {
|
916
920
|
nodelay = 1;
|
917
921
|
continue;
|
918
922
|
}
|
@@ -131,7 +131,7 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|
131
131
|
}
|
132
132
|
|
133
133
|
if (!value->valid) {
|
134
|
-
value = ngx_http_get_flushed_variable(r, (
|
134
|
+
value = ngx_http_get_flushed_variable(r, (uintptr_t) value->data);
|
135
135
|
|
136
136
|
if (value == NULL || value->not_found) {
|
137
137
|
value = &ngx_http_variable_null_value;
|
@@ -414,7 +414,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
|
414
414
|
var = ctx->var_values.elts;
|
415
415
|
|
416
416
|
for (i = 0; i < ctx->var_values.nelts; i++) {
|
417
|
-
if (index == (
|
417
|
+
if (index == (intptr_t) var[i].data) {
|
418
418
|
var = &var[i];
|
419
419
|
goto found;
|
420
420
|
}
|
@@ -429,7 +429,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
|
429
429
|
var->no_cacheable = 0;
|
430
430
|
var->not_found = 0;
|
431
431
|
var->len = 0;
|
432
|
-
var->data = (u_char *) index;
|
432
|
+
var->data = (u_char *) (intptr_t) index;
|
433
433
|
|
434
434
|
goto found;
|
435
435
|
}
|
@@ -197,7 +197,6 @@ ngx_http_memcached_handler(ngx_http_request_t *r)
|
|
197
197
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
198
198
|
}
|
199
199
|
|
200
|
-
ctx->rest = NGX_HTTP_MEMCACHED_END;
|
201
200
|
ctx->request = r;
|
202
201
|
|
203
202
|
ngx_http_set_ctx(r, ctx, ngx_http_memcached_module);
|
@@ -309,10 +308,15 @@ ngx_http_memcached_process_header(ngx_http_request_t *r)
|
|
309
308
|
|
310
309
|
found:
|
311
310
|
|
312
|
-
*p = '\0';
|
313
|
-
|
314
|
-
line.len = p - u->buffer.pos - 1;
|
315
311
|
line.data = u->buffer.pos;
|
312
|
+
line.len = p - u->buffer.pos;
|
313
|
+
|
314
|
+
if (line.len == 0 || *(p - 1) != CR) {
|
315
|
+
goto no_valid;
|
316
|
+
}
|
317
|
+
|
318
|
+
*p = '\0';
|
319
|
+
line.len--;
|
316
320
|
|
317
321
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
318
322
|
"memcached: \"%V\"", &line);
|
@@ -387,10 +391,9 @@ found:
|
|
387
391
|
length:
|
388
392
|
|
389
393
|
start = p;
|
394
|
+
p = line.data + line.len;
|
390
395
|
|
391
|
-
|
392
|
-
|
393
|
-
u->headers_in.content_length_n = ngx_atoof(start, p - start - 1);
|
396
|
+
u->headers_in.content_length_n = ngx_atoof(start, p - start);
|
394
397
|
if (u->headers_in.content_length_n == -1) {
|
395
398
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
396
399
|
"memcached sent invalid length in response \"%V\" "
|
@@ -401,7 +404,7 @@ found:
|
|
401
404
|
|
402
405
|
u->headers_in.status_n = 200;
|
403
406
|
u->state->status = 200;
|
404
|
-
u->buffer.pos = p + 1;
|
407
|
+
u->buffer.pos = p + sizeof(CRLF) - 1;
|
405
408
|
|
406
409
|
return NGX_OK;
|
407
410
|
}
|
@@ -410,8 +413,10 @@ found:
|
|
410
413
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
411
414
|
"key: \"%V\" was not found by memcached", &ctx->key);
|
412
415
|
|
416
|
+
u->headers_in.content_length_n = 0;
|
413
417
|
u->headers_in.status_n = 404;
|
414
418
|
u->state->status = 404;
|
419
|
+
u->buffer.pos = p + sizeof("END" CRLF) - 1;
|
415
420
|
u->keepalive = 1;
|
416
421
|
|
417
422
|
return NGX_OK;
|
@@ -435,7 +440,13 @@ ngx_http_memcached_filter_init(void *data)
|
|
435
440
|
|
436
441
|
u = ctx->request->upstream;
|
437
442
|
|
438
|
-
u->
|
443
|
+
if (u->headers_in.status_n != 404) {
|
444
|
+
u->length = u->headers_in.content_length_n + NGX_HTTP_MEMCACHED_END;
|
445
|
+
ctx->rest = NGX_HTTP_MEMCACHED_END;
|
446
|
+
|
447
|
+
} else {
|
448
|
+
u->length = 0;
|
449
|
+
}
|
439
450
|
|
440
451
|
return NGX_OK;
|
441
452
|
}
|
@@ -509,7 +520,7 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
|
|
509
520
|
return NGX_OK;
|
510
521
|
}
|
511
522
|
|
512
|
-
last += u->length - NGX_HTTP_MEMCACHED_END;
|
523
|
+
last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
|
513
524
|
|
514
525
|
if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
|
515
526
|
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
|
@@ -27,14 +27,15 @@
|
|
27
27
|
#define NGX_HTTP_MP4_CTTS_ATOM 15
|
28
28
|
#define NGX_HTTP_MP4_CTTS_DATA 16
|
29
29
|
#define NGX_HTTP_MP4_STSC_ATOM 17
|
30
|
-
#define
|
30
|
+
#define NGX_HTTP_MP4_STSC_START 18
|
31
31
|
#define NGX_HTTP_MP4_STSC_DATA 19
|
32
|
-
#define
|
33
|
-
#define
|
34
|
-
#define
|
35
|
-
#define
|
36
|
-
#define
|
37
|
-
#define
|
32
|
+
#define NGX_HTTP_MP4_STSC_END 20
|
33
|
+
#define NGX_HTTP_MP4_STSZ_ATOM 21
|
34
|
+
#define NGX_HTTP_MP4_STSZ_DATA 22
|
35
|
+
#define NGX_HTTP_MP4_STCO_ATOM 23
|
36
|
+
#define NGX_HTTP_MP4_STCO_DATA 24
|
37
|
+
#define NGX_HTTP_MP4_CO64_ATOM 25
|
38
|
+
#define NGX_HTTP_MP4_CO64_DATA 26
|
38
39
|
|
39
40
|
#define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
|
40
41
|
|
@@ -62,10 +63,15 @@ typedef struct {
|
|
62
63
|
uint32_t chunks;
|
63
64
|
|
64
65
|
ngx_uint_t start_sample;
|
66
|
+
ngx_uint_t end_sample;
|
65
67
|
ngx_uint_t start_chunk;
|
66
|
-
ngx_uint_t
|
67
|
-
|
68
|
+
ngx_uint_t end_chunk;
|
69
|
+
ngx_uint_t start_chunk_samples;
|
70
|
+
ngx_uint_t end_chunk_samples;
|
71
|
+
uint64_t start_chunk_samples_size;
|
72
|
+
uint64_t end_chunk_samples_size;
|
68
73
|
off_t start_offset;
|
74
|
+
off_t end_offset;
|
69
75
|
|
70
76
|
size_t tkhd_size;
|
71
77
|
size_t mdhd_size;
|
@@ -95,7 +101,8 @@ typedef struct {
|
|
95
101
|
ngx_buf_t ctts_atom_buf;
|
96
102
|
ngx_buf_t ctts_data_buf;
|
97
103
|
ngx_buf_t stsc_atom_buf;
|
98
|
-
ngx_buf_t
|
104
|
+
ngx_buf_t stsc_start_chunk_buf;
|
105
|
+
ngx_buf_t stsc_end_chunk_buf;
|
99
106
|
ngx_buf_t stsc_data_buf;
|
100
107
|
ngx_buf_t stsz_atom_buf;
|
101
108
|
ngx_buf_t stsz_data_buf;
|
@@ -104,7 +111,8 @@ typedef struct {
|
|
104
111
|
ngx_buf_t co64_atom_buf;
|
105
112
|
ngx_buf_t co64_data_buf;
|
106
113
|
|
107
|
-
ngx_mp4_stsc_entry_t
|
114
|
+
ngx_mp4_stsc_entry_t stsc_start_chunk_entry;
|
115
|
+
ngx_mp4_stsc_entry_t stsc_end_chunk_entry;
|
108
116
|
} ngx_http_mp4_trak_t;
|
109
117
|
|
110
118
|
|
@@ -121,6 +129,7 @@ typedef struct {
|
|
121
129
|
off_t end;
|
122
130
|
off_t content_length;
|
123
131
|
ngx_uint_t start;
|
132
|
+
ngx_uint_t length;
|
124
133
|
uint32_t timescale;
|
125
134
|
ngx_http_request_t *request;
|
126
135
|
ngx_array_t trak;
|
@@ -157,7 +166,11 @@ typedef struct {
|
|
157
166
|
#define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8)
|
158
167
|
#define ngx_mp4_atom_data(mp4) mp4->buffer_pos
|
159
168
|
#define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8)
|
160
|
-
|
169
|
+
|
170
|
+
|
171
|
+
#define ngx_mp4_atom_next(mp4, n) \
|
172
|
+
mp4->buffer_pos += (size_t) n; \
|
173
|
+
mp4->offset += n
|
161
174
|
|
162
175
|
|
163
176
|
#define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \
|
@@ -202,6 +215,8 @@ typedef struct {
|
|
202
215
|
&((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1]
|
203
216
|
|
204
217
|
|
218
|
+
static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r);
|
219
|
+
|
205
220
|
static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
|
206
221
|
static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
|
207
222
|
ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size);
|
@@ -213,7 +228,7 @@ static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4,
|
|
213
228
|
static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
|
214
229
|
uint64_t atom_data_size);
|
215
230
|
static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
|
216
|
-
off_t start_offset);
|
231
|
+
off_t start_offset, off_t end_offset);
|
217
232
|
static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
|
218
233
|
uint64_t atom_data_size);
|
219
234
|
static ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4,
|
@@ -252,18 +267,26 @@ static ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4,
|
|
252
267
|
uint64_t atom_data_size);
|
253
268
|
static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
254
269
|
ngx_http_mp4_trak_t *trak);
|
270
|
+
static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
271
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
255
272
|
static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
|
256
273
|
uint64_t atom_data_size);
|
257
274
|
static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
258
275
|
ngx_http_mp4_trak_t *trak);
|
276
|
+
static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
277
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
259
278
|
static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
|
260
279
|
uint64_t atom_data_size);
|
261
280
|
static void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
262
281
|
ngx_http_mp4_trak_t *trak);
|
282
|
+
static void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
283
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
263
284
|
static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
|
264
285
|
uint64_t atom_data_size);
|
265
286
|
static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
266
287
|
ngx_http_mp4_trak_t *trak);
|
288
|
+
static ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
289
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
267
290
|
static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
|
268
291
|
uint64_t atom_data_size);
|
269
292
|
static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
@@ -280,10 +303,12 @@ static ngx_int_t ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|
280
303
|
ngx_http_mp4_trak_t *trak);
|
281
304
|
static void ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4,
|
282
305
|
ngx_http_mp4_trak_t *trak, off_t adjustment);
|
306
|
+
|
283
307
|
static char *ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
284
308
|
static void *ngx_http_mp4_create_conf(ngx_conf_t *cf);
|
285
309
|
static char *ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child);
|
286
310
|
|
311
|
+
|
287
312
|
static ngx_command_t ngx_http_mp4_commands[] = {
|
288
313
|
|
289
314
|
{ ngx_string("mp4"),
|
@@ -395,8 +420,8 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|
395
420
|
{
|
396
421
|
u_char *last;
|
397
422
|
size_t root;
|
398
|
-
ngx_int_t rc, start;
|
399
|
-
ngx_uint_t level;
|
423
|
+
ngx_int_t rc, start, end;
|
424
|
+
ngx_uint_t level, length;
|
400
425
|
ngx_str_t path, value;
|
401
426
|
ngx_log_t *log;
|
402
427
|
ngx_buf_t *b;
|
@@ -501,6 +526,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|
501
526
|
r->allow_ranges = 1;
|
502
527
|
|
503
528
|
start = -1;
|
529
|
+
length = 0;
|
504
530
|
r->headers_out.content_length_n = of.size;
|
505
531
|
mp4 = NULL;
|
506
532
|
b = NULL;
|
@@ -518,47 +544,72 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|
518
544
|
ngx_set_errno(0);
|
519
545
|
start = (int) (strtod((char *) value.data, NULL) * 1000);
|
520
546
|
|
521
|
-
if (ngx_errno
|
522
|
-
|
547
|
+
if (ngx_errno != 0) {
|
548
|
+
start = -1;
|
549
|
+
}
|
550
|
+
}
|
551
|
+
|
552
|
+
if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) {
|
553
|
+
|
554
|
+
ngx_set_errno(0);
|
555
|
+
end = (int) (strtod((char *) value.data, NULL) * 1000);
|
556
|
+
|
557
|
+
if (ngx_errno != 0) {
|
558
|
+
end = -1;
|
559
|
+
}
|
560
|
+
|
561
|
+
if (end > 0) {
|
562
|
+
if (start < 0) {
|
563
|
+
start = 0;
|
564
|
+
}
|
523
565
|
|
524
|
-
|
525
|
-
|
526
|
-
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
566
|
+
if (end > start) {
|
567
|
+
length = end - start;
|
527
568
|
}
|
569
|
+
}
|
570
|
+
}
|
571
|
+
}
|
528
572
|
|
529
|
-
|
530
|
-
|
531
|
-
mp4->file.log = r->connection->log;;
|
532
|
-
mp4->end = of.size;
|
533
|
-
mp4->start = (ngx_uint_t) start;
|
534
|
-
mp4->request = r;
|
573
|
+
if (start >= 0) {
|
574
|
+
r->single_range = 1;
|
535
575
|
|
536
|
-
|
576
|
+
mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t));
|
577
|
+
if (mp4 == NULL) {
|
578
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
579
|
+
}
|
537
580
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
581
|
+
mp4->file.fd = of.fd;
|
582
|
+
mp4->file.name = path;
|
583
|
+
mp4->file.log = r->connection->log;
|
584
|
+
mp4->end = of.size;
|
585
|
+
mp4->start = (ngx_uint_t) start;
|
586
|
+
mp4->length = length;
|
587
|
+
mp4->request = r;
|
542
588
|
|
543
|
-
|
544
|
-
mp4 = NULL;
|
589
|
+
switch (ngx_http_mp4_process(mp4)) {
|
545
590
|
|
546
|
-
|
591
|
+
case NGX_DECLINED:
|
592
|
+
if (mp4->buffer) {
|
593
|
+
ngx_pfree(r->pool, mp4->buffer);
|
594
|
+
}
|
547
595
|
|
548
|
-
|
549
|
-
|
550
|
-
break;
|
596
|
+
ngx_pfree(r->pool, mp4);
|
597
|
+
mp4 = NULL;
|
551
598
|
|
552
|
-
|
553
|
-
if (mp4->buffer) {
|
554
|
-
ngx_pfree(r->pool, mp4->buffer);
|
555
|
-
}
|
599
|
+
break;
|
556
600
|
|
557
|
-
|
601
|
+
case NGX_OK:
|
602
|
+
r->headers_out.content_length_n = mp4->content_length;
|
603
|
+
break;
|
558
604
|
|
559
|
-
|
560
|
-
|
605
|
+
default: /* NGX_ERROR */
|
606
|
+
if (mp4->buffer) {
|
607
|
+
ngx_pfree(r->pool, mp4->buffer);
|
561
608
|
}
|
609
|
+
|
610
|
+
ngx_pfree(r->pool, mp4);
|
611
|
+
|
612
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
562
613
|
}
|
563
614
|
}
|
564
615
|
|
@@ -638,15 +689,15 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|
638
689
|
static ngx_int_t
|
639
690
|
ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
640
691
|
{
|
641
|
-
off_t start_offset, adjustment;
|
692
|
+
off_t start_offset, end_offset, adjustment;
|
642
693
|
ngx_int_t rc;
|
643
694
|
ngx_uint_t i, j;
|
644
695
|
ngx_chain_t **prev;
|
645
696
|
ngx_http_mp4_trak_t *trak;
|
646
697
|
ngx_http_mp4_conf_t *conf;
|
647
698
|
|
648
|
-
|
649
|
-
"mp4 start:%ui", mp4->start);
|
699
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
700
|
+
"mp4 start:%ui, length:%ui", mp4->start, mp4->length);
|
650
701
|
|
651
702
|
conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
|
652
703
|
|
@@ -688,6 +739,7 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|
688
739
|
}
|
689
740
|
|
690
741
|
start_offset = mp4->end;
|
742
|
+
end_offset = 0;
|
691
743
|
trak = mp4->trak.elts;
|
692
744
|
|
693
745
|
for (i = 0; i < mp4->trak.nelts; i++) {
|
@@ -735,6 +787,10 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|
735
787
|
start_offset = trak[i].start_offset;
|
736
788
|
}
|
737
789
|
|
790
|
+
if (end_offset < trak[i].end_offset) {
|
791
|
+
end_offset = trak[i].end_offset;
|
792
|
+
}
|
793
|
+
|
738
794
|
*prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM];
|
739
795
|
prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next;
|
740
796
|
|
@@ -746,6 +802,10 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|
746
802
|
}
|
747
803
|
}
|
748
804
|
|
805
|
+
if (end_offset < start_offset) {
|
806
|
+
end_offset = start_offset;
|
807
|
+
}
|
808
|
+
|
749
809
|
mp4->moov_size += 8;
|
750
810
|
|
751
811
|
ngx_mp4_set_32value(mp4->moov_atom_header, mp4->moov_size);
|
@@ -762,7 +822,7 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|
762
822
|
}
|
763
823
|
|
764
824
|
adjustment = mp4->ftyp_size + mp4->moov_size
|
765
|
-
+ ngx_http_mp4_update_mdat_atom(mp4, start_offset)
|
825
|
+
+ ngx_http_mp4_update_mdat_atom(mp4, start_offset, end_offset)
|
766
826
|
- start_offset;
|
767
827
|
|
768
828
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
@@ -948,7 +1008,7 @@ ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
948
1008
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom");
|
949
1009
|
|
950
1010
|
if (atom_data_size > 1024
|
951
|
-
|| ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end)
|
1011
|
+
|| ngx_mp4_atom_data(mp4) + (size_t) atom_data_size > mp4->buffer_end)
|
952
1012
|
{
|
953
1013
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
954
1014
|
"\"%s\" mp4 ftyp atom is too large:%uL",
|
@@ -1006,7 +1066,7 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1006
1066
|
|
1007
1067
|
no_mdat = (mp4->mdat_atom.buf == NULL);
|
1008
1068
|
|
1009
|
-
if (no_mdat && mp4->start == 0) {
|
1069
|
+
if (no_mdat && mp4->start == 0 && mp4->length == 0) {
|
1010
1070
|
/*
|
1011
1071
|
* send original file if moov atom resides before
|
1012
1072
|
* mdat atom and client requests integral file
|
@@ -1105,7 +1165,8 @@ ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1105
1165
|
|
1106
1166
|
|
1107
1167
|
static size_t
|
1108
|
-
ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset
|
1168
|
+
ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset,
|
1169
|
+
off_t end_offset)
|
1109
1170
|
{
|
1110
1171
|
off_t atom_data_size;
|
1111
1172
|
u_char *atom_header;
|
@@ -1113,15 +1174,16 @@ ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset)
|
|
1113
1174
|
uint64_t atom_size;
|
1114
1175
|
ngx_buf_t *atom;
|
1115
1176
|
|
1116
|
-
atom_data_size =
|
1177
|
+
atom_data_size = end_offset - start_offset;
|
1117
1178
|
mp4->mdat_data.buf->file_pos = start_offset;
|
1179
|
+
mp4->mdat_data.buf->file_last = end_offset;
|
1118
1180
|
|
1119
1181
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1120
1182
|
"mdat new offset @%O:%O", start_offset, atom_data_size);
|
1121
1183
|
|
1122
1184
|
atom_header = mp4->mdat_atom_header;
|
1123
1185
|
|
1124
|
-
if ((uint64_t) atom_data_size > 0xffffffff) {
|
1186
|
+
if ((uint64_t) atom_data_size > (uint64_t) 0xffffffff) {
|
1125
1187
|
atom_size = 1;
|
1126
1188
|
atom_header_size = sizeof(ngx_mp4_atom_header64_t);
|
1127
1189
|
ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t),
|
@@ -1196,7 +1258,7 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1196
1258
|
u_char *atom_header;
|
1197
1259
|
size_t atom_size;
|
1198
1260
|
uint32_t timescale;
|
1199
|
-
uint64_t duration;
|
1261
|
+
uint64_t duration, start_time, length_time;
|
1200
1262
|
ngx_buf_t *atom;
|
1201
1263
|
ngx_mp4_mvhd_atom_t *mvhd_atom;
|
1202
1264
|
ngx_mp4_mvhd64_atom_t *mvhd64_atom;
|
@@ -1239,7 +1301,24 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1239
1301
|
"mvhd timescale:%uD, duration:%uL, time:%.3fs",
|
1240
1302
|
timescale, duration, (double) duration / timescale);
|
1241
1303
|
|
1242
|
-
|
1304
|
+
start_time = (uint64_t) mp4->start * timescale / 1000;
|
1305
|
+
|
1306
|
+
if (duration < start_time) {
|
1307
|
+
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
1308
|
+
"\"%s\" mp4 start time exceeds file duration",
|
1309
|
+
mp4->file.name.data);
|
1310
|
+
return NGX_ERROR;
|
1311
|
+
}
|
1312
|
+
|
1313
|
+
duration -= start_time;
|
1314
|
+
|
1315
|
+
if (mp4->length) {
|
1316
|
+
length_time = (uint64_t) mp4->length * timescale / 1000;
|
1317
|
+
|
1318
|
+
if (duration > length_time) {
|
1319
|
+
duration = length_time;
|
1320
|
+
}
|
1321
|
+
}
|
1243
1322
|
|
1244
1323
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1245
1324
|
"mvhd new duration:%uL, time:%.3fs",
|
@@ -1296,7 +1375,7 @@ ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1296
1375
|
|
1297
1376
|
trak->out[NGX_HTTP_MP4_TRAK_ATOM].buf = atom;
|
1298
1377
|
|
1299
|
-
atom_end = mp4->buffer_pos + atom_data_size;
|
1378
|
+
atom_end = mp4->buffer_pos + (size_t) atom_data_size;
|
1300
1379
|
atom_file_end = mp4->offset + atom_data_size;
|
1301
1380
|
|
1302
1381
|
rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_trak_atoms, atom_data_size);
|
@@ -1386,7 +1465,7 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1386
1465
|
{
|
1387
1466
|
u_char *atom_header;
|
1388
1467
|
size_t atom_size;
|
1389
|
-
uint64_t duration;
|
1468
|
+
uint64_t duration, start_time, length_time;
|
1390
1469
|
ngx_buf_t *atom;
|
1391
1470
|
ngx_http_mp4_trak_t *trak;
|
1392
1471
|
ngx_mp4_tkhd_atom_t *tkhd_atom;
|
@@ -1426,7 +1505,23 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1426
1505
|
"tkhd duration:%uL, time:%.3fs",
|
1427
1506
|
duration, (double) duration / mp4->timescale);
|
1428
1507
|
|
1429
|
-
|
1508
|
+
start_time = (uint64_t) mp4->start * mp4->timescale / 1000;
|
1509
|
+
|
1510
|
+
if (duration <= start_time) {
|
1511
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1512
|
+
"tkhd duration is less than start time");
|
1513
|
+
return NGX_DECLINED;
|
1514
|
+
}
|
1515
|
+
|
1516
|
+
duration -= start_time;
|
1517
|
+
|
1518
|
+
if (mp4->length) {
|
1519
|
+
length_time = (uint64_t) mp4->length * mp4->timescale / 1000;
|
1520
|
+
|
1521
|
+
if (duration > length_time) {
|
1522
|
+
duration = length_time;
|
1523
|
+
}
|
1524
|
+
}
|
1430
1525
|
|
1431
1526
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1432
1527
|
"tkhd new duration:%uL, time:%.3fs",
|
@@ -1529,7 +1624,7 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1529
1624
|
u_char *atom_header;
|
1530
1625
|
size_t atom_size;
|
1531
1626
|
uint32_t timescale;
|
1532
|
-
uint64_t duration;
|
1627
|
+
uint64_t duration, start_time, length_time;
|
1533
1628
|
ngx_buf_t *atom;
|
1534
1629
|
ngx_http_mp4_trak_t *trak;
|
1535
1630
|
ngx_mp4_mdhd_atom_t *mdhd_atom;
|
@@ -1571,7 +1666,23 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|
1571
1666
|
"mdhd timescale:%uD, duration:%uL, time:%.3fs",
|
1572
1667
|
timescale, duration, (double) duration / timescale);
|
1573
1668
|
|
1574
|
-
|
1669
|
+
start_time = (uint64_t) mp4->start * timescale / 1000;
|
1670
|
+
|
1671
|
+
if (duration <= start_time) {
|
1672
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1673
|
+
"mdhd duration is less than start time");
|
1674
|
+
return NGX_DECLINED;
|
1675
|
+
}
|
1676
|
+
|
1677
|
+
duration -= start_time;
|
1678
|
+
|
1679
|
+
if (mp4->length) {
|
1680
|
+
length_time = (uint64_t) mp4->length * timescale / 1000;
|
1681
|
+
|
1682
|
+
if (duration > length_time) {
|
1683
|
+
duration = length_time;
|
1684
|
+
}
|
1685
|
+
}
|
1575
1686
|
|
1576
1687
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1577
1688
|
"mdhd new duration:%uL, time:%.3fs",
|
@@ -1944,13 +2055,9 @@ static ngx_int_t
|
|
1944
2055
|
ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
1945
2056
|
ngx_http_mp4_trak_t *trak)
|
1946
2057
|
{
|
1947
|
-
size_t
|
1948
|
-
|
1949
|
-
|
1950
|
-
ngx_buf_t *atom, *data;
|
1951
|
-
ngx_uint_t start_sample;
|
1952
|
-
ngx_mp4_stts_atom_t *stts_atom;
|
1953
|
-
ngx_mp4_stts_entry_t *entry, *end;
|
2058
|
+
size_t atom_size;
|
2059
|
+
ngx_buf_t *atom, *data;
|
2060
|
+
ngx_mp4_stts_atom_t *stts_atom;
|
1954
2061
|
|
1955
2062
|
/*
|
1956
2063
|
* mdia.minf.stbl.stts updating requires trak->timescale
|
@@ -1969,12 +2076,60 @@ ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
|
1969
2076
|
return NGX_ERROR;
|
1970
2077
|
}
|
1971
2078
|
|
1972
|
-
|
1973
|
-
|
2079
|
+
if (ngx_http_mp4_crop_stts_data(mp4, trak, 1) != NGX_OK) {
|
2080
|
+
return NGX_ERROR;
|
2081
|
+
}
|
2082
|
+
|
2083
|
+
if (ngx_http_mp4_crop_stts_data(mp4, trak, 0) != NGX_OK) {
|
2084
|
+
return NGX_ERROR;
|
2085
|
+
}
|
1974
2086
|
|
1975
2087
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
1976
|
-
"time-to-sample
|
2088
|
+
"time-to-sample entries:%uD", trak->time_to_sample_entries);
|
1977
2089
|
|
2090
|
+
atom_size = sizeof(ngx_mp4_stts_atom_t) + (data->last - data->pos);
|
2091
|
+
trak->size += atom_size;
|
2092
|
+
|
2093
|
+
atom = trak->out[NGX_HTTP_MP4_STTS_ATOM].buf;
|
2094
|
+
stts_atom = (ngx_mp4_stts_atom_t *) atom->pos;
|
2095
|
+
ngx_mp4_set_32value(stts_atom->size, atom_size);
|
2096
|
+
ngx_mp4_set_32value(stts_atom->entries, trak->time_to_sample_entries);
|
2097
|
+
|
2098
|
+
return NGX_OK;
|
2099
|
+
}
|
2100
|
+
|
2101
|
+
|
2102
|
+
static ngx_int_t
|
2103
|
+
ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
2104
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
2105
|
+
{
|
2106
|
+
uint32_t count, duration, rest;
|
2107
|
+
uint64_t start_time;
|
2108
|
+
ngx_buf_t *data;
|
2109
|
+
ngx_uint_t start_sample, entries, start_sec;
|
2110
|
+
ngx_mp4_stts_entry_t *entry, *end;
|
2111
|
+
|
2112
|
+
if (start) {
|
2113
|
+
start_sec = mp4->start;
|
2114
|
+
|
2115
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2116
|
+
"mp4 stts crop start_time:%ui", start_sec);
|
2117
|
+
|
2118
|
+
} else if (mp4->length) {
|
2119
|
+
start_sec = mp4->length;
|
2120
|
+
|
2121
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2122
|
+
"mp4 stts crop end_time:%ui", start_sec);
|
2123
|
+
|
2124
|
+
} else {
|
2125
|
+
return NGX_OK;
|
2126
|
+
}
|
2127
|
+
|
2128
|
+
data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
|
2129
|
+
|
2130
|
+
start_time = (uint64_t) start_sec * trak->timescale / 1000;
|
2131
|
+
|
2132
|
+
entries = trak->time_to_sample_entries;
|
1978
2133
|
start_sample = 0;
|
1979
2134
|
entry = (ngx_mp4_stts_entry_t *) data->pos;
|
1980
2135
|
end = (ngx_mp4_stts_entry_t *) data->last;
|
@@ -1983,13 +2138,13 @@ ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
|
1983
2138
|
count = ngx_mp4_get_32value(entry->count);
|
1984
2139
|
duration = ngx_mp4_get_32value(entry->duration);
|
1985
2140
|
|
1986
|
-
|
1987
|
-
"count:%uD, duration:%uD",
|
2141
|
+
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2142
|
+
"time:%uL, count:%uD, duration:%uD",
|
2143
|
+
start_time, count, duration);
|
1988
2144
|
|
1989
2145
|
if (start_time < (uint64_t) count * duration) {
|
1990
2146
|
start_sample += (ngx_uint_t) (start_time / duration);
|
1991
|
-
|
1992
|
-
ngx_mp4_set_32value(entry->count, count);
|
2147
|
+
rest = (uint32_t) (start_time / duration);
|
1993
2148
|
goto found;
|
1994
2149
|
}
|
1995
2150
|
|
@@ -1999,27 +2154,44 @@ ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
|
1999
2154
|
entry++;
|
2000
2155
|
}
|
2001
2156
|
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2157
|
+
if (start) {
|
2158
|
+
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
2159
|
+
"start time is out mp4 stts samples in \"%s\"",
|
2160
|
+
mp4->file.name.data);
|
2005
2161
|
|
2006
|
-
|
2162
|
+
return NGX_ERROR;
|
2163
|
+
|
2164
|
+
} else {
|
2165
|
+
trak->end_sample = trak->start_sample + start_sample;
|
2166
|
+
|
2167
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2168
|
+
"end_sample:%ui", trak->end_sample);
|
2169
|
+
|
2170
|
+
return NGX_OK;
|
2171
|
+
}
|
2007
2172
|
|
2008
2173
|
found:
|
2009
2174
|
|
2010
|
-
|
2011
|
-
|
2175
|
+
if (start) {
|
2176
|
+
ngx_mp4_set_32value(entry->count, count - rest);
|
2177
|
+
data->pos = (u_char *) entry;
|
2178
|
+
trak->time_to_sample_entries = entries;
|
2179
|
+
trak->start_sample = start_sample;
|
2012
2180
|
|
2013
|
-
|
2181
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2182
|
+
"start_sample:%ui, new count:%uD",
|
2183
|
+
trak->start_sample, count - rest);
|
2014
2184
|
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2185
|
+
} else {
|
2186
|
+
ngx_mp4_set_32value(entry->count, rest);
|
2187
|
+
data->last = (u_char *) (entry + 1);
|
2188
|
+
trak->time_to_sample_entries -= entries - 1;
|
2189
|
+
trak->end_sample = trak->start_sample + start_sample;
|
2018
2190
|
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2191
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2192
|
+
"end_sample:%ui, new count:%uD",
|
2193
|
+
trak->end_sample, rest);
|
2194
|
+
}
|
2023
2195
|
|
2024
2196
|
return NGX_OK;
|
2025
2197
|
}
|
@@ -2101,7 +2273,7 @@ ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
|
2101
2273
|
ngx_http_mp4_trak_t *trak)
|
2102
2274
|
{
|
2103
2275
|
size_t atom_size;
|
2104
|
-
uint32_t
|
2276
|
+
uint32_t sample, start_sample, *entry, *end;
|
2105
2277
|
ngx_buf_t *atom, *data;
|
2106
2278
|
ngx_http_mp4_stss_atom_t *stss_atom;
|
2107
2279
|
|
@@ -2120,18 +2292,79 @@ ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
|
2120
2292
|
return NGX_OK;
|
2121
2293
|
}
|
2122
2294
|
|
2295
|
+
ngx_http_mp4_crop_stss_data(mp4, trak, 1);
|
2296
|
+
ngx_http_mp4_crop_stss_data(mp4, trak, 0);
|
2297
|
+
|
2298
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2299
|
+
"sync sample entries:%uD", trak->sync_samples_entries);
|
2300
|
+
|
2301
|
+
if (trak->sync_samples_entries) {
|
2302
|
+
entry = (uint32_t *) data->pos;
|
2303
|
+
end = (uint32_t *) data->last;
|
2304
|
+
|
2305
|
+
start_sample = trak->start_sample;
|
2306
|
+
|
2307
|
+
while (entry < end) {
|
2308
|
+
sample = ngx_mp4_get_32value(entry);
|
2309
|
+
sample -= start_sample;
|
2310
|
+
ngx_mp4_set_32value(entry, sample);
|
2311
|
+
entry++;
|
2312
|
+
}
|
2313
|
+
|
2314
|
+
} else {
|
2315
|
+
trak->out[NGX_HTTP_MP4_STSS_DATA].buf = NULL;
|
2316
|
+
}
|
2317
|
+
|
2318
|
+
atom_size = sizeof(ngx_http_mp4_stss_atom_t) + (data->last - data->pos);
|
2319
|
+
trak->size += atom_size;
|
2320
|
+
|
2321
|
+
atom = trak->out[NGX_HTTP_MP4_STSS_ATOM].buf;
|
2322
|
+
stss_atom = (ngx_http_mp4_stss_atom_t *) atom->pos;
|
2323
|
+
|
2324
|
+
ngx_mp4_set_32value(stss_atom->size, atom_size);
|
2325
|
+
ngx_mp4_set_32value(stss_atom->entries, trak->sync_samples_entries);
|
2326
|
+
|
2327
|
+
return NGX_OK;
|
2328
|
+
}
|
2329
|
+
|
2330
|
+
|
2331
|
+
static void
|
2332
|
+
ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
2333
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
2334
|
+
{
|
2335
|
+
uint32_t sample, start_sample, *entry, *end;
|
2336
|
+
ngx_buf_t *data;
|
2337
|
+
ngx_uint_t entries;
|
2338
|
+
|
2123
2339
|
/* sync samples starts from 1 */
|
2124
|
-
start_sample = trak->start_sample + 1;
|
2125
|
-
entries = trak->sync_samples_entries;
|
2126
2340
|
|
2341
|
+
if (start) {
|
2342
|
+
start_sample = trak->start_sample + 1;
|
2343
|
+
|
2344
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2345
|
+
"mp4 stss crop start_sample:%uD", start_sample);
|
2346
|
+
|
2347
|
+
} else if (mp4->length) {
|
2348
|
+
start_sample = trak->end_sample + 1;
|
2349
|
+
|
2350
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2351
|
+
"mp4 stss crop end_sample:%uD", start_sample);
|
2352
|
+
|
2353
|
+
} else {
|
2354
|
+
return;
|
2355
|
+
}
|
2356
|
+
|
2357
|
+
data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
|
2358
|
+
|
2359
|
+
entries = trak->sync_samples_entries;
|
2127
2360
|
entry = (uint32_t *) data->pos;
|
2128
2361
|
end = (uint32_t *) data->last;
|
2129
2362
|
|
2130
2363
|
while (entry < end) {
|
2131
2364
|
sample = ngx_mp4_get_32value(entry);
|
2132
2365
|
|
2133
|
-
|
2134
|
-
"
|
2366
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2367
|
+
"sync:%uD", sample);
|
2135
2368
|
|
2136
2369
|
if (sample >= start_sample) {
|
2137
2370
|
goto found;
|
@@ -2141,35 +2374,19 @@ ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
|
2141
2374
|
entry++;
|
2142
2375
|
}
|
2143
2376
|
|
2144
|
-
|
2145
|
-
|
2146
|
-
mp4->file.name.data);
|
2147
|
-
|
2148
|
-
return NGX_ERROR;
|
2377
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2378
|
+
"sample is out of mp4 stss atom");
|
2149
2379
|
|
2150
2380
|
found:
|
2151
2381
|
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2382
|
+
if (start) {
|
2383
|
+
data->pos = (u_char *) entry;
|
2384
|
+
trak->sync_samples_entries = entries;
|
2155
2385
|
|
2156
|
-
|
2157
|
-
|
2158
|
-
|
2159
|
-
ngx_mp4_set_32value(entry, sample);
|
2160
|
-
entry++;
|
2386
|
+
} else {
|
2387
|
+
data->last = (u_char *) entry;
|
2388
|
+
trak->sync_samples_entries -= entries;
|
2161
2389
|
}
|
2162
|
-
|
2163
|
-
atom_size = sizeof(ngx_http_mp4_stss_atom_t) + (data->last - data->pos);
|
2164
|
-
trak->size += atom_size;
|
2165
|
-
|
2166
|
-
atom = trak->out[NGX_HTTP_MP4_STSS_ATOM].buf;
|
2167
|
-
stss_atom = (ngx_http_mp4_stss_atom_t *) atom->pos;
|
2168
|
-
|
2169
|
-
ngx_mp4_set_32value(stss_atom->size, atom_size);
|
2170
|
-
ngx_mp4_set_32value(stss_atom->entries, entries);
|
2171
|
-
|
2172
|
-
return NGX_OK;
|
2173
2390
|
}
|
2174
2391
|
|
2175
2392
|
|
@@ -2253,11 +2470,9 @@ static void
|
|
2253
2470
|
ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
2254
2471
|
ngx_http_mp4_trak_t *trak)
|
2255
2472
|
{
|
2256
|
-
size_t
|
2257
|
-
|
2258
|
-
|
2259
|
-
ngx_mp4_ctts_atom_t *ctts_atom;
|
2260
|
-
ngx_mp4_ctts_entry_t *entry, *end;
|
2473
|
+
size_t atom_size;
|
2474
|
+
ngx_buf_t *atom, *data;
|
2475
|
+
ngx_mp4_ctts_atom_t *ctts_atom;
|
2261
2476
|
|
2262
2477
|
/*
|
2263
2478
|
* mdia.minf.stbl.ctts updating requires trak->start_sample
|
@@ -2274,8 +2489,61 @@ ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
|
2274
2489
|
return;
|
2275
2490
|
}
|
2276
2491
|
|
2492
|
+
ngx_http_mp4_crop_ctts_data(mp4, trak, 1);
|
2493
|
+
ngx_http_mp4_crop_ctts_data(mp4, trak, 0);
|
2494
|
+
|
2495
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2496
|
+
"composition offset entries:%uD",
|
2497
|
+
trak->composition_offset_entries);
|
2498
|
+
|
2499
|
+
if (trak->composition_offset_entries == 0) {
|
2500
|
+
trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL;
|
2501
|
+
trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = NULL;
|
2502
|
+
return;
|
2503
|
+
}
|
2504
|
+
|
2505
|
+
atom_size = sizeof(ngx_mp4_ctts_atom_t) + (data->last - data->pos);
|
2506
|
+
trak->size += atom_size;
|
2507
|
+
|
2508
|
+
atom = trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf;
|
2509
|
+
ctts_atom = (ngx_mp4_ctts_atom_t *) atom->pos;
|
2510
|
+
|
2511
|
+
ngx_mp4_set_32value(ctts_atom->size, atom_size);
|
2512
|
+
ngx_mp4_set_32value(ctts_atom->entries, trak->composition_offset_entries);
|
2513
|
+
|
2514
|
+
return;
|
2515
|
+
}
|
2516
|
+
|
2517
|
+
|
2518
|
+
static void
|
2519
|
+
ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
2520
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
2521
|
+
{
|
2522
|
+
uint32_t count, start_sample, rest;
|
2523
|
+
ngx_buf_t *data;
|
2524
|
+
ngx_uint_t entries;
|
2525
|
+
ngx_mp4_ctts_entry_t *entry, *end;
|
2526
|
+
|
2277
2527
|
/* sync samples starts from 1 */
|
2278
|
-
|
2528
|
+
|
2529
|
+
if (start) {
|
2530
|
+
start_sample = trak->start_sample + 1;
|
2531
|
+
|
2532
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2533
|
+
"mp4 ctts crop start_sample:%uD", start_sample);
|
2534
|
+
|
2535
|
+
} else if (mp4->length) {
|
2536
|
+
start_sample = trak->end_sample - trak->start_sample + 1;
|
2537
|
+
|
2538
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2539
|
+
"mp4 ctts crop end_sample:%uD", start_sample);
|
2540
|
+
|
2541
|
+
} else {
|
2542
|
+
return;
|
2543
|
+
}
|
2544
|
+
|
2545
|
+
data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
|
2546
|
+
|
2279
2547
|
entries = trak->composition_offset_entries;
|
2280
2548
|
entry = (ngx_mp4_ctts_entry_t *) data->pos;
|
2281
2549
|
end = (ngx_mp4_ctts_entry_t *) data->last;
|
@@ -2284,12 +2552,11 @@ ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
|
2284
2552
|
count = ngx_mp4_get_32value(entry->count);
|
2285
2553
|
|
2286
2554
|
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2287
|
-
"
|
2555
|
+
"sample:%uD, count:%uD, offset:%uD",
|
2288
2556
|
start_sample, count, ngx_mp4_get_32value(entry->offset));
|
2289
2557
|
|
2290
2558
|
if (start_sample <= count) {
|
2291
|
-
|
2292
|
-
ngx_mp4_set_32value(entry->count, count);
|
2559
|
+
rest = start_sample - 1;
|
2293
2560
|
goto found;
|
2294
2561
|
}
|
2295
2562
|
|
@@ -2298,24 +2565,25 @@ ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
|
2298
2565
|
entry++;
|
2299
2566
|
}
|
2300
2567
|
|
2301
|
-
|
2302
|
-
|
2568
|
+
if (start) {
|
2569
|
+
data->pos = (u_char *) end;
|
2570
|
+
trak->composition_offset_entries = 0;
|
2571
|
+
}
|
2303
2572
|
|
2304
2573
|
return;
|
2305
2574
|
|
2306
2575
|
found:
|
2307
2576
|
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
atom = trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf;
|
2313
|
-
ctts_atom = (ngx_mp4_ctts_atom_t *) atom->pos;
|
2577
|
+
if (start) {
|
2578
|
+
ngx_mp4_set_32value(entry->count, count - rest);
|
2579
|
+
data->pos = (u_char *) entry;
|
2580
|
+
trak->composition_offset_entries = entries;
|
2314
2581
|
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2582
|
+
} else {
|
2583
|
+
ngx_mp4_set_32value(entry->count, rest);
|
2584
|
+
data->last = (u_char *) (entry + 1);
|
2585
|
+
trak->composition_offset_entries -= entries - 1;
|
2586
|
+
}
|
2319
2587
|
}
|
2320
2588
|
|
2321
2589
|
|
@@ -2394,11 +2662,10 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
|
2394
2662
|
ngx_http_mp4_trak_t *trak)
|
2395
2663
|
{
|
2396
2664
|
size_t atom_size;
|
2397
|
-
uint32_t
|
2398
|
-
|
2399
|
-
ngx_buf_t *atom, *data, *buf;
|
2665
|
+
uint32_t chunk;
|
2666
|
+
ngx_buf_t *atom, *data;
|
2400
2667
|
ngx_mp4_stsc_atom_t *stsc_atom;
|
2401
|
-
ngx_mp4_stsc_entry_t *entry, *
|
2668
|
+
ngx_mp4_stsc_entry_t *entry, *end;
|
2402
2669
|
|
2403
2670
|
/*
|
2404
2671
|
* mdia.minf.stbl.stsc updating requires trak->start_sample
|
@@ -2425,15 +2692,97 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
|
2425
2692
|
return NGX_ERROR;
|
2426
2693
|
}
|
2427
2694
|
|
2428
|
-
|
2695
|
+
if (ngx_http_mp4_crop_stsc_data(mp4, trak, 1) != NGX_OK) {
|
2696
|
+
return NGX_ERROR;
|
2697
|
+
}
|
2698
|
+
|
2699
|
+
if (ngx_http_mp4_crop_stsc_data(mp4, trak, 0) != NGX_OK) {
|
2700
|
+
return NGX_ERROR;
|
2701
|
+
}
|
2702
|
+
|
2703
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2704
|
+
"sample-to-chunk entries:%uD",
|
2705
|
+
trak->sample_to_chunk_entries);
|
2706
|
+
|
2707
|
+
entry = (ngx_mp4_stsc_entry_t *) data->pos;
|
2708
|
+
end = (ngx_mp4_stsc_entry_t *) data->last;
|
2709
|
+
|
2710
|
+
while (entry < end) {
|
2711
|
+
chunk = ngx_mp4_get_32value(entry->chunk);
|
2712
|
+
chunk -= trak->start_chunk;
|
2713
|
+
ngx_mp4_set_32value(entry->chunk, chunk);
|
2714
|
+
entry++;
|
2715
|
+
}
|
2716
|
+
|
2717
|
+
atom_size = sizeof(ngx_mp4_stsc_atom_t)
|
2718
|
+
+ trak->sample_to_chunk_entries * sizeof(ngx_mp4_stsc_entry_t);
|
2719
|
+
|
2720
|
+
trak->size += atom_size;
|
2721
|
+
|
2722
|
+
atom = trak->out[NGX_HTTP_MP4_STSC_ATOM].buf;
|
2723
|
+
stsc_atom = (ngx_mp4_stsc_atom_t *) atom->pos;
|
2724
|
+
|
2725
|
+
ngx_mp4_set_32value(stsc_atom->size, atom_size);
|
2726
|
+
ngx_mp4_set_32value(stsc_atom->entries, trak->sample_to_chunk_entries);
|
2727
|
+
|
2728
|
+
return NGX_OK;
|
2729
|
+
}
|
2730
|
+
|
2731
|
+
|
2732
|
+
static ngx_int_t
|
2733
|
+
ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
2734
|
+
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
2735
|
+
{
|
2736
|
+
uint32_t start_sample, chunk, samples, id, next_chunk, n,
|
2737
|
+
prev_samples;
|
2738
|
+
ngx_buf_t *data, *buf;
|
2739
|
+
ngx_uint_t entries, target_chunk, chunk_samples;
|
2740
|
+
ngx_mp4_stsc_entry_t *entry, *end, *first;
|
2741
|
+
|
2429
2742
|
entries = trak->sample_to_chunk_entries - 1;
|
2430
2743
|
|
2744
|
+
if (start) {
|
2745
|
+
start_sample = (uint32_t) trak->start_sample;
|
2746
|
+
|
2747
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2748
|
+
"mp4 stsc crop start_sample:%uD", start_sample);
|
2749
|
+
|
2750
|
+
} else if (mp4->length) {
|
2751
|
+
start_sample = (uint32_t) (trak->end_sample - trak->start_sample);
|
2752
|
+
samples = 0;
|
2753
|
+
|
2754
|
+
data = trak->out[NGX_HTTP_MP4_STSC_START].buf;
|
2755
|
+
|
2756
|
+
if (data) {
|
2757
|
+
entry = (ngx_mp4_stsc_entry_t *) data->pos;
|
2758
|
+
samples = ngx_mp4_get_32value(entry->samples);
|
2759
|
+
entries--;
|
2760
|
+
|
2761
|
+
if (samples > start_sample) {
|
2762
|
+
samples = start_sample;
|
2763
|
+
ngx_mp4_set_32value(entry->samples, samples);
|
2764
|
+
}
|
2765
|
+
|
2766
|
+
start_sample -= samples;
|
2767
|
+
}
|
2768
|
+
|
2769
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2770
|
+
"mp4 stsc crop end_sample:%uD, ext_samples:%uD",
|
2771
|
+
start_sample, samples);
|
2772
|
+
|
2773
|
+
} else {
|
2774
|
+
return NGX_OK;
|
2775
|
+
}
|
2776
|
+
|
2777
|
+
data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
|
2778
|
+
|
2431
2779
|
entry = (ngx_mp4_stsc_entry_t *) data->pos;
|
2432
2780
|
end = (ngx_mp4_stsc_entry_t *) data->last;
|
2433
2781
|
|
2434
2782
|
chunk = ngx_mp4_get_32value(entry->chunk);
|
2435
2783
|
samples = ngx_mp4_get_32value(entry->samples);
|
2436
2784
|
id = ngx_mp4_get_32value(entry->id);
|
2785
|
+
prev_samples = 0;
|
2437
2786
|
entry++;
|
2438
2787
|
|
2439
2788
|
while (entry < end) {
|
@@ -2441,18 +2790,19 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
|
2441
2790
|
next_chunk = ngx_mp4_get_32value(entry->chunk);
|
2442
2791
|
|
2443
2792
|
ngx_log_debug5(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2444
|
-
"
|
2793
|
+
"sample:%uD, chunk:%uD, chunks:%uD, "
|
2445
2794
|
"samples:%uD, id:%uD",
|
2446
2795
|
start_sample, chunk, next_chunk - chunk, samples, id);
|
2447
2796
|
|
2448
2797
|
n = (next_chunk - chunk) * samples;
|
2449
2798
|
|
2450
|
-
if (start_sample
|
2799
|
+
if (start_sample < n) {
|
2451
2800
|
goto found;
|
2452
2801
|
}
|
2453
2802
|
|
2454
2803
|
start_sample -= n;
|
2455
2804
|
|
2805
|
+
prev_samples = samples;
|
2456
2806
|
chunk = next_chunk;
|
2457
2807
|
samples = ngx_mp4_get_32value(entry->samples);
|
2458
2808
|
id = ngx_mp4_get_32value(entry->id);
|
@@ -2460,18 +2810,18 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
|
2460
2810
|
entry++;
|
2461
2811
|
}
|
2462
2812
|
|
2463
|
-
next_chunk = trak->chunks;
|
2813
|
+
next_chunk = trak->chunks + 1;
|
2464
2814
|
|
2465
2815
|
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2466
|
-
"
|
2816
|
+
"sample:%uD, chunk:%uD, chunks:%uD, samples:%uD",
|
2467
2817
|
start_sample, chunk, next_chunk - chunk, samples);
|
2468
2818
|
|
2469
2819
|
n = (next_chunk - chunk) * samples;
|
2470
2820
|
|
2471
2821
|
if (start_sample > n) {
|
2472
2822
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
2473
|
-
"
|
2474
|
-
mp4->file.name.data);
|
2823
|
+
"%s time is out mp4 stsc chunks in \"%s\"",
|
2824
|
+
start ? "start" : "end", mp4->file.name.data);
|
2475
2825
|
return NGX_ERROR;
|
2476
2826
|
}
|
2477
2827
|
|
@@ -2487,59 +2837,91 @@ found:
|
|
2487
2837
|
return NGX_ERROR;
|
2488
2838
|
}
|
2489
2839
|
|
2490
|
-
|
2840
|
+
target_chunk = chunk - 1;
|
2841
|
+
target_chunk += start_sample / samples;
|
2842
|
+
chunk_samples = start_sample % samples;
|
2491
2843
|
|
2492
|
-
|
2493
|
-
|
2844
|
+
if (start) {
|
2845
|
+
data->pos = (u_char *) entry;
|
2494
2846
|
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2847
|
+
trak->sample_to_chunk_entries = entries;
|
2848
|
+
trak->start_chunk = target_chunk;
|
2849
|
+
trak->start_chunk_samples = chunk_samples;
|
2850
|
+
|
2851
|
+
ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
|
2852
|
+
|
2853
|
+
samples -= chunk_samples;
|
2498
2854
|
|
2499
|
-
|
2500
|
-
|
2855
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2856
|
+
"start_chunk:%ui, start_chunk_samples:%ui",
|
2857
|
+
trak->start_chunk, trak->start_chunk_samples);
|
2858
|
+
|
2859
|
+
} else {
|
2860
|
+
if (start_sample) {
|
2861
|
+
data->last = (u_char *) (entry + 1);
|
2862
|
+
trak->sample_to_chunk_entries -= entries - 1;
|
2863
|
+
trak->end_chunk_samples = samples;
|
2501
2864
|
|
2502
|
-
|
2865
|
+
} else {
|
2866
|
+
data->last = (u_char *) entry;
|
2867
|
+
trak->sample_to_chunk_entries -= entries;
|
2868
|
+
trak->end_chunk_samples = prev_samples;
|
2869
|
+
}
|
2503
2870
|
|
2504
|
-
|
2871
|
+
if (chunk_samples) {
|
2872
|
+
trak->end_chunk = target_chunk + 1;
|
2873
|
+
trak->end_chunk_samples = chunk_samples;
|
2505
2874
|
|
2506
|
-
|
2875
|
+
} else {
|
2876
|
+
trak->end_chunk = target_chunk;
|
2877
|
+
}
|
2507
2878
|
|
2508
|
-
|
2879
|
+
samples = chunk_samples;
|
2880
|
+
next_chunk = chunk + 1;
|
2509
2881
|
|
2510
|
-
|
2882
|
+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2883
|
+
"end_chunk:%ui, end_chunk_samples:%ui",
|
2884
|
+
trak->end_chunk, trak->end_chunk_samples);
|
2885
|
+
}
|
2511
2886
|
|
2512
|
-
|
2887
|
+
if (chunk_samples && next_chunk - target_chunk == 2) {
|
2888
|
+
|
2889
|
+
ngx_mp4_set_32value(entry->samples, samples);
|
2890
|
+
|
2891
|
+
} else if (chunk_samples && start) {
|
2892
|
+
|
2893
|
+
first = &trak->stsc_start_chunk_entry;
|
2513
2894
|
ngx_mp4_set_32value(first->chunk, 1);
|
2514
|
-
ngx_mp4_set_32value(first->samples, samples
|
2895
|
+
ngx_mp4_set_32value(first->samples, samples);
|
2515
2896
|
ngx_mp4_set_32value(first->id, id);
|
2516
2897
|
|
2517
|
-
buf = &trak->
|
2898
|
+
buf = &trak->stsc_start_chunk_buf;
|
2518
2899
|
buf->temporary = 1;
|
2519
2900
|
buf->pos = (u_char *) first;
|
2520
2901
|
buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
|
2521
2902
|
|
2522
|
-
trak->out[
|
2903
|
+
trak->out[NGX_HTTP_MP4_STSC_START].buf = buf;
|
2523
2904
|
|
2524
|
-
ngx_mp4_set_32value(entry->chunk, 2);
|
2905
|
+
ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 2);
|
2525
2906
|
|
2526
|
-
|
2527
|
-
atom_size += sizeof(ngx_mp4_stsc_entry_t);
|
2528
|
-
}
|
2907
|
+
trak->sample_to_chunk_entries++;
|
2529
2908
|
|
2530
|
-
|
2531
|
-
chunk = ngx_mp4_get_32value(entry->chunk);
|
2532
|
-
chunk -= trak->start_chunk;
|
2533
|
-
ngx_mp4_set_32value(entry->chunk, chunk);
|
2534
|
-
}
|
2909
|
+
} else if (chunk_samples) {
|
2535
2910
|
|
2536
|
-
|
2911
|
+
first = &trak->stsc_end_chunk_entry;
|
2912
|
+
ngx_mp4_set_32value(first->chunk, trak->end_chunk - trak->start_chunk);
|
2913
|
+
ngx_mp4_set_32value(first->samples, samples);
|
2914
|
+
ngx_mp4_set_32value(first->id, id);
|
2537
2915
|
|
2538
|
-
|
2539
|
-
|
2916
|
+
buf = &trak->stsc_end_chunk_buf;
|
2917
|
+
buf->temporary = 1;
|
2918
|
+
buf->pos = (u_char *) first;
|
2919
|
+
buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
|
2540
2920
|
|
2541
|
-
|
2542
|
-
|
2921
|
+
trak->out[NGX_HTTP_MP4_STSC_END].buf = buf;
|
2922
|
+
|
2923
|
+
trak->sample_to_chunk_entries++;
|
2924
|
+
}
|
2543
2925
|
|
2544
2926
|
return NGX_OK;
|
2545
2927
|
}
|
@@ -2635,7 +3017,7 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|
2635
3017
|
ngx_http_mp4_trak_t *trak)
|
2636
3018
|
{
|
2637
3019
|
size_t atom_size;
|
2638
|
-
uint32_t *pos, *end;
|
3020
|
+
uint32_t *pos, *end, entries;
|
2639
3021
|
ngx_buf_t *atom, *data;
|
2640
3022
|
ngx_mp4_stsz_atom_t *stsz_atom;
|
2641
3023
|
|
@@ -2651,22 +3033,47 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|
2651
3033
|
data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
|
2652
3034
|
|
2653
3035
|
if (data) {
|
2654
|
-
|
3036
|
+
entries = trak->sample_sizes_entries;
|
3037
|
+
|
3038
|
+
if (trak->start_sample > entries) {
|
2655
3039
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
2656
3040
|
"start time is out mp4 stsz samples in \"%s\"",
|
2657
3041
|
mp4->file.name.data);
|
2658
3042
|
return NGX_ERROR;
|
2659
3043
|
}
|
2660
3044
|
|
3045
|
+
entries -= trak->start_sample;
|
2661
3046
|
data->pos += trak->start_sample * sizeof(uint32_t);
|
2662
3047
|
end = (uint32_t *) data->pos;
|
2663
3048
|
|
2664
|
-
for (pos = end - trak->
|
2665
|
-
trak->
|
3049
|
+
for (pos = end - trak->start_chunk_samples; pos < end; pos++) {
|
3050
|
+
trak->start_chunk_samples_size += ngx_mp4_get_32value(pos);
|
2666
3051
|
}
|
2667
3052
|
|
2668
3053
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2669
|
-
"chunk samples sizes:%uL",
|
3054
|
+
"chunk samples sizes:%uL",
|
3055
|
+
trak->start_chunk_samples_size);
|
3056
|
+
|
3057
|
+
if (mp4->length) {
|
3058
|
+
if (trak->end_sample - trak->start_sample > entries) {
|
3059
|
+
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
3060
|
+
"end time is out mp4 stsz samples in \"%s\"",
|
3061
|
+
mp4->file.name.data);
|
3062
|
+
return NGX_ERROR;
|
3063
|
+
}
|
3064
|
+
|
3065
|
+
entries = trak->end_sample - trak->start_sample;
|
3066
|
+
data->last = data->pos + entries * sizeof(uint32_t);
|
3067
|
+
end = (uint32_t *) data->last;
|
3068
|
+
|
3069
|
+
for (pos = end - trak->end_chunk_samples; pos < end; pos++) {
|
3070
|
+
trak->end_chunk_samples_size += ngx_mp4_get_32value(pos);
|
3071
|
+
}
|
3072
|
+
|
3073
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
3074
|
+
"mp4 stsz end_chunk_samples_size:%uL",
|
3075
|
+
trak->end_chunk_samples_size);
|
3076
|
+
}
|
2670
3077
|
|
2671
3078
|
atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
|
2672
3079
|
trak->size += atom_size;
|
@@ -2675,8 +3082,7 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|
2675
3082
|
stsz_atom = (ngx_mp4_stsz_atom_t *) atom->pos;
|
2676
3083
|
|
2677
3084
|
ngx_mp4_set_32value(stsz_atom->size, atom_size);
|
2678
|
-
ngx_mp4_set_32value(stsz_atom->entries,
|
2679
|
-
trak->sample_sizes_entries - trak->start_sample);
|
3085
|
+
ngx_mp4_set_32value(stsz_atom->entries, entries);
|
2680
3086
|
}
|
2681
3087
|
|
2682
3088
|
return NGX_OK;
|
@@ -2757,6 +3163,7 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|
2757
3163
|
ngx_http_mp4_trak_t *trak)
|
2758
3164
|
{
|
2759
3165
|
size_t atom_size;
|
3166
|
+
uint32_t entries;
|
2760
3167
|
ngx_buf_t *atom, *data;
|
2761
3168
|
ngx_mp4_stco_atom_t *stco_atom;
|
2762
3169
|
|
@@ -2786,21 +3193,53 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|
2786
3193
|
}
|
2787
3194
|
|
2788
3195
|
data->pos += trak->start_chunk * sizeof(uint32_t);
|
2789
|
-
atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
|
2790
|
-
trak->size += atom_size;
|
2791
3196
|
|
2792
3197
|
trak->start_offset = ngx_mp4_get_32value(data->pos);
|
2793
|
-
trak->start_offset += trak->
|
3198
|
+
trak->start_offset += trak->start_chunk_samples_size;
|
2794
3199
|
ngx_mp4_set_32value(data->pos, trak->start_offset);
|
2795
3200
|
|
2796
3201
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2797
|
-
"start chunk offset:%
|
3202
|
+
"start chunk offset:%O", trak->start_offset);
|
3203
|
+
|
3204
|
+
if (mp4->length) {
|
3205
|
+
|
3206
|
+
if (trak->end_chunk > trak->chunks) {
|
3207
|
+
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
3208
|
+
"end time is out mp4 stco chunks in \"%s\"",
|
3209
|
+
mp4->file.name.data);
|
3210
|
+
return NGX_ERROR;
|
3211
|
+
}
|
3212
|
+
|
3213
|
+
entries = trak->end_chunk - trak->start_chunk;
|
3214
|
+
data->last = data->pos + entries * sizeof(uint32_t);
|
3215
|
+
|
3216
|
+
if (entries) {
|
3217
|
+
trak->end_offset =
|
3218
|
+
ngx_mp4_get_32value(data->last - sizeof(uint32_t));
|
3219
|
+
trak->end_offset += trak->end_chunk_samples_size;
|
3220
|
+
|
3221
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
3222
|
+
"end chunk offset:%O", trak->end_offset);
|
3223
|
+
}
|
3224
|
+
|
3225
|
+
} else {
|
3226
|
+
entries = trak->chunks - trak->start_chunk;
|
3227
|
+
trak->end_offset = mp4->mdat_data.buf->file_last;
|
3228
|
+
}
|
3229
|
+
|
3230
|
+
if (entries == 0) {
|
3231
|
+
trak->start_offset = mp4->end;
|
3232
|
+
trak->end_offset = 0;
|
3233
|
+
}
|
3234
|
+
|
3235
|
+
atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
|
3236
|
+
trak->size += atom_size;
|
2798
3237
|
|
2799
3238
|
atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf;
|
2800
3239
|
stco_atom = (ngx_mp4_stco_atom_t *) atom->pos;
|
2801
3240
|
|
2802
3241
|
ngx_mp4_set_32value(stco_atom->size, atom_size);
|
2803
|
-
ngx_mp4_set_32value(stco_atom->entries,
|
3242
|
+
ngx_mp4_set_32value(stco_atom->entries, entries);
|
2804
3243
|
|
2805
3244
|
return NGX_OK;
|
2806
3245
|
}
|
@@ -2908,6 +3347,7 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|
2908
3347
|
ngx_http_mp4_trak_t *trak)
|
2909
3348
|
{
|
2910
3349
|
size_t atom_size;
|
3350
|
+
uint64_t entries;
|
2911
3351
|
ngx_buf_t *atom, *data;
|
2912
3352
|
ngx_mp4_co64_atom_t *co64_atom;
|
2913
3353
|
|
@@ -2937,21 +3377,53 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|
2937
3377
|
}
|
2938
3378
|
|
2939
3379
|
data->pos += trak->start_chunk * sizeof(uint64_t);
|
2940
|
-
atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
|
2941
|
-
trak->size += atom_size;
|
2942
3380
|
|
2943
3381
|
trak->start_offset = ngx_mp4_get_64value(data->pos);
|
2944
|
-
trak->start_offset += trak->
|
3382
|
+
trak->start_offset += trak->start_chunk_samples_size;
|
2945
3383
|
ngx_mp4_set_64value(data->pos, trak->start_offset);
|
2946
3384
|
|
2947
3385
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
2948
|
-
"start chunk offset:%
|
3386
|
+
"start chunk offset:%O", trak->start_offset);
|
3387
|
+
|
3388
|
+
if (mp4->length) {
|
3389
|
+
|
3390
|
+
if (trak->end_chunk > trak->chunks) {
|
3391
|
+
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
3392
|
+
"end time is out mp4 co64 chunks in \"%s\"",
|
3393
|
+
mp4->file.name.data);
|
3394
|
+
return NGX_ERROR;
|
3395
|
+
}
|
3396
|
+
|
3397
|
+
entries = trak->end_chunk - trak->start_chunk;
|
3398
|
+
data->last = data->pos + entries * sizeof(uint64_t);
|
3399
|
+
|
3400
|
+
if (entries) {
|
3401
|
+
trak->end_offset =
|
3402
|
+
ngx_mp4_get_64value(data->last - sizeof(uint64_t));
|
3403
|
+
trak->end_offset += trak->end_chunk_samples_size;
|
3404
|
+
|
3405
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
3406
|
+
"end chunk offset:%O", trak->end_offset);
|
3407
|
+
}
|
3408
|
+
|
3409
|
+
} else {
|
3410
|
+
entries = trak->chunks - trak->start_chunk;
|
3411
|
+
trak->end_offset = mp4->mdat_data.buf->file_last;
|
3412
|
+
}
|
3413
|
+
|
3414
|
+
if (entries == 0) {
|
3415
|
+
trak->start_offset = mp4->end;
|
3416
|
+
trak->end_offset = 0;
|
3417
|
+
}
|
3418
|
+
|
3419
|
+
atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
|
3420
|
+
trak->size += atom_size;
|
2949
3421
|
|
2950
3422
|
atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf;
|
2951
3423
|
co64_atom = (ngx_mp4_co64_atom_t *) atom->pos;
|
2952
3424
|
|
2953
3425
|
ngx_mp4_set_32value(co64_atom->size, atom_size);
|
2954
|
-
ngx_mp4_set_32value(co64_atom->entries,
|
3426
|
+
ngx_mp4_set_32value(co64_atom->entries, entries);
|
2955
3427
|
|
2956
3428
|
return NGX_OK;
|
2957
3429
|
}
|