static gboolean gst_gl_video_mixer_init_shader (GstGLMixer * mixer, GstCaps * outcaps) { GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer); if (video_mixer->shader) gst_gl_context_del_shader (GST_GL_BASE_MIXER (mixer)->context, video_mixer->shader); return gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context, video_mixer_v_src, video_mixer_f_src, &video_mixer->shader); }
static gboolean _draw_checker_background (GstGLVideoMixer * video_mixer) { GstGLMixer *mixer = GST_GL_MIXER (video_mixer); const GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable; gint attr_position_loc = 0; /* *INDENT-OFF* */ gfloat v_vertices[] = { -1.0,-1.0,-1.0f, 1.0,-1.0,-1.0f, 1.0, 1.0,-1.0f, -1.0, 1.0,-1.0f, }; /* *INDENT-ON* */ if (!video_mixer->checker) { if (!gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context, checker_v_src, checker_f_src, &video_mixer->checker)) return FALSE; } gst_gl_shader_use (video_mixer->checker); attr_position_loc = gst_gl_shader_get_attribute_location (video_mixer->checker, "a_position"); _init_vbo_indices (video_mixer); if (!video_mixer->checker_vbo) { gl->GenBuffers (1, &video_mixer->checker_vbo); gl->BindBuffer (GL_ARRAY_BUFFER, video_mixer->checker_vbo); gl->BufferData (GL_ARRAY_BUFFER, 4 * 3 * sizeof (GLfloat), v_vertices, GL_STATIC_DRAW); } else { gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, video_mixer->vbo_indices); gl->BindBuffer (GL_ARRAY_BUFFER, video_mixer->checker_vbo); } gl->VertexAttribPointer (attr_position_loc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof (GLfloat), (void *) 0); gl->EnableVertexAttribArray (attr_position_loc); gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); gl->DisableVertexAttribArray (attr_position_loc); gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); gl->BindBuffer (GL_ARRAY_BUFFER, 0); return TRUE; }
/* Convert to caps that can be accepted by this element... */ static GstCaps * get_converted_caps (GstGLStereoMix * mix, GstCaps * caps) { #if 0 GstGLContext *context = GST_GL_BASE_MIXER (mix)->context; GstCaps *result, *tmp; GST_LOG_OBJECT (mix, "Converting caps %" GST_PTR_FORMAT, caps); result = gst_gl_upload_transform_caps (context, GST_PAD_SINK, caps, NULL); tmp = result; GST_TRACE_OBJECT (mix, "transfer returned caps %" GST_PTR_FORMAT, tmp); result = gst_gl_color_convert_transform_caps (context, GST_PAD_SINK, tmp, NULL); gst_caps_unref (tmp); GST_TRACE_OBJECT (mix, "convert returned caps %" GST_PTR_FORMAT, tmp); tmp = result; result = gst_gl_view_convert_transform_caps (mix->viewconvert, GST_PAD_SINK, tmp, NULL); gst_caps_unref (tmp); #else GstCaps *result; GST_LOG_OBJECT (mix, "Converting caps %" GST_PTR_FORMAT, caps); result = gst_gl_view_convert_transform_caps (mix->viewconvert, GST_PAD_SINK, caps, NULL); #endif GST_LOG_OBJECT (mix, "returning caps %" GST_PTR_FORMAT, result); return result; }
static gboolean _draw_background (GstGLVideoMixer * video_mixer) { GstGLMixer *mixer = GST_GL_MIXER (video_mixer); const GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable; switch (video_mixer->background) { case GST_GL_VIDEO_MIXER_BACKGROUND_BLACK: gl->ClearColor (0.0, 0.0, 0.0, 1.0); gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); break; case GST_GL_VIDEO_MIXER_BACKGROUND_WHITE: gl->ClearColor (1.0, 1.0, 1.0, 1.0); gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); break; case GST_GL_VIDEO_MIXER_BACKGROUND_TRANSPARENT: gl->ClearColor (0.0, 0.0, 0.0, 0.0); gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); break; case GST_GL_VIDEO_MIXER_BACKGROUND_CHECKER: return _draw_checker_background (video_mixer); break; default: break; } return TRUE; }
/* Called after videoaggregator fixates our caps */ static gboolean _negotiated_caps (GstAggregator * agg, GstCaps * caps) { GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); GstGLStereoMix *mix = GST_GL_STEREO_MIX (vagg); GstCaps *in_caps; GST_LOG_OBJECT (mix, "Configured output caps %" GST_PTR_FORMAT, caps); if (GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps) if (!GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps)) return FALSE; /* Update the glview_convert output */ /* We can configure the view_converter now */ gst_gl_view_convert_set_context (mix->viewconvert, GST_GL_BASE_MIXER (mix)->context); in_caps = gst_video_info_to_caps (&mix->mix_info); gst_caps_set_features (in_caps, 0, gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); gst_caps_set_simple (in_caps, "texture-target", G_TYPE_STRING, GST_GL_TEXTURE_TARGET_2D_STR, NULL); gst_gl_view_convert_set_caps (mix->viewconvert, in_caps, caps); return TRUE; }
static gboolean _negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps) { GstGLBaseMixer *mix = GST_GL_BASE_MIXER (vagg); return gst_gl_base_mixer_do_bufferpool (mix, caps); }
static gboolean gst_gl_mosaic_init_shader (GstGLMixer * mixer, GstCaps * outcaps) { GstGLMosaic *mosaic = GST_GL_MOSAIC (mixer); g_clear_object (&mosaic->shader); //blocking call, wait the opengl thread has compiled the shader return gst_gl_context_gen_shader (GST_GL_BASE_MIXER (mixer)->context, mosaic_v_src, mosaic_f_src, &mosaic->shader); }
static void _init_vbo_indices (GstGLVideoMixer * mixer) { const GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable; if (!mixer->vbo_indices) { gl->GenBuffers (1, &mixer->vbo_indices); gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, mixer->vbo_indices); gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices, GL_STATIC_DRAW); } }
static gboolean _reset_pad_gl (GstAggregator * agg, GstAggregatorPad * aggpad, gpointer udata) { const GstGLFuncs *gl = GST_GL_BASE_MIXER (agg)->context->gl_vtable; GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (aggpad); if (pad->vertex_buffer) { gl->DeleteBuffers (1, &pad->vertex_buffer); pad->vertex_buffer = 0; } return FALSE; }
static gboolean gst_gl_mosaic_process_textures (GstGLMixer * mix, GstGLMemory * out_tex) { GstGLMosaic *mosaic = GST_GL_MOSAIC (mix); GstGLContext *context = GST_GL_BASE_MIXER (mix)->context; mosaic->out_tex = out_tex; gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _mosaic_render, mosaic); return TRUE; }
static void gst_gl_video_mixer_reset (GstGLMixer * mixer) { GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mixer); GstGLContext *context = GST_GL_BASE_MIXER (mixer)->context; video_mixer->input_frames = NULL; GST_DEBUG_OBJECT (mixer, "context:%p", context); if (video_mixer->shader) gst_gl_context_del_shader (context, video_mixer->shader); video_mixer->shader = NULL; if (video_mixer->checker) gst_gl_context_del_shader (context, video_mixer->checker); video_mixer->checker = NULL; if (GST_GL_BASE_MIXER (mixer)->context) gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _reset_gl, mixer); }
static gboolean gst_gl_base_mixer_src_query (GstAggregator * agg, GstQuery * query) { gboolean res = FALSE; GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg); GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONTEXT: { const gchar *context_type; GstContext *context, *old_context; res = gst_gl_handle_context_query ((GstElement *) mix, query, &mix->display, &mix->priv->other_context); if (mix->display) gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api); gst_query_parse_context_type (query, &context_type); if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("gst.gl.local_context", FALSE); s = gst_context_writable_structure (context); gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, mix->context, NULL); gst_query_set_context (query, context); gst_context_unref (context); res = mix->context != NULL; } GST_LOG_OBJECT (mix, "context query of type %s %i", context_type, res); if (res) return res; break; } default: break; } return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query); }
static void gst_gl_base_mixer_set_context (GstElement * element, GstContext * context) { GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element); GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix); gst_gl_handle_set_context (element, context, &mix->display, &mix->priv->other_context); if (mix->display) gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api); GST_ELEMENT_CLASS (parent_class)->set_context (element, context); }
static void gst_gl_base_mixer_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstGLBaseMixer *mixer = GST_GL_BASE_MIXER (object); switch (prop_id) { case PROP_CONTEXT: g_value_set_object (value, mixer->context); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean gst_gl_video_mixer_process_textures (GstGLMixer * mix, GPtrArray * frames, guint out_tex) { GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mix); video_mixer->input_frames = frames; gst_gl_context_use_fbo_v2 (GST_GL_BASE_MIXER (mix)->context, GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR (mix)->info), GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR (mix)->info), mix->fbo, mix->depthbuffer, out_tex, gst_gl_video_mixer_callback, (gpointer) video_mixer); return TRUE; }
static GstStateChangeReturn gst_gl_base_mixer_change_state (GstElement * element, GstStateChange transition) { GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element); GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GST_DEBUG_OBJECT (mix, "changing state: %s => %s", gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_gl_ensure_element_data (element, &mix->display, &mix->priv->other_context)) return GST_STATE_CHANGE_FAILURE; gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: if (mix->priv->other_context) { gst_object_unref (mix->priv->other_context); mix->priv->other_context = NULL; } if (mix->display) { gst_object_unref (mix->display); mix->display = NULL; } break; default: break; } return ret; }
static void _reset_gl (GstGLContext * context, GstGLVideoMixer * video_mixer) { const GstGLFuncs *gl = GST_GL_BASE_MIXER (video_mixer)->context->gl_vtable; if (video_mixer->vao) { gl->DeleteVertexArrays (1, &video_mixer->vao); video_mixer->vao = 0; } if (video_mixer->vbo_indices) { gl->DeleteBuffers (1, &video_mixer->vbo_indices); video_mixer->vbo_indices = 0; } gst_aggregator_iterate_sinkpads (GST_AGGREGATOR (video_mixer), _reset_pad_gl, NULL); }
static gboolean gst_gl_base_mixer_src_activate_mode (GstAggregator * aggregator, GstPadMode mode, gboolean active) { GstGLBaseMixer *mix; gboolean result = FALSE; mix = GST_GL_BASE_MIXER (aggregator); switch (mode) { case GST_PAD_MODE_PUSH: case GST_PAD_MODE_PULL: result = gst_gl_base_mixer_activate (mix, active); break; default: result = TRUE; break; } return result; }
static gboolean gst_gl_base_mixer_stop (GstAggregator * agg) { GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg); if (mix->priv->query) { gst_query_unref (mix->priv->query); mix->priv->query = NULL; } if (mix->priv->pool) { gst_object_unref (mix->priv->pool); mix->priv->pool = NULL; } if (mix->context) { gst_object_unref (mix->context); mix->context = NULL; } gst_gl_base_mixer_reset (mix); return TRUE; }
/* opengl scene, params: input texture (not the output mixer->texture) */ static void gst_gl_video_mixer_callback (gpointer stuff) { GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (stuff); GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (stuff); GstGLMixer *mixer = GST_GL_MIXER (video_mixer); GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable; GLint attr_position_loc = 0; GLint attr_texture_loc = 0; guint out_width, out_height; guint count = 0; out_width = GST_VIDEO_INFO_WIDTH (&vagg->info); out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info); gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context); gl->BindTexture (GL_TEXTURE_2D, 0); gl->Disable (GL_DEPTH_TEST); gl->Disable (GL_CULL_FACE); if (gl->GenVertexArrays) { if (!video_mixer->vao) gl->GenVertexArrays (1, &video_mixer->vao); gl->BindVertexArray (video_mixer->vao); } if (!_draw_background (video_mixer)) return; gst_gl_shader_use (video_mixer->shader); attr_position_loc = gst_gl_shader_get_attribute_location (video_mixer->shader, "a_position"); attr_texture_loc = gst_gl_shader_get_attribute_location (video_mixer->shader, "a_texCoord"); gl->Enable (GL_BLEND); while (count < video_mixer->input_frames->len) { GstGLMixerFrameData *frame; GstGLVideoMixerPad *pad; GstVideoInfo *v_info; guint in_tex; guint in_width, in_height; /* *INDENT-OFF* */ gfloat v_vertices[] = { -1.0,-1.0,-1.0f, 0.0f, 0.0f, 1.0,-1.0,-1.0f, 1.0f, 0.0f, 1.0, 1.0,-1.0f, 1.0f, 1.0f, -1.0, 1.0,-1.0f, 0.0f, 1.0f, }; /* *INDENT-ON* */ frame = g_ptr_array_index (video_mixer->input_frames, count); if (!frame) { GST_DEBUG ("skipping texture, null frame"); count++; continue; } pad = (GstGLVideoMixerPad *) frame->pad; v_info = &GST_VIDEO_AGGREGATOR_PAD (pad)->info; in_width = GST_VIDEO_INFO_WIDTH (v_info); in_height = GST_VIDEO_INFO_HEIGHT (v_info); if (!frame->texture || in_width <= 0 || in_height <= 0 || pad->alpha == 0.0f) { GST_DEBUG ("skipping texture:%u frame:%p width:%u height:%u alpha:%f", frame->texture, frame, in_width, in_height, pad->alpha); count++; continue; } in_tex = frame->texture; _init_vbo_indices (video_mixer); if (pad->geometry_change || !pad->vertex_buffer) { gint pad_width, pad_height; gfloat w, h; _mixer_pad_get_output_size (video_mixer, pad, &pad_width, &pad_height); w = ((gfloat) pad_width / (gfloat) out_width); h = ((gfloat) pad_height / (gfloat) out_height); /* top-left */ v_vertices[0] = v_vertices[15] = 2.0f * (gfloat) pad->xpos / (gfloat) out_width - 1.0f; /* bottom-left */ v_vertices[1] = v_vertices[6] = 2.0f * (gfloat) pad->ypos / (gfloat) out_height - 1.0f; /* top-right */ v_vertices[5] = v_vertices[10] = v_vertices[0] + 2.0f * w; /* bottom-right */ v_vertices[11] = v_vertices[16] = v_vertices[1] + 2.0f * h; GST_TRACE ("processing texture:%u dimensions:%ux%u, at %f,%f %fx%f with " "alpha:%f", in_tex, in_width, in_height, v_vertices[0], v_vertices[1], v_vertices[5], v_vertices[11], pad->alpha); if (!pad->vertex_buffer) gl->GenBuffers (1, &pad->vertex_buffer); gl->BindBuffer (GL_ARRAY_BUFFER, pad->vertex_buffer); gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), v_vertices, GL_STATIC_DRAW); pad->geometry_change = FALSE; } else { gl->BindBuffer (GL_ARRAY_BUFFER, pad->vertex_buffer); } gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, video_mixer->vbo_indices); gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl->BlendEquation (GL_FUNC_ADD); gl->ActiveTexture (GL_TEXTURE0); gl->BindTexture (GL_TEXTURE_2D, in_tex); gst_gl_shader_set_uniform_1i (video_mixer->shader, "texture", 0); gst_gl_shader_set_uniform_1f (video_mixer->shader, "alpha", pad->alpha); gl->EnableVertexAttribArray (attr_position_loc); gl->EnableVertexAttribArray (attr_texture_loc); gl->VertexAttribPointer (attr_position_loc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), (void *) 0); gl->VertexAttribPointer (attr_texture_loc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); ++count; } gl->DisableVertexAttribArray (attr_position_loc); gl->DisableVertexAttribArray (attr_texture_loc); if (gl->GenVertexArrays) gl->BindVertexArray (0); gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); gl->BindBuffer (GL_ARRAY_BUFFER, 0); gl->BindTexture (GL_TEXTURE_2D, 0); gl->Disable (GL_BLEND); gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context); }
/* opengl scene, params: input texture (not the output mixer->texture) */ static gboolean gst_gl_mosaic_callback (gpointer stuff) { GstGLMosaic *mosaic = GST_GL_MOSAIC (stuff); GstGLMixer *mixer = GST_GL_MIXER (mosaic); GstGLFuncs *gl = GST_GL_BASE_MIXER (mixer)->context->gl_vtable; GList *walk; static GLfloat xrot = 0; static GLfloat yrot = 0; static GLfloat zrot = 0; GLint attr_position_loc = 0; GLint attr_texture_loc = 0; const GLfloat matrix[] = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; guint count = 0; gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context); gl->BindTexture (GL_TEXTURE_2D, 0); gl->Enable (GL_DEPTH_TEST); gl->ClearColor (0.0, 0.0, 0.0, 0.0); gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gst_gl_shader_use (mosaic->shader); attr_position_loc = gst_gl_shader_get_attribute_location (mosaic->shader, "a_position"); attr_texture_loc = gst_gl_shader_get_attribute_location (mosaic->shader, "a_texCoord"); GST_OBJECT_LOCK (mosaic); walk = GST_ELEMENT (mosaic)->sinkpads; while (walk) { GstGLMixerPad *pad = walk->data; /* *INDENT-OFF* */ gfloat v_vertices[] = { /* front face */ 1.0f, 1.0f,-1.0f, 1.0f, 0.0f, 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, /* right face */ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, /* left face */ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, -1.0f,-1.0f, 1.0f, 0.0f, 0.0f, /* top face */ 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, -1.0f,-1.0f, 1.0f, 0.0f, 0.0f, -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, /* bottom face */ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, /* back face */ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 1.0f }; /* *INDENT-ON* */ guint in_tex; guint width, height; in_tex = pad->current_texture; width = GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR_PAD (pad)->info); height = GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR_PAD (pad)->info); if (!in_tex || width <= 0 || height <= 0) { GST_DEBUG ("skipping texture:%u pad:%p width:%u height %u", in_tex, pad, width, height); count++; walk = g_list_next (walk); continue; } GST_TRACE ("processing texture:%u dimensions:%ux%u", in_tex, width, height); gl->VertexAttribPointer (attr_position_loc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &v_vertices[5 * 4 * count]); gl->VertexAttribPointer (attr_texture_loc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &v_vertices[5 * 4 * count + 3]); gl->EnableVertexAttribArray (attr_position_loc); gl->EnableVertexAttribArray (attr_texture_loc); gl->ActiveTexture (GL_TEXTURE0); gl->BindTexture (GL_TEXTURE_2D, in_tex); gst_gl_shader_set_uniform_1i (mosaic->shader, "s_texture", 0); gst_gl_shader_set_uniform_1f (mosaic->shader, "xrot_degree", xrot); gst_gl_shader_set_uniform_1f (mosaic->shader, "yrot_degree", yrot); gst_gl_shader_set_uniform_1f (mosaic->shader, "zrot_degree", zrot); gst_gl_shader_set_uniform_matrix_4fv (mosaic->shader, "u_matrix", 1, GL_FALSE, matrix); gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); ++count; walk = g_list_next (walk); } GST_OBJECT_UNLOCK (mosaic); gl->DisableVertexAttribArray (attr_position_loc); gl->DisableVertexAttribArray (attr_texture_loc); gl->BindTexture (GL_TEXTURE_2D, 0); gl->Disable (GL_DEPTH_TEST); gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context); xrot += 0.6f; yrot += 0.4f; zrot += 0.8f; return TRUE; }
static gboolean gst_gl_base_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad, GstQuery * query) { gboolean ret = FALSE; GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg); GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix); GstGLBaseMixerPad *pad = GST_GL_BASE_MIXER_PAD (bpad); GST_TRACE ("QUERY %" GST_PTR_FORMAT, query); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ALLOCATION: { GstQuery *decide_query = NULL; GST_OBJECT_LOCK (mix); if (G_UNLIKELY (!mix->priv->negotiated)) { GST_DEBUG_OBJECT (mix, "not negotiated yet, can't answer ALLOCATION query"); GST_OBJECT_UNLOCK (mix); return FALSE; } if ((decide_query = mix->priv->query)) gst_query_ref (decide_query); GST_OBJECT_UNLOCK (mix); GST_DEBUG_OBJECT (mix, "calling propose allocation with query %" GST_PTR_FORMAT, decide_query); /* pass the query to the propose_allocation vmethod if any */ if (mix_class->propose_allocation) ret = mix_class->propose_allocation (mix, pad, decide_query, query); else ret = FALSE; if (decide_query) gst_query_unref (decide_query); GST_DEBUG_OBJECT (mix, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query); return ret; } case GST_QUERY_CONTEXT: { const gchar *context_type; GstContext *context, *old_context; ret = gst_gl_handle_context_query ((GstElement *) mix, query, &mix->display, &mix->priv->other_context); if (mix->display) gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api); gst_query_parse_context_type (query, &context_type); if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("gst.gl.local_context", FALSE); s = gst_context_writable_structure (context); gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, mix->context, NULL); gst_query_set_context (query, context); gst_context_unref (context); ret = mix->context != NULL; } GST_LOG_OBJECT (mix, "context query of type %s %i", context_type, ret); if (ret) return ret; break; } default: break; } return GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, bpad, query);; }