Merge branch 'master' of git://git.videolan.org/ffmpeg
authorMichael Bradshaw <mbradshaw@sorensonmedia.com>
Fri, 18 Nov 2011 15:28:03 +0000 (08:28 -0700)
committerMichael Bradshaw <mbradshaw@sorensonmedia.com>
Fri, 18 Nov 2011 15:28:03 +0000 (08:28 -0700)
ffprobe.c
libavcodec/j2kdec.c
libavcodec/vp5.c
libavcodec/vp6.c
libavformat/mxfdec.c
libavformat/tls.c

index 8864594..52f07e7 100644 (file)
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -141,7 +141,7 @@ typedef struct Writer {
     void (*print_chapter_footer)(WriterContext *wctx, const char *);
     void (*print_section_header)(WriterContext *wctx, const char *);
     void (*print_section_footer)(WriterContext *wctx, const char *);
-    void (*print_integer)       (WriterContext *wctx, const char *, int);
+    void (*print_integer)       (WriterContext *wctx, const char *, long long int);
     void (*print_string)        (WriterContext *wctx, const char *, const char *);
     void (*show_tags)           (WriterContext *wctx, AVDictionary *dict);
     int flags;                  ///< a combination or WRITER_FLAG_*
@@ -254,7 +254,7 @@ static inline void writer_print_section_footer(WriterContext *wctx,
 }
 
 static inline void writer_print_integer(WriterContext *wctx,
-                                        const char *key, int val)
+                                        const char *key, long long int val)
 {
     wctx->writer->print_integer(wctx, key, val);
     wctx->nb_item++;
@@ -285,13 +285,10 @@ static void writer_print_time(WriterContext *wctx, const char *key,
 
 static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts)
 {
-    char buf[128];
-
     if (ts == AV_NOPTS_VALUE) {
         writer_print_string(wctx, key, "N/A", 1);
     } else {
-        snprintf(buf, sizeof(buf), "%"PRId64, ts);
-        writer_print_string(wctx, key, buf, 0);
+        writer_print_integer(wctx, key, ts);
     }
 }
 
@@ -436,9 +433,9 @@ static void default_print_str(WriterContext *wctx, const char *key, const char *
     printf("%s=%s\n", key, value);
 }
 
-static void default_print_int(WriterContext *wctx, const char *key, int value)
+static void default_print_int(WriterContext *wctx, const char *key, long long int value)
 {
-    printf("%s=%d\n", key, value);
+    printf("%s=%lld\n", key, value);
 }
 
 static void default_show_tags(WriterContext *wctx, AVDictionary *dict)
@@ -649,14 +646,14 @@ static void compact_print_str(WriterContext *wctx, const char *key, const char *
                                      value, compact->item_sep, wctx));
 }
 
-static void compact_print_int(WriterContext *wctx, const char *key, int value)
+static void compact_print_int(WriterContext *wctx, const char *key, long long int value)
 {
     CompactContext *compact = wctx->priv;
 
     if (wctx->nb_item) printf("%c", compact->item_sep);
     if (!compact->nokey)
         printf("%s=", key);
-    printf("%d", value);
+    printf("%lld", value);
 }
 
 static void compact_show_tags(WriterContext *wctx, AVDictionary *dict)
@@ -825,12 +822,12 @@ static void json_print_str(WriterContext *wctx, const char *key, const char *val
     json_print_item_str(wctx, key, value, INDENT);
 }
 
-static void json_print_int(WriterContext *wctx, const char *key, int value)
+static void json_print_int(WriterContext *wctx, const char *key, long long int value)
 {
     JSONContext *json = wctx->priv;
 
     if (wctx->nb_item) printf(",\n");
-    printf(INDENT "\"%s\": %d",
+    printf(INDENT "\"%s\": %lld",
            json_escape_str(&json->buf, &json->buf_size, key, wctx), value);
 }
 
index 0fb1600..1f4acc5 100644 (file)
@@ -227,7 +227,7 @@ static int get_siz(J2kDecoderContext *s)
         uint8_t x = bytestream_get_byte(&s->buf);
         s->cbps[i] = (x & 0x7f) + 1;
         s->precision = FFMAX(s->cbps[i], s->precision);
-        s->sgnd[i] = (x & 0x80) == 1;
+        s->sgnd[i] = !!(x & 0x80);
         s->cdx[i] = bytestream_get_byte(&s->buf);
         s->cdy[i] = bytestream_get_byte(&s->buf);
     }
