]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mxfdec.c
Merge commit 'cca5e4f040971db6de0bfe6968f00c021d8a9c42'
[ffmpeg] / libavformat / mxfdec.c
index e0a4b5bd11e6a9683506d363f4881c3160ea336f..7a4255556219027e0e8515e0b4f513f70500d3a9 100644 (file)
@@ -275,7 +275,7 @@ typedef struct MXFContext {
     int parsing_backward;
     int64_t last_forward_tell;
     int last_forward_partition;
-    int current_edit_unit;
+    int64_t current_edit_unit;
     int nb_index_tables;
     MXFIndexTable *index_tables;
     int edit_units_per_packet;      ///< how many edit units to read at a time (PCM, OPAtom)
@@ -565,6 +565,9 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
     uint64_t footer_partition;
     uint32_t nb_essence_containers;
 
+    if (mxf->partitions_count >= INT_MAX / 2)
+        return AVERROR_INVALIDDATA;
+
     tmp_part = av_realloc_array(mxf->partitions, mxf->partitions_count + 1, sizeof(*mxf->partitions));
     if (!tmp_part)
         return AVERROR(ENOMEM);
@@ -1347,24 +1350,30 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment
  */
 static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out)
 {
-    int x;
     MXFPartition *last_p = NULL;
+    int a, b, m, m0;
 
     if (offset < 0)
         return AVERROR(EINVAL);
 
-    for (x = 0; x < mxf->partitions_count; x++) {
-        MXFPartition *p = &mxf->partitions[x];
+    a = -1;
+    b = mxf->partitions_count;
 
-        if (p->body_sid != body_sid)
-            continue;
+    while (b - a > 1) {
+        m0 = m = (a + b) >> 1;
 
-        if (p->body_offset > offset)
-            break;
+        while (m < b && mxf->partitions[m].body_sid != body_sid)
+            m++;
 
-        last_p = p;
+        if (m < b && mxf->partitions[m].body_offset <= offset)
+            a = m;
+        else
+            b = m0;
     }
 
+    if (a >= 0)
+        last_p = &mxf->partitions[a];
+
     if (last_p && (!last_p->essence_length || last_p->essence_length > (offset - last_p->body_offset))) {
         *offset_out = last_p->essence_offset + (offset - last_p->body_offset);
         return 0;
@@ -2786,6 +2795,7 @@ static AVStream* mxf_get_opatom_stream(MXFContext *mxf)
 static void mxf_handle_small_eubc(AVFormatContext *s)
 {
     MXFContext *mxf = s->priv_data;
+    MXFTrack *track;
 
     /* assuming non-OPAtom == frame wrapped
      * no sane writer would wrap 2 byte PCM packets with 20 byte headers.. */
@@ -2805,7 +2815,8 @@ static void mxf_handle_small_eubc(AVFormatContext *s)
     /* TODO: We could compute this from the ratio between the audio
      *       and video edit rates for 48 kHz NTSC we could use the
      *       1802-1802-1802-1802-1801 pattern. */
-    mxf->edit_units_per_packet = 1920;
+    track = st->priv_data;
+    mxf->edit_units_per_packet = FFMAX(1, track->edit_rate.num / track->edit_rate.den / 25);
 }
 
 /**
@@ -3263,7 +3274,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
                  * truncate the packet since it's probably very large (>2 GiB is common) */
                 avpriv_request_sample(s,
                                       "OPAtom misinterpreted as OP1a? "
-                                      "KLV for edit unit %i extending into "
+                                      "KLV for edit unit %"PRId64" extending into "
                                       "next edit unit",
                                       mxf->current_edit_unit);
                 klv.length = next_ofs - avio_tell(s->pb);
@@ -3307,6 +3318,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
     int64_t ret64, pos, next_pos;
     AVStream *st;
     MXFIndexTable *t;
+    MXFTrack *track;
     int edit_units;
 
     if (mxf->op != OPAtom)
@@ -3317,14 +3329,16 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
     if (!st)
         return AVERROR_EOF;
 
+    track = st->priv_data;
+
     /* OPAtom - clip wrapped demuxing */
     /* NOTE: mxf_read_header() makes sure nb_index_tables > 0 for OPAtom */
     t = &mxf->index_tables[0];
 
-    if (mxf->current_edit_unit >= st->duration)
+    if (mxf->current_edit_unit >= track->original_duration)
         return AVERROR_EOF;
 
-    edit_units = FFMIN(mxf->edit_units_per_packet, st->duration - mxf->current_edit_unit);
+    edit_units = FFMIN(mxf->edit_units_per_packet, track->original_duration - mxf->current_edit_unit);
 
     if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit, NULL, &pos, 1)) < 0)
         return ret;