comparison src/http/modules/ngx_http_mp4_module.c @ 7945:f17ba8ecaaf0

Mp4: mp4_start_key_frame directive. The directive enables including all frames from start time to the most recent key frame in the result. Those frames are removed from presentation timeline using mp4 edit lists. Edit lists are currently supported by popular players and browsers such as Chrome, Safari, QuickTime and ffmpeg. Among those not supporting them properly is Firefox[1]. Based on a patch by Tracey Jaquith, Internet Archive. [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1735300
author Roman Arutyunyan <arut@nginx.com>
date Thu, 28 Oct 2021 14:14:25 +0300
parents 24f7904dbfa0
children 1afd19dc7161 adae1da17749
comparison
equal deleted inserted replaced
7944:24f7904dbfa0 7945:f17ba8ecaaf0
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11 11
12 #define NGX_HTTP_MP4_TRAK_ATOM 0 12 #define NGX_HTTP_MP4_TRAK_ATOM 0
13 #define NGX_HTTP_MP4_TKHD_ATOM 1 13 #define NGX_HTTP_MP4_TKHD_ATOM 1
14 #define NGX_HTTP_MP4_MDIA_ATOM 2 14 #define NGX_HTTP_MP4_EDTS_ATOM 2
15 #define NGX_HTTP_MP4_MDHD_ATOM 3 15 #define NGX_HTTP_MP4_ELST_ATOM 3
16 #define NGX_HTTP_MP4_HDLR_ATOM 4 16 #define NGX_HTTP_MP4_MDIA_ATOM 4
17 #define NGX_HTTP_MP4_MINF_ATOM 5 17 #define NGX_HTTP_MP4_MDHD_ATOM 5
18 #define NGX_HTTP_MP4_VMHD_ATOM 6 18 #define NGX_HTTP_MP4_HDLR_ATOM 6
19 #define NGX_HTTP_MP4_SMHD_ATOM 7 19 #define NGX_HTTP_MP4_MINF_ATOM 7
20 #define NGX_HTTP_MP4_DINF_ATOM 8 20 #define NGX_HTTP_MP4_VMHD_ATOM 8
21 #define NGX_HTTP_MP4_STBL_ATOM 9 21 #define NGX_HTTP_MP4_SMHD_ATOM 9
22 #define NGX_HTTP_MP4_STSD_ATOM 10 22 #define NGX_HTTP_MP4_DINF_ATOM 10
23 #define NGX_HTTP_MP4_STTS_ATOM 11 23 #define NGX_HTTP_MP4_STBL_ATOM 11
24 #define NGX_HTTP_MP4_STTS_DATA 12 24 #define NGX_HTTP_MP4_STSD_ATOM 12
25 #define NGX_HTTP_MP4_STSS_ATOM 13 25 #define NGX_HTTP_MP4_STTS_ATOM 13
26 #define NGX_HTTP_MP4_STSS_DATA 14 26 #define NGX_HTTP_MP4_STTS_DATA 14
27 #define NGX_HTTP_MP4_CTTS_ATOM 15 27 #define NGX_HTTP_MP4_STSS_ATOM 15
28 #define NGX_HTTP_MP4_CTTS_DATA 16 28 #define NGX_HTTP_MP4_STSS_DATA 16
29 #define NGX_HTTP_MP4_STSC_ATOM 17 29 #define NGX_HTTP_MP4_CTTS_ATOM 17
30 #define NGX_HTTP_MP4_STSC_START 18 30 #define NGX_HTTP_MP4_CTTS_DATA 18
31 #define NGX_HTTP_MP4_STSC_DATA 19 31 #define NGX_HTTP_MP4_STSC_ATOM 19
32 #define NGX_HTTP_MP4_STSC_END 20 32 #define NGX_HTTP_MP4_STSC_START 20
33 #define NGX_HTTP_MP4_STSZ_ATOM 21 33 #define NGX_HTTP_MP4_STSC_DATA 21
34 #define NGX_HTTP_MP4_STSZ_DATA 22 34 #define NGX_HTTP_MP4_STSC_END 22
35 #define NGX_HTTP_MP4_STCO_ATOM 23 35 #define NGX_HTTP_MP4_STSZ_ATOM 23
36 #define NGX_HTTP_MP4_STCO_DATA 24 36 #define NGX_HTTP_MP4_STSZ_DATA 24
37 #define NGX_HTTP_MP4_CO64_ATOM 25 37 #define NGX_HTTP_MP4_STCO_ATOM 25
38 #define NGX_HTTP_MP4_CO64_DATA 26 38 #define NGX_HTTP_MP4_STCO_DATA 26
39 #define NGX_HTTP_MP4_CO64_ATOM 27
40 #define NGX_HTTP_MP4_CO64_DATA 28
39 41
40 #define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA 42 #define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
41 43
42 44
43 typedef struct { 45 typedef struct {
44 size_t buffer_size; 46 size_t buffer_size;
45 size_t max_buffer_size; 47 size_t max_buffer_size;
48 ngx_flag_t start_key_frame;
46 } ngx_http_mp4_conf_t; 49 } ngx_http_mp4_conf_t;
47 50
48 51
49 typedef struct { 52 typedef struct {
50 u_char chunk[4]; 53 u_char chunk[4];
51 u_char samples[4]; 54 u_char samples[4];
52 u_char id[4]; 55 u_char id[4];
53 } ngx_mp4_stsc_entry_t; 56 } ngx_mp4_stsc_entry_t;
57
58
59 typedef struct {
60 u_char size[4];
61 u_char name[4];
62 } ngx_mp4_edts_atom_t;
63
64
65 typedef struct {
66 u_char size[4];
67 u_char name[4];
68 u_char version[1];
69 u_char flags[3];
70 u_char entries[4];
71 u_char duration[8];
72 u_char media_time[8];
73 u_char media_rate[2];
74 u_char reserved[2];
75 } ngx_mp4_elst_atom_t;
54 76
55 77
56 typedef struct { 78 typedef struct {
57 uint32_t timescale; 79 uint32_t timescale;
58 uint32_t time_to_sample_entries; 80 uint32_t time_to_sample_entries;
69 ngx_uint_t start_chunk_samples; 91 ngx_uint_t start_chunk_samples;
70 ngx_uint_t end_chunk_samples; 92 ngx_uint_t end_chunk_samples;
71 uint64_t start_chunk_samples_size; 93 uint64_t start_chunk_samples_size;
72 uint64_t end_chunk_samples_size; 94 uint64_t end_chunk_samples_size;
73 uint64_t duration; 95 uint64_t duration;
96 uint64_t prefix;
97 uint64_t movie_duration;
74 off_t start_offset; 98 off_t start_offset;
75 off_t end_offset; 99 off_t end_offset;
76 100
77 size_t tkhd_size; 101 size_t tkhd_size;
78 size_t mdhd_size; 102 size_t mdhd_size;
84 108
85 ngx_chain_t out[NGX_HTTP_MP4_LAST_ATOM + 1]; 109 ngx_chain_t out[NGX_HTTP_MP4_LAST_ATOM + 1];
86 110
87 ngx_buf_t trak_atom_buf; 111 ngx_buf_t trak_atom_buf;
88 ngx_buf_t tkhd_atom_buf; 112 ngx_buf_t tkhd_atom_buf;
113 ngx_buf_t edts_atom_buf;
114 ngx_buf_t elst_atom_buf;
89 ngx_buf_t mdia_atom_buf; 115 ngx_buf_t mdia_atom_buf;
90 ngx_buf_t mdhd_atom_buf; 116 ngx_buf_t mdhd_atom_buf;
91 ngx_buf_t hdlr_atom_buf; 117 ngx_buf_t hdlr_atom_buf;
92 ngx_buf_t minf_atom_buf; 118 ngx_buf_t minf_atom_buf;
93 ngx_buf_t vmhd_atom_buf; 119 ngx_buf_t vmhd_atom_buf;
110 ngx_buf_t stco_atom_buf; 136 ngx_buf_t stco_atom_buf;
111 ngx_buf_t stco_data_buf; 137 ngx_buf_t stco_data_buf;
112 ngx_buf_t co64_atom_buf; 138 ngx_buf_t co64_atom_buf;
113 ngx_buf_t co64_data_buf; 139 ngx_buf_t co64_data_buf;
114 140
141 ngx_mp4_edts_atom_t edts_atom;
142 ngx_mp4_elst_atom_t elst_atom;
115 ngx_mp4_stsc_entry_t stsc_start_chunk_entry; 143 ngx_mp4_stsc_entry_t stsc_start_chunk_entry;
116 ngx_mp4_stsc_entry_t stsc_end_chunk_entry; 144 ngx_mp4_stsc_entry_t stsc_end_chunk_entry;
117 } ngx_http_mp4_trak_t; 145 } ngx_http_mp4_trak_t;
118 146
119 147
184 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \ 212 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \
185 ((u_char *) (p))[4] = n1; \ 213 ((u_char *) (p))[4] = n1; \
186 ((u_char *) (p))[5] = n2; \ 214 ((u_char *) (p))[5] = n2; \
187 ((u_char *) (p))[6] = n3; \ 215 ((u_char *) (p))[6] = n3; \
188 ((u_char *) (p))[7] = n4 216 ((u_char *) (p))[7] = n4
217
218 #define ngx_mp4_get_16value(p) \
219 ( ((uint16_t) ((u_char *) (p))[0] << 8) \
220 + ( ((u_char *) (p))[1]) )
221
222 #define ngx_mp4_set_16value(p, n) \
223 ((u_char *) (p))[0] = (u_char) ((n) >> 8); \
224 ((u_char *) (p))[1] = (u_char) (n)
189 225
190 #define ngx_mp4_get_32value(p) \ 226 #define ngx_mp4_get_32value(p) \
191 ( ((uint32_t) ((u_char *) (p))[0] << 24) \ 227 ( ((uint32_t) ((u_char *) (p))[0] << 24) \
192 + ( ((u_char *) (p))[1] << 16) \ 228 + ( ((u_char *) (p))[1] << 16) \
193 + ( ((u_char *) (p))[2] << 8) \ 229 + ( ((u_char *) (p))[2] << 8) \
268 uint64_t atom_data_size); 304 uint64_t atom_data_size);
269 static ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4, 305 static ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4,
270 uint64_t atom_data_size); 306 uint64_t atom_data_size);
271 static ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, 307 static ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4,
272 uint64_t atom_data_size); 308 uint64_t atom_data_size);
309 static void ngx_http_mp4_update_edts_atom(ngx_http_mp4_file_t *mp4,
310 ngx_http_mp4_trak_t *trak);
273 static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4, 311 static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
274 ngx_http_mp4_trak_t *trak); 312 ngx_http_mp4_trak_t *trak);
275 static ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, 313 static ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4,
276 uint64_t atom_data_size); 314 uint64_t atom_data_size);
277 static ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, 315 static ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4,
278 uint64_t atom_data_size); 316 uint64_t atom_data_size);
279 static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4, 317 static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
280 ngx_http_mp4_trak_t *trak); 318 ngx_http_mp4_trak_t *trak);
281 static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4, 319 static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
282 ngx_http_mp4_trak_t *trak, ngx_uint_t start); 320 ngx_http_mp4_trak_t *trak, ngx_uint_t start);
321 static uint32_t ngx_http_mp4_seek_key_frame(ngx_http_mp4_file_t *mp4,
322 ngx_http_mp4_trak_t *trak, uint32_t start_sample);
283 static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, 323 static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
284 uint64_t atom_data_size); 324 uint64_t atom_data_size);
285 static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4, 325 static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
286 ngx_http_mp4_trak_t *trak); 326 ngx_http_mp4_trak_t *trak);
287 static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4, 327 static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
341 ngx_conf_set_size_slot, 381 ngx_conf_set_size_slot,
342 NGX_HTTP_LOC_CONF_OFFSET, 382 NGX_HTTP_LOC_CONF_OFFSET,
343 offsetof(ngx_http_mp4_conf_t, max_buffer_size), 383 offsetof(ngx_http_mp4_conf_t, max_buffer_size),
344 NULL }, 384 NULL },
345 385
386 { ngx_string("mp4_start_key_frame"),
387 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
388 ngx_conf_set_flag_slot,
389 NGX_HTTP_LOC_CONF_OFFSET,
390 offsetof(ngx_http_mp4_conf_t, start_key_frame),
391 NULL },
392
346 ngx_null_command 393 ngx_null_command
347 }; 394 };
348 395
349 396
350 static ngx_http_module_t ngx_http_mp4_module_ctx = { 397 static ngx_http_module_t ngx_http_mp4_module_ctx = {
827 ngx_http_mp4_update_minf_atom(mp4, &trak[i]); 874 ngx_http_mp4_update_minf_atom(mp4, &trak[i]);
828 ngx_http_mp4_update_mdhd_atom(mp4, &trak[i]); 875 ngx_http_mp4_update_mdhd_atom(mp4, &trak[i]);
829 trak[i].size += trak[i].hdlr_size; 876 trak[i].size += trak[i].hdlr_size;
830 ngx_http_mp4_update_mdia_atom(mp4, &trak[i]); 877 ngx_http_mp4_update_mdia_atom(mp4, &trak[i]);
831 trak[i].size += trak[i].tkhd_size; 878 trak[i].size += trak[i].tkhd_size;
879 ngx_http_mp4_update_edts_atom(mp4, &trak[i]);
832 ngx_http_mp4_update_trak_atom(mp4, &trak[i]); 880 ngx_http_mp4_update_trak_atom(mp4, &trak[i]);
833 881
834 mp4->moov_size += trak[i].size; 882 mp4->moov_size += trak[i].size;
835 883
836 if (start_offset > trak[i].start_offset) { 884 if (start_offset > trak[i].start_offset) {
1588 1636
1589 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; 1637 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
1590 1638
1591 trak = ngx_mp4_last_trak(mp4); 1639 trak = ngx_mp4_last_trak(mp4);
1592 trak->tkhd_size = atom_size; 1640 trak->tkhd_size = atom_size;
1641 trak->movie_duration = duration;
1593 1642
1594 ngx_mp4_set_32value(tkhd_atom->size, atom_size); 1643 ngx_mp4_set_32value(tkhd_atom->size, atom_size);
1595 1644
1596 if (tkhd_atom->version[0] == 0) { 1645 if (tkhd_atom->version[0] == 0) {
1597 ngx_mp4_set_32value(tkhd_atom->duration, duration); 1646 ngx_mp4_set_32value(tkhd_atom->duration, duration);
1984 return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_stbl_atoms, atom_data_size); 2033 return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_stbl_atoms, atom_data_size);
1985 } 2034 }
1986 2035
1987 2036
1988 static void 2037 static void
2038 ngx_http_mp4_update_edts_atom(ngx_http_mp4_file_t *mp4,
2039 ngx_http_mp4_trak_t *trak)
2040 {
2041 ngx_buf_t *atom;
2042 ngx_mp4_elst_atom_t *elst_atom;
2043 ngx_mp4_edts_atom_t *edts_atom;
2044
2045 if (trak->prefix == 0) {
2046 return;
2047 }
2048
2049 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2050 "mp4 edts atom update prefix:%uL", trak->prefix);
2051
2052 edts_atom = &trak->edts_atom;
2053 ngx_mp4_set_32value(edts_atom->size, sizeof(ngx_mp4_edts_atom_t)
2054 + sizeof(ngx_mp4_elst_atom_t));
2055 ngx_mp4_set_atom_name(edts_atom, 'e', 'd', 't', 's');
2056
2057 atom = &trak->edts_atom_buf;
2058 atom->temporary = 1;
2059 atom->pos = (u_char *) edts_atom;
2060 atom->last = (u_char *) edts_atom + sizeof(ngx_mp4_edts_atom_t);
2061
2062 trak->out[NGX_HTTP_MP4_EDTS_ATOM].buf = atom;
2063
2064 elst_atom = &trak->elst_atom;
2065 ngx_mp4_set_32value(elst_atom->size, sizeof(ngx_mp4_elst_atom_t));
2066 ngx_mp4_set_atom_name(elst_atom, 'e', 'l', 's', 't');
2067
2068 elst_atom->version[0] = 1;
2069 elst_atom->flags[0] = 0;
2070 elst_atom->flags[1] = 0;
2071 elst_atom->flags[2] = 0;
2072
2073 ngx_mp4_set_32value(elst_atom->entries, 1);
2074 ngx_mp4_set_64value(elst_atom->duration, trak->movie_duration);
2075 ngx_mp4_set_64value(elst_atom->media_time, trak->prefix);
2076 ngx_mp4_set_16value(elst_atom->media_rate, 1);
2077 ngx_mp4_set_16value(elst_atom->reserved, 0);
2078
2079 atom = &trak->elst_atom_buf;
2080 atom->temporary = 1;
2081 atom->pos = (u_char *) elst_atom;
2082 atom->last = (u_char *) elst_atom + sizeof(ngx_mp4_elst_atom_t);
2083
2084 trak->out[NGX_HTTP_MP4_ELST_ATOM].buf = atom;
2085
2086 trak->size += sizeof(ngx_mp4_edts_atom_t) + sizeof(ngx_mp4_elst_atom_t);
2087 }
2088
2089
2090 static void
1989 ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4, 2091 ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
1990 ngx_http_mp4_trak_t *trak) 2092 ngx_http_mp4_trak_t *trak)
1991 { 2093 {
1992 ngx_buf_t *atom; 2094 ngx_buf_t *atom;
1993 2095
2181 2283
2182 static ngx_int_t 2284 static ngx_int_t
2183 ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4, 2285 ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
2184 ngx_http_mp4_trak_t *trak, ngx_uint_t start) 2286 ngx_http_mp4_trak_t *trak, ngx_uint_t start)
2185 { 2287 {
2186 uint32_t count, duration, rest; 2288 uint32_t count, duration, rest, key_prefix;
2187 uint64_t start_time; 2289 uint64_t start_time;
2188 ngx_buf_t *data; 2290 ngx_buf_t *data;
2189 ngx_uint_t start_sample, entries, start_sec; 2291 ngx_uint_t start_sample, entries, start_sec;
2190 ngx_mp4_stts_entry_t *entry, *end; 2292 ngx_mp4_stts_entry_t *entry, *end;
2191 2293
2205 return NGX_OK; 2307 return NGX_OK;
2206 } 2308 }
2207 2309
2208 data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf; 2310 data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
2209 2311
2210 start_time = (uint64_t) start_sec * trak->timescale / 1000; 2312 start_time = (uint64_t) start_sec * trak->timescale / 1000 + trak->prefix;
2211 2313
2212 entries = trak->time_to_sample_entries; 2314 entries = trak->time_to_sample_entries;
2213 start_sample = 0; 2315 start_sample = 0;
2214 entry = (ngx_mp4_stts_entry_t *) data->pos; 2316 entry = (ngx_mp4_stts_entry_t *) data->pos;
2215 end = (ngx_mp4_stts_entry_t *) data->last; 2317 end = (ngx_mp4_stts_entry_t *) data->last;
2251 } 2353 }
2252 2354
2253 found: 2355 found:
2254 2356
2255 if (start) { 2357 if (start) {
2358 key_prefix = ngx_http_mp4_seek_key_frame(mp4, trak, start_sample);
2359
2360 start_sample -= key_prefix;
2361
2362 while (rest < key_prefix) {
2363 trak->prefix += rest * duration;
2364 key_prefix -= rest;
2365
2366 entry--;
2367 entries++;
2368
2369 count = ngx_mp4_get_32value(entry->count);
2370 duration = ngx_mp4_get_32value(entry->duration);
2371 rest = count;
2372 }
2373
2374 trak->prefix += key_prefix * duration;
2375 trak->duration += trak->prefix;
2376 rest -= key_prefix;
2377
2256 ngx_mp4_set_32value(entry->count, count - rest); 2378 ngx_mp4_set_32value(entry->count, count - rest);
2257 data->pos = (u_char *) entry; 2379 data->pos = (u_char *) entry;
2258 trak->time_to_sample_entries = entries; 2380 trak->time_to_sample_entries = entries;
2259 trak->start_sample = start_sample; 2381 trak->start_sample = start_sample;
2260 2382
2272 "end_sample:%ui, new count:%uD", 2394 "end_sample:%ui, new count:%uD",
2273 trak->end_sample, rest); 2395 trak->end_sample, rest);
2274 } 2396 }
2275 2397
2276 return NGX_OK; 2398 return NGX_OK;
2399 }
2400
2401
2402 static uint32_t
2403 ngx_http_mp4_seek_key_frame(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak,
2404 uint32_t start_sample)
2405 {
2406 uint32_t key_prefix, sample, *entry, *end;
2407 ngx_buf_t *data;
2408 ngx_http_mp4_conf_t *conf;
2409
2410 conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
2411 if (!conf->start_key_frame) {
2412 return 0;
2413 }
2414
2415 data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
2416 if (data == NULL) {
2417 return 0;
2418 }
2419
2420 entry = (uint32_t *) data->pos;
2421 end = (uint32_t *) data->last;
2422
2423 /* sync samples starts from 1 */
2424 start_sample++;
2425
2426 key_prefix = 0;
2427
2428 while (entry < end) {
2429 sample = ngx_mp4_get_32value(entry);
2430 if (sample > start_sample) {
2431 break;
2432 }
2433
2434 key_prefix = start_sample - sample;
2435 entry++;
2436 }
2437
2438 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2439 "mp4 key frame prefix:%uD", key_prefix);
2440
2441 return key_prefix;
2277 } 2442 }
2278 2443
2279 2444
2280 typedef struct { 2445 typedef struct {
2281 u_char size[4]; 2446 u_char size[4];
3612 return NULL; 3777 return NULL;
3613 } 3778 }
3614 3779
3615 conf->buffer_size = NGX_CONF_UNSET_SIZE; 3780 conf->buffer_size = NGX_CONF_UNSET_SIZE;
3616 conf->max_buffer_size = NGX_CONF_UNSET_SIZE; 3781 conf->max_buffer_size = NGX_CONF_UNSET_SIZE;
3782 conf->start_key_frame = NGX_CONF_UNSET;
3617 3783
3618 return conf; 3784 return conf;
3619 } 3785 }
3620 3786
3621 3787
3626 ngx_http_mp4_conf_t *conf = child; 3792 ngx_http_mp4_conf_t *conf = child;
3627 3793
3628 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024); 3794 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024);
3629 ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size, 3795 ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size,
3630 10 * 1024 * 1024); 3796 10 * 1024 * 1024);
3797 ngx_conf_merge_value(conf->start_key_frame, prev->start_key_frame, 0);
3631 3798
3632 return NGX_CONF_OK; 3799 return NGX_CONF_OK;
3633 } 3800 }