index 50bd868..23d0acc 100644 (file)
@@ -185,7 +185,8 @@ static void vp5_parse_coeff(VP56Context *s)
         model1 = model->coeff_dccv[pt];
         model2 = model->coeff_dcct[pt][ctx];
 
-        for (coeff_idx=0; coeff_idx<64; ) {
+        coeff_idx = 0;
+        for (;;) {
             if (vp56_rac_get_prob(c, model2[0])) {
                 if (vp56_rac_get_prob(c, model2[2])) {
                     if (vp56_rac_get_prob(c, model2[3])) {
@@ -222,8 +223,11 @@ static void vp5_parse_coeff(VP56Context *s)
                 ct = 0;
                 s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 0;
             }
+            coeff_idx++;
+            if (coeff_idx >= 64)
+                break;
 
-            cg = vp5_coeff_groups[++coeff_idx];
+            cg = vp5_coeff_groups[coeff_idx];
             ctx = s->coeff_ctx[vp56_b6to4[b]][coeff_idx];
             model1 = model->coeff_ract[pt][ct][cg];
             model2 = cg > 2 ? model1 : model->coeff_acct[pt][ct][cg][ctx];
index 29fcecd..84876b7 100644 (file)
@@ -442,7 +442,8 @@ static void vp6_parse_coeff(VP56Context *s)
         model1 = model->coeff_dccv[pt];
         model2 = model->coeff_dcct[pt][ctx];
 
-        for (coeff_idx=0; coeff_idx<64; ) {
+        coeff_idx = 0;
+        for (;;) {
             if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) {
                 /* parse a coeff */
                 if (vp56_rac_get_prob(c, model2[2])) {
@@ -483,8 +484,10 @@ static void vp6_parse_coeff(VP56Context *s)
                             run += vp56_rac_get_prob(c, model3[i+8]) << i;
                 }
             }
-
-            cg = vp6_coeff_groups[coeff_idx+=run];
+            coeff_idx += run;
+            if (coeff_idx >= 64)
+                break;
+            cg = vp6_coeff_groups[coeff_idx];
             model1 = model2 = model->coeff_ract[pt][ct][cg];
         }
 
index 5180d21..9bf4183 100644 (file)
@@ -137,6 +137,20 @@ typedef struct {
 typedef struct {
     UID uid;
     enum MXFMetadataSetType type;
+    int edit_unit_byte_count;
+    int index_sid;
+    int body_sid;
+    int slice_count;
+    AVRational index_edit_rate;
+    uint64_t index_start_position;
+    uint64_t index_duration;
+    int *slice;
+    int *element_delta;
+    int nb_delta_entries;
+    int *flag_entries;
+    uint64_t *stream_offset_entries;
+    uint32_t **slice_offset_entries;
+    int nb_index_entries;
 } MXFIndexTableSegment;
 
 typedef struct {
@@ -167,6 +181,12 @@ typedef struct {
     uint8_t *local_tags;
     int local_tags_count;
     uint64_t footer_partition;
+    int system_item;
+    int64_t essence_offset;
+    int first_essence_kl_length;
+    int64_t first_essence_length;
+    KLVPacket current_klv_data;
+    int current_klv_index;
 } MXFContext;
 
 enum MXFWrappingScheme {
@@ -186,6 +206,7 @@ typedef struct {
 /* partial keys to match */
 static const uint8_t mxf_header_partition_pack_key[]       = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };
 static const uint8_t mxf_essence_element_key[]             = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };
+static const uint8_t mxf_system_item_key[]                 = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x03,0x01,0x04 };
 static const uint8_t mxf_klv_key[]                         = { 0x06,0x0e,0x2b,0x34 };
 /* complete keys to match */
 static const uint8_t mxf_crypto_source_container_ul[]      = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 };
@@ -631,15 +652,97 @@ static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size
     return 0;
 }
 
+static int mxf_read_delta_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment)
+{
+    int i, length;
+
+    segment->nb_delta_entries = avio_rb32(pb);
+    length = avio_rb32(pb);
+
+    if (!(segment->slice         = av_calloc(segment->nb_delta_entries, sizeof(*segment->slice))) ||
+        !(segment->element_delta = av_calloc(segment->nb_delta_entries, sizeof(*segment->element_delta))))
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < segment->nb_delta_entries; i++) {
+        avio_r8(pb);    /* PosTableIndex */
+        segment->slice[i] = avio_r8(pb);
+        segment->element_delta[i] = avio_rb32(pb);
+    }
+    return 0;
+}
+
+static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment)
+{
+    int i, j, length;
+
+    segment->nb_index_entries = avio_rb32(pb);
+    length = avio_rb32(pb);
+
+    if (!(segment->flag_entries          = av_calloc(segment->nb_index_entries, sizeof(*segment->flag_entries))) ||
+        !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries))))
+        return AVERROR(ENOMEM);
+
+    if (segment->slice_count &&
+        !(segment->slice_offset_entries  = av_calloc(segment->nb_index_entries, sizeof(*segment->slice_offset_entries))))
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < segment->nb_index_entries; i++) {
+        avio_rb16(pb);  /* TemporalOffset and KeyFrameOffset */
+        segment->flag_entries[i] = avio_r8(pb);
+        segment->stream_offset_entries[i] = avio_rb64(pb);
+        if (segment->slice_count) {
+            if (!(segment->slice_offset_entries[i] = av_calloc(segment->slice_count, sizeof(**segment->slice_offset_entries))))
+                return AVERROR(ENOMEM);
+
+            for (j = 0; j < segment->slice_count; j++)
+                segment->slice_offset_entries[i][j] = avio_rb32(pb);
+        }
+
+        avio_skip(pb, length - 11 - 4 * segment->slice_count);
+    }
+    return 0;
+}
+
 static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid)
 {
+    MXFIndexTableSegment *segment = arg;
     switch(tag) {
-    case 0x3F05: av_dlog(NULL, "EditUnitByteCount %d\n", avio_rb32(pb)); break;
-    case 0x3F06: av_dlog(NULL, "IndexSID %d\n", avio_rb32(pb)); break;
-    case 0x3F07: av_dlog(NULL, "BodySID %d\n", avio_rb32(pb)); break;
-    case 0x3F0B: av_dlog(NULL, "IndexEditRate %d/%d\n", avio_rb32(pb), avio_rb32(pb)); break;
-    case 0x3F0C: av_dlog(NULL, "IndexStartPosition %"PRIu64"\n", avio_rb64(pb)); break;
-    case 0x3F0D: av_dlog(NULL, "IndexDuration %"PRIu64"\n", avio_rb64(pb)); break;
+    case 0x3F05:
+        segment->edit_unit_byte_count = avio_rb32(pb);
+        av_dlog(NULL, "EditUnitByteCount %d\n", segment->edit_unit_byte_count);
+        break;
+    case 0x3F06:
+        segment->index_sid = avio_rb32(pb);
+        av_dlog(NULL, "IndexSID %d\n", segment->index_sid);
+        break;
+    case 0x3F07:
+        segment->body_sid = avio_rb32(pb);
+        av_dlog(NULL, "BodySID %d\n", segment->body_sid);
+        break;
+    case 0x3F08:
+        segment->slice_count = avio_r8(pb);
+        av_dlog(NULL, "SliceCount %d\n", segment->slice_count);
+        break;
+    case 0x3F09:
+        av_dlog(NULL, "DeltaEntryArray found\n");
+        return mxf_read_delta_entry_array(pb, segment);
+    case 0x3F0A:
+        av_dlog(NULL, "IndexEntryArray found\n");
+        return mxf_read_index_entry_array(pb, segment);
+    case 0x3F0B:
+        segment->index_edit_rate.num = avio_rb32(pb);
+        segment->index_edit_rate.den = avio_rb32(pb);
+        av_dlog(NULL, "IndexEditRate %d/%d\n", segment->index_edit_rate.num,
+                segment->index_edit_rate.den);
+        break;
+    case 0x3F0C:
+        segment->index_start_position = avio_rb64(pb);
+        av_dlog(NULL, "IndexStartPosition %"PRId64"\n", segment->index_start_position);
+        break;
+    case 0x3F0D:
+        segment->index_duration = avio_rb64(pb);
+        av_dlog(NULL, "IndexDuration %"PRId64"\n", segment->index_duration);
+        break;
     }
     return 0;
 }
