From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id C128340B91 for ; Fri, 3 Feb 2023 15:34:38 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F329568BD9A; Fri, 3 Feb 2023 17:34:34 +0200 (EET) Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-he1eur01olkn2087.outbound.protection.outlook.com [40.92.65.87]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 81C5468BC2A for ; Fri, 3 Feb 2023 17:34:28 +0200 (EET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=dYGDfsEvegcaAlWqWzmbOwrzsDbUhidNxbWpV1+clE8NHuVt9c1vgM5YQyrAZlq6D4mSJna8IPhg0GdwIFvSCa9cCRohzRLeHjeL+X5OM8lfWX37EetVWvtfDS0lBLWS558G6GrpjK1XaA9sfDj30l7BzUQEu2SYILi2tr/iE6p9mPaKOMOczX4nM6P9xasNLAw1LvngJCbdFtwKL09/VzX2Y596u8ej33zunYBOrzwmIG6MUjiPBG8Byioi8UPSG6LnAvNGx3crhwrIXKAloTqe2jxhjqKqx7f+jbBvi/ZTpF3M/zHkLey/FFpVLkQmCD8UVU4sqPC3B+YF2JP6dA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=KwUUd+CBPnBg5BnIbvINUedSOmfM+4vRvhc2uSgEioU=; b=dXVax1MlziCEVv+18Ua+Rf5/Tuv1gucAjynnQGifIhqh2a7b/nUjHhSSL3K3d8IcsWzAcvnWimrUWZDuQTDoMvi2SYe6guB8hIziOg7JGmDg8+EA2e6Mr0eJG3hmOqfQnkYxO9I0dY7s+timJPCTWNHKHkWJe//CQXO+oFtN14+ZCsmOltqdzq75rJZo9I0K5woSJHWmuGl8Qhb5ruMgfMRu69jpTAN/VdHQuVbg/i+nv3JNSl1DliHXw9NQLsuK02w3Elb0mH+VpAdebc0ab/2Jk9KIKu+gAJTPv1PmlBzuLUvdIxj+I2mnvbaON/1RAp0CBonZakkC4Sf4/khNqA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=KwUUd+CBPnBg5BnIbvINUedSOmfM+4vRvhc2uSgEioU=; b=GbZ2kfyYmxpjh3Xx/3ZmL6YcS4IXTgUyRn2IzR/qL3g107hDTP6COzb81JrOJuqNZ6zXjbKbAiCybu1UgeVTiAprnD588ve+sAX+UE+giIyLbLv3GMk69bTccC2yVcJYuUAPwNdSemw797nMuNkxEkYaCV5ycfWkazTF7V7sZGJtaiJV1TTWkMfLm+xVMzK5gAk9GSXfiOOjpotA63k/DWMRBLOopVhD2HKSwvw3DdS72W9kAqsJbWpp+LMrWAVmA8lSiskbVBgO1lHVhVhwzb2jHOZmKD2Gt5oNFCRzbteG/hdovx9qop7PYr2hiOEIId3cVTndHhPfJApP+mGfgg== Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) by DU0P250MB0817.EURP250.PROD.OUTLOOK.COM (2603:10a6:10:3e1::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6064.28; Fri, 3 Feb 2023 15:34:26 +0000 Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::ee20:26b8:7242:6ac3]) by AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::ee20:26b8:7242:6ac3%7]) with mapi id 15.20.6043.017; Fri, 3 Feb 2023 15:34:26 +0000 Message-ID: Date: Fri, 3 Feb 2023 16:34:56 +0100 Content-Language: en-US To: ffmpeg-devel@ffmpeg.org References: <20230202160708.29461-1-ffmpeg@gyani.pro> <20230202160708.29461-2-ffmpeg@gyani.pro> From: Andreas Rheinhardt In-Reply-To: <20230202160708.29461-2-ffmpeg@gyani.pro> X-TMN: [BerSEF9hibpCaHTQu3PyD/+zFCghHMGm] X-ClientProxiedBy: FR2P281CA0045.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:92::17) To AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) X-Microsoft-Original-Message-ID: <70a79cdc-0be4-950a-b77c-e0a24fd13772@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AS8P250MB0744:EE_|DU0P250MB0817:EE_ X-MS-Office365-Filtering-Correlation-Id: b255bee1-1105-4be2-6763-08db05fc21bc X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: zFJziyl6gAPDacJF++T86BhcGpRegCydqphrLKqgA34EHZ/eC31XuzcJJ5SHt1ixBw5qNN7/QxEIDhEBg5KrzWu8XsTkgM0xGJRdF+xagslm9IwOfeGDynqAbjy4wabsxzlSa0PcXffznQDHksCYPA6sdbOe0USCOxBpiU9DCa7LaYH9fxrGkwEwXfVl+9i2q3AtAuaNdicwF61H3e7efpVopotg5xI1wyYmPeon9U8hX+Ie68hO6xU4LyTnci5Mm4aU2nD6zCZj7HT4hpeAP2N6cEliOeIN4PMwMFV38U81qHx2uzQIDqCnRfBZmWn6rpWu5XN6gdwg4Zcrg2cKSq0EDbsvOwK3fPsmVDUyULRdnzby57syz/M8IeDna/F9xnAHNHkXN/VbFTyuYXkH6FkOzQfM6YBZ5DtTor6s2cIPTWIKB3sPs7nR1Ny+/d2SAuNuifWj8OyYcgnrADN+QQL0c0y4tucB+XumyAZnTZ+12WxRfAAHL2af7ulfdDLUKkIu/thJKDSDWIiTwxi2voc/bIl7omXkKcAUAbE9abrui+UGdaSwUgzTt/S8WQV4ryRfFacnCrmIklxLCRfloA+66oH8E8CHKVZLVbgNK77qMieb1fJcPZ/S7JG44JNnkIXNI5ddtd2mbonks4hszXOotYzVYim84u6OLjKfhoU= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?RnNWVmVxRVd4TW82L3dNQWhRWlBOUUx0V1g0aDBiRlJuQkEyMmdaQUVFeVBq?= =?utf-8?B?RndRUmxBdFFtanoyemV5ZU1keTdIZ3F4cXZ6OUpJZjVQOFhkUjhwWk5IcFJU?= =?utf-8?B?THZESmlLK0VLbGlKR25sVGZyZkdGSVdvbkIvUzZjbVA0dkdHQWxTR0pPekV2?= =?utf-8?B?L01aWmV1VTd0c2h0OHBlWXVwODEwM2pVVzRJakNzT05Qc3drQy82d0FNY25D?= =?utf-8?B?cmZvL2RXc2FENmlrZjY1bFZ0QUw0d0tBWllaNzM1RzZVUGhGSjdyemtBSlht?= =?utf-8?B?ZTdTWVdWMHVFdnJnNUhaTWkzV3Z5STlib3NsWVVNZHZ1VHNxcFVhQktTT2V2?= =?utf-8?B?dm4vSy9tNE1lQklzWkkrUWtIMG53TFk4bnZzL2pwMTZxSGQ3NzBjS3ZRelg0?= =?utf-8?B?aUJuWjF1cEhBV1JQVUZrYWxxSFgwQ3lBN1V1aTRzYlNPOTlDeFJ0SnFwRDM0?= =?utf-8?B?b3k5VkxmUWcrYXhjWWZabkRsaEZmemhPOC9pS1BBNEJBL0lhd3NoaDMzRG13?= =?utf-8?B?WFlZRjdHWEpKR25SdzY0a2p5Y24vdXZQN29hL3d4VGwvZUVvQUM5dTdUVFJ0?= =?utf-8?B?M3p0NC9qZnA5MEREMnZad1dlektCOTA5a2JlQUJMNzJyVlVMdW4rK3k5RWRD?= =?utf-8?B?b2kzaDAzVzgyUWJqd3FEVHJuanhnVGhYMHNEeUpWeFFIU1lINTM1Z1BQL3dM?= =?utf-8?B?MnFDOERDSEhzV2FQbkp2OVpiZG1FQTZQcTNnZ2RqZGZ0MUJLdW16bmNaSW1N?= =?utf-8?B?OVkvTk1XR21OTmttQ09UTnRQTFNENlRmNHhId29rNEw2dlZaRklqaVJod1lm?= =?utf-8?B?VmV3V2xNTXQvLzZ6YjdjcHZ3VFVFR0F3YUlOZ05Sa1piOW5ydTg0UHhjVFdZ?= =?utf-8?B?YWp1alJ0dUo4amViMnV4NnFSUXRFZUhPME9PLzZPZTFrN21hWUxNVFBlM0ho?= =?utf-8?B?cFU1aXJuWFdVdjNzL2RwTEUvOU5nMTNKa1c3cXlCR3J1YjhnUi9rOGs2R04r?= =?utf-8?B?YVE1M1hYMVNEN3RNa0RqNzRyWDd5Q05qd1MreXBkZ0RMTVBNdm5PazdhRENJ?= =?utf-8?B?cTFjanErbnJOb3RSSm9PSlEyMWNxK0RPOFBFbHh1NVpoNFMxWFdrOEFMQklO?= =?utf-8?B?a3Y2bVd0R3lUT2Z4ekRUbC9FM2gweHY2YU1Lbmd6eDM5WjlsZXRHN29EUzZ0?= =?utf-8?B?SEduNk1ENVpvcmNZdDErUlVzU1N6Q3QrTTg0STdjVm5BL1FZbzlTRHNVRDJP?= =?utf-8?B?YWhRUjVvajZUVmd0YjBMdEFaMzJ3YzE4dmxnMFIvT0tRRTR2UU16emgzNUla?= =?utf-8?B?K0IxOEpaK2Uveis3bnlUZG5qVG1OK0Q1Y1VnSFBFaTVhbDlwcURFWXFTdmpF?= =?utf-8?B?TTJsTTRzRGw4NGlKYjVlTHM0ZFVtQm9tNi95T0VydldHZ1dNcmxJSFZYT2N5?= =?utf-8?B?ZEVkc2d5RFhOak1RZnVTUzNQaHgwV2ZXRzQ4RGVzSFI1eU1zbnk1Q0QvYTZQ?= =?utf-8?B?akxjMGRJV1JNUmRqMFRaTjNvVVFBUTl0OGhjSXIxODVCU05pYnpQcWRXSjd5?= =?utf-8?B?NUs3UElvQVZaNWhaU0xFZ1MrampxcnYrM3hzaVcyd0FxQXV6K3JzTDg5YVJu?= =?utf-8?B?eDdGeWNraHo2bE5FbWZ0d1hEMk5pWGtEZDVqc1ZDcWQ0dnRka0FUTGJidG5z?= =?utf-8?B?eVl5dVNjNHlSY3hFMXhkSkZiQWVaVVkxdEZlTEk2K3Z6TTVnMEU0cFJtdHli?= =?utf-8?Q?O49Txi2BFzCBQeV38M=3D?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: b255bee1-1105-4be2-6763-08db05fc21bc X-MS-Exchange-CrossTenant-AuthSource: AS8P250MB0744.EURP250.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Feb 2023 15:34:26.0511 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DU0P250MB0817 Subject: Re: [FFmpeg-devel] [PATCH v2 2/2] avformat/flvenc: add option to read metadata from file X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Gyan Doshi: > Useful, in conjuntion with option meta_period, to vary metadata during > stream. > > File format is ffmetadata. > --- > configure | 2 +- > doc/muxers.texi | 3 + > libavformat/flvenc.c | 133 +++++++++++++++++++++++++++++++++---------- > 3 files changed, 107 insertions(+), 31 deletions(-) > > diff --git a/configure b/configure > index 9d78a244a3..de371632c4 100755 > --- a/configure > +++ b/configure > @@ -3433,7 +3433,7 @@ eac3_demuxer_select="ac3_parser" > f4v_muxer_select="mov_muxer" > fifo_muxer_deps="threads" > flac_demuxer_select="flac_parser" > -flv_muxer_select="aac_adtstoasc_bsf" > +flv_muxer_select="aac_adtstoasc_bsf ffmetadata_demuxer" > gxf_muxer_select="pcm_rechunk_bsf" > hds_muxer_select="flv_muxer" > hls_demuxer_select="adts_header ac3_parser" > diff --git a/doc/muxers.texi b/doc/muxers.texi > index 02ecddf186..000c92b2a7 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -555,6 +555,9 @@ With every video packet. > @end table > Note that metadata will always be re-emitted if a metadata update event is signalled. > > +@item meta_filename > +Specify a ffmetadata file from which to load metadata. > + > @end table > > @anchor{framecrc} > diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c > index d1c7a493d1..1332b18b41 100644 > --- a/libavformat/flvenc.c > +++ b/libavformat/flvenc.c > @@ -122,6 +122,10 @@ typedef struct FLVContext { > double framerate; > AVCodecParameters *data_par; > > + char *meta_filename; > + AVFormatContext *meta_ctx; > + AVDictionary *meta_dict; > + > int flags; > int meta_period; > } FLVContext; > @@ -277,6 +281,92 @@ static void put_amf_bool(AVIOContext *pb, int b) > avio_w8(pb, !!b); > } > > +static int read_metadata_from_file(AVFormatContext *s, unsigned int ts, int header) > +{ > + FLVContext *flv = s->priv_data; > + const AVInputFormat *meta_format = NULL; > + AVDictionary *current_meta_dict = NULL; > + float timestamp = ts/1000.f; > + int ret; > + > + if (!flv->meta_filename) > + return 0; > + > + meta_format = av_find_input_format("ffmetadata"); > + if (!meta_format) { > + av_log(s, AV_LOG_ERROR, "ffmetadata demuxer not found.\n"); > + return AVERROR(ENOSYS); > + } > + > + avformat_close_input(&flv->meta_ctx); > + > + ret = avformat_open_input(&flv->meta_ctx, flv->meta_filename, meta_format, NULL); > + if (ret < 0) { > + av_log(s, AV_LOG_ERROR, "Failed to read metadata from file %s t: %f.", flv->meta_filename, timestamp); > + if (flv->meta_dict) > + av_log(s, AV_LOG_ERROR, " Continuing with old metadata."); > + av_log(s, AV_LOG_ERROR, "\n"); > + return ret; > + } > + > + if (flv->meta_dict) { > + av_dict_copy(¤t_meta_dict, flv->meta_dict, 0); > + av_dict_free(&flv->meta_dict); > + } > + > + ret = av_dict_copy(&flv->meta_dict, flv->meta_ctx->metadata, 0); > + if (ret < 0) { > + av_log(s, AV_LOG_ERROR, "Could not transfer metadata from %s at %f seconds. Continuing with old metadata.\n", flv->meta_filename, timestamp); > + av_dict_free(&flv->meta_dict); > + av_dict_copy(&flv->meta_dict, current_meta_dict, 0); > + av_dict_free(¤t_meta_dict); > + return ret; > + } > + > + av_log(s, AV_LOG_VERBOSE, "Metadata from file %s updated %s at %f seconds.\n", flv->meta_filename, header ? "in header" : "in video packet", timestamp); > + av_dict_free(¤t_meta_dict); > + avformat_close_input(&flv->meta_ctx); > + > + return 0; > +} > + > +static int write_user_metadata_tag(AVFormatContext *s, AVDictionaryEntry *tag, AVIOContext *pb, int *metadata_count) > +{ > + > + av_log(s, AV_LOG_DEBUG, "Writing tag %s with value %s count: %d\n", tag->key, tag->value, *metadata_count); > + > + if( !strcmp(tag->key, "width") > + ||!strcmp(tag->key, "height") > + ||!strcmp(tag->key, "videodatarate") > + ||!strcmp(tag->key, "framerate") > + ||!strcmp(tag->key, "videocodecid") > + ||!strcmp(tag->key, "audiodatarate") > + ||!strcmp(tag->key, "audiosamplerate") > + ||!strcmp(tag->key, "audiosamplesize") > + ||!strcmp(tag->key, "stereo") > + ||!strcmp(tag->key, "audiocodecid") > + ||!strcmp(tag->key, "duration") > + ||!strcmp(tag->key, "onMetaData") > + ||!strcmp(tag->key, "datasize") > + ||!strcmp(tag->key, "lasttimestamp") > + ||!strcmp(tag->key, "totalframes") > + ||!strcmp(tag->key, "hasAudio") > + ||!strcmp(tag->key, "hasVideo") > + ||!strcmp(tag->key, "hasCuePoints") > + ||!strcmp(tag->key, "hasMetadata") > + ||!strcmp(tag->key, "hasKeyframes") > + ){ > + av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key); > + return AVERROR(EINVAL); > + } > + put_amf_string(pb, tag->key); > + avio_w8(pb, AMF_DATA_TYPE_STRING); > + put_amf_string(pb, tag->value); > + (*metadata_count)++; > + > + return 0; > +} > + > static void write_metadata(AVFormatContext *s, unsigned int ts) > { > AVIOContext *pb = s->pb; > @@ -360,36 +450,11 @@ static void write_metadata(AVFormatContext *s, unsigned int ts) > } > > ff_standardize_creation_time(s); > - while ((tag = av_dict_iterate(s->metadata, tag))) { > - if( !strcmp(tag->key, "width") > - ||!strcmp(tag->key, "height") > - ||!strcmp(tag->key, "videodatarate") > - ||!strcmp(tag->key, "framerate") > - ||!strcmp(tag->key, "videocodecid") > - ||!strcmp(tag->key, "audiodatarate") > - ||!strcmp(tag->key, "audiosamplerate") > - ||!strcmp(tag->key, "audiosamplesize") > - ||!strcmp(tag->key, "stereo") > - ||!strcmp(tag->key, "audiocodecid") > - ||!strcmp(tag->key, "duration") > - ||!strcmp(tag->key, "onMetaData") > - ||!strcmp(tag->key, "datasize") > - ||!strcmp(tag->key, "lasttimestamp") > - ||!strcmp(tag->key, "totalframes") > - ||!strcmp(tag->key, "hasAudio") > - ||!strcmp(tag->key, "hasVideo") > - ||!strcmp(tag->key, "hasCuePoints") > - ||!strcmp(tag->key, "hasMetadata") > - ||!strcmp(tag->key, "hasKeyframes") > - ){ > - av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key); > - continue; > - } > - put_amf_string(pb, tag->key); > - avio_w8(pb, AMF_DATA_TYPE_STRING); > - put_amf_string(pb, tag->value); > - metadata_count++; > - } > + > + while (tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)) > + write_user_metadata_tag(s, tag, pb, &metadata_count); > + while (tag = av_dict_get(flv->meta_dict, "", tag, AV_DICT_IGNORE_SUFFIX)) > + write_user_metadata_tag(s, tag, pb, &metadata_count); > > if (write_duration_filesize) { > put_amf_string(pb, "filesize"); > @@ -718,6 +783,7 @@ static int flv_write_header(AVFormatContext *s) > if (flv->flags & FLV_NO_METADATA) { > pb->seekable = 0; > } else { > + read_metadata_from_file(s, 0, 1); > write_metadata(s, 0); > } > > @@ -880,6 +946,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) > if (meta_upd_flag || > (flv->meta_period == FLV_META_AT_KF && par->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY)) || > (flv->meta_period == FLV_META_EVERY_PACKET && par->codec_type == AVMEDIA_TYPE_VIDEO )) { > + read_metadata_from_file(s, ts, 0); > write_metadata(s, ts); > if (meta_upd_flag) > s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED; > @@ -1053,6 +1120,11 @@ static void flv_deinit(AVFormatContext *s) > } > flv->filepositions = flv->head_filepositions = NULL; > flv->filepositions_count = 0; > + > + if (flv->meta_dict) > + av_dict_free(&flv->meta_dict); > + > + avformat_close_input(&flv->meta_ctx); > } > > static const AVOption options[] = { > @@ -1066,6 +1138,7 @@ static const AVOption options[] = { > { "at_start", "only once at start", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_META_ONCE_AT_START}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "meta_period" }, > { "at_keyframes", "with every video keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_META_AT_KF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "meta_period" }, > { "every_packet", "with every video packet", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_META_EVERY_PACKET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "meta_period" }, > + { "meta_filename", "ffmetadata file to import metadata", offsetof(FLVContext, meta_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, > { NULL }, > }; > What does this achieve that can't be achieved by other means (namely by an API-user updating the relevant metadata dictionaries)? - Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".