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);