3 * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:element-gloverlay
25 * Overlay GL video texture with a PNG image
29 * gst-launch-1.0 videotestsrc ! gloverlay location=image.jpg ! glimagesink
31 * FBO (Frame Buffer Object) is required.
39 #include <gst/base/gsttypefindhelper.h>
40 #include <gst/gl/gstglconfig.h>
42 #include "gstgloverlay.h"
43 #include "effects/gstgleffectssources.h"
44 #include "gstglutils.h"
48 #if defined(_MSC_VER) || (defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 6)
54 #if PNG_LIBPNG_VER >= 10400
55 #define int_p_NULL NULL
56 #define png_infopp_NULL NULL
59 #define GST_CAT_DEFAULT gst_gl_overlay_debug
60 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
63 GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_debug, "gloverlay", 0, "gloverlay element");
65 #define gst_gl_overlay_parent_class parent_class
66 G_DEFINE_TYPE_WITH_CODE (GstGLOverlay, gst_gl_overlay, GST_TYPE_GL_FILTER,
69 static gboolean gst_gl_overlay_set_caps (GstGLFilter * filter,
70 GstCaps * incaps, GstCaps * outcaps);
72 static void gst_gl_overlay_set_property (GObject * object, guint prop_id,
73 const GValue * value, GParamSpec * pspec);
74 static void gst_gl_overlay_get_property (GObject * object, guint prop_id,
75 GValue * value, GParamSpec * pspec);
77 static void gst_gl_overlay_before_transform (GstBaseTransform * trans,
79 static gboolean gst_gl_overlay_filter_texture (GstGLFilter * filter,
80 GstGLMemory * in_tex, GstGLMemory * out_tex);
82 static gboolean gst_gl_overlay_load_png (GstGLOverlay * overlay, FILE * fp);
83 static gboolean gst_gl_overlay_load_jpeg (GstGLOverlay * overlay, FILE * fp);
100 static const gchar *overlay_v_src =
101 "attribute vec4 a_position;\n"
102 "attribute vec2 a_texcoord;\n"
103 "varying vec2 v_texcoord;\n"
106 " gl_Position = a_position;\n"
107 " v_texcoord = a_texcoord;\n"
110 /* fragment source */
111 static const gchar *overlay_f_src =
113 "precision mediump float;\n"
115 "uniform sampler2D texture;\n"
116 "uniform float alpha;\n"
117 "varying vec2 v_texcoord;\n"
120 " vec4 rgba = texture2D( texture, v_texcoord );\n"
121 " gl_FragColor = vec4(rgba.rgb, rgba.a * alpha);\n"
125 /* init resources that need a gl context */
127 gst_gl_overlay_gl_start (GstGLBaseFilter * base_filter)
129 GstGLOverlay *overlay = GST_GL_OVERLAY (base_filter);
131 if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter))
134 return gst_gl_context_gen_shader (base_filter->context, overlay_v_src,
135 overlay_f_src, &overlay->shader);
138 /* free resources that need a gl context */
140 gst_gl_overlay_gl_stop (GstGLBaseFilter * base_filter)
142 GstGLOverlay *overlay = GST_GL_OVERLAY (base_filter);
143 const GstGLFuncs *gl = base_filter->context->gl_vtable;
145 if (overlay->shader) {
146 gst_object_unref (overlay->shader);
147 overlay->shader = NULL;
150 if (overlay->image_memory) {
151 gst_memory_unref ((GstMemory *) overlay->image_memory);
152 overlay->image_memory = NULL;
156 gl->DeleteVertexArrays (1, &overlay->vao);
161 gl->DeleteBuffers (1, &overlay->vbo);
165 if (overlay->vbo_indices) {
166 gl->DeleteBuffers (1, &overlay->vbo_indices);
167 overlay->vbo_indices = 0;
170 if (overlay->overlay_vao) {
171 gl->DeleteVertexArrays (1, &overlay->overlay_vao);
172 overlay->overlay_vao = 0;
175 if (overlay->overlay_vbo) {
176 gl->DeleteBuffers (1, &overlay->overlay_vbo);
177 overlay->overlay_vbo = 0;
180 GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter);
184 gst_gl_overlay_class_init (GstGLOverlayClass * klass)
186 GObjectClass *gobject_class;
187 GstElementClass *element_class;
189 gobject_class = (GObjectClass *) klass;
190 element_class = GST_ELEMENT_CLASS (klass);
192 gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass));
194 gobject_class->set_property = gst_gl_overlay_set_property;
195 gobject_class->get_property = gst_gl_overlay_get_property;
197 GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_overlay_gl_start;
198 GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_overlay_gl_stop;
200 GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_overlay_set_caps;
201 GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_overlay_filter_texture;
203 GST_BASE_TRANSFORM_CLASS (klass)->before_transform =
204 GST_DEBUG_FUNCPTR (gst_gl_overlay_before_transform);
206 g_object_class_install_property (gobject_class, PROP_LOCATION,
207 g_param_spec_string ("location", "location",
208 "Location of image file to overlay", NULL, GST_PARAM_CONTROLLABLE
209 | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
210 | G_PARAM_STATIC_STRINGS));
211 g_object_class_install_property (gobject_class, PROP_OFFSET_X,
212 g_param_spec_int ("offset-x", "X Offset",
213 "For positive value, horizontal offset of overlay image in pixels from"
214 " left of video image. For negative value, horizontal offset of overlay"
215 " image in pixels from right of video image", G_MININT, G_MAXINT, 0,
216 GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
217 | G_PARAM_STATIC_STRINGS));
218 g_object_class_install_property (gobject_class, PROP_OFFSET_Y,
219 g_param_spec_int ("offset-y", "Y Offset",
220 "For positive value, vertical offset of overlay image in pixels from"
221 " top of video image. For negative value, vertical offset of overlay"
222 " image in pixels from bottom of video image", G_MININT, G_MAXINT, 0,
223 GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
224 | G_PARAM_STATIC_STRINGS));
225 g_object_class_install_property (gobject_class, PROP_RELATIVE_X,
226 g_param_spec_double ("relative-x", "Relative X Offset",
227 "Horizontal offset of overlay image in fractions of video image "
228 "width, from top-left corner of video image", 0.0, 1.0, 0.0,
229 GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
230 | G_PARAM_STATIC_STRINGS));
231 g_object_class_install_property (gobject_class, PROP_RELATIVE_Y,
232 g_param_spec_double ("relative-y", "Relative Y Offset",
233 "Vertical offset of overlay image in fractions of video image "
234 "height, from top-left corner of video image", 0.0, 1.0, 0.0,
235 GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
236 | G_PARAM_STATIC_STRINGS));
237 g_object_class_install_property (gobject_class, PROP_OVERLAY_WIDTH,
238 g_param_spec_int ("overlay-width", "Overlay Width",
239 "Width of overlay image in pixels (0 = same as overlay image)", 0,
241 GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
242 | G_PARAM_STATIC_STRINGS));
243 g_object_class_install_property (gobject_class, PROP_OVERLAY_HEIGHT,
244 g_param_spec_int ("overlay-height", "Overlay Height",
245 "Height of overlay image in pixels (0 = same as overlay image)", 0,
247 GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE
248 | G_PARAM_STATIC_STRINGS));
249 g_object_class_install_property (gobject_class, PROP_ALPHA,
250 g_param_spec_double ("alpha", "Alpha", "Global alpha of overlay image",
251 0.0, 1.0, 1.0, GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING
252 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
254 gst_element_class_set_metadata (element_class,
255 "Gstreamer OpenGL Overlay", "Filter/Effect/Video",
256 "Overlay GL video texture with a JPEG/PNG image",
257 "Filippo Argiolas <filippo.argiolas@gmail.com>, "
258 "Matthew Waters <matthew@centricular.com>");
260 GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api =
261 GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3;
265 gst_gl_overlay_init (GstGLOverlay * overlay)
267 overlay->offset_x = 0;
268 overlay->offset_y = 0;
270 overlay->relative_x = 0.0;
271 overlay->relative_y = 0.0;
273 overlay->overlay_width = 0;
274 overlay->overlay_height = 0;
276 overlay->alpha = 1.0;
280 gst_gl_overlay_set_property (GObject * object, guint prop_id,
281 const GValue * value, GParamSpec * pspec)
283 GstGLOverlay *overlay = GST_GL_OVERLAY (object);
287 g_free (overlay->location);
288 overlay->location_has_changed = TRUE;
289 overlay->location = g_value_dup_string (value);
292 overlay->offset_x = g_value_get_int (value);
293 overlay->geometry_change = TRUE;
296 overlay->offset_y = g_value_get_int (value);
297 overlay->geometry_change = TRUE;
299 case PROP_RELATIVE_X:
300 overlay->relative_x = g_value_get_double (value);
301 overlay->geometry_change = TRUE;
303 case PROP_RELATIVE_Y:
304 overlay->relative_y = g_value_get_double (value);
305 overlay->geometry_change = TRUE;
307 case PROP_OVERLAY_WIDTH:
308 overlay->overlay_width = g_value_get_int (value);
309 overlay->geometry_change = TRUE;
311 case PROP_OVERLAY_HEIGHT:
312 overlay->overlay_height = g_value_get_int (value);
313 overlay->geometry_change = TRUE;
316 overlay->alpha = g_value_get_double (value);
319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
325 gst_gl_overlay_get_property (GObject * object, guint prop_id,
326 GValue * value, GParamSpec * pspec)
328 GstGLOverlay *overlay = GST_GL_OVERLAY (object);
332 g_value_set_string (value, overlay->location);
335 g_value_set_int (value, overlay->offset_x);
338 g_value_set_int (value, overlay->offset_y);
340 case PROP_RELATIVE_X:
341 g_value_set_double (value, overlay->relative_x);
343 case PROP_RELATIVE_Y:
344 g_value_set_double (value, overlay->relative_y);
346 case PROP_OVERLAY_WIDTH:
347 g_value_set_int (value, overlay->overlay_width);
349 case PROP_OVERLAY_HEIGHT:
350 g_value_set_int (value, overlay->overlay_height);
353 g_value_set_double (value, overlay->alpha);
356 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
362 gst_gl_overlay_set_caps (GstGLFilter * filter, GstCaps * incaps,
365 GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
366 GstStructure *s = gst_caps_get_structure (incaps, 0);
370 gst_structure_get_int (s, "width", &width);
371 gst_structure_get_int (s, "height", &height);
373 overlay->window_width = width;
374 overlay->window_height = height;
380 _unbind_buffer (GstGLOverlay * overlay)
382 GstGLFilter *filter = GST_GL_FILTER (overlay);
383 const GstGLFuncs *gl = GST_GL_BASE_FILTER (overlay)->context->gl_vtable;
385 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
386 gl->BindBuffer (GL_ARRAY_BUFFER, 0);
388 gl->DisableVertexAttribArray (filter->draw_attr_position_loc);
389 gl->DisableVertexAttribArray (filter->draw_attr_texture_loc);
393 _bind_buffer (GstGLOverlay * overlay, GLuint vbo)
395 GstGLFilter *filter = GST_GL_FILTER (overlay);
396 const GstGLFuncs *gl = GST_GL_BASE_FILTER (overlay)->context->gl_vtable;
398 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->vbo_indices);
399 gl->BindBuffer (GL_ARRAY_BUFFER, vbo);
401 gl->EnableVertexAttribArray (filter->draw_attr_position_loc);
402 gl->EnableVertexAttribArray (filter->draw_attr_texture_loc);
404 gl->VertexAttribPointer (filter->draw_attr_position_loc, 3, GL_FLOAT,
405 GL_FALSE, 5 * sizeof (GLfloat), (void *) 0);
406 gl->VertexAttribPointer (filter->draw_attr_texture_loc, 2, GL_FLOAT,
407 GL_FALSE, 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat)));
411 float v_vertices[] = {
412 /*| Vertex | TexCoord |*/
413 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
414 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
415 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
416 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
419 static const GLushort indices[] = { 0, 1, 2, 0, 2, 3, };
423 gst_gl_overlay_callback (GstGLFilter * filter, GstGLMemory * in_tex,
426 GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
429 gboolean memory_mapped = FALSE;
430 const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
431 gboolean ret = FALSE;
433 #if GST_GL_HAVE_OPENGL
434 if (gst_gl_context_get_gl_api (GST_GL_BASE_FILTER (filter)->context) &
437 gl->MatrixMode (GL_PROJECTION);
442 gl->ActiveTexture (GL_TEXTURE0);
443 gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex));
445 gst_gl_shader_use (overlay->shader);
447 gst_gl_shader_set_uniform_1f (overlay->shader, "alpha", 1.0f);
448 gst_gl_shader_set_uniform_1i (overlay->shader, "texture", 0);
450 filter->draw_attr_position_loc =
451 gst_gl_shader_get_attribute_location (overlay->shader, "a_position");
452 filter->draw_attr_texture_loc =
453 gst_gl_shader_get_attribute_location (overlay->shader, "a_texcoord");
455 gst_gl_filter_draw_fullscreen_quad (filter);
457 if (!overlay->image_memory)
460 if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info,
461 GST_MAP_READ | GST_MAP_GL) || map_info.data == NULL)
464 memory_mapped = TRUE;
465 image_tex = *(guint *) map_info.data;
467 if (!overlay->overlay_vbo) {
468 if (gl->GenVertexArrays) {
469 gl->GenVertexArrays (1, &overlay->overlay_vao);
470 gl->BindVertexArray (overlay->overlay_vao);
473 gl->GenBuffers (1, &overlay->vbo_indices);
474 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->vbo_indices);
475 gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices,
478 gl->GenBuffers (1, &overlay->overlay_vbo);
479 gl->BindBuffer (GL_ARRAY_BUFFER, overlay->overlay_vbo);
480 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->vbo_indices);
481 overlay->geometry_change = TRUE;
484 if (gl->GenVertexArrays) {
485 gl->BindVertexArray (overlay->overlay_vao);
488 if (overlay->geometry_change) {
489 gint render_width, render_height;
490 gfloat x, y, image_width, image_height;
494 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
495 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
496 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
497 -1.0f, 1.0f, 0.0f, 0.0, 1.0f,
501 /* scale from [0, 1] -> [-1, 1] */
502 x = ((gfloat) overlay->offset_x / (gfloat) overlay->window_width +
503 overlay->relative_x) * 2.0f - 1.0;
504 y = ((gfloat) overlay->offset_y / (gfloat) overlay->window_height +
505 overlay->relative_y) * 2.0f - 1.0;
506 /* scale from [0, 1] -> [0, 2] */
508 overlay->overlay_width >
509 0 ? overlay->overlay_width : overlay->image_width;
511 overlay->overlay_height >
512 0 ? overlay->overlay_height : overlay->image_height;
514 ((gfloat) render_width / (gfloat) overlay->window_width) * 2.0f;
516 ((gfloat) render_height / (gfloat) overlay->window_height) * 2.0f;
518 vertices[0] = vertices[15] = x;
519 vertices[5] = vertices[10] = x + image_width;
520 vertices[1] = vertices[6] = y;
521 vertices[11] = vertices[16] = y + image_height;
523 gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices,
527 _bind_buffer (overlay, overlay->overlay_vbo);
529 gl->BindTexture (GL_TEXTURE_2D, image_tex);
530 gst_gl_shader_set_uniform_1f (overlay->shader, "alpha", overlay->alpha);
532 gl->Enable (GL_BLEND);
533 if (gl->BlendFuncSeparate)
534 gl->BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
535 GL_ONE_MINUS_SRC_ALPHA);
537 gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
538 gl->BlendEquation (GL_FUNC_ADD);
540 gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
542 gl->Disable (GL_BLEND);
546 if (gl->GenVertexArrays)
547 gl->BindVertexArray (0);
548 _unbind_buffer (overlay);
550 gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context);
553 gst_memory_unmap ((GstMemory *) overlay->image_memory, &map_info);
555 overlay->geometry_change = FALSE;
561 load_file (GstGLOverlay * overlay)
567 GstStructure *structure;
568 gboolean success = FALSE;
570 if (overlay->location == NULL)
573 if ((fp = fopen (overlay->location, "rb")) == NULL) {
574 GST_ELEMENT_ERROR (overlay, RESOURCE, NOT_FOUND, ("Can't open file"),
575 ("File: %s", overlay->location));
579 n_read = fread (buff, 1, sizeof (buff), fp);
580 if (n_read != sizeof (buff)) {
581 GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("Can't read file header"),
582 ("File: %s", overlay->location));
586 caps = gst_type_find_helper_for_data (GST_OBJECT (overlay), buff,
587 sizeof (buff), NULL);
590 GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("Can't find file type"),
591 ("File: %s", overlay->location));
595 fseek (fp, 0, SEEK_SET);
597 structure = gst_caps_get_structure (caps, 0);
598 if (gst_structure_has_name (structure, "image/jpeg")) {
599 success = gst_gl_overlay_load_jpeg (overlay, fp);
600 } else if (gst_structure_has_name (structure, "image/png")) {
601 success = gst_gl_overlay_load_png (overlay, fp);
603 GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("Image type not supported"),
604 ("File: %s", overlay->location));
609 gst_caps_replace (&caps, NULL);
615 gst_gl_overlay_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
616 GstGLMemory * out_tex)
618 GstGLOverlay *overlay = GST_GL_OVERLAY (filter);
620 if (overlay->location_has_changed) {
621 if (overlay->image_memory) {
622 gst_memory_unref ((GstMemory *) overlay->image_memory);
623 overlay->image_memory = NULL;
626 if (!load_file (overlay))
629 overlay->location_has_changed = FALSE;
632 gst_gl_filter_render_to_target (filter, in_tex, out_tex,
633 gst_gl_overlay_callback, overlay);
639 gst_gl_overlay_before_transform (GstBaseTransform * trans, GstBuffer * outbuf)
641 GstClockTime stream_time;
643 stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
644 GST_BUFFER_TIMESTAMP (outbuf));
646 if (GST_CLOCK_TIME_IS_VALID (stream_time))
647 gst_object_sync_values (GST_OBJECT (trans), stream_time);
651 user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
653 g_warning ("%s\n", warning_msg);
657 gst_gl_overlay_load_jpeg (GstGLOverlay * overlay, FILE * fp)
659 GstGLBaseMemoryAllocator *mem_allocator;
660 GstGLVideoAllocationParams *params;
662 GstVideoAlignment v_align;
664 struct jpeg_decompress_struct cinfo;
665 struct jpeg_error_mgr jerr;
669 jpeg_create_decompress (&cinfo);
670 cinfo.err = jpeg_std_error (&jerr);
671 jpeg_stdio_src (&cinfo, fp);
672 jpeg_read_header (&cinfo, TRUE);
673 jpeg_start_decompress (&cinfo);
674 overlay->image_width = cinfo.image_width;
675 overlay->image_height = cinfo.image_height;
677 if (cinfo.num_components == 1)
678 gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_Y444,
679 overlay->image_width, overlay->image_height);
681 gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGB,
682 overlay->image_width, overlay->image_height);
684 gst_video_alignment_reset (&v_align);
685 v_align.stride_align[0] = 32 - 1;
686 gst_video_info_align (&v_info, &v_align);
689 GST_GL_BASE_MEMORY_ALLOCATOR (gst_gl_memory_allocator_get_default
690 (GST_GL_BASE_FILTER (overlay)->context));
692 gst_gl_video_allocation_params_new (GST_GL_BASE_FILTER (overlay)->context,
693 NULL, &v_info, 0, &v_align, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA);
694 overlay->image_memory = (GstGLMemory *)
695 gst_gl_base_memory_alloc (mem_allocator,
696 (GstGLAllocationParams *) params);
697 gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
698 gst_object_unref (mem_allocator);
700 if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info,
702 GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("failed to map memory"),
703 ("File: %s", overlay->location));
707 for (i = 0; i < overlay->image_height; ++i) {
708 j = map_info.data + v_info.stride[0] * i;
709 jpeg_read_scanlines (&cinfo, &j, 1);
711 jpeg_finish_decompress (&cinfo);
712 jpeg_destroy_decompress (&cinfo);
713 gst_memory_unmap ((GstMemory *) overlay->image_memory, &map_info);
719 gst_gl_overlay_load_png (GstGLOverlay * overlay, FILE * fp)
721 GstGLBaseMemoryAllocator *mem_allocator;
722 GstGLVideoAllocationParams *params;
728 png_uint_32 width = 0;
729 png_uint_32 height = 0;
732 gint interlace_type = 0;
734 guchar **rows = NULL;
739 if (!GST_GL_BASE_FILTER (overlay)->context)
742 /* Read magic number */
743 n_read = fread (magic, 1, sizeof (magic), fp);
744 if (n_read != sizeof (magic)) {
745 GST_ELEMENT_ERROR (overlay, STREAM, DECODE,
746 ("can't read PNG magic number"), ("File: %s", overlay->location));
750 /* Check for valid magic number */
751 if (png_sig_cmp (magic, 0, sizeof (magic))) {
752 GST_ELEMENT_ERROR (overlay, STREAM, DECODE,
753 ("not a valid PNG image"), ("File: %s", overlay->location));
757 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
759 if (png_ptr == NULL) {
760 GST_ELEMENT_ERROR (overlay, STREAM, DECODE,
761 ("failed to initialize the png_struct"), ("File: %s",
766 png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);
768 info_ptr = png_create_info_struct (png_ptr);
769 if (info_ptr == NULL) {
770 png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
771 GST_ELEMENT_ERROR (overlay, STREAM, DECODE,
772 ("failed to initialize the memory for image information"),
773 ("File: %s", overlay->location));
777 png_init_io (png_ptr, fp);
779 png_set_sig_bytes (png_ptr, sizeof (magic));
781 png_read_info (png_ptr, info_ptr);
783 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
784 &interlace_type, int_p_NULL, int_p_NULL);
786 if (color_type == PNG_COLOR_TYPE_RGB) {
788 png_set_filler (png_ptr, filler, PNG_FILLER_AFTER);
789 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
792 if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
793 png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
794 GST_ELEMENT_ERROR (overlay, STREAM, DECODE,
795 ("color type is not rgb"), ("File: %s", overlay->location));
799 overlay->image_width = width;
800 overlay->image_height = height;
802 gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, width, height);
804 GST_GL_BASE_MEMORY_ALLOCATOR (gst_gl_memory_allocator_get_default
805 (GST_GL_BASE_FILTER (overlay)->context));
807 gst_gl_video_allocation_params_new (GST_GL_BASE_FILTER (overlay)->context,
808 NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA);
809 overlay->image_memory = (GstGLMemory *)
810 gst_gl_base_memory_alloc (mem_allocator,
811 (GstGLAllocationParams *) params);
812 gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
813 gst_object_unref (mem_allocator);
815 if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info,
817 png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
818 GST_ELEMENT_ERROR (overlay, STREAM, DECODE,
819 ("failed to map memory"), ("File: %s", overlay->location));
822 rows = (guchar **) malloc (sizeof (guchar *) * height);
824 for (y = 0; y < height; ++y)
825 rows[y] = (guchar *) (map_info.data + y * width * 4);
827 png_read_image (png_ptr, rows);
830 gst_memory_unmap ((GstMemory *) overlay->image_memory, &map_info);
832 png_read_end (png_ptr, info_ptr);
833 png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);