diff options
Diffstat (limited to 'gst-libs/gst/play')
-rw-r--r-- | gst-libs/gst/play/gstplay.c | 184 | ||||
-rw-r--r-- | gst-libs/gst/play/gstplay.h | 10 | ||||
-rw-r--r-- | gst-libs/gst/play/play.c | 184 | ||||
-rw-r--r-- | gst-libs/gst/play/play.h | 10 |
4 files changed, 384 insertions, 4 deletions
diff --git a/gst-libs/gst/play/gstplay.c b/gst-libs/gst/play/gstplay.c index 0f1c7632..3e73e440 100644 --- a/gst-libs/gst/play/gstplay.c +++ b/gst-libs/gst/play/gstplay.c @@ -220,6 +220,53 @@ gst_play_pipeline_setup (GstPlay *play) return TRUE; } +static void +gst_play_have_video_size (GstElement *element, gint width, + gint height, GstPlay *play) +{ + 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], + 0, width, height); +} + +static gboolean +gst_play_tick_callback (GstPlay *play) +{ + GstClock *clock = NULL; + + g_return_val_if_fail (play != NULL, FALSE); + g_return_val_if_fail (GST_IS_PLAY (play), FALSE); + + clock = gst_bin_get_clock (GST_BIN (play)); + play->time_nanos = gst_clock_get_time (clock); + + g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK], + 0,play->time_nanos); + + return (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING); +} + +static void +gst_play_state_change (GstElement *element, GstElementState old, + GstElementState state) +{ + GstPlay *play; + + g_return_if_fail (element != NULL); + g_return_if_fail (GST_IS_PLAY (element)); + + play = GST_PLAY (element); + + if (state == GST_STATE_PLAYING) + { + g_timeout_add (200, (GSourceFunc) gst_play_tick_callback, play); + } + + if (GST_ELEMENT_CLASS (parent_class)->state_change) + GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state); +} + /* =========================================== */ /* */ /* Interfaces */ @@ -323,11 +370,14 @@ static void gst_play_class_init (GstPlayClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + parent_class = g_type_class_peek_parent (klass); gobject_class->dispose = gst_play_dispose; + element_class->state_change = gst_play_state_change; + gst_play_signals[TIME_TICK] = g_signal_new ("time_tick", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstPlayClass, time_tick), NULL, NULL, @@ -511,7 +561,7 @@ gst_play_set_data_src (GstPlay *play, GstElement *data_src) gboolean gst_play_set_video_sink (GstPlay *play, GstElement *video_sink) { - GstElement *video_thread, *old_video_sink, *video_scaler; + GstElement *video_thread, *old_video_sink, *video_scaler, *video_sink_element; g_return_val_if_fail (play != NULL, FALSE); g_return_val_if_fail (GST_IS_PLAY (play), FALSE); @@ -540,6 +590,17 @@ gst_play_set_video_sink (GstPlay *play, GstElement *video_sink) g_hash_table_replace (play->elements, "video_sink", video_sink); + video_sink_element = gst_play_get_sink_element (play, video_sink, + GST_PLAY_SINK_TYPE_VIDEO); + if (GST_IS_ELEMENT (video_sink_element)) + { + g_hash_table_replace (play->elements, "video_sink_element", + video_sink_element); + g_signal_connect (G_OBJECT (video_sink_element), "have_video_size", + G_CALLBACK (gst_play_have_video_size), play); + } + + return TRUE; } @@ -596,6 +657,125 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink) return TRUE; } +/** + * 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 * +gst_play_get_sink_element (GstPlay *play, + GstElement *element, GstPlaySinkType sink_type) +{ + GList *elements = NULL; + const GList *pads = NULL; + gboolean has_src, has_correct_type; + + g_return_val_if_fail (play != NULL, NULL); + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_PLAY (play), NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + if (!GST_IS_BIN (element)) + { + /* since its not a bin, we'll presume this + * element is a sink element */ + return element; + } + + elements = (GList *) gst_bin_get_list (GST_BIN (element)); + + /* traverse all elements looking for a src pad */ + + while (elements) + { + + element = GST_ELEMENT (elements->data); + + /* Recursivity :) */ + + if (GST_IS_BIN (element)) + { + element = gst_play_get_sink_element (play, element, sink_type); + if (GST_IS_ELEMENT (element)) + { + return element; + } + } + else + { + + pads = gst_element_get_pad_list (element); + has_src = FALSE; + has_correct_type = FALSE; + while (pads) + { + /* check for src pad */ + if (GST_PAD_DIRECTION (GST_PAD (pads->data)) == GST_PAD_SRC) + { + has_src = TRUE; + break; + } + else + { + /* If not a src pad checking caps */ + GstCaps *caps; + caps = gst_pad_get_caps (GST_PAD (pads->data)); + while (caps) + { + gboolean has_video_cap = FALSE, has_audio_cap = FALSE; + if (g_ascii_strcasecmp (gst_caps_get_mime (caps), + "audio/x-raw-int") == 0) + { + has_audio_cap = TRUE; + } + if ((g_ascii_strcasecmp (gst_caps_get_mime (caps), + "video/x-raw-yuv") == 0) || + (g_ascii_strcasecmp (gst_caps_get_mime (caps), + "video/x-raw-rgb") == 0)) + + { + has_video_cap = TRUE; + } + + 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; + } + caps = caps->next; + } + } + pads = g_list_next (pads); + } + if ((!has_src) && (has_correct_type)) + { + return element; + } + } + elements = g_list_next (elements); + } + /* we didn't find a sink element */ + return NULL; +} + GstPlay * gst_play_new (void) { diff --git a/gst-libs/gst/play/gstplay.h b/gst-libs/gst/play/gstplay.h index 154f0b77..4d999420 100644 --- a/gst-libs/gst/play/gstplay.h +++ b/gst-libs/gst/play/gstplay.h @@ -29,6 +29,13 @@ #define GST_IS_PLAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY)) #define GST_PLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PLAY, GstPlayClass)) +typedef enum +{ + GST_PLAY_SINK_TYPE_AUDIO, + GST_PLAY_SINK_TYPE_VIDEO, + GST_PLAY_SINK_TYPE_ANY, +} GstPlaySinkType; + typedef struct _GstPlay GstPlay; typedef struct _GstPlayClass GstPlayClass; @@ -59,6 +66,9 @@ struct _GstPlayClass GType gst_play_get_type (void); GstPlay * gst_play_new (void); +GstElement * gst_play_get_sink_element (GstPlay *play, + GstElement *element, + GstPlaySinkType sink_type); gboolean gst_play_set_data_src (GstPlay *play, GstElement *data_src); gboolean gst_play_set_video_sink (GstPlay *play, diff --git a/gst-libs/gst/play/play.c b/gst-libs/gst/play/play.c index 0f1c7632..3e73e440 100644 --- a/gst-libs/gst/play/play.c +++ b/gst-libs/gst/play/play.c @@ -220,6 +220,53 @@ gst_play_pipeline_setup (GstPlay *play) return TRUE; } +static void +gst_play_have_video_size (GstElement *element, gint width, + gint height, GstPlay *play) +{ + 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], + 0, width, height); +} + +static gboolean +gst_play_tick_callback (GstPlay *play) +{ + GstClock *clock = NULL; + + g_return_val_if_fail (play != NULL, FALSE); + g_return_val_if_fail (GST_IS_PLAY (play), FALSE); + + clock = gst_bin_get_clock (GST_BIN (play)); + play->time_nanos = gst_clock_get_time (clock); + + g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK], + 0,play->time_nanos); + + return (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING); +} + +static void +gst_play_state_change (GstElement *element, GstElementState old, + GstElementState state) +{ + GstPlay *play; + + g_return_if_fail (element != NULL); + g_return_if_fail (GST_IS_PLAY (element)); + + play = GST_PLAY (element); + + if (state == GST_STATE_PLAYING) + { + g_timeout_add (200, (GSourceFunc) gst_play_tick_callback, play); + } + + if (GST_ELEMENT_CLASS (parent_class)->state_change) + GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state); +} + /* =========================================== */ /* */ /* Interfaces */ @@ -323,11 +370,14 @@ static void gst_play_class_init (GstPlayClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + parent_class = g_type_class_peek_parent (klass); gobject_class->dispose = gst_play_dispose; + element_class->state_change = gst_play_state_change; + gst_play_signals[TIME_TICK] = g_signal_new ("time_tick", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstPlayClass, time_tick), NULL, NULL, @@ -511,7 +561,7 @@ gst_play_set_data_src (GstPlay *play, GstElement *data_src) gboolean gst_play_set_video_sink (GstPlay *play, GstElement *video_sink) { - GstElement *video_thread, *old_video_sink, *video_scaler; + GstElement *video_thread, *old_video_sink, *video_scaler, *video_sink_element; g_return_val_if_fail (play != NULL, FALSE); g_return_val_if_fail (GST_IS_PLAY (play), FALSE); @@ -540,6 +590,17 @@ gst_play_set_video_sink (GstPlay *play, GstElement *video_sink) g_hash_table_replace (play->elements, "video_sink", video_sink); + video_sink_element = gst_play_get_sink_element (play, video_sink, + GST_PLAY_SINK_TYPE_VIDEO); + if (GST_IS_ELEMENT (video_sink_element)) + { + g_hash_table_replace (play->elements, "video_sink_element", + video_sink_element); + g_signal_connect (G_OBJECT (video_sink_element), "have_video_size", + G_CALLBACK (gst_play_have_video_size), play); + } + + return TRUE; } @@ -596,6 +657,125 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink) return TRUE; } +/** + * 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 * +gst_play_get_sink_element (GstPlay *play, + GstElement *element, GstPlaySinkType sink_type) +{ + GList *elements = NULL; + const GList *pads = NULL; + gboolean has_src, has_correct_type; + + g_return_val_if_fail (play != NULL, NULL); + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_PLAY (play), NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + if (!GST_IS_BIN (element)) + { + /* since its not a bin, we'll presume this + * element is a sink element */ + return element; + } + + elements = (GList *) gst_bin_get_list (GST_BIN (element)); + + /* traverse all elements looking for a src pad */ + + while (elements) + { + + element = GST_ELEMENT (elements->data); + + /* Recursivity :) */ + + if (GST_IS_BIN (element)) + { + element = gst_play_get_sink_element (play, element, sink_type); + if (GST_IS_ELEMENT (element)) + { + return element; + } + } + else + { + + pads = gst_element_get_pad_list (element); + has_src = FALSE; + has_correct_type = FALSE; + while (pads) + { + /* check for src pad */ + if (GST_PAD_DIRECTION (GST_PAD (pads->data)) == GST_PAD_SRC) + { + has_src = TRUE; + break; + } + else + { + /* If not a src pad checking caps */ + GstCaps *caps; + caps = gst_pad_get_caps (GST_PAD (pads->data)); + while (caps) + { + gboolean has_video_cap = FALSE, has_audio_cap = FALSE; + if (g_ascii_strcasecmp (gst_caps_get_mime (caps), + "audio/x-raw-int") == 0) + { + has_audio_cap = TRUE; + } + if ((g_ascii_strcasecmp (gst_caps_get_mime (caps), + "video/x-raw-yuv") == 0) || + (g_ascii_strcasecmp (gst_caps_get_mime (caps), + "video/x-raw-rgb") == 0)) + + { + has_video_cap = TRUE; + } + + 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; + } + caps = caps->next; + } + } + pads = g_list_next (pads); + } + if ((!has_src) && (has_correct_type)) + { + return element; + } + } + elements = g_list_next (elements); + } + /* we didn't find a sink element */ + return NULL; +} + GstPlay * gst_play_new (void) { diff --git a/gst-libs/gst/play/play.h b/gst-libs/gst/play/play.h index 154f0b77..4d999420 100644 --- a/gst-libs/gst/play/play.h +++ b/gst-libs/gst/play/play.h @@ -29,6 +29,13 @@ #define GST_IS_PLAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY)) #define GST_PLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PLAY, GstPlayClass)) +typedef enum +{ + GST_PLAY_SINK_TYPE_AUDIO, + GST_PLAY_SINK_TYPE_VIDEO, + GST_PLAY_SINK_TYPE_ANY, +} GstPlaySinkType; + typedef struct _GstPlay GstPlay; typedef struct _GstPlayClass GstPlayClass; @@ -59,6 +66,9 @@ struct _GstPlayClass GType gst_play_get_type (void); GstPlay * gst_play_new (void); +GstElement * gst_play_get_sink_element (GstPlay *play, + GstElement *element, + GstPlaySinkType sink_type); gboolean gst_play_set_data_src (GstPlay *play, GstElement *data_src); gboolean gst_play_set_video_sink (GstPlay *play, |