* 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 | OP3b, | 69 | OP3b, |
| 70 | OP3c, | 70 | OP3c, |
| 71 | OPAtom, | 71 | OPAtom, |
| 72 | OPSONYOpt, /* FATE sample, violates the spec in places */ | ||
| 72 | } MXFOP; | 73 | } MXFOP; |
| 73 | 74 | ||
| 74 | typedef struct { | 75 | typedef struct { |
| @@ -78,6 +79,13 @@ typedef struct { · 3 unmodified lines | |||
| 78 | uint64_t previous_partition; | 79 | uint64_t previous_partition; |
| 79 | int index_sid; | 80 | int index_sid; |
| 80 | int body_sid; | 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 | } MXFPartition; | 89 | } MXFPartition; |
| 82 | 90 | ||
| 83 | typedef struct { | 91 | typedef struct { |
| @@ -147,6 +155,7 @@ typedef struct { · 63 unmodified lines | |||
| 147 | int *slice; | 155 | int *slice; |
| 148 | int *element_delta; | 156 | int *element_delta; |
| 149 | int nb_delta_entries; | 157 | int nb_delta_entries; |
| 158 | int8_t *temporal_offset_entries; | ||
| 150 | int *flag_entries; | 159 | int *flag_entries; |
| 151 | uint64_t *stream_offset_entries; | 160 | uint64_t *stream_offset_entries; |
| 152 | uint32_t **slice_offset_entries; | 161 | uint32_t **slice_offset_entries; |
| @@ -181,12 +190,16 @@ typedef struct { · 28 unmodified lines | |||
| 181 | uint8_t *local_tags; | 190 | uint8_t *local_tags; |
| 182 | int local_tags_count; | 191 | int local_tags_count; |
| 183 | uint64_t footer_partition; | 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 | KLVPacket current_klv_data; | 193 | KLVPacket current_klv_data; |
| 189 | int current_klv_index; | 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 | } MXFContext; | 203 | } MXFContext; |
| 191 | 204 | ||
| 192 | enum MXFWrappingScheme { | 205 | enum MXFWrappingScheme { |
| @@ -194,7 +207,8 @@ enum MXFWrappingScheme { · 1 unmodified line | |||
| 194 | Clip, | 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 | typedef struct { | 213 | typedef struct { |
| 200 | const UID key; | 214 | const UID key; |
| @@ -361,7 +375,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv · 160 unmodified lines | |||
| 361 | return 0; | 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 | KLVPacket klv; | 380 | KLVPacket klv; |
| 367 | 381 | ||
| @@ -407,7 +421,66 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) · 39 unmodified lines | |||
| 407 | return AVERROR_EOF; | 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 | MXFContext *mxf = arg; | 485 | MXFContext *mxf = arg; |
| 413 | int item_num = avio_rb32(pb); | 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 | return 0; | 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 | MXFContext *mxf = arg; | 505 | MXFContext *mxf = arg; |
| 433 | MXFPartition *partition; | 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 | if (!mxf->partitions) | 514 | if (!mxf->partitions) |
| 442 | return AVERROR(ENOMEM); | 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 | switch(uid[13]) { | 533 | switch(uid[13]) { |
| 447 | case 2: | 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 | /* consider both footers to be closed (there is only Footer and CompleteFooter) */ | 548 | /* consider both footers to be closed (there is only Footer and CompleteFooter) */ |
| 462 | partition->closed = partition->type == Footer || !(uid[14] & 1); | 549 | partition->closed = partition->type == Footer || !(uid[14] & 1); |
| 463 | partition->complete = uid[14] > 2; | 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 | partition->previous_partition = avio_rb64(pb); | 554 | partition->previous_partition = avio_rb64(pb); |
| 466 | footer_partition = avio_rb64(pb); | 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 | partition->index_sid = avio_rb32(pb); | 558 | partition->index_sid = avio_rb32(pb); |
| 469 | avio_skip(pb, 8); | 559 | avio_skip(pb, 8); |
| 470 | partition->body_sid = avio_rb32(pb); | 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 | "FooterPartition = 0x%lx, IndexSID = %i, BodySID = %i\n", | 574 | "FooterPartition = 0x%lx, IndexSID = %i, BodySID = %i\n", |
| 575 | partition->this_partition, | ||
| 485 | partition->previous_partition, footer_partition, | 576 | partition->previous_partition, footer_partition, |
| 486 | partition->index_sid, partition->body_sid); | 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 | else if (op[12] == 3 && op[13] == 2) mxf->op = OP3b; | 586 | else if (op[12] == 3 && op[13] == 2) mxf->op = OP3b; |
| 496 | else if (op[12] == 3 && op[13] == 3) mxf->op = OP3c; | 587 | else if (op[12] == 3 && op[13] == 3) mxf->op = OP3c; |
| 497 | else if (op[12] == 0x10) mxf->op = OPAtom; | 588 | else if (op[12] == 0x10) mxf->op = OPAtom; |
| 498 | else | 589 | else if (op[12] == 64&& op[13] == 1) mxf->op = OPSONYOpt; |
| 499 | av_log(mxf->fc, AV_LOG_ERROR, "unknown operational pattern: %02xh %02xh\n", op[12], op[13]); | 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 | return 0; | 606 | return 0; |
| 502 | } | 607 | } |
| @@ -513,7 +618,7 @@ static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) · 10 unmodified lines | |||
| 513 | return 0; | 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 | MXFCryptoContext *cryptocontext = arg; | 623 | MXFCryptoContext *cryptocontext = arg; |
| 519 | if (size != 16) | 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 | return 0; | 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 | MXFContext *mxf = arg; | 633 | MXFContext *mxf = arg; |
| 529 | switch (tag) { | 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 | return 0; | 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 | MXFStructuralComponent *source_clip = arg; | 651 | MXFStructuralComponent *source_clip = arg; |
| 547 | switch(tag) { | 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 | return 0; | 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 | MXFPackage *package = arg; | 673 | MXFPackage *package = arg; |
| 569 | switch(tag) { | 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 | return 0; | 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 | MXFTrack *track = arg; | 691 | MXFTrack *track = arg; |
| 587 | switch(tag) { | 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 | return 0; | 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 | MXFSequence *sequence = arg; | 712 | MXFSequence *sequence = arg; |
| 608 | switch(tag) { | 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 | return 0; | 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 | MXFPackage *package = arg; | 736 | MXFPackage *package = arg; |
| 632 | switch(tag) { | 737 | switch(tag) { |
| @@ -678,7 +783,8 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 45 unmodified lines | |||
| 678 | segment->nb_index_entries = avio_rb32(pb); | 783 | segment->nb_index_entries = avio_rb32(pb); |
| 679 | length = avio_rb32(pb); | 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 | !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) | 788 | !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) |
| 683 | return AVERROR(ENOMEM); | 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 | return AVERROR(ENOMEM); | 793 | return AVERROR(ENOMEM); |
| 688 | 794 | ||
| 689 | for (i = 0; i < segment->nb_index_entries; i++) { | 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 | segment->flag_entries[i] = avio_r8(pb); | 798 | segment->flag_entries[i] = avio_r8(pb); |
| 692 | segment->stream_offset_entries[i] = avio_rb64(pb); | 799 | segment->stream_offset_entries[i] = avio_rb64(pb); |
| 693 | if (segment->slice_count) { | 800 | if (segment->slice_count) { |
| @@ -703,7 +810,7 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg · 9 unmodified lines | |||
| 703 | return 0; | 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 | MXFIndexTableSegment *segment = arg; | 815 | MXFIndexTableSegment *segment = arg; |
| 709 | switch(tag) { | 816 | switch(tag) { |
| @@ -766,7 +873,7 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) · 56 unmodified lines | |||
| 766 | ff_mxf_decode_pixel_layout(layout, &descriptor->pix_fmt); | 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 | MXFDescriptor *descriptor = arg; | 878 | MXFDescriptor *descriptor = arg; |
| 772 | switch(tag) { | 879 | switch(tag) { |
| @@ -876,9 +983,12 @@ static const MXFCodecUL mxf_essence_container_uls[] = { · 103 unmodified lines | |||
| 876 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */ | 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 | { { 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 */ | 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 | { { 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 */ | 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 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, CODEC_ID_NONE }, | 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 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) | 992 | static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments) |
| 883 | { | 993 | { |
| 884 | int i, j, nb_segments = 0; | 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 | return 0; | 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 | int j, k, ret, nb_sorted_segments; | 1079 | int j, k, ret, nb_sorted_segments; |
| 943 | MXFIndexTableSegment **sorted_segments; | 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 | if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments))) | 1088 | if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments))) |
| 946 | return ret; | 1089 | return ret; |
| 947 | 1090 | ||
| 948 | for (j = 0; j < nb_sorted_segments; j++) { | 1091 | for (j = 0; j < nb_sorted_segments; j++) { |
| 949 | int n_delta = i; | ||
| 950 | int duration, sample_duration = 1, last_sample_size = 0; | 1092 | int duration, sample_duration = 1, last_sample_size = 0; |
| 951 | int64_t segment_size; | 1093 | int64_t segment_size; |
| 952 | MXFIndexTableSegment *tableseg = sorted_segments[j]; | 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 | if (n_delta >= tableseg->nb_delta_entries && st->index != 0) | 1096 | if (n_delta >= tableseg->nb_delta_entries && st->index != 0) |
| 962 | continue; | 1097 | continue; |
| 963 | duration = tableseg->index_duration > 0 ? tableseg->index_duration : | 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 | size = 0; | 1138 | size = 0; |
| 1004 | flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0; | 1139 | flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0; |
| 1005 | } else { | 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 | if (n_delta < tableseg->nb_delta_entries - 1) | 1142 | if (n_delta < tableseg->nb_delta_entries - 1) |
| 1008 | size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta]; | 1143 | size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta]; |
| 1009 | else { | 1144 | else { |
| @@ -1020,18 +1155,17 @@ static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st) · 10 unmodified lines | |||
| 1020 | flags = AVINDEX_KEYFRAME; | 1155 | flags = AVINDEX_KEYFRAME; |
| 1021 | } | 1156 | } |
| 1022 | 1157 | ||
| 1023 | if (k > 0 && pos < mxf->first_essence_length && accumulated_offset == 0) | 1158 | if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos, &pos) < 0) { |
| 1024 | pos += mxf->first_essence_kl_length; | 1159 | /* probably partial file - no point going further for this stream */ |
| 1025 | 1160 | break; | |
| 1026 | pos += mxf->essence_offset; | 1161 | } |
| 1027 | 1162 | ||
| 1028 | av_dlog(mxf->fc, "Stream %d IndexEntry %d n_Delta %d Offset %"PRIx64" Timestamp %"PRId64"\n", | 1163 | av_dlog(mxf->fc, "Stream %d IndexEntry %d TrackID %d Offset %"PRIx64" Timestamp %"PRId64"\n", |
| 1029 | st->index, st->nb_index_entries, n_delta, pos, sample_duration * st->nb_index_entries); | 1164 | st->index, st->nb_index_entries, track_id, pos, sample_duration * st->nb_index_entries); |
| 1030 | 1165 | ||
| 1031 | if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0) | 1166 | if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0) |
| 1032 | return ret; | 1167 | return ret; |
| 1033 | } | 1168 | } |
| 1034 | accumulated_offset += segment_size; | ||
| 1035 | } | 1169 | } |
| 1036 | 1170 | ||
| 1037 | av_free(sorted_segments); | 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 | if (!source_package) { | 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 | break; | 1233 | break; |
| 1100 | } | 1234 | } |
| 1101 | for (k = 0; k < source_package->tracks_count; k++) { | 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 | if (!source_track) | 1250 | if (!source_track) |
| 1117 | continue; | 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 | st = avformat_new_stream(mxf->fc, NULL); | 1265 | st = avformat_new_stream(mxf->fc, NULL); |
| 1120 | if (!st) { | 1266 | if (!st) { |
| 1121 | av_log(mxf->fc, AV_LOG_ERROR, "could not allocate stream\n"); | 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 | st->start_time = component->start_position; | 1275 | st->start_time = component->start_position; |
| 1130 | avpriv_set_pts_info(st, 64, material_track->edit_rate.num, material_track->edit_rate.den); | 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 | PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul); | 1278 | PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul); |
| 1138 | codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul); | 1279 | codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul); |
| 1139 | st->codec->codec_type = codec_ul->id; | 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 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ | 1324 | /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */ |
| 1179 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); | 1325 | codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul); |
| 1180 | st->codec->codec_id = codec_ul->id; | 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 | if (st->codec->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) { | 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"); | 1363 | /* TODO: decode timestamps */ |
| 1218 | st->need_parsing = AVSTREAM_PARSE_FULL; | 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 | return ret; | 1368 | return ret; |
| 1223 | } | 1369 | } |
| 1224 | return 0; | 1370 | return 0; |
| @@ -1287,7 +1433,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF · 62 unmodified lines | |||
| 1287 | } | 1433 | } |
| 1288 | if (ctx_size && tag == 0x3C0A) | 1434 | if (ctx_size && tag == 0x3C0A) |
| 1289 | avio_read(pb, ctx->uid, 16); | 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 | return -1; | 1437 | return -1; |
| 1292 | 1438 | ||
| 1293 | avio_seek(pb, next, SEEK_SET); | 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 | return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0; | 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 | static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) | 1561 | static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) |
| 1300 | { | 1562 | { |
| 1301 | MXFContext *mxf = s->priv_data; | 1563 | MXFContext *mxf = s->priv_data; |
| 1302 | KLVPacket klv; | 1564 | KLVPacket klv; |
| 1565 | int64_t essence_offset = 0; | ||
| 1566 | |||
| 1567 | mxf->last_forward_tell = INT64_MAX; | ||
| 1303 | 1568 | ||
| 1304 | if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) { | 1569 | if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) { |
| 1305 | av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n"); | 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 | avio_seek(s->pb, -14, SEEK_CUR); | 1573 | avio_seek(s->pb, -14, SEEK_CUR); |
| 1309 | mxf->fc = s; | 1574 | mxf->fc = s; |
| 1575 | mxf->run_in = avio_tell(s->pb); | ||
| 1576 | |||
| 1310 | while (!url_feof(s->pb)) { | 1577 | while (!url_feof(s->pb)) { |
| 1311 | const MXFMetadataReadTableEntry *metadata; | 1578 | const MXFMetadataReadTableEntry *metadata; |
| 1312 | 1579 | ||
| 1313 | if (klv_read_packet(&klv, s->pb) < 0) | 1580 | if (klv_read_packet(&klv, s->pb) < 0) { |
| 1314 | return -1; | 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 | PRINT_KEY(s, "read header", klv.key); | 1588 | PRINT_KEY(s, "read header", klv.key); |
| 1316 | av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); | 1589 | av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); |
| 1317 | if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || | 1590 | if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || |
| 1318 | IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | 1591 | IS_KLV_KEY(klv.key, mxf_essence_element_key) || |
| 1319 | /* FIXME avoid seek */ | 1592 | IS_KLV_KEY(klv.key, mxf_system_item_key)) { |
| 1320 | avio_seek(s->pb, klv.offset, SEEK_SET); | 1593 | if (!mxf->current_partition->essence_offset) { |
| 1321 | break; | 1594 | /* for OP1a we compute essence_offset |
| 1322 | } | 1595 | * for OPAtom we point essence_offset after the KL (usually op1a_essence_offset + 20 or 25) |
| 1323 | if (IS_KLV_KEY(klv.key, mxf_system_item_key)) { | 1596 | * TODO: for OP1a we could eliminate this entire if statement, always stopping parsing at op1a_essence_offset |
| 1324 | mxf->system_item = 1; | 1597 | * for OPAtom we still need the actual essence_offset though (the KL's length can vary) |
| 1325 | avio_skip(s->pb, klv.length); | 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 | continue; | 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 | for (metadata = mxf_metadata_read_table; metadata->read; metadata++) { | 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 | res = mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type); | 1635 | res = mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type); |
| 1334 | } else { | 1636 | } else { |
| 1335 | uint64_t next = avio_tell(s->pb) + klv.length; | 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 | avio_seek(s->pb, next, SEEK_SET); | 1639 | avio_seek(s->pb, next, SEEK_SET); |
| 1338 | } | 1640 | } |
| 1339 | if (res < 0) { | 1641 | if (res < 0) { |
| @@ -1346,6 +1648,15 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 6 unmodified lines | |||
| 1346 | if (!metadata->read) | 1648 | if (!metadata->read) |
| 1347 | avio_skip(s->pb, klv.length); | 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 | return mxf_parse_structural_metadata(mxf); | 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 | av_freep(&seg->slice_offset_entries[j]); | 1689 | av_freep(&seg->slice_offset_entries[j]); |
| 1379 | av_freep(&seg->slice); | 1690 | av_freep(&seg->slice); |
| 1380 | av_freep(&seg->element_delta); | 1691 | av_freep(&seg->element_delta); |
| 1692 | av_freep(&seg->temporal_offset_entries); | ||
| 1381 | av_freep(&seg->flag_entries); | 1693 | av_freep(&seg->flag_entries); |
| 1382 | av_freep(&seg->stream_offset_entries); | 1694 | av_freep(&seg->stream_offset_entries); |
| 1383 | av_freep(&seg->slice_offset_entries); | 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 | AVStream *st = s->streams[stream_index]; | 1729 | AVStream *st = s->streams[stream_index]; |
| 1418 | int64_t seconds; | 1730 | int64_t seconds; |
| 1731 | MXFContext* mxf = s->priv_data; | ||
| 1732 | int64_t seekpos; | ||
| 1733 | int index; | ||
| 1419 | 1734 | ||
| 1735 | if (mxf->d10) { | ||
| 1420 | if (!s->bit_rate) | 1736 | if (!s->bit_rate) |
| 1421 | return -1; | 1737 | return -1; |
| 1422 | if (sample_time < 0) | 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 | if (avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET) < 0) | 1741 | if (avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET) < 0) |
| 1426 | return -1; | 1742 | return -1; |
| 1427 | ff_update_cur_dts(s, st, sample_time); | 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 | return 0; | 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 | 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: NOPTS pos: 6144 size: 24801 | 3 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 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.880000 pts: NOPTS pos: 460800 size: 24712 |
| 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.880000 pts: NOPTS pos: 460800 size: 24712 |
| 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: NOPTS pos: 6144 size: 24801 | 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 | 10 | ret:-1 st: 1 flags:0 ts: 2.560000 |
| 11 | ret:-1 | ||
| 12 | ret: 0 st: 1 flags:1 ts: 1.480000 | 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 | ret: 0 st:-1 flags:0 ts: 0.365002 | 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 | ret: 0 st:-1 flags:1 ts:-0.740831 | 15 | ret: 0 st:-1 flags:1 ts:-0.740831 |
| 17 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | 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 | 17 | ret:-1 st: 0 flags:0 ts: 2.160000 |
| 19 | ret:-1 | ||
| 20 | ret: 0 st: 0 flags:1 ts: 1.040000 | 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 | ret: 0 st: 1 flags:0 ts:-0.040000 | 20 | ret: 0 st: 1 flags:0 ts:-0.040000 |
| 23 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | 21 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 24 | ret: 0 st: 1 flags:1 ts: 2.840000 | 22 | ret: 0 st: 1 flags:1 ts: 2.840000 |
| 25 | ret:-1 | 23 | ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 |
| 26 | ret: 0 st:-1 flags:0 ts: 1.730004 | 24 | ret:-1 st:-1 flags:0 ts: 1.730004 |
| 27 | ret:-1 | ||
| 28 | ret: 0 st:-1 flags:1 ts: 0.624171 | 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 | ret: 0 st: 0 flags:0 ts:-0.480000 | 27 | ret: 0 st: 0 flags:0 ts:-0.480000 |
| 31 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | 28 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 32 | ret: 0 st: 0 flags:1 ts: 2.400000 | 29 | ret: 0 st: 0 flags:1 ts: 2.400000 |
| 33 | ret:-1 | 30 | ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size: 24712 |
| 34 | ret: 0 st: 1 flags:0 ts: 1.320000 | 31 | ret:-1 st: 1 flags:0 ts: 1.320000 |
| 35 | ret:-1 | ||
| 36 | ret: 0 st: 1 flags:1 ts: 0.200000 | 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 | ret: 0 st:-1 flags:0 ts:-0.904994 | 34 | ret: 0 st:-1 flags:0 ts:-0.904994 |
| 39 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | 35 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |
| 40 | ret: 0 st:-1 flags:1 ts: 1.989173 | 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 | ret: 0 st: 0 flags:0 ts: 0.880000 | 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 | ret: 0 st: 0 flags:1 ts:-0.240000 | 40 | ret: 0 st: 0 flags:1 ts:-0.240000 |
| 45 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | 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 | 42 | ret:-1 st: 1 flags:0 ts: 2.680000 |
| 47 | ret:-1 | ||
| 48 | ret: 0 st: 1 flags:1 ts: 1.560000 | 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 | ret: 0 st:-1 flags:0 ts: 0.460008 | 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 | ret: 0 st:-1 flags:1 ts:-0.645825 | 47 | ret: 0 st:-1 flags:1 ts:-0.645825 |
| 53 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 | 48 | ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size: 24801 |