diff --git a/tests/Makefile.am b/tests/Makefile.am index fc258eed1a..afe894db88 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -57,25 +57,28 @@ TEST_LIBS += \ $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-wayland-@GST_MAJORMINOR@.la endif -test_codecs_source_c = \ +test_utils_dec_source_c = \ + decoder.c \ test-h264.c \ test-jpeg.c \ test-mpeg2.c \ test-mpeg4.c \ test-vc1.c \ $(NULL) -test_codecs_source_h = $(test_codecs_source_c:%.c=%.h) test-decode.h +test_utils_dec_source_h = $(test_utils_dec_source_c:%.c=%.h) test-decode.h -test_utils_source_c = image.c output.c $(test_codecs_source_c) -test_utils_source_h = image.h output.h $(test_codecs_source_h) +test_utils_source_c = image.c output.c +test_utils_source_h = image.h output.h -noinst_LTLIBRARIES = libutils.la +noinst_LTLIBRARIES = libutils.la libutils_dec.la libutils_la_SOURCES = $(test_utils_source_c) libutils_la_CFLAGS = $(TEST_CFLAGS) +libutils_dec_la_SOURCES = $(test_utils_dec_source_c) +libutils_dec_la_CFLAGS = $(TEST_CFLAGS) -test_decode_SOURCES = test-decode.c $(test_codecs_source_c) +test_decode_SOURCES = test-decode.c test_decode_CFLAGS = $(TEST_CFLAGS) -test_decode_LDADD = libutils.la $(TEST_LIBS) +test_decode_LDADD = libutils.la libutils_dec.la $(TEST_LIBS) test_display_SOURCES = test-display.c test_display_CFLAGS = $(TEST_CFLAGS) @@ -98,8 +101,9 @@ test_textures_CFLAGS = $(TEST_CFLAGS) test_textures_LDADD = libutils.la $(TEST_LIBS) EXTRA_DIST = \ - test-subpicture-data.h \ - $(test_utils_source_h) \ + test-subpicture-data.h \ + $(test_utils_dec_source_h) \ + $(test_utils_source_h) \ $(NULL) # Extra clean files so that maintainer-clean removes *everything* diff --git a/tests/decoder.c b/tests/decoder.c new file mode 100644 index 0000000000..17e2ad89cd --- /dev/null +++ b/tests/decoder.c @@ -0,0 +1,210 @@ +/* + * decoder.h - Decoder utilities for the tests + * + * Copyright (C) 2013 Intel Corporation + * + * This library 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. + * + * This library 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 this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include "decoder.h" +#include "test-jpeg.h" +#include "test-mpeg2.h" +#include "test-mpeg4.h" +#include "test-h264.h" +#include "test-vc1.h" + +typedef void (*GetVideoInfoFunc)(VideoDecodeInfo *info); + +typedef struct _CodecDefs CodecDefs; +struct _CodecDefs { + const gchar *codec_str; + GetVideoInfoFunc get_video_info; +}; + +static const CodecDefs g_codec_defs[] = { +#define INIT_FUNCS(CODEC) { #CODEC, CODEC##_get_video_info } + INIT_FUNCS(jpeg), + INIT_FUNCS(mpeg2), + INIT_FUNCS(mpeg4), + INIT_FUNCS(h264), + INIT_FUNCS(vc1), +#undef INIT_FUNCS + { NULL, } +}; + +static const CodecDefs * +find_codec_defs(const gchar *codec_str) +{ + const CodecDefs *c; + for (c = g_codec_defs; c->codec_str; c++) + if (strcmp(codec_str, c->codec_str) == 0) + return c; + return NULL; +} + +#define CODEC_DEFS_KEY "codec-defs" + +static inline const CodecDefs * +get_codec_defs(GstVaapiDecoder *decoder) +{ + return g_object_get_data(G_OBJECT(decoder), CODEC_DEFS_KEY); +} + +static inline void +set_codec_defs(GstVaapiDecoder *decoder, const CodecDefs *c) +{ + g_object_set_data(G_OBJECT(decoder), CODEC_DEFS_KEY, (gpointer)c); +} + +GstVaapiDecoder * +decoder_new(GstVaapiDisplay *display, const gchar *codec_name) +{ + GstVaapiDecoder *decoder; + const CodecDefs *codec; + GstCaps *caps; + VideoDecodeInfo info; + + if (!codec_name) + codec_name = "h264"; + + codec = find_codec_defs(codec_name); + if (!codec) { + GST_ERROR("failed to find %s codec data", codec_name); + return NULL; + } + + codec->get_video_info(&info); + caps = gst_vaapi_profile_get_caps(info.profile); + if (!caps) { + GST_ERROR("failed to create decoder caps"); + return NULL; + } + + if (info.width > 0 && info.height > 0) + gst_caps_set_simple(caps, + "width", G_TYPE_INT, info.width, + "height", G_TYPE_INT, info.height, + NULL); + + switch (gst_vaapi_profile_get_codec(info.profile)) { + case GST_VAAPI_CODEC_H264: + decoder = gst_vaapi_decoder_h264_new(display, caps); + break; +#if USE_JPEG_DECODER + case GST_VAAPI_CODEC_JPEG: + decoder = gst_vaapi_decoder_jpeg_new(display, caps); + break; +#endif + case GST_VAAPI_CODEC_MPEG2: + decoder = gst_vaapi_decoder_mpeg2_new(display, caps); + break; + case GST_VAAPI_CODEC_MPEG4: + decoder = gst_vaapi_decoder_mpeg4_new(display, caps); + break; + case GST_VAAPI_CODEC_VC1: + decoder = gst_vaapi_decoder_vc1_new(display, caps); + break; + default: + decoder = NULL; + break; + } + gst_caps_unref(caps); + if (!decoder) { + GST_ERROR("failed to create %s decoder", codec->codec_str); + return NULL; + } + + set_codec_defs(decoder, codec); + return decoder; +} + +gboolean +decoder_put_buffers(GstVaapiDecoder *decoder) +{ + const CodecDefs *codec; + VideoDecodeInfo info; + GstBuffer *buffer; + gboolean success; + + g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), FALSE); + + codec = get_codec_defs(decoder); + g_return_val_if_fail(codec != NULL, FALSE); + + buffer = gst_buffer_new(); + if (!buffer) { + GST_ERROR("failed to create encoded data buffer"); + return FALSE; + } + + codec->get_video_info(&info); + gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size); + + success = gst_vaapi_decoder_put_buffer(decoder, buffer); + gst_buffer_unref(buffer); + if (!success) { + GST_ERROR("failed to send video data to the decoder"); + return FALSE; + } + + if (!gst_vaapi_decoder_put_buffer(decoder, NULL)) { + GST_ERROR("failed to submit to the decoder"); + return FALSE; + } + return TRUE; +} + +GstVaapiSurface * +decoder_get_surface(GstVaapiDecoder *decoder) +{ + GstVaapiSurface *surface; + GstVaapiSurfaceProxy *proxy; + GstVaapiDecoderStatus status; + + g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL); + + status = gst_vaapi_decoder_get_surface(decoder, &proxy); + if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) { + GST_ERROR("failed to get decoded surface (decoder status %d)", status); + return NULL; + } + + /* Note: we only have a single I-frame to decode, so this is fine + to just release the surface proxy right away */ + surface = gst_vaapi_surface_proxy_get_surface(proxy); + gst_vaapi_surface_proxy_unref(proxy); + return surface; +} + +const gchar * +decoder_get_codec_name(GstVaapiDecoder *decoder) +{ + const CodecDefs *codec; + + g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL); + + codec = get_codec_defs(decoder); + g_return_val_if_fail(codec != NULL, FALSE); + + return codec->codec_str; +} diff --git a/tests/decoder.h b/tests/decoder.h new file mode 100644 index 0000000000..7ab95719f2 --- /dev/null +++ b/tests/decoder.h @@ -0,0 +1,39 @@ +/* + * decoder.h - Decoder utilities for the tests + * + * Copyright (C) 2013 Intel Corporation + * + * This library 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. + * + * This library 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 this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef DECODER_H +#define DECODER_H + +#include + +GstVaapiDecoder * +decoder_new(GstVaapiDisplay *display, const gchar *codec_name); + +gboolean +decoder_put_buffers(GstVaapiDecoder *decoder); + +GstVaapiSurface * +decoder_get_surface(GstVaapiDecoder *decoder); + +const gchar * +decoder_get_codec_name(GstVaapiDecoder *decoder); + +#endif /* DECODER_H */ diff --git a/tests/test-decode.c b/tests/test-decode.c index f855a146ad..4afed15c12 100644 --- a/tests/test-decode.c +++ b/tests/test-decode.c @@ -22,52 +22,13 @@ #include "config.h" #include -#include #include -#include -#include -#include -#include -#include -#include "test-jpeg.h" -#include "test-mpeg2.h" -#include "test-mpeg4.h" -#include "test-h264.h" -#include "test-vc1.h" +#include "decoder.h" #include "output.h" /* Set to 1 to check display cache works (shared VA display) */ #define CHECK_DISPLAY_CACHE 1 -typedef void (*GetVideoInfoFunc)(VideoDecodeInfo *info); - -typedef struct _CodecDefs CodecDefs; -struct _CodecDefs { - const gchar *codec_str; - GetVideoInfoFunc get_video_info; -}; - -static const CodecDefs g_codec_defs[] = { -#define INIT_FUNCS(CODEC) { #CODEC, CODEC##_get_video_info } - INIT_FUNCS(jpeg), - INIT_FUNCS(mpeg2), - INIT_FUNCS(mpeg4), - INIT_FUNCS(h264), - INIT_FUNCS(vc1), -#undef INIT_FUNCS - { NULL, } -}; - -static const CodecDefs * -get_codec_defs(const gchar *codec_str) -{ - const CodecDefs *c; - for (c = g_codec_defs; c->codec_str; c++) - if (strcmp(codec_str, c->codec_str) == 0) - return c; - return NULL; -} - static inline void pause(void) { g_print("Press any key to continue...\n"); @@ -90,13 +51,7 @@ main(int argc, char *argv[]) GstVaapiDisplay *display, *display2; GstVaapiWindow *window; GstVaapiDecoder *decoder; - GstCaps *decoder_caps; - GstStructure *structure; - GstVaapiDecoderStatus status; - const CodecDefs *codec; - GstBuffer *buffer; - GstVaapiSurfaceProxy *proxy; - VideoDecodeInfo info; + GstVaapiSurface *surface; static const guint win_width = 640; static const guint win_height = 480; @@ -104,13 +59,7 @@ main(int argc, char *argv[]) if (!video_output_init(&argc, argv, g_options)) g_error("failed to initialize video output subsystem"); - if (!g_codec_str) - g_codec_str = g_strdup("h264"); - - g_print("Test %s decode\n", g_codec_str); - codec = get_codec_defs(g_codec_str); - if (!codec) - g_error("no %s codec data found", g_codec_str); + g_print("Test decode\n"); display = video_output_create_display(NULL); if (!display) @@ -127,74 +76,27 @@ main(int argc, char *argv[]) if (!window) g_error("could not create window"); - codec->get_video_info(&info); - decoder_caps = gst_vaapi_profile_get_caps(info.profile); - if (!decoder_caps) - g_error("could not create decoder caps"); - - structure = gst_caps_get_structure(decoder_caps, 0); - if (info.width > 0 && info.height > 0) - gst_structure_set( - structure, - "width", G_TYPE_INT, info.width, - "height", G_TYPE_INT, info.height, - NULL - ); - - switch (gst_vaapi_profile_get_codec(info.profile)) { - case GST_VAAPI_CODEC_H264: - decoder = gst_vaapi_decoder_h264_new(display, decoder_caps); - break; -#if USE_JPEG_DECODER - case GST_VAAPI_CODEC_JPEG: - decoder = gst_vaapi_decoder_jpeg_new(display, decoder_caps); - break; -#endif - case GST_VAAPI_CODEC_MPEG2: - decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps); - break; - case GST_VAAPI_CODEC_MPEG4: - decoder = gst_vaapi_decoder_mpeg4_new(display, decoder_caps); - break; - case GST_VAAPI_CODEC_VC1: - decoder = gst_vaapi_decoder_vc1_new(display, decoder_caps); - break; - default: - decoder = NULL; - break; - } + decoder = decoder_new(display, g_codec_str); if (!decoder) g_error("could not create decoder"); - gst_caps_unref(decoder_caps); - buffer = gst_buffer_new(); - if (!buffer) - g_error("could not create encoded data buffer"); - gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size); + g_print("Decode %s sample frame\n", decoder_get_codec_name(decoder)); - if (!gst_vaapi_decoder_put_buffer(decoder, buffer)) - g_error("could not send video data to the decoder"); - gst_buffer_unref(buffer); + if (!decoder_put_buffers(decoder)) + g_error("could not fill decoder with sample data"); - if (!gst_vaapi_decoder_put_buffer(decoder, NULL)) - g_error("could not send EOS to the decoder"); - - status = gst_vaapi_decoder_get_surface(decoder, &proxy); - if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) - g_error("could not get decoded surface (decoder status %d)", status); + surface = decoder_get_surface(decoder); + if (!surface) + g_error("could not get decoded surface"); gst_vaapi_window_show(window); - if (!gst_vaapi_window_put_surface(window, - GST_VAAPI_SURFACE_PROXY_SURFACE(proxy), - NULL, - NULL, - GST_VAAPI_PICTURE_STRUCTURE_FRAME)) + if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, + GST_VAAPI_PICTURE_STRUCTURE_FRAME)) g_error("could not render surface"); pause(); - gst_vaapi_surface_proxy_unref(proxy); g_object_unref(decoder); g_object_unref(window); g_object_unref(display);