* tjoppen/proper_mxf_track_linking: mxfdec: Don't parse slices or DeltaEntryArrays mxfdec: Remove dead/useless code mxfdec: Hybrid demuxing/seeking solution mxfdec: Add mxf_edit_unit_absolute_offset() mxfdec: Replace zero IndexDurations with st->duration mxfdec: Add "fake" index to MXFIndexTable to assist seeking mxfdec: Add MXFIndexTables mxfdec: Move mxf_read_packet*() near the bottom of the file
Unified · Split
| @@ -148,17 +148,12 @@ typedef struct { · 147 unmodified lines | ||
| 148 | 148 | int edit_unit_byte_count; |
| 149 | 149 | int index_sid; |
| 150 | 150 | int body_sid; |
| 151 | − int slice_count; | |
| 152 | 151 | AVRational index_edit_rate; |
| 153 | 152 | uint64_t index_start_position; |
| 154 | 153 | uint64_t index_duration; |
| 155 | − int *slice; | |
| 156 | − int *element_delta; | |
| 157 | − int nb_delta_entries; | |
| 158 | 154 | int8_t *temporal_offset_entries; |
| 159 | 155 | int *flag_entries; |
| 160 | 156 | uint64_t *stream_offset_entries; |
| 161 | − uint32_t **slice_offset_entries; | |
| 162 | 157 | int nb_index_entries; |
| 163 | 158 | } MXFIndexTableSegment; |
| 164 | 159 | |
| @@ -177,6 +172,18 @@ typedef struct { · 12 unmodified lines | ||
| 177 | 172 | enum MXFMetadataSetType type; |
| 178 | 173 | } MXFMetadataSet; |
| 179 | 174 | |
| 175 | +/* decoded index table */ | |
| 176 | +typedef struct { | |
| 177 | + int index_sid; | |
| 178 | + int body_sid; | |
| 179 | + int nb_ptses; /* number of PTSes or total duration of index */ | |
| 180 | + int64_t first_dts; /* DTS = EditUnit + first_dts */ | |
| 181 | + int64_t *ptses; /* maps EditUnit -> PTS */ | |
| 182 | + int nb_segments; | |
| 183 | + MXFIndexTableSegment **segments; /* sorted by IndexStartPosition */ | |
| 184 | + AVIndexEntry *fake_index; /* used for calling ff_index_search_timestamp() */ | |
| 185 | +} MXFIndexTable; | |
| 186 | + | |
| 180 | 187 | typedef struct { |
| 181 | 188 | MXFPartition *partitions; |
| 182 | 189 | unsigned partitions_count; |
| @@ -198,12 +205,8 @@ typedef struct { · 15 unmodified lines | ||
| 198 | 205 | int64_t last_forward_tell; |
| 199 | 206 | int last_forward_partition; |
| 200 | 207 | int current_edit_unit; |
| 201 | − int current_stream; | |
| 202 | − int d10; | |
| 203 | − int broken_index; | |
| 204 | − int64_t first_dts; /* DTS = EditUnit + first_dts */ | |
| 205 | − int64_t *ptses; /* maps EditUnit -> PTS */ | |
| 206 | − int nb_ptses; | |
| 208 | + int nb_index_tables; | |
| 209 | + MXFIndexTable *index_tables; | |
| 207 | 210 | } MXFContext; |
| 208 | 211 | |
| 209 | 212 | enum MXFWrappingScheme { |
| @@ -380,117 +383,6 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv · 170 unmodified lines | ||
| 380 | 383 | return 0; |
| 381 | 384 | } |
| 382 | 385 | |
| 383 | −static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) | |
| 384 | −{ | |
| 385 | − KLVPacket klv; | |
| 386 | − | |
| 387 | − while (!url_feof(s->pb)) { | |
| 388 | − if (klv_read_packet(&klv, s->pb) < 0) | |
| 389 | − return -1; | |
| 390 | − PRINT_KEY(s, "read packet", klv.key); | |
| 391 | − av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); | |
| 392 | − if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { | |
| 393 | − int res = mxf_decrypt_triplet(s, pkt, &klv); | |
| 394 | − if (res < 0) { | |
| 395 | − av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); | |
| 396 | − return -1; | |
| 397 | − } | |
| 398 | − return 0; | |
| 399 | − } | |
| 400 | − if (IS_KLV_KEY(klv.key, mxf_essence_element_key) || | |
| 401 | − IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) { | |
| 402 | − int index = mxf_get_stream_index(s, &klv); | |
| 403 | − if (index < 0) { | |
| 404 | − av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); | |
| 405 | − goto skip; | |
| 406 | − } | |
| 407 | − if (s->streams[index]->discard == AVDISCARD_ALL) | |
| 408 | − goto skip; | |
| 409 | − /* check for 8 channels AES3 element */ | |
| 410 | − if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) { | |
| 411 | − if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) { | |
| 412 | − av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n"); | |
| 413 | − return -1; | |
| 414 | − } | |
| 415 | − } else { | |
| 416 | − int ret = av_get_packet(s->pb, pkt, klv.length); | |
| 417 | − if (ret < 0) | |
| 418 | − return ret; | |
| 419 | − } | |
| 420 | − pkt->stream_index = index; | |
| 421 | − pkt->pos = klv.offset; | |
| 422 | − return 0; | |
| 423 | − } else | |
| 424 | − skip: | |
| 425 | − avio_skip(s->pb, klv.length); | |
| 426 | − } | |
| 427 | − return AVERROR_EOF; | |
| 428 | −} | |
| 429 | − | |
| 430 | −static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 431 | −{ | |
| 432 | − MXFContext *mxf = s->priv_data; | |
| 433 | − AVIndexEntry *e; | |
| 434 | − int ret; | |
| 435 | − int64_t ret64; | |
| 436 | − KLVPacket klv; | |
| 437 | − AVStream *st; | |
| 438 | − | |
| 439 | − /* TODO: better logic for this? | |
| 440 | − * only files that lack all index segments prior to the essence need this */ | |
| 441 | − if (!s->pb->seekable && mxf->op != OPAtom || mxf->d10 || mxf->broken_index) | |
| 442 | − return mxf_read_packet_old(s, pkt); | |
| 443 | − | |
| 444 | − if (mxf->current_stream >= s->nb_streams) { | |
| 445 | − mxf->current_edit_unit++; | |
| 446 | − mxf->current_stream = 0; | |
| 447 | − } | |
| 448 | − | |
| 449 | − st = s->streams[mxf->current_stream]; | |
| 450 | − | |
| 451 | − if (mxf->current_edit_unit >= st->nb_index_entries) | |
| 452 | − return AVERROR_EOF; | |
| 453 | − | |
| 454 | − e = &st->index_entries[mxf->current_edit_unit]; | |
| 455 | − | |
| 456 | − if ((ret64 = avio_seek(s->pb, e->pos, SEEK_SET)) < 0) | |
| 457 | − return ret64; | |
| 458 | − | |
| 459 | − if (mxf->op == OPAtom) { | |
| 460 | − /* OPAtom - no KL, just essence */ | |
| 461 | − if ((ret = av_get_packet(s->pb, pkt, e->size)) != e->size) | |
| 462 | − return ret < 0 ? ret : AVERROR_EOF; | |
| 463 | − } else { | |
| 464 | − /* read KL, read L bytes of essence */ | |
| 465 | − if ((ret = klv_read_packet(&klv, s->pb)) < 0) | |
| 466 | − return ret; | |
| 467 | − | |
| 468 | − /* untested, but looks OK */ | |
| 469 | − if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { | |
| 470 | − int res = mxf_decrypt_triplet(s, pkt, &klv); | |
| 471 | − if (res < 0) { | |
| 472 | − av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); | |
| 473 | − return -1; | |
| 474 | − } | |
| 475 | − return 0; | |
| 476 | − } | |
| 477 | − | |
| 478 | − if ((ret = av_get_packet(s->pb, pkt, klv.length)) != klv.length) | |
| 479 | − return ret < 0 ? ret : AVERROR_EOF; | |
| 480 | − | |
| 481 | − pkt->pos = e->pos; | |
| 482 | − } | |
| 483 | − | |
| 484 | − if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && mxf->ptses && mxf->current_edit_unit < mxf->nb_ptses) { | |
| 485 | − pkt->dts = mxf->current_edit_unit + mxf->first_dts; | |
| 486 | − pkt->pts = mxf->ptses[mxf->current_edit_unit]; | |
| 487 | − } | |
| 488 | − | |
| 489 | − pkt->stream_index = mxf->current_stream++; | |
| 490 | − | |
| 491 | − return 0; | |
| 492 | −} | |
| 493 | − | |
| 494 | 386 | static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) |
| 495 | 387 | { |
| 496 | 388 | MXFContext *mxf = arg; |
| @@ -768,25 +660,6 @@ static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size · 271 unmodified lines | ||
| 768 | 660 | return 0; |
| 769 | 661 | } |
| 770 | 662 | |
| 771 | −static int mxf_read_delta_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment) | |
| 772 | −{ | |
| 773 | − int i, length; | |
| 774 | − | |
| 775 | − segment->nb_delta_entries = avio_rb32(pb); | |
| 776 | − length = avio_rb32(pb); | |
| 777 | − | |
| 778 | − if (!(segment->slice = av_calloc(segment->nb_delta_entries, sizeof(*segment->slice))) || | |
| 779 | − !(segment->element_delta = av_calloc(segment->nb_delta_entries, sizeof(*segment->element_delta)))) | |
| 780 | − return AVERROR(ENOMEM); | |
| 781 | − | |
| 782 | − for (i = 0; i < segment->nb_delta_entries; i++) { | |
| 783 | − avio_r8(pb); /* PosTableIndex */ | |
| 784 | − segment->slice[i] = avio_r8(pb); | |
| 785 | − segment->element_delta[i] = avio_rb32(pb); | |
| 786 | − } | |
| 787 | − return 0; | |
| 788 | −} | |
| 789 | − | |
| 790 | 663 | static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment) |
| 791 | 664 | { |
| 792 | 665 | int i, j, length; |
| @@ -799,24 +672,12 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 6 unmodified lines | ||
| 799 | 672 | !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) |
| 800 | 673 | return AVERROR(ENOMEM); |
| 801 | 674 | |
| 802 | − if (segment->slice_count && | |
| 803 | − !(segment->slice_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->slice_offset_entries)))) | |
| 804 | − return AVERROR(ENOMEM); | |
| 805 | − | |
| 806 | 675 | for (i = 0; i < segment->nb_index_entries; i++) { |
| 807 | 676 | segment->temporal_offset_entries[i] = avio_r8(pb); |
| 808 | 677 | avio_r8(pb); /* KeyFrameOffset */ |
| 809 | 678 | segment->flag_entries[i] = avio_r8(pb); |
| 810 | 679 | segment->stream_offset_entries[i] = avio_rb64(pb); |
| 811 | − if (segment->slice_count) { | |
| 812 | − if (!(segment->slice_offset_entries[i] = av_calloc(segment->slice_count, sizeof(**segment->slice_offset_entries)))) | |
| 813 | − return AVERROR(ENOMEM); | |
| 814 | − | |
| 815 | − for (j = 0; j < segment->slice_count; j++) | |
| 816 | − segment->slice_offset_entries[i][j] = avio_rb32(pb); | |
| 817 | − } | |
| 818 | − | |
| 819 | − avio_skip(pb, length - 11 - 4 * segment->slice_count); | |
| 680 | + avio_skip(pb, length - 11); | |
| 820 | 681 | } |
| 821 | 682 | return 0; |
| 822 | 683 | } |
| @@ -837,13 +698,6 @@ static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int · 14 unmodified lines | ||
| 837 | 698 | segment->body_sid = avio_rb32(pb); |
| 838 | 699 | av_dlog(NULL, "BodySID %d\n", segment->body_sid); |
| 839 | 700 | break; |
| 840 | − case 0x3F08: | |
| 841 | − segment->slice_count = avio_r8(pb); | |
| 842 | − av_dlog(NULL, "SliceCount %d\n", segment->slice_count); | |
| 843 | − break; | |
| 844 | − case 0x3F09: | |
| 845 | − av_dlog(NULL, "DeltaEntryArray found\n"); | |
| 846 | − return mxf_read_delta_entry_array(pb, segment); | |
| 847 | 701 | case 0x3F0A: |
| 848 | 702 | av_dlog(NULL, "IndexEntryArray found\n"); |
| 849 | 703 | return mxf_read_index_entry_array(pb, segment); |
| @@ -1001,8 +855,6 @@ static const MXFCodecUL mxf_sound_essence_container_uls[] = { · 151 unmodified lines | ||
| 1001 | 855 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, |
| 1002 | 856 | }; |
| 1003 | 857 | |
| 1004 | −static UID mxf_d10_ul = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }; | |
| 1005 | − | |
| 1006 | 858 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) |
| 1007 | 859 | { |
| 1008 | 860 | int i, j, nb_segments = 0; |
| @@ -1089,9 +941,9 @@ static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t of · 80 unmodified lines | ||
| 1089 | 941 | } |
| 1090 | 942 | |
| 1091 | 943 | /** |
| 1092 | − * Returns the length of the essence container with given BodySID, or zero if unknown | |
| 944 | + * Returns the end position of the essence container with given BodySID, or zero if unknown | |
| 1093 | 945 | */ |
| 1094 | −static int64_t mxf_essence_container_length(MXFContext *mxf, int body_sid) | |
| 946 | +static int64_t mxf_essence_container_end(MXFContext *mxf, int body_sid) | |
| 1095 | 947 | { |
| 1096 | 948 | int x; |
| 1097 | 949 | int64_t ret = 0; |
| @@ -1105,167 +957,90 @@ static int64_t mxf_essence_container_length(MXFContext *mxf, int body_sid) · 7 unmodified lines | ||
| 1105 | 957 | if (!p->essence_length) |
| 1106 | 958 | return 0; |
| 1107 | 959 | |
| 1108 | − ret += p->essence_length; | |
| 960 | + ret = p->essence_offset + p->essence_length; | |
| 1109 | 961 | } |
| 1110 | 962 | |
| 1111 | 963 | return ret; |
| 1112 | 964 | } |
| 1113 | 965 | |
| 1114 | −static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st, MXFIndexTableSegment **sorted_segments, int nb_sorted_segments) | |
| 966 | +/* EditUnit -> absolute offset */ | |
| 967 | +static int mxf_edit_unit_absolute_offset(MXFContext *mxf, MXFIndexTable *index_table, int64_t edit_unit, int64_t *edit_unit_out, int64_t *offset_out, int nag) | |
| 1115 | 968 | { |
| 1116 | − int64_t accumulated_offset = 0; | |
| 1117 | − int j, k, l, ret; | |
| 1118 | − int n_delta = track_id - 1; /* TrackID = 1-based stream index */ | |
| 1119 | − | |
| 1120 | − if (track_id < 1) { | |
| 1121 | − av_log(mxf->fc, AV_LOG_ERROR, "TrackID not positive: %i\n", track_id); | |
| 1122 | − return AVERROR_INVALIDDATA; | |
| 1123 | − } | |
| 1124 | − | |
| 1125 | − for (j = 0; j < nb_sorted_segments; j++) { | |
| 1126 | − int duration, sample_duration = 1, last_sample_size = 0; | |
| 1127 | − int64_t segment_size; | |
| 1128 | − MXFIndexTableSegment *tableseg = sorted_segments[j]; | |
| 1129 | − int index_delta = 1, last_size_unknown = 0; | |
| 1130 | − int64_t last_pos = 0; | |
| 969 | + int i; | |
| 970 | + int offset_temp = 0; | |
| 1131 | 971 | |
| 1132 | − /* reset accumulated_offset on BodySID change */ | |
| 1133 | − if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid) | |
| 1134 | − accumulated_offset = 0; | |
| 972 | + for (i = 0; i < index_table->nb_segments; i++) { | |
| 973 | + MXFIndexTableSegment *s = index_table->segments[i]; | |
| 1135 | 974 | |
| 1136 | − if (tableseg->nb_index_entries == 2 * tableseg->index_duration + 1) { | |
| 1137 | − /* Avid index - duplicate entries and total size as last entry */ | |
| 1138 | − index_delta = 2; | |
| 1139 | − } | |
| 975 | + edit_unit = FFMAX(edit_unit, s->index_start_position); /* clamp if trying to seek before start */ | |
| 1140 | 976 | |
| 1141 | − if (n_delta >= tableseg->nb_delta_entries && st->index != 0) | |
| 1142 | − continue; | |
| 1143 | − duration = tableseg->index_duration > 0 ? tableseg->index_duration : | |
| 1144 | − st->duration - st->nb_index_entries; | |
| 1145 | − segment_size = tableseg->edit_unit_byte_count * duration; | |
| 1146 | − /* check small EditUnitByteCount for audio */ | |
| 1147 | − if (tableseg->edit_unit_byte_count && tableseg->edit_unit_byte_count < 32 | |
| 1148 | − && !tableseg->index_duration) { | |
| 1149 | − /* duration might be prime relative to the new sample_duration, | |
| 1150 | − * which means we need to handle the last frame differently */ | |
| 1151 | − sample_duration = 8192; | |
| 1152 | − last_sample_size = (duration % sample_duration) * tableseg->edit_unit_byte_count; | |
| 1153 | − tableseg->edit_unit_byte_count *= sample_duration; | |
| 1154 | − duration /= sample_duration; | |
| 1155 | − if (last_sample_size) duration++; | |
| 1156 | − } | |
| 977 | + if (edit_unit < s->index_start_position + s->index_duration) { | |
| 978 | + int64_t index = edit_unit - s->index_start_position; | |
| 1157 | 979 | |
| 1158 | − if (duration <= 0) { | |
| 1159 | − av_log(mxf->fc, AV_LOG_WARNING, "0 duration in index for stream %i\n", st->index); | |
| 1160 | − mxf->broken_index = 1; | |
| 1161 | − return 0; | |
| 1162 | − } | |
| 980 | + if (s->edit_unit_byte_count) | |
| 981 | + offset_temp += s->edit_unit_byte_count * index; | |
| 982 | + else if (s->nb_index_entries) { | |
| 983 | + if (s->nb_index_entries == 2 * s->index_duration + 1) | |
| 984 | + index *= 2; /* Avid index */ | |
| 1163 | 985 | |
| 1164 | − for (k = l = 0; k < duration; k++, l += index_delta) { | |
| 1165 | − int64_t pos; | |
| 1166 | − int size, flags = 0; | |
| 1167 | − | |
| 1168 | − if (l < tableseg->nb_index_entries) { | |
| 1169 | − pos = tableseg->stream_offset_entries[l]; | |
| 1170 | − if (n_delta < tableseg->nb_delta_entries) { | |
| 1171 | − if (n_delta < tableseg->nb_delta_entries - 1) { | |
| 1172 | − size = | |
| 1173 | − tableseg->slice_offset_entries[l][tableseg->slice[n_delta+1]-1] + | |
| 1174 | − tableseg->element_delta[n_delta+1] - | |
| 1175 | − tableseg->element_delta[n_delta]; | |
| 1176 | − if (tableseg->slice[n_delta] > 0) | |
| 1177 | − size -= tableseg->slice_offset_entries[l][tableseg->slice[n_delta]-1]; | |
| 1178 | − } else if (l < tableseg->nb_index_entries - 1) { | |
| 1179 | − size = tableseg->stream_offset_entries[l+1] - | |
| 1180 | − tableseg->stream_offset_entries[l] - | |
| 1181 | − tableseg->slice_offset_entries[l][tableseg->slice[tableseg->nb_delta_entries-1]-1] - | |
| 1182 | − tableseg->element_delta[tableseg->nb_delta_entries-1]; | |
| 1183 | − } else | |
| 1184 | − size = 0; | |
| 1185 | − if (tableseg->slice[n_delta] > 0) | |
| 1186 | − pos += tableseg->slice_offset_entries[l][tableseg->slice[n_delta]-1]; | |
| 1187 | − pos += tableseg->element_delta[n_delta]; | |
| 1188 | − } else | |
| 1189 | − size = 0; | |
| 1190 | − flags = !(tableseg->flag_entries[l] & 0x30) ? AVINDEX_KEYFRAME : 0; | |
| 1191 | − } else { | |
| 1192 | − pos = (int64_t)k * tableseg->edit_unit_byte_count + accumulated_offset; | |
| 1193 | − if (n_delta < tableseg->nb_delta_entries - 1) | |
| 1194 | − size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta]; | |
| 1195 | − else { | |
| 1196 | − /* use smaller size for last sample if we should */ | |
| 1197 | − if (last_sample_size && k == duration - 1) | |
| 1198 | − size = last_sample_size; | |
| 1199 | − else | |
| 1200 | − size = tableseg->edit_unit_byte_count; | |
| 1201 | − if (tableseg->nb_delta_entries) | |
| 1202 | − size -= tableseg->element_delta[tableseg->nb_delta_entries-1]; | |
| 986 | + if (index < 0 || index > s->nb_index_entries) { | |
| 987 | + av_log(mxf->fc, AV_LOG_ERROR, "IndexSID %i segment at %"PRId64" IndexEntryArray too small\n", | |
| 988 | + index_table->index_sid, s->index_start_position); | |
| 989 | + return AVERROR_INVALIDDATA; | |
| 1203 | 990 | } |
| 1204 | − if (n_delta < tableseg->nb_delta_entries) | |
| 1205 | − pos += tableseg->element_delta[n_delta]; | |
| 1206 | − flags = AVINDEX_KEYFRAME; | |
| 1207 | − } | |
| 1208 | − | |
| 1209 | − if (last_size_unknown) | |
| 1210 | − st->index_entries[st->nb_index_entries-1].size = pos - last_pos; | |
| 1211 | 991 | |
| 1212 | − last_size_unknown = size == 0; | |
| 1213 | − last_pos = pos; | |
| 1214 | − | |
| 1215 | − if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos, &pos) < 0) { | |
| 1216 | − /* probably partial file - no point going further for this stream */ | |
| 1217 | − break; | |
| 992 | + offset_temp = s->stream_offset_entries[index]; | |
| 993 | + } else { | |
| 994 | + av_log(mxf->fc, AV_LOG_ERROR, "IndexSID %i segment at %"PRId64" missing EditUnitByteCount and IndexEntryArray\n", | |
| 995 | + index_table->index_sid, s->index_start_position); | |
| 996 | + return AVERROR_INVALIDDATA; | |
| 1218 | 997 | } |
| 1219 | 998 | |
| 1220 | − av_dlog(mxf->fc, "Stream %d IndexEntry %d TrackID %d Offset %"PRIx64" Timestamp %"PRId64"\n", | |
| 1221 | − st->index, st->nb_index_entries, track_id, pos, sample_duration * st->nb_index_entries); | |
| 1222 | − | |
| 1223 | − if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0) | |
| 1224 | − return ret; | |
| 1225 | − } | |
| 999 | + if (edit_unit_out) | |
| 1000 | + *edit_unit_out = edit_unit; | |
| 1226 | 1001 | |
| 1227 | − if (last_size_unknown) { | |
| 1228 | − int64_t ecl = mxf_essence_container_length(mxf, tableseg->body_sid); | |
| 1229 | − | |
| 1230 | − if (ecl > 0) | |
| 1231 | − st->index_entries[st->nb_index_entries-1].size = ecl - last_pos; | |
| 1002 | + return mxf_absolute_bodysid_offset(mxf, index_table->body_sid, offset_temp, offset_out); | |
| 1003 | + } else { | |
| 1004 | + /* EditUnitByteCount == 0 for VBR indexes, which is fine since they use explicit StreamOffsets */ | |
| 1005 | + offset_temp += s->edit_unit_byte_count * s->index_duration; | |
| 1232 | 1006 | } |
| 1233 | − | |
| 1234 | − accumulated_offset += segment_size; | |
| 1235 | 1007 | } |
| 1236 | 1008 | |
| 1237 | − return 0; | |
| 1009 | + if (nag) | |
| 1010 | + av_log(mxf->fc, AV_LOG_ERROR, "failed to map EditUnit %"PRId64" in IndexSID %i to an offset\n", edit_unit, index_table->index_sid); | |
| 1011 | + | |
| 1012 | + return AVERROR_INVALIDDATA; | |
| 1238 | 1013 | } |
| 1239 | 1014 | |
| 1240 | −static int mxf_compute_ptses(MXFContext *mxf, MXFIndexTableSegment **sorted_segments, int nb_sorted_segments) | |
| 1015 | +static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_table) | |
| 1241 | 1016 | { |
| 1242 | − int ret, i, j, x; | |
| 1017 | + int i, j, x; | |
| 1243 | 1018 | int8_t max_temporal_offset = -128; |
| 1244 | 1019 | |
| 1245 | 1020 | /* first compute how many entries we have */ |
| 1246 | − for (i = 0; i < nb_sorted_segments; i++) { | |
| 1247 | − MXFIndexTableSegment *s = sorted_segments[i]; | |
| 1021 | + for (i = 0; i < index_table->nb_segments; i++) { | |
| 1022 | + MXFIndexTableSegment *s = index_table->segments[i]; | |
| 1248 | 1023 | |
| 1249 | 1024 | if (!s->nb_index_entries) |
| 1250 | 1025 | return 0; /* no TemporalOffsets */ |
| 1251 | 1026 | |
| 1252 | − if (s->nb_index_entries == 2 * s->index_duration + 1) | |
| 1253 | − mxf->nb_ptses += s->index_duration; /* Avid index */ | |
| 1254 | − else | |
| 1255 | − mxf->nb_ptses += s->nb_index_entries; | |
| 1027 | + index_table->nb_ptses += s->index_duration; | |
| 1256 | 1028 | } |
| 1257 | 1029 | |
| 1258 | 1030 | /* paranoid check */ |
| 1259 | − if (mxf->nb_ptses <= 0) | |
| 1031 | + if (index_table->nb_ptses <= 0) | |
| 1260 | 1032 | return 0; |
| 1261 | 1033 | |
| 1262 | − if (!(mxf->ptses = av_calloc(mxf->nb_ptses, sizeof(int64_t)))) | |
| 1034 | + if (!(index_table->ptses = av_calloc(index_table->nb_ptses, sizeof(int64_t))) || | |
| 1035 | + !(index_table->fake_index = av_calloc(index_table->nb_ptses, sizeof(AVIndexEntry)))) { | |
| 1036 | + av_freep(&index_table->ptses); | |
| 1263 | 1037 | return AVERROR(ENOMEM); |
| 1038 | + } | |
| 1264 | 1039 | |
| 1265 | 1040 | /* we may have a few bad TemporalOffsets |
| 1266 | 1041 | * make sure the corresponding PTSes don't have the bogus value 0 */ |
| 1267 | − for (x = 0; x < mxf->nb_ptses; x++) | |
| 1268 | − mxf->ptses[x] = AV_NOPTS_VALUE; | |
| 1042 | + for (x = 0; x < index_table->nb_ptses; x++) | |
| 1043 | + index_table->ptses[x] = AV_NOPTS_VALUE; | |
| 1269 | 1044 | |
| 1270 | 1045 | /** |
| 1271 | 1046 | * We have this: |
| @@ -1294,8 +1069,8 @@ static int mxf_compute_ptses(MXFContext *mxf, MXFIndexTableSegment **sorted_segm · 22 unmodified lines | ||
| 1294 | 1069 | * then settings mxf->first_dts = -max(TemporalOffset[x]). |
| 1295 | 1070 | * The latter makes DTS <= PTS. |
| 1296 | 1071 | */ |
| 1297 | − for (i = x = 0; i < nb_sorted_segments; i++) { | |
| 1298 | − MXFIndexTableSegment *s = sorted_segments[i]; | |
| 1072 | + for (i = x = 0; i < index_table->nb_segments; i++) { | |
| 1073 | + MXFIndexTableSegment *s = index_table->segments[i]; | |
| 1299 | 1074 | int index_delta = 1; |
| 1300 | 1075 | |
| 1301 | 1076 | if (s->nb_index_entries == 2 * s->index_duration + 1) |
| @@ -1305,29 +1080,121 @@ static int mxf_compute_ptses(MXFContext *mxf, MXFIndexTableSegment **sorted_segm · 3 unmodified lines | ||
| 1305 | 1080 | int offset = s->temporal_offset_entries[j] / index_delta; |
| 1306 | 1081 | int index = x + offset; |
| 1307 | 1082 | |
| 1308 | − if (index < 0 || index >= mxf->nb_ptses) { | |
| 1083 | + index_table->fake_index[x].timestamp = x; | |
| 1084 | + index_table->fake_index[x].flags = !(s->flag_entries[j] & 0x30) ? AVINDEX_KEYFRAME : 0; | |
| 1085 | + | |
| 1086 | + if (index < 0 || index >= index_table->nb_ptses) { | |
| 1309 | 1087 | av_log(mxf->fc, AV_LOG_ERROR, |
| 1310 | 1088 | "index entry %i + TemporalOffset %i = %i, which is out of bounds\n", |
| 1311 | 1089 | x, offset, index); |
| 1312 | 1090 | continue; |
| 1313 | 1091 | } |
| 1314 | 1092 | |
| 1315 | − mxf->ptses[index] = x; | |
| 1093 | + index_table->ptses[index] = x; | |
| 1316 | 1094 | max_temporal_offset = FFMAX(max_temporal_offset, offset); |
| 1317 | 1095 | } |
| 1318 | 1096 | } |
| 1319 | 1097 | |
| 1320 | − mxf->first_dts = -max_temporal_offset; | |
| 1098 | + index_table->first_dts = -max_temporal_offset; | |
| 1321 | 1099 | |
| 1322 | 1100 | return 0; |
| 1323 | 1101 | } |
| 1324 | 1102 | |
| 1103 | +/** | |
| 1104 | + * Sorts and collects index table segments into index tables. | |
| 1105 | + * Also computes PTSes if possible. | |
| 1106 | + */ | |
| 1107 | +static int mxf_compute_index_tables(MXFContext *mxf) | |
| 1108 | +{ | |
| 1109 | + int i, j, k, ret, nb_sorted_segments; | |
| 1110 | + MXFIndexTableSegment **sorted_segments = NULL; | |
| 1111 | + | |
| 1112 | + if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments)) || | |
| 1113 | + nb_sorted_segments <= 0) { | |
| 1114 | + av_log(mxf->fc, AV_LOG_WARNING, "broken or empty index\n"); | |
| 1115 | + return 0; | |
| 1116 | + } | |
| 1117 | + | |
| 1118 | + /* sanity check and count unique BodySIDs/IndexSIDs */ | |
| 1119 | + for (i = 0; i < nb_sorted_segments; i++) { | |
| 1120 | + if (i == 0 || sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid) | |
| 1121 | + mxf->nb_index_tables++; | |
| 1122 | + else if (sorted_segments[i-1]->body_sid != sorted_segments[i]->body_sid) { | |
| 1123 | + av_log(mxf->fc, AV_LOG_ERROR, "found inconsistent BodySID\n"); | |
| 1124 | + ret = AVERROR_INVALIDDATA; | |
| 1125 | + goto finish_decoding_index; | |
| 1126 | + } | |
| 1127 | + } | |
| 1128 | + | |
| 1129 | + if (!(mxf->index_tables = av_calloc(mxf->nb_index_tables, sizeof(MXFIndexTable)))) { | |
| 1130 | + av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n"); | |
| 1131 | + ret = AVERROR(ENOMEM); | |
| 1132 | + goto finish_decoding_index; | |
| 1133 | + } | |
| 1134 | + | |
| 1135 | + /* distribute sorted segments to index tables */ | |
| 1136 | + for (i = j = 0; i < nb_sorted_segments; i++) { | |
| 1137 | + if (i != 0 && sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid) { | |
| 1138 | + /* next IndexSID */ | |
| 1139 | + j++; | |
| 1140 | + } | |
| 1141 | + | |
| 1142 | + mxf->index_tables[j].nb_segments++; | |
| 1143 | + } | |
| 1144 | + | |
| 1145 | + for (i = j = 0; j < mxf->nb_index_tables; i += mxf->index_tables[j++].nb_segments) { | |
| 1146 | + MXFIndexTable *t = &mxf->index_tables[j]; | |
| 1147 | + | |
| 1148 | + if (!(t->segments = av_calloc(t->nb_segments, sizeof(MXFIndexTableSegment*)))) { | |
| 1149 | + av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment pointer array\n"); | |
| 1150 | + ret = AVERROR(ENOMEM); | |
| 1151 | + goto finish_decoding_index; | |
| 1152 | + } | |
| 1153 | + | |
| 1154 | + if (sorted_segments[i]->index_start_position) | |
| 1155 | + av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i starts at EditUnit %"PRId64" - seeking may not work as expected\n", | |
| 1156 | + sorted_segments[i]->index_sid, sorted_segments[i]->index_start_position); | |
| 1157 | + | |
| 1158 | + memcpy(t->segments, &sorted_segments[i], t->nb_segments * sizeof(MXFIndexTableSegment*)); | |
| 1159 | + t->index_sid = sorted_segments[i]->index_sid; | |
| 1160 | + t->body_sid = sorted_segments[i]->body_sid; | |
| 1161 | + | |
| 1162 | + if ((ret = mxf_compute_ptses_fake_index(mxf, t)) < 0) | |
| 1163 | + goto finish_decoding_index; | |
| 1164 | + | |
| 1165 | + /* fix zero IndexDurations */ | |
| 1166 | + for (k = 0; k < t->nb_segments; k++) { | |
| 1167 | + if (t->segments[k]->index_duration) | |
| 1168 | + continue; | |
| 1169 | + | |
| 1170 | + if (t->nb_segments > 1) | |
| 1171 | + av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i segment %i has zero IndexDuration and there's more than one segment\n", | |
| 1172 | + t->index_sid, k); | |
| 1173 | + | |
| 1174 | + if (mxf->fc->nb_streams <= 0) { | |
| 1175 | + av_log(mxf->fc, AV_LOG_WARNING, "no streams?\n"); | |
| 1176 | + break; | |
| 1177 | + } | |
| 1178 | + | |
| 1179 | + /* assume the first stream's duration is reasonable | |
| 1180 | + * leave index_duration = 0 on further segments in case we have any (unlikely) | |
| 1181 | + */ | |
| 1182 | + t->segments[k]->index_duration = mxf->fc->streams[0]->duration; | |
| 1183 | + break; | |
| 1184 | + } | |
| 1185 | + } | |
| 1186 | + | |
| 1187 | + ret = 0; | |
| 1188 | +finish_decoding_index: | |
| 1189 | + av_free(sorted_segments); | |
| 1190 | + return ret; | |
| 1191 | +} | |
| 1192 | + | |
| 1325 | 1193 | static int mxf_parse_structural_metadata(MXFContext *mxf) |
| 1326 | 1194 | { |
| 1327 | 1195 | MXFPackage *material_package = NULL; |
| 1328 | 1196 | MXFPackage *temp_package = NULL; |
| 1329 | − int i, j, k, ret, nb_sorted_segments; | |
| 1330 | − MXFIndexTableSegment **sorted_segments = NULL; | |
| 1197 | + int i, j, k, ret; | |
| 1331 | 1198 | |
| 1332 | 1199 | av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count); |
| 1333 | 1200 | /* TODO: handle multiple material packages (OP3x) */ |
| @@ -1340,12 +1207,6 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 6 unmodified lines | ||
| 1340 | 1207 | return -1; |
| 1341 | 1208 | } |
| 1342 | 1209 | |
| 1343 | − if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments)) || | |
| 1344 | − nb_sorted_segments <= 0) { | |
| 1345 | − av_log(mxf->fc, AV_LOG_WARNING, "broken or empty index\n"); | |
| 1346 | − mxf->broken_index = 1; | |
| 1347 | − } | |
| 1348 | − | |
| 1349 | 1210 | for (i = 0; i < material_package->tracks_count; i++) { |
| 1350 | 1211 | MXFPackage *source_package = NULL; |
| 1351 | 1212 | MXFTrack *material_track = NULL; |
| @@ -1476,10 +1337,6 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 124 unmodified lines | ||
| 1476 | 1337 | } |
| 1477 | 1338 | } |
| 1478 | 1339 | |
| 1479 | − /* HACK: revert to the old demuxing/seeking scode for D-10 for now */ | |
| 1480 | − if (mxf_match_uid(essence_container_ul, mxf_d10_ul, 14)) | |
| 1481 | − mxf->d10 = 1; | |
| 1482 | − | |
| 1483 | 1340 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ |
| 1484 | 1341 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); |
| 1485 | 1342 | st->codec->codec_id = codec_ul->id; |
| @@ -1522,16 +1379,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 36 unmodified lines | ||
| 1522 | 1379 | /* TODO: decode timestamps */ |
| 1523 | 1380 | st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; |
| 1524 | 1381 | } |
| 1525 | − | |
| 1526 | − if (!mxf->broken_index && | |
| 1527 | − (ret = mxf_parse_index(mxf, material_track->track_id, st, sorted_segments, nb_sorted_segments))) | |
| 1528 | − goto fail_and_free; | |
| 1529 | 1382 | } |
| 1530 | 1383 | |
| 1531 | − ret = mxf_compute_ptses(mxf, sorted_segments, nb_sorted_segments); | |
| 1532 | − | |
| 1384 | + ret = 0; | |
| 1533 | 1385 | fail_and_free: |
| 1534 | − av_free(sorted_segments); | |
| 1535 | 1386 | return ret; |
| 1536 | 1387 | } |
| 1537 | 1388 | |
| @@ -1728,6 +1579,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 190 unmodified lines | ||
| 1728 | 1579 | MXFContext *mxf = s->priv_data; |
| 1729 | 1580 | KLVPacket klv; |
| 1730 | 1581 | int64_t essence_offset = 0; |
| 1582 | + int ret; | |
| 1731 | 1583 | |
| 1732 | 1584 | mxf->last_forward_tell = INT64_MAX; |
| 1733 | 1585 | |
| @@ -1823,7 +1675,153 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 89 unmodified lines | ||
| 1823 | 1675 | |
| 1824 | 1676 | mxf_compute_essence_containers(mxf); |
| 1825 | 1677 | |
| 1826 | − return mxf_parse_structural_metadata(mxf); | |
| 1678 | + /* we need to do this before computing the index tables | |
| 1679 | + * to be able to fill in zero IndexDurations with st->duration */ | |
| 1680 | + if ((ret = mxf_parse_structural_metadata(mxf)) < 0) | |
| 1681 | + return ret; | |
| 1682 | + | |
| 1683 | + if ((ret = mxf_compute_index_tables(mxf)) < 0) | |
| 1684 | + return ret; | |
| 1685 | + | |
| 1686 | + if (mxf->nb_index_tables > 1) { | |
| 1687 | + /* TODO: look up which IndexSID to use via EssenceContainerData */ | |
| 1688 | + av_log(mxf->fc, AV_LOG_INFO, "got %i index tables - only the first one (IndexSID %i) will be used\n", | |
| 1689 | + mxf->nb_index_tables, mxf->index_tables[0].index_sid); | |
| 1690 | + } else if (mxf->nb_index_tables == 0 && mxf->op == OPAtom) { | |
| 1691 | + av_log(mxf->fc, AV_LOG_ERROR, "cannot demux OPAtom without an index\n"); | |
| 1692 | + return AVERROR_INVALIDDATA; | |
| 1693 | + } | |
| 1694 | + | |
| 1695 | + return 0; | |
| 1696 | +} | |
| 1697 | + | |
| 1698 | +/** | |
| 1699 | + * Computes DTS and PTS for the given video packet based on its offset. | |
| 1700 | + */ | |
| 1701 | +static void mxf_packet_timestamps(MXFContext *mxf, AVPacket *pkt) | |
| 1702 | +{ | |
| 1703 | + int64_t next_ofs; | |
| 1704 | + MXFIndexTable *t = &mxf->index_tables[0]; | |
| 1705 | + | |
| 1706 | + /* find mxf->current_edit_unit so that the next edit unit starts ahead of pkt->pos */ | |
| 1707 | + for (;;) { | |
| 1708 | + if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_ofs, 0) < 0) | |
| 1709 | + break; | |
| 1710 | + | |
| 1711 | + if (next_ofs > pkt->pos) | |
| 1712 | + break; | |
| 1713 | + | |
| 1714 | + mxf->current_edit_unit++; | |
| 1715 | + } | |
| 1716 | + | |
| 1717 | + if (mxf->current_edit_unit >= t->nb_ptses) | |
| 1718 | + return; | |
| 1719 | + | |
| 1720 | + pkt->dts = mxf->current_edit_unit + t->first_dts; | |
| 1721 | + pkt->pts = t->ptses[mxf->current_edit_unit]; | |
| 1722 | +} | |
| 1723 | + | |
| 1724 | +static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) | |
| 1725 | +{ | |
| 1726 | + KLVPacket klv; | |
| 1727 | + | |
| 1728 | + while (!url_feof(s->pb)) { | |
| 1729 | + if (klv_read_packet(&klv, s->pb) < 0) | |
| 1730 | + return -1; | |
| 1731 | + PRINT_KEY(s, "read packet", klv.key); | |
| 1732 | + av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); | |
| 1733 | + if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { | |
| 1734 | + int res = mxf_decrypt_triplet(s, pkt, &klv); | |
| 1735 | + if (res < 0) { | |
| 1736 | + av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); | |
| 1737 | + return -1; | |
| 1738 | + } | |
| 1739 | + return 0; | |
| 1740 | + } | |
| 1741 | + if (IS_KLV_KEY(klv.key, mxf_essence_element_key) || | |
| 1742 | + IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) { | |
| 1743 | + int index = mxf_get_stream_index(s, &klv); | |
| 1744 | + if (index < 0) { | |
| 1745 | + av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); | |
| 1746 | + goto skip; | |
| 1747 | + } | |
| 1748 | + if (s->streams[index]->discard == AVDISCARD_ALL) | |
| 1749 | + goto skip; | |
| 1750 | + /* check for 8 channels AES3 element */ | |
| 1751 | + if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) { | |
| 1752 | + if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) { | |
| 1753 | + av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n"); | |
| 1754 | + return -1; | |
| 1755 | + } | |
| 1756 | + } else { | |
| 1757 | + int ret = av_get_packet(s->pb, pkt, klv.length); | |
| 1758 | + if (ret < 0) | |
| 1759 | + return ret; | |
| 1760 | + } | |
| 1761 | + pkt->stream_index = index; | |
| 1762 | + pkt->pos = klv.offset; | |
| 1763 | + | |
| 1764 | + if (s->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) | |
| 1765 | + mxf_packet_timestamps(s->priv_data, pkt); /* offset -> EditUnit -> DTS/PTS */ | |
| 1766 | + | |
| 1767 | + return 0; | |
| 1768 | + } else | |
| 1769 | + skip: | |
| 1770 | + avio_skip(s->pb, klv.length); | |
| 1771 | + } | |
| 1772 | + return AVERROR_EOF; | |
| 1773 | +} | |
| 1774 | + | |
| 1775 | +static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 1776 | +{ | |
| 1777 | + MXFContext *mxf = s->priv_data; | |
| 1778 | + int ret, size; | |
| 1779 | + int64_t ret64, pos, next_pos; | |
| 1780 | + AVStream *st; | |
| 1781 | + MXFIndexTable *t; | |
| 1782 | + | |
| 1783 | + if (mxf->op != OPAtom) | |
| 1784 | + return mxf_read_packet_old(s, pkt); | |
| 1785 | + | |
| 1786 | + /* OPAtom - clip wrapped demuxing */ | |
| 1787 | + st = s->streams[0]; | |
| 1788 | + t = &mxf->index_tables[0]; | |
| 1789 | + | |
| 1790 | + if (mxf->current_edit_unit >= st->duration) | |
| 1791 | + return AVERROR_EOF; | |
| 1792 | + | |
| 1793 | + if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit, NULL, &pos, 1)) < 0) | |
| 1794 | + return ret; | |
| 1795 | + | |
| 1796 | + /* compute size by finding the next edit unit or the end of the essence container | |
| 1797 | + * not pretty, but it works */ | |
| 1798 | + if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_pos, 0)) < 0 && | |
| 1799 | + (next_pos = mxf_essence_container_end(mxf, t->body_sid)) <= 0) { | |
| 1800 | + av_log(s, AV_LOG_ERROR, "unable to compute the size of the last packet\n"); | |
| 1801 | + return AVERROR_INVALIDDATA; | |
| 1802 | + } | |
| 1803 | + | |
| 1804 | + if ((size = next_pos - pos) <= 0) { | |
| 1805 | + av_log(s, AV_LOG_ERROR, "bad size: %i\n", size); | |
| 1806 | + return AVERROR_INVALIDDATA; | |
| 1807 | + } | |
| 1808 | + | |
| 1809 | + if ((ret64 = avio_seek(s->pb, pos, SEEK_SET)) < 0) | |
| 1810 | + return ret64; | |
| 1811 | + | |
| 1812 | + if ((ret = av_get_packet(s->pb, pkt, size)) != size) | |
| 1813 | + return ret < 0 ? ret : AVERROR_EOF; | |
| 1814 | + | |
| 1815 | + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && t->ptses && | |
| 1816 | + mxf->current_edit_unit >= 0 && mxf->current_edit_unit < t->nb_ptses) { | |
| 1817 | + pkt->dts = mxf->current_edit_unit + t->first_dts; | |
| 1818 | + pkt->pts = t->ptses[mxf->current_edit_unit]; | |
| 1819 | + } | |
| 1820 | + | |
| 1821 | + pkt->stream_index = 0; | |
| 1822 | + mxf->current_edit_unit++; | |
| 1823 | + | |
| 1824 | + return 0; | |
| 1827 | 1825 | } |
| 1828 | 1826 | |
| 1829 | 1827 | static int mxf_read_close(AVFormatContext *s) |
| @@ -1851,15 +1849,9 @@ static int mxf_read_close(AVFormatContext *s) · 21 unmodified lines | ||
| 1851 | 1849 | break; |
| 1852 | 1850 | case IndexTableSegment: |
| 1853 | 1851 | seg = (MXFIndexTableSegment *)mxf->metadata_sets[i]; |
| 1854 | − if (seg->slice_count) | |
| 1855 | − for (j = 0; j < seg->nb_index_entries; j++) | |
| 1856 | − av_freep(&seg->slice_offset_entries[j]); | |
| 1857 | − av_freep(&seg->slice); | |
| 1858 | − av_freep(&seg->element_delta); | |
| 1859 | 1852 | av_freep(&seg->temporal_offset_entries); |
| 1860 | 1853 | av_freep(&seg->flag_entries); |
| 1861 | 1854 | av_freep(&seg->stream_offset_entries); |
| 1862 | − av_freep(&seg->slice_offset_entries); | |
| 1863 | 1855 | break; |
| 1864 | 1856 | default: |
| 1865 | 1857 | break; |
| @@ -1870,7 +1862,13 @@ static int mxf_read_close(AVFormatContext *s) · 4 unmodified lines | ||
| 1870 | 1862 | av_freep(&mxf->metadata_sets); |
| 1871 | 1863 | av_freep(&mxf->aesc); |
| 1872 | 1864 | av_freep(&mxf->local_tags); |
| 1873 | − av_freep(&mxf->ptses); | |
| 1865 | + | |
| 1866 | + for (i = 0; i < mxf->nb_index_tables; i++) { | |
| 1867 | + av_freep(&mxf->index_tables[i].segments); | |
| 1868 | + av_freep(&mxf->index_tables[i].fake_index); | |
| 1869 | + } | |
| 1870 | + av_freep(&mxf->index_tables); | |
| 1871 | + | |
| 1874 | 1872 | return 0; |
| 1875 | 1873 | } |
| 1876 | 1874 | |
| @@ -1898,9 +1896,10 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti · 21 unmodified lines | ||
| 1898 | 1896 | int64_t seconds; |
| 1899 | 1897 | MXFContext* mxf = s->priv_data; |
| 1900 | 1898 | int64_t seekpos; |
| 1901 | − int index; | |
| 1899 | + int ret; | |
| 1900 | + MXFIndexTable *t; | |
| 1902 | 1901 | |
| 1903 | − if (mxf->d10) { | |
| 1902 | + if (mxf->index_tables <= 0) { | |
| 1904 | 1903 | if (!s->bit_rate) |
| 1905 | 1904 | return -1; |
| 1906 | 1905 | if (sample_time < 0) |
| @@ -1910,24 +1909,27 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti · 3 unmodified lines | ||
| 1910 | 1909 | return -1; |
| 1911 | 1910 | ff_update_cur_dts(s, st, sample_time); |
| 1912 | 1911 | } else { |
| 1913 | − if (st->nb_index_entries <= 0) | |
| 1914 | − return -1; | |
| 1912 | + t = &mxf->index_tables[0]; | |
| 1915 | 1913 | |
| 1916 | − index = av_index_search_timestamp(st, sample_time, flags); | |
| 1914 | + /* clamp above zero, else ff_index_search_timestamp() returns negative | |
| 1915 | + * this also means we allow seeking before the start */ | |
| 1916 | + sample_time = FFMAX(sample_time, 0); | |
| 1917 | 1917 | |
| 1918 | − av_dlog(s, "stream %d, timestamp %"PRId64", sample %d\n", st->index, sample_time, index); | |
| 1919 | − | |
| 1920 | − if (index < 0) { | |
| 1921 | − if (sample_time < st->index_entries[0].timestamp) | |
| 1922 | − index = 0; | |
| 1923 | − else | |
| 1924 | − return -1; | |
| 1918 | + if (t->fake_index) { | |
| 1919 | + /* behave as if we have a proper index */ | |
| 1920 | + if ((sample_time = ff_index_search_timestamp(t->fake_index, t->nb_ptses, sample_time, flags)) < 0) | |
| 1921 | + return sample_time; | |
| 1922 | + } else { | |
| 1923 | + /* no IndexEntryArray (one or more CBR segments) | |
| 1924 | + * make sure we don't seek past the end */ | |
| 1925 | + sample_time = FFMIN(sample_time, st->duration - 1); | |
| 1925 | 1926 | } |
| 1926 | 1927 | |
| 1927 | − seekpos = st->index_entries[index].pos; | |
| 1928 | − av_update_cur_dts(s, st, st->index_entries[index].timestamp); | |
| 1929 | − mxf->current_edit_unit = st->index_entries[index].timestamp; | |
| 1930 | − mxf->current_stream = 0; | |
| 1928 | + if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, &sample_time, &seekpos, 1)) << 0) | |
| 1929 | + return ret; | |
| 1930 | + | |
| 1931 | + av_update_cur_dts(s, st, sample_time); | |
| 1932 | + mxf->current_edit_unit = sample_time; | |
| 1931 | 1933 | avio_seek(s->pb, seekpos, SEEK_SET); |
| 1932 | 1934 | } |
| 1933 | 1935 | return 0; |
| @@ -2,52 +2,52 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 · 1 unmodified line | ||
| 2 | 2 | ret: 0 st:-1 flags:0 ts:-1.000000 |
| 3 | 3 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 4 | 4 | ret: 0 st:-1 flags:1 ts: 1.894167 |
| 5 | −ret:-1 | |
| 5 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 6 | 6 | ret: 0 st: 0 flags:0 ts: 0.800000 |
| 7 | −ret:-1 | |
| 7 | +ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:4265984 size:150000 | |
| 8 | 8 | ret: 0 st: 0 flags:1 ts:-0.320000 |
| 9 | 9 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 10 | 10 | ret: 0 st: 1 flags:0 ts: 2.560000 |
| 11 | −ret:-1 | |
| 11 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 12 | 12 | ret: 0 st: 1 flags:1 ts: 1.480000 |
| 13 | −ret:-1 | |
| 13 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 14 | 14 | ret: 0 st:-1 flags:0 ts: 0.365002 |
| 15 | −ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos: 6144 size:150000 | |
| 15 | +ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1923072 size:150000 | |
| 16 | 16 | ret: 0 st:-1 flags:1 ts:-0.740831 |
| 17 | 17 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 18 | 18 | ret: 0 st: 0 flags:0 ts: 2.160000 |
| 19 | −ret:-1 | |
| 19 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 20 | 20 | ret: 0 st: 0 flags:1 ts: 1.040000 |
| 21 | −ret:-1 | |
| 21 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 22 | 22 | ret: 0 st: 1 flags:0 ts:-0.040000 |
| 23 | 23 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 24 | 24 | ret: 0 st: 1 flags:1 ts: 2.840000 |
| 25 | −ret:-1 | |
| 25 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 26 | 26 | ret: 0 st:-1 flags:0 ts: 1.730004 |
| 27 | −ret:-1 | |
| 27 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 28 | 28 | ret: 0 st:-1 flags:1 ts: 0.624171 |
| 29 | −ret:-1 | |
| 29 | +ret: 0 st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:3414016 size:150000 | |
| 30 | 30 | ret: 0 st: 0 flags:0 ts:-0.480000 |
| 31 | 31 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 32 | 32 | ret: 0 st: 0 flags:1 ts: 2.400000 |
| 33 | −ret:-1 | |
| 33 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 34 | 34 | ret: 0 st: 1 flags:0 ts: 1.320000 |
| 35 | −ret:-1 | |
| 35 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 36 | 36 | ret: 0 st: 1 flags:1 ts: 0.200000 |
| 37 | −ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 6144 size:150000 | |
| 37 | +ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos:1071104 size:150000 | |
| 38 | 38 | ret: 0 st:-1 flags:0 ts:-0.904994 |
| 39 | 39 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 40 | 40 | ret: 0 st:-1 flags:1 ts: 1.989173 |
| 41 | −ret:-1 | |
| 41 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 42 | 42 | ret: 0 st: 0 flags:0 ts: 0.880000 |
| 43 | −ret:-1 | |
| 43 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:4691968 size:150000 | |
| 44 | 44 | ret: 0 st: 0 flags:1 ts:-0.240000 |
| 45 | 45 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 46 | 46 | ret: 0 st: 1 flags:0 ts: 2.680000 |
| 47 | −ret:-1 | |
| 47 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 48 | 48 | ret: 0 st: 1 flags:1 ts: 1.560000 |
| 49 | −ret:-1 | |
| 49 | +ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000 | |
| 50 | 50 | ret: 0 st:-1 flags:0 ts: 0.460008 |
| 51 | −ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos: 6144 size:150000 | |
| 51 | +ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:2562048 size:150000 | |
| 52 | 52 | ret: 0 st:-1 flags:1 ts:-0.645825 |
| 53 | 53 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |