Mp4: sanity checks cleanup.
Maxim Dounin
10 years ago
155 | 155 | |
156 | 156 | #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8) |
157 | 157 | #define ngx_mp4_atom_data(mp4) mp4->buffer_pos |
158 | #define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8) | |
158 | 159 | #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n |
159 | 160 | |
160 | 161 | |
203 | 204 | static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); |
204 | 205 | static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, |
205 | 206 | ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); |
206 | static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4); | |
207 | static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size); | |
207 | 208 | static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, |
208 | 209 | uint64_t atom_data_size); |
209 | 210 | static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, |
264 | 265 | ngx_http_mp4_trak_t *trak); |
265 | 266 | static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, |
266 | 267 | uint64_t atom_data_size); |
267 | static void ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, | |
268 | static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, | |
268 | 269 | ngx_http_mp4_trak_t *trak); |
269 | 270 | static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, |
270 | 271 | uint64_t atom_data_size); |
700 | 701 | return NGX_ERROR; |
701 | 702 | } |
702 | 703 | |
703 | ngx_http_mp4_update_stsz_atom(mp4, &trak[i]); | |
704 | if (ngx_http_mp4_update_stsz_atom(mp4, &trak[i]) != NGX_OK) { | |
705 | return NGX_ERROR; | |
706 | } | |
704 | 707 | |
705 | 708 | if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { |
706 | 709 | if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) { |
792 | 795 | |
793 | 796 | while (mp4->offset < end) { |
794 | 797 | |
795 | if (mp4->buffer_pos + sizeof(uint32_t) > mp4->buffer_end) { | |
796 | if (ngx_http_mp4_read(mp4) != NGX_OK) { | |
797 | return NGX_ERROR; | |
798 | } | |
798 | if (ngx_http_mp4_read(mp4, sizeof(uint32_t)) != NGX_OK) { | |
799 | return NGX_ERROR; | |
799 | 800 | } |
800 | 801 | |
801 | 802 | atom_header = mp4->buffer_pos; |
812 | 813 | |
813 | 814 | if (atom_size == 1) { |
814 | 815 | |
815 | if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header64_t) | |
816 | > mp4->buffer_end) | |
816 | if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header64_t)) | |
817 | != NGX_OK) | |
817 | 818 | { |
818 | if (ngx_http_mp4_read(mp4) != NGX_OK) { | |
819 | return NGX_ERROR; | |
820 | } | |
821 | ||
822 | atom_header = mp4->buffer_pos; | |
819 | return NGX_ERROR; | |
823 | 820 | } |
824 | 821 | |
825 | 822 | /* 64-bit atom size */ |
823 | atom_header = mp4->buffer_pos; | |
826 | 824 | atom_size = ngx_mp4_get_64value(atom_header + 8); |
827 | 825 | atom_header_size = sizeof(ngx_mp4_atom_header64_t); |
828 | 826 | |
834 | 832 | } |
835 | 833 | } |
836 | 834 | |
837 | if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header_t) > mp4->buffer_end) { | |
838 | if (ngx_http_mp4_read(mp4) != NGX_OK) { | |
839 | return NGX_ERROR; | |
840 | } | |
841 | ||
842 | atom_header = mp4->buffer_pos; | |
843 | } | |
844 | ||
835 | if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header_t)) != NGX_OK) { | |
836 | return NGX_ERROR; | |
837 | } | |
838 | ||
839 | atom_header = mp4->buffer_pos; | |
845 | 840 | atom_name = atom_header + sizeof(uint32_t); |
846 | 841 | |
847 | 842 | ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
848 | 843 | "mp4 atom: %*s @%O:%uL", |
849 | 844 | 4, atom_name, mp4->offset, atom_size); |
845 | ||
846 | if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset) | |
847 | || mp4->offset + (off_t) atom_size > end) | |
848 | { | |
849 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
850 | "\"%s\" mp4 atom too large:%uL", | |
851 | mp4->file.name.data, atom_size); | |
852 | return NGX_ERROR; | |
853 | } | |
850 | 854 | |
851 | 855 | for (n = 0; atom[n].name; n++) { |
852 | 856 | |
874 | 878 | |
875 | 879 | |
876 | 880 | static ngx_int_t |
877 | ngx_http_mp4_read(ngx_http_mp4_file_t *mp4) | |
878 | { | |
879 | ngx_int_t n; | |
881 | ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size) | |
882 | { | |
883 | ssize_t n; | |
884 | ||
885 | if (mp4->buffer_pos + size <= mp4->buffer_end) { | |
886 | return NGX_OK; | |
887 | } | |
880 | 888 | |
881 | 889 | if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) { |
882 | 890 | mp4->buffer_size = (size_t) (mp4->end - mp4->offset); |
891 | } | |
892 | ||
893 | if (mp4->buffer_size < size) { | |
894 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
895 | "\"%s\" mp4 file truncated", mp4->file.name.data); | |
896 | return NGX_ERROR; | |
883 | 897 | } |
884 | 898 | |
885 | 899 | if (mp4->buffer == NULL) { |
889 | 903 | } |
890 | 904 | |
891 | 905 | mp4->buffer_start = mp4->buffer; |
892 | mp4->buffer_end = mp4->buffer + mp4->buffer_size; | |
893 | 906 | } |
894 | 907 | |
895 | 908 | n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size, |
899 | 912 | return NGX_ERROR; |
900 | 913 | } |
901 | 914 | |
902 | if (n == 0) { | |
903 | return NGX_OK; | |
915 | if ((size_t) n != mp4->buffer_size) { | |
916 | ngx_log_error(NGX_LOG_CRIT, mp4->file.log, 0, | |
917 | ngx_read_file_n " read only %z of %z from \"%s\"", | |
918 | n, mp4->buffer_size, mp4->file.name.data); | |
919 | return NGX_ERROR; | |
904 | 920 | } |
905 | 921 | |
906 | 922 | mp4->buffer_pos = mp4->buffer_start; |
923 | mp4->buffer_end = mp4->buffer_start + mp4->buffer_size; | |
907 | 924 | |
908 | 925 | return NGX_OK; |
909 | 926 | } |
918 | 935 | |
919 | 936 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom"); |
920 | 937 | |
921 | if (atom_data_size > 1024) { | |
938 | if (atom_data_size > 1024 | |
939 | || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end) | |
940 | { | |
922 | 941 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
923 | 942 | "\"%s\" mp4 ftyp atom is too large:%uL", |
924 | 943 | mp4->file.name.data, atom_data_size); |
1167 | 1186 | mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header; |
1168 | 1187 | ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd'); |
1169 | 1188 | |
1189 | if (ngx_mp4_atom_data_size(ngx_mp4_mvhd_atom_t) > atom_data_size) { | |
1190 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1191 | "\"%s\" mp4 mvhd atom too small", mp4->file.name.data); | |
1192 | return NGX_ERROR; | |
1193 | } | |
1194 | ||
1170 | 1195 | if (mvhd_atom->version[0] == 0) { |
1171 | 1196 | /* version 0: 32-bit duration */ |
1172 | 1197 | timescale = ngx_mp4_get_32value(mvhd_atom->timescale); |
1174 | 1199 | |
1175 | 1200 | } else { |
1176 | 1201 | /* version 1: 64-bit duration */ |
1202 | ||
1203 | if (ngx_mp4_atom_data_size(ngx_mp4_mvhd64_atom_t) > atom_data_size) { | |
1204 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1205 | "\"%s\" mp4 mvhd atom too small", | |
1206 | mp4->file.name.data); | |
1207 | return NGX_ERROR; | |
1208 | } | |
1209 | ||
1177 | 1210 | timescale = ngx_mp4_get_32value(mvhd64_atom->timescale); |
1178 | 1211 | duration = ngx_mp4_get_64value(mvhd64_atom->duration); |
1179 | 1212 | } |
1344 | 1377 | tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header; |
1345 | 1378 | ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd'); |
1346 | 1379 | |
1380 | if (ngx_mp4_atom_data_size(ngx_mp4_tkhd_atom_t) > atom_data_size) { | |
1381 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1382 | "\"%s\" mp4 tkhd atom too small", mp4->file.name.data); | |
1383 | return NGX_ERROR; | |
1384 | } | |
1385 | ||
1347 | 1386 | if (tkhd_atom->version[0] == 0) { |
1348 | 1387 | /* version 0: 32-bit duration */ |
1349 | 1388 | duration = ngx_mp4_get_32value(tkhd_atom->duration); |
1350 | 1389 | |
1351 | 1390 | } else { |
1352 | 1391 | /* version 1: 64-bit duration */ |
1392 | ||
1393 | if (ngx_mp4_atom_data_size(ngx_mp4_tkhd64_atom_t) > atom_data_size) { | |
1394 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1395 | "\"%s\" mp4 tkhd atom too small", | |
1396 | mp4->file.name.data); | |
1397 | return NGX_ERROR; | |
1398 | } | |
1399 | ||
1353 | 1400 | duration = ngx_mp4_get_64value(tkhd64_atom->duration); |
1354 | 1401 | } |
1355 | 1402 | |
1473 | 1520 | mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header; |
1474 | 1521 | ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd'); |
1475 | 1522 | |
1523 | if (ngx_mp4_atom_data_size(ngx_mp4_mdhd_atom_t) > atom_data_size) { | |
1524 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1525 | "\"%s\" mp4 mdhd atom too small", mp4->file.name.data); | |
1526 | return NGX_ERROR; | |
1527 | } | |
1528 | ||
1476 | 1529 | if (mdhd_atom->version[0] == 0) { |
1477 | 1530 | /* version 0: everything is 32-bit */ |
1478 | 1531 | timescale = ngx_mp4_get_32value(mdhd_atom->timescale); |
1480 | 1533 | |
1481 | 1534 | } else { |
1482 | 1535 | /* version 1: 64-bit duration and 32-bit timescale */ |
1536 | ||
1537 | if (ngx_mp4_atom_data_size(ngx_mp4_mdhd64_atom_t) > atom_data_size) { | |
1538 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1539 | "\"%s\" mp4 mdhd atom too small", | |
1540 | mp4->file.name.data); | |
1541 | return NGX_ERROR; | |
1542 | } | |
1543 | ||
1483 | 1544 | timescale = ngx_mp4_get_32value(mdhd64_atom->timescale); |
1484 | 1545 | duration = ngx_mp4_get_64value(mdhd64_atom->duration); |
1485 | 1546 | } |
1755 | 1816 | ngx_mp4_set_32value(stsd_atom->size, atom_size); |
1756 | 1817 | ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd'); |
1757 | 1818 | |
1758 | if ((uint64_t) (sizeof(ngx_mp4_stsd_atom_t) - sizeof(ngx_mp4_atom_header_t)) | |
1759 | > atom_data_size) | |
1760 | { | |
1819 | if (ngx_mp4_atom_data_size(ngx_mp4_stsd_atom_t) > atom_data_size) { | |
1761 | 1820 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
1762 | "\"%s\" mp4 stsd atom too large", | |
1763 | mp4->file.name.data); | |
1821 | "\"%s\" mp4 stsd atom too small", mp4->file.name.data); | |
1764 | 1822 | return NGX_ERROR; |
1765 | 1823 | } |
1766 | 1824 | |
1824 | 1882 | stts_atom = (ngx_mp4_stts_atom_t *) atom_header; |
1825 | 1883 | ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's'); |
1826 | 1884 | |
1885 | if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) > atom_data_size) { | |
1886 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1887 | "\"%s\" mp4 stts atom too small", mp4->file.name.data); | |
1888 | return NGX_ERROR; | |
1889 | } | |
1890 | ||
1827 | 1891 | entries = ngx_mp4_get_32value(stts_atom->entries); |
1828 | 1892 | |
1829 | 1893 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1830 | 1894 | "mp4 time-to-sample entries:%uD", entries); |
1831 | 1895 | |
1896 | if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) | |
1897 | + entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size) | |
1898 | { | |
1899 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1900 | "\"%s\" mp4 stts atom too small", mp4->file.name.data); | |
1901 | return NGX_ERROR; | |
1902 | } | |
1903 | ||
1832 | 1904 | atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t); |
1833 | 1905 | atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t); |
1834 | ||
1835 | if ((uint64_t) (atom_end - stts_atom->version) > atom_data_size) { | |
1836 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1837 | "\"%s\" mp4 stts atom too large", | |
1838 | mp4->file.name.data); | |
1839 | return NGX_ERROR; | |
1840 | } | |
1841 | 1906 | |
1842 | 1907 | trak = ngx_mp4_last_trak(mp4); |
1843 | 1908 | trak->time_to_sample_entries = entries; |
1972 | 2037 | stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header; |
1973 | 2038 | ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's'); |
1974 | 2039 | |
2040 | if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) > atom_data_size) { | |
2041 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2042 | "\"%s\" mp4 stss atom too small", mp4->file.name.data); | |
2043 | return NGX_ERROR; | |
2044 | } | |
2045 | ||
1975 | 2046 | entries = ngx_mp4_get_32value(stss_atom->entries); |
1976 | 2047 | |
1977 | 2048 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1987 | 2058 | atom->pos = atom_header; |
1988 | 2059 | atom->last = atom_table; |
1989 | 2060 | |
2061 | if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) | |
2062 | + entries * sizeof(uint32_t) > atom_data_size) | |
2063 | { | |
2064 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2065 | "\"%s\" mp4 stss atom too small", mp4->file.name.data); | |
2066 | return NGX_ERROR; | |
2067 | } | |
2068 | ||
1990 | 2069 | atom_end = atom_table + entries * sizeof(uint32_t); |
1991 | ||
1992 | if ((uint64_t) (atom_end - stss_atom->version) > atom_data_size) { | |
1993 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1994 | "\"%s\" mp4 stss atom too large", mp4->file.name.data); | |
1995 | return NGX_ERROR; | |
1996 | } | |
1997 | 2070 | |
1998 | 2071 | data = &trak->stss_data_buf; |
1999 | 2072 | data->temporary = 1; |
2117 | 2190 | ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header; |
2118 | 2191 | ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's'); |
2119 | 2192 | |
2193 | if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) > atom_data_size) { | |
2194 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2195 | "\"%s\" mp4 ctts atom too small", mp4->file.name.data); | |
2196 | return NGX_ERROR; | |
2197 | } | |
2198 | ||
2120 | 2199 | entries = ngx_mp4_get_32value(ctts_atom->entries); |
2121 | 2200 | |
2122 | 2201 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
2132 | 2211 | atom->pos = atom_header; |
2133 | 2212 | atom->last = atom_table; |
2134 | 2213 | |
2214 | if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) | |
2215 | + entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size) | |
2216 | { | |
2217 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2218 | "\"%s\" mp4 ctts atom too small", mp4->file.name.data); | |
2219 | return NGX_ERROR; | |
2220 | } | |
2221 | ||
2135 | 2222 | atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t); |
2136 | ||
2137 | if ((uint64_t) (atom_end - ctts_atom->version) > atom_data_size) { | |
2138 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2139 | "\"%s\" mp4 ctts atom too large", mp4->file.name.data); | |
2140 | return NGX_ERROR; | |
2141 | } | |
2142 | 2223 | |
2143 | 2224 | data = &trak->ctts_data_buf; |
2144 | 2225 | data->temporary = 1; |
2250 | 2331 | stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header; |
2251 | 2332 | ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c'); |
2252 | 2333 | |
2334 | if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) > atom_data_size) { | |
2335 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2336 | "\"%s\" mp4 stsc atom too small", mp4->file.name.data); | |
2337 | return NGX_ERROR; | |
2338 | } | |
2339 | ||
2253 | 2340 | entries = ngx_mp4_get_32value(stsc_atom->entries); |
2254 | 2341 | |
2255 | 2342 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
2256 | 2343 | "sample-to-chunk entries:%uD", entries); |
2257 | 2344 | |
2345 | if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) | |
2346 | + entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size) | |
2347 | { | |
2348 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2349 | "\"%s\" mp4 stsc atom too small", mp4->file.name.data); | |
2350 | return NGX_ERROR; | |
2351 | } | |
2352 | ||
2258 | 2353 | atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t); |
2259 | 2354 | atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t); |
2260 | ||
2261 | if ((uint64_t) (atom_end - stsc_atom->version) > atom_data_size) { | |
2262 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2263 | "\"%s\" mp4 stsc atom too large", | |
2264 | mp4->file.name.data); | |
2265 | return NGX_ERROR; | |
2266 | } | |
2267 | 2355 | |
2268 | 2356 | trak = ngx_mp4_last_trak(mp4); |
2269 | 2357 | trak->sample_to_chunk_entries = entries; |
2312 | 2400 | if (data == NULL) { |
2313 | 2401 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
2314 | 2402 | "no mp4 stsc atoms were found in \"%s\"", |
2403 | mp4->file.name.data); | |
2404 | return NGX_ERROR; | |
2405 | } | |
2406 | ||
2407 | if (trak->sample_to_chunk_entries == 0) { | |
2408 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2409 | "zero number of entries in stsc atom in \"%s\"", | |
2315 | 2410 | mp4->file.name.data); |
2316 | 2411 | return NGX_ERROR; |
2317 | 2412 | } |
2457 | 2552 | stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header; |
2458 | 2553 | ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z'); |
2459 | 2554 | |
2555 | if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) > atom_data_size) { | |
2556 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2557 | "\"%s\" mp4 stsz atom too small", mp4->file.name.data); | |
2558 | return NGX_ERROR; | |
2559 | } | |
2560 | ||
2460 | 2561 | size = ngx_mp4_get_32value(stsz_atom->uniform_size); |
2461 | 2562 | entries = ngx_mp4_get_32value(stsz_atom->entries); |
2462 | 2563 | |
2476 | 2577 | trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom; |
2477 | 2578 | |
2478 | 2579 | if (size == 0) { |
2479 | atom_end = atom_table + entries * sizeof(uint32_t); | |
2480 | ||
2481 | if ((uint64_t) (atom_end - stsz_atom->version) > atom_data_size) { | |
2580 | if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) | |
2581 | + entries * sizeof(uint32_t) > atom_data_size) | |
2582 | { | |
2482 | 2583 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
2483 | "\"%s\" mp4 stsz atom too large", | |
2584 | "\"%s\" mp4 stsz atom too small", | |
2484 | 2585 | mp4->file.name.data); |
2485 | 2586 | return NGX_ERROR; |
2486 | 2587 | } |
2588 | ||
2589 | atom_end = atom_table + entries * sizeof(uint32_t); | |
2487 | 2590 | |
2488 | 2591 | data = &trak->stsz_data_buf; |
2489 | 2592 | data->temporary = 1; |
2506 | 2609 | } |
2507 | 2610 | |
2508 | 2611 | |
2509 | static void | |
2612 | static ngx_int_t | |
2510 | 2613 | ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, |
2511 | 2614 | ngx_http_mp4_trak_t *trak) |
2512 | 2615 | { |
2527 | 2630 | data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf; |
2528 | 2631 | |
2529 | 2632 | if (data) { |
2633 | if (trak->start_sample > trak->sample_sizes_entries) { | |
2634 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2635 | "start time is out mp4 stsz samples in \"%s\"", | |
2636 | mp4->file.name.data); | |
2637 | return NGX_ERROR; | |
2638 | } | |
2639 | ||
2530 | 2640 | data->pos += trak->start_sample * sizeof(uint32_t); |
2531 | 2641 | end = (uint32_t *) data->pos; |
2532 | 2642 | |
2547 | 2657 | ngx_mp4_set_32value(stsz_atom->entries, |
2548 | 2658 | trak->sample_sizes_entries - trak->start_sample); |
2549 | 2659 | } |
2660 | ||
2661 | return NGX_OK; | |
2550 | 2662 | } |
2551 | 2663 | |
2552 | 2664 | |
2576 | 2688 | stco_atom = (ngx_mp4_stco_atom_t *) atom_header; |
2577 | 2689 | ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o'); |
2578 | 2690 | |
2691 | if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) > atom_data_size) { | |
2692 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2693 | "\"%s\" mp4 stco atom too small", mp4->file.name.data); | |
2694 | return NGX_ERROR; | |
2695 | } | |
2696 | ||
2579 | 2697 | entries = ngx_mp4_get_32value(stco_atom->entries); |
2580 | 2698 | |
2581 | 2699 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); |
2700 | ||
2701 | if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) | |
2702 | + entries * sizeof(uint32_t) > atom_data_size) | |
2703 | { | |
2704 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2705 | "\"%s\" mp4 stco atom too small", mp4->file.name.data); | |
2706 | return NGX_ERROR; | |
2707 | } | |
2582 | 2708 | |
2583 | 2709 | atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t); |
2584 | 2710 | atom_end = atom_table + entries * sizeof(uint32_t); |
2585 | ||
2586 | if ((uint64_t) (atom_end - stco_atom->version) > atom_data_size) { | |
2587 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2588 | "\"%s\" mp4 stco atom too large", mp4->file.name.data); | |
2589 | return NGX_ERROR; | |
2590 | } | |
2591 | 2711 | |
2592 | 2712 | trak = ngx_mp4_last_trak(mp4); |
2593 | 2713 | trak->chunks = entries; |
2633 | 2753 | if (data == NULL) { |
2634 | 2754 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
2635 | 2755 | "no mp4 stco atoms were found in \"%s\"", |
2756 | mp4->file.name.data); | |
2757 | return NGX_ERROR; | |
2758 | } | |
2759 | ||
2760 | if (trak->start_chunk > trak->chunks) { | |
2761 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2762 | "start time is out mp4 stco chunks in \"%s\"", | |
2636 | 2763 | mp4->file.name.data); |
2637 | 2764 | return NGX_ERROR; |
2638 | 2765 | } |
2712 | 2839 | co64_atom = (ngx_mp4_co64_atom_t *) atom_header; |
2713 | 2840 | ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4'); |
2714 | 2841 | |
2842 | if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) > atom_data_size) { | |
2843 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2844 | "\"%s\" mp4 co64 atom too small", mp4->file.name.data); | |
2845 | return NGX_ERROR; | |
2846 | } | |
2847 | ||
2715 | 2848 | entries = ngx_mp4_get_32value(co64_atom->entries); |
2716 | 2849 | |
2717 | 2850 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); |
2851 | ||
2852 | if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) | |
2853 | + entries * sizeof(uint64_t) > atom_data_size) | |
2854 | { | |
2855 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2856 | "\"%s\" mp4 co64 atom too small", mp4->file.name.data); | |
2857 | return NGX_ERROR; | |
2858 | } | |
2718 | 2859 | |
2719 | 2860 | atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t); |
2720 | 2861 | atom_end = atom_table + entries * sizeof(uint64_t); |
2721 | ||
2722 | if ((uint64_t) (atom_end - co64_atom->version) > atom_data_size) { | |
2723 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2724 | "\"%s\" mp4 co64 atom too large", mp4->file.name.data); | |
2725 | return NGX_ERROR; | |
2726 | } | |
2727 | 2862 | |
2728 | 2863 | trak = ngx_mp4_last_trak(mp4); |
2729 | 2864 | trak->chunks = entries; |
2773 | 2908 | return NGX_ERROR; |
2774 | 2909 | } |
2775 | 2910 | |
2911 | if (trak->start_chunk > trak->chunks) { | |
2912 | ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2913 | "start time is out mp4 co64 chunks in \"%s\"", | |
2914 | mp4->file.name.data); | |
2915 | return NGX_ERROR; | |
2916 | } | |
2917 | ||
2776 | 2918 | data->pos += trak->start_chunk * sizeof(uint64_t); |
2777 | 2919 | atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos); |
2778 | 2920 | trak->size += atom_size; |