This replaces the old essence_offset code
Unified · Split
| @@ -190,9 +190,6 @@ typedef struct { · 189 unmodified lines | ||
| 190 | 190 | uint8_t *local_tags; |
| 191 | 191 | int local_tags_count; |
| 192 | 192 | uint64_t footer_partition; |
| 193 | − int64_t essence_offset; | |
| 194 | − int first_essence_kl_length; | |
| 195 | − int64_t first_essence_length; | |
| 196 | 193 | KLVPacket current_klv_data; |
| 197 | 194 | int current_klv_index; |
| 198 | 195 | int run_in; |
| @@ -985,9 +982,36 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment · 786 unmodified lines | ||
| 985 | 982 | return 0; |
| 986 | 983 | } |
| 987 | 984 | |
| 985 | +/** | |
| 986 | + * Computes the absolute file offset of the given essence container offset | |
| 987 | + */ | |
| 988 | +static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out) | |
| 989 | +{ | |
| 990 | + int x; | |
| 991 | + int64_t offset_in = offset; /* for logging */ | |
| 992 | + | |
| 993 | + for (x = 0; x < mxf->partitions_count; x++) { | |
| 994 | + MXFPartition *p = &mxf->partitions[x]; | |
| 995 | + | |
| 996 | + if (p->body_sid != body_sid) | |
| 997 | + continue; | |
| 998 | + | |
| 999 | + if (offset < p->essence_length || !p->essence_length) { | |
| 1000 | + *offset_out = p->essence_offset + offset; | |
| 1001 | + return 0; | |
| 1002 | + } | |
| 1003 | + | |
| 1004 | + offset -= p->essence_length; | |
| 1005 | + } | |
| 1006 | + | |
| 1007 | + av_log(mxf->fc, AV_LOG_ERROR, "failed to find absolute offset of %lx in BodySID %i - partial file?\n", | |
| 1008 | + offset_in, body_sid); | |
| 1009 | + | |
| 1010 | + return AVERROR_INVALIDDATA; | |
| 1011 | +} | |
| 1012 | + | |
| 988 | 1013 | static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st) |
| 989 | 1014 | { |
| 990 | − int64_t accumulated_offset = 0; | |
| 991 | 1015 | int j, k, ret, nb_sorted_segments; |
| 992 | 1016 | MXFIndexTableSegment **sorted_segments; |
| 993 | 1017 | int n_delta = track_id - 1; /* TrackID = 1-based stream index */ |
| @@ -1005,10 +1029,6 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st) · 11 unmodified lines | ||
| 1005 | 1029 | int64_t segment_size; |
| 1006 | 1030 | MXFIndexTableSegment *tableseg = sorted_segments[j]; |
| 1007 | 1031 | |
| 1008 | − /* reset accumulated_offset on BodySID change */ | |
| 1009 | − if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid) | |
| 1010 | − accumulated_offset = 0; | |
| 1011 | − | |
| 1012 | 1032 | if (n_delta >= tableseg->nb_delta_entries && st->index != 0) |
| 1013 | 1033 | continue; |
| 1014 | 1034 | duration = tableseg->index_duration > 0 ? tableseg->index_duration : |
| @@ -1054,7 +1074,7 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st) · 39 unmodified lines | ||
| 1054 | 1074 | size = 0; |
| 1055 | 1075 | flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0; |
| 1056 | 1076 | } else { |
| 1057 | − pos = (int64_t)k * tableseg->edit_unit_byte_count + accumulated_offset; | |
| 1077 | + pos = (int64_t)(tableseg->index_start_position + k) * tableseg->edit_unit_byte_count; | |
| 1058 | 1078 | if (n_delta < tableseg->nb_delta_entries - 1) |
| 1059 | 1079 | size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta]; |
| 1060 | 1080 | else { |
| @@ -1071,10 +1091,10 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st) · 10 unmodified lines | ||
| 1071 | 1091 | flags = AVINDEX_KEYFRAME; |
| 1072 | 1092 | } |
| 1073 | 1093 | |
| 1074 | − if (k > 0 && pos < mxf->first_essence_length && accumulated_offset == 0) | |
| 1075 | − pos += mxf->first_essence_kl_length; | |
| 1076 | − | |
| 1077 | − pos += mxf->essence_offset; | |
| 1094 | + if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos, &pos) < 0) { | |
| 1095 | + /* probably partial file - no point going further for this stream */ | |
| 1096 | + break; | |
| 1097 | + } | |
| 1078 | 1098 | |
| 1079 | 1099 | av_dlog(mxf->fc, "Stream %d IndexEntry %d TrackID %d Offset %"PRIx64" Timestamp %"PRId64"\n", |
| 1080 | 1100 | st->index, st->nb_index_entries, track_id, pos, sample_duration * st->nb_index_entries); |
| @@ -1082,7 +1102,6 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st) · 1 unmodified line | ||
| 1082 | 1102 | if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0) |
| 1083 | 1103 | return ret; |
| 1084 | 1104 | } |
| 1085 | − accumulated_offset += segment_size; | |
| 1086 | 1105 | } |
| 1087 | 1106 | |
| 1088 | 1107 | av_free(sorted_segments); |
| @@ -1474,6 +1493,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 385 unmodified lines | ||
| 1474 | 1493 | { |
| 1475 | 1494 | MXFContext *mxf = s->priv_data; |
| 1476 | 1495 | KLVPacket klv; |
| 1496 | + int64_t essence_offset = 0; | |
| 1477 | 1497 | |
| 1478 | 1498 | mxf->last_forward_tell = INT64_MAX; |
| 1479 | 1499 | |
| @@ -1525,13 +1545,8 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 45 unmodified lines | ||
| 1525 | 1545 | } |
| 1526 | 1546 | } |
| 1527 | 1547 | |
| 1528 | − if (!mxf->essence_offset) | |
| 1529 | − mxf->essence_offset = klv.offset; | |
| 1530 | − | |
| 1531 | − if (!mxf->first_essence_kl_length && IS_KLV_KEY(klv.key, mxf_essence_element_key)) { | |
| 1532 | − mxf->first_essence_kl_length = avio_tell(s->pb) - klv.offset; | |
| 1533 | − mxf->first_essence_length = klv.length; | |
| 1534 | − } | |
| 1548 | + if (!essence_offset) | |
| 1549 | + essence_offset = klv.offset; | |
| 1535 | 1550 | |
| 1536 | 1551 | /* seek to footer, previous partition or stop */ |
| 1537 | 1552 | if (mxf_parse_handle_essence(mxf) <= 0) |
| @@ -1565,11 +1580,11 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) · 27 unmodified lines | ||
| 1565 | 1580 | avio_skip(s->pb, klv.length); |
| 1566 | 1581 | } |
| 1567 | 1582 | /* FIXME avoid seek */ |
| 1568 | − if (!mxf->essence_offset) { | |
| 1583 | + if (!essence_offset) { | |
| 1569 | 1584 | av_log(s, AV_LOG_ERROR, "no essence\n"); |
| 1570 | 1585 | return AVERROR_INVALIDDATA; |
| 1571 | 1586 | } |
| 1572 | − avio_seek(s->pb, mxf->essence_offset, SEEK_SET); | |
| 1587 | + avio_seek(s->pb, essence_offset, SEEK_SET); | |
| 1573 | 1588 | |
| 1574 | 1589 | mxf_compute_essence_containers(mxf); |
| 1575 | 1590 | |