Mercurial > hg > nginx
comparison src/http/modules/ngx_http_mp4_module.c @ 4589:533aa09a783b stable-1.0
Merge of r4578, r4579, r4580, r4586: mp4 fixes.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 12 Apr 2012 12:55:43 +0000 |
parents | 4919fb357a5d |
children |
comparison
equal
deleted
inserted
replaced
4588:6381447b8894 | 4589:533aa09a783b |
---|---|
154 } ngx_http_mp4_atom_handler_t; | 154 } ngx_http_mp4_atom_handler_t; |
155 | 155 |
156 | 156 |
157 #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8) | 157 #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8) |
158 #define ngx_mp4_atom_data(mp4) mp4->buffer_pos | 158 #define ngx_mp4_atom_data(mp4) mp4->buffer_pos |
159 #define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8) | |
159 #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n | 160 #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n |
160 | 161 |
161 | 162 |
162 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \ | 163 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \ |
163 ((u_char *) (p))[4] = n1; \ | 164 ((u_char *) (p))[4] = n1; \ |
202 | 203 |
203 | 204 |
204 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); | 205 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4); |
205 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, | 206 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, |
206 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); | 207 ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size); |
207 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4); | 208 static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size); |
208 static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, | 209 static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, |
209 uint64_t atom_data_size); | 210 uint64_t atom_data_size); |
210 static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, | 211 static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, |
211 uint64_t atom_data_size); | 212 uint64_t atom_data_size); |
212 static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, | 213 static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, |
263 uint64_t atom_data_size); | 264 uint64_t atom_data_size); |
264 static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4, | 265 static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4, |
265 ngx_http_mp4_trak_t *trak); | 266 ngx_http_mp4_trak_t *trak); |
266 static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, | 267 static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, |
267 uint64_t atom_data_size); | 268 uint64_t atom_data_size); |
268 static void ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, | 269 static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, |
269 ngx_http_mp4_trak_t *trak); | 270 ngx_http_mp4_trak_t *trak); |
270 static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, | 271 static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, |
271 uint64_t atom_data_size); | 272 uint64_t atom_data_size); |
272 static ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4, | 273 static ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4, |
273 ngx_http_mp4_trak_t *trak); | 274 ngx_http_mp4_trak_t *trak); |
691 | 692 |
692 if (ngx_http_mp4_update_stsc_atom(mp4, &trak[i]) != NGX_OK) { | 693 if (ngx_http_mp4_update_stsc_atom(mp4, &trak[i]) != NGX_OK) { |
693 return NGX_ERROR; | 694 return NGX_ERROR; |
694 } | 695 } |
695 | 696 |
696 ngx_http_mp4_update_stsz_atom(mp4, &trak[i]); | 697 if (ngx_http_mp4_update_stsz_atom(mp4, &trak[i]) != NGX_OK) { |
698 return NGX_ERROR; | |
699 } | |
697 | 700 |
698 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { | 701 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { |
699 if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) { | 702 if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) { |
700 return NGX_ERROR; | 703 return NGX_ERROR; |
701 } | 704 } |
742 adjustment = mp4->ftyp_size + mp4->moov_size | 745 adjustment = mp4->ftyp_size + mp4->moov_size |
743 + ngx_http_mp4_update_mdat_atom(mp4, start_offset) | 746 + ngx_http_mp4_update_mdat_atom(mp4, start_offset) |
744 - start_offset; | 747 - start_offset; |
745 | 748 |
746 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 749 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
747 "mp4 adjustment:%D", adjustment); | 750 "mp4 adjustment:%O", adjustment); |
748 | 751 |
749 for (i = 0; i < mp4->trak.nelts; i++) { | 752 for (i = 0; i < mp4->trak.nelts; i++) { |
750 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { | 753 if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) { |
751 ngx_http_mp4_adjust_co64_atom(mp4, &trak[i], adjustment); | 754 ngx_http_mp4_adjust_co64_atom(mp4, &trak[i], adjustment); |
752 } else { | 755 } else { |
783 | 786 |
784 end = mp4->offset + atom_data_size; | 787 end = mp4->offset + atom_data_size; |
785 | 788 |
786 while (mp4->offset < end) { | 789 while (mp4->offset < end) { |
787 | 790 |
788 if (mp4->buffer_pos + sizeof(uint32_t) > mp4->buffer_end) { | 791 if (ngx_http_mp4_read(mp4, sizeof(uint32_t)) != NGX_OK) { |
789 if (ngx_http_mp4_read(mp4) != NGX_OK) { | 792 return NGX_ERROR; |
790 return NGX_ERROR; | |
791 } | |
792 } | 793 } |
793 | 794 |
794 atom_header = mp4->buffer_pos; | 795 atom_header = mp4->buffer_pos; |
795 atom_size = ngx_mp4_get_32value(atom_header); | 796 atom_size = ngx_mp4_get_32value(atom_header); |
796 atom_header_size = sizeof(ngx_mp4_atom_header_t); | 797 atom_header_size = sizeof(ngx_mp4_atom_header_t); |
803 | 804 |
804 if (atom_size < sizeof(ngx_mp4_atom_header_t)) { | 805 if (atom_size < sizeof(ngx_mp4_atom_header_t)) { |
805 | 806 |
806 if (atom_size == 1) { | 807 if (atom_size == 1) { |
807 | 808 |
808 if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header64_t) | 809 if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header64_t)) |
809 > mp4->buffer_end) | 810 != NGX_OK) |
810 { | 811 { |
811 if (ngx_http_mp4_read(mp4) != NGX_OK) { | 812 return NGX_ERROR; |
812 return NGX_ERROR; | |
813 } | |
814 | |
815 atom_header = mp4->buffer_pos; | |
816 } | 813 } |
817 | 814 |
818 /* 64-bit atom size */ | 815 /* 64-bit atom size */ |
816 atom_header = mp4->buffer_pos; | |
819 atom_size = ngx_mp4_get_64value(atom_header + 8); | 817 atom_size = ngx_mp4_get_64value(atom_header + 8); |
820 atom_header_size = sizeof(ngx_mp4_atom_header64_t); | 818 atom_header_size = sizeof(ngx_mp4_atom_header64_t); |
821 | 819 |
822 } else { | 820 } else { |
823 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | 821 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
825 mp4->file.name.data, atom_size); | 823 mp4->file.name.data, atom_size); |
826 return NGX_ERROR; | 824 return NGX_ERROR; |
827 } | 825 } |
828 } | 826 } |
829 | 827 |
830 if (mp4->buffer_pos + sizeof(ngx_mp4_atom_header_t) > mp4->buffer_end) { | 828 if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header_t)) != NGX_OK) { |
831 if (ngx_http_mp4_read(mp4) != NGX_OK) { | 829 return NGX_ERROR; |
832 return NGX_ERROR; | 830 } |
833 } | 831 |
834 | 832 atom_header = mp4->buffer_pos; |
835 atom_header = mp4->buffer_pos; | |
836 } | |
837 | |
838 atom_name = atom_header + sizeof(uint32_t); | 833 atom_name = atom_header + sizeof(uint32_t); |
839 | 834 |
840 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 835 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
841 "mp4 atom: %*s @%O:%uL", | 836 "mp4 atom: %*s @%O:%uL", |
842 4, atom_name, mp4->offset, atom_size); | 837 4, atom_name, mp4->offset, atom_size); |
838 | |
839 if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset) | |
840 || mp4->offset + (off_t) atom_size > end) | |
841 { | |
842 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
843 "\"%s\" mp4 atom too large:%uL", | |
844 mp4->file.name.data, atom_size); | |
845 return NGX_ERROR; | |
846 } | |
843 | 847 |
844 for (n = 0; atom[n].name; n++) { | 848 for (n = 0; atom[n].name; n++) { |
845 | 849 |
846 if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) { | 850 if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) { |
847 | 851 |
865 return NGX_OK; | 869 return NGX_OK; |
866 } | 870 } |
867 | 871 |
868 | 872 |
869 static ngx_int_t | 873 static ngx_int_t |
870 ngx_http_mp4_read(ngx_http_mp4_file_t *mp4) | 874 ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size) |
871 { | 875 { |
872 ngx_int_t n; | 876 ssize_t n; |
877 | |
878 if (mp4->buffer_pos + size <= mp4->buffer_end) { | |
879 return NGX_OK; | |
880 } | |
873 | 881 |
874 if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) { | 882 if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) { |
875 mp4->buffer_size = (size_t) (mp4->end - mp4->offset); | 883 mp4->buffer_size = (size_t) (mp4->end - mp4->offset); |
884 } | |
885 | |
886 if (mp4->buffer_size < size) { | |
887 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
888 "\"%s\" mp4 file truncated", mp4->file.name.data); | |
889 return NGX_ERROR; | |
876 } | 890 } |
877 | 891 |
878 if (mp4->buffer == NULL) { | 892 if (mp4->buffer == NULL) { |
879 mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size); | 893 mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size); |
880 if (mp4->buffer == NULL) { | 894 if (mp4->buffer == NULL) { |
881 return NGX_ERROR; | 895 return NGX_ERROR; |
882 } | 896 } |
883 | 897 |
884 mp4->buffer_start = mp4->buffer; | 898 mp4->buffer_start = mp4->buffer; |
885 mp4->buffer_end = mp4->buffer + mp4->buffer_size; | |
886 } | 899 } |
887 | 900 |
888 n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size, | 901 n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size, |
889 mp4->offset); | 902 mp4->offset); |
890 | 903 |
891 if (n == NGX_ERROR) { | 904 if (n == NGX_ERROR) { |
892 return NGX_ERROR; | 905 return NGX_ERROR; |
893 } | 906 } |
894 | 907 |
895 if (n == 0) { | 908 if ((size_t) n != mp4->buffer_size) { |
896 return NGX_OK; | 909 ngx_log_error(NGX_LOG_CRIT, mp4->file.log, 0, |
910 ngx_read_file_n " read only %z of %z from \"%s\"", | |
911 n, mp4->buffer_size, mp4->file.name.data); | |
912 return NGX_ERROR; | |
897 } | 913 } |
898 | 914 |
899 mp4->buffer_pos = mp4->buffer_start; | 915 mp4->buffer_pos = mp4->buffer_start; |
916 mp4->buffer_end = mp4->buffer_start + mp4->buffer_size; | |
900 | 917 |
901 return NGX_OK; | 918 return NGX_OK; |
902 } | 919 } |
903 | 920 |
904 | 921 |
909 size_t atom_size; | 926 size_t atom_size; |
910 ngx_buf_t *atom; | 927 ngx_buf_t *atom; |
911 | 928 |
912 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom"); | 929 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom"); |
913 | 930 |
914 if (atom_data_size > 1024) { | 931 if (atom_data_size > 1024 |
932 || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end) | |
933 { | |
915 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | 934 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
916 "\"%s\" mp4 ftyp atom is too large:%uL", | 935 "\"%s\" mp4 ftyp atom is too large:%uL", |
917 mp4->file.name.data, atom_data_size); | 936 mp4->file.name.data, atom_data_size); |
918 return NGX_ERROR; | 937 return NGX_ERROR; |
919 } | 938 } |
1158 atom_header = ngx_mp4_atom_header(mp4); | 1177 atom_header = ngx_mp4_atom_header(mp4); |
1159 mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header; | 1178 mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header; |
1160 mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header; | 1179 mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header; |
1161 ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd'); | 1180 ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd'); |
1162 | 1181 |
1182 if (ngx_mp4_atom_data_size(ngx_mp4_mvhd_atom_t) > atom_data_size) { | |
1183 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1184 "\"%s\" mp4 mvhd atom too small", mp4->file.name.data); | |
1185 return NGX_ERROR; | |
1186 } | |
1187 | |
1163 if (mvhd_atom->version[0] == 0) { | 1188 if (mvhd_atom->version[0] == 0) { |
1164 /* version 0: 32-bit duration */ | 1189 /* version 0: 32-bit duration */ |
1165 timescale = ngx_mp4_get_32value(mvhd_atom->timescale); | 1190 timescale = ngx_mp4_get_32value(mvhd_atom->timescale); |
1166 duration = ngx_mp4_get_32value(mvhd_atom->duration); | 1191 duration = ngx_mp4_get_32value(mvhd_atom->duration); |
1167 | 1192 |
1168 } else { | 1193 } else { |
1169 /* version 1: 64-bit duration */ | 1194 /* version 1: 64-bit duration */ |
1195 | |
1196 if (ngx_mp4_atom_data_size(ngx_mp4_mvhd64_atom_t) > atom_data_size) { | |
1197 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1198 "\"%s\" mp4 mvhd atom too small", | |
1199 mp4->file.name.data); | |
1200 return NGX_ERROR; | |
1201 } | |
1202 | |
1170 timescale = ngx_mp4_get_32value(mvhd64_atom->timescale); | 1203 timescale = ngx_mp4_get_32value(mvhd64_atom->timescale); |
1171 duration = ngx_mp4_get_64value(mvhd64_atom->duration); | 1204 duration = ngx_mp4_get_64value(mvhd64_atom->duration); |
1172 } | 1205 } |
1173 | 1206 |
1174 mp4->timescale = timescale; | 1207 mp4->timescale = timescale; |
1335 atom_header = ngx_mp4_atom_header(mp4); | 1368 atom_header = ngx_mp4_atom_header(mp4); |
1336 tkhd_atom = (ngx_mp4_tkhd_atom_t *) atom_header; | 1369 tkhd_atom = (ngx_mp4_tkhd_atom_t *) atom_header; |
1337 tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header; | 1370 tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header; |
1338 ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd'); | 1371 ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd'); |
1339 | 1372 |
1373 if (ngx_mp4_atom_data_size(ngx_mp4_tkhd_atom_t) > atom_data_size) { | |
1374 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1375 "\"%s\" mp4 tkhd atom too small", mp4->file.name.data); | |
1376 return NGX_ERROR; | |
1377 } | |
1378 | |
1340 if (tkhd_atom->version[0] == 0) { | 1379 if (tkhd_atom->version[0] == 0) { |
1341 /* version 0: 32-bit duration */ | 1380 /* version 0: 32-bit duration */ |
1342 duration = ngx_mp4_get_32value(tkhd_atom->duration); | 1381 duration = ngx_mp4_get_32value(tkhd_atom->duration); |
1343 | 1382 |
1344 } else { | 1383 } else { |
1345 /* version 1: 64-bit duration */ | 1384 /* version 1: 64-bit duration */ |
1385 | |
1386 if (ngx_mp4_atom_data_size(ngx_mp4_tkhd64_atom_t) > atom_data_size) { | |
1387 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1388 "\"%s\" mp4 tkhd atom too small", | |
1389 mp4->file.name.data); | |
1390 return NGX_ERROR; | |
1391 } | |
1392 | |
1346 duration = ngx_mp4_get_64value(tkhd64_atom->duration); | 1393 duration = ngx_mp4_get_64value(tkhd64_atom->duration); |
1347 } | 1394 } |
1348 | 1395 |
1349 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 1396 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1350 "tkhd duration:%uL, time:%.3fs", | 1397 "tkhd duration:%uL, time:%.3fs", |
1464 atom_header = ngx_mp4_atom_header(mp4); | 1511 atom_header = ngx_mp4_atom_header(mp4); |
1465 mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom_header; | 1512 mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom_header; |
1466 mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header; | 1513 mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header; |
1467 ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd'); | 1514 ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd'); |
1468 | 1515 |
1516 if (ngx_mp4_atom_data_size(ngx_mp4_mdhd_atom_t) > atom_data_size) { | |
1517 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1518 "\"%s\" mp4 mdhd atom too small", mp4->file.name.data); | |
1519 return NGX_ERROR; | |
1520 } | |
1521 | |
1469 if (mdhd_atom->version[0] == 0) { | 1522 if (mdhd_atom->version[0] == 0) { |
1470 /* version 0: everything is 32-bit */ | 1523 /* version 0: everything is 32-bit */ |
1471 timescale = ngx_mp4_get_32value(mdhd_atom->timescale); | 1524 timescale = ngx_mp4_get_32value(mdhd_atom->timescale); |
1472 duration = ngx_mp4_get_32value(mdhd_atom->duration); | 1525 duration = ngx_mp4_get_32value(mdhd_atom->duration); |
1473 | 1526 |
1474 } else { | 1527 } else { |
1475 /* version 1: 64-bit duration and 32-bit timescale */ | 1528 /* version 1: 64-bit duration and 32-bit timescale */ |
1529 | |
1530 if (ngx_mp4_atom_data_size(ngx_mp4_mdhd64_atom_t) > atom_data_size) { | |
1531 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1532 "\"%s\" mp4 mdhd atom too small", | |
1533 mp4->file.name.data); | |
1534 return NGX_ERROR; | |
1535 } | |
1536 | |
1476 timescale = ngx_mp4_get_32value(mdhd64_atom->timescale); | 1537 timescale = ngx_mp4_get_32value(mdhd64_atom->timescale); |
1477 duration = ngx_mp4_get_64value(mdhd64_atom->duration); | 1538 duration = ngx_mp4_get_64value(mdhd64_atom->duration); |
1478 } | 1539 } |
1479 | 1540 |
1480 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 1541 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1746 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; | 1807 atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size; |
1747 atom_table = atom_header + atom_size; | 1808 atom_table = atom_header + atom_size; |
1748 ngx_mp4_set_32value(stsd_atom->size, atom_size); | 1809 ngx_mp4_set_32value(stsd_atom->size, atom_size); |
1749 ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd'); | 1810 ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd'); |
1750 | 1811 |
1751 if ((uint64_t) (sizeof(ngx_mp4_stsd_atom_t) - sizeof(ngx_mp4_atom_header_t)) | 1812 if (ngx_mp4_atom_data_size(ngx_mp4_stsd_atom_t) > atom_data_size) { |
1752 > atom_data_size) | |
1753 { | |
1754 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | 1813 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
1755 "\"%s\" mp4 stsd atom too large", | 1814 "\"%s\" mp4 stsd atom too small", mp4->file.name.data); |
1756 mp4->file.name.data); | |
1757 return NGX_ERROR; | 1815 return NGX_ERROR; |
1758 } | 1816 } |
1759 | 1817 |
1760 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 1818 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1761 "stsd entries:%uD, media:%*s", | 1819 "stsd entries:%uD, media:%*s", |
1815 | 1873 |
1816 atom_header = ngx_mp4_atom_header(mp4); | 1874 atom_header = ngx_mp4_atom_header(mp4); |
1817 stts_atom = (ngx_mp4_stts_atom_t *) atom_header; | 1875 stts_atom = (ngx_mp4_stts_atom_t *) atom_header; |
1818 ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's'); | 1876 ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's'); |
1819 | 1877 |
1878 if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) > atom_data_size) { | |
1879 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1880 "\"%s\" mp4 stts atom too small", mp4->file.name.data); | |
1881 return NGX_ERROR; | |
1882 } | |
1883 | |
1820 entries = ngx_mp4_get_32value(stts_atom->entries); | 1884 entries = ngx_mp4_get_32value(stts_atom->entries); |
1821 | 1885 |
1822 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 1886 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1823 "mp4 time-to-sample entries:%uD", entries); | 1887 "mp4 time-to-sample entries:%uD", entries); |
1824 | 1888 |
1889 if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) | |
1890 + entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size) | |
1891 { | |
1892 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1893 "\"%s\" mp4 stts atom too small", mp4->file.name.data); | |
1894 return NGX_ERROR; | |
1895 } | |
1896 | |
1825 atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t); | 1897 atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t); |
1826 atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t); | 1898 atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t); |
1827 | |
1828 if ((uint64_t) (atom_end - stts_atom->version) > atom_data_size) { | |
1829 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1830 "\"%s\" mp4 stts atom too large", | |
1831 mp4->file.name.data); | |
1832 return NGX_ERROR; | |
1833 } | |
1834 | 1899 |
1835 trak = ngx_mp4_last_trak(mp4); | 1900 trak = ngx_mp4_last_trak(mp4); |
1836 trak->time_to_sample_entries = entries; | 1901 trak->time_to_sample_entries = entries; |
1837 | 1902 |
1838 atom = &trak->stts_atom_buf; | 1903 atom = &trak->stts_atom_buf; |
1900 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 1965 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1901 "count:%uD, duration:%uD", count, duration); | 1966 "count:%uD, duration:%uD", count, duration); |
1902 | 1967 |
1903 if (start_time < (uint64_t) count * duration) { | 1968 if (start_time < (uint64_t) count * duration) { |
1904 start_sample += (ngx_uint_t) (start_time / duration); | 1969 start_sample += (ngx_uint_t) (start_time / duration); |
1905 count -= start_sample; | 1970 count -= (uint32_t) (start_time / duration); |
1906 ngx_mp4_set_32value(entry->count, count); | 1971 ngx_mp4_set_32value(entry->count, count); |
1907 goto found; | 1972 goto found; |
1908 } | 1973 } |
1909 | 1974 |
1910 start_sample += count; | 1975 start_sample += count; |
1963 | 2028 |
1964 atom_header = ngx_mp4_atom_header(mp4); | 2029 atom_header = ngx_mp4_atom_header(mp4); |
1965 stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header; | 2030 stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header; |
1966 ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's'); | 2031 ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's'); |
1967 | 2032 |
2033 if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) > atom_data_size) { | |
2034 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2035 "\"%s\" mp4 stss atom too small", mp4->file.name.data); | |
2036 return NGX_ERROR; | |
2037 } | |
2038 | |
1968 entries = ngx_mp4_get_32value(stss_atom->entries); | 2039 entries = ngx_mp4_get_32value(stss_atom->entries); |
1969 | 2040 |
1970 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 2041 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
1971 "sync sample entries:%uD", entries); | 2042 "sync sample entries:%uD", entries); |
1972 | 2043 |
1978 atom = &trak->stss_atom_buf; | 2049 atom = &trak->stss_atom_buf; |
1979 atom->temporary = 1; | 2050 atom->temporary = 1; |
1980 atom->pos = atom_header; | 2051 atom->pos = atom_header; |
1981 atom->last = atom_table; | 2052 atom->last = atom_table; |
1982 | 2053 |
2054 if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) | |
2055 + entries * sizeof(uint32_t) > atom_data_size) | |
2056 { | |
2057 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2058 "\"%s\" mp4 stss atom too small", mp4->file.name.data); | |
2059 return NGX_ERROR; | |
2060 } | |
2061 | |
1983 atom_end = atom_table + entries * sizeof(uint32_t); | 2062 atom_end = atom_table + entries * sizeof(uint32_t); |
1984 | |
1985 if ((uint64_t) (atom_end - stss_atom->version) > atom_data_size) { | |
1986 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
1987 "\"%s\" mp4 stss atom too large", mp4->file.name.data); | |
1988 return NGX_ERROR; | |
1989 } | |
1990 | 2063 |
1991 data = &trak->stss_data_buf; | 2064 data = &trak->stss_data_buf; |
1992 data->temporary = 1; | 2065 data->temporary = 1; |
1993 data->pos = atom_table; | 2066 data->pos = atom_table; |
1994 data->last = atom_end; | 2067 data->last = atom_end; |
2108 | 2181 |
2109 atom_header = ngx_mp4_atom_header(mp4); | 2182 atom_header = ngx_mp4_atom_header(mp4); |
2110 ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header; | 2183 ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header; |
2111 ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's'); | 2184 ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's'); |
2112 | 2185 |
2186 if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) > atom_data_size) { | |
2187 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2188 "\"%s\" mp4 ctts atom too small", mp4->file.name.data); | |
2189 return NGX_ERROR; | |
2190 } | |
2191 | |
2113 entries = ngx_mp4_get_32value(ctts_atom->entries); | 2192 entries = ngx_mp4_get_32value(ctts_atom->entries); |
2114 | 2193 |
2115 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 2194 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
2116 "composition offset entries:%uD", entries); | 2195 "composition offset entries:%uD", entries); |
2117 | 2196 |
2123 atom = &trak->ctts_atom_buf; | 2202 atom = &trak->ctts_atom_buf; |
2124 atom->temporary = 1; | 2203 atom->temporary = 1; |
2125 atom->pos = atom_header; | 2204 atom->pos = atom_header; |
2126 atom->last = atom_table; | 2205 atom->last = atom_table; |
2127 | 2206 |
2207 if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) | |
2208 + entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size) | |
2209 { | |
2210 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2211 "\"%s\" mp4 ctts atom too small", mp4->file.name.data); | |
2212 return NGX_ERROR; | |
2213 } | |
2214 | |
2128 atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t); | 2215 atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t); |
2129 | |
2130 if ((uint64_t) (atom_end - ctts_atom->version) > atom_data_size) { | |
2131 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2132 "\"%s\" mp4 ctts atom too large", mp4->file.name.data); | |
2133 return NGX_ERROR; | |
2134 } | |
2135 | 2216 |
2136 data = &trak->ctts_data_buf; | 2217 data = &trak->ctts_data_buf; |
2137 data->temporary = 1; | 2218 data->temporary = 1; |
2138 data->pos = atom_table; | 2219 data->pos = atom_table; |
2139 data->last = atom_end; | 2220 data->last = atom_end; |
2241 | 2322 |
2242 atom_header = ngx_mp4_atom_header(mp4); | 2323 atom_header = ngx_mp4_atom_header(mp4); |
2243 stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header; | 2324 stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header; |
2244 ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c'); | 2325 ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c'); |
2245 | 2326 |
2327 if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) > atom_data_size) { | |
2328 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2329 "\"%s\" mp4 stsc atom too small", mp4->file.name.data); | |
2330 return NGX_ERROR; | |
2331 } | |
2332 | |
2246 entries = ngx_mp4_get_32value(stsc_atom->entries); | 2333 entries = ngx_mp4_get_32value(stsc_atom->entries); |
2247 | 2334 |
2248 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 2335 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
2249 "sample-to-chunk entries:%uD", entries); | 2336 "sample-to-chunk entries:%uD", entries); |
2250 | 2337 |
2338 if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) | |
2339 + entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size) | |
2340 { | |
2341 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2342 "\"%s\" mp4 stsc atom too small", mp4->file.name.data); | |
2343 return NGX_ERROR; | |
2344 } | |
2345 | |
2251 atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t); | 2346 atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t); |
2252 atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t); | 2347 atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t); |
2253 | |
2254 if ((uint64_t) (atom_end - stsc_atom->version) > atom_data_size) { | |
2255 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2256 "\"%s\" mp4 stsc atom too large", | |
2257 mp4->file.name.data); | |
2258 return NGX_ERROR; | |
2259 } | |
2260 | 2348 |
2261 trak = ngx_mp4_last_trak(mp4); | 2349 trak = ngx_mp4_last_trak(mp4); |
2262 trak->sample_to_chunk_entries = entries; | 2350 trak->sample_to_chunk_entries = entries; |
2263 | 2351 |
2264 atom = &trak->stsc_atom_buf; | 2352 atom = &trak->stsc_atom_buf; |
2303 data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf; | 2391 data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf; |
2304 | 2392 |
2305 if (data == NULL) { | 2393 if (data == NULL) { |
2306 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | 2394 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
2307 "no mp4 stsc atoms were found in \"%s\"", | 2395 "no mp4 stsc atoms were found in \"%s\"", |
2396 mp4->file.name.data); | |
2397 return NGX_ERROR; | |
2398 } | |
2399 | |
2400 if (trak->sample_to_chunk_entries == 0) { | |
2401 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2402 "zero number of entries in stsc atom in \"%s\"", | |
2308 mp4->file.name.data); | 2403 mp4->file.name.data); |
2309 return NGX_ERROR; | 2404 return NGX_ERROR; |
2310 } | 2405 } |
2311 | 2406 |
2312 start_sample = (uint32_t) trak->start_sample; | 2407 start_sample = (uint32_t) trak->start_sample; |
2448 | 2543 |
2449 atom_header = ngx_mp4_atom_header(mp4); | 2544 atom_header = ngx_mp4_atom_header(mp4); |
2450 stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header; | 2545 stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header; |
2451 ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z'); | 2546 ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z'); |
2452 | 2547 |
2548 if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) > atom_data_size) { | |
2549 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2550 "\"%s\" mp4 stsz atom too small", mp4->file.name.data); | |
2551 return NGX_ERROR; | |
2552 } | |
2553 | |
2453 size = ngx_mp4_get_32value(stsz_atom->uniform_size); | 2554 size = ngx_mp4_get_32value(stsz_atom->uniform_size); |
2454 entries = ngx_mp4_get_32value(stsz_atom->entries); | 2555 entries = ngx_mp4_get_32value(stsz_atom->entries); |
2455 | 2556 |
2456 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, | 2557 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, |
2457 "sample uniform size:%uD, entries:%uD", size, entries); | 2558 "sample uniform size:%uD, entries:%uD", size, entries); |
2467 atom->last = atom_table; | 2568 atom->last = atom_table; |
2468 | 2569 |
2469 trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom; | 2570 trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom; |
2470 | 2571 |
2471 if (size == 0) { | 2572 if (size == 0) { |
2472 atom_end = atom_table + entries * sizeof(uint32_t); | 2573 if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) |
2473 | 2574 + entries * sizeof(uint32_t) > atom_data_size) |
2474 if ((uint64_t) (atom_end - stsz_atom->version) > atom_data_size) { | 2575 { |
2475 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | 2576 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
2476 "\"%s\" mp4 stsz atom too large", | 2577 "\"%s\" mp4 stsz atom too small", |
2477 mp4->file.name.data); | 2578 mp4->file.name.data); |
2478 return NGX_ERROR; | 2579 return NGX_ERROR; |
2479 } | 2580 } |
2581 | |
2582 atom_end = atom_table + entries * sizeof(uint32_t); | |
2480 | 2583 |
2481 data = &trak->stsz_data_buf; | 2584 data = &trak->stsz_data_buf; |
2482 data->temporary = 1; | 2585 data->temporary = 1; |
2483 data->pos = atom_table; | 2586 data->pos = atom_table; |
2484 data->last = atom_end; | 2587 data->last = atom_end; |
2497 | 2600 |
2498 return NGX_OK; | 2601 return NGX_OK; |
2499 } | 2602 } |
2500 | 2603 |
2501 | 2604 |
2502 static void | 2605 static ngx_int_t |
2503 ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, | 2606 ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4, |
2504 ngx_http_mp4_trak_t *trak) | 2607 ngx_http_mp4_trak_t *trak) |
2505 { | 2608 { |
2506 size_t atom_size; | 2609 size_t atom_size; |
2507 uint32_t *pos, *end; | 2610 uint32_t *pos, *end; |
2518 "mp4 stsz atom update"); | 2621 "mp4 stsz atom update"); |
2519 | 2622 |
2520 data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf; | 2623 data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf; |
2521 | 2624 |
2522 if (data) { | 2625 if (data) { |
2626 if (trak->start_sample > trak->sample_sizes_entries) { | |
2627 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2628 "start time is out mp4 stsz samples in \"%s\"", | |
2629 mp4->file.name.data); | |
2630 return NGX_ERROR; | |
2631 } | |
2632 | |
2523 data->pos += trak->start_sample * sizeof(uint32_t); | 2633 data->pos += trak->start_sample * sizeof(uint32_t); |
2524 end = (uint32_t *) data->pos; | 2634 end = (uint32_t *) data->pos; |
2525 | 2635 |
2526 for (pos = end - trak->chunk_samples; pos < end; pos++) { | 2636 for (pos = end - trak->chunk_samples; pos < end; pos++) { |
2527 trak->chunk_samples_size += ngx_mp4_get_32value(pos); | 2637 trak->chunk_samples_size += ngx_mp4_get_32value(pos); |
2538 | 2648 |
2539 ngx_mp4_set_32value(stsz_atom->size, atom_size); | 2649 ngx_mp4_set_32value(stsz_atom->size, atom_size); |
2540 ngx_mp4_set_32value(stsz_atom->entries, | 2650 ngx_mp4_set_32value(stsz_atom->entries, |
2541 trak->sample_sizes_entries - trak->start_sample); | 2651 trak->sample_sizes_entries - trak->start_sample); |
2542 } | 2652 } |
2653 | |
2654 return NGX_OK; | |
2543 } | 2655 } |
2544 | 2656 |
2545 | 2657 |
2546 typedef struct { | 2658 typedef struct { |
2547 u_char size[4]; | 2659 u_char size[4]; |
2567 | 2679 |
2568 atom_header = ngx_mp4_atom_header(mp4); | 2680 atom_header = ngx_mp4_atom_header(mp4); |
2569 stco_atom = (ngx_mp4_stco_atom_t *) atom_header; | 2681 stco_atom = (ngx_mp4_stco_atom_t *) atom_header; |
2570 ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o'); | 2682 ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o'); |
2571 | 2683 |
2684 if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) > atom_data_size) { | |
2685 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2686 "\"%s\" mp4 stco atom too small", mp4->file.name.data); | |
2687 return NGX_ERROR; | |
2688 } | |
2689 | |
2572 entries = ngx_mp4_get_32value(stco_atom->entries); | 2690 entries = ngx_mp4_get_32value(stco_atom->entries); |
2573 | 2691 |
2574 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); | 2692 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); |
2693 | |
2694 if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) | |
2695 + entries * sizeof(uint32_t) > atom_data_size) | |
2696 { | |
2697 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2698 "\"%s\" mp4 stco atom too small", mp4->file.name.data); | |
2699 return NGX_ERROR; | |
2700 } | |
2575 | 2701 |
2576 atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t); | 2702 atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t); |
2577 atom_end = atom_table + entries * sizeof(uint32_t); | 2703 atom_end = atom_table + entries * sizeof(uint32_t); |
2578 | |
2579 if ((uint64_t) (atom_end - stco_atom->version) > atom_data_size) { | |
2580 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2581 "\"%s\" mp4 stco atom too large", mp4->file.name.data); | |
2582 return NGX_ERROR; | |
2583 } | |
2584 | 2704 |
2585 trak = ngx_mp4_last_trak(mp4); | 2705 trak = ngx_mp4_last_trak(mp4); |
2586 trak->chunks = entries; | 2706 trak->chunks = entries; |
2587 | 2707 |
2588 atom = &trak->stco_atom_buf; | 2708 atom = &trak->stco_atom_buf; |
2624 data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf; | 2744 data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf; |
2625 | 2745 |
2626 if (data == NULL) { | 2746 if (data == NULL) { |
2627 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | 2747 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, |
2628 "no mp4 stco atoms were found in \"%s\"", | 2748 "no mp4 stco atoms were found in \"%s\"", |
2749 mp4->file.name.data); | |
2750 return NGX_ERROR; | |
2751 } | |
2752 | |
2753 if (trak->start_chunk > trak->chunks) { | |
2754 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2755 "start time is out mp4 stco chunks in \"%s\"", | |
2629 mp4->file.name.data); | 2756 mp4->file.name.data); |
2630 return NGX_ERROR; | 2757 return NGX_ERROR; |
2631 } | 2758 } |
2632 | 2759 |
2633 data->pos += trak->start_chunk * sizeof(uint32_t); | 2760 data->pos += trak->start_chunk * sizeof(uint32_t); |
2703 | 2830 |
2704 atom_header = ngx_mp4_atom_header(mp4); | 2831 atom_header = ngx_mp4_atom_header(mp4); |
2705 co64_atom = (ngx_mp4_co64_atom_t *) atom_header; | 2832 co64_atom = (ngx_mp4_co64_atom_t *) atom_header; |
2706 ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4'); | 2833 ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4'); |
2707 | 2834 |
2835 if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) > atom_data_size) { | |
2836 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2837 "\"%s\" mp4 co64 atom too small", mp4->file.name.data); | |
2838 return NGX_ERROR; | |
2839 } | |
2840 | |
2708 entries = ngx_mp4_get_32value(co64_atom->entries); | 2841 entries = ngx_mp4_get_32value(co64_atom->entries); |
2709 | 2842 |
2710 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); | 2843 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries); |
2844 | |
2845 if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) | |
2846 + entries * sizeof(uint64_t) > atom_data_size) | |
2847 { | |
2848 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2849 "\"%s\" mp4 co64 atom too small", mp4->file.name.data); | |
2850 return NGX_ERROR; | |
2851 } | |
2711 | 2852 |
2712 atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t); | 2853 atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t); |
2713 atom_end = atom_table + entries * sizeof(uint64_t); | 2854 atom_end = atom_table + entries * sizeof(uint64_t); |
2714 | |
2715 if ((uint64_t) (atom_end - co64_atom->version) > atom_data_size) { | |
2716 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2717 "\"%s\" mp4 co64 atom too large", mp4->file.name.data); | |
2718 return NGX_ERROR; | |
2719 } | |
2720 | 2855 |
2721 trak = ngx_mp4_last_trak(mp4); | 2856 trak = ngx_mp4_last_trak(mp4); |
2722 trak->chunks = entries; | 2857 trak->chunks = entries; |
2723 | 2858 |
2724 atom = &trak->co64_atom_buf; | 2859 atom = &trak->co64_atom_buf; |
2764 "no mp4 co64 atoms were found in \"%s\"", | 2899 "no mp4 co64 atoms were found in \"%s\"", |
2765 mp4->file.name.data); | 2900 mp4->file.name.data); |
2766 return NGX_ERROR; | 2901 return NGX_ERROR; |
2767 } | 2902 } |
2768 | 2903 |
2904 if (trak->start_chunk > trak->chunks) { | |
2905 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, | |
2906 "start time is out mp4 co64 chunks in \"%s\"", | |
2907 mp4->file.name.data); | |
2908 return NGX_ERROR; | |
2909 } | |
2910 | |
2769 data->pos += trak->start_chunk * sizeof(uint64_t); | 2911 data->pos += trak->start_chunk * sizeof(uint64_t); |
2770 atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos); | 2912 atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos); |
2771 trak->size += atom_size; | 2913 trak->size += atom_size; |
2772 | 2914 |
2773 trak->start_offset = ngx_mp4_get_64value(data->pos); | 2915 trak->start_offset = ngx_mp4_get_64value(data->pos); |