1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev#include <ngx_config.h>
8e18a033bSKonstantin Ananyev#include <ngx_core.h>
9e18a033bSKonstantin Ananyev#include <ngx_http.h>
10e18a033bSKonstantin Ananyev
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_TRAK_ATOM     0
13e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_TKHD_ATOM     1
14e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_MDIA_ATOM     2
15e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_MDHD_ATOM     3
16e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_HDLR_ATOM     4
17e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_MINF_ATOM     5
18e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_VMHD_ATOM     6
19e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_SMHD_ATOM     7
20e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_DINF_ATOM     8
21e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STBL_ATOM     9
22e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSD_ATOM    10
23e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STTS_ATOM    11
24e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STTS_DATA    12
25e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSS_ATOM    13
26e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSS_DATA    14
27e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_CTTS_ATOM    15
28e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_CTTS_DATA    16
29e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSC_ATOM    17
30e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSC_START   18
31e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSC_DATA    19
32e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSC_END     20
33e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSZ_ATOM    21
34e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STSZ_DATA    22
35e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STCO_ATOM    23
36e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_STCO_DATA    24
37e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_CO64_ATOM    25
38e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_CO64_DATA    26
39e18a033bSKonstantin Ananyev
40e18a033bSKonstantin Ananyev#define NGX_HTTP_MP4_LAST_ATOM    NGX_HTTP_MP4_CO64_DATA
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyev
43e18a033bSKonstantin Ananyevtypedef struct {
44e18a033bSKonstantin Ananyev    size_t                buffer_size;
45e18a033bSKonstantin Ananyev    size_t                max_buffer_size;
46e18a033bSKonstantin Ananyev} ngx_http_mp4_conf_t;
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev
49e18a033bSKonstantin Ananyevtypedef struct {
50e18a033bSKonstantin Ananyev    u_char                chunk[4];
51e18a033bSKonstantin Ananyev    u_char                samples[4];
52e18a033bSKonstantin Ananyev    u_char                id[4];
53e18a033bSKonstantin Ananyev} ngx_mp4_stsc_entry_t;
54e18a033bSKonstantin Ananyev
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyevtypedef struct {
57e18a033bSKonstantin Ananyev    uint32_t              timescale;
58e18a033bSKonstantin Ananyev    uint32_t              time_to_sample_entries;
59e18a033bSKonstantin Ananyev    uint32_t              sample_to_chunk_entries;
60e18a033bSKonstantin Ananyev    uint32_t              sync_samples_entries;
61e18a033bSKonstantin Ananyev    uint32_t              composition_offset_entries;
62e18a033bSKonstantin Ananyev    uint32_t              sample_sizes_entries;
63e18a033bSKonstantin Ananyev    uint32_t              chunks;
64e18a033bSKonstantin Ananyev
65e18a033bSKonstantin Ananyev    ngx_uint_t            start_sample;
66e18a033bSKonstantin Ananyev    ngx_uint_t            end_sample;
67e18a033bSKonstantin Ananyev    ngx_uint_t            start_chunk;
68e18a033bSKonstantin Ananyev    ngx_uint_t            end_chunk;
69e18a033bSKonstantin Ananyev    ngx_uint_t            start_chunk_samples;
70e18a033bSKonstantin Ananyev    ngx_uint_t            end_chunk_samples;
71e18a033bSKonstantin Ananyev    uint64_t              start_chunk_samples_size;
72e18a033bSKonstantin Ananyev    uint64_t              end_chunk_samples_size;
73e18a033bSKonstantin Ananyev    off_t                 start_offset;
74e18a033bSKonstantin Ananyev    off_t                 end_offset;
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev    size_t                tkhd_size;
77e18a033bSKonstantin Ananyev    size_t                mdhd_size;
78e18a033bSKonstantin Ananyev    size_t                hdlr_size;
79e18a033bSKonstantin Ananyev    size_t                vmhd_size;
80e18a033bSKonstantin Ananyev    size_t                smhd_size;
81e18a033bSKonstantin Ananyev    size_t                dinf_size;
82e18a033bSKonstantin Ananyev    size_t                size;
83e18a033bSKonstantin Ananyev
84e18a033bSKonstantin Ananyev    ngx_chain_t           out[NGX_HTTP_MP4_LAST_ATOM + 1];
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev    ngx_buf_t             trak_atom_buf;
87e18a033bSKonstantin Ananyev    ngx_buf_t             tkhd_atom_buf;
88e18a033bSKonstantin Ananyev    ngx_buf_t             mdia_atom_buf;
89e18a033bSKonstantin Ananyev    ngx_buf_t             mdhd_atom_buf;
90e18a033bSKonstantin Ananyev    ngx_buf_t             hdlr_atom_buf;
91e18a033bSKonstantin Ananyev    ngx_buf_t             minf_atom_buf;
92e18a033bSKonstantin Ananyev    ngx_buf_t             vmhd_atom_buf;
93e18a033bSKonstantin Ananyev    ngx_buf_t             smhd_atom_buf;
94e18a033bSKonstantin Ananyev    ngx_buf_t             dinf_atom_buf;
95e18a033bSKonstantin Ananyev    ngx_buf_t             stbl_atom_buf;
96e18a033bSKonstantin Ananyev    ngx_buf_t             stsd_atom_buf;
97e18a033bSKonstantin Ananyev    ngx_buf_t             stts_atom_buf;
98e18a033bSKonstantin Ananyev    ngx_buf_t             stts_data_buf;
99e18a033bSKonstantin Ananyev    ngx_buf_t             stss_atom_buf;
100e18a033bSKonstantin Ananyev    ngx_buf_t             stss_data_buf;
101e18a033bSKonstantin Ananyev    ngx_buf_t             ctts_atom_buf;
102e18a033bSKonstantin Ananyev    ngx_buf_t             ctts_data_buf;
103e18a033bSKonstantin Ananyev    ngx_buf_t             stsc_atom_buf;
104e18a033bSKonstantin Ananyev    ngx_buf_t             stsc_start_chunk_buf;
105e18a033bSKonstantin Ananyev    ngx_buf_t             stsc_end_chunk_buf;
106e18a033bSKonstantin Ananyev    ngx_buf_t             stsc_data_buf;
107e18a033bSKonstantin Ananyev    ngx_buf_t             stsz_atom_buf;
108e18a033bSKonstantin Ananyev    ngx_buf_t             stsz_data_buf;
109e18a033bSKonstantin Ananyev    ngx_buf_t             stco_atom_buf;
110e18a033bSKonstantin Ananyev    ngx_buf_t             stco_data_buf;
111e18a033bSKonstantin Ananyev    ngx_buf_t             co64_atom_buf;
112e18a033bSKonstantin Ananyev    ngx_buf_t             co64_data_buf;
113e18a033bSKonstantin Ananyev
114e18a033bSKonstantin Ananyev    ngx_mp4_stsc_entry_t  stsc_start_chunk_entry;
115e18a033bSKonstantin Ananyev    ngx_mp4_stsc_entry_t  stsc_end_chunk_entry;
116e18a033bSKonstantin Ananyev} ngx_http_mp4_trak_t;
117e18a033bSKonstantin Ananyev
118e18a033bSKonstantin Ananyev
119e18a033bSKonstantin Ananyevtypedef struct {
120e18a033bSKonstantin Ananyev    ngx_file_t            file;
121e18a033bSKonstantin Ananyev
122e18a033bSKonstantin Ananyev    u_char               *buffer;
123e18a033bSKonstantin Ananyev    u_char               *buffer_start;
124e18a033bSKonstantin Ananyev    u_char               *buffer_pos;
125e18a033bSKonstantin Ananyev    u_char               *buffer_end;
126e18a033bSKonstantin Ananyev    size_t                buffer_size;
127e18a033bSKonstantin Ananyev
128e18a033bSKonstantin Ananyev    off_t                 offset;
129e18a033bSKonstantin Ananyev    off_t                 end;
130e18a033bSKonstantin Ananyev    off_t                 content_length;
131e18a033bSKonstantin Ananyev    ngx_uint_t            start;
132e18a033bSKonstantin Ananyev    ngx_uint_t            length;
133e18a033bSKonstantin Ananyev    uint32_t              timescale;
134e18a033bSKonstantin Ananyev    ngx_http_request_t   *request;
135e18a033bSKonstantin Ananyev    ngx_array_t           trak;
136e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t   traks[2];
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev    size_t                ftyp_size;
139e18a033bSKonstantin Ananyev    size_t                moov_size;
140e18a033bSKonstantin Ananyev
141e18a033bSKonstantin Ananyev    ngx_chain_t          *out;
142e18a033bSKonstantin Ananyev    ngx_chain_t           ftyp_atom;
143e18a033bSKonstantin Ananyev    ngx_chain_t           moov_atom;
144e18a033bSKonstantin Ananyev    ngx_chain_t           mvhd_atom;
145e18a033bSKonstantin Ananyev    ngx_chain_t           mdat_atom;
146e18a033bSKonstantin Ananyev    ngx_chain_t           mdat_data;
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyev    ngx_buf_t             ftyp_atom_buf;
149e18a033bSKonstantin Ananyev    ngx_buf_t             moov_atom_buf;
150e18a033bSKonstantin Ananyev    ngx_buf_t             mvhd_atom_buf;
151e18a033bSKonstantin Ananyev    ngx_buf_t             mdat_atom_buf;
152e18a033bSKonstantin Ananyev    ngx_buf_t             mdat_data_buf;
153e18a033bSKonstantin Ananyev
154e18a033bSKonstantin Ananyev    u_char                moov_atom_header[8];
155e18a033bSKonstantin Ananyev    u_char                mdat_atom_header[16];
156e18a033bSKonstantin Ananyev} ngx_http_mp4_file_t;
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyevtypedef struct {
160e18a033bSKonstantin Ananyev    char                 *name;
161e18a033bSKonstantin Ananyev    ngx_int_t           (*handler)(ngx_http_mp4_file_t *mp4,
162e18a033bSKonstantin Ananyev                                   uint64_t atom_data_size);
163e18a033bSKonstantin Ananyev} ngx_http_mp4_atom_handler_t;
164e18a033bSKonstantin Ananyev
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev#define ngx_mp4_atom_header(mp4)   (mp4->buffer_pos - 8)
167e18a033bSKonstantin Ananyev#define ngx_mp4_atom_data(mp4)     mp4->buffer_pos
168e18a033bSKonstantin Ananyev#define ngx_mp4_atom_data_size(t)  (uint64_t) (sizeof(t) - 8)
169e18a033bSKonstantin Ananyev
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev#define ngx_mp4_atom_next(mp4, n)                                             \
172e18a033bSKonstantin Ananyev    mp4->buffer_pos += (size_t) n;                                            \
173e18a033bSKonstantin Ananyev    mp4->offset += n
174e18a033bSKonstantin Ananyev
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev#define ngx_mp4_set_atom_name(p, n1, n2, n3, n4)                              \
177e18a033bSKonstantin Ananyev    ((u_char *) (p))[4] = n1;                                                 \
178e18a033bSKonstantin Ananyev    ((u_char *) (p))[5] = n2;                                                 \
179e18a033bSKonstantin Ananyev    ((u_char *) (p))[6] = n3;                                                 \
180e18a033bSKonstantin Ananyev    ((u_char *) (p))[7] = n4
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev#define ngx_mp4_get_32value(p)                                                \
183e18a033bSKonstantin Ananyev    ( ((uint32_t) ((u_char *) (p))[0] << 24)                                  \
184e18a033bSKonstantin Ananyev    + (           ((u_char *) (p))[1] << 16)                                  \
185e18a033bSKonstantin Ananyev    + (           ((u_char *) (p))[2] << 8)                                   \
186e18a033bSKonstantin Ananyev    + (           ((u_char *) (p))[3]) )
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev#define ngx_mp4_set_32value(p, n)                                             \
189e18a033bSKonstantin Ananyev    ((u_char *) (p))[0] = (u_char) ((n) >> 24);                               \
190e18a033bSKonstantin Ananyev    ((u_char *) (p))[1] = (u_char) ((n) >> 16);                               \
191e18a033bSKonstantin Ananyev    ((u_char *) (p))[2] = (u_char) ((n) >> 8);                                \
192e18a033bSKonstantin Ananyev    ((u_char *) (p))[3] = (u_char)  (n)
193e18a033bSKonstantin Ananyev
194e18a033bSKonstantin Ananyev#define ngx_mp4_get_64value(p)                                                \
195e18a033bSKonstantin Ananyev    ( ((uint64_t) ((u_char *) (p))[0] << 56)                                  \
196e18a033bSKonstantin Ananyev    + ((uint64_t) ((u_char *) (p))[1] << 48)                                  \
197e18a033bSKonstantin Ananyev    + ((uint64_t) ((u_char *) (p))[2] << 40)                                  \
198e18a033bSKonstantin Ananyev    + ((uint64_t) ((u_char *) (p))[3] << 32)                                  \
199e18a033bSKonstantin Ananyev    + ((uint64_t) ((u_char *) (p))[4] << 24)                                  \
200e18a033bSKonstantin Ananyev    + (           ((u_char *) (p))[5] << 16)                                  \
201e18a033bSKonstantin Ananyev    + (           ((u_char *) (p))[6] << 8)                                   \
202e18a033bSKonstantin Ananyev    + (           ((u_char *) (p))[7]) )
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev#define ngx_mp4_set_64value(p, n)                                             \
205e18a033bSKonstantin Ananyev    ((u_char *) (p))[0] = (u_char) ((uint64_t) (n) >> 56);                    \
206e18a033bSKonstantin Ananyev    ((u_char *) (p))[1] = (u_char) ((uint64_t) (n) >> 48);                    \
207e18a033bSKonstantin Ananyev    ((u_char *) (p))[2] = (u_char) ((uint64_t) (n) >> 40);                    \
208e18a033bSKonstantin Ananyev    ((u_char *) (p))[3] = (u_char) ((uint64_t) (n) >> 32);                    \
209e18a033bSKonstantin Ananyev    ((u_char *) (p))[4] = (u_char) (           (n) >> 24);                    \
210e18a033bSKonstantin Ananyev    ((u_char *) (p))[5] = (u_char) (           (n) >> 16);                    \
211e18a033bSKonstantin Ananyev    ((u_char *) (p))[6] = (u_char) (           (n) >> 8);                     \
212e18a033bSKonstantin Ananyev    ((u_char *) (p))[7] = (u_char)             (n)
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev#define ngx_mp4_last_trak(mp4)                                                \
215e18a033bSKonstantin Ananyev    &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1]
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyev
218e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r);
219e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_atofp(u_char *line, size_t n, size_t point);
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
222e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
223e18a033bSKonstantin Ananyev    ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size);
224e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size);
225e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4,
226e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
227e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4,
228e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
229e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
230e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
231e18a033bSKonstantin Ananyevstatic size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
232e18a033bSKonstantin Ananyev    off_t start_offset, off_t end_offset);
233e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
234e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
235e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4,
236e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
237e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_update_trak_atom(ngx_http_mp4_file_t *mp4,
238e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
239e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_cmov_atom(ngx_http_mp4_file_t *mp4,
240e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
241e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4,
242e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
243e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_mdia_atom(ngx_http_mp4_file_t *mp4,
244e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
245e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4,
246e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
247e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4,
248e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
249e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4,
250e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
251e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4,
252e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
253e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_update_minf_atom(ngx_http_mp4_file_t *mp4,
254e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
255e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_dinf_atom(ngx_http_mp4_file_t *mp4,
256e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
257e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_vmhd_atom(ngx_http_mp4_file_t *mp4,
258e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
259e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4,
260e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
261e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4,
262e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
263e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
264e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
265e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4,
266e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
267e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4,
268e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
269e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
270e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
271e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
272e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
273e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
274e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
275e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
276e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
277e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
278e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
279e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
280e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
281e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
282e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
283e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
284e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
285e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
286e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
287e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
288e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
289e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
290e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak, ngx_uint_t start);
291e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
292e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
293e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
294e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
295e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4,
296e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
297e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
298e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
299e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_adjust_stco_atom(ngx_http_mp4_file_t *mp4,
300e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak, int32_t adjustment);
301e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4,
302e18a033bSKonstantin Ananyev    uint64_t atom_data_size);
303e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
304e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak);
305e18a033bSKonstantin Ananyevstatic void ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4,
306e18a033bSKonstantin Ananyev    ngx_http_mp4_trak_t *trak, off_t adjustment);
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyevstatic char *ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
309e18a033bSKonstantin Ananyevstatic void *ngx_http_mp4_create_conf(ngx_conf_t *cf);
310e18a033bSKonstantin Ananyevstatic char *ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child);
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev
313e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_http_mp4_commands[] = {
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyev    { ngx_string("mp4"),
316e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
317e18a033bSKonstantin Ananyev      ngx_http_mp4,
318e18a033bSKonstantin Ananyev      0,
319e18a033bSKonstantin Ananyev      0,
320e18a033bSKonstantin Ananyev      NULL },
321e18a033bSKonstantin Ananyev
322e18a033bSKonstantin Ananyev    { ngx_string("mp4_buffer_size"),
323e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
324e18a033bSKonstantin Ananyev      ngx_conf_set_size_slot,
325e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
326e18a033bSKonstantin Ananyev      offsetof(ngx_http_mp4_conf_t, buffer_size),
327e18a033bSKonstantin Ananyev      NULL },
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev    { ngx_string("mp4_max_buffer_size"),
330e18a033bSKonstantin Ananyev      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
331e18a033bSKonstantin Ananyev      ngx_conf_set_size_slot,
332e18a033bSKonstantin Ananyev      NGX_HTTP_LOC_CONF_OFFSET,
333e18a033bSKonstantin Ananyev      offsetof(ngx_http_mp4_conf_t, max_buffer_size),
334e18a033bSKonstantin Ananyev      NULL },
335e18a033bSKonstantin Ananyev
336e18a033bSKonstantin Ananyev      ngx_null_command
337e18a033bSKonstantin Ananyev};
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev
340e18a033bSKonstantin Ananyevstatic ngx_http_module_t  ngx_http_mp4_module_ctx = {
341e18a033bSKonstantin Ananyev    NULL,                          /* preconfiguration */
342e18a033bSKonstantin Ananyev    NULL,                          /* postconfiguration */
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev    NULL,                          /* create main configuration */
345e18a033bSKonstantin Ananyev    NULL,                          /* init main configuration */
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev    NULL,                          /* create server configuration */
348e18a033bSKonstantin Ananyev    NULL,                          /* merge server configuration */
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev    ngx_http_mp4_create_conf,      /* create location configuration */
351e18a033bSKonstantin Ananyev    ngx_http_mp4_merge_conf        /* merge location configuration */
352e18a033bSKonstantin Ananyev};
353e18a033bSKonstantin Ananyev
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyevngx_module_t  ngx_http_mp4_module = {
356e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
357e18a033bSKonstantin Ananyev    &ngx_http_mp4_module_ctx,      /* module context */
358e18a033bSKonstantin Ananyev    ngx_http_mp4_commands,         /* module directives */
359e18a033bSKonstantin Ananyev    NGX_HTTP_MODULE,               /* module type */
360e18a033bSKonstantin Ananyev    NULL,                          /* init master */
361e18a033bSKonstantin Ananyev    NULL,                          /* init module */
362e18a033bSKonstantin Ananyev    NULL,                          /* init process */
363e18a033bSKonstantin Ananyev    NULL,                          /* init thread */
364e18a033bSKonstantin Ananyev    NULL,                          /* exit thread */
365e18a033bSKonstantin Ananyev    NULL,                          /* exit process */
366e18a033bSKonstantin Ananyev    NULL,                          /* exit master */
367e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
368e18a033bSKonstantin Ananyev};
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyevstatic ngx_http_mp4_atom_handler_t  ngx_http_mp4_atoms[] = {
372e18a033bSKonstantin Ananyev    { "ftyp", ngx_http_mp4_read_ftyp_atom },
373e18a033bSKonstantin Ananyev    { "moov", ngx_http_mp4_read_moov_atom },
374e18a033bSKonstantin Ananyev    { "mdat", ngx_http_mp4_read_mdat_atom },
375e18a033bSKonstantin Ananyev    { NULL, NULL }
376e18a033bSKonstantin Ananyev};
377e18a033bSKonstantin Ananyev
378e18a033bSKonstantin Ananyevstatic ngx_http_mp4_atom_handler_t  ngx_http_mp4_moov_atoms[] = {
379e18a033bSKonstantin Ananyev    { "mvhd", ngx_http_mp4_read_mvhd_atom },
380e18a033bSKonstantin Ananyev    { "trak", ngx_http_mp4_read_trak_atom },
381e18a033bSKonstantin Ananyev    { "cmov", ngx_http_mp4_read_cmov_atom },
382e18a033bSKonstantin Ananyev    { NULL, NULL }
383e18a033bSKonstantin Ananyev};
384e18a033bSKonstantin Ananyev
385e18a033bSKonstantin Ananyevstatic ngx_http_mp4_atom_handler_t  ngx_http_mp4_trak_atoms[] = {
386e18a033bSKonstantin Ananyev    { "tkhd", ngx_http_mp4_read_tkhd_atom },
387e18a033bSKonstantin Ananyev    { "mdia", ngx_http_mp4_read_mdia_atom },
388e18a033bSKonstantin Ananyev    { NULL, NULL }
389e18a033bSKonstantin Ananyev};
390e18a033bSKonstantin Ananyev
391e18a033bSKonstantin Ananyevstatic ngx_http_mp4_atom_handler_t  ngx_http_mp4_mdia_atoms[] = {
392e18a033bSKonstantin Ananyev    { "mdhd", ngx_http_mp4_read_mdhd_atom },
393e18a033bSKonstantin Ananyev    { "hdlr", ngx_http_mp4_read_hdlr_atom },
394e18a033bSKonstantin Ananyev    { "minf", ngx_http_mp4_read_minf_atom },
395e18a033bSKonstantin Ananyev    { NULL, NULL }
396e18a033bSKonstantin Ananyev};
397e18a033bSKonstantin Ananyev
398e18a033bSKonstantin Ananyevstatic ngx_http_mp4_atom_handler_t  ngx_http_mp4_minf_atoms[] = {
399e18a033bSKonstantin Ananyev    { "vmhd", ngx_http_mp4_read_vmhd_atom },
400e18a033bSKonstantin Ananyev    { "smhd", ngx_http_mp4_read_smhd_atom },
401e18a033bSKonstantin Ananyev    { "dinf", ngx_http_mp4_read_dinf_atom },
402e18a033bSKonstantin Ananyev    { "stbl", ngx_http_mp4_read_stbl_atom },
403e18a033bSKonstantin Ananyev    { NULL, NULL }
404e18a033bSKonstantin Ananyev};
405e18a033bSKonstantin Ananyev
406e18a033bSKonstantin Ananyevstatic ngx_http_mp4_atom_handler_t  ngx_http_mp4_stbl_atoms[] = {
407e18a033bSKonstantin Ananyev    { "stsd", ngx_http_mp4_read_stsd_atom },
408