mirror of
https://github.com/nginx/nginx.git
synced 2024-12-03 04:39:00 +08:00
Mp4: added "end" argument support.
This commit is contained in:
parent
7aa8c81002
commit
c6ca135923
@ -27,14 +27,15 @@
|
|||||||
#define NGX_HTTP_MP4_CTTS_ATOM 15
|
#define NGX_HTTP_MP4_CTTS_ATOM 15
|
||||||
#define NGX_HTTP_MP4_CTTS_DATA 16
|
#define NGX_HTTP_MP4_CTTS_DATA 16
|
||||||
#define NGX_HTTP_MP4_STSC_ATOM 17
|
#define NGX_HTTP_MP4_STSC_ATOM 17
|
||||||
#define NGX_HTTP_MP4_STSC_CHUNK 18
|
#define NGX_HTTP_MP4_STSC_START 18
|
||||||
#define NGX_HTTP_MP4_STSC_DATA 19
|
#define NGX_HTTP_MP4_STSC_DATA 19
|
||||||
#define NGX_HTTP_MP4_STSZ_ATOM 20
|
#define NGX_HTTP_MP4_STSC_END 20
|
||||||
#define NGX_HTTP_MP4_STSZ_DATA 21
|
#define NGX_HTTP_MP4_STSZ_ATOM 21
|
||||||
#define NGX_HTTP_MP4_STCO_ATOM 22
|
#define NGX_HTTP_MP4_STSZ_DATA 22
|
||||||
#define NGX_HTTP_MP4_STCO_DATA 23
|
#define NGX_HTTP_MP4_STCO_ATOM 23
|
||||||
#define NGX_HTTP_MP4_CO64_ATOM 24
|
#define NGX_HTTP_MP4_STCO_DATA 24
|
||||||
#define NGX_HTTP_MP4_CO64_DATA 25
|
#define NGX_HTTP_MP4_CO64_ATOM 25
|
||||||
|
#define NGX_HTTP_MP4_CO64_DATA 26
|
||||||
|
|
||||||
#define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
|
#define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
|
||||||
|
|
||||||
@ -62,10 +63,15 @@ typedef struct {
|
|||||||
uint32_t chunks;
|
uint32_t chunks;
|
||||||
|
|
||||||
ngx_uint_t start_sample;
|
ngx_uint_t start_sample;
|
||||||
|
ngx_uint_t end_sample;
|
||||||
ngx_uint_t start_chunk;
|
ngx_uint_t start_chunk;
|
||||||
ngx_uint_t chunk_samples;
|
ngx_uint_t end_chunk;
|
||||||
uint64_t chunk_samples_size;
|
ngx_uint_t start_chunk_samples;
|
||||||
|
ngx_uint_t end_chunk_samples;
|
||||||
|
uint64_t start_chunk_samples_size;
|
||||||
|
uint64_t end_chunk_samples_size;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
|
off_t end_offset;
|
||||||
|
|
||||||
size_t tkhd_size;
|
size_t tkhd_size;
|
||||||
size_t mdhd_size;
|
size_t mdhd_size;
|
||||||
@ -95,7 +101,8 @@ typedef struct {
|
|||||||
ngx_buf_t ctts_atom_buf;
|
ngx_buf_t ctts_atom_buf;
|
||||||
ngx_buf_t ctts_data_buf;
|
ngx_buf_t ctts_data_buf;
|
||||||
ngx_buf_t stsc_atom_buf;
|
ngx_buf_t stsc_atom_buf;
|
||||||
ngx_buf_t stsc_chunk_buf;
|
ngx_buf_t stsc_start_chunk_buf;
|
||||||
|
ngx_buf_t stsc_end_chunk_buf;
|
||||||
ngx_buf_t stsc_data_buf;
|
ngx_buf_t stsc_data_buf;
|
||||||
ngx_buf_t stsz_atom_buf;
|
ngx_buf_t stsz_atom_buf;
|
||||||
ngx_buf_t stsz_data_buf;
|
ngx_buf_t stsz_data_buf;
|
||||||
@ -104,7 +111,8 @@ typedef struct {
|
|||||||
ngx_buf_t co64_atom_buf;
|
ngx_buf_t co64_atom_buf;
|
||||||
ngx_buf_t co64_data_buf;
|
ngx_buf_t co64_data_buf;
|
||||||
|
|
||||||
ngx_mp4_stsc_entry_t stsc_chunk_entry;
|
ngx_mp4_stsc_entry_t stsc_start_chunk_entry;
|
||||||
|
ngx_mp4_stsc_entry_t stsc_end_chunk_entry;
|
||||||
} ngx_http_mp4_trak_t;
|
} ngx_http_mp4_trak_t;
|
||||||
|
|
||||||
|
|
||||||
@ -121,6 +129,7 @@ typedef struct {
|
|||||||
off_t end;
|
off_t end;
|
||||||
off_t content_length;
|
off_t content_length;
|
||||||
ngx_uint_t start;
|
ngx_uint_t start;
|
||||||
|
ngx_uint_t length;
|
||||||
uint32_t timescale;
|
uint32_t timescale;
|
||||||
ngx_http_request_t *request;
|
ngx_http_request_t *request;
|
||||||
ngx_array_t trak;
|
ngx_array_t trak;
|
||||||
@ -219,7 +228,7 @@ static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
|
||||||
uint64_t atom_data_size);
|
uint64_t atom_data_size);
|
||||||
static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
|
static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
|
||||||
off_t start_offset);
|
off_t start_offset, off_t end_offset);
|
||||||
static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
|
||||||
uint64_t atom_data_size);
|
uint64_t atom_data_size);
|
||||||
static ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4,
|
||||||
@ -259,25 +268,25 @@ static ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak);
|
||||||
static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
||||||
static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
|
||||||
uint64_t atom_data_size);
|
uint64_t atom_data_size);
|
||||||
static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak);
|
||||||
static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
||||||
static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
|
||||||
uint64_t atom_data_size);
|
uint64_t atom_data_size);
|
||||||
static void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
static void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak);
|
||||||
static void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
static void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
||||||
static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
|
||||||
uint64_t atom_data_size);
|
uint64_t atom_data_size);
|
||||||
static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak);
|
||||||
static ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak);
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
||||||
static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
|
||||||
uint64_t atom_data_size);
|
uint64_t atom_data_size);
|
||||||
static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
||||||
@ -411,8 +420,8 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||||||
{
|
{
|
||||||
u_char *last;
|
u_char *last;
|
||||||
size_t root;
|
size_t root;
|
||||||
ngx_int_t rc, start;
|
ngx_int_t rc, start, end;
|
||||||
ngx_uint_t level;
|
ngx_uint_t level, length;
|
||||||
ngx_str_t path, value;
|
ngx_str_t path, value;
|
||||||
ngx_log_t *log;
|
ngx_log_t *log;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
@ -517,6 +526,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||||||
r->allow_ranges = 1;
|
r->allow_ranges = 1;
|
||||||
|
|
||||||
start = -1;
|
start = -1;
|
||||||
|
length = 0;
|
||||||
r->headers_out.content_length_n = of.size;
|
r->headers_out.content_length_n = of.size;
|
||||||
mp4 = NULL;
|
mp4 = NULL;
|
||||||
b = NULL;
|
b = NULL;
|
||||||
@ -538,6 +548,26 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||||||
start = -1;
|
start = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) {
|
||||||
|
|
||||||
|
ngx_set_errno(0);
|
||||||
|
end = (int) (strtod((char *) value.data, NULL) * 1000);
|
||||||
|
|
||||||
|
if (ngx_errno != 0) {
|
||||||
|
end = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end > 0) {
|
||||||
|
if (start < 0) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end > start) {
|
||||||
|
length = end - start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start >= 0) {
|
if (start >= 0) {
|
||||||
@ -553,6 +583,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||||||
mp4->file.log = r->connection->log;
|
mp4->file.log = r->connection->log;
|
||||||
mp4->end = of.size;
|
mp4->end = of.size;
|
||||||
mp4->start = (ngx_uint_t) start;
|
mp4->start = (ngx_uint_t) start;
|
||||||
|
mp4->length = length;
|
||||||
mp4->request = r;
|
mp4->request = r;
|
||||||
|
|
||||||
switch (ngx_http_mp4_process(mp4)) {
|
switch (ngx_http_mp4_process(mp4)) {
|
||||||
@ -658,15 +689,15 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
||||||
{
|
{
|
||||||
off_t start_offset, adjustment;
|
off_t start_offset, end_offset, adjustment;
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_uint_t i, j;
|
ngx_uint_t i, j;
|
||||||
ngx_chain_t **prev;
|
ngx_chain_t **prev;
|
||||||
ngx_http_mp4_trak_t *trak;
|
ngx_http_mp4_trak_t *trak;
|
||||||
ngx_http_mp4_conf_t *conf;
|
ngx_http_mp4_conf_t *conf;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"mp4 start:%ui", mp4->start);
|
"mp4 start:%ui, length:%ui", mp4->start, mp4->length);
|
||||||
|
|
||||||
conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
|
conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
|
||||||
|
|
||||||
@ -708,6 +739,7 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
start_offset = mp4->end;
|
start_offset = mp4->end;
|
||||||
|
end_offset = 0;
|
||||||
trak = mp4->trak.elts;
|
trak = mp4->trak.elts;
|
||||||
|
|
||||||
for (i = 0; i < mp4->trak.nelts; i++) {
|
for (i = 0; i < mp4->trak.nelts; i++) {
|
||||||
@ -755,6 +787,10 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||||||
start_offset = trak[i].start_offset;
|
start_offset = trak[i].start_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (end_offset < trak[i].end_offset) {
|
||||||
|
end_offset = trak[i].end_offset;
|
||||||
|
}
|
||||||
|
|
||||||
*prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM];
|
*prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM];
|
||||||
prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next;
|
prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next;
|
||||||
|
|
||||||
@ -766,6 +802,10 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (end_offset < start_offset) {
|
||||||
|
end_offset = start_offset;
|
||||||
|
}
|
||||||
|
|
||||||
mp4->moov_size += 8;
|
mp4->moov_size += 8;
|
||||||
|
|
||||||
ngx_mp4_set_32value(mp4->moov_atom_header, mp4->moov_size);
|
ngx_mp4_set_32value(mp4->moov_atom_header, mp4->moov_size);
|
||||||
@ -782,7 +822,7 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
adjustment = mp4->ftyp_size + mp4->moov_size
|
adjustment = mp4->ftyp_size + mp4->moov_size
|
||||||
+ ngx_http_mp4_update_mdat_atom(mp4, start_offset)
|
+ ngx_http_mp4_update_mdat_atom(mp4, start_offset, end_offset)
|
||||||
- start_offset;
|
- start_offset;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
@ -1026,7 +1066,7 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
|
|
||||||
no_mdat = (mp4->mdat_atom.buf == NULL);
|
no_mdat = (mp4->mdat_atom.buf == NULL);
|
||||||
|
|
||||||
if (no_mdat && mp4->start == 0) {
|
if (no_mdat && mp4->start == 0 && mp4->length == 0) {
|
||||||
/*
|
/*
|
||||||
* send original file if moov atom resides before
|
* send original file if moov atom resides before
|
||||||
* mdat atom and client requests integral file
|
* mdat atom and client requests integral file
|
||||||
@ -1125,7 +1165,8 @@ ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
|
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset)
|
ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset,
|
||||||
|
off_t end_offset)
|
||||||
{
|
{
|
||||||
off_t atom_data_size;
|
off_t atom_data_size;
|
||||||
u_char *atom_header;
|
u_char *atom_header;
|
||||||
@ -1133,8 +1174,9 @@ ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset)
|
|||||||
uint64_t atom_size;
|
uint64_t atom_size;
|
||||||
ngx_buf_t *atom;
|
ngx_buf_t *atom;
|
||||||
|
|
||||||
atom_data_size = mp4->mdat_data.buf->file_last - start_offset;
|
atom_data_size = end_offset - start_offset;
|
||||||
mp4->mdat_data.buf->file_pos = start_offset;
|
mp4->mdat_data.buf->file_pos = start_offset;
|
||||||
|
mp4->mdat_data.buf->file_last = end_offset;
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"mdat new offset @%O:%O", start_offset, atom_data_size);
|
"mdat new offset @%O:%O", start_offset, atom_data_size);
|
||||||
@ -1216,7 +1258,7 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
u_char *atom_header;
|
u_char *atom_header;
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
uint32_t timescale;
|
uint32_t timescale;
|
||||||
uint64_t duration, start_time;
|
uint64_t duration, start_time, length_time;
|
||||||
ngx_buf_t *atom;
|
ngx_buf_t *atom;
|
||||||
ngx_mp4_mvhd_atom_t *mvhd_atom;
|
ngx_mp4_mvhd_atom_t *mvhd_atom;
|
||||||
ngx_mp4_mvhd64_atom_t *mvhd64_atom;
|
ngx_mp4_mvhd64_atom_t *mvhd64_atom;
|
||||||
@ -1270,6 +1312,14 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
|
|
||||||
duration -= start_time;
|
duration -= start_time;
|
||||||
|
|
||||||
|
if (mp4->length) {
|
||||||
|
length_time = (uint64_t) mp4->length * timescale / 1000;
|
||||||
|
|
||||||
|
if (duration > length_time) {
|
||||||
|
duration = length_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"mvhd new duration:%uL, time:%.3fs",
|
"mvhd new duration:%uL, time:%.3fs",
|
||||||
duration, (double) duration / timescale);
|
duration, (double) duration / timescale);
|
||||||
@ -1415,7 +1465,7 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
{
|
{
|
||||||
u_char *atom_header;
|
u_char *atom_header;
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
uint64_t duration, start_time;
|
uint64_t duration, start_time, length_time;
|
||||||
ngx_buf_t *atom;
|
ngx_buf_t *atom;
|
||||||
ngx_http_mp4_trak_t *trak;
|
ngx_http_mp4_trak_t *trak;
|
||||||
ngx_mp4_tkhd_atom_t *tkhd_atom;
|
ngx_mp4_tkhd_atom_t *tkhd_atom;
|
||||||
@ -1465,6 +1515,14 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
|
|
||||||
duration -= start_time;
|
duration -= start_time;
|
||||||
|
|
||||||
|
if (mp4->length) {
|
||||||
|
length_time = (uint64_t) mp4->length * mp4->timescale / 1000;
|
||||||
|
|
||||||
|
if (duration > length_time) {
|
||||||
|
duration = length_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"tkhd new duration:%uL, time:%.3fs",
|
"tkhd new duration:%uL, time:%.3fs",
|
||||||
duration, (double) duration / mp4->timescale);
|
duration, (double) duration / mp4->timescale);
|
||||||
@ -1566,7 +1624,7 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
u_char *atom_header;
|
u_char *atom_header;
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
uint32_t timescale;
|
uint32_t timescale;
|
||||||
uint64_t duration, start_time;
|
uint64_t duration, start_time, length_time;
|
||||||
ngx_buf_t *atom;
|
ngx_buf_t *atom;
|
||||||
ngx_http_mp4_trak_t *trak;
|
ngx_http_mp4_trak_t *trak;
|
||||||
ngx_mp4_mdhd_atom_t *mdhd_atom;
|
ngx_mp4_mdhd_atom_t *mdhd_atom;
|
||||||
@ -1618,6 +1676,14 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||||||
|
|
||||||
duration -= start_time;
|
duration -= start_time;
|
||||||
|
|
||||||
|
if (mp4->length) {
|
||||||
|
length_time = (uint64_t) mp4->length * timescale / 1000;
|
||||||
|
|
||||||
|
if (duration > length_time) {
|
||||||
|
duration = length_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"mdhd new duration:%uL, time:%.3fs",
|
"mdhd new duration:%uL, time:%.3fs",
|
||||||
duration, (double) duration / timescale);
|
duration, (double) duration / timescale);
|
||||||
@ -2010,7 +2076,11 @@ ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_http_mp4_crop_stts_data(mp4, trak) != NGX_OK) {
|
if (ngx_http_mp4_crop_stts_data(mp4, trak, 1) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_mp4_crop_stts_data(mp4, trak, 0) != NGX_OK) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2028,17 +2098,27 @@ ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
||||||
{
|
{
|
||||||
uint32_t count, duration;
|
uint32_t count, duration, rest;
|
||||||
uint64_t start_time;
|
uint64_t start_time;
|
||||||
ngx_buf_t *data;
|
ngx_buf_t *data;
|
||||||
ngx_uint_t start_sample, entries;
|
ngx_uint_t start_sample, entries, start_sec;
|
||||||
ngx_mp4_stts_entry_t *entry, *end;
|
ngx_mp4_stts_entry_t *entry, *end;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
start_sec = mp4->start;
|
||||||
|
|
||||||
|
} else if (mp4->length) {
|
||||||
|
start_sec = mp4->length;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
|
data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
|
||||||
|
|
||||||
start_time = (uint64_t) mp4->start * trak->timescale / 1000;
|
start_time = (uint64_t) start_sec * trak->timescale / 1000;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"time-to-sample start_time:%uL", start_time);
|
"time-to-sample start_time:%uL", start_time);
|
||||||
@ -2057,8 +2137,7 @@ ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
if (start_time < (uint64_t) count * duration) {
|
if (start_time < (uint64_t) count * duration) {
|
||||||
start_sample += (ngx_uint_t) (start_time / duration);
|
start_sample += (ngx_uint_t) (start_time / duration);
|
||||||
count -= (uint32_t) (start_time / duration);
|
rest = (uint32_t) (start_time / duration);
|
||||||
ngx_mp4_set_32value(entry->count, count);
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2079,9 +2158,18 @@ found:
|
|||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"start_sample:%ui, new count:%uD", start_sample, count);
|
"start_sample:%ui, new count:%uD", start_sample, count);
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
ngx_mp4_set_32value(entry->count, count - rest);
|
||||||
|
data->pos = (u_char *) entry;
|
||||||
trak->time_to_sample_entries = entries;
|
trak->time_to_sample_entries = entries;
|
||||||
trak->start_sample = start_sample;
|
trak->start_sample = start_sample;
|
||||||
data->pos = (u_char *) entry;
|
|
||||||
|
} else {
|
||||||
|
ngx_mp4_set_32value(entry->count, rest);
|
||||||
|
data->last = (u_char *) (entry + 1);
|
||||||
|
trak->time_to_sample_entries -= entries - 1;
|
||||||
|
trak->end_sample = trak->start_sample + start_sample;
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@ -2182,7 +2270,8 @@ ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_http_mp4_crop_stss_data(mp4, trak);
|
ngx_http_mp4_crop_stss_data(mp4, trak, 1);
|
||||||
|
ngx_http_mp4_crop_stss_data(mp4, trak, 0);
|
||||||
|
|
||||||
entry = (uint32_t *) data->pos;
|
entry = (uint32_t *) data->pos;
|
||||||
end = (uint32_t *) data->last;
|
end = (uint32_t *) data->last;
|
||||||
@ -2211,18 +2300,27 @@ ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
||||||
{
|
{
|
||||||
uint32_t sample, start_sample, *entry, *end;
|
uint32_t sample, start_sample, *entry, *end;
|
||||||
ngx_buf_t *data;
|
ngx_buf_t *data;
|
||||||
ngx_uint_t entries;
|
ngx_uint_t entries;
|
||||||
|
|
||||||
|
/* sync samples starts from 1 */
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
start_sample = trak->start_sample + 1;
|
||||||
|
|
||||||
|
} else if (mp4->length) {
|
||||||
|
start_sample = trak->end_sample + 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
|
data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
|
||||||
|
|
||||||
/* sync samples starts from 1 */
|
|
||||||
start_sample = trak->start_sample + 1;
|
|
||||||
entries = trak->sync_samples_entries;
|
entries = trak->sync_samples_entries;
|
||||||
|
|
||||||
entry = (uint32_t *) data->pos;
|
entry = (uint32_t *) data->pos;
|
||||||
end = (uint32_t *) data->last;
|
end = (uint32_t *) data->last;
|
||||||
|
|
||||||
@ -2245,8 +2343,14 @@ ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
found:
|
found:
|
||||||
|
|
||||||
|
if (start) {
|
||||||
data->pos = (u_char *) entry;
|
data->pos = (u_char *) entry;
|
||||||
trak->sync_samples_entries = entries;
|
trak->sync_samples_entries = entries;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
data->last = (u_char *) entry;
|
||||||
|
trak->sync_samples_entries -= entries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2349,7 +2453,8 @@ ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_http_mp4_crop_ctts_data(mp4, trak);
|
ngx_http_mp4_crop_ctts_data(mp4, trak, 1);
|
||||||
|
ngx_http_mp4_crop_ctts_data(mp4, trak, 0);
|
||||||
|
|
||||||
if (trak->composition_offset_entries == 0) {
|
if (trak->composition_offset_entries == 0) {
|
||||||
trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL;
|
trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL;
|
||||||
@ -2372,17 +2477,27 @@ ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
||||||
{
|
{
|
||||||
uint32_t count, start_sample;
|
uint32_t count, start_sample, rest;
|
||||||
ngx_buf_t *data;
|
ngx_buf_t *data;
|
||||||
ngx_uint_t entries;
|
ngx_uint_t entries;
|
||||||
ngx_mp4_ctts_entry_t *entry, *end;
|
ngx_mp4_ctts_entry_t *entry, *end;
|
||||||
|
|
||||||
|
/* sync samples starts from 1 */
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
start_sample = trak->start_sample + 1;
|
||||||
|
|
||||||
|
} else if (mp4->length) {
|
||||||
|
start_sample = trak->end_sample - trak->start_sample + 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
|
data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
|
||||||
|
|
||||||
/* sync samples starts from 1 */
|
|
||||||
start_sample = trak->start_sample + 1;
|
|
||||||
entries = trak->composition_offset_entries;
|
entries = trak->composition_offset_entries;
|
||||||
entry = (ngx_mp4_ctts_entry_t *) data->pos;
|
entry = (ngx_mp4_ctts_entry_t *) data->pos;
|
||||||
end = (ngx_mp4_ctts_entry_t *) data->last;
|
end = (ngx_mp4_ctts_entry_t *) data->last;
|
||||||
@ -2395,8 +2510,7 @@ ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
|||||||
start_sample, count, ngx_mp4_get_32value(entry->offset));
|
start_sample, count, ngx_mp4_get_32value(entry->offset));
|
||||||
|
|
||||||
if (start_sample <= count) {
|
if (start_sample <= count) {
|
||||||
count -= (start_sample - 1);
|
rest = start_sample - 1;
|
||||||
ngx_mp4_set_32value(entry->count, count);
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2405,15 +2519,25 @@ ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
|
|||||||
entry++;
|
entry++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (start) {
|
||||||
data->pos = (u_char *) end;
|
data->pos = (u_char *) end;
|
||||||
trak->composition_offset_entries = 0;
|
trak->composition_offset_entries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
ngx_mp4_set_32value(entry->count, count - rest);
|
||||||
data->pos = (u_char *) entry;
|
data->pos = (u_char *) entry;
|
||||||
trak->composition_offset_entries = entries;
|
trak->composition_offset_entries = entries;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_mp4_set_32value(entry->count, rest);
|
||||||
|
data->last = (u_char *) (entry + 1);
|
||||||
|
trak->composition_offset_entries -= entries - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2522,7 +2646,11 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_http_mp4_crop_stsc_data(mp4, trak) != NGX_OK) {
|
if (ngx_http_mp4_crop_stsc_data(mp4, trak, 1) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_mp4_crop_stsc_data(mp4, trak, 0) != NGX_OK) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2553,24 +2681,53 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
||||||
{
|
{
|
||||||
uint32_t start_sample, chunk, samples, id, next_chunk, n;
|
uint32_t start_sample, chunk, samples, id, next_chunk, n,
|
||||||
|
prev_samples;
|
||||||
ngx_buf_t *data, *buf;
|
ngx_buf_t *data, *buf;
|
||||||
ngx_uint_t entries, target_chunk, chunk_samples;
|
ngx_uint_t entries, target_chunk, chunk_samples;
|
||||||
ngx_mp4_stsc_entry_t *entry, *end, *first;
|
ngx_mp4_stsc_entry_t *entry, *end, *first;
|
||||||
|
|
||||||
data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
|
|
||||||
|
|
||||||
start_sample = (uint32_t) trak->start_sample;
|
|
||||||
entries = trak->sample_to_chunk_entries - 1;
|
entries = trak->sample_to_chunk_entries - 1;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
start_sample = (uint32_t) trak->start_sample;
|
||||||
|
|
||||||
|
} else if (mp4->length) {
|
||||||
|
start_sample = (uint32_t) (trak->end_sample - trak->start_sample);
|
||||||
|
|
||||||
|
data = trak->out[NGX_HTTP_MP4_STSC_START].buf;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
entry = (ngx_mp4_stsc_entry_t *) data->pos;
|
||||||
|
samples = ngx_mp4_get_32value(entry->samples);
|
||||||
|
entries--;
|
||||||
|
|
||||||
|
if (samples > start_sample) {
|
||||||
|
samples = start_sample;
|
||||||
|
ngx_mp4_set_32value(entry->samples, samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
|
"mp4 stsc using %uD start samples", samples);
|
||||||
|
|
||||||
|
start_sample -= samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
|
||||||
|
|
||||||
entry = (ngx_mp4_stsc_entry_t *) data->pos;
|
entry = (ngx_mp4_stsc_entry_t *) data->pos;
|
||||||
end = (ngx_mp4_stsc_entry_t *) data->last;
|
end = (ngx_mp4_stsc_entry_t *) data->last;
|
||||||
|
|
||||||
chunk = ngx_mp4_get_32value(entry->chunk);
|
chunk = ngx_mp4_get_32value(entry->chunk);
|
||||||
samples = ngx_mp4_get_32value(entry->samples);
|
samples = ngx_mp4_get_32value(entry->samples);
|
||||||
id = ngx_mp4_get_32value(entry->id);
|
id = ngx_mp4_get_32value(entry->id);
|
||||||
|
prev_samples = 0;
|
||||||
entry++;
|
entry++;
|
||||||
|
|
||||||
while (entry < end) {
|
while (entry < end) {
|
||||||
@ -2590,6 +2747,7 @@ ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
start_sample -= n;
|
start_sample -= n;
|
||||||
|
|
||||||
|
prev_samples = samples;
|
||||||
chunk = next_chunk;
|
chunk = next_chunk;
|
||||||
samples = ngx_mp4_get_32value(entry->samples);
|
samples = ngx_mp4_get_32value(entry->samples);
|
||||||
id = ngx_mp4_get_32value(entry->id);
|
id = ngx_mp4_get_32value(entry->id);
|
||||||
@ -2632,39 +2790,79 @@ found:
|
|||||||
"start chunk:%ui, samples:%uD",
|
"start chunk:%ui, samples:%uD",
|
||||||
target_chunk, chunk_samples);
|
target_chunk, chunk_samples);
|
||||||
|
|
||||||
|
if (start) {
|
||||||
data->pos = (u_char *) entry;
|
data->pos = (u_char *) entry;
|
||||||
|
|
||||||
|
trak->sample_to_chunk_entries = entries;
|
||||||
trak->start_chunk = target_chunk;
|
trak->start_chunk = target_chunk;
|
||||||
trak->chunk_samples = chunk_samples;
|
trak->start_chunk_samples = chunk_samples;
|
||||||
|
|
||||||
ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
|
ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
|
||||||
|
|
||||||
samples -= chunk_samples;
|
samples -= chunk_samples;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (start_sample) {
|
||||||
|
data->last = (u_char *) (entry + 1);
|
||||||
|
trak->sample_to_chunk_entries -= entries - 1;
|
||||||
|
trak->end_chunk_samples = samples;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
data->last = (u_char *) entry;
|
||||||
|
trak->sample_to_chunk_entries -= entries;
|
||||||
|
trak->end_chunk_samples = prev_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunk_samples) {
|
||||||
|
trak->end_chunk = target_chunk + 1;
|
||||||
|
trak->end_chunk_samples = chunk_samples;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
trak->end_chunk = target_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
samples = chunk_samples;
|
||||||
|
next_chunk = chunk + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (chunk_samples && next_chunk - target_chunk == 2) {
|
if (chunk_samples && next_chunk - target_chunk == 2) {
|
||||||
|
|
||||||
ngx_mp4_set_32value(entry->samples, samples);
|
ngx_mp4_set_32value(entry->samples, samples);
|
||||||
|
|
||||||
} else if (chunk_samples) {
|
} else if (chunk_samples && start) {
|
||||||
|
|
||||||
first = &trak->stsc_chunk_entry;
|
first = &trak->stsc_start_chunk_entry;
|
||||||
ngx_mp4_set_32value(first->chunk, 1);
|
ngx_mp4_set_32value(first->chunk, 1);
|
||||||
ngx_mp4_set_32value(first->samples, samples);
|
ngx_mp4_set_32value(first->samples, samples);
|
||||||
ngx_mp4_set_32value(first->id, id);
|
ngx_mp4_set_32value(first->id, id);
|
||||||
|
|
||||||
buf = &trak->stsc_chunk_buf;
|
buf = &trak->stsc_start_chunk_buf;
|
||||||
buf->temporary = 1;
|
buf->temporary = 1;
|
||||||
buf->pos = (u_char *) first;
|
buf->pos = (u_char *) first;
|
||||||
buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
|
buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
|
||||||
|
|
||||||
trak->out[NGX_HTTP_MP4_STSC_CHUNK].buf = buf;
|
trak->out[NGX_HTTP_MP4_STSC_START].buf = buf;
|
||||||
|
|
||||||
ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 2);
|
ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 2);
|
||||||
|
|
||||||
entries++;
|
trak->sample_to_chunk_entries++;
|
||||||
}
|
|
||||||
|
|
||||||
trak->sample_to_chunk_entries = entries;
|
} else if (chunk_samples) {
|
||||||
|
|
||||||
|
first = &trak->stsc_end_chunk_entry;
|
||||||
|
ngx_mp4_set_32value(first->chunk, trak->end_chunk - trak->start_chunk);
|
||||||
|
ngx_mp4_set_32value(first->samples, samples);
|
||||||
|
ngx_mp4_set_32value(first->id, id);
|
||||||
|
|
||||||
|
buf = &trak->stsc_end_chunk_buf;
|
||||||
|
buf->temporary = 1;
|
||||||
|
buf->pos = (u_char *) first;
|
||||||
|
buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
|
||||||
|
|
||||||
|
trak->out[NGX_HTTP_MP4_STSC_END].buf = buf;
|
||||||
|
|
||||||
|
trak->sample_to_chunk_entries++;
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@ -2760,7 +2958,7 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak)
|
||||||
{
|
{
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
uint32_t *pos, *end;
|
uint32_t *pos, *end, entries;
|
||||||
ngx_buf_t *atom, *data;
|
ngx_buf_t *atom, *data;
|
||||||
ngx_mp4_stsz_atom_t *stsz_atom;
|
ngx_mp4_stsz_atom_t *stsz_atom;
|
||||||
|
|
||||||
@ -2776,22 +2974,47 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
|
data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
if (trak->start_sample > trak->sample_sizes_entries) {
|
entries = trak->sample_sizes_entries;
|
||||||
|
|
||||||
|
if (trak->start_sample > entries) {
|
||||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
"start time is out mp4 stsz samples in \"%s\"",
|
"start time is out mp4 stsz samples in \"%s\"",
|
||||||
mp4->file.name.data);
|
mp4->file.name.data);
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entries -= trak->start_sample;
|
||||||
data->pos += trak->start_sample * sizeof(uint32_t);
|
data->pos += trak->start_sample * sizeof(uint32_t);
|
||||||
end = (uint32_t *) data->pos;
|
end = (uint32_t *) data->pos;
|
||||||
|
|
||||||
for (pos = end - trak->chunk_samples; pos < end; pos++) {
|
for (pos = end - trak->start_chunk_samples; pos < end; pos++) {
|
||||||
trak->chunk_samples_size += ngx_mp4_get_32value(pos);
|
trak->start_chunk_samples_size += ngx_mp4_get_32value(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"chunk samples sizes:%uL", trak->chunk_samples_size);
|
"chunk samples sizes:%uL",
|
||||||
|
trak->start_chunk_samples_size);
|
||||||
|
|
||||||
|
if (mp4->length) {
|
||||||
|
if (trak->end_sample - trak->start_sample > entries) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"end time is out mp4 stsz samples in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = trak->end_sample - trak->start_sample;
|
||||||
|
data->last = data->pos + entries * sizeof(uint32_t);
|
||||||
|
end = (uint32_t *) data->last;
|
||||||
|
|
||||||
|
for (pos = end - trak->end_chunk_samples; pos < end; pos++) {
|
||||||
|
trak->end_chunk_samples_size += ngx_mp4_get_32value(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
|
"mp4 stsz end_chunk_samples_size:%uL",
|
||||||
|
trak->end_chunk_samples_size);
|
||||||
|
}
|
||||||
|
|
||||||
atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
|
atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
|
||||||
trak->size += atom_size;
|
trak->size += atom_size;
|
||||||
@ -2800,8 +3023,7 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
stsz_atom = (ngx_mp4_stsz_atom_t *) atom->pos;
|
stsz_atom = (ngx_mp4_stsz_atom_t *) atom->pos;
|
||||||
|
|
||||||
ngx_mp4_set_32value(stsz_atom->size, atom_size);
|
ngx_mp4_set_32value(stsz_atom->size, atom_size);
|
||||||
ngx_mp4_set_32value(stsz_atom->entries,
|
ngx_mp4_set_32value(stsz_atom->entries, entries);
|
||||||
trak->sample_sizes_entries - trak->start_sample);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@ -2882,6 +3104,7 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak)
|
||||||
{
|
{
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
|
uint32_t entries;
|
||||||
ngx_buf_t *atom, *data;
|
ngx_buf_t *atom, *data;
|
||||||
ngx_mp4_stco_atom_t *stco_atom;
|
ngx_mp4_stco_atom_t *stco_atom;
|
||||||
|
|
||||||
@ -2911,21 +3134,53 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->pos += trak->start_chunk * sizeof(uint32_t);
|
data->pos += trak->start_chunk * sizeof(uint32_t);
|
||||||
atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
|
|
||||||
trak->size += atom_size;
|
|
||||||
|
|
||||||
trak->start_offset = ngx_mp4_get_32value(data->pos);
|
trak->start_offset = ngx_mp4_get_32value(data->pos);
|
||||||
trak->start_offset += trak->chunk_samples_size;
|
trak->start_offset += trak->start_chunk_samples_size;
|
||||||
ngx_mp4_set_32value(data->pos, trak->start_offset);
|
ngx_mp4_set_32value(data->pos, trak->start_offset);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"start chunk offset:%uD", trak->start_offset);
|
"start chunk offset:%uD", trak->start_offset);
|
||||||
|
|
||||||
|
if (mp4->length) {
|
||||||
|
|
||||||
|
if (trak->end_chunk > trak->chunks) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"end time is out mp4 stco chunks in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = trak->end_chunk - trak->start_chunk;
|
||||||
|
data->last = data->pos + entries * sizeof(uint32_t);
|
||||||
|
|
||||||
|
if (entries) {
|
||||||
|
trak->end_offset =
|
||||||
|
ngx_mp4_get_32value(data->last - sizeof(uint32_t));
|
||||||
|
trak->end_offset += trak->end_chunk_samples_size;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
|
"end chunk offset:%O", trak->end_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
entries = trak->chunks - trak->start_chunk;
|
||||||
|
trak->end_offset = mp4->mdat_data.buf->file_last;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries == 0) {
|
||||||
|
trak->start_offset = mp4->end;
|
||||||
|
trak->end_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
|
||||||
|
trak->size += atom_size;
|
||||||
|
|
||||||
atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf;
|
atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf;
|
||||||
stco_atom = (ngx_mp4_stco_atom_t *) atom->pos;
|
stco_atom = (ngx_mp4_stco_atom_t *) atom->pos;
|
||||||
|
|
||||||
ngx_mp4_set_32value(stco_atom->size, atom_size);
|
ngx_mp4_set_32value(stco_atom->size, atom_size);
|
||||||
ngx_mp4_set_32value(stco_atom->entries, trak->chunks - trak->start_chunk);
|
ngx_mp4_set_32value(stco_atom->entries, entries);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@ -3033,6 +3288,7 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak)
|
||||||
{
|
{
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
|
uint64_t entries;
|
||||||
ngx_buf_t *atom, *data;
|
ngx_buf_t *atom, *data;
|
||||||
ngx_mp4_co64_atom_t *co64_atom;
|
ngx_mp4_co64_atom_t *co64_atom;
|
||||||
|
|
||||||
@ -3062,21 +3318,53 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->pos += trak->start_chunk * sizeof(uint64_t);
|
data->pos += trak->start_chunk * sizeof(uint64_t);
|
||||||
atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
|
|
||||||
trak->size += atom_size;
|
|
||||||
|
|
||||||
trak->start_offset = ngx_mp4_get_64value(data->pos);
|
trak->start_offset = ngx_mp4_get_64value(data->pos);
|
||||||
trak->start_offset += trak->chunk_samples_size;
|
trak->start_offset += trak->start_chunk_samples_size;
|
||||||
ngx_mp4_set_64value(data->pos, trak->start_offset);
|
ngx_mp4_set_64value(data->pos, trak->start_offset);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"start chunk offset:%uL", trak->start_offset);
|
"start chunk offset:%uL", trak->start_offset);
|
||||||
|
|
||||||
|
if (mp4->length) {
|
||||||
|
|
||||||
|
if (trak->end_chunk > trak->chunks) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"end time is out mp4 co64 chunks in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = trak->end_chunk - trak->start_chunk;
|
||||||
|
data->last = data->pos + entries * sizeof(uint64_t);
|
||||||
|
|
||||||
|
if (entries) {
|
||||||
|
trak->end_offset =
|
||||||
|
ngx_mp4_get_64value(data->last - sizeof(uint64_t));
|
||||||
|
trak->end_offset += trak->end_chunk_samples_size;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
|
"end chunk offset:%O", trak->end_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
entries = trak->chunks - trak->start_chunk;
|
||||||
|
trak->end_offset = mp4->mdat_data.buf->file_last;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries == 0) {
|
||||||
|
trak->start_offset = mp4->end;
|
||||||
|
trak->end_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
|
||||||
|
trak->size += atom_size;
|
||||||
|
|
||||||
atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf;
|
atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf;
|
||||||
co64_atom = (ngx_mp4_co64_atom_t *) atom->pos;
|
co64_atom = (ngx_mp4_co64_atom_t *) atom->pos;
|
||||||
|
|
||||||
ngx_mp4_set_32value(co64_atom->size, atom_size);
|
ngx_mp4_set_32value(co64_atom->size, atom_size);
|
||||||
ngx_mp4_set_32value(co64_atom->entries, trak->chunks - trak->start_chunk);
|
ngx_mp4_set_32value(co64_atom->entries, entries);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user