Add initial VA display abstraction.
[profile/ivi/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidisplay.c
1 /*
2  *  gstvaapidisplay.c - VA display abstraction
3  *
4  *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "vaapi_utils.h"
23 #include "gstvaapidisplay.h"
24 #include <va/va_backend.h>
25
26 #define DEBUG 1
27 #include "vaapi_debug.h"
28
29 G_DEFINE_TYPE(GstVaapiDisplay, gst_vaapi_display, G_TYPE_OBJECT);
30
31 #define GST_VAAPI_DISPLAY_GET_PRIVATE(obj)                      \
32     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
33                                  GST_VAAPI_TYPE_DISPLAY,        \
34                                  GstVaapiDisplayPrivate))
35
36 struct _GstVaapiDisplayPrivate {
37     VADisplay           display;
38     VAProfile          *profiles;
39     unsigned int        num_profiles;
40     VAImageFormat      *image_formats;
41     unsigned int        num_image_formats;
42     VAImageFormat      *subpicture_formats;
43     unsigned int       *subpicture_flags;
44     unsigned int        num_subpicture_formats;
45 };
46
47 enum {
48     PROP_0,
49
50     PROP_DISPLAY
51 };
52
53 static void
54 gst_vaapi_display_set_display(GstVaapiDisplay *display, VADisplay va_display);
55
56 static void
57 gst_vaapi_display_finalize(GObject *object)
58 {
59     GstVaapiDisplay        *display = GST_VAAPI_DISPLAY(object);
60     GstVaapiDisplayPrivate *priv    = display->priv;
61
62     gst_vaapi_display_set_display(display, NULL);
63
64     G_OBJECT_CLASS(gst_vaapi_display_parent_class)->finalize(object);
65 }
66
67 static void
68 gst_vaapi_display_set_property(GObject      *object,
69                                guint         prop_id,
70                                const GValue *value,
71                                GParamSpec   *pspec)
72 {
73     GstVaapiDisplay        *display = GST_VAAPI_DISPLAY(object);
74     GstVaapiDisplayPrivate *priv    = display->priv;
75
76     switch (prop_id) {
77     case PROP_DISPLAY:
78         gst_vaapi_display_set_display(display, g_value_get_pointer(value));
79         break;
80     default:
81         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
82         break;
83     }
84 }
85
86 static void
87 gst_vaapi_display_get_property(GObject    *object,
88                                guint       prop_id,
89                                GValue     *value,
90                                GParamSpec *pspec)
91 {
92     GstVaapiDisplay        *display = GST_VAAPI_DISPLAY(object);
93     GstVaapiDisplayPrivate *priv    = display->priv;
94
95     switch (prop_id) {
96     case PROP_DISPLAY:
97         g_value_set_pointer(value, gst_vaapi_display_get_display(display));
98         break;
99     default:
100         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
101         break;
102     }
103 }
104
105 static void
106 gst_vaapi_display_class_init(GstVaapiDisplayClass *klass)
107 {
108     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
109
110     g_type_class_add_private(klass, sizeof(GstVaapiDisplayPrivate));
111
112     object_class->finalize     = gst_vaapi_display_finalize;
113     object_class->set_property = gst_vaapi_display_set_property;
114     object_class->get_property = gst_vaapi_display_get_property;
115
116     g_object_class_install_property
117         (object_class,
118          PROP_DISPLAY,
119          g_param_spec_pointer("display",
120                               "VA display",
121                               "VA display",
122                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
123 }
124
125 static void
126 gst_vaapi_display_init(GstVaapiDisplay *display)
127 {
128     GstVaapiDisplayPrivate *priv = GST_VAAPI_DISPLAY_GET_PRIVATE(display);
129
130     display->priv                = priv;
131     priv->display                = NULL;
132     priv->profiles               = 0;
133     priv->num_profiles           = 0;
134     priv->image_formats          = NULL;
135     priv->num_image_formats      = 0;
136     priv->subpicture_formats     = NULL;
137     priv->subpicture_flags       = NULL;
138     priv->num_subpicture_formats = 0;
139 }
140
141 VADisplay
142 gst_vaapi_display_get_display(GstVaapiDisplay *display)
143 {
144     GstVaapiDisplayPrivate *priv = display->priv;
145
146     return priv->display;
147 }
148
149 static void
150 gst_vaapi_display_destroy_resources(GstVaapiDisplay *display)
151 {
152     GstVaapiDisplayPrivate *priv = display->priv;
153
154     if (priv->profiles) {
155         g_free(priv->profiles);
156         priv->profiles = NULL;
157     }
158
159     if (priv->image_formats) {
160         g_free(priv->image_formats);
161         priv->image_formats = NULL;
162     }
163
164     if (priv->subpicture_formats) {
165         g_free(priv->subpicture_formats);
166         priv->subpicture_formats = NULL;
167     }
168
169     if (priv->subpicture_flags) {
170         g_free(priv->subpicture_flags);
171         priv->subpicture_flags = NULL;
172     }
173 }
174
175 static gboolean
176 gst_vaapi_display_create_resources(GstVaapiDisplay *display)
177 {
178     GstVaapiDisplayPrivate *priv = display->priv;
179     VAStatus status;
180     unsigned int i;
181
182     /* VA profiles */
183     priv->num_profiles = vaMaxNumProfiles(priv->display);
184     priv->profiles = g_new(VAProfile, priv->num_profiles);
185     if (!priv->profiles)
186         return FALSE;
187     status = vaQueryConfigProfiles(priv->display,
188                                    priv->profiles,
189                                    &priv->num_profiles);
190     if (!vaapi_check_status(status, "vaQueryConfigProfiles()"))
191         return FALSE;
192
193     D(bug("%d profiles\n", priv->num_profiles));
194     for (i = 0; i < priv->num_profiles; i++)
195         D(bug("  %s\n", string_of_VAProfile(priv->profiles[i])));
196
197     /* VA image formats */
198     priv->num_image_formats = vaMaxNumImageFormats(priv->display);
199     priv->image_formats = g_new(VAImageFormat, priv->num_image_formats);
200     if (!priv->image_formats)
201         return FALSE;
202     status = vaQueryImageFormats(priv->display,
203                                  priv->image_formats,
204                                  &priv->num_image_formats);
205     if (!vaapi_check_status(status, "vaQueryImageFormats()"))
206         return FALSE;
207
208     D(bug("%d image formats\n", priv->num_image_formats));
209     for (i = 0; i < priv->num_image_formats; i++)
210         D(bug("  %s\n", string_of_FOURCC(priv->image_formats[i].fourcc)));
211
212     /* VA subpicture formats */
213     priv->num_subpicture_formats = vaMaxNumSubpictureFormats(priv->display);
214     priv->subpicture_formats = g_new(VAImageFormat, priv->num_subpicture_formats);
215     if (!priv->subpicture_formats)
216         return FALSE;
217     priv->subpicture_flags = g_new(unsigned int, priv->num_subpicture_formats);
218     if (!priv->subpicture_flags)
219         return FALSE;
220     status = vaQuerySubpictureFormats(priv->display,
221                                       priv->subpicture_formats,
222                                       priv->subpicture_flags,
223                                       &priv->num_image_formats);
224     if (!vaapi_check_status(status, "vaQuerySubpictureFormats()"))
225         return FALSE;
226
227     D(bug("%d subpicture formats\n", priv->num_subpicture_formats));
228     for (i = 0; i < priv->num_subpicture_formats; i++)
229         D(bug("  %s\n", string_of_FOURCC(priv->subpicture_formats[i].fourcc)));
230
231     return TRUE;
232 }
233
234 void
235 gst_vaapi_display_set_display(GstVaapiDisplay *display, VADisplay va_display)
236 {
237     GstVaapiDisplayPrivate *priv = display->priv;
238     VAStatus status;
239     int major_version, minor_version;
240
241     if (priv->display) {
242         gst_vaapi_display_destroy_resources(display);
243
244         /* XXX: make sure this VADisplay is really the last occurrence */
245         status = vaTerminate(priv->display);
246         if (!vaapi_check_status(status, "vaTerminate()"))
247             return;
248         priv->display = NULL;
249     }
250
251     if (va_display) {
252         status = vaInitialize(va_display, &major_version, &minor_version);
253         if (!vaapi_check_status(status, "vaInitialize()"))
254             return;
255         priv->display = va_display;
256         D(bug("VA-API version %d.%d\n", major_version, minor_version));
257
258         if (!gst_vaapi_display_create_resources(display)) {
259             gst_vaapi_display_destroy_resources(display);
260             return;
261         }
262     }
263 }