@@ -626,7 +626,8 @@ SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h
SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h
-TOOLS = graph2dot
+TOOLS = graph2dot \
+ spherical_compare
TESTPROGS = drawutils filtfmts formats integral
TESTPROGS-$(CONFIG_DNN) += dnn-layer-avgpool dnn-layer-conv2d dnn-layer-dense \
dnn-layer-depth2space dnn-layer-mathbinary \
@@ -259,7 +259,8 @@ FATE_EXTERN-$(CONFIG_FFMPEG) += $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG)
FATE_EXTERN-$(CONFIG_FFPROBE) += $(FATE_SAMPLES_FFPROBE)
FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_SAMPLES_FFMPEG_FFPROBE-yes)
FATE_EXTERN-$(call ALLYES, FFMPEG FFPROBE) += $(FATE_SAMPLES_FFMPEG_FFPROBE)
-FATE_EXTERN += $(FATE_EXTERN-yes) $(FATE_SAMPLES_FASTSTART)
+FATE_EXTERN += $(FATE_EXTERN-yes) $(FATE_SAMPLES_FASTSTART) \
+ $(FATE_SAMPLES_SPHERICAL_COMPARE)
FATE += $(FATE-yes)
@@ -273,6 +274,7 @@ $(FATE_FFPROBE) $(FATE_FFMPEG_FFPROBE) $(FATE_SAMPLES_FFPROBE) $(FATE_SAMPLES_FF
$(FATE_SAMPLES_FASTSTART): tools/qt-faststart$(EXESUF)
$(FATE_SAMPLES_DUMP_DATA) $(FATE_SAMPLES_DUMP_DATA-yes): tools/venc_data_dump$(EXESUF)
$(FATE_SAMPLES_SCALE_SLICE): tools/scale_slice_test$(EXESUF)
+$(FATE_SAMPLES_SPHERICAL_COMPARE): tools/spherical_compare$(EXESUF)
ifdef SAMPLES
FATE += $(FATE_EXTERN)
@@ -572,6 +572,12 @@ venc_data(){
run tools/venc_data_dump${EXECSUF} ${file} ${stream} ${frames} ${threads} ${thread_type}
}
+spherical_compare(){
+ file=$1
+ filterchain=$2
+ run tools/spherical_compare${EXECSUF} ${file} ${filterchain}
+}
+
null(){
:
}
@@ -698,6 +698,25 @@ fate-filter-refcmp-blockdetect-yuv: CMD = cmp_metadata blockdetect yuv420p 0.015
FATE_FILTER_CMP_METADATA-$(CONFIG_BLURDETECT_FILTER) += fate-filter-refcmp-blurdetect-yuv
fate-filter-refcmp-blurdetect-yuv: CMD = cmp_metadata blurdetect yuv420p 0.015
+SPHERICAL_DEPS = MATROSKA_DEMUXER VP8_DECODER V360_FILTER SSIM360_FILTER
+SPHERICAL_SAMPLE = $(TARGET_SAMPLES)/spherical/Worlds_First_Live_360_Rocket_Launch-_Orbital_ATK_CRS-7_cut.mkv
+
+FATE_FILTER_SPHERICAL += fate-filter-spherical-c3x2
+fate-filter-spherical-c3x2: CMD = spherical_compare $(SPHERICAL_SAMPLE) \
+ "split[in][ref];[in]v360=input=e:output=c3x2[main];[main][ref]ssim360=main_projection=c3x2:ref_projection=e"
+
+FATE_FILTER_SPHERICAL += fate-filter-spherical-barrel
+fate-filter-spherical-barrel: CMD = spherical_compare $(SPHERICAL_SAMPLE) \
+ "split[in][ref];[in]v360=input=e:output=barrel[main];[main][ref]ssim360=main_projection=barrel:ref_projection=e"
+
+FATE_SAMPLES_SPHERICAL_COMPARE-$(call ALLYES, $(SPHERICAL_DEPS)) += $(FATE_FILTER_SPHERICAL)
+FATE_SAMPLES_SPHERICAL_COMPARE += $(FATE_SAMPLES_SPHERICAL_COMPARE-yes)
+
+$(FATE_SAMPLES_SPHERICAL_COMPARE): CMP = oneoff
+$(FATE_SAMPLES_SPHERICAL_COMPARE): CMP_UNIT = f32
+
+fate-filter-spherical: $(FATE_SAMPLES_SPHERICAL_COMPARE)
+
FATE_FILTER_CMP_METADATA-$(CONFIG_SITI_FILTER) += fate-filter-refcmp-siti-yuv
fate-filter-refcmp-siti-yuv: CMD = cmp_metadata siti yuv420p 0.015
new file mode 100644
GIT binary patch
literal 160
zcmZ2dP;1Y?&;ZBstrs1apo!UXVTuLqxPYOq&=ylnzV$qYx^?cDVu!z;!%!E~f6fsA
Dpn5ON
literal 0
HcmV?d00001
@@ -19,6 +19,7 @@ tools/target_io_dem_fuzzer.o: tools/target_dem_fuzzer.c
tools/venc_data_dump$(EXESUF): tools/decode_simple.o
tools/scale_slice_test$(EXESUF): tools/decode_simple.o
+tools/spherical_compare$(EXESUF): tools/decode_simple.o
tools/decode_simple.o: | tools
new file mode 100644
@@ -0,0 +1,176 @@
+/*
+ * 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
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "decode_simple.h"
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/common.h"
+#include "libavutil/dict.h"
+#include "libavutil/error.h"
+#include "libavutil/pixdesc.h"
+
+#include "libavformat/avformat.h"
+
+#include "libavcodec/avcodec.h"
+
+#include "libavfilter/avfilter.h"
+#include "libavfilter/buffersink.h"
+#include "libavfilter/buffersrc.h"
+
+typedef struct PrivData {
+ const char *filterchain;
+ AVFilterGraph *fg;
+ AVFilterContext *src;
+ AVFilterContext *sink;
+ AVFrame *frame;
+
+ uint64_t nb_frames;
+} PrivData;
+
+static int process_frame(DecodeContext *dc, AVFrame *frame)
+{
+ PrivData *pd = dc->opaque;
+ int ret;
+
+ if (!pd->fg) {
+ AVFilterInOut *inputs, *outputs;
+ char filterchain[1024];
+
+ if (!frame)
+ return 0;
+
+ snprintf(filterchain, sizeof(filterchain),
+ "buffer@src=width=%d:height=%d:pix_fmt=%s:time_base=%d/%d,"
+ "%s,buffersink@sink",
+ frame->width, frame->height,
+ av_get_pix_fmt_name(frame->format),
+ dc->stream->time_base.num, dc->stream->time_base.den,
+ pd->filterchain);
+
+ pd->fg = avfilter_graph_alloc();
+ if (!pd->fg)
+ return AVERROR(ENOMEM);
+
+ ret = avfilter_graph_parse2(pd->fg, filterchain, &inputs, &outputs);
+ if (ret < 0)
+ return ret;
+
+ av_assert0(!inputs && !outputs);
+
+ pd->src = avfilter_graph_get_filter(pd->fg, "buffer@src");
+ pd->sink = avfilter_graph_get_filter(pd->fg, "buffersink@sink");
+ av_assert0(pd->src && pd->sink);
+
+ ret = avfilter_graph_config(pd->fg, pd->fg);
+ if (ret < 0)
+ return ret;
+
+ pd->frame = av_frame_alloc();
+ if (!pd->frame)
+ return AVERROR(ENOMEM);
+ }
+
+ ret = av_buffersrc_write_frame(pd->src, frame);
+ if (ret < 0)
+ return ret;
+
+ while (ret >= 0) {
+ static const char *keys[] = {
+ "lavfi.ssim360.Y",
+ "lavfi.ssim360.U",
+ "lavfi.ssim360.V",
+ "lavfi.ssim360.All",
+ "lavfi.ssim360.dB",
+ };
+
+ av_frame_unref(pd->frame);
+ ret = av_buffersink_get_frame(pd->sink, pd->frame);
+ if ((frame && ret == AVERROR(EAGAIN)) ||
+ (!frame && ret == AVERROR_EOF))
+ return 0;
+ else if (ret < 0)
+ return ret;
+
+ fprintf(stderr, "frame %"PRIu64"\n", pd->nb_frames);
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(keys); i++) {
+ const AVDictionaryEntry *t = av_dict_get(pd->frame->metadata, keys[i], NULL, 0);
+ float val;
+ size_t written;
+
+ if (!t) {
+ fprintf(stderr, "Metadata key '%s' not present in frame %"PRIu64"\n",
+ keys[i], pd->nb_frames);
+ return AVERROR(EINVAL);
+ }
+ fprintf(stderr, "%s=%s\n", t->key, t->value);
+
+ val = strtof(t->value, NULL);
+
+ written = fwrite(&val, sizeof(val), 1, stdout);
+ if (written != 1) {
+ fprintf(stderr, "Error writing to stdout\n");
+ return AVERROR(EIO);
+ }
+ }
+
+ pd->nb_frames++;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ PrivData pd;
+ DecodeContext dc;
+
+ const char *filename, *fc;
+ int ret = 0;
+
+ if (argc <= 2) {
+ fprintf(stderr, "Usage: %s <input file> <filterchain>\n", argv[0]);
+ return 0;
+ }
+
+ filename = argv[1];
+ fc = argv[2];
+
+ memset(&pd, 0, sizeof(pd));
+ pd.filterchain = fc;
+
+ ret = ds_open(&dc, filename, 0);
+ if (ret < 0)
+ goto finish;
+
+ dc.process_frame = process_frame;
+ dc.opaque = &pd;
+
+ ret = ds_run(&dc);
+
+finish:
+ avfilter_graph_free(&pd.fg);
+ av_frame_free(&pd.frame);
+ ds_free(&dc);
+ return ret;
+}