11d018b9734024898ee2dc708ce8400108d2a2e3
[platform/upstream/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 "config.h"
24 #include <string.h>
25 #include <gst/vaapi/gstvaapidecoder.h>
26 #include <gst/vaapi/gstvaapidecoder_mpeg2.h>
27 #include <gst/vaapi/gstvaapisurface.h>
28 #include "output.h"
29 #include "test-mpeg2.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(mpeg2),
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     GstVaapiDisplay      *display;
90     GstVaapiWindow       *window;
91     GstVaapiDecoder      *decoder = NULL;
92     GstCaps              *decoder_caps;
93     GstStructure         *structure;
94     GstVaapiDecoderStatus status;
95     const CodecDefs      *codec;
96     GstBuffer            *buffer;
97     GstVaapiSurfaceProxy *proxy;
98     GstVaapiSurface      *surface;
99     VideoDecodeInfo       info;
100     VideoSubpictureInfo   subinfo;
101     GstVaapiImage        *subtitle_image;
102     GstVaapiSubpicture   *subpicture;
103     GstCaps              *argbcaps;
104     GstVaapiRectangle     sub_rect;
105     guint                 surf_width, surf_height;
106
107     static const guint win_width  = 640;
108     static const guint win_height = 480;
109
110     if (!video_output_init(&argc, argv, g_options))
111         g_error("failed to initialize video output subsystem");
112
113     if (!g_codec_str)
114         g_codec_str = g_strdup("mpeg2");
115
116     g_print("Test %s decode\n", g_codec_str);
117     codec = get_codec_defs(g_codec_str);
118     if (!codec)
119         g_error("no %s codec data found", g_codec_str);
120
121     display = video_output_create_display(NULL);
122     if (!display)
123         g_error("could not create VA display");
124
125     window = video_output_create_window(display, win_width, win_height);
126     if (!window)
127         g_error("could not create window");
128
129     codec->get_video_info(&info);
130     decoder_caps = gst_vaapi_profile_get_caps(info.profile);
131     if (!decoder_caps)
132         g_error("could not create decoder caps");
133
134     structure = gst_caps_get_structure(decoder_caps, 0);
135     if (info.width > 0 && info.height > 0)
136         gst_structure_set(
137             structure,
138             "width",  G_TYPE_INT, info.width,
139             "height", G_TYPE_INT, info.height,
140             NULL
141         );
142
143     decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps);
144     if (!decoder)
145         g_error("could not create video decoder");
146     gst_caps_unref(decoder_caps);
147
148     buffer = gst_buffer_new();
149     if (!buffer)
150         g_error("could not create encoded data buffer");
151     gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size);
152
153     if (!gst_vaapi_decoder_put_buffer(decoder, buffer))
154         g_error("could not send video data to the decoder");
155     gst_buffer_unref(buffer);
156
157     if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
158         g_error("could not send EOS to the decoder");
159
160     status = gst_vaapi_decoder_get_surface(decoder, &proxy);
161     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
162         g_error("could not get decoded surface (decoder status %d)", status);
163
164     surface = gst_vaapi_surface_proxy_get_surface(proxy);
165     if (!surface)
166         g_error("could not get underlying surface");
167
168     gst_vaapi_surface_get_size(surface, &surf_width, &surf_height);
169     printf("surface size %dx%d\n", surf_width, surf_height);
170
171     subpicture_get_info (&subinfo);
172
173     /* Adding subpicture */
174     argbcaps = gst_caps_new_simple ("video/x-raw-rgb",
175               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
176               "bpp", G_TYPE_INT, 32,
177               "red_mask", G_TYPE_INT, 0xff000000,
178               "green_mask", G_TYPE_INT, 0x00ff0000,
179               "blue_mask", G_TYPE_INT, 0x0000ff00,
180               "alpha_mask", G_TYPE_INT, 0x000000ff,
181               "width", G_TYPE_INT,  subinfo.width,
182               "height", G_TYPE_INT, subinfo.height,
183                NULL);
184
185     buffer = gst_buffer_new_and_alloc (subinfo.data_size);
186     upload_image (GST_BUFFER_DATA (buffer), subinfo.data, subinfo.data_size);
187     gst_buffer_set_caps (buffer, argbcaps);
188
189     subtitle_image = gst_vaapi_image_new (display,
190       GST_VAAPI_IMAGE_RGBA, subinfo.width, subinfo.height);
191
192     if (!gst_vaapi_image_update_from_buffer (subtitle_image, buffer, NULL))
193         g_error ("could not update VA image with subtitle data");
194
195     subpicture = gst_vaapi_subpicture_new (subtitle_image);
196
197     /* We position it as a subtitle, centered at the bottom. */
198     sub_rect.x = (surf_width - subinfo.width) / 2;
199     sub_rect.y = surf_height - subinfo.height - 10;
200     sub_rect.height = subinfo.height;
201     sub_rect.width = subinfo.width;
202
203     if (!gst_vaapi_surface_associate_subpicture (
204          surface,
205          subpicture,
206          NULL,
207          &sub_rect))
208         g_error("could not associate subpicture");
209
210     gst_vaapi_window_show(window);
211
212     if (!gst_vaapi_window_put_surface(window,
213                                       GST_VAAPI_SURFACE_PROXY_SURFACE(proxy),
214                                       NULL,
215                                       NULL,
216                                       GST_VAAPI_PICTURE_STRUCTURE_FRAME))
217         g_error("could not render surface");
218
219     pause();
220
221     gst_buffer_unref(buffer);
222     gst_vaapi_surface_proxy_unref(proxy);
223     g_object_unref(decoder);
224     g_object_unref(window);
225     g_object_unref(display);
226     g_free(g_codec_str);
227     video_output_exit();
228     return 0;
229 }