2003-12-07 13:29:10 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 2003 Julien Moutte <julien@moutte.net>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
2003-12-22 01:47:08 +00:00
|
|
|
#include <string.h>
|
2003-12-07 13:29:10 +00:00
|
|
|
|
2004-01-30 22:38:56 +00:00
|
|
|
#include "play.h"
|
2004-07-30 13:41:55 +00:00
|
|
|
#include <gst/gst-i18n-plugin.h>
|
2003-12-07 13:29:10 +00:00
|
|
|
|
2004-02-02 10:49:32 +00:00
|
|
|
#define TICK_INTERVAL_MSEC 200
|
|
|
|
|
2004-03-29 17:19:38 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (play_debug);
|
|
|
|
#define GST_CAT_DEFAULT play_debug
|
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
TIME_TICK,
|
|
|
|
STREAM_LENGTH,
|
|
|
|
HAVE_VIDEO_SIZE,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
2004-03-14 22:34:30 +00:00
|
|
|
struct _GstPlayPrivate
|
|
|
|
{
|
2003-12-11 22:29:14 +00:00
|
|
|
char *location;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
GHashTable *elements;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
gint64 time_nanos;
|
|
|
|
gint64 length_nanos;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
gint get_length_attempt;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-03-15 19:32:25 +00:00
|
|
|
gint tick_unblock_remaining; /* how many msecs left
|
|
|
|
to unblock due to seeking */
|
2004-02-02 10:49:32 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
guint tick_id;
|
|
|
|
guint length_id;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
gulong handoff_hid;
|
2004-01-31 15:56:32 +00:00
|
|
|
|
|
|
|
/* error/debug handling */
|
|
|
|
GError *error;
|
|
|
|
gchar *debug;
|
2003-12-11 22:29:14 +00:00
|
|
|
};
|
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
static guint gst_play_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
static GstPipelineClass *parent_class = NULL;
|
|
|
|
|
|
|
|
/* ======================================================= */
|
|
|
|
/* */
|
|
|
|
/* Private Methods */
|
|
|
|
/* */
|
|
|
|
/* ======================================================= */
|
|
|
|
|
2004-03-14 22:34:30 +00:00
|
|
|
static GstCaps *gst_play_video_fixate (GstPad * pad, const GstCaps * caps,
|
|
|
|
gpointer user_data);
|
|
|
|
static GstCaps *gst_play_audio_fixate (GstPad * pad, const GstCaps * caps,
|
|
|
|
gpointer user_data);
|
2004-03-06 00:42:19 +00:00
|
|
|
|
2004-01-31 15:56:32 +00:00
|
|
|
static GQuark
|
|
|
|
gst_play_error_quark (void)
|
|
|
|
{
|
|
|
|
static GQuark quark = 0;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-31 15:56:32 +00:00
|
|
|
if (quark == 0)
|
|
|
|
quark = g_quark_from_static_string ("gst-play-error-quark");
|
|
|
|
return quark;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* General GError creation */
|
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_error_create (GError ** error, const gchar * message)
|
2004-01-31 15:56:32 +00:00
|
|
|
{
|
|
|
|
/* check if caller wanted an error reported */
|
|
|
|
if (error == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*error = g_error_new (GST_PLAY_ERROR, 0, message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* GError creation when plugin is missing */
|
|
|
|
/* FIXME: what if multiple elements could have been used and they're all
|
|
|
|
* missing ? varargs ? */
|
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_error_plugin (const gchar * element, GError ** error)
|
2004-01-31 15:56:32 +00:00
|
|
|
{
|
|
|
|
gchar *message;
|
|
|
|
|
2004-07-30 13:41:55 +00:00
|
|
|
message = g_strdup_printf (_("The %s element could not be found. "
|
|
|
|
"This element is essential for playback. "
|
|
|
|
"Please install the right plug-in and verify "
|
|
|
|
"that it works by running 'gst-inspect %s'"), element, element);
|
2004-01-31 15:56:32 +00:00
|
|
|
gst_play_error_create (error, message);
|
|
|
|
g_free (message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GST_PLAY_MAKE_OR_ERROR(el, factory, name, error) \
|
|
|
|
G_STMT_START { \
|
|
|
|
el = gst_element_factory_make (factory, name); \
|
2004-07-30 13:41:55 +00:00
|
|
|
if (!GST_IS_ELEMENT (el)) { \
|
2004-01-31 15:56:32 +00:00
|
|
|
gst_play_error_plugin (factory, error); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
2004-07-30 13:41:55 +00:00
|
|
|
/* Create a colorspace element from the list of acceptable ones;
|
|
|
|
* set error and fail if none found. */
|
|
|
|
#define GST_PLAY_MAKE_CS_OR_ERROR(el, name, error) \
|
|
|
|
G_STMT_START { \
|
|
|
|
el = gst_element_factory_make ("ffmpegcolorspace", name); \
|
|
|
|
if (!GST_IS_ELEMENT (el)) \
|
|
|
|
el = gst_element_factory_make ("ffcolorspace", name); \
|
|
|
|
if (!GST_IS_ELEMENT (el)) \
|
|
|
|
el = gst_element_factory_make ("hermescolorspace", name); \
|
|
|
|
if (!GST_IS_ELEMENT (el)) { \
|
|
|
|
gst_play_error_create (error, \
|
|
|
|
_("No usable colorspace element could be found.\n" \
|
|
|
|
"Please install one and restart.")); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
2004-01-31 15:56:32 +00:00
|
|
|
#define GST_PLAY_ERROR_RETURN(error, message) \
|
|
|
|
G_STMT_START { \
|
|
|
|
gst_play_error_create (error, message); \
|
|
|
|
return FALSE; \
|
|
|
|
} G_STMT_END
|
|
|
|
|
2004-07-08 14:38:48 +00:00
|
|
|
#define GST_PLAY_HASH_LOOKUP(element, key, retval_if_fail) \
|
|
|
|
G_STMT_START { \
|
|
|
|
(element) = g_hash_table_lookup (play->priv->elements, (key));\
|
|
|
|
if (!element) \
|
|
|
|
return (retval_if_fail); \
|
|
|
|
} G_STMT_END
|
2004-01-31 15:56:32 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
/* setup parts of the pipeline
|
|
|
|
* only put decoding part in the thread
|
|
|
|
* create all others and keep them around
|
|
|
|
*/
|
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
static gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_pipeline_setup (GstPlay * play, GError ** error)
|
2003-12-07 13:29:10 +00:00
|
|
|
{
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Threads */
|
|
|
|
GstElement *work_thread, *audio_thread, *video_thread;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
/* output bin */
|
|
|
|
GstElement *output_bin;
|
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Main Thread elements */
|
2004-07-08 13:44:06 +00:00
|
|
|
GstElement *source, *autoplugger;
|
|
|
|
|
|
|
|
/* output bin elements */
|
|
|
|
GstElement *audioconvert, *volume, *tee, *identity;
|
2004-01-25 12:28:05 +00:00
|
|
|
GstElement *identity_cs;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Visualization bin */
|
|
|
|
GstElement *vis_bin, *vis_queue, *vis_element, *vis_cs;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Video Thread elements */
|
2004-01-25 12:28:05 +00:00
|
|
|
GstElement *video_queue, *video_switch, *video_cs, *video_balance;
|
|
|
|
GstElement *balance_cs, *video_scaler, *video_sink;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Audio Thread elements */
|
|
|
|
GstElement *audio_queue, *audio_sink;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Some useful pads */
|
|
|
|
GstPad *tee_pad1, *tee_pad2;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "setting up pipeline");
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Creating main thread and its elements */
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
{
|
2004-03-14 22:34:30 +00:00
|
|
|
GST_PLAY_MAKE_OR_ERROR (work_thread, "thread", "work_thread", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "work_thread", work_thread);
|
|
|
|
gst_bin_add (GST_BIN (play), work_thread);
|
|
|
|
|
|
|
|
/* Placeholder for datasrc */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (source, "fakesrc", "source", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "source", source);
|
|
|
|
|
|
|
|
/* Autoplugger */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (autoplugger, "spider", "autoplugger", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "autoplugger", autoplugger);
|
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
/* adding and linking */
|
|
|
|
gst_bin_add_many (GST_BIN (work_thread), source, autoplugger, NULL);
|
|
|
|
if (!gst_element_link (source, autoplugger))
|
|
|
|
GST_PLAY_ERROR_RETURN (error, "Could not link source and autoplugger");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* output bin */
|
|
|
|
{
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (output_bin, "bin", "output_bin", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "output_bin", output_bin);
|
2004-03-14 22:34:30 +00:00
|
|
|
/* Make sure we convert audio to the needed format */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (audioconvert, "audioconvert", "audioconvert",
|
2004-03-15 19:32:25 +00:00
|
|
|
error);
|
2004-03-14 22:34:30 +00:00
|
|
|
g_hash_table_insert (play->priv->elements, "audioconvert", audioconvert);
|
|
|
|
|
|
|
|
/* Duplicate audio signal to audio sink and visualization thread */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (tee, "tee", "tee", error);
|
|
|
|
tee_pad1 = gst_element_get_request_pad (tee, "src%d");
|
|
|
|
tee_pad2 = gst_element_get_request_pad (tee, "src%d");
|
|
|
|
g_hash_table_insert (play->priv->elements, "tee_pad1", tee_pad1);
|
|
|
|
g_hash_table_insert (play->priv->elements, "tee_pad2", tee_pad2);
|
|
|
|
g_hash_table_insert (play->priv->elements, "tee", tee);
|
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
gst_bin_add_many (GST_BIN (output_bin), audioconvert, tee, NULL);
|
|
|
|
if (!gst_element_link (audioconvert, tee))
|
|
|
|
GST_PLAY_ERROR_RETURN (error, "Could not link audio thread elements");
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
/* identity ! colorspace ! switch */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (identity, "identity", "identity", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "identity", identity);
|
2004-07-30 13:41:55 +00:00
|
|
|
GST_PLAY_MAKE_CS_OR_ERROR (identity_cs, "identity_cs", error);
|
2004-03-14 22:34:30 +00:00
|
|
|
g_hash_table_insert (play->priv->elements, "identity_cs", identity_cs);
|
2004-07-08 13:44:06 +00:00
|
|
|
gst_bin_add_many (GST_BIN (output_bin), identity, identity_cs, NULL);
|
2004-07-28 16:22:53 +00:00
|
|
|
if (!gst_element_link (identity, identity_cs))
|
2004-03-14 22:34:30 +00:00
|
|
|
GST_PLAY_ERROR_RETURN (error, "Could not link work thread elements");
|
2004-07-08 17:34:08 +00:00
|
|
|
/* we ref the output bin so we can put it in and out the work_thread
|
|
|
|
* whenever we want */
|
|
|
|
gst_object_ref (GST_OBJECT (output_bin));
|
|
|
|
GST_DEBUG_OBJECT (play, "adding output bin to work thread in setup");
|
2004-07-08 13:44:06 +00:00
|
|
|
gst_bin_add (GST_BIN (work_thread), output_bin);
|
2004-07-08 17:34:08 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Visualization bin (note: it s not added to the pipeline yet) */
|
|
|
|
{
|
2004-03-14 22:34:30 +00:00
|
|
|
vis_bin = gst_bin_new ("vis_bin");
|
|
|
|
if (!GST_IS_ELEMENT (vis_bin)) {
|
|
|
|
gst_play_error_plugin ("bin", error);
|
2004-01-25 12:28:05 +00:00
|
|
|
return FALSE;
|
2004-01-31 15:56:32 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
g_hash_table_insert (play->priv->elements, "vis_bin", vis_bin);
|
|
|
|
|
|
|
|
/* Buffer queue for video data */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (vis_queue, "queue", "vis_queue", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "vis_queue", vis_queue);
|
|
|
|
|
|
|
|
/* Visualization element placeholder */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (vis_element, "identity", "vis_element", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
|
|
|
|
|
|
|
/* Colorspace conversion */
|
2004-07-30 13:41:55 +00:00
|
|
|
GST_PLAY_MAKE_CS_OR_ERROR (vis_cs, "vis_cs", error);
|
2004-03-14 22:34:30 +00:00
|
|
|
g_hash_table_insert (play->priv->elements, "vis_cs", vis_cs);
|
|
|
|
|
|
|
|
gst_bin_add_many (GST_BIN (vis_bin), vis_queue, vis_element, vis_cs, NULL);
|
|
|
|
if (!gst_element_link_many (vis_queue, vis_element, vis_cs, NULL))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link visualisation thread elements");
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_element_add_ghost_pad (vis_bin, gst_element_get_pad (vis_cs, "src"),
|
2004-03-15 19:32:25 +00:00
|
|
|
"src");
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
}
|
|
|
|
/* Creating our video output bin */
|
|
|
|
{
|
2004-03-14 22:34:30 +00:00
|
|
|
GST_PLAY_MAKE_OR_ERROR (video_thread, "thread", "video_thread", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "video_thread", video_thread);
|
2004-07-08 13:44:06 +00:00
|
|
|
gst_bin_add (GST_BIN (output_bin), video_thread);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
/* Buffer queue for video data */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (video_queue, "queue", "video_queue", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
|
|
|
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (video_switch, "switch", "video_switch", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "video_switch", video_switch);
|
|
|
|
|
|
|
|
/* Colorspace conversion */
|
2004-07-30 13:41:55 +00:00
|
|
|
GST_PLAY_MAKE_CS_OR_ERROR (video_cs, "video_cs", error);
|
2004-03-14 22:34:30 +00:00
|
|
|
g_hash_table_insert (play->priv->elements, "video_cs", video_cs);
|
|
|
|
|
|
|
|
/* Software colorbalance */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (video_balance, "videobalance", "video_balance",
|
2004-03-15 19:32:25 +00:00
|
|
|
error);
|
2004-03-14 22:34:30 +00:00
|
|
|
g_hash_table_insert (play->priv->elements, "video_balance", video_balance);
|
|
|
|
|
|
|
|
/* Colorspace conversion */
|
2004-07-30 13:41:55 +00:00
|
|
|
GST_PLAY_MAKE_CS_OR_ERROR (balance_cs, "balance_cs", error);
|
2004-03-14 22:34:30 +00:00
|
|
|
g_hash_table_insert (play->priv->elements, "balance_cs", balance_cs);
|
|
|
|
|
|
|
|
/* Software scaling of video stream */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (video_scaler, "videoscale", "video_scaler", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "video_scaler", video_scaler);
|
|
|
|
g_signal_connect (gst_element_get_pad (video_scaler, "src"), "fixate",
|
2004-03-15 19:32:25 +00:00
|
|
|
G_CALLBACK (gst_play_video_fixate), play);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
/* Placeholder for future video sink bin */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (video_sink, "fakesink", "video_sink", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
|
|
|
|
|
|
|
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_switch,
|
2004-03-15 19:32:25 +00:00
|
|
|
video_cs, video_balance, balance_cs, video_scaler, video_sink, NULL);
|
2004-03-14 22:34:30 +00:00
|
|
|
/* break down linking so we can figure out what might be failing */
|
|
|
|
if (!gst_element_link (video_queue, video_switch))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread (queue and switch)");
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link (video_switch, video_cs))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread (switch and cs)");
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link (video_cs, video_balance))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread (cs and balance)");
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link (video_balance, balance_cs))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread (balance and balance_cs)");
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link (balance_cs, video_scaler))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread (balance_cs and scaler)");
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link (video_scaler, video_sink))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread (balance_cs and scaler)");
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_element_add_ghost_pad (video_thread, gst_element_get_pad (video_queue,
|
2004-03-15 19:32:25 +00:00
|
|
|
"sink"), "sink");
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link (identity_cs, video_thread))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link video output thread elements");
|
2004-01-14 21:50:39 +00:00
|
|
|
}
|
2003-12-07 13:29:10 +00:00
|
|
|
/* Creating our audio output bin
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
{ queue ! fakesink } */
|
|
|
|
{
|
2004-03-14 22:34:30 +00:00
|
|
|
GST_PLAY_MAKE_OR_ERROR (audio_thread, "thread", "audio_thread", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "audio_thread", audio_thread);
|
2004-07-08 13:44:06 +00:00
|
|
|
gst_bin_add (GST_BIN (output_bin), audio_thread);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
/* Buffer queue for our audio thread */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (audio_queue, "queue", "audio_queue", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "audio_queue", audio_queue);
|
|
|
|
|
|
|
|
/* Volume control */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (volume, "volume", "volume", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "volume", volume);
|
|
|
|
g_signal_connect (gst_element_get_pad (volume, "src"), "fixate",
|
2004-03-15 19:32:25 +00:00
|
|
|
G_CALLBACK (gst_play_audio_fixate), play);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
/* Placeholder for future audio sink bin */
|
|
|
|
GST_PLAY_MAKE_OR_ERROR (audio_sink, "fakesink", "audio_sink", error);
|
|
|
|
g_hash_table_insert (play->priv->elements, "audio_sink", audio_sink);
|
|
|
|
|
|
|
|
gst_bin_add_many (GST_BIN (audio_thread), audio_queue, volume, audio_sink,
|
2004-03-15 19:32:25 +00:00
|
|
|
NULL);
|
2004-03-14 22:34:30 +00:00
|
|
|
if (!gst_element_link_many (audio_queue, volume, audio_sink, NULL))
|
|
|
|
GST_PLAY_ERROR_RETURN (error,
|
2004-03-15 19:32:25 +00:00
|
|
|
"Could not link audio output thread elements");
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_element_add_ghost_pad (audio_thread, gst_element_get_pad (audio_queue,
|
2004-03-15 19:32:25 +00:00
|
|
|
"sink"), "sink");
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_pad_link (tee_pad2, gst_element_get_pad (audio_queue, "sink"));
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "setting up pipeline succeeded.");
|
2003-12-07 13:29:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_have_video_size (GstElement * element, gint width,
|
|
|
|
gint height, GstPlay * play)
|
2003-12-07 19:02:31 +00:00
|
|
|
{
|
|
|
|
g_return_if_fail (play != NULL);
|
|
|
|
g_return_if_fail (GST_IS_PLAY (play));
|
|
|
|
g_signal_emit (G_OBJECT (play), gst_play_signals[HAVE_VIDEO_SIZE],
|
2004-03-14 22:34:30 +00:00
|
|
|
0, width, height);
|
2003-12-07 19:02:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_tick_callback (GstPlay * play)
|
2003-12-07 19:02:31 +00:00
|
|
|
{
|
2004-01-27 21:24:14 +00:00
|
|
|
GstFormat format = GST_FORMAT_TIME;
|
|
|
|
gboolean q = FALSE;
|
|
|
|
GstElement *audio_sink_element = NULL;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
2004-02-02 10:49:32 +00:00
|
|
|
/* just return without updating the UI when we are in the middle of seeking */
|
2004-03-14 22:34:30 +00:00
|
|
|
if (play->priv->tick_unblock_remaining > 0) {
|
2004-02-02 10:49:32 +00:00
|
|
|
play->priv->tick_unblock_remaining -= TICK_INTERVAL_MSEC;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (!GST_IS_PLAY (play)) {
|
|
|
|
play->priv->tick_id = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-14 02:37:12 +00:00
|
|
|
audio_sink_element = g_hash_table_lookup (play->priv->elements,
|
2004-03-14 22:34:30 +00:00
|
|
|
"audio_sink_element");
|
|
|
|
|
2004-01-27 21:24:14 +00:00
|
|
|
if (!GST_IS_ELEMENT (audio_sink_element)) {
|
|
|
|
play->priv->tick_id = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-27 21:24:14 +00:00
|
|
|
q = gst_element_query (audio_sink_element, GST_QUERY_POSITION, &format,
|
2004-03-14 22:34:30 +00:00
|
|
|
&(play->priv->time_nanos));
|
|
|
|
|
2004-01-27 21:24:14 +00:00
|
|
|
if (q)
|
|
|
|
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK],
|
2004-03-15 19:32:25 +00:00
|
|
|
0, play->priv->time_nanos);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING)
|
|
|
|
return TRUE;
|
2003-12-14 17:00:18 +00:00
|
|
|
else {
|
|
|
|
play->priv->tick_id = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-12-08 16:01:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_get_length_callback (GstPlay * play)
|
2003-12-08 16:01:49 +00:00
|
|
|
{
|
|
|
|
GstElement *audio_sink_element, *video_sink_element;
|
|
|
|
GstFormat format = GST_FORMAT_TIME;
|
|
|
|
gint64 value;
|
|
|
|
gboolean q = FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "trying to get length");
|
2003-12-08 16:01:49 +00:00
|
|
|
/* We try to get length from all real sink elements */
|
2003-12-11 22:29:14 +00:00
|
|
|
audio_sink_element = g_hash_table_lookup (play->priv->elements,
|
2004-03-14 22:34:30 +00:00
|
|
|
"audio_sink_element");
|
2003-12-11 22:29:14 +00:00
|
|
|
video_sink_element = g_hash_table_lookup (play->priv->elements,
|
2004-03-14 22:34:30 +00:00
|
|
|
"video_sink_element");
|
2003-12-08 16:01:49 +00:00
|
|
|
if (!GST_IS_ELEMENT (audio_sink_element) &&
|
2003-12-14 17:00:18 +00:00
|
|
|
!GST_IS_ELEMENT (video_sink_element)) {
|
|
|
|
play->priv->length_id = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
/* Audio first and then Video */
|
2004-07-08 13:44:06 +00:00
|
|
|
if (GST_IS_ELEMENT (audio_sink_element)) {
|
|
|
|
GST_DEBUG_OBJECT (play, "querying for length on audio sink");
|
2003-12-21 19:48:40 +00:00
|
|
|
q = gst_element_query (audio_sink_element, GST_QUERY_TOTAL, &format,
|
2004-03-15 19:32:25 +00:00
|
|
|
&value);
|
2004-07-08 13:44:06 +00:00
|
|
|
} else
|
|
|
|
GST_DEBUG_OBJECT (play, "no audio sink element");
|
|
|
|
if (!q) {
|
|
|
|
GST_DEBUG_OBJECT (play, "no query result from audio sink");
|
|
|
|
if (GST_IS_ELEMENT (video_sink_element)) {
|
|
|
|
GST_DEBUG_OBJECT (play, "querying for length on video sink");
|
|
|
|
q = gst_element_query (video_sink_element, GST_QUERY_TOTAL, &format,
|
|
|
|
&value);
|
|
|
|
}
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (q) {
|
|
|
|
play->priv->length_nanos = value;
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "got length, %" GST_TIME_FORMAT,
|
|
|
|
GST_TIME_ARGS ((GstClockTime) value));
|
2003-12-14 17:00:18 +00:00
|
|
|
g_signal_emit (G_OBJECT (play), gst_play_signals[STREAM_LENGTH],
|
2004-03-15 19:32:25 +00:00
|
|
|
0, play->priv->length_nanos);
|
2003-12-14 17:00:18 +00:00
|
|
|
play->priv->length_id = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
play->priv->get_length_attempt++;
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "no length yet, was attempt %d",
|
|
|
|
play->priv->get_length_attempt);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
/* We try 16 times */
|
2003-12-14 17:00:18 +00:00
|
|
|
if (play->priv->get_length_attempt > 15) {
|
|
|
|
play->priv->length_id = 0;
|
|
|
|
return FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
} else
|
2003-12-08 16:01:49 +00:00
|
|
|
return TRUE;
|
2003-12-07 19:02:31 +00:00
|
|
|
}
|
|
|
|
|
2004-03-06 00:42:19 +00:00
|
|
|
static GstCaps *
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_video_fixate (GstPad * pad, const GstCaps * caps, gpointer user_data)
|
2004-03-06 00:42:19 +00:00
|
|
|
{
|
|
|
|
GstStructure *structure;
|
|
|
|
GstCaps *newcaps;
|
|
|
|
|
|
|
|
GST_DEBUG ("video fixate %p %" GST_PTR_FORMAT, pad, caps);
|
|
|
|
|
2004-03-14 22:34:30 +00:00
|
|
|
if (gst_caps_get_size (caps) > 1)
|
|
|
|
return NULL;
|
2004-03-06 00:42:19 +00:00
|
|
|
|
|
|
|
newcaps = gst_caps_copy (caps);
|
|
|
|
structure = gst_caps_get_structure (newcaps, 0);
|
|
|
|
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "width") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_int (structure, "width", 320)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "height") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_int (structure, "height", 240)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "framerate") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_double (structure, "framerate",
|
2004-03-15 19:32:25 +00:00
|
|
|
30.0)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* failed to fixate */
|
|
|
|
gst_caps_free (newcaps);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstCaps *
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_audio_fixate (GstPad * pad, const GstCaps * caps, gpointer user_data)
|
2004-03-06 00:42:19 +00:00
|
|
|
{
|
|
|
|
GstCaps *newcaps;
|
|
|
|
GstStructure *structure;
|
|
|
|
|
|
|
|
GST_DEBUG ("audio fixate %p %" GST_PTR_FORMAT, pad, caps);
|
|
|
|
|
2004-03-14 22:34:30 +00:00
|
|
|
newcaps =
|
|
|
|
gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (caps, 0)),
|
|
|
|
NULL);
|
2004-03-06 00:42:19 +00:00
|
|
|
structure = gst_caps_get_structure (newcaps, 0);
|
|
|
|
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "rate") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_int (structure, "rate", 44100)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "depth") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_int (structure, "depth", 16)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "width") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_int (structure, "width", 16)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
2004-03-23 16:59:59 +00:00
|
|
|
if (gst_structure_has_field (structure, "channels") &&
|
|
|
|
gst_caps_structure_fixate_field_nearest_int (structure, "channels", 2)) {
|
2004-03-06 00:42:19 +00:00
|
|
|
return newcaps;
|
|
|
|
}
|
|
|
|
|
|
|
|
gst_caps_free (newcaps);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-07-08 17:34:08 +00:00
|
|
|
/* this is a signal handler because we want this called AFTER the state
|
|
|
|
* change has passed. FIXME: core should rename signal to state-changed
|
|
|
|
* to make this clear. */
|
2003-12-07 19:02:31 +00:00
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_state_change (GstElement * element, GstElementState old,
|
|
|
|
GstElementState state)
|
2003-12-07 19:02:31 +00:00
|
|
|
{
|
|
|
|
GstPlay *play;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
g_return_if_fail (element != NULL);
|
|
|
|
g_return_if_fail (GST_IS_PLAY (element));
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
play = GST_PLAY (element);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (state == GST_STATE_PLAYING) {
|
|
|
|
if (play->priv->tick_id) {
|
|
|
|
g_source_remove (play->priv->tick_id);
|
|
|
|
play->priv->tick_id = 0;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-02-02 10:49:32 +00:00
|
|
|
play->priv->tick_id = g_timeout_add (TICK_INTERVAL_MSEC,
|
2004-03-15 19:32:25 +00:00
|
|
|
(GSourceFunc) gst_play_tick_callback, play);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
play->priv->get_length_attempt = 0;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (play->priv->length_id) {
|
|
|
|
g_source_remove (play->priv->length_id);
|
|
|
|
play->priv->length_id = 0;
|
2003-12-07 19:02:31 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-02-02 10:49:32 +00:00
|
|
|
play->priv->length_id = g_timeout_add (TICK_INTERVAL_MSEC,
|
2004-03-15 19:32:25 +00:00
|
|
|
(GSourceFunc) gst_play_get_length_callback, play);
|
2004-03-14 22:34:30 +00:00
|
|
|
} else {
|
2004-02-15 17:41:28 +00:00
|
|
|
if (play->priv->tick_id) {
|
|
|
|
g_source_remove (play->priv->tick_id);
|
|
|
|
play->priv->tick_id = 0;
|
|
|
|
}
|
|
|
|
if (play->priv->length_id) {
|
|
|
|
g_source_remove (play->priv->length_id);
|
|
|
|
play->priv->length_id = 0;
|
|
|
|
}
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
if (GST_ELEMENT_CLASS (parent_class)->state_change)
|
|
|
|
GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state);
|
|
|
|
}
|
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_identity_handoff (GstElement * identity, GstBuffer * buf,
|
|
|
|
GstPlay * play)
|
2004-01-25 12:28:05 +00:00
|
|
|
{
|
|
|
|
g_signal_handler_disconnect (G_OBJECT (identity), play->priv->handoff_hid);
|
|
|
|
play->priv->handoff_hid = 0;
|
|
|
|
gst_play_connect_visualization (play, FALSE);
|
|
|
|
}
|
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
/* =========================================== */
|
|
|
|
/* */
|
|
|
|
/* Init & Dispose & Class init */
|
|
|
|
/* */
|
|
|
|
/* =========================================== */
|
|
|
|
|
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_dispose (GObject * object)
|
2003-12-07 13:29:10 +00:00
|
|
|
{
|
|
|
|
GstPlay *play;
|
2004-07-08 17:34:08 +00:00
|
|
|
GstElement *output_bin;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
g_return_if_fail (object != NULL);
|
|
|
|
g_return_if_fail (GST_IS_PLAY (object));
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
play = GST_PLAY (object);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (play->priv->length_id) {
|
|
|
|
g_source_remove (play->priv->length_id);
|
|
|
|
play->priv->length_id = 0;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (play->priv->tick_id) {
|
|
|
|
g_source_remove (play->priv->tick_id);
|
|
|
|
play->priv->tick_id = 0;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (play->priv->location) {
|
|
|
|
g_free (play->priv->location);
|
|
|
|
play->priv->location = NULL;
|
|
|
|
}
|
2004-07-08 17:34:08 +00:00
|
|
|
/* since we reffed our output bin to keep it around, unref it here */
|
|
|
|
output_bin = g_hash_table_lookup (play->priv->elements, "output_bin");
|
|
|
|
if (output_bin)
|
|
|
|
gst_object_unref (GST_OBJECT (output_bin));
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (play->priv->elements) {
|
|
|
|
g_hash_table_destroy (play->priv->elements);
|
|
|
|
play->priv->elements = NULL;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_init (GstPlay * play)
|
2003-12-07 13:29:10 +00:00
|
|
|
{
|
2003-12-11 22:29:14 +00:00
|
|
|
play->priv = g_new0 (GstPlayPrivate, 1);
|
|
|
|
play->priv->location = NULL;
|
|
|
|
play->priv->length_nanos = 0;
|
|
|
|
play->priv->time_nanos = 0;
|
|
|
|
play->priv->elements = g_hash_table_new (g_str_hash, g_str_equal);
|
2004-01-31 15:56:32 +00:00
|
|
|
play->priv->error = NULL;
|
|
|
|
play->priv->debug = NULL;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
|
|
|
if (!gst_play_pipeline_setup (play, &play->priv->error)) {
|
2004-01-31 15:56:32 +00:00
|
|
|
g_warning ("libgstplay: failed initializing pipeline, error: %s",
|
2004-03-15 19:32:25 +00:00
|
|
|
play->priv->error->message);
|
2004-01-31 15:56:32 +00:00
|
|
|
}
|
2003-12-07 13:29:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_class_init (GstPlayClass * klass)
|
2003-12-07 13:29:10 +00:00
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
2003-12-07 19:02:31 +00:00
|
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
|
|
|
|
gobject_class->dispose = gst_play_dispose;
|
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
element_class->state_change = gst_play_state_change;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
gst_play_signals[TIME_TICK] =
|
2004-03-14 22:34:30 +00:00
|
|
|
g_signal_new ("time-tick", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GstPlayClass, time_tick), NULL, NULL,
|
|
|
|
gst_marshal_VOID__INT64, G_TYPE_NONE, 1, G_TYPE_INT64);
|
2003-12-07 13:29:10 +00:00
|
|
|
gst_play_signals[STREAM_LENGTH] =
|
2004-03-14 22:34:30 +00:00
|
|
|
g_signal_new ("stream-length", G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GstPlayClass, stream_length), NULL, NULL,
|
|
|
|
gst_marshal_VOID__INT64, G_TYPE_NONE, 1, G_TYPE_INT64);
|
2003-12-07 13:29:10 +00:00
|
|
|
gst_play_signals[HAVE_VIDEO_SIZE] =
|
2004-03-14 22:34:30 +00:00
|
|
|
g_signal_new ("have-video-size", G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GstPlayClass, have_video_size), NULL, NULL,
|
|
|
|
gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
|
2004-03-29 17:19:38 +00:00
|
|
|
GST_DEBUG_CATEGORY_INIT (play_debug, "GST_PLAY", 0, "GStreamer Play library");
|
|
|
|
GST_DEBUG ("Play class initialized");
|
2003-12-07 13:29:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ======================================================= */
|
|
|
|
/* */
|
|
|
|
/* Public Methods */
|
|
|
|
/* */
|
|
|
|
/* ======================================================= */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_set_location:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @location: a const #char* indicating location to play
|
|
|
|
*
|
|
|
|
* Set location of @play to @location.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if location was set successfully.
|
|
|
|
*/
|
|
|
|
gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_set_location (GstPlay * play, const char *location)
|
2003-12-07 13:29:10 +00:00
|
|
|
{
|
2004-01-14 21:50:39 +00:00
|
|
|
GstElement *work_thread, *source, *autoplugger;
|
2004-01-25 12:28:05 +00:00
|
|
|
GstElement *audioconvert, *identity;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
if (play->priv->location)
|
|
|
|
g_free (play->priv->location);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
play->priv->location = g_strdup (location);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-03-29 17:19:38 +00:00
|
|
|
if (GST_STATE (GST_ELEMENT (play)) != GST_STATE_READY) {
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-29 17:19:38 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (work_thread, "work_thread", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (source, "source", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (autoplugger, "autoplugger", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (audioconvert, "audioconvert", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (identity, "identity", FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 14:38:48 +00:00
|
|
|
/* Spider can autoplug only once. We remove the actual one and put a new
|
2003-12-07 17:56:10 +00:00
|
|
|
autoplugger */
|
|
|
|
gst_element_unlink (source, autoplugger);
|
2004-01-25 12:28:05 +00:00
|
|
|
gst_element_unlink (autoplugger, identity);
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
gst_element_unlink (autoplugger, audioconvert);
|
2003-12-07 17:56:10 +00:00
|
|
|
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
|
|
|
if (!GST_IS_ELEMENT (autoplugger))
|
|
|
|
return FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
|
|
|
gst_element_link (source, autoplugger);
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
gst_element_link (autoplugger, audioconvert);
|
2004-01-27 16:42:40 +00:00
|
|
|
gst_element_link (autoplugger, identity);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* FIXME: Why don't we have an interface to do that kind of stuff ? */
|
2003-12-11 22:29:14 +00:00
|
|
|
g_object_set (G_OBJECT (source), "location", play->priv->location, NULL);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
play->priv->length_nanos = 0LL;
|
|
|
|
play->priv->time_nanos = 0LL;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
g_signal_emit (G_OBJECT (play), gst_play_signals[STREAM_LENGTH], 0, 0LL);
|
|
|
|
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK], 0, 0LL);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_get_location:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
*
|
|
|
|
* Get current location of @play.
|
|
|
|
*
|
|
|
|
* Returns: a const #char* pointer to current location.
|
|
|
|
*/
|
|
|
|
char *
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_get_location (GstPlay * play)
|
2003-12-07 13:29:10 +00:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (play != NULL, NULL);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), NULL);
|
2003-12-11 22:29:14 +00:00
|
|
|
return g_strdup (play->priv->location);
|
2003-12-07 13:29:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_seek_to_time:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @time_nanos: a #gint64 indicating a time position.
|
|
|
|
*
|
|
|
|
* Performs a seek on @play until @time_nanos.
|
|
|
|
*/
|
2004-07-08 13:44:06 +00:00
|
|
|
/* FIXME: use GstClockTime for 0.9 */
|
2003-12-07 13:29:10 +00:00
|
|
|
gboolean
|
|
|
|
gst_play_seek_to_time (GstPlay * play, gint64 time_nanos)
|
|
|
|
{
|
2004-01-29 22:44:42 +00:00
|
|
|
GstElement *audio_seek_element, *video_seek_element, *audio_sink_element;
|
2004-07-08 13:44:06 +00:00
|
|
|
GstClockTime seek_to;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2004-07-08 13:44:06 +00:00
|
|
|
g_return_val_if_fail (time_nanos >= 0L, FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
seek_to = (GstClockTime) time_nanos;
|
|
|
|
GST_DEBUG_OBJECT (play, "seeking to time %" GST_TIME_FORMAT,
|
|
|
|
GST_TIME_ARGS (seek_to));
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-29 22:44:42 +00:00
|
|
|
audio_seek_element = g_hash_table_lookup (play->priv->elements,
|
2004-03-14 22:34:30 +00:00
|
|
|
"audioconvert");
|
2003-12-11 22:29:14 +00:00
|
|
|
audio_sink_element = g_hash_table_lookup (play->priv->elements,
|
2004-03-14 22:34:30 +00:00
|
|
|
"audio_sink_element");
|
|
|
|
video_seek_element = g_hash_table_lookup (play->priv->elements, "identity");
|
|
|
|
|
2004-01-29 22:44:42 +00:00
|
|
|
if (GST_IS_ELEMENT (audio_seek_element) &&
|
|
|
|
GST_IS_ELEMENT (video_seek_element) &&
|
|
|
|
GST_IS_ELEMENT (audio_sink_element)) {
|
2003-12-14 17:00:18 +00:00
|
|
|
gboolean s = FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-02-02 10:49:32 +00:00
|
|
|
/* HACK: block tick signal from idler for 500 msec */
|
|
|
|
/* GStreamer can't currently report when seeking is finished,
|
|
|
|
so we just chose a .5 sec default block time */
|
|
|
|
play->priv->tick_unblock_remaining = 500;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-29 22:44:42 +00:00
|
|
|
s = gst_element_seek (video_seek_element, GST_FORMAT_TIME |
|
2004-03-15 19:32:25 +00:00
|
|
|
GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, time_nanos);
|
2003-12-14 17:00:18 +00:00
|
|
|
if (!s) {
|
2004-01-29 22:44:42 +00:00
|
|
|
s = gst_element_seek (audio_seek_element, GST_FORMAT_TIME |
|
2004-03-15 19:32:25 +00:00
|
|
|
GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, time_nanos);
|
2003-12-08 16:01:49 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (s) {
|
2004-01-27 21:24:14 +00:00
|
|
|
GstFormat format = GST_FORMAT_TIME;
|
|
|
|
gboolean q = FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-27 21:24:14 +00:00
|
|
|
q = gst_element_query (audio_sink_element, GST_QUERY_POSITION, &format,
|
2004-03-15 19:32:25 +00:00
|
|
|
&(play->priv->time_nanos));
|
2004-01-27 21:24:14 +00:00
|
|
|
|
|
|
|
if (q)
|
2004-03-15 19:32:25 +00:00
|
|
|
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK],
|
|
|
|
0, play->priv->time_nanos);
|
2003-12-14 17:00:18 +00:00
|
|
|
}
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/**
|
|
|
|
* gst_play_set_data_src:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @data_src: a #GstElement.
|
|
|
|
*
|
|
|
|
* Set @data_src as the source element of @play.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if call succeeded.
|
|
|
|
*/
|
|
|
|
gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_set_data_src (GstPlay * play, GstElement * data_src)
|
2003-12-07 17:56:10 +00:00
|
|
|
{
|
|
|
|
GstElement *work_thread, *old_data_src, *autoplugger;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "setting new data src element %s",
|
|
|
|
GST_ELEMENT_NAME (data_src));
|
2003-12-07 17:56:10 +00:00
|
|
|
/* We bring back the pipeline to READY */
|
2004-03-29 17:19:38 +00:00
|
|
|
if (GST_STATE (GST_ELEMENT (play)) != GST_STATE_READY) {
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-29 17:19:38 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* Getting needed objects */
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (work_thread, "work_thread", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (old_data_src, "source", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (autoplugger, "autoplugger", FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* Unlinking old source from autoplugger, removing it from pipeline, adding
|
|
|
|
the new one and connecting it to autoplugger FIXME: we should put a new
|
|
|
|
autoplugger here as spider can autoplugg only once */
|
|
|
|
gst_element_unlink (old_data_src, autoplugger);
|
|
|
|
gst_bin_remove (GST_BIN (work_thread), old_data_src);
|
|
|
|
gst_bin_add (GST_BIN (work_thread), data_src);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (!gst_element_link (data_src, autoplugger)) {
|
|
|
|
GST_ERROR_OBJECT (play, "could not link source to autoplugger");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
g_hash_table_replace (play->priv->elements, "source", data_src);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_set_video_sink:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @video_sink: a #GstElement.
|
|
|
|
*
|
|
|
|
* Set @video_sink as the video sink element of @play.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if call succeeded.
|
|
|
|
*/
|
|
|
|
gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_set_video_sink (GstPlay * play, GstElement * video_sink)
|
2003-12-07 17:56:10 +00:00
|
|
|
{
|
2003-12-07 19:02:31 +00:00
|
|
|
GstElement *video_thread, *old_video_sink, *video_scaler, *video_sink_element;
|
2004-03-29 17:19:38 +00:00
|
|
|
GstElementStateReturn ret;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2003-12-21 19:48:40 +00:00
|
|
|
g_return_val_if_fail (video_sink != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_ELEMENT (video_sink), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* We bring back the pipeline to READY */
|
2004-03-29 17:19:38 +00:00
|
|
|
if (GST_STATE (GST_ELEMENT (play)) != GST_STATE_READY) {
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-29 17:19:38 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* Getting needed objects */
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (video_thread, "video_thread", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (old_video_sink, "video_sink", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (video_scaler, "video_scaler", FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* Unlinking old video sink from video scaler, removing it from pipeline,
|
|
|
|
adding the new one and linking it */
|
|
|
|
gst_element_unlink (video_scaler, old_video_sink);
|
|
|
|
gst_bin_remove (GST_BIN (video_thread), old_video_sink);
|
|
|
|
gst_bin_add (GST_BIN (video_thread), video_sink);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (!gst_element_link (video_scaler, video_sink)) {
|
|
|
|
GST_ERROR_OBJECT (play, "could not link video_scaler to video_sink");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
g_hash_table_replace (play->priv->elements, "video_sink", video_sink);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
video_sink_element = gst_play_get_sink_element (play, video_sink,
|
2004-03-14 22:34:30 +00:00
|
|
|
GST_PLAY_SINK_TYPE_VIDEO);
|
2003-12-14 17:00:18 +00:00
|
|
|
if (GST_IS_ELEMENT (video_sink_element)) {
|
|
|
|
g_hash_table_replace (play->priv->elements, "video_sink_element",
|
2004-03-15 19:32:25 +00:00
|
|
|
video_sink_element);
|
2004-01-07 21:49:25 +00:00
|
|
|
if (GST_IS_X_OVERLAY (video_sink_element)) {
|
|
|
|
g_signal_connect (G_OBJECT (video_sink_element),
|
2004-03-15 19:32:25 +00:00
|
|
|
"desired_size_changed", G_CALLBACK (gst_play_have_video_size), play);
|
2004-01-07 21:49:25 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
}
|
|
|
|
|
2004-03-29 17:19:38 +00:00
|
|
|
ret = gst_element_set_state (video_sink, GST_STATE (GST_ELEMENT (play)));
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_set_audio_sink:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @audio_sink: a #GstElement.
|
|
|
|
*
|
|
|
|
* Set @audio_sink as the audio sink element of @play.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if call succeeded.
|
|
|
|
*/
|
|
|
|
gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_set_audio_sink (GstPlay * play, GstElement * audio_sink)
|
2003-12-07 17:56:10 +00:00
|
|
|
{
|
2004-02-02 22:18:38 +00:00
|
|
|
GstElement *old_audio_sink, *audio_thread, *volume, *audio_sink_element;
|
2004-03-29 17:19:38 +00:00
|
|
|
GstElementStateReturn ret;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2003-12-21 19:48:40 +00:00
|
|
|
g_return_val_if_fail (audio_sink != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_ELEMENT (audio_sink), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* We bring back the pipeline to READY */
|
2004-03-29 17:19:38 +00:00
|
|
|
if (GST_STATE (GST_ELEMENT (play)) != GST_STATE_READY) {
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-29 17:19:38 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* Getting needed objects */
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (audio_thread, "audio_thread", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (volume, "volume", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (old_audio_sink, "audio_sink", FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
/* Unlinking old audiosink, removing it from pipeline, putting the new one
|
|
|
|
and linking it */
|
2004-02-02 22:18:38 +00:00
|
|
|
gst_element_unlink (volume, old_audio_sink);
|
2003-12-07 17:56:10 +00:00
|
|
|
gst_bin_remove (GST_BIN (audio_thread), old_audio_sink);
|
|
|
|
gst_bin_add (GST_BIN (audio_thread), audio_sink);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (!gst_element_link (volume, audio_sink)) {
|
|
|
|
GST_ERROR_OBJECT (play, "could not link volume to audio_sink");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-11 22:29:14 +00:00
|
|
|
g_hash_table_replace (play->priv->elements, "audio_sink", audio_sink);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
audio_sink_element = gst_play_get_sink_element (play, audio_sink,
|
2004-03-14 22:34:30 +00:00
|
|
|
GST_PLAY_SINK_TYPE_AUDIO);
|
2003-12-14 17:00:18 +00:00
|
|
|
if (GST_IS_ELEMENT (audio_sink_element)) {
|
|
|
|
g_hash_table_replace (play->priv->elements, "audio_sink_element",
|
2004-03-15 19:32:25 +00:00
|
|
|
audio_sink_element);
|
2003-12-14 17:00:18 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-03-29 17:19:38 +00:00
|
|
|
ret = gst_element_set_state (audio_sink, GST_STATE (GST_ELEMENT (play)));
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_set_visualization:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @element: a #GstElement.
|
|
|
|
*
|
|
|
|
* Set @video_sink as the video sink element of @play.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if call succeeded.
|
|
|
|
*/
|
|
|
|
gboolean
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_set_visualization (GstPlay * play, GstElement * vis_element)
|
2003-12-08 16:01:49 +00:00
|
|
|
{
|
2004-01-25 12:28:05 +00:00
|
|
|
GstElement *vis_bin, *vis_queue, *old_vis_element, *vis_cs;
|
2003-12-08 16:01:49 +00:00
|
|
|
gboolean was_playing = FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2003-12-21 19:48:40 +00:00
|
|
|
g_return_val_if_fail (vis_element != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
/* Getting needed objects */
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (vis_bin, "vis_bin", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (vis_queue, "vis_queue", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (old_vis_element, "vis_element", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (vis_cs, "vis_cs", FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* We bring back the pipeline to PAUSED */
|
|
|
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
2004-03-29 17:19:38 +00:00
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-01-25 12:28:05 +00:00
|
|
|
was_playing = TRUE;
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
}
|
2004-01-25 12:28:05 +00:00
|
|
|
|
|
|
|
gst_element_unlink_many (vis_queue, old_vis_element, vis_cs, NULL);
|
|
|
|
gst_bin_remove (GST_BIN (vis_bin), old_vis_element);
|
|
|
|
gst_bin_add (GST_BIN (vis_bin), vis_element);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (!gst_element_link_many (vis_queue, vis_element, vis_cs, NULL)) {
|
|
|
|
GST_ERROR_OBJECT (play, "could not link vis bin elements");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-03-29 17:19:38 +00:00
|
|
|
if (was_playing) {
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-29 17:19:38 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_play_connect_visualization:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @connect: a #gboolean indicating wether or not
|
|
|
|
* visualization should be connected.
|
|
|
|
*
|
|
|
|
* Connect or disconnect visualization bin in @play.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if call succeeded.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
|
|
|
{
|
2004-01-25 12:28:05 +00:00
|
|
|
GstElement *video_thread, *vis_queue, *vis_bin, *video_switch, *identity;
|
|
|
|
GstPad *tee_pad1, *vis_queue_pad, *vis_bin_pad, *switch_pad;
|
|
|
|
gboolean was_playing = FALSE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-08 16:01:49 +00:00
|
|
|
g_return_val_if_fail (play != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-02-14 18:37:48 +00:00
|
|
|
/* Until i fix the switch */
|
|
|
|
return TRUE;
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Getting needed objects */
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (video_thread, "video_thread", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (vis_bin, "vis_bin", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (vis_queue, "vis_queue", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (video_switch, "video_switch", FALSE);
|
|
|
|
GST_PLAY_HASH_LOOKUP (identity, "identity", FALSE);
|
|
|
|
|
|
|
|
GST_PLAY_HASH_LOOKUP (tee_pad1, "tee_pad1", FALSE);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
vis_queue_pad = gst_element_get_pad (vis_queue, "sink");
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* Check if the vis element is in the pipeline. That means visualization is
|
|
|
|
connected already */
|
2004-01-25 12:28:05 +00:00
|
|
|
if (gst_element_get_managing_bin (vis_bin)) {
|
2004-03-14 22:34:30 +00:00
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* If we are supposed to connect then nothing to do we return */
|
|
|
|
if (connect) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Disconnecting visualization */
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* We bring back the pipeline to PAUSED */
|
|
|
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
2004-03-29 17:19:38 +00:00
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-01-25 12:28:05 +00:00
|
|
|
was_playing = TRUE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Unlinking, removing */
|
|
|
|
gst_pad_unlink (tee_pad1, vis_queue_pad);
|
|
|
|
vis_bin_pad = gst_element_get_pad (vis_bin, "src");
|
|
|
|
switch_pad = gst_pad_get_peer (vis_bin_pad);
|
|
|
|
gst_pad_unlink (vis_bin_pad, switch_pad);
|
|
|
|
gst_element_release_request_pad (video_switch, switch_pad);
|
|
|
|
gst_object_ref (GST_OBJECT (vis_bin));
|
|
|
|
gst_bin_remove (GST_BIN (video_thread), vis_bin);
|
2004-03-14 22:34:30 +00:00
|
|
|
} else {
|
|
|
|
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
/* If we are supposed to disconnect then nothing to do we return */
|
|
|
|
if (!connect) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Connecting visualization */
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* We bring back the pipeline to PAUSED */
|
|
|
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
2004-03-29 17:19:38 +00:00
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-01-25 12:28:05 +00:00
|
|
|
was_playing = TRUE;
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-01-25 12:28:05 +00:00
|
|
|
/* Adding, linking */
|
|
|
|
play->priv->handoff_hid = g_signal_connect (G_OBJECT (identity),
|
2004-03-15 19:32:25 +00:00
|
|
|
"handoff", G_CALLBACK (gst_play_identity_handoff), play);
|
2004-01-25 12:28:05 +00:00
|
|
|
gst_bin_add (GST_BIN (video_thread), vis_bin);
|
|
|
|
gst_pad_link (tee_pad1, vis_queue_pad);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (!gst_element_link (vis_bin, video_switch)) {
|
|
|
|
GST_ERROR_OBJECT (play, "could not link vis bin to video switch");
|
|
|
|
return FALSE;
|
|
|
|
}
|
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS:
2004-01-23 Julien MOUTTE <julien@moutte.net>
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
(gst_play_set_location), (gst_play_seek_to_time),
(gst_play_set_audio_sink), (gst_play_set_visualization),
(gst_play_connect_visualization), (gst_play_get_sink_element): Reworked
the pipeline from scratch. Visualization is back and switch went out as
i realized it was not possible to use the way i wanted.
* sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear),
(gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext
clearing in state change from READY to NULL. So that one can clean the
X ressources keeping the element.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state),
(gst_xvimagesink_colorbalance_set_value),
(gst_xvimagesink_colorbalance_get_value),
(gst_xvimagesink_set_property), (gst_xvimagesink_dispose),
(gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state
change from READY to NULL and fixed some stupid bugs in colorbalance
get/set values. Also added the following feature : when nobody tries to
set some values to the colorbalance levels before the xcontext is
grabbed, then when creating channels list from Xv attributes we set the
internal values to the Xv defaults. This way we handle buggy Xv drivers
that set default hue values far from the middle of the range (Thanks
to Jon Trowbridge for pointing that issue).
* sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if
colorbalance levels have been set before xcontext is grabbed.
2004-01-22 23:54:34 +00:00
|
|
|
}
|
|
|
|
|
2004-03-29 17:19:38 +00:00
|
|
|
if (was_playing) {
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
|
|
|
|
ret = gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
2004-07-08 17:34:08 +00:00
|
|
|
if (ret == GST_STATE_FAILURE) {
|
|
|
|
GST_ERROR_OBJECT (play, "failed setting to READY");
|
2004-03-29 17:19:38 +00:00
|
|
|
return FALSE;
|
2004-07-08 17:34:08 +00:00
|
|
|
}
|
2004-03-29 17:19:38 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-03-15 21:41:35 +00:00
|
|
|
/**
|
|
|
|
* gst_play_get_framerate:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
*
|
|
|
|
* Get the video framerate from @play.
|
|
|
|
*
|
|
|
|
* Returns: a #gdouble indicating video framerate in frame per second.
|
|
|
|
*/
|
|
|
|
gdouble
|
|
|
|
gst_play_get_framerate (GstPlay * play)
|
|
|
|
{
|
|
|
|
GstElement *video_element = NULL;
|
|
|
|
GstPad *video_pad = NULL;
|
|
|
|
GstCaps *video_pad_caps = NULL;
|
|
|
|
GstStructure *structure = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), 0);
|
|
|
|
|
2004-07-08 14:38:48 +00:00
|
|
|
GST_PLAY_HASH_LOOKUP (video_element, "video_sink", 0);
|
2004-03-15 21:41:35 +00:00
|
|
|
video_pad = gst_element_get_pad (video_element, "sink");
|
|
|
|
if (!GST_IS_PAD (video_pad))
|
|
|
|
return 0;
|
|
|
|
video_pad_caps = (GstCaps *) gst_pad_get_negotiated_caps (video_pad);
|
|
|
|
if (!GST_IS_CAPS (video_pad_caps))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
structure = gst_caps_get_structure (video_pad_caps, 0);
|
|
|
|
|
|
|
|
if (structure) {
|
|
|
|
gdouble value;
|
|
|
|
|
|
|
|
gst_structure_get_double (structure, "framerate", &value);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
/**
|
|
|
|
* gst_play_get_sink_element:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @element: a #GstElement.
|
|
|
|
* @sink_type: a #GstPlaySinkType.
|
|
|
|
*
|
|
|
|
* Searches recursively for a sink #GstElement with
|
|
|
|
* type @sink_type in @element which is supposed to be a #GstBin.
|
|
|
|
*
|
|
|
|
* Returns: the sink #GstElement of @element.
|
|
|
|
*/
|
|
|
|
GstElement *
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_get_sink_element (GstPlay * play,
|
|
|
|
GstElement * element, GstPlaySinkType sink_type)
|
2003-12-07 19:02:31 +00:00
|
|
|
{
|
|
|
|
GList *elements = NULL;
|
|
|
|
const GList *pads = NULL;
|
|
|
|
gboolean has_src, has_correct_type;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_PLAY (play), NULL);
|
|
|
|
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
|
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "looking for sink element in %s",
|
|
|
|
GST_ELEMENT_NAME (element));
|
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (!GST_IS_BIN (element)) {
|
2004-07-08 13:44:06 +00:00
|
|
|
/* since its not a bin, we'll assume this
|
2003-12-14 17:00:18 +00:00
|
|
|
* element is a sink element */
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "not a bin, returning %s as sink element",
|
|
|
|
GST_ELEMENT_NAME (element));
|
2003-12-14 17:00:18 +00:00
|
|
|
return element;
|
|
|
|
}
|
2003-12-07 19:02:31 +00:00
|
|
|
|
|
|
|
elements = (GList *) gst_bin_get_list (GST_BIN (element));
|
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
/* traverse all elements looking for one without src pad */
|
2003-12-07 19:02:31 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
while (elements) {
|
|
|
|
element = GST_ELEMENT (elements->data);
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "looking at element %s",
|
|
|
|
GST_ELEMENT_NAME (element));
|
2003-12-14 17:00:18 +00:00
|
|
|
|
|
|
|
/* Recursivity :) */
|
|
|
|
|
|
|
|
if (GST_IS_BIN (element)) {
|
|
|
|
element = gst_play_get_sink_element (play, element, sink_type);
|
|
|
|
if (GST_IS_ELEMENT (element))
|
2004-03-15 19:32:25 +00:00
|
|
|
return element;
|
2004-03-14 22:34:30 +00:00
|
|
|
} else {
|
2003-12-14 17:00:18 +00:00
|
|
|
pads = gst_element_get_pad_list (element);
|
|
|
|
has_src = FALSE;
|
|
|
|
has_correct_type = FALSE;
|
|
|
|
while (pads) {
|
2004-03-15 19:32:25 +00:00
|
|
|
/* check for src pad */
|
|
|
|
if (GST_PAD_DIRECTION (GST_PAD (pads->data)) == GST_PAD_SRC) {
|
2004-07-08 13:44:06 +00:00
|
|
|
GST_DEBUG_OBJECT (play, "element %s has a src pad",
|
|
|
|
GST_ELEMENT_NAME (element));
|
2004-03-15 19:32:25 +00:00
|
|
|
has_src = TRUE;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
/* If not a src pad checking caps */
|
2004-07-08 13:44:06 +00:00
|
|
|
GstPad *pad;
|
2004-03-15 19:32:25 +00:00
|
|
|
GstCaps *caps;
|
|
|
|
GstStructure *structure;
|
2004-07-08 13:44:06 +00:00
|
|
|
int i;
|
2004-03-15 19:32:25 +00:00
|
|
|
gboolean has_video_cap = FALSE;
|
|
|
|
gboolean has_audio_cap = FALSE;
|
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
pad = GST_PAD (pads->data);
|
|
|
|
caps = gst_pad_get_caps (pad);
|
|
|
|
/* loop over all caps members to find mime types */
|
|
|
|
for (i = 0; i < gst_caps_get_size (caps); ++i) {
|
|
|
|
structure = gst_caps_get_structure (caps, i);
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (play,
|
|
|
|
"looking at caps %d pad %s:%s on element %s with mime %s", i,
|
|
|
|
GST_DEBUG_PAD_NAME (pad),
|
|
|
|
GST_ELEMENT_NAME (element), gst_structure_get_name (structure));
|
|
|
|
|
|
|
|
if (strcmp (gst_structure_get_name (structure),
|
|
|
|
"audio/x-raw-int") == 0) {
|
|
|
|
has_audio_cap = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp (gst_structure_get_name (structure),
|
|
|
|
"video/x-raw-yuv") == 0 ||
|
|
|
|
strcmp (gst_structure_get_name (structure),
|
|
|
|
"video/x-raw-rgb") == 0) {
|
|
|
|
has_video_cap = TRUE;
|
|
|
|
}
|
2004-03-15 19:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gst_caps_free (caps);
|
|
|
|
|
|
|
|
switch (sink_type) {
|
|
|
|
case GST_PLAY_SINK_TYPE_AUDIO:
|
|
|
|
if (has_audio_cap)
|
|
|
|
has_correct_type = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_PLAY_SINK_TYPE_VIDEO:
|
|
|
|
if (has_video_cap)
|
|
|
|
has_correct_type = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_PLAY_SINK_TYPE_ANY:
|
|
|
|
if ((has_video_cap) || (has_audio_cap))
|
|
|
|
has_correct_type = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
has_correct_type = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pads = g_list_next (pads);
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2004-07-08 13:44:06 +00:00
|
|
|
if ((!has_src) && (has_correct_type)) {
|
|
|
|
GST_DEBUG_OBJECT (play, "found %s with src pad and correct type",
|
|
|
|
GST_ELEMENT_NAME (element));
|
2004-03-15 19:32:25 +00:00
|
|
|
return element;
|
2004-07-08 13:44:06 +00:00
|
|
|
}
|
2003-12-07 19:02:31 +00:00
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
elements = g_list_next (elements);
|
|
|
|
}
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
/* we didn't find a sink element */
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-07 19:02:31 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-07-08 17:34:08 +00:00
|
|
|
/**
|
|
|
|
* gst_play_get_all_by_interface:
|
|
|
|
* @play: a #GstPlay.
|
|
|
|
* @interface: an interface.
|
|
|
|
*
|
|
|
|
* Returns all elements that are used by @play implementing the given interface.
|
|
|
|
*
|
|
|
|
* Returns: a #GList of #GstElement implementing the interface.
|
|
|
|
*/
|
|
|
|
GList *
|
|
|
|
gst_play_get_all_by_interface (GstPlay * play, GType interface)
|
|
|
|
{
|
|
|
|
GstElement *output_bin;
|
|
|
|
|
|
|
|
GST_PLAY_HASH_LOOKUP (output_bin, "output_bin", NULL);
|
|
|
|
return gst_bin_get_all_by_interface (GST_BIN (output_bin), interface);
|
|
|
|
}
|
|
|
|
|
2003-12-07 17:56:10 +00:00
|
|
|
GstPlay *
|
2004-03-14 22:34:30 +00:00
|
|
|
gst_play_new (GError ** error)
|
2003-12-07 17:56:10 +00:00
|
|
|
{
|
|
|
|
GstPlay *play = g_object_new (GST_TYPE_PLAY, NULL);
|
2004-01-31 15:56:32 +00:00
|
|
|
|
2004-03-14 22:34:30 +00:00
|
|
|
if (play->priv->error) {
|
|
|
|
if (error) {
|
2004-02-02 10:19:38 +00:00
|
|
|
*error = play->priv->error;
|
|
|
|
play->priv->error = NULL;
|
2004-03-14 22:34:30 +00:00
|
|
|
} else {
|
|
|
|
g_warning ("Error creating GstPlay object.\n%s",
|
2004-03-15 19:32:25 +00:00
|
|
|
play->priv->error->message);
|
2004-02-02 10:19:38 +00:00
|
|
|
g_error_free (play->priv->error);
|
|
|
|
}
|
2004-01-31 15:56:32 +00:00
|
|
|
}
|
2003-12-07 17:56:10 +00:00
|
|
|
return play;
|
|
|
|
}
|
|
|
|
|
2003-12-07 13:29:10 +00:00
|
|
|
/* =========================================== */
|
|
|
|
/* */
|
|
|
|
/* Object typing & Creation */
|
|
|
|
/* */
|
|
|
|
/* =========================================== */
|
|
|
|
|
|
|
|
GType
|
|
|
|
gst_play_get_type (void)
|
|
|
|
{
|
|
|
|
static GType play_type = 0;
|
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
if (!play_type) {
|
|
|
|
static const GTypeInfo play_info = {
|
|
|
|
sizeof (GstPlayClass),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(GClassInitFunc) gst_play_class_init,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
sizeof (GstPlay),
|
|
|
|
0,
|
|
|
|
(GInstanceInitFunc) gst_play_init,
|
|
|
|
NULL
|
|
|
|
};
|
2004-03-14 22:34:30 +00:00
|
|
|
|
2003-12-14 17:00:18 +00:00
|
|
|
play_type = g_type_register_static (GST_TYPE_PIPELINE, "GstPlay",
|
2004-03-15 19:32:25 +00:00
|
|
|
&play_info, 0);
|
2003-12-14 17:00:18 +00:00
|
|
|
}
|
2003-12-07 13:29:10 +00:00
|
|
|
|
|
|
|
return play_type;
|
|
|
|
}
|