Merge branch 'move_subdir_editing-services' into tizen_gst_1.19.2_mono
[platform/upstream/gstreamer.git] / subprojects / gstreamer-vaapi / gst / vaapi / gstvaapivideometa_texture.c
1 /*
2  *  gstvaapivideometa_texture.c - GStreamer/VA video meta (GLTextureUpload)
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2011-2014 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *  Copyright (C) 2013 Igalia
9  *    Author: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
10  *
11  *  This library is free software; you can redistribute it and/or
12  *  modify it under the terms of the GNU Lesser General Public License
13  *  as published by the Free Software Foundation; either version 2.1
14  *  of the License, or (at your option) any later version.
15  *
16  *  This library is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *  Lesser General Public License for more details.
20  *
21  *  You should have received a copy of the GNU Lesser General Public
22  *  License along with this library; if not, write to the Free
23  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  *  Boston, MA 02110-1301 USA
25  */
26
27 #include "gstcompat.h"
28 #include "gst/vaapi/ogl_compat.h"
29 #include "gstvaapivideometa.h"
30 #include "gstvaapivideometa_texture.h"
31 #include "gstvaapipluginutil.h"
32
33 #if USE_GLX
34 #include <gst/vaapi/gstvaapitexture_glx.h>
35 #endif
36
37 #define DEFAULT_FORMAT GST_VIDEO_FORMAT_RGBA
38
39 #if (USE_GLX || USE_EGL)
40 struct _GstVaapiVideoMetaTexture
41 {
42   GstVaapiTexture *texture;
43   GstVideoGLTextureType texture_type[4];
44   guint gl_format;
45   guint width;
46   guint height;
47 };
48
49 static guint
50 get_texture_orientation_flags (GstVideoGLTextureOrientation orientation)
51 {
52   guint flags;
53
54   switch (orientation) {
55     case GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_FLIP:
56       flags = GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED;
57       break;
58     case GST_VIDEO_GL_TEXTURE_ORIENTATION_X_FLIP_Y_NORMAL:
59       flags = GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED;
60       break;
61     case GST_VIDEO_GL_TEXTURE_ORIENTATION_X_FLIP_Y_FLIP:
62       flags = GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED |
63           GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED;
64       break;
65     default:
66       flags = 0;
67       break;
68   }
69   return flags;
70 }
71
72 static gboolean
73 meta_texture_ensure_format (GstVaapiVideoMetaTexture * meta,
74     GstVideoFormat format)
75 {
76   memset (meta->texture_type, 0, sizeof (meta->texture_type));
77
78   switch (format) {
79     case GST_VIDEO_FORMAT_RGBA:
80       meta->gl_format = GL_RGBA;
81       meta->texture_type[0] = GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
82       break;
83     case GST_VIDEO_FORMAT_BGRA:
84       meta->gl_format = GL_BGRA_EXT;
85       /* FIXME: add GST_VIDEO_GL_TEXTURE_TYPE_BGRA extension */
86       meta->texture_type[0] = GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
87       break;
88     default:
89       goto error_unsupported_format;
90   }
91   return TRUE;
92
93   /* ERRORS */
94 error_unsupported_format:
95   GST_ERROR ("unsupported texture format %s",
96       gst_video_format_to_string (format));
97   return FALSE;
98 }
99
100 static gboolean
101 meta_texture_ensure_info_from_buffer (GstVaapiVideoMetaTexture * meta,
102     GstBuffer * buffer)
103 {
104   GstVideoMeta *vmeta;
105   GstVideoFormat format;
106
107   if (!buffer || !(vmeta = gst_buffer_get_video_meta (buffer))) {
108     format = DEFAULT_FORMAT;
109     meta->width = 0;
110     meta->height = 0;
111   } else {
112     const GstVideoFormatInfo *const fmt_info =
113         gst_video_format_get_info (vmeta->format);
114     format = (fmt_info && GST_VIDEO_FORMAT_INFO_IS_RGB (fmt_info)) ?
115         vmeta->format : DEFAULT_FORMAT;
116     meta->width = vmeta->width;
117     meta->height = vmeta->height;
118   }
119   return meta_texture_ensure_format (meta, format);
120 }
121
122 static void
123 meta_texture_free (GstVaapiVideoMetaTexture * meta)
124 {
125   if (G_UNLIKELY (!meta))
126     return;
127
128   gst_mini_object_replace ((GstMiniObject **) & meta->texture, NULL);
129   g_slice_free (GstVaapiVideoMetaTexture, meta);
130 }
131
132 static GstVaapiVideoMetaTexture *
133 meta_texture_new (void)
134 {
135   GstVaapiVideoMetaTexture *meta;
136
137   meta = g_slice_new (GstVaapiVideoMetaTexture);
138   if (!meta)
139     return NULL;
140
141   meta->texture = NULL;
142   if (!meta_texture_ensure_info_from_buffer (meta, NULL))
143     goto error;
144   return meta;
145
146   /* ERRORS */
147 error:
148   {
149     meta_texture_free (meta);
150     return NULL;
151   }
152 }
153
154 static GstVaapiVideoMetaTexture *
155 meta_texture_copy (GstVaapiVideoMetaTexture * meta)
156 {
157   GstVaapiVideoMetaTexture *copy;
158
159   copy = meta_texture_new ();
160   if (!copy)
161     return NULL;
162
163   memcpy (copy->texture_type, meta->texture_type, sizeof (meta->texture_type));
164   copy->gl_format = meta->gl_format;
165   copy->width = meta->width;
166   copy->height = meta->height;
167
168   gst_mini_object_replace ((GstMiniObject **) & copy->texture,
169       (GstMiniObject *) meta->texture);
170   return copy;
171 }
172
173 static gboolean
174 gst_vaapi_texture_upload (GstVideoGLTextureUploadMeta * meta,
175     guint texture_id[4])
176 {
177   GstVaapiVideoMeta *const vmeta =
178       gst_buffer_get_vaapi_video_meta (meta->buffer);
179   GstVaapiVideoMetaTexture *const meta_texture = meta->user_data;
180   GstVaapiSurfaceProxy *const proxy =
181       gst_vaapi_video_meta_get_surface_proxy (vmeta);
182   GstVaapiSurface *const surface = gst_vaapi_surface_proxy_get_surface (proxy);
183   GstVaapiDisplay *const dpy = gst_vaapi_surface_get_display (surface);
184   GstVaapiTexture *texture = NULL;
185
186   if (!gst_vaapi_display_has_opengl (dpy))
187     return FALSE;
188
189   if (meta_texture->texture
190       /* Check whether VA display changed */
191       && GST_VAAPI_TEXTURE_DISPLAY (meta_texture->texture) == dpy
192       /* Check whether texture id changed */
193       && (gst_vaapi_texture_get_id (meta_texture->texture) == texture_id[0])) {
194     texture = meta_texture->texture;
195   }
196
197   if (!texture) {
198     /* FIXME: should we assume target? */
199     texture =
200         gst_vaapi_texture_new_wrapped (dpy, texture_id[0],
201         GL_TEXTURE_2D, meta_texture->gl_format, meta_texture->width,
202         meta_texture->height);
203   }
204
205   if (meta_texture->texture != texture) {
206     gst_mini_object_replace ((GstMiniObject **) & meta_texture->texture,
207         (GstMiniObject *) texture);
208   }
209
210   if (!texture)
211     return FALSE;
212
213   gst_vaapi_texture_set_orientation_flags (meta_texture->texture,
214       get_texture_orientation_flags (meta->texture_orientation));
215
216   return gst_vaapi_texture_put_surface (meta_texture->texture, surface,
217       gst_vaapi_surface_proxy_get_crop_rect (proxy),
218       gst_vaapi_video_meta_get_render_flags (vmeta));
219 }
220
221 GstMeta *
222 gst_buffer_add_texture_upload_meta (GstBuffer * buffer)
223 {
224   GstVaapiVideoMetaTexture *meta_texture;
225
226   if (!buffer)
227     return FALSE;
228
229   meta_texture = meta_texture_new ();
230   if (!meta_texture)
231     return FALSE;
232
233   if (!meta_texture_ensure_info_from_buffer (meta_texture, buffer))
234     goto error;
235
236   return (GstMeta *) gst_buffer_add_video_gl_texture_upload_meta (buffer,
237       GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL, 1,
238       meta_texture->texture_type, gst_vaapi_texture_upload, meta_texture,
239       (GBoxedCopyFunc) meta_texture_copy, (GBoxedFreeFunc) meta_texture_free);
240
241   /* ERRORS */
242 error:
243   {
244     meta_texture_free (meta_texture);
245     return NULL;
246   }
247 }
248
249 gboolean
250 gst_buffer_ensure_texture_upload_meta (GstBuffer * buffer)
251 {
252   GstVideoGLTextureUploadMeta *const meta =
253       gst_buffer_get_video_gl_texture_upload_meta (buffer);
254
255   return meta ?
256       meta_texture_ensure_info_from_buffer (meta->user_data, buffer) :
257       (gst_buffer_add_texture_upload_meta (buffer) != NULL);
258 }
259 #endif