@@ -776,11 +879,171 @@ static const MXFCodecUL mxf_essence_container_uls[] = {
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,      CODEC_ID_NONE },
 };
 
+static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments)
+{
+    int i, j, nb_segments = 0;
+    MXFIndexTableSegment **unsorted_segments;
+    int last_body_sid = -1, last_index_sid = -1, last_index_start = -1;
+
+    /* count number of segments, allocate arrays and copy unsorted segments */
+    for (i = 0; i < mxf->metadata_sets_count; i++)
+        if (mxf->metadata_sets[i]->type == IndexTableSegment)
+            nb_segments++;
+
+    if (!(unsorted_segments = av_calloc(nb_segments, sizeof(*unsorted_segments))) ||
+        !(*sorted_segments  = av_calloc(nb_segments, sizeof(**sorted_segments)))) {
+        av_free(unsorted_segments);
+        return AVERROR(ENOMEM);
+    }
+
+    for (i = j = 0; i < mxf->metadata_sets_count; i++)
+        if (mxf->metadata_sets[i]->type == IndexTableSegment)
+            unsorted_segments[j++] = (MXFIndexTableSegment*)mxf->metadata_sets[i];
+
+    *nb_sorted_segments = 0;
+
+    /* sort segments by {BodySID, IndexSID, IndexStartPosition}, remove duplicates while we're at it */
+    for (i = 0; i < nb_segments; i++) {
+        int best = -1, best_body_sid = -1, best_index_sid = -1, best_index_start = -1;
+
+        for (j = 0; j < nb_segments; j++) {
+            MXFIndexTableSegment *s = unsorted_segments[j];
+
+            /* Require larger BosySID, IndexSID or IndexStartPosition then the previous entry. This removes duplicates.
+             * We want the smallest values for the keys than what we currently have, unless this is the first such entry this time around.
+             */
+            if ((i == 0     || s->body_sid > last_body_sid || s->index_sid > last_index_sid || s->index_start_position > last_index_start) &&
+                (best == -1 || s->body_sid < best_body_sid || s->index_sid < best_index_sid || s->index_start_position < best_index_start)) {
+                best             = j;
+                best_body_sid    = s->body_sid;
+                best_index_sid   = s->index_sid;
+                best_index_start = s->index_start_position;
+            }
+        }
+
+        /* no suitable entry found -> we're done */
+        if (best == -1)
+            break;
+
+        (*sorted_segments)[(*nb_sorted_segments)++] = unsorted_segments[best];
+        last_body_sid    = best_body_sid;
+        last_index_sid   = best_index_sid;
+        last_index_start = best_index_start;
+    }
+
+    av_free(unsorted_segments);
+
+    return 0;
+}
+
+static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st)
+{
+    int64_t accumulated_offset = 0;
+    int j, k, ret, nb_sorted_segments;
+    MXFIndexTableSegment **sorted_segments;
+
+    if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments)))
+        return ret;
+
+    for (j = 0; j < nb_sorted_segments; j++) {
+        int n_delta = i;
+        int duration, sample_duration = 1, last_sample_size = 0;
+        int64_t segment_size;
+        MXFIndexTableSegment *tableseg = sorted_segments[j];
+
+        /* reset accumulated_offset on BodySID change */
+        if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid)
+            accumulated_offset = 0;
+
+        /* HACK: How to correctly link between streams and slices? */
+        if (i < mxf->system_item + st->index)
+            n_delta++;
+        if (n_delta >= tableseg->nb_delta_entries && st->index != 0)
+            continue;
+        duration = tableseg->index_duration > 0 ? tableseg->index_duration :
+            st->duration - st->nb_index_entries;
+        segment_size = tableseg->edit_unit_byte_count * duration;
+        /* check small EditUnitByteCount for audio */
+        if (tableseg->edit_unit_byte_count && tableseg->edit_unit_byte_count < 32
+            && !tableseg->index_duration) {
+            /* duration might be prime relative to the new sample_duration,
+             * which means we need to handle the last frame differently */
+            sample_duration = 8192;
+            last_sample_size = (duration % sample_duration) * tableseg->edit_unit_byte_count;
+            tableseg->edit_unit_byte_count *= sample_duration;
+            duration /= sample_duration;
+            if (last_sample_size) duration++;
+        }
+
+        for (k = 0; k < duration; k++) {
+            int64_t pos;
+            int size, flags = 0;
+
+            if (k < tableseg->nb_index_entries) {
+                pos = tableseg->stream_offset_entries[k];
+                if (n_delta < tableseg->nb_delta_entries) {
+                    if (n_delta < tableseg->nb_delta_entries - 1) {
+                        size =
+                            tableseg->slice_offset_entries[k][tableseg->slice[n_delta+1]-1] +
+                            tableseg->element_delta[n_delta+1] -
+                            tableseg->element_delta[n_delta];
+                        if (tableseg->slice[n_delta] > 0)
+                            size -= tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
+                    } else if (k < duration - 1) {
+                        size = tableseg->stream_offset_entries[k+1] -
+                            tableseg->stream_offset_entries[k] -
+                            tableseg->slice_offset_entries[k][tableseg->slice[tableseg->nb_delta_entries-1]-1] -
+                            tableseg->element_delta[tableseg->nb_delta_entries-1];
+                    } else
+                        size = 0;
+                    if (tableseg->slice[n_delta] > 0)
+                        pos += tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
+                    pos += tableseg->element_delta[n_delta];
+                } else
+                    size = 0;
+                flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0;
+            } else {
+                pos = (int64_t)k * tableseg->edit_unit_byte_count + accumulated_offset;
+                if (n_delta < tableseg->nb_delta_entries - 1)
+                    size = tableseg->element_delta[n_delta+1] - tableseg->element_delta[n_delta];
+                else {
+                    /* use smaller size for last sample if we should */
+                    if (last_sample_size && k == duration - 1)
+                        size = last_sample_size;
+                    else
+                        size = tableseg->edit_unit_byte_count;
+                    if (tableseg->nb_delta_entries)
+                        size -= tableseg->element_delta[tableseg->nb_delta_entries-1];
+                }
+                if (n_delta < tableseg->nb_delta_entries)
+                    pos += tableseg->element_delta[n_delta];
+                flags = AVINDEX_KEYFRAME;
+            }
+
+            if (k > 0 && pos < mxf->first_essence_length && accumulated_offset == 0)
+                pos += mxf->first_essence_kl_length;
+
+            pos += mxf->essence_offset;
+
+            av_dlog(mxf->fc, "Stream %d IndexEntry %d n_Delta %d Offset %"PRIx64" Timestamp %"PRId64"\n",
+                    st->index, st->nb_index_entries, n_delta, pos, sample_duration * st->nb_index_entries);
+
+            if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0)
+                return ret;
+        }
+        accumulated_offset += segment_size;
+    }
+
+    av_free(sorted_segments);
+
+    return 0;
+}
+
 static int mxf_parse_structural_metadata(MXFContext *mxf)
 {
     MXFPackage *material_package = NULL;
     MXFPackage *temp_package = NULL;
-    int i, j, k;
+    int i, j, k, ret;
 
     av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count);
     /* TODO: handle multiple material packages (OP3x) */
