diff options
author | Michael Bradshaw <mbradshaw@sorensonmedia.com> | 2011-11-18 08:28:03 -0700 |
---|---|---|
committer | Michael Bradshaw <mbradshaw@sorensonmedia.com> | 2011-11-18 08:28:03 -0700 |
commit | 99252726e8a95bc457033de208dd9d0d56103e62 (patch) | |
tree | 45d6a0bb9cb7c8cb6bb51edfe639bd627fd4349d | |
parent | 7c92c03b8d0aec2b593ade85525c7a8f87fecc63 (diff) | |
parent | fd1cea6549c29c557b22021451ef6d0fe6ef2123 (diff) | |
download | ffmpeg-99252726e8a95bc457033de208dd9d0d56103e62.tar.gz |
Merge branch 'master' of git://git.videolan.org/ffmpeg
-rw-r--r-- | ffprobe.c | 21 | ||||
-rw-r--r-- | libavcodec/j2kdec.c | 2 | ||||
-rw-r--r-- | libavcodec/vp5.c | 8 | ||||
-rw-r--r-- | libavcodec/vp6.c | 9 | ||||
-rw-r--r-- | libavformat/mxfdec.c | 298 | ||||
-rw-r--r-- | libavformat/tls.c | 2 |
6 files changed, 313 insertions, 27 deletions
@@ -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); } diff --git a/libavcodec/j2kdec.c b/libavcodec/j2kdec.c index 0fb1600a6d..1f4acc53fd 100644 --- a/libavcodec/j2kdec.c +++ b/libavcodec/j2kdec.c @@ -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); } diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index 50bd868b51..23d0acc631 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -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]; diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 29fcecdb57..84876b7146 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -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]; } diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 5180d21f86..9bf4183298 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -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; } diff --git a/libavformat/tls.c b/libavformat/tls.c index 33ee782fa8..72c2b85016 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -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); |