Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_mp4_module.c @ 5324:8ef1722143dc
SPDY: do not reject headers with empty value (ticket #396).
A quote from SPDY draft 2 specification: "The length of each name and
value must be greater than zero. A receiver of a zero-length name or
value must send a RST_STREAM with code PROTOCOL error."
But it appears that Chrome browser allows sending requests over SPDY/2
connection using JavaScript that contain headers with empty values.
For better compatibility across SPDY clients and to be compliant with
HTTP, such headers are no longer rejected.
Also, it is worth noting that in SPDY draft 3 the statement has been
changed so that it permits empty values for headers.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Thu, 15 Aug 2013 19:16:09 +0400 |
parents | 322434f13bd8 |
children | 670ceaba03d8 |
rev | line source |
---|---|
4085 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
4085 | 5 */ |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
12 #define NGX_HTTP_MP4_TRAK_ATOM 0 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
13 #define NGX_HTTP_MP4_TKHD_ATOM 1 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
14 #define NGX_HTTP_MP4_MDIA_ATOM 2 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
15 #define NGX_HTTP_MP4_MDHD_ATOM 3 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
16 #define NGX_HTTP_MP4_HDLR_ATOM 4 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
17 #define NGX_HTTP_MP4_MINF_ATOM 5 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
18 #define NGX_HTTP_MP4_VMHD_ATOM 6 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
19 #define NGX_HTTP_MP4_SMHD_ATOM 7 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
20 #define NGX_HTTP_MP4_DINF_ATOM 8 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
21 #define NGX_HTTP_MP4_STBL_ATOM 9 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
22 #define NGX_HTTP_MP4_STSD_ATOM 10 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
23 #define NGX_HTTP_MP4_STTS_ATOM 11 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
24 #define NGX_HTTP_MP4_STTS_DATA 12 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
25 #define NGX_HTTP_MP4_STSS_ATOM 13 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
26 #define NGX_HTTP_MP4_STSS_DATA 14 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
27 #define NGX_HTTP_MP4_CTTS_ATOM 15 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
28 #define NGX_HTTP_MP4_CTTS_DATA 16 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
29 #define NGX_HTTP_MP4_STSC_ATOM 17 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
30 #define NGX_HTTP_MP4_STSC_CHUNK 18 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
31 #define NGX_HTTP_MP4_STSC_DATA 19 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
32 #define NGX_HTTP_MP4_STSZ_ATOM 20 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
33 #define NGX_HTTP_MP4_STSZ_DATA 21 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
34 #define NGX_HTTP_MP4_STCO_ATOM 22 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
35 #define NGX_HTTP_MP4_STCO_DATA 23 |
4112 | 36 #define NGX_HTTP_MP4_CO64_ATOM 24 |
37 #define NGX_HTTP_MP4_CO64_DATA 25 | |
38 | |
39 #define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA | |
4085 | 40 |
41 | |
42 typedef struct { | |
43 size_t buffer_size; | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
44 size_t max_buffer_size; |
4085 | 45 } ngx_http_mp4_conf_t; |
46 | |
47 | |
48 typedef struct { | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
49 u_char chunk[4]; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
50 u_char samples[4]; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
51 u_char id[4]; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
52 } ngx_mp4_stsc_entry_t; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
53 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
54 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
55 typedef struct { |
4085 | 56 uint32_t timescale; |
57 uint32_t time_to_sample_entries; | |
58 uint32_t sample_to_chunk_entries; | |
59 uint32_t sync_samples_entries; | |
60 uint32_t composition_offset_entries; | |
61 uint32_t sample_sizes_entries; | |
62 uint32_t chunks; | |
63 | |
64 ngx_uint_t start_sample; | |
65 ngx_uint_t start_chunk; | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
66 ngx_uint_t chunk_samples; |
4112 | 67 uint64_t chunk_samples_size; |
4085 | 68 off_t start_offset; |
69 | |
70 size_t tkhd_size; | |
71 size_t mdhd_size; | |
72 size_t hdlr_size; | |
73 size_t vmhd_size; | |
74 size_t smhd_size; | |
75 size_t dinf_size; | |
76 size_t size; | |
77 | |
78 ngx_chain_t out[NGX_HTTP_MP4_LAST_ATOM + 1]; | |
79 | |
80 ngx_buf_t trak_atom_buf; | |
81 ngx_buf_t tkhd_atom_buf; | |
82 ngx_buf_t mdia_atom_buf; | |
83 ngx_buf_t mdhd_atom_buf; | |
84 ngx_buf_t hdlr_atom_buf; | |
85 ngx_buf_t minf_atom_buf; | |
86 ngx_buf_t vmhd_atom_buf; | |
87 ngx_buf_t smhd_atom_buf; | |
88 ngx_buf_t dinf_atom_buf; | |
89 ngx_buf_t stbl_atom_buf; | |
90 ngx_buf_t stsd_atom_buf; | |
91 ngx_buf_t stts_atom_buf; | |
92 ngx_buf_t stts_data_buf; | |
93 ngx_buf_t stss_atom_buf; | |
94 ngx_buf_t stss_data_buf; | |
95 ngx_buf_t ctts_atom_buf; | |
96 ngx_buf_t ctts_data_buf; | |
97 ngx_buf_t stsc_atom_buf; | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
98 ngx_buf_t stsc_chunk_buf; |
4085 | 99 ngx_buf_t stsc_data_buf; |
100 ngx_buf_t stsz_atom_buf; | |
101 ngx_buf_t stsz_data_buf; | |
4107 | 102 ngx_buf_t stco_atom_buf; |
103 ngx_buf_t stco_data_buf; | |
4112 | 104 ngx_buf_t co64_atom_buf; |
105 ngx_buf_t co64_data_buf; | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
106 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
107 ngx_mp4_stsc_entry_t stsc_chunk_entry; |
4085 | 108 } ngx_http_mp4_trak_t; |
109 | |
110 | |
111 typedef struct { | |
112 ngx_file_t file; | |
113 | |
114 u_char *buffer; | |
115 u_char *buffer_start; | |
116 u_char *buffer_pos; | |
117 u_char *buffer_end; | |
118 size_t buffer_size; | |
119 | |
120 off_t offset; | |
121 off_t end; | |
122 off_t content_length; | |
123 ngx_uint_t start; | |
124 uint32_t timescale; | |
125 ngx_http_request_t *request; | |
126 ngx_array_t trak; | |
127 ngx_http_mp4_trak_t traks[2]; | |
128 | |
129 size_t ftyp_size; | |
130 size_t moov_size; | |
131 | |
132 ngx_chain_t *out; | |
133 ngx_chain_t ftyp_atom; | |
134 ngx_chain_t moov_atom; | |
135 ngx_chain_t mvhd_atom; | |
136 ngx_chain_t mdat_atom; | |
137 ngx_chain_t mdat_data; | |
138 | |
139 ngx_buf_t ftyp_atom_buf; | |
140 ngx_buf_t moov_atom_buf; | |
141 ngx_buf_t mvhd_atom_buf; | |
142 ngx_buf_t mdat_atom_buf; | |
143 ngx_buf_t mdat_data_buf; | |
144 | |
145 u_char moov_atom_header[8]; | |
146 u_char mdat_atom_header[16]; | |
147 } ngx_http_mp4_file_t; | |
148 | |
149 | |
150 typedef struct { | |
151 char *name; | |
152 ngx_int_t (*handler)(ngx_http_mp4_file_t *mp4, | |
153 uint64_t atom_data_size); | |
154 } ngx_http_mp4_atom_handler_t; | |
155 | |
156 | |
157 #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8) | |
158 #define ngx_mp4_atom_data(mp4) mp4->buffer_pos | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
159 #define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8) |
4085 | 160 #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n |
161 | |
162 | |
163 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \ | |
164 ((u_char *) (p))[4] = n1; \ | |
165 ((u_char *) (p))[5] = n2; \ | |
166 ((u_char *) (p))[6] = n3; \ | |
167 ((u_char *) (p))[7] = n4 | |
168 | |
169 #define ngx_mp4_get_32value(p) \ | |
4402
b20019ecfdcc
Fixed handling of mp4 above 2G and 32bit offsets (ticket #84).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4382
diff
changeset
|
170 ( ((uint32_t) ((u_char *) (p))[0] << 24) \ |
b20019ecfdcc
Fixed handling of mp4 above 2G and 32bit offsets (ticket #84).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4382
diff
changeset
|
171 + ( ((u_char *) (p))[1] << 16) \ |
b20019ecfdcc
Fixed handling of mp4 above 2G and 32bit offsets (ticket #84).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4382
diff
changeset
|
172 + ( ((u_char *) (p))[2] << 8) \ |
b20019ecfdcc
Fixed handling of mp4 above 2G and 32bit offsets (ticket #84).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4382
diff
changeset
|
173 + ( ((u_char *) (p))[3]) ) |
4085 | 174 |
175 #define ngx_mp4_set_32value(p, n) \ | |
176 ((u_char *) (p))[0] = (u_char) ((n) >> 24); \ | |
177 ((u_char *) (p))[1] = (u_char) ((n) >> 16); \ | |
178 ((u_char *) (p))[2] = (u_char) ((n) >> 8); \ | |
179 ((u_char *) (p))[3] = (u_char) (n) | |
180 | |
181 #define ngx_mp4_get_64value(p) \ | |
182 ( ((uint64_t) ((u_char *) (p))[0] << 56) \ | |
183 + ((uint64_t) ((u_char *) (p))[1] << 48) \ | |
184 + ((uint64_t) ((u_char *) (p))[2] << 40) \ | |
185 + ((uint64_t) ((u_char *) (p))[3] << 32) \ | |
186 + ((uint64_t) ((u_char *) (p))[4] << 24) \ | |
187 + ( ((u_char *) (p))[5] << 16) \ | |
188 + ( ((u_char *) (p))[6] << 8) \ | |
189 + ( ((u_char *) (p))[7]) ) | |
190 | |
191 #define ngx_mp4_set_64value(p, n) \ | |
4155
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
192 ((u_char *) (p))[0] = (u_char) ((uint64_t) (n) >> 56); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
193 ((u_char *) (p))[1] = (u_char) ((uint64_t) (n) >> 48); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
194 ((u_char *) (p))[2] = (u_char) ((uint64_t) (n) >> 40); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
195 ((u_char *) (p))[3] = (u_char) ((uint64_t) (n) >> 32); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
196 ((u_char *) (p))[4] = (u_char) ( (n) >> 24); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
197 ((u_char *) (p))[5] = (u_char) ( (n) >> 16); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
198 ((u_char *) (p))[6] = (u_char) ( (n) >> 8); \ |
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
199 ((u_char *) (p))[7] = (u_char) (n) |
4085 | 200 |
201 #define ngx_mp4_last_trak(mp4) \ | |
202 &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1] | |
203 | |
204 | |
5202
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
205 static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r); |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
206 |
4085 | 207 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); |
208 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, | |
209 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
210 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size); |
4085 | 211 static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, |
212 uint64_t atom_data_size); | |
213 static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, | |
214 uint64_t atom_data_size); | |
215 static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, | |
216 uint64_t atom_data_size); | |
217 static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, | |
218 off_t start_offset); | |
219 static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, | |
220 uint64_t atom_data_size); | |
221 static ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4, | |
222 uint64_t atom_data_size); | |
223 static void ngx_http_mp4_update_trak_atom(ngx_http_mp4_file_t *mp4, | |
224 ngx_http_mp4_trak_t *trak); | |
225 static ngx_int_t ngx_http_mp4_read_cmov_atom(ngx_http_mp4_file_t *mp4, | |
226 uint64_t atom_data_size); | |
227 static ngx_int_t ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, | |
228 uint64_t atom_data_size); | |
229 static ngx_int_t ngx_http_mp4_read_mdia_atom(ngx_http_mp4_file_t *mp4, | |
230 uint64_t atom_data_size); | |
231 static void ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4, | |
232 ngx_http_mp4_trak_t *trak); | |
233 static ngx_int_t ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, | |
234 uint64_t atom_data_size); | |
235 static ngx_int_t ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, | |
236 uint64_t atom_data_size); | |
237 static ngx_int_t ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4, | |
238 uint64_t atom_data_size); | |
239 static void ngx_http_mp4_update_minf_atom(ngx_http_mp4_file_t *mp4, | |
240 ngx_http_mp4_trak_t *trak); | |
241 static ngx_int_t ngx_http_mp4_read_dinf_atom(ngx_http_mp4_file_t *mp4, | |
242 uint64_t atom_data_size); | |
243 static ngx_int_t ngx_http_mp4_read_vmhd_atom(ngx_http_mp4_file_t *mp4, | |
244 uint64_t atom_data_size); | |
245 static ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4, | |
246 uint64_t atom_data_size); | |
247 static ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, | |
248 uint64_t atom_data_size); | |
249 static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4, | |
250 ngx_http_mp4_trak_t *trak); | |
251 static ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, | |
252 uint64_t atom_data_size); | |
253 static ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, | |
254 uint64_t atom_data_size); | |
255 static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4, | |
256 ngx_http_mp4_trak_t *trak); | |
257 static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, | |
258 uint64_t atom_data_size); | |
259 static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4, | |
260 ngx_http_mp4_trak_t *trak); | |
261 static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, | |
262 uint64_t atom_data_size); | |
263 static void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4, | |
264 ngx_http_mp4_trak_t *trak); | |
265 static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4, | |
266 uint64_t atom_data_size); | |
267 static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4, | |
268 ngx_http_mp4_trak_t *trak); | |
269 static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, | |
270 uint64_t atom_data_size); | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
271 static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, |
4085 | 272 ngx_http_mp4_trak_t *trak); |
273 static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, | |
274 uint64_t atom_data_size); | |
275 static ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4, | |
276 ngx_http_mp4_trak_t *trak); | |
277 static void ngx_http_mp4_adjust_stco_atom(ngx_http_mp4_file_t *mp4, | |
278 ngx_http_mp4_trak_t *trak, int32_t adjustment); | |
4112 | 279 static ngx_int_t ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4, |
280 uint64_t atom_data_size); | |
281 static ngx_int_t ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4, | |
282 ngx_http_mp4_trak_t *trak); | |
283 static void ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4, | |
284 ngx_http_mp4_trak_t *trak, off_t adjustment); | |
5202
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
285 |
4085 | 286 static char *ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
287 static void *ngx_http_mp4_create_conf(ngx_conf_t *cf); | |
288 static char *ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child); | |
289 | |
5202
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
290 |
4085 | 291 static ngx_command_t ngx_http_mp4_commands[] = { |
292 | |
293 { ngx_string("mp4"), | |
294 NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, | |
295 ngx_http_mp4, | |
296 0, | |
297 0, | |
298 NULL }, | |
299 | |
300 { ngx_string("mp4_buffer_size"), | |
301 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
302 ngx_conf_set_size_slot, | |
303 NGX_HTTP_LOC_CONF_OFFSET, | |
304 offsetof(ngx_http_mp4_conf_t, buffer_size), | |
305 NULL }, | |
306 | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
307 { ngx_string("mp4_max_buffer_size"), |
4085 | 308 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
309 ngx_conf_set_size_slot, | |
310 NGX_HTTP_LOC_CONF_OFFSET, | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
311 offsetof(ngx_http_mp4_conf_t, max_buffer_size), |
4085 | 312 NULL }, |
313 | |
314 ngx_null_command | |
315 }; | |
316 | |
317 | |
318 static ngx_http_module_t ngx_http_mp4_module_ctx = { | |
319 NULL, /* preconfiguration */ | |
320 NULL, /* postconfiguration */ | |
321 | |
322 NULL, /* create main configuration */ | |
323 NULL, /* init main configuration */ | |
324 | |
325 NULL, /* create server configuration */ | |
326 NULL, /* merge server configuration */ | |
327 | |
328 ngx_http_mp4_create_conf, /* create location configuration */ | |
329 ngx_http_mp4_merge_conf /* merge location configuration */ | |
330 }; | |
331 | |
332 | |
333 ngx_module_t ngx_http_mp4_module = { | |
334 NGX_MODULE_V1, | |
335 &ngx_http_mp4_module_ctx, /* module context */ | |
336 ngx_http_mp4_commands, /* module directives */ | |
337 NGX_HTTP_MODULE, /* module type */ | |
338 NULL, /* init master */ | |
339 NULL, /* init module */ | |
340 NULL, /* init process */ | |
341 NULL, /* init thread */ | |
342 NULL, /* exit thread */ | |
343 NULL, /* exit process */ | |
344 NULL, /* exit master */ | |
345 NGX_MODULE_V1_PADDING | |
346 }; | |
347 | |
348 | |
349 static ngx_http_mp4_atom_handler_t ngx_http_mp4_atoms[] = { | |
350 { "ftyp", ngx_http_mp4_read_ftyp_atom }, | |
351 { "moov", ngx_http_mp4_read_moov_atom }, | |
352 { "mdat", ngx_http_mp4_read_mdat_atom }, | |
353 { NULL, NULL } | |
354 }; | |
355 | |
356 static ngx_http_mp4_atom_handler_t ngx_http_mp4_moov_atoms[] = { | |
357 { "mvhd", ngx_http_mp4_read_mvhd_atom }, | |
358 { "trak", ngx_http_mp4_read_trak_atom }, | |
359 { "cmov", ngx_http_mp4_read_cmov_atom }, | |
360 { NULL, NULL } | |
361 }; | |
362 | |
363 static ngx_http_mp4_atom_handler_t ngx_http_mp4_trak_atoms[] = { | |
364 { "tkhd", ngx_http_mp4_read_tkhd_atom }, | |
365 { "mdia", ngx_http_mp4_read_mdia_atom }, | |
366 { NULL, NULL } | |
367 }; | |
368 | |
369 static ngx_http_mp4_atom_handler_t ngx_http_mp4_mdia_atoms[] = { | |
370 { "mdhd", ngx_http_mp4_read_mdhd_atom }, | |
371 { "hdlr", ngx_http_mp4_read_hdlr_atom }, | |
372 { "minf", ngx_http_mp4_read_minf_atom }, | |
373 { NULL, NULL } | |
374 }; | |
375 | |
376 static ngx_http_mp4_atom_handler_t ngx_http_mp4_minf_atoms[] = { | |
377 { "vmhd", ngx_http_mp4_read_vmhd_atom }, | |
378 { "smhd", ngx_http_mp4_read_smhd_atom }, | |
379 { "dinf", ngx_http_mp4_read_dinf_atom }, | |
380 { "stbl", ngx_http_mp4_read_stbl_atom }, | |
381 { NULL, NULL } | |
382 }; | |
383 | |
384 static ngx_http_mp4_atom_handler_t ngx_http_mp4_stbl_atoms[] = { | |
385 { "stsd", ngx_http_mp4_read_stsd_atom }, | |
386 { "stts", ngx_http_mp4_read_stts_atom }, | |
387 { "stss", ngx_http_mp4_read_stss_atom }, | |
388 { "ctts", ngx_http_mp4_read_ctts_atom }, | |
389 { "stsc", ngx_http_mp4_read_stsc_atom }, | |
390 { "stsz", ngx_http_mp4_read_stsz_atom }, | |
391 { "stco", ngx_http_mp4_read_stco_atom }, | |
4112 | 392 { "co64", ngx_http_mp4_read_co64_atom }, |
4085 | 393 { NULL, NULL } |
394 }; | |
395 | |
396 | |
397 static ngx_int_t | |
398 ngx_http_mp4_handler(ngx_http_request_t *r) | |
399 { | |
400 u_char *last; | |
401 size_t root; | |
402 ngx_int_t rc, start; | |
403 ngx_uint_t level; | |
404 ngx_str_t path, value; | |
405 ngx_log_t *log; | |
406 ngx_buf_t *b; | |
407 ngx_chain_t out; | |
408 ngx_http_mp4_file_t *mp4; | |
409 ngx_open_file_info_t of; | |
410 ngx_http_core_loc_conf_t *clcf; | |
411 | |
412 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { | |
413 return NGX_HTTP_NOT_ALLOWED; | |
414 } | |
415 | |
416 if (r->uri.data[r->uri.len - 1] == '/') { | |
417 return NGX_DECLINED; | |
418 } | |
419 | |
420 rc = ngx_http_discard_request_body(r); | |
421 | |
422 if (rc != NGX_OK) { | |
423 return rc; | |
424 } | |
425 | |
426 last = ngx_http_map_uri_to_path(r, &path, &root, 0); | |
427 if (last == NULL) { | |
428 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
429 } | |
430 | |
431 log = r->connection->log; | |
432 | |
433 path.len = last - path.data; | |
434 | |
435 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, | |
436 "http mp4 filename: \"%V\"", &path); | |
437 | |
438 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
439 | |
440 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); | |
441 | |
442 of.read_ahead = clcf->read_ahead; | |
4087
3aa3b7bb9f0d
Bugfix of r4086: directio was always enabled if mp4 file was sent as is.
Igor Sysoev <igor@sysoev.ru>
parents:
4085
diff
changeset
|
443 of.directio = NGX_MAX_OFF_T_VALUE; |
4085 | 444 of.valid = clcf->open_file_cache_valid; |
445 of.min_uses = clcf->open_file_cache_min_uses; | |
446 of.errors = clcf->open_file_cache_errors; | |
447 of.events = clcf->open_file_cache_events; | |
4494
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
448 |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
449 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
450 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
451 } |
4085 | 452 |
453 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) | |
454 != NGX_OK) | |
455 { | |
456 switch (of.err) { | |
457 | |
458 case 0: | |
459 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
460 | |
461 case NGX_ENOENT: | |
462 case NGX_ENOTDIR: | |
463 case NGX_ENAMETOOLONG: | |
464 | |
465 level = NGX_LOG_ERR; | |
466 rc = NGX_HTTP_NOT_FOUND; | |
467 break; | |
468 | |
469 case NGX_EACCES: | |
4478
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
470 #if (NGX_HAVE_OPENAT) |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
471 case NGX_EMLINK: |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
472 case NGX_ELOOP: |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
473 #endif |
4085 | 474 |
475 level = NGX_LOG_ERR; | |
476 rc = NGX_HTTP_FORBIDDEN; | |
477 break; | |
478 | |
479 default: | |
480 | |
481 level = NGX_LOG_CRIT; | |
482 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
483 break; | |
484 } | |
485 | |
486 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { | |
487 ngx_log_error(level, log, of.err, | |
488 "%s \"%s\" failed", of.failed, path.data); | |
489 } | |
490 | |
491 return rc; | |
492 } | |
493 | |
494 if (!of.is_file) { | |
495 | |
496 if (ngx_close_file(of.fd) == NGX_FILE_ERROR) { | |
497 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
498 ngx_close_file_n " \"%s\" failed", path.data); | |
499 } | |
500 | |
501 return NGX_DECLINED; | |
502 } | |
503 | |
504 r->root_tested = !r->error_page; | |
505 r->allow_ranges = 1; | |
506 | |
507 start = -1; | |
508 r->headers_out.content_length_n = of.size; | |
509 mp4 = NULL; | |
510 b = NULL; | |
511 | |
512 if (r->args.len) { | |
513 | |
514 if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { | |
515 | |
4156
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
516 /* |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
517 * A Flash player may send start value with a lot of digits |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
518 * after dot so strtod() is used instead of atofp(). NaNs and |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
519 * infinities become negative numbers after (int) conversion. |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
520 */ |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
521 |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
522 ngx_set_errno(0); |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
523 start = (int) (strtod((char *) value.data, NULL) * 1000); |
67a4654ba7d9
Using strtod() instead of atofp() to support a lot of digits after dot in
Igor Sysoev <igor@sysoev.ru>
parents:
4155
diff
changeset
|
524 |
5202
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
525 if (ngx_errno != 0) { |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
526 start = -1; |
4085 | 527 } |
528 } | |
529 } | |
530 | |
5202
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
531 if (start >= 0) { |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
532 r->allow_ranges = 0; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
533 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
534 mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t)); |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
535 if (mp4 == NULL) { |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
536 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
537 } |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
538 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
539 mp4->file.fd = of.fd; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
540 mp4->file.name = path; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
541 mp4->file.log = r->connection->log;; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
542 mp4->end = of.size; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
543 mp4->start = (ngx_uint_t) start; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
544 mp4->request = r; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
545 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
546 switch (ngx_http_mp4_process(mp4)) { |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
547 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
548 case NGX_DECLINED: |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
549 if (mp4->buffer) { |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
550 ngx_pfree(r->pool, mp4->buffer); |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
551 } |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
552 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
553 ngx_pfree(r->pool, mp4); |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
554 mp4 = NULL; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
555 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
556 break; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
557 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
558 case NGX_OK: |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
559 r->headers_out.content_length_n = mp4->content_length; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
560 break; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
561 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
562 default: /* NGX_ERROR */ |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
563 if (mp4->buffer) { |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
564 ngx_pfree(r->pool, mp4->buffer); |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
565 } |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
566 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
567 ngx_pfree(r->pool, mp4); |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
568 |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
569 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
570 } |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
571 } |
322434f13bd8
Mp4: indentation and style, no functional changes.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5097
diff
changeset
|
572 |
4085 | 573 log->action = "sending mp4 to client"; |
574 | |
575 if (clcf->directio <= of.size) { | |
576 | |
577 /* | |
578 * DIRECTIO is set on transfer only | |
579 * to allow kernel to cache "moov" atom | |
580 */ | |
581 | |
582 if (ngx_directio_on(of.fd) == NGX_FILE_ERROR) { | |
583 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
584 ngx_directio_on_n " \"%s\" failed", path.data); | |
585 } | |
586 | |
4087
3aa3b7bb9f0d
Bugfix of r4086: directio was always enabled if mp4 file was sent as is.
Igor Sysoev <igor@sysoev.ru>
parents:
4085
diff
changeset
|
587 of.is_directio = 1; |
3aa3b7bb9f0d
Bugfix of r4086: directio was always enabled if mp4 file was sent as is.
Igor Sysoev <igor@sysoev.ru>
parents:
4085
diff
changeset
|
588 |
4085 | 589 if (mp4) { |
590 mp4->file.directio = 1; | |
591 } | |
592 } | |
593 | |
594 r->headers_out.status = NGX_HTTP_OK; | |
595 r->headers_out.last_modified_time = of.mtime; | |
596 | |
4748
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4705
diff
changeset
|
597 if (ngx_http_set_etag(r) != NGX_OK) { |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4705
diff
changeset
|
598 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4705
diff
changeset
|
599 } |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4705
diff
changeset
|
600 |
4085 | 601 if (ngx_http_set_content_type(r) != NGX_OK) { |
602 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
603 } | |
604 | |
605 if (mp4 == NULL) { | |
606 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); | |
607 if (b == NULL) { | |
608 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
609 } | |
610 | |
611 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | |
612 if (b->file == NULL) { | |
613 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
614 } | |
615 } | |
616 | |
617 rc = ngx_http_send_header(r); | |
618 | |
619 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
620 return rc; | |
621 } | |
622 | |
623 if (mp4) { | |
624 return ngx_http_output_filter(r, mp4->out); | |
625 } | |
626 | |
627 b->file_pos = 0; | |
628 b->file_last = of.size; | |
629 | |
630 b->in_file = b->file_last ? 1 : 0; | |
4611
2b6cb7528409
Allows particular modules to handle subrequests properly.
Andrey Belov <defan@nginx.com>
parents:
4585
diff
changeset
|
631 b->last_buf = (r == r->main) ? 1 : 0; |
4085 | 632 b->last_in_chain = 1; |
633 | |
634 b->file->fd = of.fd; | |
635 b->file->name = path; | |
636 b->file->log = log; | |
637 b->file->directio = of.is_directio; | |
638 | |
639 out.buf = b; | |
640 out.next = NULL; | |
641 | |
642 return ngx_http_output_filter(r, &out); | |
643 } | |
644 | |
645 | |
646 static ngx_int_t | |
647 ngx_http_mp4_process(ngx_http_mp4_file_t *mp4) | |
648 { | |
649 off_t start_offset, adjustment; | |
650 ngx_int_t rc; | |
651 ngx_uint_t i, j; | |
652 ngx_chain_t **prev; | |
653 ngx_http_mp4_trak_t *trak; | |
654 ngx_http_mp4_conf_t *conf; | |
655 | |
656 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
657 "mp4 start:%ui", mp4->start); | |
658 | |
659 conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module); | |
660 | |
661 mp4->buffer_size = conf->buffer_size; | |
662 | |
663 rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_atoms, mp4->end); | |
664 if (rc != NGX_OK) { | |
665 return rc; | |
666 } | |
667 | |
668 if (mp4->trak.nelts == 0) { | |
669 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
670 "no mp4 trak atoms were found in \"%s\"", | |
671 mp4->file.name.data); | |
672 return NGX_ERROR; | |
673 } | |
674 | |
675 if (mp4->mdat_atom.buf == NULL) { | |
676 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
677 "no mp4 mdat atom was found in \"%s\"", | |
678 mp4->file.name.data); | |
679 return NGX_ERROR; | |
680 } | |
681 | |
682 prev = &mp4->out; | |
683 | |
684 if (mp4->ftyp_atom.buf) { | |
685 *prev = &mp4->ftyp_atom; | |
686 prev = &mp4->ftyp_atom.next; | |
687 } | |
688 | |
689 *prev = &mp4->moov_atom; | |
690 prev = &mp4->moov_atom.next; | |
691 | |
692 if (mp4->mvhd_atom.buf) { | |
693 mp4->moov_size += mp4->mvhd_atom_buf.last - mp4->mvhd_atom_buf.pos; | |
694 *prev = &mp4->mvhd_atom; | |
695 prev = &mp4->mvhd_atom.next; | |
696 } | |
697 | |
698 start_offset = mp4->end; | |
699 trak = mp4->trak.elts; | |
700 | |
701 for (i = 0; i < mp4->trak.nelts; i++) { | |
702 | |
703 if (ngx_http_mp4_update_stts_atom(mp4, &trak[i]) != NGX_OK) { | |
704 return NGX_ERROR; | |
705 } | |
706 | |
707 if (ngx_http_mp4_update_stss_atom(mp4, &trak[i]) != NGX_OK) { | |
708 return NGX_ERROR; | |
709 } | |
710 | |
711 ngx_http_mp4_update_ctts_atom(mp4, &trak[i]); | |
712 | |
713 if (ngx_http_mp4_update_stsc_atom(mp4, &trak[i]) != NGX_OK) { | |
714 return NGX_ERROR; | |
715 } | |
716 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
717 if (ngx_http_mp4_update_stsz_atom(mp4, &trak[i]) != NGX_OK) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
718 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
719 } |
4085 | 720 |
4112 | 721 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { |
722 if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) { | |
723 return NGX_ERROR; | |
724 } | |
725 | |
726 } else { | |
727 if (ngx_http_mp4_update_stco_atom(mp4, &trak[i]) != NGX_OK) { | |
728 return NGX_ERROR; | |
729 } | |
4085 | 730 } |
731 | |
732 ngx_http_mp4_update_stbl_atom(mp4, &trak[i]); | |
733 ngx_http_mp4_update_minf_atom(mp4, &trak[i]); | |
734 trak[i].size += trak[i].mdhd_size; | |
735 trak[i].size += trak[i].hdlr_size; | |
736 ngx_http_mp4_update_mdia_atom(mp4, &trak[i]); | |
737 trak[i].size += trak[i].tkhd_size; | |
738 ngx_http_mp4_update_trak_atom(mp4, &trak[i]); | |
739 | |
740 mp4->moov_size += trak[i].size; | |
741 | |
742 if (start_offset > trak[i].start_offset) { | |
743 start_offset = trak[i].start_offset; | |
744 } | |
745 | |
746 *prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM]; | |
747 prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next; | |
748 | |
749 for (j = 0; j < NGX_HTTP_MP4_LAST_ATOM + 1; j++) { | |
750 if (trak[i].out[j].buf) { | |
751 *prev = &trak[i].out[j]; | |
752 prev = &trak[i].out[j].next; | |
753 } | |
754 } | |
755 } | |
756 | |
757 mp4->moov_size += 8; | |
758 | |
759 ngx_mp4_set_32value(mp4->moov_atom_header, mp4->moov_size); | |
760 ngx_mp4_set_atom_name(mp4->moov_atom_header, 'm', 'o', 'o', 'v'); | |
761 mp4->content_length += mp4->moov_size; | |
762 | |
763 *prev = &mp4->mdat_atom; | |
764 | |
5097
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
765 if (start_offset > mp4->mdat_data.buf->file_last) { |
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
766 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
767 "start time is out mp4 mdat atom in \"%s\"", |
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
768 mp4->file.name.data); |
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
769 return NGX_ERROR; |
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
770 } |
37671d0042b7
Mp4: fixed handling of too small mdat atoms (ticket #266).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4820
diff
changeset
|
771 |
4085 | 772 adjustment = mp4->ftyp_size + mp4->moov_size |
773 + ngx_http_mp4_update_mdat_atom(mp4, start_offset) | |
774 - start_offset; | |
775 | |
4088
8fe1da7b8386
bugfix of r4086: nginx could not be built without debug log.
Igor Sysoev <igor@sysoev.ru>
parents:
4087
diff
changeset
|
776 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
4579 | 777 "mp4 adjustment:%O", adjustment); |
4085 | 778 |
779 for (i = 0; i < mp4->trak.nelts; i++) { | |
4112 | 780 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { |
781 ngx_http_mp4_adjust_co64_atom(mp4, &trak[i], adjustment); | |
782 } else { | |
783 ngx_http_mp4_adjust_stco_atom(mp4, &trak[i], (int32_t) adjustment); | |
784 } | |
4085 | 785 } |
786 | |
787 return NGX_OK; | |
788 } | |
789 | |
790 | |
791 typedef struct { | |
792 u_char size[4]; | |
793 u_char name[4]; | |
794 } ngx_mp4_atom_header_t; | |
795 | |
796 typedef struct { | |
797 u_char size[4]; | |
798 u_char name[4]; | |
799 u_char size64[8]; | |
800 } ngx_mp4_atom_header64_t; | |
801 | |
802 | |
803 static ngx_int_t | |
804 ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, | |
805 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size) | |
806 { | |
807 off_t end; | |
808 size_t atom_header_size; | |
809 u_char *atom_header, *atom_name; | |
810 uint64_t atom_size; | |
811 ngx_int_t rc; | |
812 ngx_uint_t n; | |
813 | |
814 end = mp4->offset + atom_data_size; | |
815 | |
816 while (mp4->offset < end) { | |
817 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
818 if (ngx_http_mp4_read(mp4, sizeof(uint32_t)) != NGX_OK) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
819 return NGX_ERROR; |
4085 | 820 } |
821 | |
822 atom_header = mp4->buffer_pos; | |
823 atom_size = ngx_mp4_get_32value(atom_header); | |
824 atom_header_size = sizeof(ngx_mp4_atom_header_t); | |
825 | |
826 if (atom_size == 0) { | |
827 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
828 "mp4 atom end"); | |
829 return NGX_OK; | |
830 } | |
831 | |
832 if (atom_size < sizeof(ngx_mp4_atom_header_t)) { | |
833 | |
834 if (atom_size == 1) { | |
835 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
836 if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header64_t)) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
837 != NGX_OK) |
4085 | 838 { |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
839 return NGX_ERROR; |
4085 | 840 } |
841 | |
842 /* 64-bit atom size */ | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
843 atom_header = mp4->buffer_pos; |
4085 | 844 atom_size = ngx_mp4_get_64value(atom_header + 8); |
845 atom_header_size = sizeof(ngx_mp4_atom_header64_t); | |
846 | |
847 } else { | |
848 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
849 "\"%s\" mp4 atom is too small:%uL", | |
850 mp4->file.name.data, atom_size); | |
851 return NGX_ERROR; | |
852 } | |
853 } | |
854 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
855 if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header_t)) != NGX_OK) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
856 return NGX_ERROR; |
4085 | 857 } |
858 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
859 atom_header = mp4->buffer_pos; |
4085 | 860 atom_name = atom_header + sizeof(uint32_t); |
861 | |
4088
8fe1da7b8386
bugfix of r4086: nginx could not be built without debug log.
Igor Sysoev <igor@sysoev.ru>
parents:
4087
diff
changeset
|
862 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
4085 | 863 "mp4 atom: %*s @%O:%uL", |
864 4, atom_name, mp4->offset, atom_size); | |
865 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
866 if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
867 || mp4->offset + (off_t) atom_size > end) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
868 { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
869 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
870 "\"%s\" mp4 atom too large:%uL", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
871 mp4->file.name.data, atom_size); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
872 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
873 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
874 |
4085 | 875 for (n = 0; atom[n].name; n++) { |
876 | |
877 if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) { | |
878 | |
879 ngx_mp4_atom_next(mp4, atom_header_size); | |
880 | |
881 rc = atom[n].handler(mp4, atom_size - atom_header_size); | |
882 if (rc != NGX_OK) { | |
883 return rc; | |
884 } | |
885 | |
886 goto next; | |
887 } | |
888 } | |
889 | |
890 ngx_mp4_atom_next(mp4, atom_size); | |
891 | |
892 next: | |
893 continue; | |
894 } | |
895 | |
896 return NGX_OK; | |
897 } | |
898 | |
899 | |
900 static ngx_int_t | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
901 ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size) |
4085 | 902 { |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
903 ssize_t n; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
904 |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
905 if (mp4->buffer_pos + size <= mp4->buffer_end) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
906 return NGX_OK; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
907 } |
4085 | 908 |
909 if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) { | |
910 mp4->buffer_size = (size_t) (mp4->end - mp4->offset); | |
911 } | |
912 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
913 if (mp4->buffer_size < size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
914 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
915 "\"%s\" mp4 file truncated", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
916 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
917 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
918 |
4085 | 919 if (mp4->buffer == NULL) { |
920 mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size); | |
921 if (mp4->buffer == NULL) { | |
922 return NGX_ERROR; | |
923 } | |
924 | |
925 mp4->buffer_start = mp4->buffer; | |
926 } | |
927 | |
928 n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size, | |
929 mp4->offset); | |
930 | |
931 if (n == NGX_ERROR) { | |
932 return NGX_ERROR; | |
933 } | |
934 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
935 if ((size_t) n != mp4->buffer_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
936 ngx_log_error(NGX_LOG_CRIT, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
937 ngx_read_file_n " read only %z of %z from \"%s\"", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
938 n, mp4->buffer_size, mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
939 return NGX_ERROR; |
4085 | 940 } |
941 | |
942 mp4->buffer_pos = mp4->buffer_start; | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
943 mp4->buffer_end = mp4->buffer_start + mp4->buffer_size; |
4085 | 944 |
945 return NGX_OK; | |
946 } | |
947 | |
948 | |
949 static ngx_int_t | |
950 ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
951 { | |
952 u_char *ftyp_atom; | |
953 size_t atom_size; | |
954 ngx_buf_t *atom; | |
955 | |
956 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom"); | |
957 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
958 if (atom_data_size > 1024 |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
959 || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
960 { |
4085 | 961 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
962 "\"%s\" mp4 ftyp atom is too large:%uL", | |
963 mp4->file.name.data, atom_data_size); | |
964 return NGX_ERROR; | |
965 } | |
966 | |
967 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
968 | |
969 ftyp_atom = ngx_palloc(mp4->request->pool, atom_size); | |
970 if (ftyp_atom == NULL) { | |
971 return NGX_ERROR; | |
972 } | |
973 | |
974 ngx_mp4_set_32value(ftyp_atom, atom_size); | |
975 ngx_mp4_set_atom_name(ftyp_atom, 'f', 't', 'y', 'p'); | |
976 | |
977 /* | |
978 * only moov atom content is guaranteed to be in mp4->buffer | |
979 * during sending response, so ftyp atom content should be copied | |
980 */ | |
981 ngx_memcpy(ftyp_atom + sizeof(ngx_mp4_atom_header_t), | |
982 ngx_mp4_atom_data(mp4), (size_t) atom_data_size); | |
983 | |
984 atom = &mp4->ftyp_atom_buf; | |
985 atom->temporary = 1; | |
986 atom->pos = ftyp_atom; | |
987 atom->last = ftyp_atom + atom_size; | |
988 | |
989 mp4->ftyp_atom.buf = atom; | |
990 mp4->ftyp_size = atom_size; | |
991 mp4->content_length = atom_size; | |
992 | |
993 ngx_mp4_atom_next(mp4, atom_data_size); | |
994 | |
995 return NGX_OK; | |
996 } | |
997 | |
998 | |
999 /* | |
1000 * Small excess buffer to process atoms after moov atom, mp4->buffer_start | |
1001 * will be set to this buffer part after moov atom processing. | |
1002 */ | |
1003 #define NGX_HTTP_MP4_MOOV_BUFFER_EXCESS (4 * 1024) | |
1004 | |
1005 static ngx_int_t | |
1006 ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1007 { | |
1008 ngx_int_t rc; | |
1009 ngx_uint_t no_mdat; | |
1010 ngx_buf_t *atom; | |
1011 ngx_http_mp4_conf_t *conf; | |
1012 | |
1013 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 moov atom"); | |
1014 | |
1015 no_mdat = (mp4->mdat_atom.buf == NULL); | |
1016 | |
1017 if (no_mdat && mp4->start == 0) { | |
1018 /* | |
1019 * send original file if moov atom resides before | |
1020 * mdat atom and client requests integral file | |
1021 */ | |
1022 return NGX_DECLINED; | |
1023 } | |
1024 | |
1025 conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module); | |
1026 | |
1027 if (atom_data_size > mp4->buffer_size) { | |
1028 | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
1029 if (atom_data_size > conf->max_buffer_size) { |
4085 | 1030 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
1031 "\"%s\" mp4 moov atom is too large:%uL, " | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
1032 "you may want to increase mp4_max_buffer_size", |
4085 | 1033 mp4->file.name.data, atom_data_size); |
1034 return NGX_ERROR; | |
1035 } | |
1036 | |
1037 ngx_pfree(mp4->request->pool, mp4->buffer); | |
1038 mp4->buffer = NULL; | |
1039 mp4->buffer_pos = NULL; | |
1040 mp4->buffer_end = NULL; | |
1041 | |
1042 mp4->buffer_size = (size_t) atom_data_size | |
1043 + NGX_HTTP_MP4_MOOV_BUFFER_EXCESS * no_mdat; | |
1044 } | |
1045 | |
4705
9a43b145a8ba
Mp4: fixed build on win32 after r4689.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4688
diff
changeset
|
1046 if (ngx_http_mp4_read(mp4, (size_t) atom_data_size) != NGX_OK) { |
4688
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1047 return NGX_ERROR; |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1048 } |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1049 |
4085 | 1050 mp4->trak.elts = &mp4->traks; |
1051 mp4->trak.size = sizeof(ngx_http_mp4_trak_t); | |
1052 mp4->trak.nalloc = 2; | |
1053 mp4->trak.pool = mp4->request->pool; | |
1054 | |
1055 atom = &mp4->moov_atom_buf; | |
1056 atom->temporary = 1; | |
1057 atom->pos = mp4->moov_atom_header; | |
1058 atom->last = mp4->moov_atom_header + 8; | |
1059 | |
1060 mp4->moov_atom.buf = &mp4->moov_atom_buf; | |
1061 | |
1062 rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_moov_atoms, atom_data_size); | |
1063 | |
1064 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 moov atom done"); | |
1065 | |
1066 if (no_mdat) { | |
1067 mp4->buffer_start = mp4->buffer_pos; | |
1068 mp4->buffer_size = NGX_HTTP_MP4_MOOV_BUFFER_EXCESS; | |
1069 | |
4688
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1070 if (mp4->buffer_start + mp4->buffer_size > mp4->buffer_end) { |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1071 mp4->buffer = NULL; |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1072 mp4->buffer_pos = NULL; |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1073 mp4->buffer_end = NULL; |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1074 } |
5fedb27c3e36
Mp4: fixed streaming if moov atom is at buffer edge.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4687
diff
changeset
|
1075 |
4085 | 1076 } else { |
1077 /* skip atoms after moov atom */ | |
1078 mp4->offset = mp4->end; | |
1079 } | |
1080 | |
1081 return rc; | |
1082 } | |
1083 | |
1084 | |
1085 static ngx_int_t | |
1086 ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1087 { | |
1088 ngx_buf_t *data; | |
1089 | |
1090 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mdat atom"); | |
1091 | |
1092 data = &mp4->mdat_data_buf; | |
1093 data->file = &mp4->file; | |
1094 data->in_file = 1; | |
1095 data->last_buf = 1; | |
1096 data->last_in_chain = 1; | |
1097 data->file_last = mp4->offset + atom_data_size; | |
1098 | |
1099 mp4->mdat_atom.buf = &mp4->mdat_atom_buf; | |
1100 mp4->mdat_atom.next = &mp4->mdat_data; | |
1101 mp4->mdat_data.buf = data; | |
1102 | |
1103 if (mp4->trak.nelts) { | |
1104 /* skip atoms after mdat atom */ | |
1105 mp4->offset = mp4->end; | |
1106 | |
1107 } else { | |
1108 ngx_mp4_atom_next(mp4, atom_data_size); | |
1109 } | |
1110 | |
1111 return NGX_OK; | |
1112 } | |
1113 | |
1114 | |
1115 static size_t | |
1116 ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset) | |
1117 { | |
1118 off_t atom_data_size; | |
1119 u_char *atom_header; | |
1120 uint32_t atom_header_size; | |
1121 uint64_t atom_size; | |
1122 ngx_buf_t *atom; | |
1123 | |
1124 atom_data_size = mp4->mdat_data.buf->file_last - start_offset; | |
1125 mp4->mdat_data.buf->file_pos = start_offset; | |
1126 | |
4088
8fe1da7b8386
bugfix of r4086: nginx could not be built without debug log.
Igor Sysoev <igor@sysoev.ru>
parents:
4087
diff
changeset
|
1127 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
4085 | 1128 "mdat new offset @%O:%O", start_offset, atom_data_size); |
1129 | |
1130 atom_header = mp4->mdat_atom_header; | |
1131 | |
4155
d9636bf3f159
Fix of building on platforms with 32-bit off_t. (closed #23)
Igor Sysoev <igor@sysoev.ru>
parents:
4112
diff
changeset
|
1132 if ((uint64_t) atom_data_size > 0xffffffff) { |
4085 | 1133 atom_size = 1; |
1134 atom_header_size = sizeof(ngx_mp4_atom_header64_t); | |
1135 ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t), | |
1136 sizeof(ngx_mp4_atom_header64_t) + atom_data_size); | |
1137 } else { | |
1138 atom_size = sizeof(ngx_mp4_atom_header_t) + atom_data_size; | |
1139 atom_header_size = sizeof(ngx_mp4_atom_header_t); | |
1140 } | |
1141 | |
4282
71cdac0b9ea6
Fix of "Content-Length" header of MP4 response if start argument was used.
Igor Sysoev <igor@sysoev.ru>
parents:
4189
diff
changeset
|
1142 mp4->content_length += atom_header_size + atom_data_size; |
71cdac0b9ea6
Fix of "Content-Length" header of MP4 response if start argument was used.
Igor Sysoev <igor@sysoev.ru>
parents:
4189
diff
changeset
|
1143 |
4085 | 1144 ngx_mp4_set_32value(atom_header, atom_size); |
1145 ngx_mp4_set_atom_name(atom_header, 'm', 'd', 'a', 't'); | |
1146 | |
1147 atom = &mp4->mdat_atom_buf; | |
1148 atom->temporary = 1; | |
1149 atom->pos = atom_header; | |
1150 atom->last = atom_header + atom_header_size; | |
1151 | |
1152 return atom_header_size; | |
1153 } | |
1154 | |
1155 | |
1156 typedef struct { | |
1157 u_char size[4]; | |
1158 u_char name[4]; | |
1159 u_char version[1]; | |
1160 u_char flags[3]; | |
1161 u_char creation_time[4]; | |
1162 u_char modification_time[4]; | |
1163 u_char timescale[4]; | |
1164 u_char duration[4]; | |
1165 u_char rate[4]; | |
1166 u_char volume[2]; | |
1167 u_char reserved[10]; | |
1168 u_char matrix[36]; | |
1169 u_char preview_time[4]; | |
1170 u_char preview_duration[4]; | |
1171 u_char poster_time[4]; | |
1172 u_char selection_time[4]; | |
1173 u_char selection_duration[4]; | |
1174 u_char current_time[4]; | |
1175 u_char next_track_id[4]; | |
1176 } ngx_mp4_mvhd_atom_t; | |
1177 | |
1178 typedef struct { | |
1179 u_char size[4]; | |
1180 u_char name[4]; | |
1181 u_char version[1]; | |
1182 u_char flags[3]; | |
1183 u_char creation_time[8]; | |
1184 u_char modification_time[8]; | |
1185 u_char timescale[4]; | |
1186 u_char duration[8]; | |
1187 u_char rate[4]; | |
1188 u_char volume[2]; | |
1189 u_char reserved[10]; | |
1190 u_char matrix[36]; | |
1191 u_char preview_time[4]; | |
1192 u_char preview_duration[4]; | |
1193 u_char poster_time[4]; | |
1194 u_char selection_time[4]; | |
1195 u_char selection_duration[4]; | |
1196 u_char current_time[4]; | |
1197 u_char next_track_id[4]; | |
1198 } ngx_mp4_mvhd64_atom_t; | |
1199 | |
1200 | |
1201 static ngx_int_t | |
1202 ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1203 { | |
1204 u_char *atom_header; | |
1205 size_t atom_size; | |
1206 uint32_t timescale; | |
1207 uint64_t duration; | |
1208 ngx_buf_t *atom; | |
1209 ngx_mp4_mvhd_atom_t *mvhd_atom; | |
1210 ngx_mp4_mvhd64_atom_t *mvhd64_atom; | |
1211 | |
1212 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mvhd atom"); | |
1213 | |
1214 atom_header = ngx_mp4_atom_header(mp4); | |
1215 mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header; | |
1216 mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header; | |
1217 ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd'); | |
1218 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1219 if (ngx_mp4_atom_data_size(ngx_mp4_mvhd_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1220 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1221 "\"%s\" mp4 mvhd atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1222 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1223 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1224 |
4085 | 1225 if (mvhd_atom->version[0] == 0) { |
1226 /* version 0: 32-bit duration */ | |
1227 timescale = ngx_mp4_get_32value(mvhd_atom->timescale); | |
1228 duration = ngx_mp4_get_32value(mvhd_atom->duration); | |
1229 | |
1230 } else { | |
1231 /* version 1: 64-bit duration */ | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1232 |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1233 if (ngx_mp4_atom_data_size(ngx_mp4_mvhd64_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1234 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1235 "\"%s\" mp4 mvhd atom too small", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1236 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1237 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1238 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1239 |
4085 | 1240 timescale = ngx_mp4_get_32value(mvhd64_atom->timescale); |
1241 duration = ngx_mp4_get_64value(mvhd64_atom->duration); | |
1242 } | |
1243 | |
1244 mp4->timescale = timescale; | |
1245 | |
1246 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1247 "mvhd timescale:%uD, duration:%uL, time:%.3fs", | |
1248 timescale, duration, (double) duration / timescale); | |
1249 | |
1250 duration -= (uint64_t) mp4->start * timescale / 1000; | |
1251 | |
1252 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1253 "mvhd new duration:%uL, time:%.3fs", | |
1254 duration, (double) duration / timescale); | |
1255 | |
1256 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1257 ngx_mp4_set_32value(mvhd_atom->size, atom_size); | |
1258 | |
1259 if (mvhd_atom->version[0] == 0) { | |
1260 ngx_mp4_set_32value(mvhd_atom->duration, duration); | |
1261 | |
1262 } else { | |
1263 ngx_mp4_set_64value(mvhd64_atom->duration, duration); | |
1264 } | |
1265 | |
1266 atom = &mp4->mvhd_atom_buf; | |
1267 atom->temporary = 1; | |
1268 atom->pos = atom_header; | |
1269 atom->last = atom_header + atom_size; | |
1270 | |
1271 mp4->mvhd_atom.buf = atom; | |
1272 | |
1273 ngx_mp4_atom_next(mp4, atom_data_size); | |
1274 | |
1275 return NGX_OK; | |
1276 } | |
1277 | |
1278 | |
1279 static ngx_int_t | |
1280 ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1281 { | |
4099
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1282 u_char *atom_header, *atom_end; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1283 off_t atom_file_end; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1284 ngx_int_t rc; |
4085 | 1285 ngx_buf_t *atom; |
1286 ngx_http_mp4_trak_t *trak; | |
1287 | |
1288 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 trak atom"); | |
1289 | |
1290 trak = ngx_array_push(&mp4->trak); | |
1291 if (trak == NULL) { | |
1292 return NGX_ERROR; | |
1293 } | |
1294 | |
1295 ngx_memzero(trak, sizeof(ngx_http_mp4_trak_t)); | |
1296 | |
1297 atom_header = ngx_mp4_atom_header(mp4); | |
1298 ngx_mp4_set_atom_name(atom_header, 't', 'r', 'a', 'k'); | |
1299 | |
1300 atom = &trak->trak_atom_buf; | |
1301 atom->temporary = 1; | |
1302 atom->pos = atom_header; | |
1303 atom->last = atom_header + sizeof(ngx_mp4_atom_header_t); | |
1304 | |
1305 trak->out[NGX_HTTP_MP4_TRAK_ATOM].buf = atom; | |
1306 | |
4099
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1307 atom_end = mp4->buffer_pos + atom_data_size; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1308 atom_file_end = mp4->offset + atom_data_size; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1309 |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1310 rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_trak_atoms, atom_data_size); |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1311 |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1312 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1313 "mp4 trak atom: %i", rc); |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1314 |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1315 if (rc == NGX_DECLINED) { |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1316 /* skip this trak */ |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1317 ngx_memzero(trak, sizeof(ngx_http_mp4_trak_t)); |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1318 mp4->trak.nelts--; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1319 mp4->buffer_pos = atom_end; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1320 mp4->offset = atom_file_end; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1321 return NGX_OK; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1322 } |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1323 |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1324 return rc; |
4085 | 1325 } |
1326 | |
1327 | |
1328 static void | |
1329 ngx_http_mp4_update_trak_atom(ngx_http_mp4_file_t *mp4, | |
1330 ngx_http_mp4_trak_t *trak) | |
1331 { | |
1332 ngx_buf_t *atom; | |
1333 | |
1334 trak->size += sizeof(ngx_mp4_atom_header_t); | |
1335 atom = &trak->trak_atom_buf; | |
1336 ngx_mp4_set_32value(atom->pos, trak->size); | |
1337 } | |
1338 | |
1339 | |
1340 static ngx_int_t | |
1341 ngx_http_mp4_read_cmov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1342 { | |
1343 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1344 "\"%s\" mp4 compressed moov atom (cmov) is not supported", | |
1345 mp4->file.name.data); | |
1346 | |
1347 return NGX_ERROR; | |
1348 } | |
1349 | |
1350 | |
1351 typedef struct { | |
1352 u_char size[4]; | |
1353 u_char name[4]; | |
1354 u_char version[1]; | |
1355 u_char flags[3]; | |
1356 u_char creation_time[4]; | |
1357 u_char modification_time[4]; | |
1358 u_char track_id[4]; | |
1359 u_char reserved1[4]; | |
1360 u_char duration[4]; | |
1361 u_char reserved2[8]; | |
1362 u_char layer[2]; | |
1363 u_char group[2]; | |
1364 u_char volume[2]; | |
1365 u_char reverved3[2]; | |
1366 u_char matrix[36]; | |
1367 u_char width[4]; | |
1368 u_char heigth[4]; | |
1369 } ngx_mp4_tkhd_atom_t; | |
1370 | |
1371 typedef struct { | |
1372 u_char size[4]; | |
1373 u_char name[4]; | |
1374 u_char version[1]; | |
1375 u_char flags[3]; | |
1376 u_char creation_time[8]; | |
1377 u_char modification_time[8]; | |
1378 u_char track_id[4]; | |
1379 u_char reserved1[4]; | |
1380 u_char duration[8]; | |
1381 u_char reserved2[8]; | |
1382 u_char layer[2]; | |
1383 u_char group[2]; | |
1384 u_char volume[2]; | |
1385 u_char reverved3[2]; | |
1386 u_char matrix[36]; | |
1387 u_char width[4]; | |
1388 u_char heigth[4]; | |
1389 } ngx_mp4_tkhd64_atom_t; | |
1390 | |
1391 | |
1392 static ngx_int_t | |
1393 ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1394 { | |
1395 u_char *atom_header; | |
1396 size_t atom_size; | |
1397 uint64_t duration; | |
1398 ngx_buf_t *atom; | |
1399 ngx_http_mp4_trak_t *trak; | |
1400 ngx_mp4_tkhd_atom_t *tkhd_atom; | |
1401 ngx_mp4_tkhd64_atom_t *tkhd64_atom; | |
1402 | |
1403 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 tkhd atom"); | |
1404 | |
1405 atom_header = ngx_mp4_atom_header(mp4); | |
1406 tkhd_atom = (ngx_mp4_tkhd_atom_t *) atom_header; | |
1407 tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header; | |
1408 ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd'); | |
1409 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1410 if (ngx_mp4_atom_data_size(ngx_mp4_tkhd_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1411 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1412 "\"%s\" mp4 tkhd atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1413 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1414 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1415 |
4085 | 1416 if (tkhd_atom->version[0] == 0) { |
1417 /* version 0: 32-bit duration */ | |
1418 duration = ngx_mp4_get_32value(tkhd_atom->duration); | |
1419 | |
1420 } else { | |
1421 /* version 1: 64-bit duration */ | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1422 |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1423 if (ngx_mp4_atom_data_size(ngx_mp4_tkhd64_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1424 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1425 "\"%s\" mp4 tkhd atom too small", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1426 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1427 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1428 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1429 |
4085 | 1430 duration = ngx_mp4_get_64value(tkhd64_atom->duration); |
1431 } | |
1432 | |
1433 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1434 "tkhd duration:%uL, time:%.3fs", | |
1435 duration, (double) duration / mp4->timescale); | |
1436 | |
1437 duration -= (uint64_t) mp4->start * mp4->timescale / 1000; | |
1438 | |
1439 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1440 "tkhd new duration:%uL, time:%.3fs", | |
1441 duration, (double) duration / mp4->timescale); | |
1442 | |
1443 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1444 | |
1445 trak = ngx_mp4_last_trak(mp4); | |
1446 trak->tkhd_size = atom_size; | |
1447 | |
1448 ngx_mp4_set_32value(tkhd_atom->size, atom_size); | |
1449 | |
1450 if (tkhd_atom->version[0] == 0) { | |
1451 ngx_mp4_set_32value(tkhd_atom->duration, duration); | |
1452 | |
1453 } else { | |
1454 ngx_mp4_set_64value(tkhd64_atom->duration, duration); | |
1455 } | |
1456 | |
1457 atom = &trak->tkhd_atom_buf; | |
1458 atom->temporary = 1; | |
1459 atom->pos = atom_header; | |
1460 atom->last = atom_header + atom_size; | |
1461 | |
1462 trak->out[NGX_HTTP_MP4_TKHD_ATOM].buf = atom; | |
1463 | |
1464 ngx_mp4_atom_next(mp4, atom_data_size); | |
1465 | |
1466 return NGX_OK; | |
1467 } | |
1468 | |
1469 | |
1470 static ngx_int_t | |
1471 ngx_http_mp4_read_mdia_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1472 { | |
1473 u_char *atom_header; | |
1474 ngx_buf_t *atom; | |
1475 ngx_http_mp4_trak_t *trak; | |
1476 | |
1477 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "process mdia atom"); | |
1478 | |
1479 atom_header = ngx_mp4_atom_header(mp4); | |
1480 ngx_mp4_set_atom_name(atom_header, 'm', 'd', 'i', 'a'); | |
1481 | |
1482 trak = ngx_mp4_last_trak(mp4); | |
1483 | |
1484 atom = &trak->mdia_atom_buf; | |
1485 atom->temporary = 1; | |
1486 atom->pos = atom_header; | |
1487 atom->last = atom_header + sizeof(ngx_mp4_atom_header_t); | |
1488 | |
1489 trak->out[NGX_HTTP_MP4_MDIA_ATOM].buf = atom; | |
1490 | |
1491 return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_mdia_atoms, atom_data_size); | |
1492 } | |
1493 | |
1494 | |
1495 static void | |
1496 ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4, | |
1497 ngx_http_mp4_trak_t *trak) | |
1498 { | |
1499 ngx_buf_t *atom; | |
1500 | |
1501 trak->size += sizeof(ngx_mp4_atom_header_t); | |
1502 atom = &trak->mdia_atom_buf; | |
1503 ngx_mp4_set_32value(atom->pos, trak->size); | |
1504 } | |
1505 | |
1506 | |
1507 typedef struct { | |
1508 u_char size[4]; | |
1509 u_char name[4]; | |
1510 u_char version[1]; | |
1511 u_char flags[3]; | |
1512 u_char creation_time[4]; | |
1513 u_char modification_time[4]; | |
1514 u_char timescale[4]; | |
1515 u_char duration[4]; | |
1516 u_char language[2]; | |
1517 u_char quality[2]; | |
1518 } ngx_mp4_mdhd_atom_t; | |
1519 | |
1520 typedef struct { | |
1521 u_char size[4]; | |
1522 u_char name[4]; | |
1523 u_char version[1]; | |
1524 u_char flags[3]; | |
1525 u_char creation_time[8]; | |
1526 u_char modification_time[8]; | |
1527 u_char timescale[4]; | |
1528 u_char duration[8]; | |
1529 u_char language[2]; | |
1530 u_char quality[2]; | |
1531 } ngx_mp4_mdhd64_atom_t; | |
1532 | |
1533 | |
1534 static ngx_int_t | |
1535 ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1536 { | |
1537 u_char *atom_header; | |
1538 size_t atom_size; | |
1539 uint32_t timescale; | |
1540 uint64_t duration; | |
1541 ngx_buf_t *atom; | |
1542 ngx_http_mp4_trak_t *trak; | |
1543 ngx_mp4_mdhd_atom_t *mdhd_atom; | |
1544 ngx_mp4_mdhd64_atom_t *mdhd64_atom; | |
1545 | |
1546 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mdhd atom"); | |
1547 | |
1548 atom_header = ngx_mp4_atom_header(mp4); | |
1549 mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom_header; | |
1550 mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header; | |
1551 ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd'); | |
1552 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1553 if (ngx_mp4_atom_data_size(ngx_mp4_mdhd_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1554 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1555 "\"%s\" mp4 mdhd atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1556 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1557 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1558 |
4085 | 1559 if (mdhd_atom->version[0] == 0) { |
1560 /* version 0: everything is 32-bit */ | |
1561 timescale = ngx_mp4_get_32value(mdhd_atom->timescale); | |
1562 duration = ngx_mp4_get_32value(mdhd_atom->duration); | |
1563 | |
1564 } else { | |
1565 /* version 1: 64-bit duration and 32-bit timescale */ | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1566 |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1567 if (ngx_mp4_atom_data_size(ngx_mp4_mdhd64_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1568 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1569 "\"%s\" mp4 mdhd atom too small", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1570 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1571 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1572 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1573 |
4085 | 1574 timescale = ngx_mp4_get_32value(mdhd64_atom->timescale); |
1575 duration = ngx_mp4_get_64value(mdhd64_atom->duration); | |
1576 } | |
1577 | |
1578 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1579 "mdhd timescale:%uD, duration:%uL, time:%.3fs", | |
1580 timescale, duration, (double) duration / timescale); | |
1581 | |
1582 duration -= (uint64_t) mp4->start * timescale / 1000; | |
1583 | |
1584 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1585 "mdhd new duration:%uL, time:%.3fs", | |
1586 duration, (double) duration / timescale); | |
1587 | |
1588 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1589 | |
1590 trak = ngx_mp4_last_trak(mp4); | |
1591 trak->mdhd_size = atom_size; | |
1592 trak->timescale = timescale; | |
1593 | |
1594 ngx_mp4_set_32value(mdhd_atom->size, atom_size); | |
1595 | |
1596 if (mdhd_atom->version[0] == 0) { | |
1597 ngx_mp4_set_32value(mdhd_atom->duration, duration); | |
1598 | |
1599 } else { | |
1600 ngx_mp4_set_64value(mdhd64_atom->duration, duration); | |
1601 } | |
1602 | |
1603 atom = &trak->mdhd_atom_buf; | |
1604 atom->temporary = 1; | |
1605 atom->pos = atom_header; | |
1606 atom->last = atom_header + atom_size; | |
1607 | |
1608 trak->out[NGX_HTTP_MP4_MDHD_ATOM].buf = atom; | |
1609 | |
1610 ngx_mp4_atom_next(mp4, atom_data_size); | |
1611 | |
1612 return NGX_OK; | |
1613 } | |
1614 | |
1615 | |
1616 static ngx_int_t | |
1617 ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1618 { | |
1619 u_char *atom_header; | |
1620 size_t atom_size; | |
1621 ngx_buf_t *atom; | |
1622 ngx_http_mp4_trak_t *trak; | |
1623 | |
1624 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 hdlr atom"); | |
1625 | |
1626 atom_header = ngx_mp4_atom_header(mp4); | |
1627 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1628 ngx_mp4_set_32value(atom_header, atom_size); | |
1629 ngx_mp4_set_atom_name(atom_header, 'h', 'd', 'l', 'r'); | |
1630 | |
1631 trak = ngx_mp4_last_trak(mp4); | |
1632 | |
1633 atom = &trak->hdlr_atom_buf; | |
1634 atom->temporary = 1; | |
1635 atom->pos = atom_header; | |
1636 atom->last = atom_header + atom_size; | |
1637 | |
1638 trak->hdlr_size = atom_size; | |
1639 trak->out[NGX_HTTP_MP4_HDLR_ATOM].buf = atom; | |
1640 | |
1641 ngx_mp4_atom_next(mp4, atom_data_size); | |
1642 | |
1643 return NGX_OK; | |
1644 } | |
1645 | |
1646 | |
1647 static ngx_int_t | |
1648 ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1649 { | |
1650 u_char *atom_header; | |
1651 ngx_buf_t *atom; | |
1652 ngx_http_mp4_trak_t *trak; | |
1653 | |
1654 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "process minf atom"); | |
1655 | |
1656 atom_header = ngx_mp4_atom_header(mp4); | |
1657 ngx_mp4_set_atom_name(atom_header, 'm', 'i', 'n', 'f'); | |
1658 | |
1659 trak = ngx_mp4_last_trak(mp4); | |
1660 | |
1661 atom = &trak->minf_atom_buf; | |
1662 atom->temporary = 1; | |
1663 atom->pos = atom_header; | |
1664 atom->last = atom_header + sizeof(ngx_mp4_atom_header_t); | |
1665 | |
1666 trak->out[NGX_HTTP_MP4_MINF_ATOM].buf = atom; | |
1667 | |
1668 return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_minf_atoms, atom_data_size); | |
1669 } | |
1670 | |
1671 | |
1672 static void | |
1673 ngx_http_mp4_update_minf_atom(ngx_http_mp4_file_t *mp4, | |
1674 ngx_http_mp4_trak_t *trak) | |
1675 { | |
1676 ngx_buf_t *atom; | |
1677 | |
1678 trak->size += sizeof(ngx_mp4_atom_header_t) | |
1679 + trak->vmhd_size | |
1680 + trak->smhd_size | |
1681 + trak->dinf_size; | |
1682 atom = &trak->minf_atom_buf; | |
1683 ngx_mp4_set_32value(atom->pos, trak->size); | |
1684 } | |
1685 | |
1686 | |
1687 static ngx_int_t | |
1688 ngx_http_mp4_read_vmhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1689 { | |
1690 u_char *atom_header; | |
1691 size_t atom_size; | |
1692 ngx_buf_t *atom; | |
1693 ngx_http_mp4_trak_t *trak; | |
1694 | |
1695 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 vmhd atom"); | |
1696 | |
1697 atom_header = ngx_mp4_atom_header(mp4); | |
1698 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1699 ngx_mp4_set_32value(atom_header, atom_size); | |
1700 ngx_mp4_set_atom_name(atom_header, 'v', 'm', 'h', 'd'); | |
1701 | |
1702 trak = ngx_mp4_last_trak(mp4); | |
1703 | |
1704 atom = &trak->vmhd_atom_buf; | |
1705 atom->temporary = 1; | |
1706 atom->pos = atom_header; | |
1707 atom->last = atom_header + atom_size; | |
1708 | |
1709 trak->vmhd_size += atom_size; | |
1710 trak->out[NGX_HTTP_MP4_VMHD_ATOM].buf = atom; | |
1711 | |
1712 ngx_mp4_atom_next(mp4, atom_data_size); | |
1713 | |
1714 return NGX_OK; | |
1715 } | |
1716 | |
1717 | |
1718 static ngx_int_t | |
1719 ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1720 { | |
1721 u_char *atom_header; | |
1722 size_t atom_size; | |
1723 ngx_buf_t *atom; | |
1724 ngx_http_mp4_trak_t *trak; | |
1725 | |
1726 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 smhd atom"); | |
1727 | |
1728 atom_header = ngx_mp4_atom_header(mp4); | |
1729 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1730 ngx_mp4_set_32value(atom_header, atom_size); | |
1731 ngx_mp4_set_atom_name(atom_header, 's', 'm', 'h', 'd'); | |
1732 | |
1733 trak = ngx_mp4_last_trak(mp4); | |
1734 | |
1735 atom = &trak->smhd_atom_buf; | |
1736 atom->temporary = 1; | |
1737 atom->pos = atom_header; | |
1738 atom->last = atom_header + atom_size; | |
1739 | |
1740 trak->vmhd_size += atom_size; | |
1741 trak->out[NGX_HTTP_MP4_SMHD_ATOM].buf = atom; | |
1742 | |
1743 ngx_mp4_atom_next(mp4, atom_data_size); | |
1744 | |
1745 return NGX_OK; | |
1746 } | |
1747 | |
1748 | |
1749 static ngx_int_t | |
1750 ngx_http_mp4_read_dinf_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1751 { | |
1752 u_char *atom_header; | |
1753 size_t atom_size; | |
1754 ngx_buf_t *atom; | |
1755 ngx_http_mp4_trak_t *trak; | |
1756 | |
1757 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 dinf atom"); | |
1758 | |
1759 atom_header = ngx_mp4_atom_header(mp4); | |
1760 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1761 ngx_mp4_set_32value(atom_header, atom_size); | |
1762 ngx_mp4_set_atom_name(atom_header, 'd', 'i', 'n', 'f'); | |
1763 | |
1764 trak = ngx_mp4_last_trak(mp4); | |
1765 | |
1766 atom = &trak->dinf_atom_buf; | |
1767 atom->temporary = 1; | |
1768 atom->pos = atom_header; | |
1769 atom->last = atom_header + atom_size; | |
1770 | |
1771 trak->dinf_size += atom_size; | |
1772 trak->out[NGX_HTTP_MP4_DINF_ATOM].buf = atom; | |
1773 | |
1774 ngx_mp4_atom_next(mp4, atom_data_size); | |
1775 | |
1776 return NGX_OK; | |
1777 } | |
1778 | |
1779 | |
1780 static ngx_int_t | |
1781 ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1782 { | |
1783 u_char *atom_header; | |
1784 ngx_buf_t *atom; | |
1785 ngx_http_mp4_trak_t *trak; | |
1786 | |
1787 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "process stbl atom"); | |
1788 | |
1789 atom_header = ngx_mp4_atom_header(mp4); | |
1790 ngx_mp4_set_atom_name(atom_header, 's', 't', 'b', 'l'); | |
1791 | |
1792 trak = ngx_mp4_last_trak(mp4); | |
1793 | |
1794 atom = &trak->stbl_atom_buf; | |
1795 atom->temporary = 1; | |
1796 atom->pos = atom_header; | |
1797 atom->last = atom_header + sizeof(ngx_mp4_atom_header_t); | |
1798 | |
1799 trak->out[NGX_HTTP_MP4_STBL_ATOM].buf = atom; | |
1800 | |
1801 return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_stbl_atoms, atom_data_size); | |
1802 } | |
1803 | |
1804 | |
1805 static void | |
1806 ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4, | |
1807 ngx_http_mp4_trak_t *trak) | |
1808 { | |
1809 ngx_buf_t *atom; | |
1810 | |
1811 trak->size += sizeof(ngx_mp4_atom_header_t); | |
1812 atom = &trak->stbl_atom_buf; | |
1813 ngx_mp4_set_32value(atom->pos, trak->size); | |
1814 } | |
1815 | |
1816 | |
1817 typedef struct { | |
1818 u_char size[4]; | |
1819 u_char name[4]; | |
1820 u_char version[1]; | |
1821 u_char flags[3]; | |
1822 u_char entries[4]; | |
4099
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1823 |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1824 u_char media_size[4]; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1825 u_char media_name[4]; |
4085 | 1826 } ngx_mp4_stsd_atom_t; |
1827 | |
1828 | |
1829 static ngx_int_t | |
1830 ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1831 { | |
1832 u_char *atom_header, *atom_table; | |
1833 size_t atom_size; | |
1834 ngx_buf_t *atom; | |
1835 ngx_mp4_stsd_atom_t *stsd_atom; | |
1836 ngx_http_mp4_trak_t *trak; | |
1837 | |
1838 /* sample description atom */ | |
1839 | |
1840 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stsd atom"); | |
1841 | |
1842 atom_header = ngx_mp4_atom_header(mp4); | |
1843 stsd_atom = (ngx_mp4_stsd_atom_t *) atom_header; | |
1844 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | |
1845 atom_table = atom_header + atom_size; | |
1846 ngx_mp4_set_32value(stsd_atom->size, atom_size); | |
1847 ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd'); | |
1848 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1849 if (ngx_mp4_atom_data_size(ngx_mp4_stsd_atom_t) > atom_data_size) { |
4099
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1850 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1851 "\"%s\" mp4 stsd atom too small", mp4->file.name.data); |
4099
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1852 return NGX_ERROR; |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1853 } |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1854 |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1855 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1856 "stsd entries:%uD, media:%*s", |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1857 ngx_mp4_get_32value(stsd_atom->entries), |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1858 4, stsd_atom->media_name); |
9ee6944590c0
Skipping traks with unsupported media formats.
Igor Sysoev <igor@sysoev.ru>
parents:
4098
diff
changeset
|
1859 |
4085 | 1860 trak = ngx_mp4_last_trak(mp4); |
1861 | |
1862 atom = &trak->stsd_atom_buf; | |
1863 atom->temporary = 1; | |
1864 atom->pos = atom_header; | |
1865 atom->last = atom_table; | |
1866 | |
1867 trak->out[NGX_HTTP_MP4_STSD_ATOM].buf = atom; | |
1868 trak->size += atom_size; | |
1869 | |
1870 ngx_mp4_atom_next(mp4, atom_data_size); | |
1871 | |
1872 return NGX_OK; | |
1873 } | |
1874 | |
1875 | |
1876 typedef struct { | |
1877 u_char size[4]; | |
1878 u_char name[4]; | |
1879 u_char version[1]; | |
1880 u_char flags[3]; | |
1881 u_char entries[4]; | |
1882 } ngx_mp4_stts_atom_t; | |
1883 | |
1884 typedef struct { | |
1885 u_char count[4]; | |
1886 u_char duration[4]; | |
1887 } ngx_mp4_stts_entry_t; | |
1888 | |
1889 | |
1890 static ngx_int_t | |
1891 ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
1892 { | |
1893 u_char *atom_header, *atom_table, *atom_end; | |
1894 uint32_t entries; | |
1895 ngx_buf_t *atom, *data; | |
1896 ngx_mp4_stts_atom_t *stts_atom; | |
1897 ngx_http_mp4_trak_t *trak; | |
1898 | |
1899 /* time-to-sample atom */ | |
1900 | |
1901 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stts atom"); | |
1902 | |
1903 atom_header = ngx_mp4_atom_header(mp4); | |
1904 stts_atom = (ngx_mp4_stts_atom_t *) atom_header; | |
1905 ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's'); | |
1906 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1907 if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1908 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1909 "\"%s\" mp4 stts atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1910 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1911 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1912 |
4085 | 1913 entries = ngx_mp4_get_32value(stts_atom->entries); |
1914 | |
1915 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
4096 | 1916 "mp4 time-to-sample entries:%uD", entries); |
4085 | 1917 |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1918 if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1919 + entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1920 { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1921 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1922 "\"%s\" mp4 stts atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1923 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1924 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
1925 |
4085 | 1926 atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t); |
1927 atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t); | |
1928 | |
1929 trak = ngx_mp4_last_trak(mp4); | |
1930 trak->time_to_sample_entries = entries; | |
1931 | |
1932 atom = &trak->stts_atom_buf; | |
1933 atom->temporary = 1; | |
1934 atom->pos = atom_header; | |
1935 atom->last = atom_table; | |
1936 | |
1937 data = &trak->stts_data_buf; | |
1938 data->temporary = 1; | |
1939 data->pos = atom_table; | |
1940 data->last = atom_end; | |
1941 | |
1942 trak->out[NGX_HTTP_MP4_STTS_ATOM].buf = atom; | |
1943 trak->out[NGX_HTTP_MP4_STTS_DATA].buf = data; | |
1944 | |
1945 ngx_mp4_atom_next(mp4, atom_data_size); | |
1946 | |
1947 return NGX_OK; | |
1948 } | |
1949 | |
1950 | |
1951 static ngx_int_t | |
1952 ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4, | |
1953 ngx_http_mp4_trak_t *trak) | |
1954 { | |
1955 size_t atom_size; | |
1956 uint32_t entries, count, duration; | |
1957 uint64_t start_time; | |
1958 ngx_buf_t *atom, *data; | |
1959 ngx_uint_t start_sample; | |
1960 ngx_mp4_stts_atom_t *stts_atom; | |
1961 ngx_mp4_stts_entry_t *entry, *end; | |
1962 | |
1963 /* | |
1964 * mdia.minf.stbl.stts updating requires trak->timescale | |
1965 * from mdia.mdhd atom which may reside after mdia.minf | |
1966 */ | |
1967 | |
1968 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1969 "mp4 stts atom update"); | |
1970 | |
1971 data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf; | |
1972 | |
1973 if (data == NULL) { | |
1974 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1975 "no mp4 stts atoms were found in \"%s\"", | |
1976 mp4->file.name.data); | |
1977 return NGX_ERROR; | |
1978 } | |
1979 | |
1980 entries = trak->time_to_sample_entries; | |
4189
a12c558503f0
Fixing mp4 module seeking on 32-bit platforms.
Igor Sysoev <igor@sysoev.ru>
parents:
4156
diff
changeset
|
1981 start_time = (uint64_t) mp4->start * trak->timescale / 1000; |
4085 | 1982 |
1983 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
4096 | 1984 "time-to-sample start_time:%uL", start_time); |
4085 | 1985 |
1986 start_sample = 0; | |
1987 entry = (ngx_mp4_stts_entry_t *) data->pos; | |
1988 end = (ngx_mp4_stts_entry_t *) data->last; | |
1989 | |
1990 while (entry < end) { | |
1991 count = ngx_mp4_get_32value(entry->count); | |
1992 duration = ngx_mp4_get_32value(entry->duration); | |
1993 | |
1994 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
1995 "count:%uD, duration:%uD", count, duration); | |
1996 | |
4306 | 1997 if (start_time < (uint64_t) count * duration) { |
4085 | 1998 start_sample += (ngx_uint_t) (start_time / duration); |
4578 | 1999 count -= (uint32_t) (start_time / duration); |
4085 | 2000 ngx_mp4_set_32value(entry->count, count); |
2001 goto found; | |
2002 } | |
2003 | |
2004 start_sample += count; | |
2005 start_time -= count * duration; | |
2006 entries--; | |
2007 entry++; | |
2008 } | |
2009 | |
2010 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
4094 | 2011 "start time is out mp4 stts samples in \"%s\"", |
4085 | 2012 mp4->file.name.data); |
2013 | |
2014 return NGX_ERROR; | |
2015 | |
2016 found: | |
2017 | |
2018 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2019 "start_sample:%ui, new count:%uD", start_sample, count); | |
2020 | |
2021 trak->start_sample = start_sample; | |
2022 | |
2023 data->pos = (u_char *) entry; | |
2024 atom_size = sizeof(ngx_mp4_stts_atom_t) + (data->last - data->pos); | |
2025 trak->size += atom_size; | |
2026 | |
2027 atom = trak->out[NGX_HTTP_MP4_STTS_ATOM].buf; | |
2028 stts_atom = (ngx_mp4_stts_atom_t *) atom->pos; | |
2029 ngx_mp4_set_32value(stts_atom->size, atom_size); | |
2030 ngx_mp4_set_32value(stts_atom->entries, entries); | |
2031 | |
2032 return NGX_OK; | |
2033 } | |
2034 | |
2035 | |
2036 typedef struct { | |
2037 u_char size[4]; | |
2038 u_char name[4]; | |
2039 u_char version[1]; | |
2040 u_char flags[3]; | |
2041 u_char entries[4]; | |
2042 } ngx_http_mp4_stss_atom_t; | |
2043 | |
2044 | |
2045 static ngx_int_t | |
2046 ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
2047 { | |
2048 u_char *atom_header, *atom_table, *atom_end; | |
2049 uint32_t entries; | |
2050 ngx_buf_t *atom, *data; | |
2051 ngx_http_mp4_trak_t *trak; | |
2052 ngx_http_mp4_stss_atom_t *stss_atom; | |
2053 | |
2054 /* sync samples atom */ | |
2055 | |
2056 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stss atom"); | |
2057 | |
2058 atom_header = ngx_mp4_atom_header(mp4); | |
2059 stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header; | |
2060 ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's'); | |
2061 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2062 if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2063 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2064 "\"%s\" mp4 stss atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2065 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2066 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2067 |
4085 | 2068 entries = ngx_mp4_get_32value(stss_atom->entries); |
2069 | |
2070 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
4096 | 2071 "sync sample entries:%uD", entries); |
4085 | 2072 |
2073 trak = ngx_mp4_last_trak(mp4); | |
2074 trak->sync_samples_entries = entries; | |
2075 | |
2076 atom_table = atom_header + sizeof(ngx_http_mp4_stss_atom_t); | |
2077 | |
2078 atom = &trak->stss_atom_buf; | |
2079 atom->temporary = 1; | |
2080 atom->pos = atom_header; | |
2081 atom->last = atom_table; | |
2082 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2083 if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2084 + entries * sizeof(uint32_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2085 { |
4085 | 2086 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2087 "\"%s\" mp4 stss atom too small", mp4->file.name.data); |
4085 | 2088 return NGX_ERROR; |
2089 } | |
2090 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2091 atom_end = atom_table + entries * sizeof(uint32_t); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2092 |
4085 | 2093 data = &trak->stss_data_buf; |
2094 data->temporary = 1; | |
2095 data->pos = atom_table; | |
2096 data->last = atom_end; | |
2097 | |
2098 trak->out[NGX_HTTP_MP4_STSS_ATOM].buf = atom; | |
2099 trak->out[NGX_HTTP_MP4_STSS_DATA].buf = data; | |
2100 | |
2101 ngx_mp4_atom_next(mp4, atom_data_size); | |
2102 | |
2103 return NGX_OK; | |
2104 } | |
2105 | |
2106 | |
2107 static ngx_int_t | |
2108 ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4, | |
2109 ngx_http_mp4_trak_t *trak) | |
2110 { | |
2111 size_t atom_size; | |
2112 uint32_t entries, sample, start_sample, *entry, *end; | |
2113 ngx_buf_t *atom, *data; | |
2114 ngx_http_mp4_stss_atom_t *stss_atom; | |
2115 | |
2116 /* | |
2117 * mdia.minf.stbl.stss updating requires trak->start_sample | |
2118 * from mdia.minf.stbl.stts which depends on value from mdia.mdhd | |
2119 * atom which may reside after mdia.minf | |
2120 */ | |
2121 | |
2122 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2123 "mp4 stss atom update"); | |
2124 | |
2125 data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf; | |
2126 | |
2127 if (data == NULL) { | |
2128 return NGX_OK; | |
2129 } | |
2130 | |
2131 /* sync samples starts from 1 */ | |
2132 start_sample = trak->start_sample + 1; | |
2133 entries = trak->sync_samples_entries; | |
2134 | |
2135 entry = (uint32_t *) data->pos; | |
2136 end = (uint32_t *) data->last; | |
2137 | |
2138 while (entry < end) { | |
2139 sample = ngx_mp4_get_32value(entry); | |
2140 | |
2141 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2142 "start:%uD, sync:%uD", start_sample, sample); | |
2143 | |
2144 if (sample >= start_sample) { | |
2145 goto found; | |
2146 } | |
2147 | |
2148 entries--; | |
2149 entry++; | |
2150 } | |
2151 | |
2152 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2153 "start sample is out of mp4 stss atom in \"%s\"", | |
2154 mp4->file.name.data); | |
2155 | |
2156 return NGX_ERROR; | |
2157 | |
2158 found: | |
2159 | |
2160 data->pos = (u_char *) entry; | |
2161 | |
2162 start_sample = trak->start_sample; | |
2163 | |
2164 while (entry < end) { | |
2165 sample = ngx_mp4_get_32value(entry); | |
2166 sample -= start_sample; | |
2167 ngx_mp4_set_32value(entry, sample); | |
2168 entry++; | |
2169 } | |
2170 | |
2171 atom_size = sizeof(ngx_http_mp4_stss_atom_t) + (data->last - data->pos); | |
2172 trak->size += atom_size; | |
2173 | |
2174 atom = trak->out[NGX_HTTP_MP4_STSS_ATOM].buf; | |
2175 stss_atom = (ngx_http_mp4_stss_atom_t *) atom->pos; | |
2176 | |
2177 ngx_mp4_set_32value(stss_atom->size, atom_size); | |
2178 ngx_mp4_set_32value(stss_atom->entries, entries); | |
2179 | |
2180 return NGX_OK; | |
2181 } | |
2182 | |
2183 | |
2184 typedef struct { | |
2185 u_char size[4]; | |
2186 u_char name[4]; | |
2187 u_char version[1]; | |
2188 u_char flags[3]; | |
2189 u_char entries[4]; | |
2190 } ngx_mp4_ctts_atom_t; | |
2191 | |
2192 typedef struct { | |
2193 u_char count[4]; | |
2194 u_char offset[4]; | |
2195 } ngx_mp4_ctts_entry_t; | |
2196 | |
2197 | |
2198 static ngx_int_t | |
2199 ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
2200 { | |
2201 u_char *atom_header, *atom_table, *atom_end; | |
2202 uint32_t entries; | |
2203 ngx_buf_t *atom, *data; | |
2204 ngx_mp4_ctts_atom_t *ctts_atom; | |
2205 ngx_http_mp4_trak_t *trak; | |
2206 | |
2207 /* composition offsets atom */ | |
2208 | |
2209 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ctts atom"); | |
2210 | |
2211 atom_header = ngx_mp4_atom_header(mp4); | |
2212 ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header; | |
2213 ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's'); | |
2214 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2215 if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2216 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2217 "\"%s\" mp4 ctts atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2218 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2219 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2220 |
4085 | 2221 entries = ngx_mp4_get_32value(ctts_atom->entries); |
2222 | |
2223 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
4096 | 2224 "composition offset entries:%uD", entries); |
4085 | 2225 |
2226 trak = ngx_mp4_last_trak(mp4); | |
2227 trak->composition_offset_entries = entries; | |
2228 | |
2229 atom_table = atom_header + sizeof(ngx_mp4_ctts_atom_t); | |
2230 | |
2231 atom = &trak->ctts_atom_buf; | |
2232 atom->temporary = 1; | |
2233 atom->pos = atom_header; | |
2234 atom->last = atom_table; | |
2235 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2236 if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2237 + entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2238 { |
4085 | 2239 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2240 "\"%s\" mp4 ctts atom too small", mp4->file.name.data); |
4085 | 2241 return NGX_ERROR; |
2242 } | |
2243 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2244 atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2245 |
4085 | 2246 data = &trak->ctts_data_buf; |
2247 data->temporary = 1; | |
2248 data->pos = atom_table; | |
2249 data->last = atom_end; | |
2250 | |
2251 trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = atom; | |
2252 trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = data; | |
2253 | |
2254 ngx_mp4_atom_next(mp4, atom_data_size); | |
2255 | |
2256 return NGX_OK; | |
2257 } | |
2258 | |
2259 | |
2260 static void | |
2261 ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4, | |
2262 ngx_http_mp4_trak_t *trak) | |
2263 { | |
2264 size_t atom_size; | |
2265 uint32_t entries, count, start_sample; | |
2266 ngx_buf_t *atom, *data; | |
2267 ngx_mp4_ctts_atom_t *ctts_atom; | |
2268 ngx_mp4_ctts_entry_t *entry, *end; | |
2269 | |
2270 /* | |
2271 * mdia.minf.stbl.ctts updating requires trak->start_sample | |
2272 * from mdia.minf.stbl.stts which depends on value from mdia.mdhd | |
2273 * atom which may reside after mdia.minf | |
2274 */ | |
2275 | |
2276 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2277 "mp4 ctts atom update"); | |
2278 | |
2279 data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf; | |
2280 | |
2281 if (data == NULL) { | |
2282 return; | |
2283 } | |
2284 | |
2285 /* sync samples starts from 1 */ | |
2286 start_sample = trak->start_sample + 1; | |
2287 entries = trak->composition_offset_entries; | |
2288 entry = (ngx_mp4_ctts_entry_t *) data->pos; | |
2289 end = (ngx_mp4_ctts_entry_t *) data->last; | |
2290 | |
2291 while (entry < end) { | |
2292 count = ngx_mp4_get_32value(entry->count); | |
2293 | |
4088
8fe1da7b8386
bugfix of r4086: nginx could not be built without debug log.
Igor Sysoev <igor@sysoev.ru>
parents:
4087
diff
changeset
|
2294 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
4085 | 2295 "start:%uD, count:%uD, offset:%uD", |
2296 start_sample, count, ngx_mp4_get_32value(entry->offset)); | |
2297 | |
2298 if (start_sample <= count) { | |
2299 count -= (start_sample - 1); | |
2300 ngx_mp4_set_32value(entry->count, count); | |
2301 goto found; | |
2302 } | |
2303 | |
2304 start_sample -= count; | |
2305 entries--; | |
2306 entry++; | |
2307 } | |
2308 | |
2309 trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL; | |
2310 trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = NULL; | |
2311 | |
2312 return; | |
2313 | |
2314 found: | |
2315 | |
2316 data->pos = (u_char *) entry; | |
2317 atom_size = sizeof(ngx_mp4_ctts_atom_t) + (data->last - data->pos); | |
2318 trak->size += atom_size; | |
2319 | |
2320 atom = trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf; | |
2321 ctts_atom = (ngx_mp4_ctts_atom_t *) atom->pos; | |
2322 | |
2323 ngx_mp4_set_32value(ctts_atom->size, atom_size); | |
2324 ngx_mp4_set_32value(ctts_atom->entries, entries); | |
2325 | |
2326 return; | |
2327 } | |
2328 | |
2329 | |
2330 typedef struct { | |
2331 u_char size[4]; | |
2332 u_char name[4]; | |
2333 u_char version[1]; | |
2334 u_char flags[3]; | |
2335 u_char entries[4]; | |
2336 } ngx_mp4_stsc_atom_t; | |
2337 | |
2338 | |
2339 static ngx_int_t | |
2340 ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
2341 { | |
2342 u_char *atom_header, *atom_table, *atom_end; | |
2343 uint32_t entries; | |
2344 ngx_buf_t *atom, *data; | |
2345 ngx_mp4_stsc_atom_t *stsc_atom; | |
2346 ngx_http_mp4_trak_t *trak; | |
2347 | |
2348 /* sample-to-chunk atom */ | |
2349 | |
2350 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stsc atom"); | |
2351 | |
2352 atom_header = ngx_mp4_atom_header(mp4); | |
2353 stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header; | |
2354 ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c'); | |
2355 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2356 if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2357 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2358 "\"%s\" mp4 stsc atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2359 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2360 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2361 |
4085 | 2362 entries = ngx_mp4_get_32value(stsc_atom->entries); |
2363 | |
2364 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
4096 | 2365 "sample-to-chunk entries:%uD", entries); |
4085 | 2366 |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2367 if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2368 + entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2369 { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2370 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2371 "\"%s\" mp4 stsc atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2372 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2373 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2374 |
4085 | 2375 atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t); |
2376 atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t); | |
2377 | |
2378 trak = ngx_mp4_last_trak(mp4); | |
2379 trak->sample_to_chunk_entries = entries; | |
2380 | |
2381 atom = &trak->stsc_atom_buf; | |
2382 atom->temporary = 1; | |
2383 atom->pos = atom_header; | |
2384 atom->last = atom_table; | |
2385 | |
2386 data = &trak->stsc_data_buf; | |
2387 data->temporary = 1; | |
2388 data->pos = atom_table; | |
2389 data->last = atom_end; | |
2390 | |
2391 trak->out[NGX_HTTP_MP4_STSC_ATOM].buf = atom; | |
2392 trak->out[NGX_HTTP_MP4_STSC_DATA].buf = data; | |
2393 | |
2394 ngx_mp4_atom_next(mp4, atom_data_size); | |
2395 | |
2396 return NGX_OK; | |
2397 } | |
2398 | |
2399 | |
2400 static ngx_int_t | |
2401 ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4, | |
2402 ngx_http_mp4_trak_t *trak) | |
2403 { | |
2404 size_t atom_size; | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2405 uint32_t start_sample, entries, chunk, samples, id, |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2406 next_chunk, n; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2407 ngx_buf_t *atom, *data, *buf; |
4085 | 2408 ngx_mp4_stsc_atom_t *stsc_atom; |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2409 ngx_mp4_stsc_entry_t *entry, *first, *end; |
4085 | 2410 |
2411 /* | |
2412 * mdia.minf.stbl.stsc updating requires trak->start_sample | |
2413 * from mdia.minf.stbl.stts which depends on value from mdia.mdhd | |
2414 * atom which may reside after mdia.minf | |
2415 */ | |
2416 | |
2417 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2418 "mp4 stsc atom update"); | |
2419 | |
2420 data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf; | |
2421 | |
2422 if (data == NULL) { | |
2423 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2424 "no mp4 stsc atoms were found in \"%s\"", | |
2425 mp4->file.name.data); | |
2426 return NGX_ERROR; | |
2427 } | |
2428 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2429 if (trak->sample_to_chunk_entries == 0) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2430 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2431 "zero number of entries in stsc atom in \"%s\"", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2432 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2433 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2434 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2435 |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2436 start_sample = (uint32_t) trak->start_sample; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2437 entries = trak->sample_to_chunk_entries - 1; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2438 |
4085 | 2439 entry = (ngx_mp4_stsc_entry_t *) data->pos; |
2440 end = (ngx_mp4_stsc_entry_t *) data->last; | |
2441 | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2442 chunk = ngx_mp4_get_32value(entry->chunk); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2443 samples = ngx_mp4_get_32value(entry->samples); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2444 id = ngx_mp4_get_32value(entry->id); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2445 entry++; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2446 |
4085 | 2447 while (entry < end) { |
2448 | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2449 next_chunk = ngx_mp4_get_32value(entry->chunk); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2450 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2451 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2452 "start_sample:%uD, chunk:%uD, chunks:%uD, " |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2453 "samples:%uD, id:%uD", |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2454 start_sample, chunk, next_chunk - chunk, samples, id); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2455 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2456 n = (next_chunk - chunk) * samples; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2457 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2458 if (start_sample <= n) { |
4085 | 2459 goto found; |
2460 } | |
2461 | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2462 start_sample -= n; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2463 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2464 chunk = next_chunk; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2465 samples = ngx_mp4_get_32value(entry->samples); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2466 id = ngx_mp4_get_32value(entry->id); |
4085 | 2467 entries--; |
2468 entry++; | |
2469 } | |
2470 | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2471 next_chunk = trak->chunks; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2472 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2473 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2474 "start_sample:%uD, chunk:%uD, chunks:%uD, samples:%uD", |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2475 start_sample, chunk, next_chunk - chunk, samples); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2476 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2477 n = (next_chunk - chunk) * samples; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2478 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2479 if (start_sample > n) { |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2480 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2481 "start time is out mp4 stsc chunks in \"%s\"", |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2482 mp4->file.name.data); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2483 return NGX_ERROR; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2484 } |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2485 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2486 found: |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2487 |
4085 | 2488 entries++; |
2489 entry--; | |
2490 | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2491 if (samples == 0) { |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2492 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2493 "zero number of samples in \"%s\"", |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2494 mp4->file.name.data); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2495 return NGX_ERROR; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2496 } |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2497 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2498 trak->start_chunk = chunk - 1; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2499 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2500 trak->start_chunk += start_sample / samples; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2501 trak->chunk_samples = start_sample % samples; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2502 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2503 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2504 "start chunk:%ui, samples:%uD", |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2505 trak->start_chunk, trak->chunk_samples); |
4085 | 2506 |
2507 data->pos = (u_char *) entry; | |
2508 atom_size = sizeof(ngx_mp4_stsc_atom_t) + (data->last - data->pos); | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2509 |
4382
b4d54fa76853
Fixed mp4 if first entry in stsc was skipped (ticket #72).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4306
diff
changeset
|
2510 ngx_mp4_set_32value(entry->chunk, 1); |
b4d54fa76853
Fixed mp4 if first entry in stsc was skipped (ticket #72).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4306
diff
changeset
|
2511 |
4687
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2512 if (trak->chunk_samples && next_chunk - trak->start_chunk == 2) { |
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2513 |
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2514 /* last chunk in the entry */ |
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2515 |
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2516 ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples); |
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2517 |
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2518 } else if (trak->chunk_samples) { |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2519 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2520 first = &trak->stsc_chunk_entry; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2521 ngx_mp4_set_32value(first->chunk, 1); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2522 ngx_mp4_set_32value(first->samples, samples - trak->chunk_samples); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2523 ngx_mp4_set_32value(first->id, id); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2524 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2525 buf = &trak->stsc_chunk_buf; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2526 buf->temporary = 1; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2527 buf->pos = (u_char *) first; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2528 buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2529 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2530 trak->out[NGX_HTTP_MP4_STSC_CHUNK].buf = buf; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2531 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2532 ngx_mp4_set_32value(entry->chunk, 2); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2533 |
4687
7f50a4063100
Mp4: fixed non-keyframe seeks in some cases (ticket #175).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
2534 entries++; |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2535 atom_size += sizeof(ngx_mp4_stsc_entry_t); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2536 } |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2537 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2538 while (++entry < end) { |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2539 chunk = ngx_mp4_get_32value(entry->chunk); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2540 chunk -= trak->start_chunk; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2541 ngx_mp4_set_32value(entry->chunk, chunk); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2542 } |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2543 |
4085 | 2544 trak->size += atom_size; |
2545 | |
2546 atom = trak->out[NGX_HTTP_MP4_STSC_ATOM].buf; | |
2547 stsc_atom = (ngx_mp4_stsc_atom_t *) atom->pos; | |
2548 | |
2549 ngx_mp4_set_32value(stsc_atom->size, atom_size); | |
2550 ngx_mp4_set_32value(stsc_atom->entries, entries); | |
2551 | |
2552 return NGX_OK; | |
2553 } | |
2554 | |
2555 | |
2556 typedef struct { | |
2557 u_char size[4]; | |
2558 u_char name[4]; | |
2559 u_char version[1]; | |
2560 u_char flags[3]; | |
2561 u_char uniform_size[4]; | |
2562 u_char entries[4]; | |
2563 } ngx_mp4_stsz_atom_t; | |
2564 | |
2565 | |
2566 static ngx_int_t | |
2567 ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
2568 { | |
2569 u_char *atom_header, *atom_table, *atom_end; | |
2570 size_t atom_size; | |
2571 uint32_t entries, size; | |
2572 ngx_buf_t *atom, *data; | |
2573 ngx_mp4_stsz_atom_t *stsz_atom; | |
2574 ngx_http_mp4_trak_t *trak; | |
2575 | |
2576 /* sample sizes atom */ | |
2577 | |
2578 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stsz atom"); | |
2579 | |
2580 atom_header = ngx_mp4_atom_header(mp4); | |
2581 stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header; | |
2582 ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z'); | |
2583 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2584 if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2585 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2586 "\"%s\" mp4 stsz atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2587 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2588 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2589 |
4085 | 2590 size = ngx_mp4_get_32value(stsz_atom->uniform_size); |
2591 entries = ngx_mp4_get_32value(stsz_atom->entries); | |
2592 | |
2593 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2594 "sample uniform size:%uD, entries:%uD", size, entries); | |
2595 | |
2596 trak = ngx_mp4_last_trak(mp4); | |
2597 trak->sample_sizes_entries = entries; | |
2598 | |
2599 atom_table = atom_header + sizeof(ngx_mp4_stsz_atom_t); | |
2600 | |
2601 atom = &trak->stsz_atom_buf; | |
2602 atom->temporary = 1; | |
2603 atom->pos = atom_header; | |
2604 atom->last = atom_table; | |
2605 | |
2606 trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom; | |
2607 | |
2608 if (size == 0) { | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2609 if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2610 + entries * sizeof(uint32_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2611 { |
4085 | 2612 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2613 "\"%s\" mp4 stsz atom too small", |
4085 | 2614 mp4->file.name.data); |
2615 return NGX_ERROR; | |
2616 } | |
2617 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2618 atom_end = atom_table + entries * sizeof(uint32_t); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2619 |
4085 | 2620 data = &trak->stsz_data_buf; |
2621 data->temporary = 1; | |
2622 data->pos = atom_table; | |
2623 data->last = atom_end; | |
2624 | |
2625 trak->out[NGX_HTTP_MP4_STSZ_DATA].buf = data; | |
2626 | |
2627 } else { | |
2628 /* if size != 0 then all samples are the same size */ | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2629 /* TODO : chunk samples */ |
4085 | 2630 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; |
2631 ngx_mp4_set_32value(atom_header, atom_size); | |
2632 trak->size += atom_size; | |
2633 } | |
2634 | |
2635 ngx_mp4_atom_next(mp4, atom_data_size); | |
2636 | |
2637 return NGX_OK; | |
2638 } | |
2639 | |
2640 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2641 static ngx_int_t |
4085 | 2642 ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, |
2643 ngx_http_mp4_trak_t *trak) | |
2644 { | |
2645 size_t atom_size; | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2646 uint32_t *pos, *end; |
4085 | 2647 ngx_buf_t *atom, *data; |
2648 ngx_mp4_stsz_atom_t *stsz_atom; | |
2649 | |
2650 /* | |
2651 * mdia.minf.stbl.stsz updating requires trak->start_sample | |
2652 * from mdia.minf.stbl.stts which depends on value from mdia.mdhd | |
2653 * atom which may reside after mdia.minf | |
2654 */ | |
2655 | |
2656 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2657 "mp4 stsz atom update"); | |
2658 | |
2659 data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf; | |
2660 | |
2661 if (data) { | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2662 if (trak->start_sample > trak->sample_sizes_entries) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2663 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2664 "start time is out mp4 stsz samples in \"%s\"", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2665 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2666 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2667 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2668 |
4085 | 2669 data->pos += trak->start_sample * sizeof(uint32_t); |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2670 end = (uint32_t *) data->pos; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2671 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2672 for (pos = end - trak->chunk_samples; pos < end; pos++) { |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2673 trak->chunk_samples_size += ngx_mp4_get_32value(pos); |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2674 } |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2675 |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2676 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
4112 | 2677 "chunk samples sizes:%uL", trak->chunk_samples_size); |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2678 |
4085 | 2679 atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos); |
2680 trak->size += atom_size; | |
2681 | |
2682 atom = trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf; | |
2683 stsz_atom = (ngx_mp4_stsz_atom_t *) atom->pos; | |
2684 | |
2685 ngx_mp4_set_32value(stsz_atom->size, atom_size); | |
2686 ngx_mp4_set_32value(stsz_atom->entries, | |
2687 trak->sample_sizes_entries - trak->start_sample); | |
2688 } | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2689 |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2690 return NGX_OK; |
4085 | 2691 } |
2692 | |
2693 | |
2694 typedef struct { | |
2695 u_char size[4]; | |
2696 u_char name[4]; | |
2697 u_char version[1]; | |
2698 u_char flags[3]; | |
2699 u_char entries[4]; | |
2700 } ngx_mp4_stco_atom_t; | |
2701 | |
2702 | |
2703 static ngx_int_t | |
2704 ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
2705 { | |
2706 u_char *atom_header, *atom_table, *atom_end; | |
2707 uint32_t entries; | |
2708 ngx_buf_t *atom, *data; | |
2709 ngx_mp4_stco_atom_t *stco_atom; | |
2710 ngx_http_mp4_trak_t *trak; | |
2711 | |
2712 /* chunk offsets atom */ | |
2713 | |
2714 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stco atom"); | |
2715 | |
2716 atom_header = ngx_mp4_atom_header(mp4); | |
2717 stco_atom = (ngx_mp4_stco_atom_t *) atom_header; | |
2718 ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o'); | |
2719 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2720 if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2721 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2722 "\"%s\" mp4 stco atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2723 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2724 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2725 |
4085 | 2726 entries = ngx_mp4_get_32value(stco_atom->entries); |
2727 | |
2728 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); | |
2729 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2730 if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2731 + entries * sizeof(uint32_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2732 { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2733 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2734 "\"%s\" mp4 stco atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2735 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2736 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2737 |
4085 | 2738 atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t); |
2739 atom_end = atom_table + entries * sizeof(uint32_t); | |
2740 | |
2741 trak = ngx_mp4_last_trak(mp4); | |
2742 trak->chunks = entries; | |
2743 | |
4107 | 2744 atom = &trak->stco_atom_buf; |
4085 | 2745 atom->temporary = 1; |
2746 atom->pos = atom_header; | |
2747 atom->last = atom_table; | |
2748 | |
4107 | 2749 data = &trak->stco_data_buf; |
4085 | 2750 data->temporary = 1; |
2751 data->pos = atom_table; | |
2752 data->last = atom_end; | |
2753 | |
2754 trak->out[NGX_HTTP_MP4_STCO_ATOM].buf = atom; | |
2755 trak->out[NGX_HTTP_MP4_STCO_DATA].buf = data; | |
2756 | |
2757 ngx_mp4_atom_next(mp4, atom_data_size); | |
2758 | |
2759 return NGX_OK; | |
2760 } | |
2761 | |
2762 | |
2763 static ngx_int_t | |
2764 ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4, | |
2765 ngx_http_mp4_trak_t *trak) | |
2766 { | |
2767 size_t atom_size; | |
2768 ngx_buf_t *atom, *data; | |
2769 ngx_mp4_stco_atom_t *stco_atom; | |
2770 | |
2771 /* | |
2772 * mdia.minf.stbl.stco updating requires trak->start_chunk | |
2773 * from mdia.minf.stbl.stsc which depends on value from mdia.mdhd | |
2774 * atom which may reside after mdia.minf | |
2775 */ | |
2776 | |
2777 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2778 "mp4 stco atom update"); | |
2779 | |
2780 data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf; | |
2781 | |
2782 if (data == NULL) { | |
2783 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2784 "no mp4 stco atoms were found in \"%s\"", | |
2785 mp4->file.name.data); | |
2786 return NGX_ERROR; | |
2787 } | |
2788 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2789 if (trak->start_chunk > trak->chunks) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2790 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2791 "start time is out mp4 stco chunks in \"%s\"", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2792 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2793 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2794 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2795 |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2796 data->pos += trak->start_chunk * sizeof(uint32_t); |
4085 | 2797 atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos); |
2798 trak->size += atom_size; | |
2799 | |
2800 trak->start_offset = ngx_mp4_get_32value(data->pos); | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2801 trak->start_offset += trak->chunk_samples_size; |
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2802 ngx_mp4_set_32value(data->pos, trak->start_offset); |
4085 | 2803 |
2804 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2805 "start chunk offset:%uD", trak->start_offset); | |
2806 | |
2807 atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf; | |
2808 stco_atom = (ngx_mp4_stco_atom_t *) atom->pos; | |
2809 | |
2810 ngx_mp4_set_32value(stco_atom->size, atom_size); | |
4098
a3e07fab98a3
Fix of case when start sample does not reside on chunk boundary.
Igor Sysoev <igor@sysoev.ru>
parents:
4096
diff
changeset
|
2811 ngx_mp4_set_32value(stco_atom->entries, trak->chunks - trak->start_chunk); |
4085 | 2812 |
2813 return NGX_OK; | |
2814 } | |
2815 | |
2816 | |
2817 static void | |
2818 ngx_http_mp4_adjust_stco_atom(ngx_http_mp4_file_t *mp4, | |
2819 ngx_http_mp4_trak_t *trak, int32_t adjustment) | |
2820 { | |
2821 uint32_t offset, *entry, *end; | |
2822 ngx_buf_t *data; | |
2823 | |
2824 /* | |
2825 * moov.trak.mdia.minf.stbl.stco adjustment requires | |
2826 * minimal start offset of all traks and new moov atom size | |
2827 */ | |
2828 | |
2829 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2830 "mp4 stco atom adjustment"); | |
2831 | |
2832 data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf; | |
2833 entry = (uint32_t *) data->pos; | |
2834 end = (uint32_t *) data->last; | |
2835 | |
2836 while (entry < end) { | |
2837 offset = ngx_mp4_get_32value(entry); | |
2838 offset += adjustment; | |
2839 ngx_mp4_set_32value(entry, offset); | |
2840 entry++; | |
2841 } | |
2842 } | |
2843 | |
2844 | |
4112 | 2845 typedef struct { |
2846 u_char size[4]; | |
2847 u_char name[4]; | |
2848 u_char version[1]; | |
2849 u_char flags[3]; | |
2850 u_char entries[4]; | |
2851 } ngx_mp4_co64_atom_t; | |
2852 | |
2853 | |
2854 static ngx_int_t | |
2855 ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) | |
2856 { | |
2857 u_char *atom_header, *atom_table, *atom_end; | |
2858 uint32_t entries; | |
2859 ngx_buf_t *atom, *data; | |
2860 ngx_mp4_co64_atom_t *co64_atom; | |
2861 ngx_http_mp4_trak_t *trak; | |
2862 | |
2863 /* chunk offsets atom */ | |
2864 | |
2865 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 co64 atom"); | |
2866 | |
2867 atom_header = ngx_mp4_atom_header(mp4); | |
2868 co64_atom = (ngx_mp4_co64_atom_t *) atom_header; | |
2869 ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4'); | |
2870 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2871 if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) > atom_data_size) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2872 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2873 "\"%s\" mp4 co64 atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2874 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2875 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2876 |
4112 | 2877 entries = ngx_mp4_get_32value(co64_atom->entries); |
2878 | |
2879 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); | |
2880 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2881 if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2882 + entries * sizeof(uint64_t) > atom_data_size) |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2883 { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2884 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2885 "\"%s\" mp4 co64 atom too small", mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2886 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2887 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2888 |
4112 | 2889 atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t); |
2890 atom_end = atom_table + entries * sizeof(uint64_t); | |
2891 | |
2892 trak = ngx_mp4_last_trak(mp4); | |
2893 trak->chunks = entries; | |
2894 | |
2895 atom = &trak->co64_atom_buf; | |
2896 atom->temporary = 1; | |
2897 atom->pos = atom_header; | |
2898 atom->last = atom_table; | |
2899 | |
2900 data = &trak->co64_data_buf; | |
2901 data->temporary = 1; | |
2902 data->pos = atom_table; | |
2903 data->last = atom_end; | |
2904 | |
2905 trak->out[NGX_HTTP_MP4_CO64_ATOM].buf = atom; | |
2906 trak->out[NGX_HTTP_MP4_CO64_DATA].buf = data; | |
2907 | |
2908 ngx_mp4_atom_next(mp4, atom_data_size); | |
2909 | |
2910 return NGX_OK; | |
2911 } | |
2912 | |
2913 | |
2914 static ngx_int_t | |
2915 ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4, | |
2916 ngx_http_mp4_trak_t *trak) | |
2917 { | |
2918 size_t atom_size; | |
2919 ngx_buf_t *atom, *data; | |
2920 ngx_mp4_co64_atom_t *co64_atom; | |
2921 | |
2922 /* | |
2923 * mdia.minf.stbl.co64 updating requires trak->start_chunk | |
2924 * from mdia.minf.stbl.stsc which depends on value from mdia.mdhd | |
2925 * atom which may reside after mdia.minf | |
2926 */ | |
2927 | |
2928 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2929 "mp4 co64 atom update"); | |
2930 | |
2931 data = trak->out[NGX_HTTP_MP4_CO64_DATA].buf; | |
2932 | |
2933 if (data == NULL) { | |
2934 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2935 "no mp4 co64 atoms were found in \"%s\"", | |
2936 mp4->file.name.data); | |
2937 return NGX_ERROR; | |
2938 } | |
2939 | |
4585
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2940 if (trak->start_chunk > trak->chunks) { |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2941 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2942 "start time is out mp4 co64 chunks in \"%s\"", |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2943 mp4->file.name.data); |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2944 return NGX_ERROR; |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2945 } |
3f874d645f45
Mp4: sanity checks cleanup.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4579
diff
changeset
|
2946 |
4112 | 2947 data->pos += trak->start_chunk * sizeof(uint64_t); |
2948 atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos); | |
2949 trak->size += atom_size; | |
2950 | |
2951 trak->start_offset = ngx_mp4_get_64value(data->pos); | |
2952 trak->start_offset += trak->chunk_samples_size; | |
2953 ngx_mp4_set_64value(data->pos, trak->start_offset); | |
2954 | |
2955 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2956 "start chunk offset:%uL", trak->start_offset); | |
2957 | |
2958 atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf; | |
2959 co64_atom = (ngx_mp4_co64_atom_t *) atom->pos; | |
2960 | |
2961 ngx_mp4_set_32value(co64_atom->size, atom_size); | |
2962 ngx_mp4_set_32value(co64_atom->entries, trak->chunks - trak->start_chunk); | |
2963 | |
2964 return NGX_OK; | |
2965 } | |
2966 | |
2967 | |
2968 static void | |
2969 ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4, | |
2970 ngx_http_mp4_trak_t *trak, off_t adjustment) | |
2971 { | |
2972 uint64_t offset, *entry, *end; | |
2973 ngx_buf_t *data; | |
2974 | |
2975 /* | |
2976 * moov.trak.mdia.minf.stbl.co64 adjustment requires | |
2977 * minimal start offset of all traks and new moov atom size | |
2978 */ | |
2979 | |
2980 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | |
2981 "mp4 co64 atom adjustment"); | |
2982 | |
2983 data = trak->out[NGX_HTTP_MP4_CO64_DATA].buf; | |
2984 entry = (uint64_t *) data->pos; | |
2985 end = (uint64_t *) data->last; | |
2986 | |
2987 while (entry < end) { | |
2988 offset = ngx_mp4_get_64value(entry); | |
2989 offset += adjustment; | |
2990 ngx_mp4_set_64value(entry, offset); | |
2991 entry++; | |
2992 } | |
2993 } | |
2994 | |
2995 | |
4085 | 2996 static char * |
2997 ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
2998 { | |
2999 ngx_http_core_loc_conf_t *clcf; | |
3000 | |
3001 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
3002 clcf->handler = ngx_http_mp4_handler; | |
3003 | |
3004 return NGX_CONF_OK; | |
3005 } | |
3006 | |
3007 | |
3008 static void * | |
3009 ngx_http_mp4_create_conf(ngx_conf_t *cf) | |
3010 { | |
3011 ngx_http_mp4_conf_t *conf; | |
3012 | |
3013 conf = ngx_palloc(cf->pool, sizeof(ngx_http_mp4_conf_t)); | |
3014 if (conf == NULL) { | |
3015 return NULL; | |
3016 } | |
3017 | |
3018 conf->buffer_size = NGX_CONF_UNSET_SIZE; | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
3019 conf->max_buffer_size = NGX_CONF_UNSET_SIZE; |
4085 | 3020 |
3021 return conf; | |
3022 } | |
3023 | |
3024 | |
3025 static char * | |
3026 ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
3027 { | |
3028 ngx_http_mp4_conf_t *prev = parent; | |
3029 ngx_http_mp4_conf_t *conf = child; | |
3030 | |
3031 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024); | |
4089
e27670e1ab70
mp4_max_moov_size directive has been renamed to mp4_max_buffer_size.
Igor Sysoev <igor@sysoev.ru>
parents:
4088
diff
changeset
|
3032 ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size, |
4085 | 3033 10 * 1024 * 1024); |
3034 | |
3035 return NGX_CONF_OK; | |
3036 } |