Add broken gst video widget

This commit is contained in:
Matthew Allum 2005-04-26 08:56:53 +00:00
parent 298f878086
commit 26decbdb97
17 changed files with 846 additions and 258 deletions

View File

@ -1,3 +1,31 @@
2005-04-26 mallum,,, <mallum@openedhand.com>
* clutter/Makefile.am:
* clutter/cltr-core.c: (cltr_init):
* clutter/cltr-events.c: (cltr_events_init), (cltr_main_loop):
* clutter/cltr-photo-grid.c:
* clutter/cltr-private.h:
* clutter/cltr-scratch.c: (cltr_scratch_handle_xevent),
(cltr_scratch_paint):
* clutter/cltr-texture.c: (cltr_texture_render_to_gl_quad),
(init_tiles), (cltr_texture_unrealize), (cltr_texture_realize),
(cltr_texture_new), (cltr_texture_no_tile_new),
(cltr_texture_get_pixbuf):
* clutter/cltr-texture.h:
* clutter/cltr-video.c:
* clutter/cltr-video.h:
* clutter/cltr-widget.c: (cltr_widget_queue_paint):
* clutter/cltr.h:
* examples/Makefile.am:
* examples/player.c:
* gst/cltrimagesink.c: (gst_cltrimagesink_fixate),
(gst_cltrimagesink_getcaps), (gst_cltrimagesink_sink_link),
(gst_cltrimagesink_change_state), (gst_cltrimagesink_chain),
(gst_cltrimagesink_set_property), (gst_cltrimagesink_get_property),
(gst_cltrimagesink_finalize), (gst_cltrimagesink_class_init):
* gst/cltrimagesink.h:
Initial go at very hacky gst video widget
2005-04-22 mallum,,, <mallum@openedhand.com>
* clutter/Makefile.am:

View File

@ -7,6 +7,7 @@ source_h = pixbuf.h util.h fonts.h \
cltr-widget.h \
cltr-window.h \
cltr-photo-grid.h \
cltr-video.h \
cltr-list.h \
cltr-overlay.h \
cltr-button.h \
@ -20,16 +21,17 @@ source_c = pixbuf.c util.c fonts.c \
cltr-events.c \
cltr-window.c \
cltr-photo-grid.c \
cltr-video.c \
cltr-list.c \
cltr-overlay.c \
cltr-button.c \
cltr-scratch.c
AM_CFLAGS = @GCC_FLAGS@ @CLTR_CFLAGS@
AM_CFLAGS = @GCC_FLAGS@ @CLTR_CFLAGS@ $(GST_CFLAGS) $(GCONF_CFLAGS)
lib_LTLIBRARIES = libclutter.la
libclutter_la_SOURCES = $(source_c) $(source_h)
libclutter_la_LIBADD = @CLTR_LIBS@
libclutter_la_LIBADD = @CLTR_LIBS@ $(GST_LIBS) $(GCONF_LIBS)
# http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91
# current : revision : age

View File

@ -34,6 +34,8 @@ cltr_init(int *argc, char ***argv)
XVisualInfo *vinfo;
gst_init (argc, argv);
if (!g_thread_supported ())
g_thread_init (NULL);
// XInitThreads ();

View File

