tests: add test for subpictures.
[profile/ivi/gstreamer-vaapi.git] / tests / test-subpicture.c
1 /*
2  *  test-subpicture.c - Test GstVaapiSubpicture
3  *
4  *  Copyright (C) <2011> Intel Corporation
5  *  Copyright (C) <2011> Collabora Ltd.
6  *  Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
21  */
22
23 #include <string.h>
24 #include <gst/vaapi/gstvaapidisplay_x11.h>
25 #include <gst/vaapi/gstvaapiwindow_x11.h>
26 #include <gst/vaapi/gstvaapidecoder.h>
27 #include <gst/vaapi/gstvaapidecoder_ffmpeg.h>
28 #include <gst/vaapi/gstvaapisurface.h>
29 #include "test-h264.h"
30 #include "test-subpicture-data.h"
31
32 typedef void (*GetVideoInfoFunc)(VideoDecodeInfo *info);
33
34 typedef struct _CodecDefs CodecDefs;
35 struct _CodecDefs {
36     const gchar        *codec_str;
37     GetVideoInfoFunc    get_video_info;
38 };
39
40 static const CodecDefs g_codec_defs[] = {
41 #define INIT_FUNCS(CODEC) { #CODEC, CODEC##_get_video_info }
42     INIT_FUNCS(h264),
43 #undef INIT_FUNCS
44     { NULL, }
45 };
46
47 static const CodecDefs *
48 get_codec_defs(const gchar *codec_str)
49 {
50     const CodecDefs *c;
51     for (c = g_codec_defs; c->codec_str; c++)
52         if (strcmp(codec_str, c->codec_str) == 0)
53             return c;
54     return NULL;
55 }
56
57 static inline void pause(void)
58 {
59     g_print("Press any key to continue...\n");
60     getchar();
61 }
62
63 static gchar *g_codec_str;
64
65 static GOptionEntry g_options[] = {
66     { "codec", 'c',
67       0,
68       G_OPTION_ARG_STRING, &g_codec_str,
69       "codec to test", NULL },
70     { NULL, }
71 };
72
73 int
74 main(int argc, char *argv[])
75 {
76     GOptionContext       *options;
77     GstVaapiDisplay      *display;
78     GstVaapiWindow       *window;
79     GstVaapiDecoder      *decoder;
80     GstCaps              *decoder_caps;
81     GstStructure         *structure;
82     GstVaapiDecoderStatus status;
83     const CodecDefs      *codec;
84     GstBuffer            *buffer;
85     GstVaapiSurfaceProxy *proxy;
86     VideoDecodeInfo       info;
87     VideoSubpictureInfo   subinfo;
88     GstVaapiImage        *subtitle_image;
89     GstVaapiSubpicture   *subpicture;
90     GstCaps *argbcaps;
91     GstVaapiRectangle sub_rect;
92
93     static const guint win_width  = 640;
94     static const guint win_height = 480;
95
96     gst_init(&argc, &argv);
97
98     options = g_option_context_new(" - test-decode options");
99     g_option_context_add_main_entries(options, g_options, NULL);
100     g_option_context_parse(options, &argc, &argv, NULL);
101     g_option_context_free(options);
102
103     if (!g_codec_str)
104         g_codec_str = g_strdup("h264");
105
106     g_print("Test %s decode\n", g_codec_str);
107     codec = get_codec_defs(g_codec_str);
108     if (!codec)
109         g_error("no %s codec data found", g_codec_str);
110
111     display = gst_vaapi_display_x11_new(NULL);
112     if (!display)
113         g_error("could not create VA display");
114
115     window = gst_vaapi_window_x11_new(display, win_width, win_height);
116     if (!window)
117         g_error("could not create window");
118
119     codec->get_video_info(&info);
120     decoder_caps = gst_vaapi_profile_get_caps(info.profile);
121     if (!decoder_caps)
122         g_error("could not create decoder caps");
123
124     structure = gst_caps_get_structure(decoder_caps, 0);
125     if (info.width > 0 && info.height > 0)
126         gst_structure_set(
127             structure,
128             "width",  G_TYPE_INT, info.width,
129             "height", G_TYPE_INT, info.height,
130             NULL
131         );
132
133     decoder = gst_vaapi_decoder_ffmpeg_new(display, decoder_caps);
134     if (!decoder)
135         g_error("could not create FFmpeg decoder");
136     gst_caps_unref(decoder_caps);
137
138     buffer = gst_buffer_new();
139     if (!buffer)
140         g_error("could not create encoded data buffer");
141     gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size);
142
143     if (!gst_vaapi_decoder_put_buffer(decoder, buffer))
144         g_error("could not send video data to the decoder");
145     gst_buffer_unref(buffer);
146
147     if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
148         g_error("could not send EOS to the decoder");
149
150     proxy = gst_vaapi_decoder_get_surface(decoder, &status);
151     if (!proxy)
152         g_error("could not get decoded surface (decoder status %d)", status);
153
154     subpicture_get_info (&subinfo);
155
156     /* Adding subpicture */
157     argbcaps = gst_caps_new_simple ("video/x-raw-rgb",
158               "endianness", G_TYPE_INT, 1,
159               "bpp", G_TYPE_INT, 32,
160               "width", G_TYPE_INT,  subinfo.width,
161               "height", G_TYPE_INT, subinfo.height,
162                NULL);
163
164     buffer = gst_buffer_new ();
165     gst_buffer_set_data(buffer, (guchar *)subinfo.data, subinfo.data_size);
166     gst_buffer_set_caps (buffer, argbcaps);
167
168     subtitle_image = gst_vaapi_image_new (display,
169       GST_VAAPI_IMAGE_RGBA, subinfo.width, subinfo.height);
170
171     gst_vaapi_image_update_from_buffer (subtitle_image, buffer);
172
173     subpicture = gst_vaapi_subpicture_new (subtitle_image);
174
175     /* We position it as a subtitle, centered at the bottom. */
176     sub_rect.x = (win_width - subinfo.width) / 2;
177     sub_rect.y = win_height - subinfo.height - 10;
178     sub_rect.height = subinfo.height;
179     sub_rect.width = subinfo.height;
180
181     if (!gst_vaapi_surface_associate_subpicture (
182          GST_VAAPI_SURFACE_PROXY_SURFACE(proxy),
183          subpicture,
184          NULL,
185          &sub_rect))
186         g_error("could not associate subpicture");
187
188     gst_vaapi_window_show(window);
189
190     if (!gst_vaapi_window_put_surface(window,
191                                       GST_VAAPI_SURFACE_PROXY_SURFACE(proxy),
192                                       NULL,
193                                       NULL,
194                                       GST_VAAPI_PICTURE_STRUCTURE_FRAME))
195         g_error("could not render surface");
196
197     pause();
198
199     gst_buffer_unref(buffer);
200     g_object_unref(proxy);
201     g_object_unref(decoder);
202     g_object_unref(window);
203     g_object_unref(display);
204     g_free(g_codec_str);
205     gst_deinit();
206     return 0;
207 }