* tjoppen/opatom_demuxing_and_seeking: mxfdec: Index table driven demuxing and seeking mxfdec: Compute packet offsets properly mxfdec: Use MaterialPackage - Track - TrackID instead of the system_item hack mxfdec: Parse more values in PartitionPack mxfdec: Parse TemporalOffsets mxfdec: av_dlog():ify 'no corresponding source package found' mxfdec: Compute essence container offsets and lengths into mxf->partitions mxfdec: Make mxf->partitions sorted by offset mxfdec: Parse ThisPartition mxfdec: Speed up metadata and index parsing mxfdec: Make sure DataDefinition is consistent between material track and source track mxfdec: Add EssenceContainer UL found in 0001GL00.MXF.A1.mxf_opatom.mxf
Unified · Split
| @@ -69,6 +69,7 @@ typedef enum { · 68 unmodified lines | ||
| 69 | 69 | OP3b, |
| 70 | 70 | OP3c, |
| 71 | 71 | OPAtom, |
| 72 | + OPSONYOpt, /* FATE sample, violates the spec in places */ | |
| 72 | 73 | } MXFOP; |
| 73 | 74 | |
| 74 | 75 | typedef struct { |
| @@ -78,6 +79,13 @@ typedef struct { · 3 unmodified lines | ||
| 78 | 79 | uint64_t previous_partition; |
| 79 | 80 | int index_sid; |
| 80 | 81 | int body_sid; |
| 82 | + int64_t this_partition; | |
| 83 | + int64_t essence_offset; /* absolute offset of essence */ | |
| 84 | + int64_t essence_length; | |
| 85 | + int32_t kag_size; | |
| 86 | + int64_t header_byte_count; | |
| 87 | + int64_t index_byte_count; | |
| 88 | + int pack_length; | |
| 81 | 89 | } MXFPartition; |
| 82 | 90 | |
| 83 | 91 | typedef struct { |
| @@ -147,6 +155,7 @@ typedef struct { · 63 unmodified lines | ||
| 147 | 155 | int *slice; |
| 148 | 156 | int *element_delta; |
| 149 | 157 | int nb_delta_entries; |
| 158 | + int8_t *temporal_offset_entries; | |
| 150 | 159 | int *flag_entries; |
| 151 | 160 | uint64_t *stream_offset_entries; |
| 152 | 161 | uint32_t **slice_offset_entries; |
| @@ -181,12 +190,16 @@ typedef struct { · 28 unmodified lines | ||
| 181 | 190 | uint8_t *local_tags; |
| 182 | 191 | int local_tags_count; |
| 183 | 192 | uint64_t footer_partition; |
| 184 | − int system_item; | |
| 185 | − int64_t essence_offset; | |
| 186 | − int first_essence_kl_length; | |
| 187 | − int64_t first_essence_length; | |
| 188 | 193 | KLVPacket current_klv_data; |
| 189 | 194 | int current_klv_index; |
| 195 | + int run_in; | |
| 196 | + MXFPartition *current_partition; | |
| 197 | + int parsing_backward; | |
| 198 | + int64_t last_forward_tell; | |
| 199 | + int last_forward_partition; | |
| 200 | + int current_edit_unit; | |
| 201 | + int current_stream; | |
| 202 | + int d10; | |
| 190 | 203 | } MXFContext; |
| 191 | 204 | |
| 192 | 205 | enum MXFWrappingScheme { |
| @@ -194,7 +207,8 @@ enum MXFWrappingScheme { · 1 unmodified line | ||
| 194 | 207 | Clip, |
| 195 | 208 | }; |
| 196 | 209 | |
| 197 | −typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid); | |
| 210 | +/* NOTE: klv_offset is not set (-1) for local keys */ | |
| 211 | +typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset); | |
| 198 | 212 | |
| 199 | 213 | typedef struct { |
| 200 | 214 | const UID key; |
| @@ -361,7 +375,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv · 160 unmodified lines | ||
| 361 | 375 | return 0; |
| 362 | 376 | } |
| 363 | 377 | |
| 364 | −static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 378 | +static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) | |
| 365 | 379 | { |
| 366 | 380 | KLVPacket klv; |
| 367 | 381 | |
| @@ -407,7 +421,66 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) · 39 unmodified lines | ||
| 407 | 421 | return AVERROR_EOF; |
| 408 | 422 | } |
| 409 | 423 | |
| 410 | −static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 424 | +static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 425 | +{ | |
| 426 | + MXFContext *mxf = s->priv_data; | |
| 427 | + AVIndexEntry *e; | |
| 428 | + int ret; | |
| 429 | + int64_t ret64; | |
| 430 | + KLVPacket klv; | |
| 431 | + AVStream *st; | |
| 432 | + | |
| 433 | + /* TODO: better logic for this? | |
| 434 | + * only files that lack all index segments prior to the essence need this */ | |
| 435 | + if (!s->pb->seekable && mxf->op != OPAtom || mxf->d10) | |
| 436 | + return mxf_read_packet_old(s, pkt); | |
| 437 | + | |
| 438 | + if (mxf->current_stream >= s->nb_streams) { | |
| 439 | + mxf->current_edit_unit++; | |
| 440 | + mxf->current_stream = 0; | |
| 441 | + } | |
| 442 | + | |
| 443 | + st = s->streams[mxf->current_stream]; | |
| 444 | + | |
| 445 | + if (mxf->current_edit_unit >= st->nb_index_entries) | |
| 446 | + return AVERROR_EOF; | |
| 447 | + | |
| 448 | + e = &st->index_entries[mxf->current_edit_unit]; | |
| 449 | + | |
| 450 | + if ((ret64 = avio_seek(s->pb, e->pos, SEEK_SET)) < 0) | |
| 451 | + return ret64; | |
| 452 | + | |
| 453 | + if (mxf->op == OPAtom) { | |
| 454 | + /* OPAtom - no KL, just essence */ | |
| 455 | + if ((ret = av_get_packet(s->pb, pkt, e->size)) != e->size) | |
| 456 | + return ret < 0 ? ret : AVERROR_EOF; | |
| 457 | + } else { | |
| 458 | + /* read KL, read L bytes of essence */ | |
| 459 | + if ((ret = klv_read_packet(&klv, s->pb)) < 0) | |
| 460 | + return ret; | |
| 461 | + | |
| 462 | + /* untested, but looks OK */ | |
| 463 | + if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { | |
| 464 | + int res = mxf_decrypt_triplet(s, pkt, &klv); | |
| 465 | + if (res < 0) { | |
| 466 | + av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n"); | |
| 467 | + return -1; | |
| 468 | + } | |
| 469 | + return 0; | |
| 470 | + } | |
| 471 | + | |
| 472 | + if ((ret = av_get_packet(s->pb, pkt, klv.length)) != klv.length) | |
| 473 | + return ret < 0 ? ret : AVERROR_EOF; | |
| 474 | + | |
| 475 | + pkt->pos = e->pos; | |
| 476 | + } | |
| 477 | + | |
| 478 | + pkt->stream_index = mxf->current_stream++; | |
| 479 | + | |
| 480 | + return 0; | |
| 481 | +} | |
| 482 | + | |
| 483 | +static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 411 | 484 | { |
| 412 | 485 | MXFContext *mxf = arg; |
| 413 | 486 | int item_num = avio_rb32(pb); |
| @@ -427,7 +500,7 @@ static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, U · 13 unmodified lines | ||
| 427 | 500 | return 0; |
| 428 | 501 | } |
| 429 | 502 | |
| 430 | −static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 503 | +static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 431 | 504 | { |
| 432 | 505 | MXFContext *mxf = arg; |
| 433 | 506 | MXFPartition *partition; |
| @@ -441,7 +514,21 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size · 7 unmodified lines | ||
| 441 | 514 | if (!mxf->partitions) |
| 442 | 515 | return AVERROR(ENOMEM); |
| 443 | 516 | |
| 444 | − partition = &mxf->partitions[mxf->partitions_count++]; | |
| 517 | + if (mxf->parsing_backward) { | |
| 518 | + /* insert the new partition pack in the middle | |
| 519 | + * this makes the entries in mxf->partitions sorted by offset */ | |
| 520 | + memmove(&mxf->partitions[mxf->last_forward_partition+1], | |
| 521 | + &mxf->partitions[mxf->last_forward_partition], | |
| 522 | + (mxf->partitions_count - mxf->last_forward_partition)*sizeof(*mxf->partitions)); | |
| 523 | + partition = mxf->current_partition = &mxf->partitions[mxf->last_forward_partition]; | |
| 524 | + } else { | |
| 525 | + mxf->last_forward_partition++; | |
| 526 | + partition = mxf->current_partition = &mxf->partitions[mxf->partitions_count]; | |
| 527 | + } | |
| 528 | + | |
| 529 | + memset(partition, 0, sizeof(*partition)); | |
| 530 | + mxf->partitions_count++; | |
| 531 | + partition->pack_length = avio_tell(pb) - klv_offset + size; | |
| 445 | 532 | |
| 446 | 533 | switch(uid[13]) { |
| 447 | 534 | case 2: |
| @@ -461,10 +548,13 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size · 13 unmodified lines | ||
| 461 | 548 | /* consider both footers to be closed (there is only Footer and CompleteFooter) */ |
| 462 | 549 | partition->closed = partition->type == Footer || !(uid[14] & 1); |
| 463 | 550 | partition->complete = uid[14] > 2; |
| 464 | − avio_skip(pb, 16); | |
| 551 | + avio_skip(pb, 4); | |
| 552 | + partition->kag_size = avio_rb32(pb); | |
| 553 | + partition->this_partition = avio_rb64(pb); | |
| 465 | 554 | partition->previous_partition = avio_rb64(pb); |
| 466 | 555 | footer_partition = avio_rb64(pb); |
| 467 | − avio_skip(pb, 16); | |
| 556 | + partition->header_byte_count = avio_rb64(pb); | |
| 557 | + partition->index_byte_count = avio_rb64(pb); | |
| 468 | 558 | partition->index_sid = avio_rb32(pb); |
| 469 | 559 | avio_skip(pb, 8); |
| 470 | 560 | partition->body_sid = avio_rb32(pb); |
| @@ -480,8 +570,9 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size · 9 unmodified lines | ||
| 480 | 570 | } |
| 481 | 571 | } |
| 482 | 572 | |
| 483 | − av_dlog(mxf->fc, "PartitionPack: PreviousPartition = 0x%lx, " | |
| 573 | + av_dlog(mxf->fc, "PartitionPack: ThisPartition = 0x%lx, PreviousPartition = 0x%lx, " | |
| 484 | 574 | "FooterPartition = 0x%lx, IndexSID = %i, BodySID = %i\n", |
| 575 | + partition->this_partition, | |
| 485 | 576 | partition->previous_partition, footer_partition, |
| 486 | 577 | partition->index_sid, partition->body_sid); |
| 487 | 578 | |
| @@ -495,8 +586,22 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size · 7 unmodified lines | ||
| 495 | 586 | else if (op[12] == 3 && op[13] == 2) mxf->op = OP3b; |
| 496 | 587 | else if (op[12] == 3 && op[13] == 3) mxf->op = OP3c; |
| 497 | 588 | else if (op[12] == 0x10) mxf->op = OPAtom; |
| 498 | − else | |
| 499 | − av_log(mxf->fc, AV_LOG_ERROR, "unknown operational pattern: %02xh %02xh\n", op[12], op[13]); | |
| 589 | + else if (op[12] == 64&& op[13] == 1) mxf->op = OPSONYOpt; | |
| 590 | + else { | |
| 591 | + av_log(mxf->fc, AV_LOG_ERROR, "unknown operational pattern: %02xh %02xh - guessing OP1a\n", op[12], op[13]); | |
| 592 | + mxf->op = OP1a; | |
| 593 | + } | |
| 594 | + | |
| 595 | + if (partition->kag_size <= 0 || partition->kag_size > (1 << 20)) { | |
| 596 | + av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %i - guessing ", partition->kag_size); | |
| 597 | + | |
| 598 | + if (mxf->op == OPSONYOpt) | |
| 599 | + partition->kag_size = 512; | |
| 600 | + else | |
| 601 | + partition->kag_size = 1; | |
| 602 | + | |
| 603 | + av_log(mxf->fc, AV_LOG_WARNING, "%i\n", partition->kag_size); | |
| 604 | + } | |
| 500 | 605 | |
| 501 | 606 | return 0; |
| 502 | 607 | } |
| @@ -513,7 +618,7 @@ static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) · 10 unmodified lines | ||
| 513 | 618 | return 0; |
| 514 | 619 | } |
| 515 | 620 | |
| 516 | −static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 621 | +static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 517 | 622 | { |
| 518 | 623 | MXFCryptoContext *cryptocontext = arg; |
| 519 | 624 | if (size != 16) |
| @@ -523,7 +628,7 @@ static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, i · 3 unmodified lines | ||
| 523 | 628 | return 0; |
| 524 | 629 | } |
| 525 | 630 | |
| 526 | −static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 631 | +static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 527 | 632 | { |
| 528 | 633 | MXFContext *mxf = arg; |
| 529 | 634 | switch (tag) { |
| @@ -541,7 +646,7 @@ static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int siz · 11 unmodified lines | ||
| 541 | 646 | return 0; |
| 542 | 647 | } |
| 543 | 648 | |
| 544 | −static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 649 | +static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 545 | 650 | { |
| 546 | 651 | MXFStructuralComponent *source_clip = arg; |
| 547 | 652 | switch(tag) { |
| @@ -563,7 +668,7 @@ static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, U · 15 unmodified lines | ||
| 563 | 668 | return 0; |
| 564 | 669 | } |
| 565 | 670 | |
| 566 | −static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 671 | +static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 567 | 672 | { |
| 568 | 673 | MXFPackage *package = arg; |
| 569 | 674 | switch(tag) { |
| @@ -581,7 +686,7 @@ static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int si · 11 unmodified lines | ||
| 581 | 686 | return 0; |
| 582 | 687 | } |
| 583 | 688 | |
| 584 | −static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 689 | +static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 585 | 690 | { |
| 586 | 691 | MXFTrack *track = arg; |
| 587 | 692 | switch(tag) { |
| @@ -602,7 +707,7 @@ static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid · 14 unmodified lines | ||
| 602 | 707 | return 0; |
| 603 | 708 | } |
| 604 | 709 | |
| 605 | −static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 710 | +static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 606 | 711 | { |
| 607 | 712 | MXFSequence *sequence = arg; |
| 608 | 713 | switch(tag) { |
| @@ -626,7 +731,7 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID · 17 unmodified lines | ||
| 626 | 731 | return 0; |
| 627 | 732 | } |
| 628 | 733 | |
| 629 | −static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 734 | +static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 630 | 735 | { |
| 631 | 736 | MXFPackage *package = arg; |
| 632 | 737 | switch(tag) { |
| @@ -678,7 +783,8 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 45 unmodified lines | ||
| 678 | 783 | segment->nb_index_entries = avio_rb32(pb); |
| 679 | 784 | length = avio_rb32(pb); |
| 680 | 785 | |
| 681 | − if (!(segment->flag_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->flag_entries))) || | |
| 786 | + if (!(segment->temporal_offset_entries=av_calloc(segment->nb_index_entries, sizeof(*segment->temporal_offset_entries))) || | |
| 787 | + !(segment->flag_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->flag_entries))) || | |
| 682 | 788 | !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) |
| 683 | 789 | return AVERROR(ENOMEM); |
| 684 | 790 | |
| @@ -687,7 +793,8 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 2 unmodified lines | ||
| 687 | 793 | return AVERROR(ENOMEM); |
| 688 | 794 | |
| 689 | 795 | for (i = 0; i < segment->nb_index_entries; i++) { |
| 690 | − avio_rb16(pb); /* TemporalOffset and KeyFrameOffset */ | |
| 796 | + segment->temporal_offset_entries[i] = avio_r8(pb); | |
| 797 | + avio_r8(pb); /* KeyFrameOffset */ | |
| 691 | 798 | segment->flag_entries[i] = avio_r8(pb); |
| 692 | 799 | segment->stream_offset_entries[i] = avio_rb64(pb); |
| 693 | 800 | if (segment->slice_count) { |
| @@ -703,7 +810,7 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 9 unmodified lines | ||
| 703 | 810 | return 0; |
| 704 | 811 | } |
| 705 | 812 | |
| 706 | −static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 813 | +static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 707 | 814 | { |
| 708 | 815 | MXFIndexTableSegment *segment = arg; |
| 709 | 816 | switch(tag) { |
| @@ -766,7 +873,7 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) · 56 unmodified lines | ||
| 766 | 873 | ff_mxf_decode_pixel_layout(layout, &descriptor->pix_fmt); |
| 767 | 874 | } |
| 768 | 875 | |
| 769 | −static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid) | |
| 876 | +static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) | |
| 770 | 877 | { |
| 771 | 878 | MXFDescriptor *descriptor = arg; |
| 772 | 879 | switch(tag) { |
| @@ -876,9 +983,12 @@ static const MXFCodecUL mxf_essence_container_uls[] = { · 103 unmodified lines | ||
| 876 | 983 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */ |
| 877 | 984 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */ |
| 878 | 985 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */ |
| 986 | + { { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0xFF,0x4B,0x46,0x41,0x41,0x00,0x0D,0x4D,0x4F }, 14, CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */ | |
| 879 | 987 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, |
| 880 | 988 | }; |
| 881 | 989 | |
| 990 | +static UID mxf_d10_ul = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }; | |
| 991 | + | |
| 882 | 992 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) |
| 883 | 993 | { |
| 884 | 994 | int i, j, nb_segments = 0; |
| @@ -936,28 +1046,53 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment · 51 unmodified lines | ||
| 936 | 1046 | return 0; |
| 937 | 1047 | } |
| 938 | 1048 | |
| 939 | −static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st) | |
| 1049 | +/** | |
| 1050 | + * Computes the absolute file offset of the given essence container offset | |
| 1051 | + */ | |
| 1052 | +static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out) | |
| 1053 | +{ | |
| 1054 | + int x; | |
| 1055 | + int64_t offset_in = offset; /* for logging */ | |
| 1056 | + | |
| 1057 | + for (x = 0; x < mxf->partitions_count; x++) { | |
| 1058 | + MXFPartition *p = &mxf->partitions[x]; | |
| 1059 | + | |
| 1060 | + if (p->body_sid != body_sid) | |
| 1061 | + continue; | |
| 1062 | + | |
| 1063 | + if (offset < p->essence_length || !p->essence_length) { | |
| 1064 | + *offset_out = p->essence_offset + offset; | |
| 1065 | + return 0; | |
| 1066 | + } | |
| 1067 | + | |
| 1068 | + offset -= p->essence_length; | |
| 1069 | + } | |
| 1070 | + | |
| 1071 | + av_log(mxf->fc, AV_LOG_ERROR, "failed to find absolute offset of %lx in BodySID %i - partial file?\n", | |
| 1072 | + offset_in, body_sid); | |
| 1073 | + | |
| 1074 | + return AVERROR_INVALIDDATA; | |
| 1075 | +} | |
| 1076 | + | |
| 1077 | +static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st) | |
| 940 | 1078 | { |
| 941 | − int64_t accumulated_offset = 0; | |
| 942 | 1079 | int j, k, ret, nb_sorted_segments; |
| 943 | 1080 | MXFIndexTableSegment **sorted_segments; |
| 1081 | + int n_delta = track_id - 1; /* TrackID = 1-based stream index */ | |
| 1082 | + | |
| 1083 | + if (track_id < 1) { | |
| 1084 | + av_log(mxf->fc, AV_LOG_ERROR, "TrackID not positive: %i\n", track_id); | |
| 1085 | + return AVERROR_INVALIDDATA; | |
| 1086 | + } | |
| 944 | 1087 | |
| 945 | 1088 | if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments))) |
| 946 | 1089 | return ret; |
| 947 | 1090 | |
| 948 | 1091 | for (j = 0; j < nb_sorted_segments; j++) { |
| 949 | − int n_delta = i; | |
| 950 | 1092 | int duration, sample_duration = 1, last_sample_size = 0; |
| 951 | 1093 | int64_t segment_size; |
| 952 | 1094 | MXFIndexTableSegment *tableseg = sorted_segments[j]; |
| 953 | 1095 | |
| 954 | − /* reset accumulated_offset on BodySID change */ | |
| 955 | − if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid) | |
| 956 | − accumulated_offset = 0; | |
| 957 | − | |
| 958 | − /* HACK: How to correctly link between streams and slices? */ | |
| 959 | − if (i < mxf->system_item + st->index) | |
| 960 | − n_delta++; | |
| 961 | 1096 | if (n_delta >= tableseg->nb_delta_entries && st->index != 0) |
| 962 | 1097 | continue; |
| 963 | 1098 | duration = tableseg->index_duration > 0 ? tableseg->index_duration : |
| @@ -1003,7 +1138,7 @@ static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st) · 39 unmodified lines | ||
| 1003 | 1138 | size = 0; |
| 1004 | 1139 | flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0; |
| 1005 | 1140 | } else { |
| 1006 | − pos = (int64_t)k * tableseg->edit_unit_byte_count + accumulated_offset; | |
| 1141 | + pos = (int64_t)(tableseg->index_start_position + k) * tableseg->edit_unit_byte_count; | |
| 1007 | 1142 | if (n_delta < tableseg->nb_delta_entries - 1) |
| 1008 | 1143 | size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta]; |
| 1009 | 1144 | else { |
| @@ -1020,18 +1155,17 @@ static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st) · 10 unmodified lines | ||
| 1020 | 1155 | flags = AVINDEX_KEYFRAME; |
| 1021 | 1156 | } |
| 1022 | 1157 | |
| 1023 | − if (k > 0 && pos < mxf->first_essence_length && accumulated_offset == 0) | |
| 1024 | − pos += mxf->first_essence_kl_length; | |
| 1025 | − | |
| 1026 | − pos += mxf->essence_offset; | |
| 1158 | + if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos, &pos) < 0) { | |
| 1159 | + /* probably partial file - no point going further for this stream */ | |
| 1160 | + break; | |
| 1161 | + } | |
| 1027 | 1162 | |
| 1028 | − av_dlog(mxf->fc, "Stream %d IndexEntry %d n_Delta %d Offset %"PRIx64" Timestamp %"PRId64"\n", | |
| 1029 | − st->index, st->nb_index_entries, n_delta, pos, sample_duration * st->nb_index_entries); | |
| 1163 | + av_dlog(mxf->fc, "Stream %d IndexEntry %d TrackID %d Offset %"PRIx64" Timestamp %"PRId64"\n", | |
| 1164 | + st->index, st->nb_index_entries, track_id, pos, sample_duration * st->nb_index_entries); | |
| 1030 | 1165 | |
| 1031 | 1166 | if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0) |
| 1032 | 1167 | return ret; |
| 1033 | 1168 | } |
| 1034 | − accumulated_offset += segment_size; | |
| 1035 | 1169 | } |
| 1036 | 1170 | |
| 1037 | 1171 | av_free(sorted_segments); |
| @@ -1095,7 +1229,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 57 unmodified lines | ||
| 1095 | 1229 | } |
| 1096 | 1230 | } |
| 1097 | 1231 | if (!source_package) { |
| 1098 | − av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source package found\n", material_track->track_id); | |
| 1232 | + av_dlog(mxf->fc, "material track %d: no corresponding source package found\n", material_track->track_id); | |
| 1099 | 1233 | break; |
| 1100 | 1234 | } |
| 1101 | 1235 | for (k = 0; k < source_package->tracks_count; k++) { |
| @@ -1116,6 +1250,18 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 14 unmodified lines | ||
| 1116 | 1250 | if (!source_track) |
| 1117 | 1251 | continue; |
| 1118 | 1252 | |
| 1253 | + if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) { | |
| 1254 | + av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n"); | |
| 1255 | + return -1; | |
| 1256 | + } | |
| 1257 | + | |
| 1258 | + /* 0001GL00.MXF.A1.mxf_opatom.mxf has the same SourcePackageID as 0001GL.MXF.V1.mxf_opatom.mxf | |
| 1259 | + * This would result in both files appearing to have two streams. Work around this by sanity checking DataDefinition */ | |
| 1260 | + if (memcmp(material_track->sequence->data_definition_ul, source_track->sequence->data_definition_ul, 16)) { | |
| 1261 | + av_log(mxf->fc, AV_LOG_ERROR, "material track %d: DataDefinition mismatch\n", material_track->track_id); | |
| 1262 | + continue; | |
| 1263 | + } | |
| 1264 | + | |
| 1119 | 1265 | st = avformat_new_stream(mxf->fc, NULL); |
| 1120 | 1266 | if (!st) { |
| 1121 | 1267 | av_log(mxf->fc, AV_LOG_ERROR, "could not allocate stream\n"); |
| @@ -1129,11 +1275,6 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 7 unmodified lines | ||
| 1129 | 1275 | st->start_time = component->start_position; |
| 1130 | 1276 | avpriv_set_pts_info(st, 64, material_track->edit_rate.num, material_track->edit_rate.den); |
| 1131 | 1277 | |
| 1132 | − if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) { | |
| 1133 | − av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n"); | |
| 1134 | − return -1; | |
| 1135 | − } | |
| 1136 | − | |
| 1137 | 1278 | PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul); |
| 1138 | 1279 | codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul); |
| 1139 | 1280 | st->codec->codec_type = codec_ul->id; |
| @@ -1175,6 +1316,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 35 unmodified lines | ||
| 1175 | 1316 | } |
| 1176 | 1317 | } |
| 1177 | 1318 | } |
| 1319 | + | |
| 1320 | + /* HACK: revert to the old demuxing/seeking scode for D-10 for now */ | |
| 1321 | + if (mxf_match_uid(essence_container_ul, mxf_d10_ul, 14)) | |
| 1322 | + mxf->d10 = 1; | |
| 1323 | + | |
| 1178 | 1324 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ |
| 1179 | 1325 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); |
| 1180 | 1326 | st->codec->codec_id = codec_ul->id; |
| @@ -1214,11 +1360,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) · 33 unmodified lines | ||
| 1214 | 1360 | } |
| 1215 | 1361 | } |
| 1216 | 1362 | if (st->codec->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) { |
| 1217 | − av_log(mxf->fc, AV_LOG_WARNING, "only frame wrapped mappings are correctly supported\n"); | |
| 1218 | − st->need_parsing = AVSTREAM_PARSE_FULL; | |
| 1363 | + /* TODO: decode timestamps */ | |
| 1364 | + st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; | |
| 1219 | 1365 | } |
| 1220 | 1366 | |
| 1221 | − if ((ret = mxf_parse_index(mxf, i, st))) | |
| 1367 | + if ((ret = mxf_parse_index(mxf, material_track->track_id, st))) | |
| 1222 | 1368 | return ret; |
| 1223 | 1369 | } |
| 1224 | 1370 | return 0; |
| @@ -1287,7 +1433,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF · 62 unmodified lines | ||
| 1287 | 1433 | } |
| 1288 | 1434 | if (ctx_size && tag == 0x3C0A) |
| 1289 | 1435 | avio_read(pb, ctx->uid, 16); |
| 1290 | − else if (read_child(ctx, pb, tag, size, uid) < 0) | |
| 1436 | + else if (read_child(ctx, pb, tag, size, uid, -1) < 0) | |
| 1291 | 1437 | return -1; |
| 1292 | 1438 | |
| 1293 | 1439 | avio_seek(pb, next, SEEK_SET); |
| @@ -1296,10 +1442,129 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF · 2 unmodified lines | ||
| 1296 | 1442 | return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0; |
| 1297 | 1443 | } |
| 1298 | 1444 | |
| 1445 | +/** | |
| 1446 | + * Seeks to the previous partition, if possible | |
| 1447 | + * @return <= 0 if we should stop parsing, > 0 if we should keep going | |
| 1448 | + */ | |
| 1449 | +static int mxf_seek_to_previous_partition(MXFContext *mxf) | |
| 1450 | +{ | |
| 1451 | + AVIOContext *pb = mxf->fc->pb; | |
| 1452 | + | |
| 1453 | + if (!mxf->current_partition || | |
| 1454 | + mxf->run_in + mxf->current_partition->previous_partition <= mxf->last_forward_tell) | |
| 1455 | + return 0; /* we've parsed all partitions */ | |
| 1456 | + | |
| 1457 | + /* seek to previous partition */ | |
| 1458 | + avio_seek(pb, mxf->run_in + mxf->current_partition->previous_partition, SEEK_SET); | |
| 1459 | + mxf->current_partition = NULL; | |
| 1460 | + | |
| 1461 | + av_dlog(mxf->fc, "seeking to previous partition\n"); | |
| 1462 | + | |
| 1463 | + return 1; | |
| 1464 | +} | |
| 1465 | + | |
| 1466 | +/** | |
| 1467 | + * Called when essence is encountered | |
| 1468 | + * @return <= 0 if we should stop parsing, > 0 if we should keep going | |
| 1469 | + */ | |
| 1470 | +static int mxf_parse_handle_essence(MXFContext *mxf) | |
| 1471 | +{ | |
| 1472 | + AVIOContext *pb = mxf->fc->pb; | |
| 1473 | + int64_t ret; | |
| 1474 | + | |
| 1475 | + if (!mxf->current_partition) { | |
| 1476 | + av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to PartitionPack\n"); | |
| 1477 | + return AVERROR_INVALIDDATA; | |
| 1478 | + } | |
| 1479 | + | |
| 1480 | + if (mxf->parsing_backward) { | |
| 1481 | + return mxf_seek_to_previous_partition(mxf); | |
| 1482 | + } else { | |
| 1483 | + if (!mxf->footer_partition) { | |
| 1484 | + av_dlog(mxf->fc, "no footer\n"); | |
| 1485 | + return 0; | |
| 1486 | + } | |
| 1487 | + | |
| 1488 | + av_dlog(mxf->fc, "seeking to footer\n"); | |
| 1489 | + | |
| 1490 | + /* remember where we were so we don't end up seeking further back than this */ | |
| 1491 | + mxf->last_forward_tell = avio_tell(pb); | |
| 1492 | + | |
| 1493 | + if (!pb->seekable) { | |
| 1494 | + av_log(mxf->fc, AV_LOG_INFO, "file is not seekable - not parsing footer\n"); | |
| 1495 | + return -1; | |
| 1496 | + } | |
| 1497 | + | |
| 1498 | + /* seek to footer partition and parse backward */ | |
| 1499 | + if ((ret = avio_seek(pb, mxf->run_in + mxf->footer_partition, SEEK_SET)) < 0) { | |
| 1500 | + av_log(mxf->fc, AV_LOG_ERROR, "failed to seek to footer @ 0x%"PRIx64" (%"PRId64") - partial file?\n", | |
| 1501 | + mxf->run_in + mxf->footer_partition, ret); | |
| 1502 | + return ret; | |
| 1503 | + } | |
| 1504 | + | |
| 1505 | + mxf->current_partition = NULL; | |
| 1506 | + mxf->parsing_backward = 1; | |
| 1507 | + } | |
| 1508 | + | |
| 1509 | + return 1; | |
| 1510 | +} | |
| 1511 | + | |
| 1512 | +/** | |
| 1513 | + * Called when the next partition or EOF is encountered | |
| 1514 | + * @return <= 0 if we should stop parsing, > 0 if we should keep going | |
| 1515 | + */ | |
| 1516 | +static int mxf_parse_handle_partition_or_eof(MXFContext *mxf) | |
| 1517 | +{ | |
| 1518 | + return mxf->parsing_backward ? mxf_seek_to_previous_partition(mxf) : 1; | |
| 1519 | +} | |
| 1520 | + | |
| 1521 | +/** | |
| 1522 | + * Figures out the proper offset and length of the essence container in each partition | |
| 1523 | + */ | |
| 1524 | +static void mxf_compute_essence_containers(MXFContext *mxf) | |
| 1525 | +{ | |
| 1526 | + int x; | |
| 1527 | + | |
| 1528 | + /* everything is already correct */ | |
| 1529 | + if (mxf->op == OPAtom) | |
| 1530 | + return; | |
| 1531 | + | |
| 1532 | + for (x = 0; x < mxf->partitions_count; x++) { | |
| 1533 | + MXFPartition *p = &mxf->partitions[x]; | |
| 1534 | + | |
| 1535 | + if (!p->body_sid) | |
| 1536 | + continue; /* BodySID == 0 -> no essence */ | |
| 1537 | + | |
| 1538 | + if (x >= mxf->partitions_count - 1) | |
| 1539 | + break; /* last partition - can't compute length (and we don't need to) */ | |
| 1540 | + | |
| 1541 | + /* essence container spans to the next partition */ | |
| 1542 | + p->essence_length = mxf->partitions[x+1].this_partition - p->essence_offset; | |
| 1543 | + | |
| 1544 | + if (p->essence_length < 0) { | |
| 1545 | + /* next ThisPartition < essence_offset */ | |
| 1546 | + p->essence_length = 0; | |
| 1547 | + av_log(mxf->fc, AV_LOG_ERROR, "partition %i: bad ThisPartition = %lx\n", | |
| 1548 | + x+1, mxf->partitions[x+1].this_partition); | |
| 1549 | + } | |
| 1550 | + } | |
| 1551 | +} | |
| 1552 | + | |
| 1553 | +static int64_t round_to_kag(int64_t position, int kag_size) | |
| 1554 | +{ | |
| 1555 | + /* TODO: account for run-in? the spec isn't clear whether KAG should account for it */ | |
| 1556 | + /* NOTE: kag_size may be any integer between 1 - 2^10 */ | |
| 1557 | + int64_t ret = (position / kag_size) * kag_size; | |
| 1558 | + return ret == position ? ret : ret + kag_size; | |
| 1559 | +} | |
| 1560 | + | |
| 1299 | 1561 | static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) |
| 1300 | 1562 | { |
| 1301 | 1563 | MXFContext *mxf = s->priv_data; |
| 1302 | 1564 | KLVPacket klv; |
| 1565 | + int64_t essence_offset = 0; | |
| 1566 | + | |
| 1567 | + mxf->last_forward_tell = INT64_MAX; | |
| 1303 | 1568 | |
| 1304 | 1569 | if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) { |
| 1305 | 1570 | av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n"); |
| @@ -1307,23 +1572,60 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 1 unmodified line | ||
| 1307 | 1572 | } |
| 1308 | 1573 | avio_seek(s->pb, -14, SEEK_CUR); |
| 1309 | 1574 | mxf->fc = s; |
| 1575 | + mxf->run_in = avio_tell(s->pb); | |
| 1576 | + | |
| 1310 | 1577 | while (!url_feof(s->pb)) { |
| 1311 | 1578 | const MXFMetadataReadTableEntry *metadata; |
| 1312 | 1579 | |
| 1313 | − if (klv_read_packet(&klv, s->pb) < 0) | |
| 1314 | − return -1; | |
| 1580 | + if (klv_read_packet(&klv, s->pb) < 0) { | |
| 1581 | + /* EOF - seek to previous partition or stop */ | |
| 1582 | + if(mxf_parse_handle_partition_or_eof(mxf) <= 0) | |
| 1583 | + break; | |
| 1584 | + else | |
| 1585 | + continue; | |
| 1586 | + } | |
| 1587 | + | |
| 1315 | 1588 | PRINT_KEY(s, "read header", klv.key); |
| 1316 | 1589 | av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); |
| 1317 | 1590 | if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || |
| 1318 | − IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
| 1319 | − /* FIXME avoid seek */ | |
| 1320 | − avio_seek(s->pb, klv.offset, SEEK_SET); | |
| 1321 | − break; | |
| 1322 | − } | |
| 1323 | − if (IS_KLV_KEY(klv.key, mxf_system_item_key)) { | |
| 1324 | − mxf->system_item = 1; | |
| 1325 | − avio_skip(s->pb, klv.length); | |
| 1591 | + IS_KLV_KEY(klv.key, mxf_essence_element_key) || | |
| 1592 | + IS_KLV_KEY(klv.key, mxf_system_item_key)) { | |
| 1593 | + if (!mxf->current_partition->essence_offset) { | |
| 1594 | + /* for OP1a we compute essence_offset | |
| 1595 | + * for OPAtom we point essence_offset after the KL (usually op1a_essence_offset + 20 or 25) | |
| 1596 | + * TODO: for OP1a we could eliminate this entire if statement, always stopping parsing at op1a_essence_offset | |
| 1597 | + * for OPAtom we still need the actual essence_offset though (the KL's length can vary) | |
| 1598 | + */ | |
| 1599 | + int64_t op1a_essence_offset = | |
| 1600 | + round_to_kag(mxf->current_partition->this_partition + | |
| 1601 | + mxf->current_partition->pack_length, mxf->current_partition->kag_size) + | |
| 1602 | + round_to_kag(mxf->current_partition->header_byte_count, mxf->current_partition->kag_size) + | |
| 1603 | + round_to_kag(mxf->current_partition->index_byte_count, mxf->current_partition->kag_size); | |
| 1604 | + | |
| 1605 | + if (mxf->op == OPAtom) { | |
| 1606 | + /* point essence_offset to the actual data | |
| 1607 | + * OPAtom has all the essence in one big KLV | |
| 1608 | + */ | |
| 1609 | + mxf->current_partition->essence_offset = avio_tell(s->pb); | |
| 1610 | + mxf->current_partition->essence_length = klv.length; | |
| 1611 | + } else { | |
| 1612 | + /* NOTE: op1a_essence_offset may be less than to klv.offset (C0023S01.mxf) */ | |
| 1613 | + mxf->current_partition->essence_offset = op1a_essence_offset; | |
| 1614 | + } | |
| 1615 | + } | |
| 1616 | + | |
| 1617 | + if (!essence_offset) | |
| 1618 | + essence_offset = klv.offset; | |
| 1619 | + | |
| 1620 | + /* seek to footer, previous partition or stop */ | |
| 1621 | + if (mxf_parse_handle_essence(mxf) <= 0) | |
| 1622 | + break; | |
| 1326 | 1623 | continue; |
| 1624 | + } else if (!memcmp(klv.key, mxf_header_partition_pack_key, 13) && | |
| 1625 | + klv.key[13] >= 2 && klv.key[13] <= 4 && mxf->current_partition) { | |
| 1626 | + /* next partition pack - keep going, seek to previous partition or stop */ | |
| 1627 | + if(mxf_parse_handle_partition_or_eof(mxf) <= 0) | |
| 1628 | + break; | |
| 1327 | 1629 | } |
| 1328 | 1630 | |
| 1329 | 1631 | for (metadata = mxf_metadata_read_table; metadata->read; metadata++) { |
| @@ -1333,7 +1635,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 3 unmodified lines | ||
| 1333 | 1635 | res = mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type); |
| 1334 | 1636 | } else { |
| 1335 | 1637 | uint64_t next = avio_tell(s->pb) + klv.length; |
| 1336 | − res = metadata->read(mxf, s->pb, 0, 0, klv.key); | |
| 1638 | + res = metadata->read(mxf, s->pb, 0, klv.length, klv.key, klv.offset); | |
| 1337 | 1639 | avio_seek(s->pb, next, SEEK_SET); |
| 1338 | 1640 | } |
| 1339 | 1641 | if (res < 0) { |
| @@ -1346,6 +1648,15 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 6 unmodified lines | ||
| 1346 | 1648 | if (!metadata->read) |
| 1347 | 1649 | avio_skip(s->pb, klv.length); |
| 1348 | 1650 | } |
| 1651 | + /* FIXME avoid seek */ | |
| 1652 | + if (!essence_offset) { | |
| 1653 | + av_log(s, AV_LOG_ERROR, "no essence\n"); | |
| 1654 | + return AVERROR_INVALIDDATA; | |
| 1655 | + } | |
| 1656 | + avio_seek(s->pb, essence_offset, SEEK_SET); | |
| 1657 | + | |
| 1658 | + mxf_compute_essence_containers(mxf); | |
| 1659 | + | |
| 1349 | 1660 | return mxf_parse_structural_metadata(mxf); |
| 1350 | 1661 | } |
| 1351 | 1662 | |
| @@ -1378,6 +1689,7 @@ static int mxf_read_close(AVFormatContext *s) · 26 unmodified lines | ||
| 1378 | 1689 | av_freep(&seg->slice_offset_entries[j]); |
| 1379 | 1690 | av_freep(&seg->slice); |
| 1380 | 1691 | av_freep(&seg->element_delta); |
| 1692 | + av_freep(&seg->temporal_offset_entries); | |
| 1381 | 1693 | av_freep(&seg->flag_entries); |
| 1382 | 1694 | av_freep(&seg->stream_offset_entries); |
| 1383 | 1695 | av_freep(&seg->slice_offset_entries); |
| @@ -1416,7 +1728,11 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti · 32 unmodified lines | ||
| 1416 | 1728 | { |
| 1417 | 1729 | AVStream *st = s->streams[stream_index]; |
| 1418 | 1730 | int64_t seconds; |
| 1731 | + MXFContext* mxf = s->priv_data; | |
| 1732 | + int64_t seekpos; | |
| 1733 | + int index; | |
| 1419 | 1734 | |
| 1735 | + if (mxf->d10) { | |
| 1420 | 1736 | if (!s->bit_rate) |
| 1421 | 1737 | return -1; |
| 1422 | 1738 | if (sample_time < 0) |
| @@ -1425,6 +1741,27 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti · 2 unmodified lines | ||
| 1425 | 1741 | if (avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET) < 0) |
| 1426 | 1742 | return -1; |
| 1427 | 1743 | ff_update_cur_dts(s, st, sample_time); |
| 1744 | + } else { | |
| 1745 | + if (st->nb_index_entries <= 0) | |
| 1746 | + return -1; | |
| 1747 | + | |
| 1748 | + index = av_index_search_timestamp(st, sample_time, flags); | |
| 1749 | + | |
| 1750 | + av_dlog(s, "stream %d, timestamp %"PRId64", sample %d\n", st->index, sample_time, index); | |
| 1751 | + | |
| 1752 | + if (index < 0) { | |
| 1753 | + if (sample_time < st->index_entries[0].timestamp) | |
| 1754 | + index = 0; | |
| 1755 | + else | |
| 1756 | + return -1; | |
| 1757 | + } | |
| 1758 | + | |
| 1759 | + seekpos = st->index_entries[index].pos; | |
| 1760 | + av_update_cur_dts(s, st, st->index_entries[index].timestamp); | |
| 1761 | + mxf->current_edit_unit = st->index_entries[index].timestamp; | |
| 1762 | + mxf->current_stream = 0; | |
| 1763 | + avio_seek(s->pb, seekpos, SEEK_SET); | |
| 1764 | + } | |
| 1428 | 1765 | return 0; |
| 1429 | 1766 | } |
| 1430 | 1767 | |
| @@ -2,52 +2,47 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 · 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: NOPTS pos: 6144 size: 24801 |
| 4 | 4 | ret: 0 st:-1 flags:1 ts: 1.894167 |
| 5 | −ret:-1 | |
| 5 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 6 | 6 | ret: 0 st: 0 flags:0 ts: 0.800000 |
| 7 | −ret:-1 | |
| 7 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 8 | 8 | ret: 0 st: 0 flags:1 ts:-0.320000 |
| 9 | 9 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 10 | −ret: 0 st: 1 flags:0 ts: 2.560000 | |
| 11 | −ret:-1 | |
| 10 | +ret:-1 st: 1 flags:0 ts: 2.560000 | |
| 12 | 11 | ret: 0 st: 1 flags:1 ts: 1.480000 |
| 13 | −ret:-1 | |
| 12 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 14 | 13 | ret: 0 st:-1 flags:0 ts: 0.365002 |
| 15 | −ret: 0 st: 0 flags:1 dts: 0.360000 pts: NOPTS pos: 6144 size: 24801 | |
| 14 | +ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 211968 size: 24787 | |
| 16 | 15 | ret: 0 st:-1 flags:1 ts:-0.740831 |
| 17 | 16 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 18 | −ret: 0 st: 0 flags:0 ts: 2.160000 | |
| 19 | −ret:-1 | |
| 17 | +ret:-1 st: 0 flags:0 ts: 2.160000 | |
| 20 | 18 | ret: 0 st: 0 flags:1 ts: 1.040000 |
| 21 | −ret:-1 | |
| 19 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 22 | 20 | ret: 0 st: 1 flags:0 ts:-0.040000 |
| 23 | 21 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 24 | 22 | ret: 0 st: 1 flags:1 ts: 2.840000 |
| 25 | −ret:-1 | |
| 26 | −ret: 0 st:-1 flags:0 ts: 1.730004 | |
| 27 | −ret:-1 | |
| 23 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 24 | +ret:-1 st:-1 flags:0 ts: 1.730004 | |
| 28 | 25 | ret: 0 st:-1 flags:1 ts: 0.624171 |
| 29 | −ret:-1 | |
| 26 | +ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 211968 size: 24787 | |
| 30 | 27 | ret: 0 st: 0 flags:0 ts:-0.480000 |
| 31 | 28 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 32 | 29 | ret: 0 st: 0 flags:1 ts: 2.400000 |
| 33 | −ret:-1 | |
| 34 | −ret: 0 st: 1 flags:0 ts: 1.320000 | |
| 35 | −ret:-1 | |
| 30 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 31 | +ret:-1 st: 1 flags:0 ts: 1.320000 | |
| 36 | 32 | ret: 0 st: 1 flags:1 ts: 0.200000 |
| 37 | −ret: 0 st: 0 flags:1 dts: 0.200000 pts: NOPTS pos: 6144 size: 24801 | |
| 33 | +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | |
| 38 | 34 | ret: 0 st:-1 flags:0 ts:-0.904994 |
| 39 | 35 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 40 | 36 | ret: 0 st:-1 flags:1 ts: 1.989173 |
| 41 | −ret:-1 | |
| 37 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 42 | 38 | ret: 0 st: 0 flags:0 ts: 0.880000 |
| 43 | −ret:-1 | |
| 39 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 44 | 40 | ret: 0 st: 0 flags:1 ts:-0.240000 |
| 45 | 41 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 46 | −ret: 0 st: 1 flags:0 ts: 2.680000 | |
| 47 | −ret:-1 | |
| 42 | +ret:-1 st: 1 flags:0 ts: 2.680000 | |
| 48 | 43 | ret: 0 st: 1 flags:1 ts: 1.560000 |
| 49 | −ret:-1 | |
| 44 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 50 | 45 | ret: 0 st:-1 flags:0 ts: 0.460008 |
| 51 | −ret: 0 st: 0 flags:1 dts: 0.480000 pts: NOPTS pos: 6144 size: 24801 | |
| 46 | +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 | |
| 52 | 47 | ret: 0 st:-1 flags:1 ts:-0.645825 |
| 53 | 48 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |