top_builddir = @top_builddir@
with_demo_app = @with_demo_app@
with_SDL2 = @with_SDL2@
+with_benchmark = @with_benchmark@
with_coverage = @with_coverage@
CC=@CC@
CXX=@CXX@
-CXXFLAGS=-Wall @CXXFLAGS@ -fvisibility-inlines-hidden -I$(GTEST_DIR)/include @SDL2_CFLAGS@ @SDL_CFLAGS@ @Eigen3_CFLAGS@ @epoxy_CFLAGS@ @FFTW3_CFLAGS@
+CXXFLAGS=-Wall @CXXFLAGS@ -fvisibility-inlines-hidden -I$(GTEST_DIR)/include @SDL2_CFLAGS@ @SDL_CFLAGS@ @Eigen3_CFLAGS@ @epoxy_CFLAGS@ @FFTW3_CFLAGS@ @benchmark_CFLAGS@
ifeq ($(with_SDL2),yes)
CXXFLAGS += -DHAVE_SDL2
endif
+ifeq ($(with_benchmark),yes)
+CXXFLAGS += -DHAVE_BENCHMARK
+endif
LDFLAGS=@LDFLAGS@
LDLIBS=@epoxy_LIBS@ @FFTW3_LIBS@ -lpthread
-TEST_LDLIBS=@epoxy_LIBS@ @SDL2_LIBS@ @SDL_LIBS@ -lpthread
+TEST_LDLIBS=@epoxy_LIBS@ @SDL2_LIBS@ @SDL_LIBS@ @benchmark_LIBS@ -lpthread
DEMO_LDLIBS=@SDL2_image_LIBS@ @SDL_image_LIBS@ -lrt -lpthread @libpng_LIBS@ @FFTW3_LIBS@
SHELL=@SHELL@
LIBTOOL=@LIBTOOL@ --tag=CXX
OK, you need
-* A C++98 compiler. GCC will do. (I haven't tried Windows, but it
+* A C++11 compiler. GCC will do. (I haven't tried Windows, but it
works fine on Linux and OS X, and Movit is not very POSIX-bound.)
* GNU Make.
* A GPU capable of running OpenGL 3.0 or newer. GLES3 (for mobile devices)
will also work.
* The [Eigen 3], [FFTW3] and [Google Test] libraries. (The library itself
does not depend on the latter, but you probably want to run the unit tests.)
+ If you also have the Google microbenchmark library, you can get some
+ benchmarks as well.
* The [epoxy] library, for dealing with OpenGL extensions on various
platforms.
LT_INIT
PKG_PROG_PKG_CONFIG
+CXXFLAGS="$CXXFLAGS -std=gnu++11"
+
AC_CONFIG_SRCDIR(effect.cpp)
AC_CONFIG_AUX_DIR(.)
fi
PKG_CHECK_MODULES([libpng], [libpng], [], [with_demo_app=no; AC_MSG_WARN([libpng not found, demo program will not be built])])
+# This is only needed for microbenchmarks, so optional.
+PKG_CHECK_MODULES([benchmark], [benchmark], [with_benchmark=yes], [with_benchmark=no; AC_MSG_WARN([Google microbenchmark framework not found, microbenchmarks will not be built])])
+
AC_SUBST([with_demo_app])
+AC_SUBST([with_benchmark])
AC_SUBST([with_SDL2])
with_coverage=no
// Unit tests for DeinterlaceEffect.
+#ifdef HAVE_BENCHMARK
+#include <benchmark/benchmark.h>
+#endif
#include <epoxy/gl.h>
#include <algorithm>
}
}
+#ifdef HAVE_BENCHMARK
+void BM_DeinterlaceEffect_Gray(benchmark::State &state)
+{
+ unsigned width = state.range(0), height = state.range(1);
+ unsigned field_height = height / 2;
+
+ float *field1 = new float[width * field_height];
+ float *field2 = new float[width * field_height];
+ float *field3 = new float[width * field_height];
+ float *field4 = new float[width * field_height];
+ float *field5 = new float[width * field_height];
+ float *out_data = new float[width * height];
+
+ for (unsigned i = 0; i < width * field_height; ++i) {
+ field1[i] = rand();
+ field2[i] = rand();
+ field3[i] = rand();
+ field4[i] = rand();
+ field5[i] = rand();
+ }
+
+ EffectChainTester tester(NULL, width, height);
+ Effect *input1 = tester.add_input(field1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+ Effect *input2 = tester.add_input(field2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+ Effect *input3 = tester.add_input(field3, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+ Effect *input4 = tester.add_input(field4, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+ Effect *input5 = tester.add_input(field5, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+ Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), input1, input2, input3, input4, input5);
+
+ ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
+
+ tester.benchmark(state, out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+ delete[] field1;
+ delete[] field2;
+ delete[] field3;
+ delete[] field4;
+ delete[] field5;
+ delete[] out_data;
+}
+BENCHMARK(BM_DeinterlaceEffect_Gray)->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+#endif
+
} // namespace movit
#include <SDL/SDL_error.h>
#include <SDL/SDL_video.h>
#endif
+#ifdef HAVE_BENCHMARK
+#include <benchmark/benchmark.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
SDL_WM_SetCaption("OpenGL window for unit test", NULL);
#endif
- testing::InitGoogleTest(&argc, argv);
- int err = RUN_ALL_TESTS();
+ int err;
+ if (argc >= 2 && strcmp(argv[1], "--benchmark") == 0) {
+#ifdef HAVE_BENCHMARK
+ --argc;
+ ::benchmark::Initialize(&argc, argv + 1);
+ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+ ::benchmark::RunSpecifiedBenchmarks();
+ err = 0;
+#else
+ fprintf(stderr, "No support for microbenchmarks compiled in.\n");
+ err = 1;
+#endif
+ } else {
+ testing::InitGoogleTest(&argc, argv);
+ err = RUN_ALL_TESTS();
+ }
SDL_Quit();
- exit(err);
+ return err;
}
internal_run<uint32_t>(out_data, NULL, NULL, NULL, GL_UNSIGNED_INT_2_10_10_10_REV, format, color_space, gamma_curve, alpha_format);
}
+#ifdef HAVE_BENCHMARK
+
+void EffectChainTester::benchmark(benchmark::State &state, float *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<float>(out_data, NULL, NULL, NULL, GL_FLOAT, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, float *out_data, float *out_data2, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<float>(out_data, out_data2, NULL, NULL, GL_FLOAT, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, float *out_data, float *out_data2, float *out_data3, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<float>(out_data, out_data2, out_data3, NULL, GL_FLOAT, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, float *out_data, float *out_data2, float *out_data3, float *out_data4, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run(out_data, out_data2, out_data3, out_data4, GL_FLOAT, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, unsigned char *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<unsigned char>(out_data, NULL, NULL, NULL, GL_UNSIGNED_BYTE, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, unsigned char *out_data, unsigned char *out_data2, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<unsigned char>(out_data, out_data2, NULL, NULL, GL_UNSIGNED_BYTE, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, unsigned char *out_data, unsigned char *out_data2, unsigned char *out_data3, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<unsigned char>(out_data, out_data2, out_data3, NULL, GL_UNSIGNED_BYTE, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, unsigned char *out_data, unsigned char *out_data2, unsigned char *out_data3, unsigned char *out_data4, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run(out_data, out_data2, out_data3, out_data4, GL_UNSIGNED_BYTE, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark(benchmark::State &state, uint16_t *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<uint16_t>(out_data, NULL, NULL, NULL, GL_UNSIGNED_SHORT, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+void EffectChainTester::benchmark_10_10_10_2(benchmark::State &state, uint32_t *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+{
+ internal_run<uint32_t>(out_data, NULL, NULL, NULL, GL_UNSIGNED_INT_2_10_10_10_REV, format, color_space, gamma_curve, alpha_format, &state);
+}
+
+#endif
+
template<class T>
-void EffectChainTester::internal_run(T *out_data, T *out_data2, T *out_data3, T *out_data4, GLenum internal_format, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format)
+void EffectChainTester::internal_run(T *out_data, T *out_data2, T *out_data3, T *out_data4, GLenum internal_format, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format
+#ifdef HAVE_BENCHMARK
+, benchmark::State *benchmark_state
+#endif
+)
{
if (!finalized) {
finalize_chain(color_space, gamma_curve, alpha_format);
chain.render_to_fbo(fbo, width, height);
+#ifdef HAVE_BENCHMARK
+ // If running benchmarks: Now we've warmed up everything, so let's run the
+ // actual benchmark loop.
+ if (benchmark_state != nullptr) {
+ glFinish();
+ size_t iters = benchmark_state->max_iterations;
+ for (auto _ : *benchmark_state) {
+ chain.render_to_fbo(fbo, width, height);
+ if (--iters == 0) {
+ glFinish();
+ }
+ }
+ benchmark_state->SetItemsProcessed(benchmark_state->iterations() * width * height);
+ }
+#endif
+
T *data[4] = { out_data, out_data2, out_data3, out_data4 };
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
#define _MOVIT_TEST_UTIL_H 1
#include <epoxy/gl.h>
+#ifdef HAVE_BENCHMARK
+#include <benchmark/benchmark.h>
+#endif
#include "effect_chain.h"
#include "image_format.h"
EffectChain *get_chain() { return &chain; }
Input *add_input(const float *data, MovitPixelFormat pixel_format, Colorspace color_space, GammaCurve gamma_curve, int input_width = -1, int input_height = -1);
Input *add_input(const unsigned char *data, MovitPixelFormat pixel_format, Colorspace color_space, GammaCurve gamma_curve, int input_width = -1, int input_height = -1);
+
void run(float *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
void run(float *out_data, float *out_data2, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
void run(float *out_data, float *out_data2, float *out_data3, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
void run(unsigned char *out_data, unsigned char *out_data2, unsigned char *out_data3, unsigned char *out_data4, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
void run(uint16_t *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
void run_10_10_10_2(uint32_t *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+
+#ifdef HAVE_BENCHMARK
+ void benchmark(benchmark::State &state, float *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, float *out_data, float *out_data2, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, float *out_data, float *out_data2, float *out_data3, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, float *out_data, float *out_data2, float *out_data3, float *out_data4, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, unsigned char *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, unsigned char *out_data, unsigned char *out_data2, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, unsigned char *out_data, unsigned char *out_data2, unsigned char *out_data3, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, unsigned char *out_data, unsigned char *out_data2, unsigned char *out_data3, unsigned char *out_data4, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark(benchmark::State &state, uint16_t *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void benchmark_10_10_10_2(benchmark::State &state, uint32_t *out_data, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+#endif
+
void add_output(const ImageFormat &format, OutputAlphaFormat alpha_format);
void add_ycbcr_output(const ImageFormat &format, OutputAlphaFormat alpha_format, const YCbCrFormat &ycbcr_format, YCbCrOutputSplitting output_splitting = YCBCR_OUTPUT_INTERLEAVED, GLenum output_type = GL_UNSIGNED_BYTE);
void finalize_chain(Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format);
template<class T>
- void internal_run(T *out_data, T *out_data2, T *out_data3, T *out_data4, GLenum internal_format, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+ void internal_run(T *out_data, T *out_data2, T *out_data3, T *out_data4, GLenum internal_format, GLenum format, Colorspace color_space, GammaCurve gamma_curve, OutputAlphaFormat alpha_format = OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED
+#ifdef HAVE_BENCHMARK
+ , benchmark::State *state = NULL
+#endif
+);
EffectChain chain;
unsigned width, height;
// changes, even within git versions. There is no specific version
// documentation outside the regular changelogs, though.
-#define MOVIT_VERSION 32
+#define MOVIT_VERSION 33
#endif // !defined(_MOVIT_VERSION_H)