@ -137,7 +137,7 @@ cltr_events_init()
g_source_attach (source, gmain_context);
g_source_unref (source);
ctx->internal_event_q = g_queue_new();
ctx->internal_event_q = g_async_queue_new();
}
void
@ -155,12 +155,12 @@ cltr_main_loop()
while (TRUE)
{
if (!g_queue_is_empty (ctx->internal_event_q))
if (g_async_queue_length (ctx->internal_event_q))
{
CltrWindow *win = CLTR_WINDOW(ctx->window);
/* Empty the queue */
while (g_queue_pop_head(ctx->internal_event_q) != NULL) ;
while (g_async_queue_try_pop(ctx->internal_event_q) != NULL) ;
/* Repaint everything visible from window down - URG.
* GL workings make it difficult to paint single part with

View File

@ -22,7 +22,7 @@
*/
#define FPS_TO_TIMEOUT(t) (1000/(t))
struct CltrPhotoGridCell
{

View File

@ -65,11 +65,13 @@ struct ClutterMainContext
GLXContext gl_context;
CltrWidget *window;
GQueue *internal_event_q;
GAsyncQueue *internal_event_q;
};
ClutterMainContext CltrCntx;
#define CLTR_CONTEXT() &CltrCntx
#define FPS_TO_TIMEOUT(t) (1000/(t))
#endif

View File

@ -67,7 +67,7 @@ cltr_scratch_handle_xevent (CltrWidget *widget, XEvent *xev)
}
static void
cltr_scratch_paint(CltrWidget *widget)
cltr_scratch_paint_old(CltrWidget *widget)
{
CltrScratch *scratch = CLTR_SCRATCH(widget);
@ -120,8 +120,10 @@ cltr_scratch_paint(CltrWidget *widget)
static void
cltr_scratch_paint_old(CltrWidget *widget)
cltr_scratch_paint(CltrWidget *widget)
{
CltrScratch *scratch = CLTR_SCRATCH(widget);
glPushMatrix();
CLTR_MARK();
@ -136,6 +138,15 @@ cltr_scratch_paint_old(CltrWidget *widget)
widget->x + widget->width,
widget->y + widget->height);
glEnable(GL_TEXTURE_2D);
cltr_texture_render_to_gl_quad(scratch->tex,
widget->x,
widget->y,
widget->x + widget->width ,
widget->y + widget->height);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);

View File

@ -32,8 +32,8 @@ cltr_texture_render_to_gl_quad(CltrTexture *texture,
int x2,
int y2)
{
int qx1, qx2, qy1, qy2;
int qwidth, qheight;
int qx1 = 0, qx2 = 0, qy1 = 0, qy2 = 0;
int qwidth = 0, qheight = 0;
int x, y, i =0, lastx = 0, lasty = 0;
float tx, ty;
@ -43,6 +43,29 @@ cltr_texture_render_to_gl_quad(CltrTexture *texture,
if (texture->tiles == NULL)
cltr_texture_realize(texture);
if (!texture->tiled)
{
glBindTexture(GL_TEXTURE_2D, texture->tiles[0]);
tx = (float) texture->pixb->width / texture->width;
ty = (float) texture->pixb->height / texture->height;
qx1 = x1;
qx2 = x2;
qy1 = y1;
qy2 = y2;
glBegin (GL_QUADS);
glTexCoord2f (tx, ty); glVertex2i (qx2, qy2);
glTexCoord2f (0, ty); glVertex2i (qx1, qy2);
glTexCoord2f (0, 0); glVertex2i (qx1, qy1);
glTexCoord2f (tx, 0); glVertex2i (qx2, qy1);
glEnd ();
return;
}
for (x=0; x < texture->n_x_tiles; x++)
{
lasty = 0;
@ -239,10 +262,15 @@ cltr_texture_unrealize(CltrTexture *texture)
if (texture->tiles == NULL)
return;
glDeleteTextures(texture->n_x_tiles * texture->n_y_tiles, texture->tiles);
if (!texture->tiled)
glDeleteTextures(1, texture->tiles);
else
glDeleteTextures(texture->n_x_tiles * texture->n_y_tiles, texture->tiles);
g_free(texture->tiles);
texture->tiles = NULL;
}
void
@ -250,8 +278,41 @@ cltr_texture_realize(CltrTexture *texture)
{
int x, y, i = 0;
texture->tiles = g_new (GLuint, texture->n_x_tiles * texture->n_y_tiles);
glGenTextures (texture->n_x_tiles * texture->n_y_tiles, texture->tiles);
if (!texture->tiled)
{
if (!texture->tiles)
{
texture->tiles = g_new (GLuint, 1);
glGenTextures (1, texture->tiles);
}
glBindTexture(GL_TEXTURE_2D, texture->tiles[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, /*GL_COMPRESSED_RGBA_ARB*/ GL_RGBA,
texture->width,
texture->height,
0, GL_RGBA,
GL_UNSIGNED_INT_8_8_8_8,
NULL);
CLTR_GLERR();
cltr_texture_sync_pixbuf(texture);
return;
}
if (!texture->tiles)
{
texture->tiles = g_new (GLuint, texture->n_x_tiles * texture->n_y_tiles);
glGenTextures (texture->n_x_tiles * texture->n_y_tiles, texture->tiles);
}
for (x=0; x < texture->n_x_tiles; x++)
for (y=0; y < texture->n_y_tiles; y++)
@ -259,41 +320,40 @@ cltr_texture_realize(CltrTexture *texture)
Pixbuf *pixtmp;
int src_h, src_w;
src_w = texture->tile_x_size[x];
src_h = texture->tile_y_size[y];
/*
CLTR_DBG("%i+%i, %ix%i to %ix%i, waste %ix%i",
texture->tile_x_position[x],
texture->tile_y_position[y],
texture->tile_x_size[x],
texture->tile_y_size[y],
texture->width,
texture->height,
texture->tile_x_waste[x],
texture->tile_y_waste[y]);
CLTR_DBG("%i+%i, %ix%i to %ix%i, waste %ix%i",
texture->tile_x_position[x],
texture->tile_y_position[y],
texture->tile_x_size[x],
texture->tile_y_size[y],
texture->width,
texture->height,
texture->tile_x_waste[x],
texture->tile_y_waste[y]);
*/
/* Only break the pixbuf up if we have multiple tiles */
if (texture->n_x_tiles > 1 && texture->n_y_tiles >1)
{
pixtmp = pixbuf_new(texture->tile_x_size[x],
texture->tile_y_size[y]);
pixbuf_copy(texture->pixb,
pixtmp,
texture->tile_x_position[x],
texture->tile_y_position[y],
texture->tile_x_size[x],
texture->tile_y_size[y],
0,0);
}
else pixtmp = texture->pixb;
/* if (texture->n_x_tiles > 1 && texture->n_y_tiles >1) */
{
pixtmp = pixbuf_new(texture->tile_x_size[x],
texture->tile_y_size[y]);
pixbuf_copy(texture->pixb,
pixtmp,
texture->tile_x_position[x],
texture->tile_y_position[y],
texture->tile_x_size[x],
texture->tile_y_size[y],
0,0);
}
/* else pixtmp = texture->pixb; */
glBindTexture(GL_TEXTURE_2D, texture->tiles[i]);
CLTR_GLERR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
@ -311,12 +371,16 @@ cltr_texture_realize(CltrTexture *texture)
CLTR_GLERR();
if (pixtmp != texture->pixb)
pixbuf_unref(pixtmp);
CLTR_DBG("pixtmp is %ix%i texture %ix%i\n",
pixtmp->width, pixtmp->height,
texture->width, texture->height);
pixbuf_unref(pixtmp);
i++;
}
}
CltrTexture*
@ -324,24 +388,55 @@ cltr_texture_new(Pixbuf *pixb)
{
CltrTexture *texture;
CLTR_MARK();
texture = g_malloc0(sizeof(CltrTexture));
texture->width = pixb->width;
texture->height = pixb->height;
texture->tiled = TRUE;
/* maybe we should copy the pixbuf - a change to refed one would explode */
texture->pixb = pixb;
texture->mutex = g_mutex_new();
pixbuf_ref(pixb);
init_tiles (texture);
return texture;
}
CltrTexture*
cltr_texture_no_tile_new(Pixbuf *pixb)
{
CltrTexture *texture;
CLTR_MARK();
texture = g_malloc0(sizeof(CltrTexture));
texture->tiled = FALSE;
texture->width = next_p2(pixb->width);
texture->height = next_p2(pixb->height);
if (!can_create (texture->width, texture->height))
{
free(texture);
return NULL;
}
texture->pixb = pixb;
texture->mutex = g_mutex_new();
pixbuf_ref(pixb);
return texture;
}
Pixbuf*
cltr_texture_get_pixbuf(CltrTexture* texture)
{
@ -349,7 +444,62 @@ cltr_texture_get_pixbuf(CltrTexture* texture)
}
void
cltr_texture_resync_pixbuf(CltrTexture* texture)
cltr_texture_lock(CltrTexture* texture)
{
cltr_texture_unrealize(texture);
g_mutex_lock(texture->mutex);
}
void
cltr_texture_unlock(CltrTexture* texture)
{
g_mutex_unlock(texture->mutex);
}
void
cltr_texture_sync_pixbuf(CltrTexture* texture)
{
if (texture->tiled)
{
cltr_texture_realize(texture);
}
else
{
glBindTexture(GL_TEXTURE_2D, texture->tiles[0]);
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
texture->pixb->width,
texture->pixb->height,
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
texture->pixb->data);
}
}
/*
* This is a nasty hack to work round me not figuring out
* how to get RGBA data out of gstreamer in a format clutters
* GL setup can handle :(
*
* The good side is it probably speeds video playback up by
* avoiding copys of frame data.
*/
void
cltr_texture_force_rgb_data(CltrTexture *texture,
int width,
int height,
int *data)
{
if (texture->tiled)
return;
if (!texture->tiles)
cltr_texture_realize(texture);
glBindTexture(GL_TEXTURE_2D, texture->tiles[0]);
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
width,
height,
GL_RGB, GL_UNSIGNED_BYTE,
data);
}

View File

@ -3,7 +3,7 @@
#include "cltr.h"
typedef struct CltrTexture CltrTexture;
struct CltrTexture
{
@ -11,12 +11,16 @@ struct CltrTexture
int width, height;
gboolean tiled;
int n_x_tiles, n_y_tiles;
int *tile_x_position, *tile_x_size, *tile_x_waste;
int *tile_y_position, *tile_y_size, *tile_y_waste;
GLuint *tiles;
GMutex *mutex;
gint refcnt;
};
@ -24,6 +28,9 @@ struct CltrTexture
CltrTexture*
cltr_texture_new(Pixbuf *pixb);
CltrTexture*
cltr_texture_no_tile_new(Pixbuf *pixb);
void
cltr_texture_unrealize(CltrTexture *texture);
@ -41,7 +48,19 @@ Pixbuf*
cltr_texture_get_pixbuf(CltrTexture* texture);
void
cltr_texture_resync_pixbuf(CltrTexture* texture);
cltr_texture_lock(CltrTexture* texture);
void
cltr_texture_unlock(CltrTexture* texture);
void
cltr_texture_sync_pixbuf(CltrTexture* texture);
void
cltr_texture_force_rgb_data(CltrTexture *texture,
int width,
int height,
int *data);
#endif

425
clutter/cltr-video.c Normal file
View File

@ -0,0 +1,425 @@
#include "cltr-video.h"
#include "cltr-private.h"
struct CltrVideo
{
CltrWidget widget;
GstPlay *play;
GstElement *data_src, *video_sink, *audio_sink, *vis_element;
GAsyncQueue *queue;
int video_width, video_height;
CltrTexture *frame_texture;
};
static void
cltr_video_show(CltrWidget *widget);
static gboolean
cltr_video_handle_xevent (CltrWidget *widget, XEvent *xev);
static void
cltr_video_paint(CltrWidget *widget);
static gint64 length = 0; /* to go */
static void
cltr_video_print_tag (const GstTagList *list,
const gchar *tag,
gpointer unused)
{
gint i, count;
count = gst_tag_list_get_tag_size (list, tag);
for (i = 0; i < count; i++) {
gchar *str;
if (gst_tag_get_type (tag) == G_TYPE_STRING) {
if (!gst_tag_list_get_string_index (list, tag, i, &str))
g_assert_not_reached ();
} else {
str =
g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
}
if (i == 0) {
g_print ("%15s: %s\n", gst_tag_get_nick (tag), str);
} else {
g_print (" : %s\n", str);
}
g_free (str);
}
}
static void
cltr_video_got_found_tag (GstPlay *play,
GstElement *source,
GstTagList *tag_list,
CltrVideo *video)
{
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_FOUND_TAG;
signal->signal_data.found_tag.source = source;
signal->signal_data.found_tag.tag_list = gst_tag_list_copy (tag_list);
g_async_queue_push (video->queue, signal);
/* gst_tag_list_foreach (tag_list, cltr_video_print_tag, NULL); */
}
static void
cltr_video_got_time_tick (GstPlay *play,
gint64 time_nanos,
CltrVideo *video)
{
CltrVideoSignal *signal;
/*
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_FOUND_TAG;
signal->signal_data.found_tag.source = source;
signal->signal_data.found_tag.tag_list = gst_tag_list_copy (tag_list);
g_async_queue_push (video->queue, signal);
*/
g_print ("time tick %f\n", time_nanos / (float) GST_SECOND);
}
static void
cltr_video_got_stream_length (GstPlay *play,
gint64 length_nanos,
CltrVideo *video)
{
/*
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_VIDEO_SIZE;
signal->signal_data.video_size.width = width;
signal->signal_data.video_size.height = height;
g_async_queue_push (video->queue, signal);
*/
CLTR_DBG ("got length %" G_GUINT64_FORMAT "\n", length_nanos);
length = length_nanos;
}
static void
cltr_video_got_video_size (GstPlay *play,
gint width,
gint height,
CltrVideo *video)
{
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_VIDEO_SIZE;
signal->signal_data.video_size.width = width;
signal->signal_data.video_size.height = height;
g_async_queue_push (video->queue, signal);
}
static void
cltr_video_got_eos (GstPlay* play, CltrVideo *video)
{
CLTR_DBG ("End Of Stream\n");
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_EOS;
g_async_queue_push (video->queue, signal);
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
}
static gboolean
cltr_video_seek_timer (GstPlay * play)
{
gst_play_seek_to_time (play, length / 2);
return FALSE;
}
static void
caps_set (GObject *obj,
GParamSpec *pspec,
CltrVideo *video)
{
GstPad *pad = GST_PAD (obj);
GstStructure *s;
if (!GST_PAD_CAPS (pad))
return;
s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
if (s) {
const GValue *par;
if (!(gst_structure_get_double (s, "framerate", &bvw->priv->video_fps) &&
gst_structure_get_int (s, "width", &bvw->priv->video_width) &&
gst_structure_get_int (s, "height", &bvw->priv->video_height)))
return;
if ((par = gst_structure_get_value (s,
"pixel-aspect-ratio"))) {
gint num = gst_value_get_fraction_numerator (par),
den = gst_value_get_fraction_denominator (par);
if (num > den)
bvw->priv->video_width *= (gfloat) num / den;
else
bvw->priv->video_height *= (gfloat) den / num;
}
got_video_size (bvw->priv->play, bvw->priv->video_width,
bvw->priv->video_height, bvw);
}
*/
/* and disable ourselves */
//g_signal_handlers_disconnect_by_func (pad, caps_set, bvw);
}
CltrWidget*
cltr_video_new(int width, int height)
{
CltrVideo *video;
GError *error = NULL;
video = g_malloc0(sizeof(CltrVideo));
video->widget.width = width;
video->widget.height = height;
video->widget.show = cltr_video_show;
video->widget.paint = cltr_video_paint;
video->widget.xevent_handler = cltr_video_handle_xevent;
/* Creating the GstPlay object */
video->play = gst_play_new (&error);
if (error)
{
g_print ("Error: could not create play object:\n%s\n", error->message);
g_error_free (error);
return NULL;
}
/* Getting default audio and video plugins from GConf */
video->vis_element = gst_element_factory_make ("goom", "vis_element");
video->data_src = gst_element_factory_make ("gnomevfssrc", "source");
video->audio_sink = gst_gconf_get_default_audio_sink ();
if (!GST_IS_ELEMENT (video->audio_sink))
g_error ("Could not get default audio sink from GConf");
video->video_sink = gst_element_factory_make ("cltrimagesink", "cltr-output");
if (!GST_IS_ELEMENT (video->video_sink))
g_error ("Could not get clutter video sink");
video->queue = g_async_queue_new ();
gst_element_set(video->video_sink, "queue", video->queue, NULL);
/* Let's send them to GstPlay object */
if (!gst_play_set_audio_sink (video->play, video->audio_sink))
g_warning ("Could not set audio sink");
if (!gst_play_set_video_sink (video->play, video->video_sink))
g_warning ("Could not set video sink");
if (!gst_play_set_data_src (video->play, video->data_src))
g_warning ("Could not set data src");
if (!gst_play_set_visualization (video->play, video->vis_element))
g_warning ("Could not set visualisation");
/* Setting location we want to play */
/* Uncomment that line to get an XML dump of the pipeline */
/* gst_xml_write_file (GST_ELEMENT (play), stdout); */
g_signal_connect (G_OBJECT (video->play), "time_tick",
G_CALLBACK (cltr_video_got_time_tick), video);
g_signal_connect (G_OBJECT (video->play), "stream_length",
G_CALLBACK (cltr_video_got_stream_length), video);
g_signal_connect (G_OBJECT (video->play), "have_video_size",
G_CALLBACK (cltr_video_got_video_size), video);
g_signal_connect (G_OBJECT (video->play), "found_tag",
G_CALLBACK (cltr_video_got_found_tag), video);
g_signal_connect (G_OBJECT (video->play), "error",
G_CALLBACK (gst_element_default_error), NULL);
g_signal_connect (G_OBJECT (video->play),
"eos", G_CALLBACK (cltr_video_got_eos), video);
g_signal_connect (G_OBJECT (video->video_sink), "notify::caps",
G_CALLBACK (caps_set), video);
/*
g_object_set (G_OBJECT (video->play), "volume",
(gdouble) (1. * 0 / 100), NULL);
*/
/* gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY); */
return CLTR_WIDGET(video);
}
static gboolean
cltr_video_idler (CltrVideo *video)
{
gint queue_length;
CltrVideoSignal *signal;
signal = g_async_queue_try_pop (video->queue);
if (!signal)
return TRUE;
switch (signal->signal_id)
{
case CLTR_VIDEO_ASYNC_TEXTURE:
video->frame_texture = signal->signal_data.texture.ref;
/*
* we can actually grab the width and height from
* the textures pixbuf.
*/
cltr_widget_queue_paint(CLTR_WIDGET(video));
break;
case CLTR_VIDEO_ASYNC_VIDEO_SIZE:
video->video_width = signal->signal_data.video_size.width;
video->video_height = signal->signal_data.video_size.height;
break;
case CLTR_VIDEO_ASYNC_ERROR:
break;
case CLTR_VIDEO_ASYNC_FOUND_TAG:
break;
case CLTR_VIDEO_ASYNC_NOTIFY_STREAMINFO:
break;
case CLTR_VIDEO_ASYNC_EOS:
break;
case CLTR_VIDEO_ASYNC_BUFFERING:
break;
case CLTR_VIDEO_ASYNC_REDIRECT:
break;
}
g_free (signal);
return TRUE;
}
gboolean
cltr_video_set_source(CltrVideo *video, char *location)
{
if (!gst_play_set_location (video->play, location))
return FALSE;
return TRUE;
}
void
cltr_video_play(CltrVideo *video)
{
/* Change state to PLAYING */
if (gst_element_set_state (GST_ELEMENT (video->play),
GST_STATE_PLAYING) == GST_STATE_FAILURE)
g_error ("Could not set state to PLAYING");
g_timeout_add(FPS_TO_TIMEOUT(20), (GSourceFunc) cltr_video_idler, video);
}
void
cltr_video_pause(CltrVideo *video)
{
if (gst_element_set_state (GST_ELEMENT (video->play),
GST_STATE_PAUSED) == GST_STATE_FAILURE)
g_error ("Could not set state to PAUSED");
}
static void
cltr_video_show(CltrWidget *widget)
{
return;
}
static void
cltr_video_hide(CltrWidget *widget)
{
return;
}
static gboolean
cltr_video_handle_xevent (CltrWidget *widget, XEvent *xev)
{
CLTR_DBG("X Event");
return False;
}
static void
cltr_video_paint(CltrWidget *widget)
{
CltrVideo *video = CLTR_VIDEO(widget);
glPushMatrix();
if (video->frame_texture
&& video->video_height
&& video->video_width)
{
int dis_x, dis_y, dis_height, dis_width;
if (video->video_width > video->video_height)
{
dis_width = widget->width;
dis_height = ( video->video_height * widget->width )
/ video->video_width;
dis_y = (widget->height - dis_height)/2;
dis_x = 0;
}
glColor4f(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
cltr_texture_lock(video->frame_texture);
cltr_texture_render_to_gl_quad(video->frame_texture,
dis_x,
dis_y,
dis_x + dis_width,
dis_y + dis_height);
cltr_texture_unlock(video->frame_texture);
glDisable(GL_TEXTURE_2D);
}
glPopMatrix();
}

73
clutter/cltr-video.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef _HAVE_CLTR_VIDEO_H
#define _HAVE_CLTR_VIDEO_H
#include "cltr.h"
#include <gst/play/play.h>
#include <gst/gconf/gconf.h>
typedef struct CltrVideo CltrVideo;
/* Signals - cltrimagesink needs to deliver texture signals :/ */
enum {
CLTR_VIDEO_ASYNC_TEXTURE,
CLTR_VIDEO_ASYNC_VIDEO_SIZE,
CLTR_VIDEO_ASYNC_ERROR,
CLTR_VIDEO_ASYNC_FOUND_TAG,
CLTR_VIDEO_ASYNC_NOTIFY_STREAMINFO,
CLTR_VIDEO_ASYNC_EOS,
CLTR_VIDEO_ASYNC_BUFFERING,
CLTR_VIDEO_ASYNC_REDIRECT
};
typedef struct CltrVideoSignal
{
gint signal_id;
union
{
struct
{
gint width;
gint height;
} video_size;
struct
{
GstElement *element;
GError *error;
char *debug_message;
} error;
struct
{
GstElement *source;
GstTagList *tag_list;
} found_tag;
struct
{
gint percent;
} buffering;
struct
{
gchar *new_location;
} redirect;
struct
{
CltrTexture *ref;
} texture;
} signal_data;
}
CltrVideoSignal;
#define CLTR_VIDEO(w) ((CltrVideo*)(w))
CltrWidget*
cltr_video_new(int width, int height);
gboolean
cltr_video_set_source(CltrVideo *video, char *location);
void
cltr_video_play(CltrVideo *video);
#endif

View File

@ -101,7 +101,7 @@ cltr_widget_queue_paint(CltrWidget *widget)
{
ClutterMainContext *ctx = CLTR_CONTEXT();
g_queue_push_head (ctx->internal_event_q, (gpointer)widget);
g_async_queue_push (ctx->internal_event_q, (gpointer)widget);
}
gboolean

View File

@ -16,6 +16,8 @@
#include <glib.h>
#include <gst/gconf/gconf.h>
#include "pixbuf.h"
#include "fonts.h"
@ -34,6 +36,8 @@ typedef struct CltrRect
}
CltrRect;
typedef struct CltrTexture CltrTexture;
#define cltr_rect_x1(r) ((r).x)
#define cltr_rect_y1(r) ((r).y)
#define cltr_rect_x2(r) ((r).x + (r).width)
@ -52,5 +56,6 @@ CltrRect;
#include "cltr-overlay.h"
#include "cltr-button.h"
#include "cltr-photo-grid.h"
#include "cltr-video.h"
#endif

View File

@ -1,15 +1,19 @@
noinst_PROGRAMS = scratch photos player
scratch_SOURCES = scratch.c
scratch_CFLAGS = $(CLTR_CFLAGS)
scratch_CFLAGS = $(CLTR_CFLAGS) $(GST_CFLAGS) $(GCONF_CFLAGS)
scratch_LDFLAGS = \
$(CLTR_LIBS) \
$(GST_LIBS) \
$(GCONF_LIBS) \
$(top_builddir)/clutter/libclutter.la
photos_SOURCES = photos.c
photos_CFLAGS = $(CLTR_CFLAGS)
photos_CFLAGS = $(CLTR_CFLAGS) $(GST_CFLAGS) $(GCONF_CFLAGS)
photos_LDFLAGS = \
$(CLTR_LIBS) \
$(GST_LIBS) \
$(GCONF_LIBS) \
$(top_builddir)/clutter/libclutter.la
player_SOURCES = player.c

View File

@ -19,90 +19,11 @@
#include <clutter/cltr.h>
#include <gst/play/play.h>
#include <gst/gconf/gconf.h>
static GMainLoop *loop = NULL;
static gint64 length = 0;
static void
print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
{
gint i, count;
count = gst_tag_list_get_tag_size (list, tag);
for (i = 0; i < count; i++) {
gchar *str;
if (gst_tag_get_type (tag) == G_TYPE_STRING) {
if (!gst_tag_list_get_string_index (list, tag, i, &str))
g_assert_not_reached ();
} else {
str =
g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
}
if (i == 0) {
g_print ("%15s: %s\n", gst_tag_get_nick (tag), str);
} else {
g_print (" : %s\n", str);
}
g_free (str);
}
}
static void
got_found_tag (GstPlay * play, GstElement * source, GstTagList * tag_list)
{
gst_tag_list_foreach (tag_list, print_tag, NULL);
}
static void
got_time_tick (GstPlay * play, gint64 time_nanos)
{
g_print ("time tick %f\n", time_nanos / (float) GST_SECOND);
}
static void
got_stream_length (GstPlay * play, gint64 length_nanos)
{
g_print ("got length %" G_GUINT64_FORMAT "\n", length_nanos);
length = length_nanos;
}
static void
got_video_size (GstPlay * play, gint width, gint height)
{
g_print ("got video size %d, %d\n", width, height);
}
static void
got_eos (GstPlay * play)
{
g_print ("End Of Stream\n");
g_main_loop_quit (loop);
}
static gboolean
seek_timer (GstPlay * play)
{
gst_play_seek_to_time (play, length / 2);
return FALSE;
}
int
main (int argc, char *argv[])
{
GstPlay *play;
GstElement *data_src, *video_sink, *audio_sink, *vis_element;
GError *error = NULL;
CltrWidget *win, *video, *test;
CltrWidget *win;
/* Initing GStreamer library */
gst_init (&argc, &argv);
cltr_init (&argc, &argv);
if (argc != 2) {
@ -111,86 +32,22 @@ main (int argc, char *argv[])
}
win = cltr_window_new(800, 600);
video = cltr_video_new(800, 600);
cltr_video_set_source(CLTR_VIDEO(video), argv[1]);
cltr_widget_add_child(win, video, 0, 0);
test = cltr_scratch_new(300, 300);
cltr_widget_add_child(win, test, 100, 100);
cltr_widget_show_all(win);
loop = g_main_loop_new (NULL, FALSE);
/* Creating the GstPlay object */
play = gst_play_new (&error);
if (error) {
g_print ("Error: could not create play object:\n%s\n", error->message);
g_error_free (error);
return 1;
}
/* Getting default audio and video plugins from GConf */
vis_element = gst_element_factory_make ("goom", "vis_element");
data_src = gst_element_factory_make ("gnomevfssrc", "source");
audio_sink = gst_gconf_get_default_audio_sink ();
if (!GST_IS_ELEMENT (audio_sink))
g_error ("Could not get default audio sink from GConf");
/*
video_sink = gst_gconf_get_default_video_sink ();
if (!GST_IS_ELEMENT (video_sink))
g_error ("Could not get default video sink from GConf");
*/
video_sink = gst_element_factory_make ("cltrimagesink", "cltr-output");
gst_element_set(video_sink, "widget", win, NULL);
if (video_sink == NULL)
g_printf("sink NULL\n");
/* Let's send them to GstPlay object */
if (!gst_play_set_audio_sink (play, audio_sink))
g_warning ("Could not set audio sink");
if (!gst_play_set_video_sink (play, video_sink))
g_warning ("Could not set video sink");
if (!gst_play_set_data_src (play, data_src))
g_warning ("Could not set data src");
if (!gst_play_set_visualization (play, vis_element))
g_warning ("Could not set visualisation");
/* Setting location we want to play */
if (!gst_play_set_location (play, argv[1]))
g_warning ("Could not set location");
/* Uncomment that line to get an XML dump of the pipeline */
gst_xml_write_file (GST_ELEMENT (play), stdout);
g_signal_connect (G_OBJECT (play), "time_tick",
G_CALLBACK (got_time_tick), NULL);
g_signal_connect (G_OBJECT (play), "stream_length",
G_CALLBACK (got_stream_length), NULL);
g_signal_connect (G_OBJECT (play), "have_video_size",
G_CALLBACK (got_video_size), NULL);
g_signal_connect (G_OBJECT (play), "found_tag",
G_CALLBACK (got_found_tag), NULL);
g_signal_connect (G_OBJECT (play), "error",
G_CALLBACK (gst_element_default_error), NULL);
g_signal_connect (G_OBJECT (play), "eos", G_CALLBACK (got_eos), NULL);
/* Change state to PLAYING */
if (gst_element_set_state (GST_ELEMENT (play),
GST_STATE_PLAYING) == GST_STATE_FAILURE)
g_error ("Could not set state to PLAYING");
g_timeout_add (20000, (GSourceFunc) seek_timer, play);
cltr_video_play(CLTR_VIDEO(video));
cltr_main_loop();
// g_main_loop_run (loop);
g_print ("setting pipeline to ready\n");
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
/* unref
gst_object_unref (GST_OBJECT (play)); */
exit (0);
}

View File

@ -30,7 +30,7 @@
/* Debugging category */
#include <gst/gstinfo.h>
GST_DEBUG_CATEGORY_STATIC (gst_debug_cltrimagesink);
GST_DEBUG_CATEGORY_STATIC (gst_debug_cltrimagesink);
#define GST_CAT_DEFAULT gst_debug_cltrimagesink
@ -70,7 +70,7 @@ static guint gst_cltrimagesink_signals[LAST_SIGNAL] = { 0 };
enum
{
ARG_0,
ARG_WIDGET,
ARG_QUEUE,
ARG_SYNCHRONOUS,
ARG_SIGNAL_HANDOFFS
/* FILL ME */
@ -103,6 +103,15 @@ Element stuff
=================
*/
#define SWAP_4(x) ( ((x) << 24) | \
(((x) << 16) & 0x00ff0000) | \
(((x) << 8) & 0x0000ff00) | \
0x000000ff )
static GstCaps *
gst_cltrimagesink_fixate (GstPad *pad,
const GstCaps *caps)
@ -110,8 +119,6 @@ gst_cltrimagesink_fixate (GstPad *pad,
GstStructure *structure;
GstCaps *newcaps;
DBG("mark");
if (gst_caps_get_size (caps) > 1)
return NULL;
@ -153,9 +160,11 @@ gst_cltrimagesink_getcaps (GstPad * pad)
"bpp", G_TYPE_INT, 24,
"depth", G_TYPE_INT, 24,
"endianness", G_TYPE_INT, G_BIG_ENDIAN,
"red_mask", G_TYPE_INT, 0xff0000,
"green_mask", G_TYPE_INT, 0x00ff00,
"blue_mask", G_TYPE_INT, 0xff,
/*
"red_mask", G_TYPE_INT, 0xff0000,
"green_mask", G_TYPE_INT, 0x0000ff,
"blue_mask", G_TYPE_INT, 0x00ff00,
*/
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_DOUBLE_RANGE, 1.0, 100.0, NULL);
@ -172,8 +181,6 @@ gst_cltrimagesink_sink_link (GstPad * pad, const GstCaps * caps)
GstStructure *structure;
Pixbuf *pixb = NULL;
DBG("mark");
cltrimagesink = GST_CLTRIMAGESINK (gst_pad_get_parent (pad));
/*
@ -220,7 +227,7 @@ gst_cltrimagesink_sink_link (GstPad * pad, const GstCaps * caps)
GST_VIDEOSINK_HEIGHT (cltrimagesink));
/* Is this the right place ? */
cltrimagesink->texture = cltr_texture_new(pixb);
cltrimagesink->texture = cltr_texture_no_tile_new(pixb);
pixbuf_unref(pixb);
@ -249,7 +256,6 @@ gst_cltrimagesink_change_state (GstElement * element)
*/
break;
case GST_STATE_READY_TO_PAUSED:
printf ("ready to paused\n");
cltrimagesink->time = 0;
break;
case GST_STATE_PAUSED_TO_PLAYING:
@ -283,8 +289,6 @@ gst_cltrimagesink_chain (GstPad * pad, GstData * data)
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
DBG("mark");
cltrimagesink = GST_CLTRIMAGESINK (gst_pad_get_parent (pad));
if (GST_IS_EVENT (data))
@ -303,8 +307,6 @@ gst_cltrimagesink_chain (GstPad * pad, GstData * data)
/* If this buffer has been allocated using our buffer management we
* simply put the ximage which is in the PRIVATE pointer */
DBG("time is is %li", cltrimagesink->time);
#if 0
if (GST_BUFFER_FREE_DATA_FUNC (buf) == gst_cltrimagesink_buffer_free)
{
@ -323,38 +325,47 @@ gst_cltrimagesink_chain (GstPad * pad, GstData * data)
/* need to copy the data into out pixbuf here */
Pixbuf *pixb = NULL;
cltr_texture_lock(cltrimagesink->texture);
pixb = cltr_texture_get_pixbuf(cltrimagesink->texture);
if (pixb)
memcpy (pixb->data,
GST_BUFFER_DATA (buf),
MIN (GST_BUFFER_SIZE (buf),
pixb->bytes_per_line * pixb->width));
{
/*
memcpy (pixb->data,
GST_BUFFER_DATA (buf),
MIN (GST_BUFFER_SIZE (buf),
pixb->bytes_per_line * pixb->width));
*/
cltr_texture_resync_pixbuf(cltrimagesink->texture);
/* EVIL */
/*
cltr_texture_render_to_gl_quad(cltrimagesink->texture,
0, 0, 320, 240);
*/
if (GST_BUFFER_SIZE (buf) >= pixb->width * pixb->height * 3)
cltr_texture_force_rgb_data(cltrimagesink->texture,
pixb->width,
pixb->height,
GST_BUFFER_DATA (buf));
#if 0
memcpy (cltrimagesink->cltrimage->data,
GST_BUFFER_DATA (buf),
MIN (GST_BUFFER_SIZE (buf),
cltrimagesink->cltrimage->size));
gst_cltrimagesink_ximage_put (cltrimagesink,
cltrimagesink->cltrimage);
#endif
}
cltr_texture_unlock(cltrimagesink->texture);
if (cltrimagesink->queue)
{
CltrVideoSignal *signal;
signal = g_new0 (CltrVideoSignal, 1);
signal->signal_id = CLTR_VIDEO_ASYNC_TEXTURE;
signal->signal_data.texture.ref = cltrimagesink->texture;
g_async_queue_push(cltrimagesink->queue,
(gpointer)signal);
}
}
else
{
/* No image available. Something went wrong during capsnego ! */
DBG("MARK, texture == NULL");
gst_buffer_unref (buf);
GST_ELEMENT_ERROR (cltrimagesink, CORE, NEGOTIATION, (NULL),
("no format defined before chain function"));
@ -406,8 +417,8 @@ gst_cltrimagesink_set_property (GObject *object,
switch (prop_id)
{
case ARG_WIDGET:
cltrimagesink->widget = g_value_get_pointer (value);
case ARG_QUEUE:
cltrimagesink->queue = g_value_get_pointer (value);
break;
/*
case ARG_SIGNAL_HANDOFFS:
@ -434,8 +445,8 @@ gst_cltrimagesink_get_property (GObject *object,
switch (prop_id)
{
case ARG_WIDGET:
g_value_set_pointer (value, cltrimagesink->widget);
case ARG_QUEUE:
g_value_set_pointer (value, cltrimagesink->queue);
break;
/*
case ARG_SIGNAL_HANDOFFS:
@ -472,8 +483,6 @@ gst_cltrimagesink_finalize (GObject *object)
static void
gst_cltrimagesink_init (GstCltrimageSink * cltrimagesink)
{
DBG("mark");
GST_VIDEOSINK_PAD (cltrimagesink)
= gst_pad_new_from_template ( gst_static_pad_template_get(&gst_cltrimagesink_sink_template_factory), "sink");
@ -536,10 +545,10 @@ gst_cltrimagesink_class_init (GstCltrimageSinkClass * klass)
/* TOGO */
g_object_class_install_property (gobject_class,
ARG_WIDGET,
g_param_spec_pointer ("widget",
"Widget",
"Cltr drawable widget",
ARG_QUEUE,
g_param_spec_pointer ("queue",
"Queue",
"Async Signal Queue",
G_PARAM_READWRITE));
/* TOGO */

View File

@ -37,9 +37,9 @@ struct _GstCltrimageSink
GMutex *pool_lock;
GSList *image_pool;
GstCaps *caps;
GstCaps *caps;
GAsyncQueue *queue;
CltrWidget *widget;
};
struct _GstCltrimageSinkClass {
@ -52,6 +52,7 @@ struct _GstCltrimageSinkClass {
GType gst_cltrimagesink_get_type(void); /* XXX needed ? */
G_END_DECLS
#endif /* __GST_CLTRIMAGESINK_H__ */