[FFmpeg-devel] [PATCH v2] hwcontext: Add test for device creation and derivation
Xiang, Haihao
haihao.xiang at intel.com
Wed May 16 04:14:11 EEST 2018
On Tue, 2018-05-15 at 23:15 +0100, Mark Thompson wrote:
> This uses any devices it can find on the host system - on a system with no
> hardware device support or in builds with no support included it will do
> nothing and pass.
> ---
>
> It now comes under a new target "fate-hw", which is not run as part of "fate".
>
> I found the CMP option, so it no longer has a reference file. All output is
> therefore now on stderr.
>
> Thanks,
>
> - Mark
>
> (In terms of further tests under fate-hw, I'm intending to add a hwframes test
> which tries to make frames contexts and do upload/download. There should
> probably be something with frames context mapping too, but I'm unsure exactly
> what. I'd also like to have some tests for the complex header construction
> code in VAAPI encode, but how to actually run that needs a bit more thought.)
>
>
> libavutil/Makefile | 1 +
> libavutil/tests/.gitignore | 1 +
> libavutil/tests/hwdevice.c | 226
> +++++++++++++++++++++++++++++++++++++++++++++
> tests/Makefile | 5 +
> tests/fate/hw.mak | 6 ++
> 5 files changed, 239 insertions(+)
> create mode 100644 libavutil/tests/hwdevice.c
> create mode 100644 tests/fate/hw.mak
>
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 4fe470748c..d0632f16a6 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -206,6 +206,7 @@ TESTPROGS =
> adler32 \
> fifo \
> hash \
> hmac \
> + hwdevice \
> integer \
> imgutils \
> lfg \
> diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
> index 8ede070887..71f75a8ee9 100644
> --- a/libavutil/tests/.gitignore
> +++ b/libavutil/tests/.gitignore
> @@ -22,6 +22,7 @@
> /file
> /hash
> /hmac
> +/hwdevice
> /imgutils
> /lfg
> /lls
> diff --git a/libavutil/tests/hwdevice.c b/libavutil/tests/hwdevice.c
> new file mode 100644
> index 0000000000..7eb355c988
> --- /dev/null
> +++ b/libavutil/tests/hwdevice.c
> @@ -0,0 +1,226 @@
> +/*
> + * 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 "libavutil/hwcontext.h"
> +
> +static int test_derivation(AVBufferRef *src_ref, const char *src_name)
> +{
> + enum AVHWDeviceType derived_type;
> + const char *derived_name;
> + AVBufferRef *derived_ref = NULL, *back_ref = NULL;
> + AVHWDeviceContext *src_dev, *derived_dev;
> + int err;
> +
> + src_dev = (AVHWDeviceContext*)src_ref->data;
> +
> + derived_type = AV_HWDEVICE_TYPE_NONE;
> + while (1) {
> + derived_type = av_hwdevice_iterate_types(derived_type);
> + if (derived_type == AV_HWDEVICE_TYPE_NONE)
> + break;
> +
> + derived_name = av_hwdevice_get_type_name(derived_type);
> +
> + err = av_hwdevice_ctx_create_derived(&derived_ref, derived_type,
> + src_ref, 0);
> + if (err < 0) {
> + fprintf(stderr, "Unable to derive %s -> %s: %d.\n",
> + src_name, derived_name, err);
> + continue;
> + }
> +
> + derived_dev = (AVHWDeviceContext*)derived_ref->data;
> + if (derived_dev->type != derived_type) {
> + fprintf(stderr, "Device derived as type %d has type %d.\n",
> + derived_type, derived_dev->type);
> + goto fail;
> + }
> +
> + if (derived_type == src_dev->type) {
> + if (derived_dev != src_dev) {
> + fprintf(stderr, "Derivation of %s from itself succeeded "
> + "but did not return the same device.\n", src_name);
> + goto fail;
> + }
> + av_buffer_unref(&derived_ref);
> + continue;
> + }
> +
> + err = av_hwdevice_ctx_create_derived(&back_ref, src_dev->type,
> + derived_ref, 0);
> + if (err < 0) {
> + fprintf(stderr, "Derivation %s to %s succeeded, but derivation "
> + "back again failed: %d.\n",
> + src_name, derived_name, err);
> + goto fail;
> + }
> +
> + if (back_ref->data != src_ref->data) {
> + fprintf(stderr, "Derivation %s to %s succeeded, but derivation "
> + "back again did not return the original device.\n",
> + src_name, derived_name);
> + goto fail;
> + }
> +
> + fprintf(stderr, "Successfully tested derivation %s -> %s.\n",
> + src_name, derived_name);
> +
> + av_buffer_unref(&derived_ref);
> + av_buffer_unref(&back_ref);
> + }
> +
> + return 0;
> +
> +fail:
> + av_buffer_unref(&derived_ref);
> + av_buffer_unref(&back_ref);
> + return -1;
> +}
> +
> +static int test_device(enum AVHWDeviceType type, const char *name,
> + const char *device, AVDictionary *opts, int flags)
> +{
> + AVBufferRef *ref;
> + AVHWDeviceContext *dev;
> + int err;
> +
> + err = av_hwdevice_ctx_create(&ref, type, device, opts, flags);
> + if (err < 0) {
> + fprintf(stderr, "Failed to create %s device: %d.\n", name, err);
> + return 1;
> + }
> +
> + dev = (AVHWDeviceContext*)ref->data;
> + if (dev->type != type) {
> + fprintf(stderr, "Device created as type %d has type %d.\n",
> + type, dev->type);
> + av_buffer_unref(&ref);
> + return -1;
> + }
> +
> + fprintf(stderr, "Device type %s successfully created.\n", name);
> +
> + err = test_derivation(ref, name);
> +
> + av_buffer_unref(&ref);
> +
> + return err;
> +}
> +
> +static const struct {
> + enum AVHWDeviceType type;
> + const char *possible_devices[5];
> +} test_devices[] = {
> + { AV_HWDEVICE_TYPE_CUDA,
> + { "0", "1", "2" } },
> + { AV_HWDEVICE_TYPE_DRM,
> + { "/dev/dri/card0", "/dev/dri/card1",
> + "/dev/dri/renderD128", "/dev/dri/renderD129" } },
> + { AV_HWDEVICE_TYPE_DXVA2,
> + { "0", "1", "2" } },
> + { AV_HWDEVICE_TYPE_D3D11VA,
> + { "0", "1", "2" } },
> + { AV_HWDEVICE_TYPE_OPENCL,
> + { "0.0", "0.1", "1.0", "1.1" } },
> + { AV_HWDEVICE_TYPE_VAAPI,
> + { "/dev/dri/renderD128", "/dev/dri/renderD129", ":0" } },
> +};
> +
> +static int test_device_type(enum AVHWDeviceType type)
> +{
> + enum AVHWDeviceType check;
> + const char *name;
> + int i, j, found, err;
> +
> + name = av_hwdevice_get_type_name(type);
> + if (!name) {
> + fprintf(stderr, "No name available for device type %d.\n", type);
> + return -1;
> + }
> +
> + check = av_hwdevice_find_type_by_name(name);
> + if (check != type) {
> + fprintf(stderr, "Type %d maps to name %s maps to type %d.\n",
> + type, name, check);
> + return -1;
> + }
> +
> + found = 0;
> +
> + err = test_device(type, name, NULL, NULL, 0);
> + if (err < 0) {
> + fprintf(stderr, "Test failed for %s with default options.\n", name);
> + return -1;
> + }
> + if (err == 0) {
> + fprintf(stderr, "Test passed for %s with default options.\n", name);
> + ++found;
> + }
> +
> + for (i = 0; i < FF_ARRAY_ELEMS(test_devices); i++) {
> + if (test_devices[i].type != type)
> + continue;
> +
> + for (j = 0; test_devices[i].possible_devices[j]; j++) {
> + err = test_device(type, name,
> + test_devices[i].possible_devices[j],
> + NULL, 0);
> + if (err < 0) {
> + fprintf(stderr, "Test failed for %s with device %s.\n",
> + name, test_devices[i].possible_devices[j]);
> + return -1;
> + }
> + if (err == 0) {
> + fprintf(stderr, "Test passed for %s with device %s.\n",
> + name, test_devices[i].possible_devices[j]);
> + ++found;
> + }
> + }
> + }
> +
> + return !found;
> +}
> +
> +int main(void)
> +{
> + enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
> + int pass, fail, skip, err;
> +
> + pass = fail = skip = 0;
> + while (1) {
> + type = av_hwdevice_iterate_types(type);
> + if (type == AV_HWDEVICE_TYPE_NONE)
> + break;
> +
> + err = test_device_type(type);
> + if (err == 0)
> + ++pass;
> + else if (err < 0)
> + ++fail;
> + else
> + ++skip;
> + }
> +
> + fprintf(stderr, "Attempted to test %d device types: "
> + "%d passed, %d failed, %d skipped.\n",
> + pass + fail + skip, pass, fail, skip);
> +
> + return fail > 0;
> +}
> diff --git a/tests/Makefile b/tests/Makefile
> index 6074ac748e..98d7b6d608 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -131,6 +131,7 @@ include $(SRC_PATH)/tests/fate/gif.mak
> include $(SRC_PATH)/tests/fate/h264.mak
> include $(SRC_PATH)/tests/fate/hap.mak
> include $(SRC_PATH)/tests/fate/hevc.mak
> +include $(SRC_PATH)/tests/fate/hw.mak
> include $(SRC_PATH)/tests/fate/id3v2.mak
> include $(SRC_PATH)/tests/fate/image.mak
> include $(SRC_PATH)/tests/fate/indeo.mak
> @@ -215,6 +216,10 @@ $(addprefix fate-, $(IGNORE_TESTS)): REPORT=ignore
>
> fate:: $(FATE)
>
> +# Tests requiring hardware support are not included in a default fate run.
> +fate-hw: $(FATE_HW-yes)
> +FATE += $(FATE_HW-yes)
> +
> $(FATE) $(FATE_TESTS-no): export PROGSUF = $(PROGSSUF)
> $(FATE) $(FATE_TESTS-no): $(FATE_UTILS:%=tests/%$(HOSTEXESUF))
> @echo "TEST $(@:fate-%=%)"
> diff --git a/tests/fate/hw.mak b/tests/fate/hw.mak
> new file mode 100644
> index 0000000000..d606cdeab6
> --- /dev/null
> +++ b/tests/fate/hw.mak
> @@ -0,0 +1,6 @@
> +FATE_HWCONTEXT += fate-hwdevice
> +fate-hwdevice: libavutil/tests/hwdevice$(EXESUF)
> +fate-hwdevice: CMD = run libavutil/tests/hwdevice
> +fate-hwdevice: CMP = null
> +
> +FATE_HW-$(CONFIG_AVUTIL) += $(FATE_HWCONTEXT)
LGTM, thanks
More information about the ffmpeg-devel
mailing list