diff options
author | Tomas Härdin <tomas.hardin@codemill.se> | 2011-12-08 11:18:21 +0100 |
---|---|---|
committer | Tomas Härdin <tomas.hardin@codemill.se> | 2011-12-08 18:19:44 +0100 |
commit | 336246238e8251840bb6f93e4110884c0b4ee8e6 (patch) | |
tree | 5363b8d5cbe36c8cab0b9b331dd2b945896906d1 | |
parent | 289bc14449bba2ba62d8ede4b22925055670055c (diff) | |
download | ffmpeg-336246238e8251840bb6f93e4110884c0b4ee8e6.tar.gz |
mxfdec: Compute essence container offsets and lengths into mxf->partitions
-rw-r--r-- | libavformat/mxfdec.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 26024ae90a..179d3a75db 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -79,6 +79,8 @@ typedef struct { int index_sid; int body_sid; int64_t this_partition; + int64_t essence_offset; /* absolute offset of essence */ + int64_t essence_length; } MXFPartition; typedef struct { @@ -1401,6 +1403,46 @@ static int mxf_parse_handle_partition_or_eof(MXFContext *mxf) return mxf->parsing_backward ? mxf_seek_to_previous_partition(mxf) : 1; } +/** + * Figures out the proper offset and length of the essence container in each partition + */ +static void mxf_compute_essence_containers(MXFContext *mxf) +{ + int x; + + /* everything is already correct */ + if (mxf->op == OPAtom) + return; + + for (x = 0; x < mxf->partitions_count; x++) { + MXFPartition *p = &mxf->partitions[x]; + + if (!p->body_sid) + continue; /* BodySID == 0 -> no essence */ + + if (x >= mxf->partitions_count - 1) + break; /* last partition - can't compute length (and we don't need to) */ + + /* essence container spans to the next partition */ + p->essence_length = mxf->partitions[x+1].this_partition - p->essence_offset; + + if (p->essence_length < 0) { + /* next ThisPartition < essence_offset */ + p->essence_length = 0; + av_log(mxf->fc, AV_LOG_ERROR, "partition %i: bad ThisPartition = %lx\n", + x+1, mxf->partitions[x+1].this_partition); + } + } +} + +static int64_t round_to_kag(int64_t position, int kag_size) +{ + /* TODO: account for run-in? the spec isn't clear whether KAG should account for it */ + /* NOTE: kag_size may be any integer between 1 - 2^10 */ + int64_t ret = (position / kag_size) * kag_size; + return ret == position ? ret : ret + kag_size; +} + static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) { MXFContext *mxf = s->priv_data; @@ -1432,6 +1474,30 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_system_item_key)) { + if (!mxf->current_partition->essence_offset) { + /* for OP1a we compute essence_offset + * for OPAtom we point essence_offset after the KL (usually op1a_essence_offset + 20 or 25) + * TODO: for OP1a we could eliminate this entire if statement, always stopping parsing at op1a_essence_offset + * for OPAtom we still need the actual essence_offset though (the KL's length can vary) + */ + int64_t op1a_essence_offset = + round_to_kag(mxf->current_partition->this_partition + + mxf->current_partition->pack_length, mxf->current_partition->kag_size) + + round_to_kag(mxf->current_partition->header_byte_count, mxf->current_partition->kag_size) + + round_to_kag(mxf->current_partition->index_byte_count, mxf->current_partition->kag_size); + + if (mxf->op == OPAtom) { + /* point essence_offset to the actual data + * OPAtom has all the essence in one big KLV + */ + mxf->current_partition->essence_offset = avio_tell(s->pb); + mxf->current_partition->essence_length = klv.length; + } else { + /* NOTE: op1a_essence_offset may be less than to klv.offset (C0023S01.mxf) */ + mxf->current_partition->essence_offset = op1a_essence_offset; + } + } + if (IS_KLV_KEY(klv.key, mxf_system_item_key)) { mxf->system_item = 1; } @@ -1481,6 +1547,9 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) return AVERROR_INVALIDDATA; } avio_seek(s->pb, mxf->essence_offset, SEEK_SET); + + mxf_compute_essence_containers(mxf); + return mxf_parse_structural_metadata(mxf); } |