@@ -954,6 +1217,9 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             av_log(mxf->fc, AV_LOG_WARNING, "only frame wrapped mappings are correctly supported\n");
             st->need_parsing = AVSTREAM_PARSE_FULL;
         }
+
+        if ((ret = mxf_parse_index(mxf, i, st)))
+            return ret;
     }
     return 0;
 }
@@ -1054,6 +1320,11 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
             avio_seek(s->pb, klv.offset, SEEK_SET);
             break;
         }
+        if (IS_KLV_KEY(klv.key, mxf_system_item_key)) {
+            mxf->system_item = 1;
+            avio_skip(s->pb, klv.length);
+            continue;
+        }
 
         for (metadata = mxf_metadata_read_table; metadata->read; metadata++) {
             if (IS_KLV_KEY(klv.key, metadata->key)) {
@@ -1081,7 +1352,8 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 static int mxf_read_close(AVFormatContext *s)
 {
     MXFContext *mxf = s->priv_data;
-    int i;
+    MXFIndexTableSegment *seg;
+    int i, j;
 
     av_freep(&mxf->packages_refs);
 
@@ -1100,6 +1372,16 @@ static int mxf_read_close(AVFormatContext *s)
         case MaterialPackage:
             av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs);
             break;
+        case IndexTableSegment:
+            seg = (MXFIndexTableSegment *)mxf->metadata_sets[i];
+            for (j = 0; j < seg->nb_index_entries; j++)
+                av_freep(&seg->slice_offset_entries[j]);
+            av_freep(&seg->slice);
+            av_freep(&seg->element_delta);
+            av_freep(&seg->flag_entries);
+            av_freep(&seg->stream_offset_entries);
+            av_freep(&seg->slice_offset_entries);
+            break;
         default:
             break;
         }
index 33ee782..72c2b85 100644 (file)
@@ -147,7 +147,7 @@ static int tls_open(URLContext *h, const char *uri, int flags)
             goto fail;
     }
 #elif CONFIG_OPENSSL
-    c->ctx = SSL_CTX_new(SSLv3_client_method());
+    c->ctx = SSL_CTX_new(TLSv1_client_method());
     if (!c->ctx) {
         av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
         ret = AVERROR(EIO);