summaryrefslogtreecommitdiff
path: root/clutter-gst/clutter-gst-video-sink.c
diff options
context:
space:
mode:
Diffstat (limited to 'clutter-gst/clutter-gst-video-sink.c')
-rw-r--r--clutter-gst/clutter-gst-video-sink.c330
1 files changed, 153 insertions, 177 deletions
diff --git a/clutter-gst/clutter-gst-video-sink.c b/clutter-gst/clutter-gst-video-sink.c
index 7d12b37..db9b254 100644
--- a/clutter-gst/clutter-gst-video-sink.c
+++ b/clutter-gst/clutter-gst-video-sink.c
@@ -197,10 +197,7 @@ typedef enum _ClutterGstRendererState
struct _ClutterGstVideoSinkPrivate
{
ClutterTexture *texture;
- CoglHandle u_tex;
- CoglHandle v_tex;
- CoglHandle program;
- CoglHandle shader;
+ CoglMaterial *material_template;
ClutterGstVideoFormat format;
gboolean bgr;
@@ -379,56 +376,19 @@ _string_array_to_char_array (char *dst,
}
#endif
-static void
-clutter_gst_video_sink_set_glsl_shader (ClutterGstVideoSink *sink,
- const gchar *shader_src)
-{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
-
- if (priv->program)
- {
- cogl_program_unref (priv->program);
- priv->program = NULL;
- }
-
- if (priv->shader)
- {
- cogl_handle_unref (priv->shader);
- priv->shader = NULL;
- }
-
- if (shader_src)
- {
- /* Create shader through COGL - necessary as we need to be able to set
- * integer uniform variables for multi-texturing.
- */
- priv->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
- cogl_shader_source (priv->shader, shader_src);
- cogl_shader_compile (priv->shader);
-
- priv->program = cogl_create_program ();
- cogl_program_attach_shader (priv->program, priv->shader);
- cogl_program_link (priv->program);
- }
-}
-
-/* some renderers don't need all the ClutterGstRenderer vtable */
-static void
-clutter_gst_dummy_init (ClutterGstVideoSink *sink)
-{
-}
-
-#ifdef CLUTTER_COGL_HAS_GL
static CoglHandle
-_create_arbfp_program (gchar *source)
+_create_cogl_program (const char *source)
{
CoglHandle shader;
CoglHandle program;
-
+
+ /* Create shader through Cogl - necessary as we need to be able to set
+ * integer uniform variables for multi-texturing.
+ */
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
cogl_shader_source (shader, source);
cogl_shader_compile (shader);
-
+
program = cogl_create_program ();
cogl_program_attach_shader (program, shader);
cogl_program_link (program);
@@ -437,13 +397,98 @@ _create_arbfp_program (gchar *source)
return program;
}
-#endif
+
+static void
+_create_template_material (ClutterGstVideoSink *sink,
+ const char *source,
+ gboolean set_uniforms,
+ int n_layers)
+{
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglMaterial *template;
+ int i;
+
+ if (priv->material_template)
+ cogl_object_unref (priv->material_template);
+
+ template = cogl_material_new ();
+
+ if (source)
+ {
+ CoglHandle program = _create_cogl_program (source);
+
+ if (set_uniforms)
+ {
+ unsigned int location;
+
+ cogl_program_use (program);
+
+ location = cogl_program_get_uniform_location (program, "ytex");
+ cogl_program_uniform_1i (location, 0);
+ if (n_layers > 1)
+ {
+ location = cogl_program_get_uniform_location (program, "utex");
+ cogl_program_uniform_1i (location, 1);
+ }
+ if (n_layers > 2)
+ {
+ location = cogl_program_get_uniform_location (program, "vtex");
+ cogl_program_uniform_1i (location, 2);
+ }
+
+ cogl_program_use (COGL_INVALID_HANDLE);
+ }
+
+ cogl_material_set_user_program (template, program);
+ cogl_handle_unref (program);
+ }
+
+ for (i = 0; i < n_layers; i++)
+ cogl_material_set_layer (template, i, COGL_INVALID_HANDLE);
+
+ priv->material_template = template;
+}
+
+static void
+_create_paint_material (ClutterGstVideoSink *sink,
+ CoglHandle tex0,
+ CoglHandle tex1,
+ CoglHandle tex2)
+{
+ ClutterGstVideoSinkPrivate *priv= sink->priv;
+ CoglMaterial *material = cogl_material_copy (priv->material_template);
+
+ if (tex0 != COGL_INVALID_HANDLE)
+ {
+ cogl_material_set_layer (material, 0, tex0);
+ cogl_handle_unref (tex0);
+ }
+ if (tex1 != COGL_INVALID_HANDLE)
+ {
+ cogl_material_set_layer (material, 1, tex1);
+ cogl_handle_unref (tex1);
+ }
+ if (tex2 != COGL_INVALID_HANDLE)
+ {
+ cogl_material_set_layer (material, 2, tex2);
+ cogl_handle_unref (tex2);
+ }
+
+ clutter_texture_set_cogl_material (priv->texture, material);
+ cogl_object_unref (material);
+}
static void
clutter_gst_dummy_deinit (ClutterGstVideoSink *sink)
{
}
+static void
+clutter_gst_rgb_init (ClutterGstVideoSink *sink)
+{
+ _create_template_material (sink, NULL, FALSE, 1);
+}
+
/*
* RGB 24 / BGR 24
*
@@ -454,18 +499,20 @@ static void
clutter_gst_rgb24_upload (ClutterGstVideoSink *sink,
GstBuffer *buffer)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
-
- clutter_texture_set_from_rgb_data (priv->texture,
- GST_BUFFER_DATA (buffer),
- FALSE,
- priv->width,
- priv->height,
- GST_ROUND_UP_4 (3 * priv->width),
- 3,
- priv->bgr ?
- CLUTTER_TEXTURE_RGB_FLAG_BGR : 0,
- NULL);
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglHandle tex =
+ cogl_texture_new_from_data (priv->width,
+ priv->height,
+ CLUTTER_GST_TEXTURE_FLAGS,
+ COGL_PIXEL_FORMAT_RGB_888,
+ COGL_PIXEL_FORMAT_RGB_888,
+ GST_ROUND_UP_4 (3 * priv->width),
+ GST_BUFFER_DATA (buffer));
+
+ _create_paint_material (sink,
+ tex,
+ COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
}
static ClutterGstRenderer rgb24_renderer =
@@ -474,7 +521,7 @@ static ClutterGstRenderer rgb24_renderer =
CLUTTER_GST_RGB24,
0,
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR),
- clutter_gst_dummy_init,
+ clutter_gst_rgb_init,
clutter_gst_dummy_deinit,
clutter_gst_rgb24_upload,
};
@@ -487,18 +534,20 @@ static void
clutter_gst_rgb32_upload (ClutterGstVideoSink *sink,
GstBuffer *buffer)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
-
- clutter_texture_set_from_rgb_data (priv->texture,
- GST_BUFFER_DATA (buffer),
- TRUE,
- priv->width,
- priv->height,
- GST_ROUND_UP_4 (4 * priv->width),
- 4,
- priv->bgr ?
- CLUTTER_TEXTURE_RGB_FLAG_BGR : 0,
- NULL);
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglHandle tex =
+ cogl_texture_new_from_data (priv->width,
+ priv->height,
+ CLUTTER_GST_TEXTURE_FLAGS,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ GST_ROUND_UP_4 (4 * priv->width),
+ GST_BUFFER_DATA (buffer));
+
+ _create_paint_material (sink,
+ tex,
+ COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
}
static ClutterGstRenderer rgb32_renderer =
@@ -507,7 +556,7 @@ static ClutterGstRenderer rgb32_renderer =
CLUTTER_GST_RGB32,
0,
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA),
- clutter_gst_dummy_init,
+ clutter_gst_rgb_init,
clutter_gst_dummy_deinit,
clutter_gst_rgb32_upload,
};
@@ -525,9 +574,7 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
ClutterGstVideoSinkPrivate *priv = sink->priv;
gint y_row_stride = GST_ROUND_UP_4 (priv->width);
gint uv_row_stride = GST_ROUND_UP_4 (priv->width / 2);
- CoglHandle y_tex, u_tex, v_tex, material;
-
- material = clutter_texture_get_cogl_material (priv->texture);
+ CoglHandle y_tex, u_tex, v_tex;
y_tex = cogl_texture_new_from_data (priv->width,
priv->height,
@@ -537,9 +584,6 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
y_row_stride,
GST_BUFFER_DATA (buffer));
- clutter_texture_set_cogl_texture (priv->texture, y_tex);
- cogl_handle_unref (y_tex);
-
u_tex = cogl_texture_new_from_data (priv->width / 2,
priv->height / 2,
CLUTTER_GST_TEXTURE_FLAGS,
@@ -549,9 +593,6 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
GST_BUFFER_DATA (buffer) +
(y_row_stride * priv->height));
- cogl_material_set_layer (material, 1, u_tex);
- cogl_handle_unref (u_tex);
-
v_tex = cogl_texture_new_from_data (priv->width / 2,
priv->height / 2,
CLUTTER_GST_TEXTURE_FLAGS,
@@ -562,37 +603,13 @@ clutter_gst_yv12_upload (ClutterGstVideoSink *sink,
+ (y_row_stride * priv->height)
+ (uv_row_stride * priv->height / 2));
- cogl_material_set_layer (material, 2, v_tex);
- cogl_handle_unref (v_tex);
+ _create_paint_material (sink, y_tex, u_tex, v_tex);
}
static void
clutter_gst_yv12_glsl_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
- GLint location;
- CoglMaterial *material;
-
- clutter_gst_video_sink_set_glsl_shader (sink, yv12_to_rgba_shader);
-
- cogl_program_use (priv->program);
- location = cogl_program_get_uniform_location (priv->program, "ytex");
- cogl_program_uniform_1i (location, 0);
- location = cogl_program_get_uniform_location (priv->program, "utex");
- cogl_program_uniform_1i (location, 1);
- location = cogl_program_get_uniform_location (priv->program, "vtex");
- cogl_program_uniform_1i (location, 2);
-
- cogl_program_use (COGL_INVALID_HANDLE);
-
- material = clutter_texture_get_cogl_material (priv->texture);
- cogl_material_set_user_program (material, priv->program);
-}
-
-static void
-clutter_gst_yv12_glsl_deinit (ClutterGstVideoSink *sink)
-{
- clutter_gst_video_sink_set_glsl_shader (sink, NULL);
+ _create_template_material (sink, yv12_to_rgba_shader, TRUE, 3);
}
@@ -603,7 +620,7 @@ static ClutterGstRenderer yv12_glsl_renderer =
CLUTTER_GST_GLSL | CLUTTER_GST_MULTI_TEXTURE,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")),
clutter_gst_yv12_glsl_init,
- clutter_gst_yv12_glsl_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_yv12_upload,
};
@@ -617,27 +634,12 @@ static ClutterGstRenderer yv12_glsl_renderer =
static void
clutter_gst_yv12_fp_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
- CoglMaterial *material;
- CoglHandle program;
-
- gchar *shader;
-
- shader = g_malloc(YV12_FP_SZ + 1);
+ char *shader = g_malloc (YV12_FP_SZ + 1);
_string_array_to_char_array (shader, YV12_fp);
- material = clutter_texture_get_cogl_material (priv->texture);
-
- program = _create_arbfp_program (shader);
- cogl_material_set_user_program (material, program);
- cogl_handle_unref (program);
+ _create_template_material (sink, shader, FALSE, 3);
- g_free(shader);
-}
-
-static void
-clutter_gst_yv12_fp_deinit (ClutterGstVideoSink *sink)
-{
+ g_free (shader);
}
static ClutterGstRenderer yv12_fp_renderer =
@@ -647,7 +649,7 @@ static ClutterGstRenderer yv12_fp_renderer =
CLUTTER_GST_FP | CLUTTER_GST_MULTI_TEXTURE,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")),
clutter_gst_yv12_fp_init,
- clutter_gst_yv12_fp_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_yv12_upload,
};
#endif
@@ -662,23 +664,7 @@ static ClutterGstRenderer yv12_fp_renderer =
static void
clutter_gst_i420_glsl_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
- GLint location;
- CoglMaterial *material;
-
- clutter_gst_video_sink_set_glsl_shader (sink, yv12_to_rgba_shader);
-
- cogl_program_use (priv->program);
- location = cogl_program_get_uniform_location (priv->program, "ytex");
- cogl_program_uniform_1i (location, 0);
- location = cogl_program_get_uniform_location (priv->program, "utex");
- cogl_program_uniform_1i (location, 1);
- location = cogl_program_get_uniform_location (priv->program, "vtex");
- cogl_program_uniform_1i (location, 2);
- cogl_program_use (COGL_INVALID_HANDLE);
-
- material = clutter_texture_get_cogl_material (priv->texture);
- cogl_material_set_user_program (material, priv->program);
+ _create_template_material (sink, yv12_to_rgba_shader, TRUE, 3);
}
static ClutterGstRenderer i420_glsl_renderer =
@@ -688,7 +674,7 @@ static ClutterGstRenderer i420_glsl_renderer =
CLUTTER_GST_GLSL | CLUTTER_GST_MULTI_TEXTURE,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")),
clutter_gst_i420_glsl_init,
- clutter_gst_yv12_glsl_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_yv12_upload,
};
@@ -703,19 +689,12 @@ static ClutterGstRenderer i420_glsl_renderer =
static void
clutter_gst_i420_fp_init (ClutterGstVideoSink *sink)
{
- ClutterGstVideoSinkPrivate *priv = sink->priv;
- CoglMaterial *material;
- CoglHandle program;
- gchar *shader;
-
- shader = g_malloc(I420_FP_SZ + 1);
+ char *shader = g_malloc(I420_FP_SZ + 1);
_string_array_to_char_array (shader, I420_fp);
- material = clutter_texture_get_cogl_material (priv->texture);
- program = _create_arbfp_program (shader);
- cogl_material_set_user_program (material, program);
- cogl_handle_unref (program);
- g_free(shader);
+ _create_template_material (sink, shader, FALSE, 3);
+
+ g_free (shader);
}
static ClutterGstRenderer i420_fp_renderer =
@@ -741,30 +720,27 @@ static ClutterGstRenderer i420_fp_renderer =
static void
clutter_gst_ayuv_glsl_init(ClutterGstVideoSink *sink)
{
- clutter_gst_video_sink_set_glsl_shader (sink, ayuv_to_rgba_shader);
-}
-
-static void
-clutter_gst_ayuv_glsl_deinit(ClutterGstVideoSink *sink)
-{
- clutter_gst_video_sink_set_glsl_shader (sink, NULL);
+ _create_template_material (sink, ayuv_to_rgba_shader, TRUE, 1);
}
static void
clutter_gst_ayuv_upload (ClutterGstVideoSink *sink,
GstBuffer *buffer)
{
- ClutterGstVideoSinkPrivate *priv= sink->priv;
-
- clutter_texture_set_from_rgb_data (priv->texture,
- GST_BUFFER_DATA (buffer),
- TRUE,
- priv->width,
- priv->height,
- GST_ROUND_UP_4 (4 * priv->width),
- 4,
- 0,
- NULL);
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ CoglHandle tex =
+ cogl_texture_new_from_data (priv->width,
+ priv->height,
+ CLUTTER_GST_TEXTURE_FLAGS,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ GST_ROUND_UP_4 (4 * priv->width),
+ GST_BUFFER_DATA (buffer));
+
+ _create_paint_material (sink,
+ tex,
+ COGL_INVALID_HANDLE,
+ COGL_INVALID_HANDLE);
}
static ClutterGstRenderer ayuv_glsl_renderer =
@@ -774,7 +750,7 @@ static ClutterGstRenderer ayuv_glsl_renderer =
CLUTTER_GST_GLSL,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")),
clutter_gst_ayuv_glsl_init,
- clutter_gst_ayuv_glsl_deinit,
+ clutter_gst_dummy_deinit,
clutter_gst_ayuv_upload,
};