From 14aeb6ae37c0f137d7f3038efc51d25f8f371751 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 20 Nov 2018 14:51:36 +0800 Subject: [PATCH 05/11] playbin3: Fix qt videoplayer cannot change video state Change-Id: I765bbe0caebe333855bd16fdd0843e0257491246 Signed-off-by: shine.liu Signed-off-by: Jeffy Chen --- gst/playback/gstplaybin3.c | 256 ++++++++++++++++++++++++++++++++++++- 1 file changed, 252 insertions(+), 4 deletions(-) diff --git a/gst/playback/gstplaybin3.c b/gst/playback/gstplaybin3.c index a732160..c22d9db 100644 --- a/gst/playback/gstplaybin3.c +++ b/gst/playback/gstplaybin3.c @@ -532,6 +532,16 @@ struct _GstPlayBin3Class /* get the last video sample and convert it to the given caps */ GstSample *(*convert_sample) (GstPlayBin3 * playbin, GstCaps * caps); + + /* notify app that number of audio/video/text streams changed */ + void (*video_changed) (GstPlayBin3 * playbin); + void (*audio_changed) (GstPlayBin3 * playbin); + void (*text_changed) (GstPlayBin3 * playbin); + + /* get audio/video/text tags for a stream */ + GstTagList *(*get_video_tags) (GstPlayBin3 * playbin, gint stream); + GstTagList *(*get_audio_tags) (GstPlayBin3 * playbin, gint stream); + GstTagList *(*get_text_tags) (GstPlayBin3 * playbin, gint stream); }; /* props */ @@ -565,6 +575,12 @@ enum PROP_SUBURI, PROP_CURRENT_SUBURI, PROP_FLAGS, + PROP_N_VIDEO, + PROP_CURRENT_VIDEO, + PROP_N_AUDIO, + PROP_CURRENT_AUDIO, + PROP_N_TEXT, + PROP_CURRENT_TEXT, PROP_SUBTITLE_ENCODING, PROP_AUDIO_SINK, PROP_VIDEO_SINK, @@ -597,6 +613,12 @@ enum SIGNAL_CONVERT_SAMPLE, SIGNAL_SOURCE_SETUP, SIGNAL_ELEMENT_SETUP, + SIGNAL_VIDEO_CHANGED, + SIGNAL_AUDIO_CHANGED, + SIGNAL_TEXT_CHANGED, + SIGNAL_GET_VIDEO_TAGS, + SIGNAL_GET_AUDIO_TAGS, + SIGNAL_GET_TEXT_TAGS, LAST_SIGNAL }; @@ -621,6 +643,13 @@ static void gst_play_bin3_deep_element_added (GstBin * playbin, static gboolean gst_play_bin3_send_event (GstElement * element, GstEvent * event); +static GstTagList *gst_play_bin3_get_video_tags (GstPlayBin3 * playbin, + gint stream); +static GstTagList *gst_play_bin3_get_audio_tags (GstPlayBin3 * playbin, + gint stream); +static GstTagList *gst_play_bin3_get_text_tags (GstPlayBin3 * playbin, + gint stream); + static GstSample *gst_play_bin3_convert_sample (GstPlayBin3 * playbin, GstCaps * caps); @@ -755,6 +784,36 @@ gst_play_bin3_class_init (GstPlayBin3Class * klass) GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_N_VIDEO, + g_param_spec_int ("n-video", "Number Video", + "Total number of video streams", 0, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO, + g_param_spec_int ("current-video", "Current Video", + "Currently playing video stream (-1 = auto)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_N_AUDIO, + g_param_spec_int ("n-audio", "Number Audio", + "Total number of audio streams", 0, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO, + g_param_spec_int ("current-audio", "Current audio", + "Currently playing audio stream (-1 = auto)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_N_TEXT, + g_param_spec_int ("n-text", "Number Text", + "Total number of text streams", 0, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT, + g_param_spec_int ("current-text", "Current Text", + "Currently playing text stream (-1 = auto)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, g_param_spec_string ("subtitle-encoding", "subtitle encoding", "Encoding to assume if input subtitles are not in UTF-8 encoding. " @@ -1024,6 +1083,41 @@ gst_play_bin3_class_init (GstPlayBin3Class * klass) g_signal_new ("element-setup", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + gst_play_bin3_signals[SIGNAL_VIDEO_CHANGED] = + g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBin3Class, video_changed), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_play_bin3_signals[SIGNAL_AUDIO_CHANGED] = + g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBin3Class, audio_changed), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_play_bin3_signals[SIGNAL_TEXT_CHANGED] = + g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBin3Class, text_changed), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_play_bin3_signals[SIGNAL_GET_VIDEO_TAGS] = + g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBin3Class, get_video_tags), NULL, NULL, + g_cclosure_marshal_generic, GST_TYPE_TAG_LIST, 1, G_TYPE_INT); + + gst_play_bin3_signals[SIGNAL_GET_AUDIO_TAGS] = + g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBin3Class, get_audio_tags), NULL, NULL, + g_cclosure_marshal_generic, GST_TYPE_TAG_LIST, 1, G_TYPE_INT); + + gst_play_bin3_signals[SIGNAL_GET_TEXT_TAGS] = + g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBin3Class, get_text_tags), NULL, NULL, + g_cclosure_marshal_generic, GST_TYPE_TAG_LIST, 1, G_TYPE_INT); /** * GstPlayBin3::convert-sample * @playbin: a #GstPlayBin3 @@ -1045,6 +1139,10 @@ gst_play_bin3_class_init (GstPlayBin3Class * klass) G_STRUCT_OFFSET (GstPlayBin3Class, convert_sample), NULL, NULL, NULL, GST_TYPE_SAMPLE, 1, GST_TYPE_CAPS); + klass->get_video_tags = gst_play_bin3_get_video_tags; + klass->get_audio_tags = gst_play_bin3_get_audio_tags; + klass->get_text_tags = gst_play_bin3_get_text_tags; + klass->convert_sample = gst_play_bin3_convert_sample; gst_element_class_set_static_metadata (gstelement_klass, @@ -1559,6 +1657,72 @@ get_group (GstPlayBin3 * playbin) return result; } +static GstTagList * +get_tags (GstPlayBin3 * playbin, gint type, gint stream) +{ + GstTagList *result; + GPtrArray *channels; + GstPad *sinkpad; + + switch (type) { + case PLAYBIN_STREAM_AUDIO: + channels = playbin->combiner[PLAYBIN_STREAM_AUDIO].streams; + break; + case PLAYBIN_STREAM_VIDEO: + channels = playbin->combiner[PLAYBIN_STREAM_VIDEO].streams; + break; + case PLAYBIN_STREAM_TEXT: + channels = playbin->combiner[PLAYBIN_STREAM_TEXT].streams; + break; + default: + channels = NULL; + break; + } + + if (!channels || stream >= channels->len) + return NULL; + + sinkpad = g_ptr_array_index (channels, stream); + g_object_get (sinkpad, "tags", &result, NULL); + + return result; +} + +static GstTagList * +gst_play_bin3_get_video_tags (GstPlayBin3 * playbin, gint stream) +{ + GstTagList *result; + + GST_PLAY_BIN3_LOCK (playbin); + result = get_tags (playbin, PLAYBIN_STREAM_VIDEO, stream); + GST_PLAY_BIN3_UNLOCK (playbin); + + return result; +} + +static GstTagList * +gst_play_bin3_get_audio_tags (GstPlayBin3 * playbin, gint stream) +{ + GstTagList *result; + + GST_PLAY_BIN3_LOCK (playbin); + result = get_tags (playbin, PLAYBIN_STREAM_AUDIO, stream); + GST_PLAY_BIN3_UNLOCK (playbin); + + return result; +} + +static GstTagList * +gst_play_bin3_get_text_tags (GstPlayBin3 * playbin, gint stream) +{ + GstTagList *result; + + GST_PLAY_BIN3_LOCK (playbin); + result = get_tags (playbin, PLAYBIN_STREAM_TEXT, stream); + GST_PLAY_BIN3_UNLOCK (playbin); + + return result; +} static GstSample * gst_play_bin3_convert_sample (GstPlayBin3 * playbin, GstCaps * caps) @@ -1772,6 +1936,15 @@ gst_play_bin3_set_property (GObject * object, guint prop_id, GST_SOURCE_GROUP_UNLOCK (playbin->curr_group); } break; + case PROP_CURRENT_VIDEO: + gst_play_bin3_set_current_video_stream (playbin, g_value_get_int (value)); + break; + case PROP_CURRENT_AUDIO: + gst_play_bin3_set_current_audio_stream (playbin, g_value_get_int (value)); + break; + case PROP_CURRENT_TEXT: + gst_play_bin3_set_current_text_stream (playbin, g_value_get_int (value)); + break; case PROP_SUBTITLE_ENCODING: gst_play_bin3_set_encoding (playbin, g_value_get_string (value)); break; @@ -1960,6 +2133,57 @@ gst_play_bin3_get_property (GObject * object, guint prop_id, GValue * value, case PROP_FLAGS: g_value_set_flags (value, gst_play_bin3_get_flags (playbin)); break; + case PROP_N_VIDEO: + { + gint n_video; + + GST_PLAY_BIN3_LOCK (playbin); + n_video = + (playbin->combiner[PLAYBIN_STREAM_VIDEO].streams ? playbin-> + combiner[PLAYBIN_STREAM_VIDEO].streams->len : 0); + g_value_set_int (value, n_video); + GST_PLAY_BIN3_UNLOCK (playbin); + break; + } + case PROP_CURRENT_VIDEO: + GST_PLAY_BIN3_LOCK (playbin); + g_value_set_int (value, playbin->current_video); + GST_PLAY_BIN3_UNLOCK (playbin); + break; + case PROP_N_AUDIO: + { + gint n_audio; + + GST_PLAY_BIN3_LOCK (playbin); + n_audio = + (playbin->combiner[PLAYBIN_STREAM_AUDIO].streams ? playbin-> + combiner[PLAYBIN_STREAM_AUDIO].streams->len : 0); + g_value_set_int (value, n_audio); + GST_PLAY_BIN3_UNLOCK (playbin); + break; + } + case PROP_CURRENT_AUDIO: + GST_PLAY_BIN3_LOCK (playbin); + g_value_set_int (value, playbin->current_audio); + GST_PLAY_BIN3_UNLOCK (playbin); + break; + case PROP_N_TEXT: + { + gint n_text; + + GST_PLAY_BIN3_LOCK (playbin); + n_text = + (playbin->combiner[PLAYBIN_STREAM_TEXT].streams ? playbin-> + combiner[PLAYBIN_STREAM_TEXT].streams->len : 0); + g_value_set_int (value, n_text); + GST_PLAY_BIN3_UNLOCK (playbin); + break; + } + case PROP_CURRENT_TEXT: + GST_PLAY_BIN3_LOCK (playbin); + g_value_set_int (value, playbin->current_text); + GST_PLAY_BIN3_UNLOCK (playbin); + break; case PROP_SUBTITLE_ENCODING: GST_PLAY_BIN3_LOCK (playbin); g_value_take_string (value, @@ -2569,9 +2793,7 @@ gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg) if (target_group) gst_object_replace ((GstObject **) & target_group->collection, (GstObject *) collection); - /* FIXME: Only do the following if it's the current group? */ - if (target_group == playbin->curr_group) - update_combiner_info (playbin, target_group->collection); + update_combiner_info (playbin, target_group->collection); if (pstate) playbin->do_stream_selections = FALSE; do_stream_selection (playbin, target_group); @@ -3068,6 +3290,8 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstSourceGroup * group) gchar *pad_name; GstPlayBin3 *playbin = group->playbin; + gboolean changed = FALSE; + GST_PLAY_BIN3_SHUTDOWN_LOCK (playbin, shutdown); pad_name = gst_object_get_name (GST_OBJECT (pad)); @@ -3096,7 +3320,8 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstSourceGroup * group) combine = &playbin->combiner[pb_stream_type]; - combiner_control_pad (playbin, combine, pad); + if (combiner_control_pad (playbin, combine, pad)) + changed = combine->combiner ? TRUE : FALSE; control_source_pad (group, pad, combine->stream_type); @@ -3111,6 +3336,29 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstSourceGroup * group) GST_PLAY_BIN3_SHUTDOWN_UNLOCK (playbin); + if (changed) { + int signal; + + switch (combine->type) { + case GST_PLAY_SINK_TYPE_VIDEO: + signal = SIGNAL_VIDEO_CHANGED; + break; + case GST_PLAY_SINK_TYPE_AUDIO: + signal = SIGNAL_AUDIO_CHANGED; + break; + case GST_PLAY_SINK_TYPE_TEXT: + signal = SIGNAL_TEXT_CHANGED; + break; + default: + signal = -1; + } + + if (signal >= 0) { + g_signal_emit (G_OBJECT (playbin), gst_play_bin3_signals[signal], 0, + NULL); + } + } + return; /* ERRORS */ -- 2.20.1