From e277ba3892378d6562913e2a803f3a126d46c720 Mon Sep 17 00:00:00 2001 From: Lyon Wang Date: Fri, 30 Dec 2016 15:53:21 +0800 Subject: [PATCH 14/26] Specific patches for gstplayer API player: Add get_rotate, set_rotate API - Add gstplayer get_rotate() and set_rotate() API player: Add force-aspect-ratio config - Add get/set force-aspect-ratio config API player: Add set audio / text sink API - Add get/set audio / text sink API Upstream-Status: Inappropriate [i.MX specific] Signed-off-by: Lyon Wang Conflicts: gst-libs/gst/player/gstplayer.c gst-libs/gst/player/gstplayer.h --- gst-libs/gst/player/gstplayer.c | 284 ++++++++++++++++++++++++++++++++++++++++ gst-libs/gst/player/gstplayer.h | 11 ++ 2 files changed, 295 insertions(+) diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c index 273a480..92ad919 100644 --- a/gst-libs/gst/player/gstplayer.c +++ b/gst-libs/gst/player/gstplayer.c @@ -82,6 +82,7 @@ typedef enum CONFIG_QUARK_USER_AGENT = 0, CONFIG_QUARK_POSITION_INTERVAL_UPDATE, CONFIG_QUARK_ACCURATE_SEEK, + CONFIG_QUARK_FORCE_ASPECT_RATIO, CONFIG_QUARK_MAX } ConfigQuarkId; @@ -90,6 +91,7 @@ static const gchar *_config_quark_strings[] = { "user-agent", "position-interval-update", "accurate-seek", + "force-aspect-ratio", }; GQuark _config_quark_table[CONFIG_QUARK_MAX]; @@ -286,6 +288,7 @@ gst_player_init (GstPlayer * self) self->config = gst_structure_new_id (QUARK_CONFIG, CONFIG_QUARK (POSITION_INTERVAL_UPDATE), G_TYPE_UINT, DEFAULT_POSITION_UPDATE_INTERVAL_MS, CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, FALSE, + CONFIG_QUARK (FORCE_ASPECT_RATIO), G_TYPE_BOOLEAN, TRUE, NULL); /* *INDENT-ON* */ @@ -4758,3 +4761,284 @@ gst_player_get_video_snapshot (GstPlayer * self, return sample; } + +/** + * gst_player_get_video_sink: + * @player: #GstPlayer instance + * + * Returns: actual video sink element + */ +GstElement * +gst_player_get_video_sink (GstPlayer * self) +{ + GstElement *sink = NULL; + GstElement *actual_sink = NULL; + GstIteratorResult rc; + GstIterator *it; + GValue item = { 0, }; + g_return_val_if_fail (GST_IS_PLAYER (self), NULL); + + g_object_get (G_OBJECT (self->playbin), "video-sink", &sink, NULL); + if (NULL == sink) { + GST_WARNING_OBJECT (self, "No video-sink found"); + return NULL; + } + it = gst_bin_iterate_sinks ((GstBin *) sink); + do { + rc = gst_iterator_next (it, &item); + if (rc == GST_ITERATOR_OK) { + break; + } + } while (rc != GST_ITERATOR_DONE); + + g_object_unref (sink); + actual_sink = g_value_get_object (&item); + g_value_unset (&item); + gst_iterator_free (it); + + if (NULL == actual_sink) { + GST_WARNING_OBJECT (self, "No video-sink found"); + return NULL; + } + + return actual_sink; +} + +/** + * gst_palyer_set_rotate: + * @player: #GstPlayer instance + * @rotation: rotation degree value + * + * Returns: %TRUE or %FALSE + * + * Set the rotation vaule + */ +gboolean +gst_player_set_rotate (GstPlayer * self, gint rotation) +{ + GstElement *video_sink = NULL; + GObjectClass *gobjclass = NULL; + g_return_val_if_fail (GST_IS_PLAYER (self), FALSE); + + video_sink = gst_player_get_video_sink (self); + if (NULL == video_sink) { + GST_WARNING_OBJECT (self, " cannot get video sink "); + return FALSE; + } + GST_DEBUG_OBJECT (self, "set rotation degree '%d'", rotation); + + gobjclass = G_OBJECT_GET_CLASS (G_OBJECT (video_sink)); + if (g_object_class_find_property (gobjclass, "rotate") + && g_object_class_find_property (gobjclass, "reconfig")) { + g_object_set (G_OBJECT (video_sink), "rotate", rotation / 90, NULL); + g_object_set (G_OBJECT (video_sink), "reconfig", 1, NULL); + } else if (g_object_class_find_property (gobjclass, "rotate-method")) { + g_object_set (G_OBJECT (video_sink), "rotate-method", rotation / 90, NULL); + } else { + GST_INFO_OBJECT (self, "can't set rotation for current video sink %s'", + gst_element_get_name (video_sink)); + return FALSE; + } + + return TRUE; +} + +/** + * gst_player_get_rotate: + * @player: #GstPlayer instance + * + * Returns: the rotation degree value + */ +gint +gst_player_get_rotate (GstPlayer * self) +{ + GstElement *video_sink = NULL; + GObjectClass *gobjclass = NULL; + gint rotation = 0; + g_return_val_if_fail (GST_IS_PLAYER (self), 0); + + video_sink = gst_player_get_video_sink (self); + if (NULL == video_sink) { + GST_WARNING_OBJECT (self, " cannot get video sink "); + return 0; + } + + /* check if the element has "rotate" property */ + gobjclass = G_OBJECT_GET_CLASS (video_sink); + if (g_object_class_find_property (gobjclass, "rotate")) { + g_object_get (G_OBJECT (video_sink), "rotate", &rotation, NULL); + rotation = rotation * 90; + } else if (g_object_class_find_property (gobjclass, "rotate-method")) { + g_object_get (G_OBJECT (video_sink), "rotate-method", &rotation, NULL); + rotation = rotation * 90; + } + + GST_DEBUG_OBJECT (self, "get rotation degree '%d'", rotation); + + return rotation; +} + +/** + * gst_player_config_set_force_aspect_ratio: + * @player: #GstPlayer instance + * @force_aspect_ratio: keey original aspect ratio or not + * + * Enable or disable force aspect ratio + * force_aspect_ratio seeking is TRUE by default. + * + * Since: 1.12 + */ +void +gst_player_config_set_force_aspect_ratio (GstPlayer * self, gboolean force_aspect_ratio) +{ + GstStructure *config = self->config; + g_return_if_fail (config != NULL); + + gst_structure_id_set (config, + CONFIG_QUARK (FORCE_ASPECT_RATIO), G_TYPE_BOOLEAN, force_aspect_ratio, NULL); + + g_object_set(self->playbin, "force-aspect-ratio", force_aspect_ratio, NULL); +} + +/** + * gst_player_config_get_force_aspect_ratio: + * @config: a #GstPlayer configuration + * + * Returns: %TRUE if force-aspect-ratio is enabled + * + * Since 1.12 + */ +gboolean +gst_player_config_get_force_aspect_ratio (const GstStructure * config) +{ + gboolean force_aspect_ratio = TRUE; + + g_return_val_if_fail (config != NULL, FALSE); + + gst_structure_id_get (config, + CONFIG_QUARK (FORCE_ASPECT_RATIO), G_TYPE_BOOLEAN, &force_aspect_ratio, NULL); + + return force_aspect_ratio; +} + +/** + * gst_player_set_audio_sink: + * @player: #GstPlayer instance + * @audio_sink: the custom audio sink to set + * + * Returns: %TRUE or %FALSE + * + * Set the customize audio sink + */ +gboolean +gst_player_set_audio_sink (GstPlayer * self, GstElement * audio_sink) +{ + g_return_val_if_fail (GST_IS_PLAYER (self), FALSE); + g_return_val_if_fail (audio_sink != NULL, FALSE); + + g_object_set (G_OBJECT (self->playbin), "audio-sink", audio_sink, NULL); + return TRUE; +} + +/** + * gst_player_set_text_sink: + * @player: #GstPlayer instance + * @text_sink: the custom text sink to set + * + * Returns: %TRUE or %FALSE + * + * Set the customize text sink + */ +gboolean +gst_player_set_text_sink (GstPlayer * self, GstElement * text_sink) +{ + g_return_val_if_fail (GST_IS_PLAYER (self), FALSE); + g_return_val_if_fail (text_sink != NULL, FALSE); + + g_object_set (G_OBJECT (self->playbin), "text-sink", text_sink, NULL); + return TRUE; +} + +/** + * gst_player_get_audio_sink: + * @player: #GstPlayer instance + * + * Returns: actual audio sink element + */ +GstElement * +gst_player_get_audio_sink (GstPlayer * self) +{ + GstElement *sink = NULL; + GstElement *actual_sink = NULL; + GstIteratorResult rc; + GstIterator *it; + GValue item = { 0, }; + g_return_val_if_fail (GST_IS_PLAYER (self), NULL); + + g_object_get (G_OBJECT (self->playbin), "audio-sink", &sink, NULL); + if (NULL == sink) { + GST_WARNING_OBJECT (self, "No audio-sink found"); + return NULL; + } + it = gst_bin_iterate_sinks ((GstBin *) sink); + do { + rc = gst_iterator_next (it, &item); + if (rc == GST_ITERATOR_OK) { + break; + } + } while (rc != GST_ITERATOR_DONE); + + g_object_unref (sink); + actual_sink = g_value_get_object (&item); + g_value_unset (&item); + gst_iterator_free (it); + + if (NULL == actual_sink) { + GST_WARNING_OBJECT (self, "No auido-sink found"); + return NULL; + } + + return actual_sink; +} + +/** + * gst_player_get_text_sink: + * @player: #GstPlayer instance + * + * Returns: actual text sink element + */ +GstElement * +gst_player_get_text_sink (GstPlayer * self) +{ + GstElement *sink = NULL; + GstElement *actual_sink = NULL; + GstIteratorResult rc; + GstIterator *it; + GValue item = { 0, }; + g_return_val_if_fail (GST_IS_PLAYER (self), NULL); + + g_object_get (G_OBJECT (self->playbin), "text-sink", &sink, NULL); + if (NULL == sink) { + GST_WARNING_OBJECT (self, "No text-sink found"); + return NULL; + } + it = gst_bin_iterate_sinks ((GstBin *) sink); + do { + rc = gst_iterator_next (it, &item); + if (rc == GST_ITERATOR_OK) { + break; + } + } while (rc != GST_ITERATOR_DONE); + + g_object_unref (sink); + actual_sink = g_value_get_object (&item); + g_value_unset (&item); + gst_iterator_free (it); + + if (NULL == actual_sink) { + GST_WARNING_OBJECT (self, "No text-sink found"); + return NULL; + } + + return actual_sink; +} diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h index 0338d1a..f444918 100644 --- a/gst-libs/gst/player/gstplayer.h +++ b/gst-libs/gst/player/gstplayer.h @@ -216,6 +216,17 @@ typedef enum GstSample * gst_player_get_video_snapshot (GstPlayer * player, GstPlayerSnapshotFormat format, GstStructure * config); +/* Custom gstplayer API */ +gboolean gst_player_set_rotate (GstPlayer * player, gint rotation); +gint gst_player_get_rotate (GstPlayer * player); + +void gst_player_config_set_force_aspect_ratio (GstPlayer * self, gboolean force_aspect_ratio); +gboolean gst_player_config_get_force_aspect_ratio (const GstStructure * config); + +gboolean gst_player_set_audio_sink (GstPlayer * player, GstElement * audio_sink); +gboolean gst_player_set_text_sink (GstPlayer * player, GstElement * text_sink); +GstElement * gst_player_get_audio_sink (GstPlayer * player); +GstElement * gst_player_get_text_sink (GstPlayer * player); G_END_DECLS -- 1.9.1