History

lavc: add lavfi metadata support.

This commit introduces a new AVPacket side data type: AV_PKT_DATA_STRINGS_METADATA. Its main goal is to provide a way to transmit the metadata from the AVFilterBufferRef up to the AVFrame. This is at the moment "only" useful for lavfi input from libavdevice: lavd/lavfi only outputs packets, and the metadata from the buffer ref kept in its context needs to be transmitted from the packet to the frame by the decoders. The buffer ref can be destroyed at any time (along with the metadata), and a duplication of the AVPacket needs to duplicate the metadata as well, so the choice of using the side data to store them was selected. Making sure lavd/lavfi raises the metadata is useful to allow tools like ffprobe to access the filters metadata (it is at the moment the only way); ffprobe will now automatically show the AVFrame metadata in any customizable output format for users. API users will also be able to access the AVFrame->metadata pointer the same way ffprobe does (av_frame_get_metadata). All the changes are done in this single commit to avoid some memory leaks: for instances, the changes in lavfi/avcodec.c are meant to duplicate the metadata from the buffer ref into the AVFrame. Unless we have an internal way of freeing the AVFrame->metadata automatically, it will leak in most of the user apps. To fix this problem, we introduce AVCodecContext->metadata and link avctx->metadata to the current frame->metadata and free it at each decode frame call (and in the codec closing callback for the last one). But doing this also means to update the way the tiff decoder already handles the AVFrame->metadata (it's the only one decoder with frame metadata at the moment), by making sure it is not trying to free a pointer already freed by the lavc internals. The lavfi/avcodec.c buffer ref code is based on an old Thomas Kühnel work, the rest of the code belongs to the commit author.

Clément Bœsch committed 14 years ago

Commit 6fb2fd81 parent d7b8a9a10 files · +90 −7Browse files

Unified · Split

10 files
  1. doc/APIchanges +7 −0
  2. libavcodec/avcodec.h +13 −0
  3. libavcodec/tiff.c +3 −4
  4. libavcodec/utils.c +28 −0
  5. libavcodec/version.h +1 −1
  6. libavdevice/lavfi.c +23 −0
  7. libavfilter/avcodec.c +3 −0
  8. libavfilter/avfilter.h +2 −0
  9. libavfilter/buffer.c +8 −0
  10. libavfilter/version.h +2 −2
doc/APIchanges+7−0
@@ -15,6 +15,13 @@ libavutil: 2011-04-18 · 14 unmodified lines
15 15
16API changes, most recent first:16API changes, most recent first:
17 17
182012-10-21 - xxxxxxx - lavc 54.68.100 - avcodec.h
19 lavfi 3.20.100 - avfilter.h
20 Add AV_PKT_DATA_STRINGS_METADATA side data type, used to transmit key/value
21 strings between AVPacket and AVFrame, and add metadata field to
22 AVCodecContext (which shall not be accessed by users; see AVFrame metadata
23 instead).
24
182012-09-27 - a70b493 - lavd 54.3.100 - version.h252012-09-27 - a70b493 - lavd 54.3.100 - version.h
19 Add LIBAVDEVICE_IDENT symbol.26 Add LIBAVDEVICE_IDENT symbol.
20 27
libavcodec/avcodec.h+13−0
@@ -942,6 +942,12 @@ enum AVPacketSideDataType { · 941 unmodified lines
942 * @endcode942 * @endcode
943 */943 */
944 AV_PKT_DATA_JP_DUALMONO,944 AV_PKT_DATA_JP_DUALMONO,
945
946 /**
947 * A list of zero terminated key/value strings. There is no end marker for
948 * the list, so it is required to rely on the side data size to stop.
949 */
950 AV_PKT_DATA_STRINGS_METADATA,
945};951};
946 952
947typedef struct AVPacket {953typedef struct AVPacket {
@@ -3091,6 +3097,13 @@ typedef struct AVCodecContext { · 2143 unmodified lines
3091 int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far3097 int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far
3092 int64_t pts_correction_last_pts; /// PTS of the last frame3098 int64_t pts_correction_last_pts; /// PTS of the last frame
3093 int64_t pts_correction_last_dts; /// DTS of the last frame3099 int64_t pts_correction_last_dts; /// DTS of the last frame
3100
3101 /**
3102 * Current frame metadata.
3103 * - decoding: maintained and used by libavcodec, not intended to be used by user apps
3104 * - encoding: unused
3105 */
3106 AVDictionary *metadata;
3094} AVCodecContext;3107} AVCodecContext;
3095 3108
3096AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx);3109AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx);
libavcodec/tiff.c+3−4
@@ -1018,8 +1018,9 @@ static int decode_frame(AVCodecContext *avctx, · 1017 unmodified lines
1018 s->compr = TIFF_RAW;1018 s->compr = TIFF_RAW;
1019 s->fill_order = 0;1019 s->fill_order = 0;
1020 free_geotags(s);1020 free_geotags(s);
1021 /* free existing metadata */1021 /* metadata has been destroyed from lavc internals, that pointer is not
1022 av_dict_free(&s->picture.metadata);1022 * valid anymore */
1023 s->picture.metadata = NULL;
1023 1024
1024 // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number1025 // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number
1025 // that further identifies the file as a TIFF file"1026 // that further identifies the file as a TIFF file"
@@ -1169,8 +1170,6 @@ static av_cold int tiff_end(AVCodecContext *avctx) · 143 unmodified lines
1169 TiffContext *const s = avctx->priv_data;1170 TiffContext *const s = avctx->priv_data;
1170 1171
1171 free_geotags(s);1172 free_geotags(s);
1172 if (avctx->coded_frame && avctx->coded_frame->metadata)
1173 av_dict_free(&avctx->coded_frame->metadata);
1174 1173
1175 ff_lzw_decode_close(&s->lzw);1174 ff_lzw_decode_close(&s->lzw);
1176 if (s->picture.data[0])1175 if (s->picture.data[0])
libavcodec/utils.c+28−0
@@ -1592,6 +1592,31 @@ static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) · 1591 unmodified lines
1592 }1592 }
1593}1593}
1594 1594
1595static int add_metadata_from_side_data(AVCodecContext *avctx, AVFrame *frame)
1596{
1597 int size, ret = 0;
1598 const uint8_t *side_metadata;
1599 const uint8_t *end;
1600
1601 av_dict_free(&avctx->metadata);
1602 side_metadata = av_packet_get_side_data(avctx->pkt,
1603 AV_PKT_DATA_STRINGS_METADATA, &size);
1604 if (!side_metadata)
1605 goto end;
1606 end = side_metadata + size;
1607 while (side_metadata < end) {
1608 const uint8_t *key = side_metadata;
1609 const uint8_t *val = side_metadata + strlen(key) + 1;
1610 int ret = av_dict_set(&frame->metadata, key, val, 0);
1611 if (ret < 0)
1612 break;
1613 side_metadata = val + strlen(val) + 1;
1614 }
1615end:
1616 avctx->metadata = frame->metadata;
1617 return ret;
1618}
1619
1595int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,1620int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
1596 int *got_picture_ptr,1621 int *got_picture_ptr,
1597 const AVPacket *avpkt)1622 const AVPacket *avpkt)
@@ -1630,6 +1655,7 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi · 32 unmodified lines
1630 if (!picture->height) picture->height = avctx->height;1655 if (!picture->height) picture->height = avctx->height;
1631 if (picture->format == AV_PIX_FMT_NONE) picture->format = avctx->pix_fmt;1656 if (picture->format == AV_PIX_FMT_NONE) picture->format = avctx->pix_fmt;
1632 }1657 }
1658 add_metadata_from_side_data(avctx, picture);
1633 1659
1634 emms_c(); //needed to avoid an emms_c() call before every return;1660 emms_c(); //needed to avoid an emms_c() call before every return;
1635 1661
@@ -1749,6 +1775,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, · 113 unmodified lines
1749 if (!frame->sample_rate)1775 if (!frame->sample_rate)
1750 frame->sample_rate = avctx->sample_rate;1776 frame->sample_rate = avctx->sample_rate;
1751 }1777 }
1778 add_metadata_from_side_data(avctx, frame);
1752 1779
1753 side= av_packet_get_side_data(avctx->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size);1780 side= av_packet_get_side_data(avctx->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
1754 if(side && side_size>=10) {1781 if(side && side_size>=10) {
@@ -1901,6 +1928,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) · 146 unmodified lines
1901 avctx->internal->byte_buffer_size = 0;1928 avctx->internal->byte_buffer_size = 0;
1902 av_freep(&avctx->internal->byte_buffer);1929 av_freep(&avctx->internal->byte_buffer);
1903 av_freep(&avctx->internal);1930 av_freep(&avctx->internal);
1931 av_dict_free(&avctx->metadata);
1904 }1932 }
1905 1933
1906 if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)1934 if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
libavcodec/version.h+1−1
@@ -29,7 +29,7 @@ · 28 unmodified lines
29#include "libavutil/avutil.h"29#include "libavutil/avutil.h"
30 30
31#define LIBAVCODEC_VERSION_MAJOR 5431#define LIBAVCODEC_VERSION_MAJOR 54
32#define LIBAVCODEC_VERSION_MINOR 6732#define LIBAVCODEC_VERSION_MINOR 68
33#define LIBAVCODEC_VERSION_MICRO 10033#define LIBAVCODEC_VERSION_MICRO 100
34 34
35#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \35#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
libavdevice/lavfi.c+23−0
@@ -27,6 +27,7 @@ · 26 unmodified lines
27 27
28#include "float.h" /* DBL_MIN, DBL_MAX */28#include "float.h" /* DBL_MIN, DBL_MAX */
29 29
30#include "libavutil/bprint.h"
30#include "libavutil/log.h"31#include "libavutil/log.h"
31#include "libavutil/mem.h"32#include "libavutil/mem.h"
32#include "libavutil/opt.h"33#include "libavutil/opt.h"
@@ -339,6 +340,28 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) · 306 unmodified lines
339 memcpy(pkt->data, ref->data[0], size);340 memcpy(pkt->data, ref->data[0], size);
340 }341 }
341 342
343 if (ref->metadata) {
344 uint8_t *metadata;
345 AVDictionaryEntry *e = NULL;
346 AVBPrint meta_buf;
347
348 av_bprint_init(&meta_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
349 while ((e = av_dict_get(ref->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
350 av_bprintf(&meta_buf, "%s", e->key);
351 av_bprint_chars(&meta_buf, '\0', 1);
352 av_bprintf(&meta_buf, "%s", e->value);
353 av_bprint_chars(&meta_buf, '\0', 1);
354 }
355 if (!av_bprint_is_complete(&meta_buf) ||
356 !(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA,
357 meta_buf.len))) {
358 av_bprint_finalize(&meta_buf, NULL);
359 return AVERROR(ENOMEM);
360 }
361 memcpy(metadata, meta_buf.str, meta_buf.len);
362 av_bprint_finalize(&meta_buf, NULL);
363 }
364
342 pkt->stream_index = stream_idx;365 pkt->stream_index = stream_idx;
343 pkt->pts = ref->pts;366 pkt->pts = ref->pts;
344 pkt->pos = ref->pos;367 pkt->pos = ref->pos;
libavfilter/avcodec.c+3−0
@@ -33,6 +33,9 @@ int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src) · 32 unmodified lines
33 dst->pos = av_frame_get_pkt_pos(src);33 dst->pos = av_frame_get_pkt_pos(src);
34 dst->format = src->format;34 dst->format = src->format;
35 35
36 av_dict_free(&dst->metadata);
37 av_dict_copy(&dst->metadata, av_frame_get_metadata(src), 0);
38
36 switch (dst->type) {39 switch (dst->type) {
37 case AVMEDIA_TYPE_VIDEO:40 case AVMEDIA_TYPE_VIDEO:
38 dst->video->w = src->width;41 dst->video->w = src->width;
libavfilter/avfilter.h+2−0
@@ -180,6 +180,8 @@ typedef struct AVFilterBufferRef { · 179 unmodified lines
180 int perms; ///< permissions, see the AV_PERM_* flags180 int perms; ///< permissions, see the AV_PERM_* flags
181 181
182 enum AVMediaType type; ///< media type of buffer data182 enum AVMediaType type; ///< media type of buffer data
183
184 AVDictionary *metadata; ///< dictionary containing metadata key=value tags
183} AVFilterBufferRef;185} AVFilterBufferRef;
184 186
185/**187/**
libavfilter/buffer.c+8−0
@@ -54,6 +54,10 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) · 53 unmodified lines
54 if (!ret)54 if (!ret)
55 return NULL;55 return NULL;
56 *ret = *ref;56 *ret = *ref;
57
58 ret->metadata = NULL;
59 av_dict_copy(&ret->metadata, ref->metadata, 0);
60
57 if (ref->type == AVMEDIA_TYPE_VIDEO) {61 if (ref->type == AVMEDIA_TYPE_VIDEO) {
58 ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));62 ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
59 if (!ret->video) {63 if (!ret->video) {
@@ -172,6 +176,7 @@ void avfilter_unref_buffer(AVFilterBufferRef *ref) · 112 unmodified lines
172 av_freep(&ref->video->qp_table);176 av_freep(&ref->video->qp_table);
173 av_freep(&ref->video);177 av_freep(&ref->video);
174 av_freep(&ref->audio);178 av_freep(&ref->audio);
179 av_dict_free(&ref->metadata);
175 av_free(ref);180 av_free(ref);
176}181}
177 182
@@ -197,6 +202,9 @@ void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *s · 19 unmodified lines
197 case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break;202 case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break;
198 default: break;203 default: break;
199 }204 }
205
206 av_dict_free(&dst->metadata);
207 av_dict_copy(&dst->metadata, src->metadata, 0);
200}208}
201 209
202AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink,210AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink,
libavfilter/version.h+2−2
@@ -29,8 +29,8 @@ · 28 unmodified lines
29#include "libavutil/avutil.h"29#include "libavutil/avutil.h"
30 30
31#define LIBAVFILTER_VERSION_MAJOR 331#define LIBAVFILTER_VERSION_MAJOR 3
32#define LIBAVFILTER_VERSION_MINOR 1932#define LIBAVFILTER_VERSION_MINOR 20
33#define LIBAVFILTER_VERSION_MICRO 10333#define LIBAVFILTER_VERSION_MICRO 100
34 34
35#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \35#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 LIBAVFILTER_VERSION_MINOR, \36 LIBAVFILTER_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t