tests: fix subpicture test.
[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 static void
74 upload_image (guint8 *dst, const guint32 *src, guint size)
75 {
76     guint i;
77
78     for (i = 0; i < size; i += 4) {
79         dst[i    ] = *src >> 24;
80         dst[i + 1] = *src >> 16;
81         dst[i + 2] = *src >> 8;
82         dst[i + 3] = *src++;
83     }
84 }
85
86 int
87 main(int argc, char *argv[])
88 {
89     GOptionContext       *options;
90     GstVaapiDisplay      *display;
91     GstVaapiWindow       *window;
92     GstVaapiDecoder      *decoder;
93     GstCaps              *decoder_caps;
94     GstStructure         *structure;
95     GstVaapiDecoderStatus status;
96     const CodecDefs      *codec;
97     GstBuffer            *buffer;
98     GstVaapiSurfaceProxy *proxy;
99     GstVaapiSurface      *surface;
100     VideoDecodeInfo       info;
101     VideoSubpictureInfo   subinfo;
102     GstVaapiImage        *subtitle_image;
103     GstVaapiSubpicture   *subpicture;
104     GstCaps              *argbcaps;
105     GstVaapiRectangle     sub_rect;
106     guint                 surf_width, surf_height;
107
108     static const guint win_width  = 640;
109     static const guint win_height = 480;
110
111     gst_init(&argc, &argv);
112
113     options = g_option_context_new(" - test-decode options");
114     g_option_context_add_main_entries(options, g_options, NULL);
115     g_option_context_parse(options, &argc, &argv, NULL);
116     g_option_context_free(options);
117
118     if (!g_codec_str)
119         g_codec_str = g_strdup("h264");
120
121     g_print("Test %s decode\n", g_codec_str);
122     codec = get_codec_defs(g_codec_str);
123     if (!codec)
124         g_error("no %s codec data found", g_codec_str);
125
126     display = gst_vaapi_display_x11_new(NULL);
127     if (!display)
128         g_error("could not create VA display");
129
130     window = gst_vaapi_window_x11_new(display, win_width, win_height);
131     if (!window)
132         g_error("could not create window");
133
134     codec->get_video_info(&info);
135     decoder_caps = gst_vaapi_profile_get_caps(info.profile);
136     if (!decoder_caps)
137         g_error("could not create decoder caps");
138
139     structure = gst_caps_get_structure(decoder_caps, 0);
140     if (info.width > 0 && info.height > 0)
141         gst_structure_set(
142             structure,
143             "width",  G_TYPE_INT, info.width,
144             "height", G_TYPE_INT, info.height,
145             NULL
146         );
147
148     decoder = gst_vaapi_decoder_ffmpeg_new(display, decoder_caps);
149     if (!decoder)
150         g_error("could not create FFmpeg decoder");
151     gst_caps_unref(decoder_caps);
152
153     buffer = gst_buffer_new();
154     if (!buffer)
155         g_error("could not create encoded data buffer");
156     gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size);
157
158     if (!gst_vaapi_decoder_put_buffer(decoder, buffer))
159         g_error("could not send video data to the decoder");
160     gst_buffer_unref(buffer);
161
162     if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
163         g_error("could not send EOS to the decoder");
164
165     proxy = gst_vaapi_decoder_get_surface(decoder, &status);
166     if (!proxy)
167         g_error("could not get decoded surface (decoder status %d)", status);
168
169     surface = gst_vaapi_surface_proxy_get_surface(proxy);
170     if (!surface)
171         g_error("could not get underlying surface");
172
173     gst_vaapi_surface_get_size(surface, &surf_width, &surf_height);
174     printf("surface size %dx%d\n", surf_width, surf_height);
175
176     subpicture_get_info (&subinfo);
177
178     /* Adding subpicture */
179     argbcaps = gst_caps_new_simple ("video/x-raw-rgb",
180               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
181               "bpp", G_TYPE_INT, 32,
182               "red_mask", G_TYPE_INT, 0xff000000,
183               "green_mask", G_TYPE_INT, 0x00ff0000,
184               "blue_mask", G_TYPE_INT, 0x0000ff00,
185               "alpha_mask", G_TYPE_INT, 0x000000ff,
186               "width", G_TYPE_INT,  subinfo.width,
187               "height", G_TYPE_INT, subinfo.height,
188                NULL);
189
190     buffer = gst_buffer_new_and_alloc (subinfo.data_size);
191     upload_image (GST_BUFFER_DATA (buffer), subinfo.data, subinfo.data_size);
192     gst_buffer_set_caps (buffer, argbcaps);
193
194     subtitle_image = gst_vaapi_image_new (display,
195       GST_VAAPI_IMAGE_RGBA, subinfo.width, subinfo.height);
196
197     if (!gst_vaapi_image_update_from_buffer (subtitle_image, buffer))
198         g_error ("could not update VA image with subtitle data");
199
200     subpicture = gst_vaapi_subpicture_new (subtitle_image);
201
202     /* We position it as a subtitle, centered at the bottom. */
203     sub_rect.x = (surf_width - subinfo.width) / 2;
204     sub_rect.y = surf_height - subinfo.height - 10;
205     sub_rect.height = subinfo.height;
206     sub_rect.width = subinfo.width;
207
208     if (!gst_vaapi_surface_associate_subpicture (
209          surface,
210          subpicture,
211          NULL,
212          &sub_rect))
213         g_error("could not associate subpicture");
214
215     gst_vaapi_window_show(window);
216
217     if (!gst_vaapi_window_put_surface(window,
218                                       GST_VAAPI_SURFACE_PROXY_SURFACE(proxy),
219                                       NULL,
220                                       NULL,
221                                       GST_VAAPI_PICTURE_STRUCTURE_FRAME))
222         g_error("could not render surface");
223
224     pause();
225
226     gst_buffer_unref(buffer);
227     g_object_unref(proxy);
228     g_object_unref(decoder);
229     g_object_unref(window);
230     g_object_unref(display);
231     g_free(g_codec_str);
232     gst_deinit();
233     return 0;
234 }