[FFmpeg-cvslog] avformat/mxfdec: compute both essence_offset and essence_length in mxf_compute_essence_containers
Marton Balint
git at videolan.org
Sun Jun 24 21:44:11 EEST 2018
ffmpeg | branch: master | Marton Balint <cus at passwd.hu> | Wed May 23 23:20:44 2018 +0200| [6345770eeb974dcf2197ef145a92051125415884] | committer: Marton Balint
avformat/mxfdec: compute both essence_offset and essence_length in mxf_compute_essence_containers
Also compute the correct essence_offset and essence_length for all clip wrapped
essences.
Signed-off-by: Marton Balint <cus at passwd.hu>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=6345770eeb974dcf2197ef145a92051125415884
---
libavformat/mxfdec.c | 108 +++++++++++++++++++++++++++------------------------
1 file changed, 57 insertions(+), 51 deletions(-)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index d5bb0c5911..2c153a20e2 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -98,6 +98,7 @@ typedef struct MXFPartition {
int pack_length;
int64_t pack_ofs; ///< absolute offset of pack in file, including run-in
int64_t body_offset;
+ KLVPacket first_essence_klv;
} MXFPartition;
typedef struct MXFCryptoContext {
@@ -2784,47 +2785,76 @@ static int mxf_parse_handle_partition_or_eof(MXFContext *mxf)
return mxf->parsing_backward ? mxf_seek_to_previous_partition(mxf) : 1;
}
+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 MXFWrappingScheme mxf_get_wrapping_by_body_sid(AVFormatContext *s, int body_sid)
+{
+ for (int i = 0; i < s->nb_streams; i++) {
+ MXFTrack *track = s->streams[i]->priv_data;
+ if (track && track->body_sid == body_sid && track->wrapping != UnknownWrapped)
+ return track->wrapping;
+ }
+ return UnknownWrapped;
+}
+
/**
* Figures out the proper offset and length of the essence container in each partition
*/
-static void mxf_compute_essence_containers(MXFContext *mxf)
+static void mxf_compute_essence_containers(AVFormatContext *s)
{
+ MXFContext *mxf = s->priv_data;
int x;
- /* everything is already correct */
- if (mxf->op == OPAtom)
- return;
-
for (x = 0; x < mxf->partitions_count; x++) {
MXFPartition *p = &mxf->partitions[x];
+ MXFWrappingScheme wrapping;
if (!p->body_sid)
continue; /* BodySID == 0 -> no essence */
- if (x >= mxf->partitions_count - 1)
- break; /* FooterPartition - can't compute length (and we don't need to) */
+ /* for non clip-wrapped essences we compute essence_offset
+ * for clip wrapped essences we point essence_offset after the KL (usually klv.offset + 20 or 25)
+ */
- /* essence container spans to the next partition */
- p->essence_length = mxf->partitions[x+1].this_partition - p->essence_offset;
+ wrapping = (mxf->op == OPAtom) ? ClipWrapped : mxf_get_wrapping_by_body_sid(s, p->body_sid);
- if (p->essence_length < 0) {
- /* next ThisPartition < essence_offset */
- p->essence_length = 0;
- av_log(mxf->fc, AV_LOG_ERROR,
- "partition %i: bad ThisPartition = %"PRIX64"\n",
- x+1, mxf->partitions[x+1].this_partition);
+ if (wrapping == ClipWrapped) {
+ p->essence_offset = p->first_essence_klv.next_klv - p->first_essence_klv.length;
+ p->essence_length = p->first_essence_klv.length;
+ } else {
+ int64_t op1a_essence_offset =
+ p->this_partition +
+ round_to_kag(p->pack_length, p->kag_size) +
+ round_to_kag(p->header_byte_count, p->kag_size) +
+ round_to_kag(p->index_byte_count, p->kag_size);
+
+ /* NOTE: op1a_essence_offset may be less than to klv.offset (C0023S01.mxf) */
+ if (IS_KLV_KEY(p->first_essence_klv.key, mxf_system_item_key_cp) || IS_KLV_KEY(p->first_essence_klv.key, mxf_system_item_key_gc))
+ p->essence_offset = p->first_essence_klv.offset;
+ else
+ p->essence_offset = op1a_essence_offset;
+
+ /* essence container spans to the next partition */
+ if (x < mxf->partitions_count - 1)
+ 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 = %"PRIX64"\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 is_pcm(enum AVCodecID codec_id)
{
/* we only care about "normal" PCM codecs until we get samples */
@@ -3036,32 +3066,8 @@ static int mxf_read_header(AVFormatContext *s)
return AVERROR_INVALIDDATA;
}
- 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 =
- mxf->current_partition->this_partition +
- round_to_kag(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) */
- if (IS_KLV_KEY(klv.key, mxf_system_item_key_cp) || IS_KLV_KEY(klv.key, mxf_system_item_key_gc))
- mxf->current_partition->essence_offset = klv.offset;
- else
- mxf->current_partition->essence_offset = op1a_essence_offset;
- }
- }
+ if (!mxf->current_partition->first_essence_klv.offset)
+ mxf->current_partition->first_essence_klv = klv;
if (!essence_offset)
essence_offset = klv.offset;
@@ -3100,8 +3106,6 @@ static int mxf_read_header(AVFormatContext *s)
}
avio_seek(s->pb, essence_offset, SEEK_SET);
- mxf_compute_essence_containers(mxf);
-
/* we need to do this before computing the index tables
* to be able to fill in zero IndexDurations with st->duration */
if ((ret = mxf_parse_structural_metadata(mxf)) < 0)
@@ -3123,6 +3127,8 @@ static int mxf_read_header(AVFormatContext *s)
goto fail;
}
+ mxf_compute_essence_containers(s);
+
mxf_handle_small_eubc(s);
return 0;
More information about the ffmpeg-cvslog
mailing list