From c193043d8bc9731674d2a055d5b3ce97c3e33ff2 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 20 Nov 2018 14:51:36 +0800 Subject: [PATCH 05/14] 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 | 252 +++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/gst/playback/gstplaybin3.c b/gst/playback/gstplaybin3.c index 46eb478..f059474 100644 --- a/gst/playback/gstplaybin3.c +++ b/gst/playback/gstplaybin3.c @@ -388,6 +388,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 */ @@ -421,6 +431,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, @@ -454,6 +470,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 }; @@ -473,6 +495,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); @@ -610,6 +639,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. " @@ -893,6 +952,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 @@ -914,6 +1008,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, @@ -1232,6 +1330,73 @@ gst_play_bin3_set_flags (GstPlayBin3 * playbin, GstPlayFlags flags) "use-buffering", ((flags & GST_PLAY_FLAG_BUFFERING) != 0), NULL); } +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) { @@ -1435,6 +1600,15 @@ gst_play_bin3_set_property (GObject * object, guint prop_id, case PROP_FLAGS: gst_play_bin3_set_flags (playbin, g_value_get_flags (value)); 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; @@ -1595,6 +1769,57 @@ gst_play_bin3_get_property (GObject * object, guint prop_id, GValue * value, case PROP_FLAGS: g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink)); 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, @@ -2429,6 +2654,7 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstPlayBin3 * playbin) gchar *pad_name; GstPad *combine_pad; GstStreamType selected, active, cur; + gboolean changed = FALSE; pad_name = gst_object_get_name (GST_OBJECT (pad)); @@ -2476,10 +2702,36 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstPlayBin3 * playbin) } combine_pad = combiner_control_pad (playbin, combine, pad); + if (combine_pad) + changed = combine->combiner ? TRUE : FALSE; + control_source_pad (playbin, pad, combine_pad, combine->stream_type); GST_PLAY_BIN3_UNLOCK (playbin); + if (changed) { + int signal; + + switch (combine->stream_type) { + case GST_STREAM_TYPE_VIDEO: + signal = SIGNAL_VIDEO_CHANGED; + break; + case GST_STREAM_TYPE_AUDIO: + signal = SIGNAL_AUDIO_CHANGED; + break; + case GST_STREAM_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