* 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 | int edit_unit_byte_count; | 148 | int edit_unit_byte_count; |
| 149 | int index_sid; | 149 | int index_sid; |
| 150 | int body_sid; | 150 | int body_sid; |
| 151 | int slice_count; | ||
| 152 | AVRational index_edit_rate; | 151 | AVRational index_edit_rate; |
| 153 | uint64_t index_start_position; | 152 | uint64_t index_start_position; |
| 154 | uint64_t index_duration; | 153 | uint64_t index_duration; |
| 155 | int *slice; | ||
| 156 | int *element_delta; | ||
| 157 | int nb_delta_entries; | ||
| 158 | int8_t *temporal_offset_entries; | 154 | int8_t *temporal_offset_entries; |
| 159 | int *flag_entries; | 155 | int *flag_entries; |
| 160 | uint64_t *stream_offset_entries; | 156 | uint64_t *stream_offset_entries; |
| 161 | uint32_t **slice_offset_entries; | ||
| 162 | int nb_index_entries; | 157 | int nb_index_entries; |
| 163 | } MXFIndexTableSegment; | 158 | } MXFIndexTableSegment; |
| 164 | 159 | ||
| @@ -177,6 +172,18 @@ typedef struct { · 12 unmodified lines | |||
| 177 | enum MXFMetadataSetType type; | 172 | enum MXFMetadataSetType type; |
| 178 | } MXFMetadataSet; | 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 | typedef struct { | 187 | typedef struct { |
| 181 | MXFPartition *partitions; | 188 | MXFPartition *partitions; |
| 182 | unsigned partitions_count; | 189 | unsigned partitions_count; |
| @@ -198,12 +205,8 @@ typedef struct { · 15 unmodified lines | |||
| 198 | int64_t last_forward_tell; | 205 | int64_t last_forward_tell; |
| 199 | int last_forward_partition; | 206 | int last_forward_partition; |
| 200 | int current_edit_unit; | 207 | int current_edit_unit; |
| 201 | int current_stream; | 208 | int nb_index_tables; |
| 202 | int d10; | 209 | MXFIndexTable *index_tables; |
| 203 | int broken_index; | ||
| 204 | int64_t first_dts; /* DTS = EditUnit + first_dts */ | ||
| 205 | int64_t *ptses; /* maps EditUnit -> PTS */ | ||
| 206 | int nb_ptses; | ||
| 207 | } MXFContext; | 210 | } MXFContext; |
| 208 | 211 | ||
| 209 | enum MXFWrappingScheme { | 212 | enum MXFWrappingScheme { |
| @@ -380,117 +383,6 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv · 170 unmodified lines | |||
| 380 | return 0; | 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 | static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | 386 | static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) |
| 495 | { | 387 | { |
| 496 | MXFContext *mxf = arg; | 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 | return 0; | 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 | static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment) | 663 | static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment) |
| 791 | { | 664 | { |
| 792 | int i, j, length; | 665 | int i, j, length; |
| @@ -799,24 +672,12 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 6 unmodified lines | |||
| 799 | !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) | 672 | !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) |
| 800 | return AVERROR(ENOMEM); | 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 | for (i = 0; i < segment->nb_index_entries; i++) { | 675 | for (i = 0; i < segment->nb_index_entries; i++) { |
| 807 | segment->temporal_offset_entries[i] = avio_r8(pb); | 676 | segment->temporal_offset_entries[i] = avio_r8(pb); |
| 808 | avio_r8(pb); /* KeyFrameOffset */ | 677 | avio_r8(pb); /* KeyFrameOffset */ |
| 809 | segment->flag_entries[i] = avio_r8(pb); | 678 | segment->flag_entries[i] = avio_r8(pb); |
| 810 | segment->stream_offset_entries[i] = avio_rb64(pb); | 679 | segment->stream_offset_entries[i] = avio_rb64(pb); |
| 811 | if (segment->slice_count) { | 680 | avio_skip(pb, length - 11); |
| 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); | ||
| 820 | } | 681 | } |
| 821 | return 0; | 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 | segment->body_sid = avio_rb32(pb); | 698 | segment->body_sid = avio_rb32(pb); |
| 838 | av_dlog(NULL, "BodySID %d\n", segment->body_sid); | 699 | av_dlog(NULL, "BodySID %d\n", segment->body_sid); |
| 839 | break; | 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 | case 0x3F0A: | 701 | case 0x3F0A: |
| 848 | av_dlog(NULL, "IndexEntryArray found\n"); | 702 | av_dlog(NULL, "IndexEntryArray found\n"); |
| 849 | return mxf_read_index_entry_array(pb, segment); | 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 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, | 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 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) | 858 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) |
| 1007 | { | 859 | { |
| 1008 | int i, j, nb_segments = 0; | 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 | int x; | 948 | int x; |
| 1097 | int64_t ret = 0; | 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 | if (!p->essence_length) | 957 | if (!p->essence_length) |
| 1106 | return 0; | 958 | return 0; |
| 1107 | 959 | ||
| 1108 | ret += p->essence_length; | 960 | ret = p->essence_offset + p->essence_length; |
| 1109 | } | 961 | } |
| 1110 | 962 | ||
| 1111 | return ret; | 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; | 969 | int i; |
| 1117 | int j, k, l, ret; | 970 | int offset_temp = 0; |
| 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; | ||
| 1131 | 971 | ||
| 1132 | /* reset accumulated_offset on BodySID change */ | 972 | for (i = 0; i < index_table->nb_segments; i++) { |
| 1133 | if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid) | 973 | MXFIndexTableSegment *s = index_table->segments[i]; |
| 1134 | accumulated_offset = 0; | ||
| 1135 | 974 | ||
| 1136 | if (tableseg->nb_index_entries == 2 * tableseg->index_duration + 1) { | 975 | edit_unit = FFMAX(edit_unit, s->index_start_position); /* clamp if trying to seek before start */ |
| 1137 | /* Avid index - duplicate entries and total size as last entry */ | ||
| 1138 | index_delta = 2; | ||
| 1139 | } | ||
| 1140 | 976 | ||
| 1141 | if (n_delta >= tableseg->nb_delta_entries && st->index != 0) | 977 | if (edit_unit < s->index_start_position + s->index_duration) { |
| 1142 | continue; | 978 | int64_t index = edit_unit - s->index_start_position; |
| 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 | } | ||
| 1157 | 979 | ||
| 1158 | if (duration <= 0) { | 980 | if (s->edit_unit_byte_count) |
| 1159 | av_log(mxf->fc, AV_LOG_WARNING, "0 duration in index for stream %i\n", st->index); | 981 | offset_temp += s->edit_unit_byte_count * index; |
| 1160 | mxf->broken_index = 1; | 982 | else if (s->nb_index_entries) { |
| 1161 | return 0; | 983 | if (s->nb_index_entries == 2 * s->index_duration + 1) |
| 1162 | } | 984 | index *= 2; /* Avid index */ |
| 1163 | 985 | ||
| 1164 | for (k = l = 0; k < duration; k++, l += index_delta) { | 986 | if (index < 0 || index > s->nb_index_entries) { |
| 1165 | int64_t pos; | 987 | av_log(mxf->fc, AV_LOG_ERROR, "IndexSID %i segment at %"PRId64" IndexEntryArray too small\n", |
| 1166 | int size, flags = 0; | 988 | index_table->index_sid, s->index_start_position); |
| 1167 | 989 | return AVERROR_INVALIDDATA; | |
| 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]; | ||
| 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; | 992 | offset_temp = s->stream_offset_entries[index]; |
| 1213 | last_pos = pos; | 993 | } else { |
| 1214 | 994 | av_log(mxf->fc, AV_LOG_ERROR, "IndexSID %i segment at %"PRId64" missing EditUnitByteCount and IndexEntryArray\n", | |
| 1215 | if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos, &pos) < 0) { | 995 | index_table->index_sid, s->index_start_position); |
| 1216 | /* probably partial file - no point going further for this stream */ | 996 | return AVERROR_INVALIDDATA; |
| 1217 | break; | ||
| 1218 | } | 997 | } |
| 1219 | 998 | ||
| 1220 | av_dlog(mxf->fc, "Stream %d IndexEntry %d TrackID %d Offset %"PRIx64" Timestamp %"PRId64"\n", | 999 | if (edit_unit_out) |
| 1221 | st->index, st->nb_index_entries, track_id, pos, sample_duration * st->nb_index_entries); | 1000 | *edit_unit_out = edit_unit; |
| 1222 | |||
| 1223 | if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0) | ||
| 1224 | return ret; | ||
| 1225 | } | ||
| 1226 | 1001 | ||
| 1227 | if (last_size_unknown) { | 1002 | return mxf_absolute_bodysid_offset(mxf, index_table->body_sid, offset_temp, offset_out); |
| 1228 | int64_t ecl = mxf_essence_container_length(mxf, tableseg->body_sid); | 1003 | } else { |
| 1229 | 1004 | /* EditUnitByteCount == 0 for VBR indexes, which is fine since they use explicit StreamOffsets */ | |
| 1230 | if (ecl > 0) | 1005 | offset_temp += s->edit_unit_byte_count * s->index_duration; |
| 1231 | st->index_entries[st->nb_index_entries-1].size = ecl - last_pos; | ||
| 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 | int8_t max_temporal_offset = -128; | 1018 | int8_t max_temporal_offset = -128; |
| 1244 | 1019 | ||
| 1245 | /* first compute how many entries we have */ | 1020 | /* first compute how many entries we have */ |
| 1246 | for (i = 0; i < nb_sorted_segments; i++) { | 1021 | for (i = 0; i < index_table->nb_segments; i++) { |
| 1247 | MXFIndexTableSegment *s = sorted_segments[i]; | 1022 | MXFIndexTableSegment *s = index_table->segments[i]; |
| 1248 | 1023 | ||
| 1249 | if (!s->nb_index_entries) | 1024 | if (!s->nb_index_entries) |
| 1250 | return 0; /* no TemporalOffsets */ | 1025 | return 0; /* no TemporalOffsets */ |
| 1251 | 1026 | ||
| 1252 | if (s->nb_index_entries == 2 * s->index_duration + 1) | 1027 | index_table->nb_ptses += s->index_duration; |
| 1253 | mxf->nb_ptses += s->index_duration; /* Avid index */ | ||
| 1254 | else | ||
| 1255 | mxf->nb_ptses += s->nb_index_entries; | ||
| 1256 | } | 1028 | } |
| 1257 | 1029 | ||
| 1258 | /* paranoid check */ | 1030 | /* paranoid check */ |
| 1259 | if (mxf->nb_ptses <= 0) | 1031 | if (index_table->nb_ptses <= 0) |
| 1260 | return 0; | 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 | return AVERROR(ENOMEM); | 1037 | return AVERROR(ENOMEM); |
| 1038 | } | ||
| 1264 | 1039 | ||
| 1265 | /* we may have a few bad TemporalOffsets | 1040 | /* we may have a few bad TemporalOffsets |
| 1266 | * make sure the corresponding PTSes don't have the bogus value 0 */ | 1041 | * make sure the corresponding PTSes don't have the bogus value 0 */ |
| 1267 | for (x = 0; x < mxf->nb_ptses; x++) | 1042 | for (x = 0; x < index_table->nb_ptses; x++) |
| 1268 | mxf->ptses[x] = AV_NOPTS_VALUE; | 1043 | index_table->ptses[x] = AV_NOPTS_VALUE; |
| 1269 | 1044 | ||
| 1270 | /** | 1045 | /** |
| 1271 | * We have this: | 1046 | * We have this: |
| @@ -1294,8 +1069,8 @@ static int mxf_compute_ptses(MXFContext *mxf, MXFIndexTableSegment **sorted_segm · 22 unmodified lines | |||
| 1294 | * then settings mxf->first_dts = -max(TemporalOffset[x]). | 1069 | * then settings mxf->first_dts = -max(TemporalOffset[x]). |
| 1295 | * The latter makes DTS <= PTS. | 1070 | * The latter makes DTS <= PTS. |
| 1296 | */ | 1071 | */ |
| 1297 | for (i = x = 0; i < nb_sorted_segments; i++) { | 1072 | for (i = x = 0; i < index_table->nb_segments; i++) { |
| 1298 | MXFIndexTableSegment *s = sorted_segments[i]; | 1073 | MXFIndexTableSegment *s = index_table->segments[i]; |
| 1299 | int index_delta = 1; | 1074 | int index_delta = 1; |
| 1300 | 1075 | ||
| 1301 | if (s->nb_index_entries == 2 * s->index_duration + 1) | 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 | int offset = s->temporal_offset_entries[j] / index_delta; | 1080 | int offset = s->temporal_offset_entries[j] / index_delta; |
| 1306 | int index = x + offset; | 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 | av_log(mxf->fc, AV_LOG_ERROR, | 1087 | av_log(mxf->fc, AV_LOG_ERROR, |
| 1310 | "index entry %i + TemporalOffset %i = %i, which is out of bounds\n", | 1088 | "index entry %i + TemporalOffset %i = %i, which is out of bounds\n", |
| 1311 | x, offset, index); | 1089 | x, offset, index); |
| 1312 | continue; | 1090 | continue; |
| 1313 | } | 1091 | } |
| 1314 | 1092 | ||
| 1315 | mxf->ptses[index] = x; | 1093 | index_table->ptses[index] = x; |
| 1316 | max_temporal_offset = FFMAX(max_temporal_offset, offset); | 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 | return 0; | 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 | static int mxf_parse_structural_metadata(MXFContext *mxf) | 1193 | static int mxf_parse_structural_metadata(MXFContext *mxf) |
| 1326 | { | 1194 | { |
| 1327 | MXFPackage *material_package = NULL; | 1195 | MXFPackage *material_package = NULL; |
| 1328 | MXFPackage *temp_package = NULL; | 1196 | MXFPackage *temp_package = NULL; |
| 1329 | int i, j, k, ret, nb_sorted_segments; | 1197 | int i, j, k, ret; |
| 1330 | MXFIndexTableSegment **sorted_segments = NULL; | ||
| 1331 | 1198 | ||
| 1332 | av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count); | 1199 | av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count); |
| 1333 | /* TODO: handle multiple material packages (OP3x) */ | 1200 | /* TODO: handle multiple material packages (OP3x) */ |
| @@ -1340,12 +1207,6 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 6 unmodified lines | |||
| 1340 | return -1; | 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 | for (i = 0; i < material_package->tracks_count; i++) { | 1210 | for (i = 0; i < material_package->tracks_count; i++) { |
| 1350 | MXFPackage *source_package = NULL; | 1211 | MXFPackage *source_package = NULL; |
| 1351 | MXFTrack *material_track = NULL; | 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 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ | 1340 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ |
| 1484 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); | 1341 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); |
| 1485 | st->codec->codec_id = codec_ul->id; | 1342 | st->codec->codec_id = codec_ul->id; |
| @@ -1522,16 +1379,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 36 unmodified lines | |||
| 1522 | /* TODO: decode timestamps */ | 1379 | /* TODO: decode timestamps */ |
| 1523 | st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; | 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); | 1384 | ret = 0; |
| 1532 | |||
| 1533 | fail_and_free: | 1385 | fail_and_free: |
| 1534 | av_free(sorted_segments); | ||
| 1535 | return ret; | 1386 | return ret; |
| 1536 | } | 1387 | } |
| 1537 | 1388 | ||
| @@ -1728,6 +1579,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 190 unmodified lines | |||
| 1728 | MXFContext *mxf = s->priv_data; | 1579 | MXFContext *mxf = s->priv_data; |
| 1729 | KLVPacket klv; | 1580 | KLVPacket klv; |
| 1730 | int64_t essence_offset = 0; | 1581 | int64_t essence_offset = 0; |
| 1582 | int ret; | ||
| 1731 | 1583 | ||
| 1732 | mxf->last_forward_tell = INT64_MAX; | 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 | mxf_compute_essence_containers(mxf); | 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 | static int mxf_read_close(AVFormatContext *s) | 1827 | static int mxf_read_close(AVFormatContext *s) |
| @@ -1851,15 +1849,9 @@ static int mxf_read_close(AVFormatContext *s) · 21 unmodified lines | |||
| 1851 | break; | 1849 | break; |
| 1852 | case IndexTableSegment: | 1850 | case IndexTableSegment: |
| 1853 | seg = (MXFIndexTableSegment *)mxf->metadata_sets[i]; | 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 | av_freep(&seg->temporal_offset_entries); | 1852 | av_freep(&seg->temporal_offset_entries); |
| 1860 | av_freep(&seg->flag_entries); | 1853 | av_freep(&seg->flag_entries); |
| 1861 | av_freep(&seg->stream_offset_entries); | 1854 | av_freep(&seg->stream_offset_entries); |
| 1862 | av_freep(&seg->slice_offset_entries); | ||
| 1863 | break; | 1855 | break; |
| 1864 | default: | 1856 | default: |
| 1865 | break; | 1857 | break; |
| @@ -1870,7 +1862,13 @@ static int mxf_read_close(AVFormatContext *s) · 4 unmodified lines | |||
| 1870 | av_freep(&mxf->metadata_sets); | 1862 | av_freep(&mxf->metadata_sets); |
| 1871 | av_freep(&mxf->aesc); | 1863 | av_freep(&mxf->aesc); |
| 1872 | av_freep(&mxf->local_tags); | 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 | return 0; | 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 | int64_t seconds; | 1896 | int64_t seconds; |
| 1899 | MXFContext* mxf = s->priv_data; | 1897 | MXFContext* mxf = s->priv_data; |
| 1900 | int64_t seekpos; | 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 | if (!s->bit_rate) | 1903 | if (!s->bit_rate) |
| 1905 | return -1; | 1904 | return -1; |
| 1906 | if (sample_time < 0) | 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 | return -1; | 1909 | return -1; |
| 1911 | ff_update_cur_dts(s, st, sample_time); | 1910 | ff_update_cur_dts(s, st, sample_time); |
| 1912 | } else { | 1911 | } else { |
| 1913 | if (st->nb_index_entries <= 0) | 1912 | t = &mxf->index_tables[0]; |
| 1914 | return -1; | ||
| 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); | 1918 | if (t->fake_index) { |
| 1919 | 1919 | /* behave as if we have a proper index */ | |
| 1920 | if (index < 0) { | 1920 | if ((sample_time = ff_index_search_timestamp(t->fake_index, t->nb_ptses, sample_time, flags)) < 0) |
| 1921 | if (sample_time < st->index_entries[0].timestamp) | 1921 | return sample_time; |
| 1922 | index = 0; | 1922 | } else { |
| 1923 | else | 1923 | /* no IndexEntryArray (one or more CBR segments) |
| 1924 | return -1; | 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 | if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, &sample_time, &seekpos, 1)) << 0) |
| 1928 | av_update_cur_dts(s, st, st->index_entries[index].timestamp); | 1929 | return ret; |
| 1929 | mxf->current_edit_unit = st->index_entries[index].timestamp; | 1930 | |
| 1930 | mxf->current_stream = 0; | 1931 | av_update_cur_dts(s, st, sample_time); |
| 1932 | mxf->current_edit_unit = sample_time; | ||
| 1931 | avio_seek(s->pb, seekpos, SEEK_SET); | 1933 | avio_seek(s->pb, seekpos, SEEK_SET); |
| 1932 | } | 1934 | } |
| 1933 | return 0; | 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 | ret: 0 st:-1 flags:0 ts:-1.000000 | 2 | ret: 0 st:-1 flags:0 ts:-1.000000 |
| 3 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 3 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 4 | ret: 0 st:-1 flags:1 ts: 1.894167 | 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 | ret: 0 st: 0 flags:0 ts: 0.800000 | 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 | ret: 0 st: 0 flags:1 ts:-0.320000 | 8 | ret: 0 st: 0 flags:1 ts:-0.320000 |
| 9 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 9 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 10 | ret: 0 st: 1 flags:0 ts: 2.560000 | 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 | ret: 0 st: 1 flags:1 ts: 1.480000 | 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 | ret: 0 st:-1 flags:0 ts: 0.365002 | 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 | ret: 0 st:-1 flags:1 ts:-0.740831 | 16 | ret: 0 st:-1 flags:1 ts:-0.740831 |
| 17 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 17 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 18 | ret: 0 st: 0 flags:0 ts: 2.160000 | 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 | ret: 0 st: 0 flags:1 ts: 1.040000 | 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 | ret: 0 st: 1 flags:0 ts:-0.040000 | 22 | ret: 0 st: 1 flags:0 ts:-0.040000 |
| 23 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 23 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 24 | ret: 0 st: 1 flags:1 ts: 2.840000 | 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 | ret: 0 st:-1 flags:0 ts: 1.730004 | 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 | ret: 0 st:-1 flags:1 ts: 0.624171 | 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 | ret: 0 st: 0 flags:0 ts:-0.480000 | 30 | ret: 0 st: 0 flags:0 ts:-0.480000 |
| 31 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 31 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 32 | ret: 0 st: 0 flags:1 ts: 2.400000 | 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 | ret: 0 st: 1 flags:0 ts: 1.320000 | 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 | ret: 0 st: 1 flags:1 ts: 0.200000 | 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 | ret: 0 st:-1 flags:0 ts:-0.904994 | 38 | ret: 0 st:-1 flags:0 ts:-0.904994 |
| 39 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 39 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 40 | ret: 0 st:-1 flags:1 ts: 1.989173 | 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 | ret: 0 st: 0 flags:0 ts: 0.880000 | 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 | ret: 0 st: 0 flags:1 ts:-0.240000 | 44 | ret: 0 st: 0 flags:1 ts:-0.240000 |
| 45 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 45 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |
| 46 | ret: 0 st: 1 flags:0 ts: 2.680000 | 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 | ret: 0 st: 1 flags:1 ts: 1.560000 | 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 | ret: 0 st:-1 flags:0 ts: 0.460008 | 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 | ret: 0 st:-1 flags:1 ts:-0.645825 | 52 | ret: 0 st:-1 flags:1 ts:-0.645825 |
| 53 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 | 53 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 6144 size:150000 |