PR #20867 opened by toots URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20867 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20867.patch
>From f3a114f7dea9f31888dc9deb39bbe5ee5e808c0c Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 8 Nov 2025 10:19:30 -0600 Subject: [PATCH 1/3] libavformat: export av_dump_dictionary --- doc/APIchanges | 3 +++ libavformat/avformat.h | 14 ++++++++++++++ libavformat/dump.c | 12 ++++++------ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 9d128ae77b..42bc3dba35 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28 API changes, most recent first: +2025-11-08 - xxxxxxxxxx - lavf 62.6.101 - avformat.h + Added av_dump_dictionary(). + 2025-11-01 - xxxxxxxxxx - lavc 62.19.100 - avcodec.h Schedule AVCodecParser and av_parser_init() to use enum AVCodecID for codec ids on the next major version bump. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a7446546e5..a6cf9b0dfa 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2818,6 +2818,20 @@ void av_dump_format(AVFormatContext *ic, const char *url, int is_output); +/** + * Print the given dictionary. + * + * @param ctx the logging context + * @param m the dictionay to print + * @param name name of the dictionary + * @param indent intendation to use between key and values + * @param log_level log level to use for printing + */ +void av_dump_dictionary(void *ctx, + const AVDictionary *m, + const char *name, + const char *indent, + int log_level); #define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d #define AV_FRAME_FILENAME_FLAGS_IGNORE_TRUNCATION 2 ///< Ignore truncated output instead of returning an error diff --git a/libavformat/dump.c b/libavformat/dump.c index 2948189432..d30732fbef 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -139,9 +139,9 @@ static void print_fps(double d, const char *postfix, int log_level) av_log(NULL, log_level, "%1.0fk %s", d / 1000, postfix); } -static void dump_dictionary(void *ctx, const AVDictionary *m, - const char *name, const char *indent, - int log_level) +void av_dump_dictionary(void *ctx, const AVDictionary *m, + const char *name, const char *indent, + int log_level) { const AVDictionaryEntry *tag = NULL; @@ -170,7 +170,7 @@ static void dump_metadata(void *ctx, const AVDictionary *m, const char *indent, int log_level) { if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))) - dump_dictionary(ctx, m, "Metadata", indent, log_level); + av_dump_dictionary(ctx, m, "Metadata", indent, log_level); } /* param change side data*/ @@ -734,7 +734,7 @@ static void dump_stream_group(const AVFormatContext *ic, uint8_t *printed, dump_disposition(stg->disposition, AV_LOG_INFO); av_log(NULL, AV_LOG_INFO, "\n"); dump_metadata(NULL, stg->metadata, " ", AV_LOG_INFO); - dump_dictionary(NULL, mix_presentation->annotations, "Annotations", " ", AV_LOG_INFO); + av_dump_dictionary(NULL, mix_presentation->annotations, "Annotations", " ", AV_LOG_INFO); for (int j = 0; j < mix_presentation->nb_submixes; j++) { AVIAMFSubmix *sub_mix = mix_presentation->submixes[j]; av_log(NULL, AV_LOG_INFO, " Submix %d:\n", j); @@ -753,7 +753,7 @@ static void dump_stream_group(const AVFormatContext *ic, uint8_t *printed, if (flags & AVFMT_SHOW_IDS) av_log(NULL, AV_LOG_INFO, "[0x%"PRIx64"]", audio_element->id); av_log(NULL, AV_LOG_INFO, "\n"); - dump_dictionary(NULL, submix_element->annotations, "Annotations", " ", AV_LOG_INFO); + av_dump_dictionary(NULL, submix_element->annotations, "Annotations", " ", AV_LOG_INFO); } } for (int k = 0; k < sub_mix->nb_layouts; k++) { -- 2.49.1 >From 020070a61204ab3b227f1f977abbb466b3316859 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 8 Nov 2025 12:03:32 -0600 Subject: [PATCH 2/3] libavutil: add av_dict_md5_sum. --- doc/APIchanges | 3 +++ libavutil/dict.c | 22 ++++++++++++++++++++++ libavutil/dict.h | 12 ++++++++++++ 3 files changed, 37 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index 42bc3dba35..7c9c864577 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28 API changes, most recent first: +2025-11-08 - xxxxxxxxxx - lavu 60.17.100 - dict.h + Added av_dict_md5_sum(). + 2025-11-08 - xxxxxxxxxx - lavf 62.6.101 - avformat.h Added av_dump_dictionary(). diff --git a/libavutil/dict.c b/libavutil/dict.c index fafb454fd3..9404718429 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -26,6 +26,7 @@ #include "avstring.h" #include "dict.h" #include "error.h" +#include "md5.h" #include "mem.h" #include "bprint.h" @@ -284,3 +285,24 @@ int av_dict_get_string(const AVDictionary *m, char **buffer, } return av_bprint_finalize(&bprint, buffer); } + +int av_dict_md5_sum(uint8_t *dst, const AVDictionary *m) +{ + struct AVMD5 *ctx = av_md5_alloc(); + const AVDictionaryEntry *entry = av_dict_iterate(m, NULL); + + if (!ctx) return AVERROR(ENOMEM); + + av_md5_init(ctx); + + while (entry) { + av_md5_update(ctx, entry->key, strlen(entry->key)); + av_md5_update(ctx, entry->value, strlen(entry->value)); + entry = av_dict_iterate(m, entry); + } + + av_md5_final(ctx, dst); + av_free(ctx); + + return 0; +} diff --git a/libavutil/dict.h b/libavutil/dict.h index 93c7cbf128..2685974e8e 100644 --- a/libavutil/dict.h +++ b/libavutil/dict.h @@ -31,6 +31,7 @@ #define AVUTIL_DICT_H #include <stdint.h> +#include <stddef.h> /** * @addtogroup lavu_dict AVDictionary @@ -235,6 +236,17 @@ void av_dict_free(AVDictionary **m); int av_dict_get_string(const AVDictionary *m, char **buffer, const char key_val_sep, const char pairs_sep); +/** + * Compute the md5 sum of a dictionary. + * + * @param dst The output buffer to write the digest into + * @param m The dictionary + * @param len The length of the data, in bytes + * + * @return >= 0 on success, negative on error + */ +int av_dict_md5_sum(uint8_t *dst, const AVDictionary *m); + /** * @} */ -- 2.49.1 >From 05b34a1e3911c1430ade6360641b5e8dea99a6f4 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sat, 8 Nov 2025 10:32:32 -0600 Subject: [PATCH 3/3] ffplay: print new metadata --- fftools/ffplay.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index dc2627521e..6d7b7a57af 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -196,6 +196,7 @@ typedef struct Decoder { int64_t next_pts; AVRational next_pts_tb; SDL_Thread *decoder_tid; + uint8_t last_metadata_hash[16]; } Decoder; typedef struct VideoState { @@ -577,6 +578,8 @@ static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, S static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { int ret = AVERROR(EAGAIN); + uint8_t metadata_hash[16]; + char metadata_description[96]; for (;;) { if (d->queue->serial == d->pkt_serial) { @@ -615,8 +618,26 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { avcodec_flush_buffers(d->avctx); return 0; } - if (ret >= 0) + if (ret >= 0) { + if (frame->metadata) { + ret = av_dict_md5_sum(metadata_hash, frame->metadata); + if (ret < 0) return ret; + if (memcmp(metadata_hash, d->last_metadata_hash, sizeof(metadata_hash))) { + memcpy(d->last_metadata_hash, metadata_hash, sizeof(metadata_hash)); + if (show_status) { + printf("\x1b[2K\r"); + fflush(stdout); + } + snprintf(metadata_description, + sizeof(metadata_description), + "\r New metadata for %s stream %d", + d->avctx->codec_type == AVMEDIA_TYPE_AUDIO ? "audio" : "video", + d->pkt ? d->pkt->stream_index : -1); + av_dump_dictionary(NULL, frame->metadata, metadata_description, " ", AV_LOG_INFO); + } + } return 1; + } } while (ret != AVERROR(EAGAIN)); } @@ -2762,6 +2783,11 @@ static int stream_component_open(VideoState *is, int stream_index) is->audio_stream = stream_index; is->audio_st = ic->streams[stream_index]; + if (is->audio_st->metadata) { + ret = av_dict_md5_sum(is->auddec.last_metadata_hash, is->audio_st->metadata); + if (ret < 0) goto fail; + } + if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0) goto fail; if (is->ic->iformat->flags & AVFMT_NOTIMESTAMPS) { @@ -2776,6 +2802,11 @@ static int stream_component_open(VideoState *is, int stream_index) is->video_stream = stream_index; is->video_st = ic->streams[stream_index]; + if (is->video_st->metadata) { + ret = av_dict_md5_sum(is->viddec.last_metadata_hash, is->video_st->metadata); + if (ret < 0) goto fail; + } + if ((ret = decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread)) < 0) goto fail; if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0) -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
