diff --git a/doc/APIchanges b/doc/APIchanges index 1d6d34b500..bb9d543b92 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,13 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-10-21 - xxxxxxx - lavc 54.68.100 - avcodec.h + lavfi 3.20.100 - avfilter.h + Add AV_PKT_DATA_STRINGS_METADATA side data type, used to transmit key/value + strings between AVPacket and AVFrame, and add metadata field to + AVCodecContext (which shall not be accessed by users; see AVFrame metadata + instead). + 2012-09-27 - a70b493 - lavd 54.3.100 - version.h Add LIBAVDEVICE_IDENT symbol. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0b3a19af19..3936d5e1c0 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -942,6 +942,12 @@ enum AVPacketSideDataType { * @endcode */ AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, }; typedef struct AVPacket { @@ -3091,6 +3097,13 @@ typedef struct AVCodecContext { int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far int64_t pts_correction_last_pts; /// PTS of the last frame int64_t pts_correction_last_dts; /// DTS of the last frame + + /** + * Current frame metadata. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + AVDictionary *metadata; } AVCodecContext; AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 1f9a029556..34dd42dbf0 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1018,8 +1018,9 @@ static int decode_frame(AVCodecContext *avctx, s->compr = TIFF_RAW; s->fill_order = 0; free_geotags(s); - /* free existing metadata */ - av_dict_free(&s->picture.metadata); + /* metadata has been destroyed from lavc internals, that pointer is not + * valid anymore */ + s->picture.metadata = NULL; // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number // that further identifies the file as a TIFF file" @@ -1169,8 +1170,6 @@ static av_cold int tiff_end(AVCodecContext *avctx) TiffContext *const s = avctx->priv_data; free_geotags(s); - if (avctx->coded_frame && avctx->coded_frame->metadata) - av_dict_free(&avctx->coded_frame->metadata); ff_lzw_decode_close(&s->lzw); if (s->picture.data[0]) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e4b3ed71c6..06999f5425 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1592,6 +1592,31 @@ static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) } } +static int add_metadata_from_side_data(AVCodecContext *avctx, AVFrame *frame) +{ + int size, ret = 0; + const uint8_t *side_metadata; + const uint8_t *end; + + av_dict_free(&avctx->metadata); + side_metadata = av_packet_get_side_data(avctx->pkt, + AV_PKT_DATA_STRINGS_METADATA, &size); + if (!side_metadata) + goto end; + end = side_metadata + size; + while (side_metadata < end) { + const uint8_t *key = side_metadata; + const uint8_t *val = side_metadata + strlen(key) + 1; + int ret = av_dict_set(&frame->metadata, key, val, 0); + if (ret < 0) + break; + side_metadata = val + strlen(val) + 1; + } +end: + avctx->metadata = frame->metadata; + return ret; +} + int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt) @@ -1630,6 +1655,7 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi if (!picture->height) picture->height = avctx->height; if (picture->format == AV_PIX_FMT_NONE) picture->format = avctx->pix_fmt; } + add_metadata_from_side_data(avctx, picture); emms_c(); //needed to avoid an emms_c() call before every return; @@ -1749,6 +1775,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, if (!frame->sample_rate) frame->sample_rate = avctx->sample_rate; } + add_metadata_from_side_data(avctx, frame); side= av_packet_get_side_data(avctx->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size); if(side && side_size>=10) { @@ -1901,6 +1928,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) avctx->internal->byte_buffer_size = 0; av_freep(&avctx->internal->byte_buffer); av_freep(&avctx->internal); + av_dict_free(&avctx->metadata); } if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) diff --git a/libavcodec/version.h b/libavcodec/version.h index b2d5c1b506..a52d72668b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 67 +#define LIBAVCODEC_VERSION_MINOR 68 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 944794fb87..82c5844fab 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -27,6 +27,7 @@ #include "float.h" /* DBL_MIN, DBL_MAX */ +#include "libavutil/bprint.h" #include "libavutil/log.h" #include "libavutil/mem.h" #include "libavutil/opt.h" @@ -339,6 +340,28 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) memcpy(pkt->data, ref->data[0], size); } + if (ref->metadata) { + uint8_t *metadata; + AVDictionaryEntry *e = NULL; + AVBPrint meta_buf; + + av_bprint_init(&meta_buf, 0, AV_BPRINT_SIZE_UNLIMITED); + while ((e = av_dict_get(ref->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { + av_bprintf(&meta_buf, "%s", e->key); + av_bprint_chars(&meta_buf, '\0', 1); + av_bprintf(&meta_buf, "%s", e->value); + av_bprint_chars(&meta_buf, '\0', 1); + } + if (!av_bprint_is_complete(&meta_buf) || + !(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, + meta_buf.len))) { + av_bprint_finalize(&meta_buf, NULL); + return AVERROR(ENOMEM); + } + memcpy(metadata, meta_buf.str, meta_buf.len); + av_bprint_finalize(&meta_buf, NULL); + } + pkt->stream_index = stream_idx; pkt->pts = ref->pts; pkt->pos = ref->pos; diff --git a/libavfilter/avcodec.c b/libavfilter/avcodec.c index 313080dc01..2a173b2c91 100644 --- a/libavfilter/avcodec.c +++ b/libavfilter/avcodec.c @@ -33,6 +33,9 @@ int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src) dst->pos = av_frame_get_pkt_pos(src); dst->format = src->format; + av_dict_free(&dst->metadata); + av_dict_copy(&dst->metadata, av_frame_get_metadata(src), 0); + switch (dst->type) { case AVMEDIA_TYPE_VIDEO: dst->video->w = src->width; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 510f28a8de..dccd4204f3 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -180,6 +180,8 @@ typedef struct AVFilterBufferRef { int perms; ///< permissions, see the AV_PERM_* flags enum AVMediaType type; ///< media type of buffer data + + AVDictionary *metadata; ///< dictionary containing metadata key=value tags } AVFilterBufferRef; /** diff --git a/libavfilter/buffer.c b/libavfilter/buffer.c index fc65b82825..ae1867f834 100644 --- a/libavfilter/buffer.c +++ b/libavfilter/buffer.c @@ -54,6 +54,10 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) if (!ret) return NULL; *ret = *ref; + + ret->metadata = NULL; + av_dict_copy(&ret->metadata, ref->metadata, 0); + if (ref->type == AVMEDIA_TYPE_VIDEO) { ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps)); if (!ret->video) { @@ -172,6 +176,7 @@ void avfilter_unref_buffer(AVFilterBufferRef *ref) av_freep(&ref->video->qp_table); av_freep(&ref->video); av_freep(&ref->audio); + av_dict_free(&ref->metadata); av_free(ref); } @@ -197,6 +202,9 @@ void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *s case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break; default: break; } + + av_dict_free(&dst->metadata); + av_dict_copy(&dst->metadata, src->metadata, 0); } AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink, diff --git a/libavfilter/version.h b/libavfilter/version.h index 1f9320c5e5..eeb78059e7 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,8 +29,8 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 3 -#define LIBAVFILTER_VERSION_MINOR 19 -#define LIBAVFILTER_VERSION_MICRO 103 +#define LIBAVFILTER_VERSION_MINOR 20 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \