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 CF54843390 for ; Sat, 9 Jul 2022 07:57:18 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6517F68B7D3; Sat, 9 Jul 2022 10:57:15 +0300 (EEST) Received: from mail-yb1-f181.google.com (mail-yb1-f181.google.com [209.85.219.181]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 09A0768B9B2 for ; Sat, 9 Jul 2022 10:57:08 +0300 (EEST) Received: by mail-yb1-f181.google.com with SMTP id 136so1207897ybl.5 for ; Sat, 09 Jul 2022 00:57:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=yvoFbkl+/9DNumZnKkXVf98X+VhXQsLyA4SJULCCQC0=; b=n7046twO4JItlxPQgbJHvVsIedrSLBUfh0e7Ds9QS0zbK9ctJ314R7vdZEcMSSr1Wk qns3qRkQJTX77NX9tJk2y/4TZ3i4/uPNbKFXChW9M4GXCrcDHu/ZcIg6txAtmkxpdMFE Yn/PfoBj9CseEbwTUqIKxGU2uh51iT+oE6YYHPyk70MeeiyaXEeWsq/tHFeEDEb4puxn htYlWJoq8eNjurb39g+AP1JmJz4V0ILKQMjlxAgQe772TFmAZX/hONK9mcndBtbDabPz SCjS9ZBmhtA8pxiOremPxRXbmic+pvgsSCoPO+8NuryCPCpvdFgHT4EeoJ5PMQ2kLKDR ni0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=yvoFbkl+/9DNumZnKkXVf98X+VhXQsLyA4SJULCCQC0=; b=bDyvP5P1fhO4P4bcFnTLOX01TEDtW6FfQ2pb10hQUZslRDRAVkIa8CaCeHm2aLROUZ VZnT1ulYxE9kYsGjcIFrjtAo09jVhExYOL/x1vTsx49Vv6TMBd1GhhEkZCRbtWfyfgyA /mVaaWYJECA3aXmMHkykNasRBN0zsa6wCuRLV9ODMU0n+S6k34OeJ7SQYgWshSUmqvgR R8GXj0208X5CjEpxP0l5Ri5QsDNMN0rZ18jCFNks68KiiCsi1dvweo9eI3vKK0aVV7Nw 4pdVUOVfEa46k7Ak38u2/mm8GvRKRoTPlQq7bdfANG3ASic1Fi6VUj4lNGB+Bkkp8B+f LKmg== X-Gm-Message-State: AJIora9N8IjwjB5FOS4ClxMDThEW7MGkTSfR1efbODFjr6ukgLKzLbpy sP8kaxOrr4iTk1uhtPrRjGOCMg0ryB9oW03eA7xYrYc1 X-Google-Smtp-Source: AGRyM1tVwz7liFoTfHsA1oHXqj1sQN1bJr48Cu5O/9wJwsKri5aKixScTn5OeawRlYE7n4+cke1ucpOPg+IakfX4+40= X-Received: by 2002:a25:928e:0:b0:669:11d3:f9c2 with SMTP id y14-20020a25928e000000b0066911d3f9c2mr7711359ybl.250.1657353426207; Sat, 09 Jul 2022 00:57:06 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Paul B Mahol Date: Sat, 9 Jul 2022 09:59:46 +0200 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: Re: [FFmpeg-devel] [PATCH] Add metadatareader filter. 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 Cc: Raymond Cheng 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: On Sat, Jul 9, 2022 at 8:44 AM Raymond Cheng wrote: > I also feel, btw, that there is already precedent for this kind of implied > relationship between f_metadata.c and f_metadatareader.c. For example, the > demuxer/muxer pairs in libavformat, such as movenc.c and mov.c are > complimentary, the latter is implicitly meant to read what the former has > written, and there is no obligation to go to some third component as > neutral ground. Same goes for the encoder/decoder pairs in libavcodec. I > want the same "mated pair" status for f_metadata.c and f_metadatareader.c. > > Having said that, I am not at all opposed to modifying f_metadata.c to > write VTT instead of its current format, and having f_metadatareader.c read > VTT. The benefit of that is that VTT is a standalone format understood > everywhere, so that producing such a VTT file can be used by browsers, not > just f_metadatareader.c. You wouldn't have to burn hard subs by reading the > VTT into f_metadatareader.c, you could just place it alongside the MP4 and > the browser will render soft subs. But I'd prefer to do that in stages, > with first stage making no modifications to f_metadata.c. > VTT is not good pick at all. This functionality should be in metadata filter instead, and not in separate filter. Also it is too much complex implementation of interesting idea. > > ...Cheng > > -----Original Message----- > From: Raymond Cheng > Sent: Saturday, July 9, 2022 9:26 AM > To: FFmpeg development discussions and patches > Subject: RE: [FFmpeg-devel] [PATCH] Add metadatareader filter. > > Thanks, it will probably take me a couple days to incorporate some of the > feedback regarding style, but some comments: > > 1) The intent of metadatareader is to read what the metadata filter wrote > to a file, which as you already know, does not make use of any established > format. It simply calls vsnprintf. This intent is backed by FATE test, so > any breaking changes ought to hopefully be caught (and if not, the tests > can be enhanced). If I were to follow your suggestion of adopting a format, > then I think I'd choose VTT, and this would be a much bigger change. It > would necessitate that the metadata filter also be modified to output to > VTT rather than use its current log format. I think if we wanted to do > that, I'd still prefer to do that as a stage 2, and start with a stage 1 > where f_metadata.c is UNMODIFIED but we still have a f_metadatareader.c > which can read what it writes to a log file. Are you suggesting that we can > have such a stage 1, with unmodified f_metadata.c, where f_metadatareader.c > is using an already established format already available in ffmpeg? I think > I would be hesitant to go that path d > ue to the asymmetry (f_metadatareader.c uses an existing libavformat to > parse, but f_metadata.c does not and calls vsnprintf directly). > > 2) Regarding error_tracing.h, I'm all for having a discussion (I assume > you are suggesting to start a new discussion thread), but perhaps also as a > stage 2, maybe for stage 1, I will just delete the file and only move the > macros currently being used into f_metadatareader.c so that they are > self-contained and not intended for general use. > > ...Cheng > > -----Original Message----- > From: ffmpeg-devel On Behalf Of Nicolas > George > Sent: Thursday, July 7, 2022 3:09 PM > To: FFmpeg development discussions and patches > Subject: Re: [FFmpeg-devel] [PATCH] Add metadatareader filter. > > Raymond Cheng (12022-07-06): > > FFmpeg has a handy set of filters, metadata/ametadata, which allow us > > to add, print or save per-frame metadata to a file. I will use these > > filters when I want to save the results from speech transcription, > > for instance. What is missing is a way to round-trip the saved > > metadata, so I decided to add filters which go in the opposite > > direction: metadatareader/ametadatareader. These filters inject > > per-frame metadata into the filter graph from a previously saved > > metadata/ametadata file. > > > > If you had a speech transcription filter called speech_recognition > > which produced per-frame metadata using the key "transcription", > > here is how you might use the metadata reader to burn hard subtitles: > > > > Pass 1: ffmpeg -i input -vn -sn -af > speech_recognition,ametadata=mode=print:file=transcription.txt -f null > /dev/null > > Pass 2: ffmpeg -i input -vf > metadatareader=file=transcription.txt,drawtext=fontsize=30:x=30:y=30:fontcolor=yellow:text="'%{metadata\:transcription}'" > out.mp4 > > > > It should be noted in the example above that the metadata crossed > > over from audio to video. It was saved from audio in Pass 1, and > > applied to video on Pass 2. This is perfectly valid, as well as > > non-crossover applications. > > Thanks for the contribution. The feature is interesting, but details > will need to be worked on. > > The coding style needs to be consistent with the rest of FFmpeg's code. > In particular, only use CamelCase for types, not for variables and > functions. And we definitely do not include the type of variables in > their names. > > > > > Signed-off-by: Raymond Cheng > > --- > > Changelog | 1 + > > configure | 2 + > > libavfilter/Makefile | 2 + > > libavfilter/allfilters.c | 2 + > > libavfilter/f_metadatareader.c | 455 +++++++++++++++++ > > It looks to me the file from which the metadata is taken gets parsed in > this patch, and the syntax was invented for the occasion. > > First, if the syntax is invented for the occasion, it must be > documented. > > Second, we try to avoid inventing a syntax for the occasion. Note that > this objection could have been applied to the print option of the > metadata filter; but printing is a much simpler task than parsing and is > often done the quick-and-dirty way. > > I suggest to use libavformat to read frames metadata from a supported > format. > > If libavformat does not contain a format that supports frame metadata > and is easy to write, then we can invent a syntax there. > > But before inventing a syntax for the whole format, we can consider > using a subtitle format and only invent a syntax to encode frame > metadata in the subtitles text. > > > libavutil/error_tracing.h | 126 +++++ > > I am all for adding syntactic sugar in libavutil to make error checking > more lightweight. But it needs to be discussed in its own right to meet > the needs and style of more developers. > > > tests/fate-run.sh | 3 + > > Spurious unrelated changes, debug? > > > tests/fate/filter-audio.mak | 7 + > > tests/fate/filter-video.mak | 6 + > > tests/ref/fate/filter-ametadatareader | 690 ++++++++++++++++++++++++++ > > tests/ref/fate/filter-metadatareader | 14 + > > 11 files changed, 1308 insertions(+) > > create mode 100644 libavfilter/f_metadatareader.c > > create mode 100644 libavutil/error_tracing.h > > create mode 100644 tests/ref/fate/filter-ametadatareader > > create mode 100644 tests/ref/fate/filter-metadatareader > > > > diff --git a/Changelog b/Changelog > > index ba679aa64e..646eac87e9 100644 > > --- a/Changelog > > +++ b/Changelog > > @@ -23,6 +23,7 @@ version 5.1: > > - virtualbass audio filter > > - VDPAU AV1 hwaccel > > - PHM image format support > > +- metadatareader video and ametadatareader audio filter > > > > > > version 5.0: > > diff --git a/configure b/configure > > index fea512e8ef..8262f8d708 100755 > > --- a/configure > > +++ b/configure > > @@ -3614,6 +3614,7 @@ libzmq_protocol_select="network" > > > > # filters > > ametadata_filter_deps="avformat" > > +ametadatareader_filter_deps="avformat" > > amovie_filter_deps="avcodec avformat" > > aresample_filter_deps="swresample" > > asr_filter_deps="pocketsphinx" > > @@ -3679,6 +3680,7 @@ libplacebo_filter_deps="libplacebo vulkan" > > lv2_filter_deps="lv2" > > mcdeint_filter_deps="avcodec gpl" > > metadata_filter_deps="avformat" > > +metadatareader_filter_deps="avformat" > > movie_filter_deps="avcodec avformat" > > mpdecimate_filter_deps="gpl" > > mpdecimate_filter_select="pixelutils" > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > > index 22b0a0ca15..15de9b3815 100644 > > --- a/libavfilter/Makefile > > +++ b/libavfilter/Makefile > > @@ -71,6 +71,7 @@ OBJS-$(CONFIG_ALLPASS_FILTER) += > af_biquads.o > > OBJS-$(CONFIG_ALOOP_FILTER) += f_loop.o > > OBJS-$(CONFIG_AMERGE_FILTER) += af_amerge.o > > OBJS-$(CONFIG_AMETADATA_FILTER) += f_metadata.o > > +OBJS-$(CONFIG_AMETADATAREADER_FILTER) += f_metadatareader.o > > OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o > > OBJS-$(CONFIG_AMULTIPLY_FILTER) += af_amultiply.o > > OBJS-$(CONFIG_ANEQUALIZER_FILTER) += af_anequalizer.o > > @@ -365,6 +366,7 @@ OBJS-$(CONFIG_MEDIAN_FILTER) += > vf_median.o > > OBJS-$(CONFIG_MERGEPLANES_FILTER) += vf_mergeplanes.o > framesync.o > > OBJS-$(CONFIG_MESTIMATE_FILTER) += vf_mestimate.o > motion_estimation.o > > OBJS-$(CONFIG_METADATA_FILTER) += f_metadata.o > > +OBJS-$(CONFIG_METADATAREADER_FILTER) += f_metadatareader.o > > OBJS-$(CONFIG_MIDEQUALIZER_FILTER) += vf_midequalizer.o > framesync.o > > OBJS-$(CONFIG_MINTERPOLATE_FILTER) += vf_minterpolate.o > motion_estimation.o > > OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o framesync.o > > diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c > > index ec70feef11..3e58e52ea7 100644 > > --- a/libavfilter/allfilters.c > > +++ b/libavfilter/allfilters.c > > @@ -58,6 +58,7 @@ extern const AVFilter ff_af_allpass; > > extern const AVFilter ff_af_aloop; > > extern const AVFilter ff_af_amerge; > > extern const AVFilter ff_af_ametadata; > > +extern const AVFilter ff_af_ametadatareader; > > extern const AVFilter ff_af_amix; > > extern const AVFilter ff_af_amultiply; > > extern const AVFilter ff_af_anequalizer; > > @@ -346,6 +347,7 @@ extern const AVFilter ff_vf_median; > > extern const AVFilter ff_vf_mergeplanes; > > extern const AVFilter ff_vf_mestimate; > > extern const AVFilter ff_vf_metadata; > > +extern const AVFilter ff_vf_metadatareader; > > extern const AVFilter ff_vf_midequalizer; > > extern const AVFilter ff_vf_minterpolate; > > extern const AVFilter ff_vf_mix; > > diff --git a/libavfilter/f_metadatareader.c > b/libavfilter/f_metadatareader.c > > new file mode 100644 > > index 0000000000..c36d3ac42b > > --- /dev/null > > +++ b/libavfilter/f_metadatareader.c > > @@ -0,0 +1,455 @@ > > +/* > > + * Copyright (c) 2022 Raymond Cheng > > + * > > + * This file is part of FFmpeg. > > + * > > + * FFmpeg is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU Lesser General Public > > + * License as published by the Free Software Foundation; either > > + * version 2.1 of the License, or (at your option) any later version. > > + * > > + * FFmpeg is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * Lesser General Public License for more details. > > + * > > + * You should have received a copy of the GNU Lesser General Public > > + * License along with FFmpeg; if not, write to the Free Software > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > 02110-1301 USA > > + */ > > + > > + /** > > + * @file > > + * filter for replaying previously saved frame metadata > > + */ > > + > > +#include "config_components.h" > > + > > +#include > > +#include > > +#include "libavfilter/avfilter.h" > > +#include "libavfilter/internal.h" > > +#include "libavfilter/audio.h" > > +#include "libavutil/error_tracing.h" > > +#include "libavutil/log.h" > > +#include "libavutil/opt.h" > > +#include "libavutil/samplefmt.h" > > + > > +// For all macros in error_tracing.h, we shall require AVFilterContext > *ctx be defined, and > > +// use ctx->priv as the private avclass. > > +#undef ERROR_TRACKING_AVCLASS > > +#define ERROR_TRACKING_AVCLASS ctx->priv > > + > > > +//=========================================================================== > > +// Type Definitions > > > +//=========================================================================== > > + > > +typedef struct MetadataEntry { > > + int64_t frame_num; > > + int64_t pts; > > + double pts_time; > > + AVDictionary *metadata; > > +} MetadataEntry; > > + > > +typedef struct MetadataReaderContext { > > + const AVClass *class; > > + > > + char *file_str; > > + > > + int parsed_entries; > > + int allocated_entries; > > + MetadataEntry *rgEntries; > > + int curr_idx; > > +} MetadataReaderContext; > > + > > > +//=========================================================================== > > +// Methods > > > +//=========================================================================== > > + > > +static av_cold int parse_line(AVFilterContext *ctx, char **rgTokens, > int numTokens, char *pszLine, const char *pszDelims) > > +{ > > + int iResult = 0; > > + MetadataReaderContext *pThis = ctx->priv; > > + char szLineForError[8192]; > > + > > + int chars_to_copy = strlen(pszLine); > > + if (chars_to_copy >= FF_ARRAY_ELEMS(szLineForError)) > > + chars_to_copy = FF_ARRAY_ELEMS(szLineForError) - 1; > > + > > + strncpy(szLineForError, pszLine, chars_to_copy); > > + szLineForError[chars_to_copy] = '\0'; > > + for (int i = 0; i < numTokens; i++) { > > + rgTokens[i] = strtok(i == 0 ? pszLine: NULL, pszDelims); > > + CHECKCOND_EXIT(rgTokens[i], AVERROR_INVALIDDATA); > > + } > > + > > +exit: > > + if (iResult < 0) { > > + av_log(pThis, AV_LOG_ERROR, "Failed to parse line from %s: > %s\n", pThis->file_str, > > + iResult == AVERROR(ERANGE) ? pszLine : szLineForError); > > + } > > + > > + return iResult; > > +} > > + > > +static av_cold void remove_newline(char *psz, int idx) > > +{ > > + char c; > > + if (idx < 0) > > + return; // This can happen for small length > > + > > + c = psz[idx]; > > + if (c == '\r' || c == '\n') > > + psz[idx] = '\0'; > > +} > > + > > +static av_cold int check_for_nopts(AVFilterContext *ctx, char *psz) > > +{ > > + int iResult = 0; > > + MetadataReaderContext *pThis = ctx->priv; > > + > > + const char szNOPTS[] = "NOPTS"; > > + if (!strncmp(szNOPTS, psz, FF_ARRAY_ELEMS(szNOPTS))) { > > + av_log(pThis, AV_LOG_ERROR, "Found NOPTS in %s: Current > implementation does not handle this!\n", pThis->file_str); > > + CHECKINT_EXIT(AVERROR_INVALIDDATA); > > + } > > + > > +exit: > > + return iResult; > > +} > > + > > +static av_cold void remove_trailing_newlines(char *psz) > > +{ > > + int len = strlen(psz); > > + remove_newline(psz, len - 1); > > + remove_newline(psz, len - 2); > > +} > > + > > +static av_cold int init(AVFilterContext *ctx) > > +{ > > + int iResult = 0; > > + MetadataReaderContext *pThis = ctx->priv; > > + FILE *file = NULL; > > + char szLine[8192]; > > + char szLastKey[1024]; > > + szLine[0] = '\0'; > > + szLastKey[0] = '\0'; > > + > > + CHECKCOND_EXIT(pThis->file_str && pThis->file_str[0] != '\0', > AVERROR(EINVAL)); > > + pThis->curr_idx = -1; // We pre-increment this index so we can > handle multi-line metadata > > + > > + errno = 0; > > + file = fopen(pThis->file_str, "r"); > > + if (!file) { > > + char *pszErrStr = strerror(errno); > > + av_log(pThis, AV_LOG_ERROR, "Failed to open file %s: errno = > %d: %s\n", pThis->file_str, errno, > > + pszErrStr ? pszErrStr : "(No error string)"); > > + CHECKINT_EXIT(AVERROR(ENOENT)); > > + } > > + > > > + while (fgets(szLine, FF_ARRAY_ELEMS(szLine), file)) { > > This is misusing FF_ARRAY_ELEMS(): you want the actual size. > > > + const char szFrame[] = "frame:"; > > + if (!strncmp(szFrame, szLine, FF_ARRAY_ELEMS(szFrame) - 1)) { > > + const char szPts[] = "pts"; > > + const char szPtsTime[] = "pts_time"; > > + char *rgTokens[5] = { 0 }; > > + MetadataEntry *entry; > > + > > + pThis->curr_idx++; > > + pThis->parsed_entries++; > > + if (pThis->curr_idx >= pThis->allocated_entries) { > > + int new_allocated_entries = pThis->allocated_entries + > 100; > > + CHECKINT_EXIT(av_reallocp_array(&pThis->rgEntries, > new_allocated_entries, sizeof(pThis->rgEntries[0]))); > > + pThis->allocated_entries = new_allocated_entries; > > + } > > + > > + // Tokenize and verify the fixed values > > + CHECKINT_EXIT(parse_line(ctx, rgTokens, > FF_ARRAY_ELEMS(rgTokens), szLine + FF_ARRAY_ELEMS(szFrame) - 1, " :")); > > + CHECKCOND_EXIT(!strncmp(szPts, rgTokens[1], > FF_ARRAY_ELEMS(szPts)), AVERROR_INVALIDDATA); > > + CHECKCOND_EXIT(!strncmp(szPtsTime, rgTokens[3], > FF_ARRAY_ELEMS(szPtsTime)), AVERROR_INVALIDDATA); > > + > > + // Parse and save the values > > + entry = &pThis->rgEntries[pThis->curr_idx]; > > + entry->frame_num = atoll(rgTokens[0]); > > + if (pThis->curr_idx > 0 && (entry - 1)->frame_num >= > entry->frame_num) { > > + av_log(pThis, AV_LOG_ERROR, "Frame numbers in %s went > from %"PRId64" to %"PRId64", expected monotonic increase!\n", > > + pThis->file_str, (entry - 1)->frame_num, > entry->frame_num); > > + CHECKINT_EXIT(AVERROR_INVALIDDATA); > > + } > > + CHECKINT_EXIT(check_for_nopts(ctx, rgTokens[2])); > > + entry->pts = atoll(rgTokens[2]); > > + if (pThis->curr_idx > 0 && (entry - 1)->pts >= entry->pts) { > > + av_log(pThis, AV_LOG_ERROR, "pts in %s went from > %"PRId64" to %"PRId64", current implementation can't handle this!\n", > > + pThis->file_str, (entry - 1)->pts, entry->pts); > > + CHECKINT_EXIT(AVERROR_INVALIDDATA); > > + } > > + CHECKINT_EXIT(check_for_nopts(ctx, rgTokens[4])); > > + entry->pts_time = atof(rgTokens[4]); // We don't have > time_base, so we lose some accuracy, but probably close enough > > + if (pThis->curr_idx > 0 && (entry - 1)->pts_time >= > entry->pts_time) { > > + av_log(pThis, AV_LOG_ERROR, "pts_time in %s went from > %g to %g, current implementation can't handle this!\n", > > + pThis->file_str, (entry - 1)->pts_time, > entry->pts_time); > > + CHECKINT_EXIT(AVERROR_INVALIDDATA); > > + } > > + > > + entry->metadata = NULL; > > + szLastKey[0] = '\0'; > > + } else { > > + char *pszEquals; > > + if (pThis->curr_idx < 0) { > > + av_log(pThis, AV_LOG_ERROR, "Expected frame: line in > %s, instead got: %s!\n", pThis->file_str, szLine); > > + CHECKINT_EXIT(AVERROR_INVALIDDATA); > > + } > > + > > + pszEquals = strchr(szLine, '='); // Find first instance, > ignore subsequent > > + if (pszEquals) { > > + // New key/value entry - remove any CRLF found at end > of value string > > + int chars_to_copy; > > + char *pszValue = pszEquals + 1; > > + *pszEquals = '\0'; > > + remove_trailing_newlines(pszValue); > > + > CHECKINT_EXIT(av_dict_set(&pThis->rgEntries[pThis->curr_idx].metadata, > szLine, pszValue, 0)); > > + > > + chars_to_copy = strlen(szLine); > > + if (chars_to_copy >= FF_ARRAY_ELEMS(szLastKey)) > > + chars_to_copy = FF_ARRAY_ELEMS(szLastKey) - 1; > > + > > + strncpy(szLastKey, szLine, chars_to_copy); > > + szLastKey[chars_to_copy] = '\0'; > > + } else { > > + // This should be a continuation of a prior key/value > entry - prepend newline, then append value > > + remove_trailing_newlines(szLine); > > + > CHECKINT_EXIT(av_dict_set(&pThis->rgEntries[pThis->curr_idx].metadata, > szLastKey, "\n", AV_DICT_APPEND)); > > + > CHECKINT_EXIT(av_dict_set(&pThis->rgEntries[pThis->curr_idx].metadata, > szLastKey, szLine, AV_DICT_APPEND)); > > + } > > + } > > + } > > + > > + pThis->curr_idx = 0; > > + fclose(file); // Ignore error > > + > > +exit: > > + return iResult; > > +} > > + > > +static av_cold void uninit(AVFilterContext *ctx) > > +{ > > + MetadataReaderContext *pThis = ctx->priv; > > + if (pThis->rgEntries) { > > + for (int i = 0; i < pThis->parsed_entries; i++) > > + av_dict_free(&pThis->rgEntries[i].metadata); > > + > > + av_freep(&pThis->rgEntries); > > + } > > +} > > + > > +// tolerance is exclusive - we snap to an entry which is different by > LESS THAN but not equal to tolerance > > +static int set_curr_idx(AVFilterContext *ctx, double pts_time, double > tolerance, int *found) > > +{ > > + int iResult = 0; > > + MetadataReaderContext *pThis = ctx->priv; > > + > > + // This function assumes that incoming pts's are increasing and do > not regress. > > + *found = 0; > > + while (pThis->curr_idx < pThis->parsed_entries) { > > + MetadataEntry *entry = &pThis->rgEntries[pThis->curr_idx]; > > + if (fabs(entry->pts_time - pts_time) < tolerance) { > > + *found = 1; > > + break; // Apply current entry's metadata dictionary > > + } else if (entry->pts_time > pts_time) { > > + if (pThis->curr_idx <= 0) { > > + av_log(pThis, AV_LOG_DEBUG, "No corresponding metadata > entries found for pts_time %g.\n", > > + pts_time); > > + goto exit; > > + } > > + > > + if ((entry - 1)->pts_time <= pts_time) { > > + *found = 1; > > + pThis->curr_idx--; // Apply previous entry's metadata > dictionary > > + break; > > + } else { > > + av_log(pThis, AV_LOG_ERROR, "pts_time may have > regressed: %g may require rewinding more than one entry (not > implemented)!\n", > > + pts_time); > > + CHECKINT_EXIT(AVERROR(ENOTSUP)); > > + } > > + } else if (pThis->curr_idx + 1 >= pThis->parsed_entries) { > > + // If we reach this point, then entry->pts_time is strictly > < pts_time and no more entries, > > + // so current index is the correct one. > > + *found = 1; > > + break; > > + } > > + > > + // Advance variables > > + pThis->curr_idx++; > > + } > > + > > +exit: > > + return iResult; > > +} > > + > > +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) > > +{ > > + int iResult = 0; > > + AVFilterContext *ctx = inlink->dst; > > + MetadataReaderContext *pThis = (MetadataReaderContext*)ctx->priv; > > + int found; > > + double pts_time; > > + > > + if (frame->pts == AV_NOPTS_VALUE) { > > + av_log(pThis, AV_LOG_ERROR, "Current implementation cannot > handle PTS of AV_NOPTS_VALUE!"); > > + CHECKINT_EXIT(AVERROR(ENOTSUP)); > > + } > > + > > + pts_time = av_q2d(inlink->time_base) * frame->pts; > > + CHECKINT_EXIT(set_curr_idx(ctx, pts_time, 0.001, &found)); // 1 > millisecond tolerance > > + if (found) { > > + CHECKINT_EXIT(av_dict_copy(&frame->metadata, > pThis->rgEntries[pThis->curr_idx].metadata, 0)); > > + } > > + > > + av_assert_int32_equals(1, ctx->nb_outputs); > > + CHECKINT_EXIT_EX_EAGAIN_EOF(ff_filter_frame(ctx->outputs[0], > frame)); > > + > > +exit: > > + if (iResult < 0) { > > + av_frame_free(&frame); > > + } > > + > > + return iResult; > > +} > > + > > +static int filter_frame_audio(AVFilterLink *inlink, AVFrame *frame) > > +{ > > + int iResult = 0; > > + AVFilterContext *ctx = inlink->dst; > > + MetadataReaderContext *pThis = (MetadataReaderContext*)ctx->priv; > > + AVFrame *pFrame = NULL; > > + int found; > > + int nb_samples_sent = 0; > > + double tolerance, pts_time, pts_end; > > + > > + if (frame->pts == AV_NOPTS_VALUE) { > > + av_log(pThis, AV_LOG_ERROR, "Current implementation cannot > handle PTS of AV_NOPTS_VALUE!"); > > + CHECKINT_EXIT(AVERROR(ENOTSUP)); > > + } > > + > > + tolerance = 1.0 / inlink->sample_rate; // less than 1 audio sample > tolerance > > + pts_time = av_q2d(inlink->time_base) * frame->pts; > > + pts_end = av_q2d(inlink->time_base) * (frame->pts + > frame->nb_samples); > > + CHECKINT_EXIT(set_curr_idx(ctx, pts_time, tolerance, &found)); > > + if (!found) { > > + av_assert_int32_equals(1, ctx->nb_outputs); > > + CHECKINT_EXIT_EX_EAGAIN_EOF(ff_filter_frame(ctx->outputs[0], > frame)); > > + goto exit; > > + } > > + > > + while (found) { > > + int nb_samples; > > + double metadata_pts_end; > > + if (pThis->curr_idx + 1 < pThis->parsed_entries) > > + metadata_pts_end = pThis->rgEntries[pThis->curr_idx + > 1].pts_time; > > + else > > + metadata_pts_end = pts_end; > > + > > + nb_samples = (int)(inlink->sample_rate * (fmax(pts_end, > metadata_pts_end) - pts_time) + 0.5); > > + av_assert_int32_ge(nb_samples, 1); // If nb_samples is 0 we are > going into an infinite loop > > + if (nb_samples > frame->nb_samples - nb_samples_sent) > > + nb_samples = frame->nb_samples - nb_samples_sent; > > + > > + pFrame = ff_get_audio_buffer(ctx->outputs[0], nb_samples); > > + CHECKCOND_EXIT(pFrame, AVERROR(ENOMEM)); > > + CHECKINT_EXIT(av_samples_copy(pFrame->extended_data, > frame->extended_data, 0, nb_samples_sent, > > + nb_samples, frame->ch_layout.nb_channels, frame->format)); > > + CHECKINT_EXIT(av_dict_copy(&pFrame->metadata, > pThis->rgEntries[pThis->curr_idx].metadata, 0)); > > + pFrame->pts = frame->pts + nb_samples_sent; > > + > > + av_assert_int32_equals(1, ctx->nb_outputs); > > + CHECKINT_EXIT_EX_EAGAIN_EOF(ff_filter_frame(ctx->outputs[0], > pFrame)); > > + > > + nb_samples_sent += nb_samples; > > + if (nb_samples_sent >= frame->nb_samples) > > + break; > > + > > + pts_time = av_q2d(inlink->time_base) * (frame->pts + > nb_samples_sent); > > + CHECKINT_EXIT(set_curr_idx(ctx, pts_time, tolerance, &found)); > > + } > > + > > +exit: > > + if (iResult < 0) { > > + av_frame_free(&pFrame); > > + av_frame_free(&frame); > > + } > > + > > + return iResult; > > +} > > + > > +#define OFFSET(x) offsetof(MetadataReaderContext, x) > > +#define DEFINE_OPTIONS(filt_name, FLAGS) \ > > +static const AVOption filt_name##_options[] = { \ > > + { "file", "set file to read metadata information from", > OFFSET(file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, \ > > + { NULL } \ > > +} > > + > > +#if CONFIG_AMETADATAREADER_FILTER > > + > > +DEFINE_OPTIONS(ametadatareader, AV_OPT_FLAG_AUDIO_PARAM | > AV_OPT_FLAG_FILTERING_PARAM); > > +AVFILTER_DEFINE_CLASS(ametadatareader); > > + > > +static const AVFilterPad ainputs[] = { > > + { > > + .name = "default", > > + .type = AVMEDIA_TYPE_AUDIO, > > + .filter_frame = filter_frame_audio, > > + }, > > +}; > > + > > +static const AVFilterPad aoutputs[] = { > > + { > > + .name = "default", > > + .type = AVMEDIA_TYPE_AUDIO, > > + }, > > +}; > > + > > +const AVFilter ff_af_ametadatareader = { > > + .name = "ametadatareader", > > + .description = NULL_IF_CONFIG_SMALL("Replay a/v metadata from prior > session onto audio stream."), > > + .priv_size = sizeof(MetadataReaderContext), > > + .priv_class = &ametadatareader_class, > > + .init = init, > > + .uninit = uninit, > > + FILTER_INPUTS(ainputs), > > + FILTER_OUTPUTS(aoutputs), > > + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, > > +}; > > +#endif // CONFIG_AMETADATAREADER_FILTER > > + > > +#if CONFIG_METADATAREADER_FILTER > > + > > +DEFINE_OPTIONS(metadatareader, AV_OPT_FLAG_VIDEO_PARAM | > AV_OPT_FLAG_FILTERING_PARAM); > > +AVFILTER_DEFINE_CLASS(metadatareader); > > + > > +static const AVFilterPad inputs[] = { > > + { > > + .name = "default", > > + .type = AVMEDIA_TYPE_VIDEO, > > + .filter_frame = filter_frame, > > + }, > > +}; > > + > > +static const AVFilterPad outputs[] = { > > + { > > + .name = "default", > > + .type = AVMEDIA_TYPE_VIDEO, > > + }, > > +}; > > + > > +const AVFilter ff_vf_metadatareader = { > > + .name = "metadatareader", > > + .description = NULL_IF_CONFIG_SMALL("Replay a/v metadata from prior > session onto video stream."), > > + .priv_size = sizeof(MetadataReaderContext), > > + .priv_class = &metadatareader_class, > > + .init = init, > > + .uninit = uninit, > > + FILTER_INPUTS(inputs), > > + FILTER_OUTPUTS(outputs), > > + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, > > +}; > > +#endif // CONFIG_METADATAREADER_FILTER > > diff --git a/libavutil/error_tracing.h b/libavutil/error_tracing.h > > new file mode 100644 > > index 0000000000..0543c69619 > > --- /dev/null > > +++ b/libavutil/error_tracing.h > > @@ -0,0 +1,126 @@ > > +/* > > + * This file is part of FFmpeg. > > + * > > + * FFmpeg is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU Lesser General Public > > + * License as published by the Free Software Foundation; either > > + * version 2.1 of the License, or (at your option) any later version. > > + * > > + * FFmpeg is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * Lesser General Public License for more details. > > + * > > + * You should have received a copy of the GNU Lesser General Public > > + * License along with FFmpeg; if not, write to the Free Software > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > 02110-1301 USA > > + */ > > + > > +/** > > + * @file > > + * error code definitions > > + */ > > + > > +#ifndef AVUTIL_ERROR_TRACING_H > > +#define AVUTIL_ERROR_TRACING_H > > + > > > +//=========================================================================== > > +// Macros > > > +//=========================================================================== > > + > > +#define CHECKINT_EXIT_AVCLASS(x, avclass) \ > > + iResult = (x); \ > > + if (iResult < 0) { \ > > + av_log(avclass, AV_LOG_WARNING, "%s(%d): *** ERROR ***: > %d!\n", \ > > + __FILE__, __LINE__, iResult); \ > > + goto exit; \ > > + } else {} \ > > + > > +#define CHECKCOND_EXIT_AVCLASS(cond, errCode, avclass) > CHECKINT_EXIT_AVCLASS((cond) ? 0 : errCode, avclass) > > + > > +#define CHECKINT_EXIT_EX_EAGAIN_EOF_AVCLASS(x, avclass) > \ > > + iResult = (x); > \ > > + if (iResult < 0) { > \ > > + if (AVERROR(EAGAIN) != iResult && AVERROR_EOF != iResult) { > \ > > + av_log(avclass, AV_LOG_WARNING, "%s(%d): *** ERROR ***: > %d!\n",\ > > + __FILE__, __LINE__, iResult); > \ > > + goto exit; > \ > > + } else { > \ > > + av_log(avclass, AV_LOG_DEBUG, "%s(%d): > CHECKINT_EXIT_EX_EAGAIN_EOF saw %s!\n", \ > > + __FILE__, __LINE__, AVERROR_EOF == iResult ? > "AVERROR_EOF" : "AVERROR(EAGAIN)"); \ > > + } > \ > > + } else {} > > + > > +#define CHECK_ARG_SIZES(expected, actual, size) \ > > + static_assert(sizeof(actual) == size, "The parameter, " > AV_STRINGIFY(actual) ", is not " AV_STRINGIFY(size) " bytes! Please use the > correctly-sized macro."); \ > > + static_assert(sizeof(expected) <= size, "The parameter, " > AV_STRINGIFY(expected) ", is greater than " AV_STRINGIFY(size) " bytes! > Please use the correctly-sized macro."); > > + > > +#define av_assert_equals_msg_avclass(expected, actual, msg, avclass, > size, formattype) do { \ > > + CHECK_ARG_SIZES(expected, actual, size) > \ > > + if ((expected) != (actual)) { > \ > > + av_log(avclass, AV_LOG_PANIC, > \ > > + "Assertion failed: Expected " formattype " (%s), actual is > " formattype " (%s) %s at %s:%d\n", \ > > + (expected), AV_STRINGIFY(expected), (actual), > \ > > + AV_STRINGIFY(actual), msg, __FILE__, __LINE__); > \ > > + abort(); > \ > > + } > \ > > +} while (0) > > +#define av_assert_int32_equals_msg_avclass(expected, actual, msg, > avclass) av_assert_equals_msg_avclass(expected, actual, msg, avclass, 4, > "%"PRId32) > > +#define av_assert_int32_equals_avclass(expected, actual, avclass) > av_assert_int32_equals_msg_avclass(expected, actual, "-", avclass) > > +#define av_assert_int64_equals_msg_avclass(expected, actual, msg, > avclass) av_assert_equals_msg_avclass(expected, actual, msg, avclass, 8, > "%"PRId64) > > +#define av_assert_int64_equals_avclass(expected, actual, avclass) > av_assert_int64_equals_msg_avclass(expected, actual, "-", avclass) > > + > > +#define av_assert_ge_msg_avclass(actual, minvalue, msg, avclass, size, > formattype) do { \ > > + CHECK_ARG_SIZES(minvalue, actual, size) > \ > > + if ((actual) < (minvalue)) { > \ > > + av_log(avclass, AV_LOG_PANIC, > \ > > + "Assertion failed: %s (" formattype ") < %s (" formattype > ") %s at %s:%d\n", \ > > + AV_STRINGIFY(actual), (actual), AV_STRINGIFY(minvalue), > \ > > + (minvalue), msg, __FILE__, __LINE__); > \ > > + abort(); > \ > > + } > \ > > +} while (0) > > +#define av_assert_int32_ge_msg_avclass(actual, minvalue, msg, avclass) > av_assert_ge_msg_avclass(actual, minvalue, msg, avclass, 4, "%"PRId32) > > +#define av_assert_int32_ge_avclass(actual, minvalue, avclass) > av_assert_int32_ge_msg_avclass(actual, minvalue, "-", avclass) > > +#define av_assert_int64_ge_msg_avclass(actual, minvalue, msg, avclass) > av_assert_ge_msg_avclass(actual, minvalue, msg, avclass, 8, "%"PRId64) > > +#define av_assert_int64_ge_avclass(actual, minvalue, avclass) > av_assert_int64_ge_msg_avclass(actual, minvalue, "-", avclass) > > + > > +#define av_assert_str_equals_msg_avclass(expected, actual, msg, > avclass) do { \ > > + if (strcmp(expected, actual)) { > \ > > + av_log(avclass, AV_LOG_PANIC, > \ > > + "Assertion failed: Expected \"%s\" (%s), actual is \"%s\" > (%s) %s at %s:%d\n", \ > > + (expected), AV_STRINGIFY(expected), (actual), > \ > > + AV_STRINGIFY(actual), msg, __FILE__, __LINE__); > \ > > + abort(); > \ > > + } > \ > > +} while (0) > > +#define av_assert_str_equals_avclass(expected, actual, avclass) > av_assert_str_equals_msg_avclass(expected, actual, "-", avclass) > > + > > > +//=========================================================================== > > +// Short Definitions > > > +//=========================================================================== > > + > > +// By default, use NULL for avclass, but you SHOULD undef and re-define > ERROR_TRACING_AVCLASS > > +// to use your private avclass in your own *.c file. For instance, if > all of your functions > > +// use the convention, AVFilterContext *ctx, you can require ctx->priv > always be defined > > +// when using these macros, or if you always have a private pointer (eg > MOVMuxContext *mov > > +// in movenc.c), then you can require that mov be defined when using > these macros. > > + > > +#define ERROR_TRACKING_AVCLASS NULL > > + > > +#define CHECKINT_EXIT(x) CHECKINT_EXIT_AVCLASS(x, > ERROR_TRACKING_AVCLASS) > > +#define CHECKCOND_EXIT(cond, errCode) CHECKCOND_EXIT_AVCLASS(cond, > errCode, ERROR_TRACKING_AVCLASS) > > +#define CHECKINT_EXIT_EX_EAGAIN_EOF(x) > CHECKINT_EXIT_EX_EAGAIN_EOF_AVCLASS(x, ERROR_TRACKING_AVCLASS) > > + > > +#define av_assert_int32_equals_msg(expected, actual, msg) > av_assert_int32_equals_msg_avclass(expected, actual, msg, > ERROR_TRACKING_AVCLASS) > > +#define av_assert_int32_equals(expected, actual) > av_assert_int32_equals_avclass(expected, actual, ERROR_TRACKING_AVCLASS) > > +#define av_assert_int64_equals_msg(expected, actual, msg) > av_assert_int64_equals_msg_avclass(expected, actual, msg, > ERROR_TRACKING_AVCLASS) > > +#define av_assert_int64_equals(expected, actual) > av_assert_int64_equals_avclass(expected, actual, ERROR_TRACKING_AVCLASS) > > +#define av_assert_int32_ge_msg(actual, minvalue, msg) > av_assert_int32_ge_msg_avclass(actual, minvalue, msg, > ERROR_TRACKING_AVCLASS) > > +#define av_assert_int32_ge(actual, minvalue) > av_assert_int32_ge_avclass(actual, minvalue, ERROR_TRACKING_AVCLASS) > > +#define av_assert_int64_ge_msg(actual, minvalue, msg) > av_assert_int64_ge_msg_avclass(actual, minvalue, msg, > ERROR_TRACKING_AVCLASS) > > +#define av_assert_int64_ge(actual, minvalue) > av_assert_int64_ge_avclass(actual, minvalue, ERROR_TRACKING_AVCLASS) > > +#define av_assert_str_equals_msg(expected, actual, msg) > av_assert_str_equals_msg_avclass(expected, actual, msg, > ERROR_TRACKING_AVCLASS) > > +#define av_assert_str_equals(expected, actual) > av_assert_str_equals_avclass(expected, actual, ERROR_TRACKING_AVCLASS) > > + > > +#endif // AVUTIL_ERROR_TRACING_H > > diff --git a/tests/fate-run.sh b/tests/fate-run.sh > > index 525e8e5499..09a7525321 100755 > > --- a/tests/fate-run.sh > > +++ b/tests/fate-run.sh > > @@ -76,6 +76,7 @@ oneline(){ > > } > > > > run(){ > > + echo $target_exec $target_path/"$@" >> $outfile.cmd > > test "${V:-0}" -gt 0 && echo "$target_exec" $target_path/"$@" >&3 > > $target_exec $target_path/"$@" > > } > > @@ -98,6 +99,7 @@ probetags(){ > > } > > > > runlocal(){ > > + echo ${base}/"$@" ${base} >&3 >> $outfile.cmd > > test "${V:-0}" -gt 0 && echo ${base}/"$@" ${base} >&3 > > ${base}/"$@" ${base} > > } > > @@ -576,6 +578,7 @@ null(){ > > # must be kept verbatim > > set -f > > > > +#echo $command TO $outfile ERRTO $errfile > $outfile.cmd > > exec 3>&2 > > eval $command >"$outfile" 2>$errfile > > err=$? > > diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak > > index eff32b9f81..ca1b60f47a 100644 > > --- a/tests/fate/filter-audio.mak > > +++ b/tests/fate/filter-audio.mak > > @@ -397,6 +397,13 @@ fate-filter-hdcd-s32p: CMD = md5 -i $(SRC) -af hdcd > -f s32le > > fate-filter-hdcd-s32p: CMP = oneline > > fate-filter-hdcd-s32p: REF = 0c5513e83eedaa10ab6fac9ddc173cf5 > > > > +# A metadata reader, reading the ref file and connected to a metadata > (writer) should be identity transform > > +FATE_AFILTER_SAMPLES-$(call ALLYES, AMETADATA_FILTER > AMETADATAREADER_FILTER WAV_DEMUXER PCM_S16LE_DECODER) += > fate-filter-ametadatareader > > +fate-filter-ametadatareader: tests/data/asynth-44100-2.wav > > +fate-filter-ametadatareader: CMD = ffmpeg -i > $(TARGET_PATH)/tests/data/asynth-44100-2.wav -af \ > > + > ametadatareader=file=$(SRC_PATH)/tests/ref/fate/filter-metadatareader,ametadata=mode=print:file=- > \ > > + -f null /dev/null > > + > > FATE_AFILTER-yes += fate-filter-formats > > fate-filter-formats: libavfilter/tests/formats$(EXESUF) > > fate-filter-formats: CMD = run libavfilter/tests/formats$(EXESUF) > > diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak > > index faed832cd4..51d9058f0f 100644 > > --- a/tests/fate/filter-video.mak > > +++ b/tests/fate/filter-video.mak > > @@ -711,6 +711,12 @@ fate-filter-refcmp-ssim-rgb: CMD = refcmp_metadata > ssim rgb24 0.015 > > FATE_FILTER_REFCMP_METADATA-$(CONFIG_SSIM_FILTER) += > fate-filter-refcmp-ssim-yuv > > fate-filter-refcmp-ssim-yuv: CMD = refcmp_metadata ssim yuv422p 0.015 > > > > +# A metadata reader, reading the ref file and connected to a metadata > (writer) should be identity transform > > +FATE_FILTER_SAMPLES-$(call ALLYES, FFMPEG LAVFI_INDEV TESTSRC2_FILTER > METADATA_FILTER METADATAREADER_FILTER) += fate-filter-metadatareader > > +fate-filter-metadatareader: CMD = ffmpeg -lavfi \ > > + > "testsrc2=size=300x200:rate=1:duration=5,format=rgb24,metadatareader=file=$(SRC_PATH)/tests/ref/fate/filter-metadatareader,metadata=mode=print:file=-" > \ > > + -f null /dev/null > > + > > FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER SPLIT_FILTER AVGBLUR_FILTER > \ > > METADATA_FILTER WRAPPED_AVFRAME_ENCODER > NULL_MUXER \ > > PIPE_PROTOCOL) += > $(FATE_FILTER_REFCMP_METADATA-yes) > > diff --git a/tests/ref/fate/filter-ametadatareader > b/tests/ref/fate/filter-ametadatareader > > new file mode 100644 > > index 0000000000..e1a473e574 > > --- /dev/null > > +++ b/tests/ref/fate/filter-ametadatareader > > @@ -0,0 +1,690 @@ > > +frame:0 pts:0 pts_time:0 > > +TestKey1=AAAAA > > +frame:1 pts:1024 pts_time:0.02322 > > +TestKey1=AAAAA > > +frame:2 pts:2048 pts_time:0.0464399 > > +TestKey1=AAAAA > > +frame:3 pts:3072 pts_time:0.0696599 > > +TestKey1=AAAAA > > +frame:4 pts:4096 pts_time:0.0928798 > > +TestKey1=AAAAA > > +frame:5 pts:5120 pts_time:0.1161 > > +TestKey1=AAAAA > > +frame:6 pts:6144 pts_time:0.13932 > > +TestKey1=AAAAA > > +frame:7 pts:7168 pts_time:0.16254 > > +TestKey1=AAAAA > > +frame:8 pts:8192 pts_time:0.18576 > > +TestKey1=AAAAA > > +frame:9 pts:9216 pts_time:0.20898 > > +TestKey1=AAAAA > > +frame:10 pts:10240 pts_time:0.2322 > > +TestKey1=AAAAA > > +frame:11 pts:11264 pts_time:0.25542 > > +TestKey1=AAAAA > > +frame:12 pts:12288 pts_time:0.278639 > > +TestKey1=AAAAA > > +frame:13 pts:13312 pts_time:0.301859 > > +TestKey1=AAAAA > > +frame:14 pts:14336 pts_time:0.325079 > > +TestKey1=AAAAA > > +frame:15 pts:15360 pts_time:0.348299 > > +TestKey1=AAAAA > > +frame:16 pts:16384 pts_time:0.371519 > > +TestKey1=AAAAA > > +frame:17 pts:17408 pts_time:0.394739 > > +TestKey1=AAAAA > > +frame:18 pts:18432 pts_time:0.417959 > > +TestKey1=AAAAA > > +frame:19 pts:19456 pts_time:0.441179 > > +TestKey1=AAAAA > > +frame:20 pts:20480 pts_time:0.464399 > > +TestKey1=AAAAA > > +frame:21 pts:21504 pts_time:0.487619 > > +TestKey1=AAAAA > > +frame:22 pts:22528 pts_time:0.510839 > > +TestKey1=AAAAA > > +frame:23 pts:23552 pts_time:0.534059 > > +TestKey1=AAAAA > > +frame:24 pts:24576 pts_time:0.557279 > > +TestKey1=AAAAA > > +frame:25 pts:25600 pts_time:0.580499 > > +TestKey1=AAAAA > > +frame:26 pts:26624 pts_time:0.603719 > > +TestKey1=AAAAA > > +frame:27 pts:27648 pts_time:0.626939 > > +TestKey1=AAAAA > > +frame:28 pts:28672 pts_time:0.650159 > > +TestKey1=AAAAA > > +frame:29 pts:29696 pts_time:0.673379 > > +TestKey1=AAAAA > > +frame:30 pts:30720 pts_time:0.696599 > > +TestKey1=AAAAA > > +frame:31 pts:31744 pts_time:0.719819 > > +TestKey1=AAAAA > > +frame:32 pts:32768 pts_time:0.743039 > > +TestKey1=AAAAA > > +frame:33 pts:33792 pts_time:0.766259 > > +TestKey1=AAAAA > > +frame:34 pts:34816 pts_time:0.789478 > > +TestKey1=AAAAA > > +frame:35 pts:35840 pts_time:0.812698 > > +TestKey1=AAAAA > > +frame:36 pts:36864 pts_time:0.835918 > > +TestKey1=AAAAA > > +frame:37 pts:37888 pts_time:0.859138 > > +TestKey1=AAAAA > > +frame:38 pts:38912 pts_time:0.882358 > > +TestKey1=AAAAA > > +frame:39 pts:39936 pts_time:0.905578 > > +TestKey1=AAAAA > > +frame:40 pts:40960 pts_time:0.928798 > > +TestKey1=AAAAA > > +frame:41 pts:41984 pts_time:0.952018 > > +TestKey1=AAAAA > > +frame:42 pts:43008 pts_time:0.975238 > > +TestKey1=AAAAA > > +frame:43 pts:44032 pts_time:0.998458 > > +TestKey1=AAAAA > > +frame:44 pts:45056 pts_time:1.02168 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:45 pts:46080 pts_time:1.0449 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:46 pts:47104 pts_time:1.06812 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:47 pts:48128 pts_time:1.09134 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:48 pts:49152 pts_time:1.11456 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:49 pts:50176 pts_time:1.13778 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:50 pts:51200 pts_time:1.161 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:51 pts:52224 pts_time:1.18422 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:52 pts:53248 pts_time:1.20744 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:53 pts:54272 pts_time:1.23066 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:54 pts:55296 pts_time:1.25388 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:55 pts:56320 pts_time:1.2771 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:56 pts:57344 pts_time:1.30032 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:57 pts:58368 pts_time:1.32354 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:58 pts:59392 pts_time:1.34676 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:59 pts:60416 pts_time:1.36998 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:60 pts:61440 pts_time:1.3932 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:61 pts:62464 pts_time:1.41642 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:62 pts:63488 pts_time:1.43964 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:63 pts:64512 pts_time:1.46286 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:64 pts:65536 pts_time:1.48608 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:65 pts:66560 pts_time:1.5093 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:66 pts:67584 pts_time:1.53252 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:67 pts:68608 pts_time:1.55574 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:68 pts:69632 pts_time:1.57896 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:69 pts:70656 pts_time:1.60218 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:70 pts:71680 pts_time:1.6254 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:71 pts:72704 pts_time:1.64862 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:72 pts:73728 pts_time:1.67184 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:73 pts:74752 pts_time:1.69506 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:74 pts:75776 pts_time:1.71828 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:75 pts:76800 pts_time:1.7415 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:76 pts:77824 pts_time:1.76472 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:77 pts:78848 pts_time:1.78794 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:78 pts:79872 pts_time:1.81116 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:79 pts:80896 pts_time:1.83438 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:80 pts:81920 pts_time:1.8576 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:81 pts:82944 pts_time:1.88082 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:82 pts:83968 pts_time:1.90404 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:83 pts:84992 pts_time:1.92726 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:84 pts:86016 pts_time:1.95048 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:85 pts:87040 pts_time:1.9737 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:86 pts:88064 pts_time:1.99692 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:87 pts:89088 pts_time:2.02014 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:88 pts:90112 pts_time:2.04336 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:89 pts:91136 pts_time:2.06658 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:90 pts:92160 pts_time:2.0898 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:91 pts:93184 pts_time:2.11302 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:92 pts:94208 pts_time:2.13624 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:93 pts:95232 pts_time:2.15946 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:94 pts:96256 pts_time:2.18268 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:95 pts:97280 pts_time:2.2059 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:96 pts:98304 pts_time:2.22912 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:97 pts:99328 pts_time:2.25234 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:98 pts:100352 pts_time:2.27556 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:99 pts:101376 pts_time:2.29878 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:100 pts:102400 pts_time:2.322 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:101 pts:103424 pts_time:2.34522 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:102 pts:104448 pts_time:2.36844 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:103 pts:105472 pts_time:2.39166 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:104 pts:106496 pts_time:2.41488 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:105 pts:107520 pts_time:2.4381 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:106 pts:108544 pts_time:2.46132 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:107 pts:109568 pts_time:2.48454 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:108 pts:110592 pts_time:2.50776 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:109 pts:111616 pts_time:2.53098 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:110 pts:112640 pts_time:2.5542 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:111 pts:113664 pts_time:2.57741 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:112 pts:114688 pts_time:2.60063 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:113 pts:115712 pts_time:2.62385 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:114 pts:116736 pts_time:2.64707 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:115 pts:117760 pts_time:2.67029 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:116 pts:118784 pts_time:2.69351 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:117 pts:119808 pts_time:2.71673 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:118 pts:120832 pts_time:2.73995 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:119 pts:121856 pts_time:2.76317 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:120 pts:122880 pts_time:2.78639 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:121 pts:123904 pts_time:2.80961 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:122 pts:124928 pts_time:2.83283 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:123 pts:125952 pts_time:2.85605 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:124 pts:126976 pts_time:2.87927 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:125 pts:128000 pts_time:2.90249 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:126 pts:129024 pts_time:2.92571 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:127 pts:130048 pts_time:2.94893 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:128 pts:131072 pts_time:2.97215 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:129 pts:132096 pts_time:2.99537 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:130 pts:133120 pts_time:3.01859 > > +TestKey1= > > +frame:131 pts:134144 pts_time:3.04181 > > +TestKey1= > > +frame:132 pts:135168 pts_time:3.06503 > > +TestKey1= > > +frame:133 pts:136192 pts_time:3.08825 > > +TestKey1= > > +frame:134 pts:137216 pts_time:3.11147 > > +TestKey1= > > +frame:135 pts:138240 pts_time:3.13469 > > +TestKey1= > > +frame:136 pts:139264 pts_time:3.15791 > > +TestKey1= > > +frame:137 pts:140288 pts_time:3.18113 > > +TestKey1= > > +frame:138 pts:141312 pts_time:3.20435 > > +TestKey1= > > +frame:139 pts:142336 pts_time:3.22757 > > +TestKey1= > > +frame:140 pts:143360 pts_time:3.25079 > > +TestKey1= > > +frame:141 pts:144384 pts_time:3.27401 > > +TestKey1= > > +frame:142 pts:145408 pts_time:3.29723 > > +TestKey1= > > +frame:143 pts:146432 pts_time:3.32045 > > +TestKey1= > > +frame:144 pts:147456 pts_time:3.34367 > > +TestKey1= > > +frame:145 pts:148480 pts_time:3.36689 > > +TestKey1= > > +frame:146 pts:149504 pts_time:3.39011 > > +TestKey1= > > +frame:147 pts:150528 pts_time:3.41333 > > +TestKey1= > > +frame:148 pts:151552 pts_time:3.43655 > > +TestKey1= > > +frame:149 pts:152576 pts_time:3.45977 > > +TestKey1= > > +frame:150 pts:153600 pts_time:3.48299 > > +TestKey1= > > +frame:151 pts:154624 pts_time:3.50621 > > +TestKey1= > > +frame:152 pts:155648 pts_time:3.52943 > > +TestKey1= > > +frame:153 pts:156672 pts_time:3.55265 > > +TestKey1= > > +frame:154 pts:157696 pts_time:3.57587 > > +TestKey1= > > +frame:155 pts:158720 pts_time:3.59909 > > +TestKey1= > > +frame:156 pts:159744 pts_time:3.62231 > > +TestKey1= > > +frame:157 pts:160768 pts_time:3.64553 > > +TestKey1= > > +frame:158 pts:161792 pts_time:3.66875 > > +TestKey1= > > +frame:159 pts:162816 pts_time:3.69197 > > +TestKey1= > > +frame:160 pts:163840 pts_time:3.71519 > > +TestKey1= > > +frame:161 pts:164864 pts_time:3.73841 > > +TestKey1= > > +frame:162 pts:165888 pts_time:3.76163 > > +TestKey1= > > +frame:163 pts:166912 pts_time:3.78485 > > +TestKey1= > > +frame:164 pts:167936 pts_time:3.80807 > > +TestKey1= > > +frame:165 pts:168960 pts_time:3.83129 > > +TestKey1= > > +frame:166 pts:169984 pts_time:3.85451 > > +TestKey1= > > +frame:167 pts:171008 pts_time:3.87773 > > +TestKey1= > > +frame:168 pts:172032 pts_time:3.90095 > > +TestKey1= > > +frame:169 pts:173056 pts_time:3.92417 > > +TestKey1= > > +frame:170 pts:174080 pts_time:3.94739 > > +TestKey1= > > +frame:171 pts:175104 pts_time:3.97061 > > +TestKey1= > > +frame:172 pts:176128 pts_time:3.99383 > > +TestKey1= > > +frame:173 pts:177152 pts_time:4.01705 > > +TestKey1=DDDDD EEEEE > > +frame:174 pts:178176 pts_time:4.04027 > > +TestKey1=DDDDD EEEEE > > +frame:175 pts:179200 pts_time:4.06349 > > +TestKey1=DDDDD EEEEE > > +frame:176 pts:180224 pts_time:4.08671 > > +TestKey1=DDDDD EEEEE > > +frame:177 pts:181248 pts_time:4.10993 > > +TestKey1=DDDDD EEEEE > > +frame:178 pts:182272 pts_time:4.13315 > > +TestKey1=DDDDD EEEEE > > +frame:179 pts:183296 pts_time:4.15637 > > +TestKey1=DDDDD EEEEE > > +frame:180 pts:184320 pts_time:4.17959 > > +TestKey1=DDDDD EEEEE > > +frame:181 pts:185344 pts_time:4.20281 > > +TestKey1=DDDDD EEEEE > > +frame:182 pts:186368 pts_time:4.22603 > > +TestKey1=DDDDD EEEEE > > +frame:183 pts:187392 pts_time:4.24925 > > +TestKey1=DDDDD EEEEE > > +frame:184 pts:188416 pts_time:4.27247 > > +TestKey1=DDDDD EEEEE > > +frame:185 pts:189440 pts_time:4.29569 > > +TestKey1=DDDDD EEEEE > > +frame:186 pts:190464 pts_time:4.31891 > > +TestKey1=DDDDD EEEEE > > +frame:187 pts:191488 pts_time:4.34213 > > +TestKey1=DDDDD EEEEE > > +frame:188 pts:192512 pts_time:4.36535 > > +TestKey1=DDDDD EEEEE > > +frame:189 pts:193536 pts_time:4.38857 > > +TestKey1=DDDDD EEEEE > > +frame:190 pts:194560 pts_time:4.41179 > > +TestKey1=DDDDD EEEEE > > +frame:191 pts:195584 pts_time:4.43501 > > +TestKey1=DDDDD EEEEE > > +frame:192 pts:196608 pts_time:4.45823 > > +TestKey1=DDDDD EEEEE > > +frame:193 pts:197632 pts_time:4.48145 > > +TestKey1=DDDDD EEEEE > > +frame:194 pts:198656 pts_time:4.50467 > > +TestKey1=DDDDD EEEEE > > +frame:195 pts:199680 pts_time:4.52789 > > +TestKey1=DDDDD EEEEE > > +frame:196 pts:200704 pts_time:4.55111 > > +TestKey1=DDDDD EEEEE > > +frame:197 pts:201728 pts_time:4.57433 > > +TestKey1=DDDDD EEEEE > > +frame:198 pts:202752 pts_time:4.59755 > > +TestKey1=DDDDD EEEEE > > +frame:199 pts:203776 pts_time:4.62077 > > +TestKey1=DDDDD EEEEE > > +frame:200 pts:204800 pts_time:4.64399 > > +TestKey1=DDDDD EEEEE > > +frame:201 pts:205824 pts_time:4.66721 > > +TestKey1=DDDDD EEEEE > > +frame:202 pts:206848 pts_time:4.69043 > > +TestKey1=DDDDD EEEEE > > +frame:203 pts:207872 pts_time:4.71365 > > +TestKey1=DDDDD EEEEE > > +frame:204 pts:208896 pts_time:4.73687 > > +TestKey1=DDDDD EEEEE > > +frame:205 pts:209920 pts_time:4.76009 > > +TestKey1=DDDDD EEEEE > > +frame:206 pts:210944 pts_time:4.78331 > > +TestKey1=DDDDD EEEEE > > +frame:207 pts:211968 pts_time:4.80653 > > +TestKey1=DDDDD EEEEE > > +frame:208 pts:212992 pts_time:4.82975 > > +TestKey1=DDDDD EEEEE > > +frame:209 pts:214016 pts_time:4.85297 > > +TestKey1=DDDDD EEEEE > > +frame:210 pts:215040 pts_time:4.87619 > > +TestKey1=DDDDD EEEEE > > +frame:211 pts:216064 pts_time:4.89941 > > +TestKey1=DDDDD EEEEE > > +frame:212 pts:217088 pts_time:4.92263 > > +TestKey1=DDDDD EEEEE > > +frame:213 pts:218112 pts_time:4.94585 > > +TestKey1=DDDDD EEEEE > > +frame:214 pts:219136 pts_time:4.96907 > > +TestKey1=DDDDD EEEEE > > +frame:215 pts:220160 pts_time:4.99229 > > +TestKey1=DDDDD EEEEE > > +frame:216 pts:221184 pts_time:5.01551 > > +TestKey1=DDDDD EEEEE > > +frame:217 pts:222208 pts_time:5.03873 > > +TestKey1=DDDDD EEEEE > > +frame:218 pts:223232 pts_time:5.06195 > > +TestKey1=DDDDD EEEEE > > +frame:219 pts:224256 pts_time:5.08517 > > +TestKey1=DDDDD EEEEE > > +frame:220 pts:225280 pts_time:5.10839 > > +TestKey1=DDDDD EEEEE > > +frame:221 pts:226304 pts_time:5.13161 > > +TestKey1=DDDDD EEEEE > > +frame:222 pts:227328 pts_time:5.15483 > > +TestKey1=DDDDD EEEEE > > +frame:223 pts:228352 pts_time:5.17805 > > +TestKey1=DDDDD EEEEE > > +frame:224 pts:229376 pts_time:5.20127 > > +TestKey1=DDDDD EEEEE > > +frame:225 pts:230400 pts_time:5.22449 > > +TestKey1=DDDDD EEEEE > > +frame:226 pts:231424 pts_time:5.24771 > > +TestKey1=DDDDD EEEEE > > +frame:227 pts:232448 pts_time:5.27093 > > +TestKey1=DDDDD EEEEE > > +frame:228 pts:233472 pts_time:5.29415 > > +TestKey1=DDDDD EEEEE > > +frame:229 pts:234496 pts_time:5.31737 > > +TestKey1=DDDDD EEEEE > > +frame:230 pts:235520 pts_time:5.34059 > > +TestKey1=DDDDD EEEEE > > +frame:231 pts:236544 pts_time:5.36381 > > +TestKey1=DDDDD EEEEE > > +frame:232 pts:237568 pts_time:5.38703 > > +TestKey1=DDDDD EEEEE > > +frame:233 pts:238592 pts_time:5.41025 > > +TestKey1=DDDDD EEEEE > > +frame:234 pts:239616 pts_time:5.43347 > > +TestKey1=DDDDD EEEEE > > +frame:235 pts:240640 pts_time:5.45669 > > +TestKey1=DDDDD EEEEE > > +frame:236 pts:241664 pts_time:5.47991 > > +TestKey1=DDDDD EEEEE > > +frame:237 pts:242688 pts_time:5.50313 > > +TestKey1=DDDDD EEEEE > > +frame:238 pts:243712 pts_time:5.52635 > > +TestKey1=DDDDD EEEEE > > +frame:239 pts:244736 pts_time:5.54957 > > +TestKey1=DDDDD EEEEE > > +frame:240 pts:245760 pts_time:5.57279 > > +TestKey1=DDDDD EEEEE > > +frame:241 pts:246784 pts_time:5.59601 > > +TestKey1=DDDDD EEEEE > > +frame:242 pts:247808 pts_time:5.61923 > > +TestKey1=DDDDD EEEEE > > +frame:243 pts:248832 pts_time:5.64245 > > +TestKey1=DDDDD EEEEE > > +frame:244 pts:249856 pts_time:5.66567 > > +TestKey1=DDDDD EEEEE > > +frame:245 pts:250880 pts_time:5.68889 > > +TestKey1=DDDDD EEEEE > > +frame:246 pts:251904 pts_time:5.71211 > > +TestKey1=DDDDD EEEEE > > +frame:247 pts:252928 pts_time:5.73533 > > +TestKey1=DDDDD EEEEE > > +frame:248 pts:253952 pts_time:5.75855 > > +TestKey1=DDDDD EEEEE > > +frame:249 pts:254976 pts_time:5.78177 > > +TestKey1=DDDDD EEEEE > > +frame:250 pts:256000 pts_time:5.80499 > > +TestKey1=DDDDD EEEEE > > +frame:251 pts:257024 pts_time:5.82821 > > +TestKey1=DDDDD EEEEE > > +frame:252 pts:258048 pts_time:5.85143 > > +TestKey1=DDDDD EEEEE > > +frame:253 pts:259072 pts_time:5.87465 > > +TestKey1=DDDDD EEEEE > > +frame:254 pts:260096 pts_time:5.89787 > > +TestKey1=DDDDD EEEEE > > +frame:255 pts:261120 pts_time:5.92109 > > +TestKey1=DDDDD EEEEE > > +frame:256 pts:262144 pts_time:5.94431 > > +TestKey1=DDDDD EEEEE > > +frame:257 pts:263168 pts_time:5.96753 > > +TestKey1=DDDDD EEEEE > > +frame:258 pts:264192 pts_time:5.99075 > > +TestKey1=DDDDD EEEEE > > diff --git a/tests/ref/fate/filter-metadatareader > b/tests/ref/fate/filter-metadatareader > > new file mode 100644 > > index 0000000000..f9301960d5 > > --- /dev/null > > +++ b/tests/ref/fate/filter-metadatareader > > @@ -0,0 +1,14 @@ > > +frame:0 pts:0 pts_time:0 > > +TestKey1=AAAAA > > +frame:1 pts:1 pts_time:1 > > +TestKey1=BBBBB > > +TestKey2=bbbbb > > +frame:2 pts:2 pts_time:2 > > +TestKey1=CCCCC > > +TestKey3=Multi > > +Line > > +Value > > +frame:3 pts:3 pts_time:3 > > +TestKey1= > > +frame:4 pts:4 pts_time:4 > > +TestKey1=DDDDD EEEEE > > Regards, > > -- > Nicolas George > _______________________________________________ > 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". > _______________________________________________ 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".