1From 14aeb6ae37c0f137d7f3038efc51d25f8f371751 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Tue, 20 Nov 2018 14:51:36 +0800
4Subject: [PATCH 05/11] playbin3: Fix qt videoplayer cannot change video state
5
6Change-Id: I765bbe0caebe333855bd16fdd0843e0257491246
7Signed-off-by: shine.liu <shine.liu@rock-chips.com>
8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
9---
10 gst/playback/gstplaybin3.c | 256 ++++++++++++++++++++++++++++++++++++-
11 1 file changed, 252 insertions(+), 4 deletions(-)
12
13diff --git a/gst/playback/gstplaybin3.c b/gst/playback/gstplaybin3.c
14index a732160..c22d9db 100644
15--- a/gst/playback/gstplaybin3.c
16+++ b/gst/playback/gstplaybin3.c
17@@ -532,6 +532,16 @@ struct _GstPlayBin3Class
18
19   /* get the last video sample and convert it to the given caps */
20   GstSample *(*convert_sample) (GstPlayBin3 * playbin, GstCaps * caps);
21+
22+  /* notify app that number of audio/video/text streams changed */
23+  void (*video_changed) (GstPlayBin3 * playbin);
24+  void (*audio_changed) (GstPlayBin3 * playbin);
25+  void (*text_changed) (GstPlayBin3 * playbin);
26+
27+  /* get audio/video/text tags for a stream */
28+  GstTagList *(*get_video_tags) (GstPlayBin3 * playbin, gint stream);
29+  GstTagList *(*get_audio_tags) (GstPlayBin3 * playbin, gint stream);
30+  GstTagList *(*get_text_tags) (GstPlayBin3 * playbin, gint stream);
31 };
32
33 /* props */
34@@ -565,6 +575,12 @@ enum
35   PROP_SUBURI,
36   PROP_CURRENT_SUBURI,
37   PROP_FLAGS,
38+  PROP_N_VIDEO,
39+  PROP_CURRENT_VIDEO,
40+  PROP_N_AUDIO,
41+  PROP_CURRENT_AUDIO,
42+  PROP_N_TEXT,
43+  PROP_CURRENT_TEXT,
44   PROP_SUBTITLE_ENCODING,
45   PROP_AUDIO_SINK,
46   PROP_VIDEO_SINK,
47@@ -597,6 +613,12 @@ enum
48   SIGNAL_CONVERT_SAMPLE,
49   SIGNAL_SOURCE_SETUP,
50   SIGNAL_ELEMENT_SETUP,
51+  SIGNAL_VIDEO_CHANGED,
52+  SIGNAL_AUDIO_CHANGED,
53+  SIGNAL_TEXT_CHANGED,
54+  SIGNAL_GET_VIDEO_TAGS,
55+  SIGNAL_GET_AUDIO_TAGS,
56+  SIGNAL_GET_TEXT_TAGS,
57   LAST_SIGNAL
58 };
59
60@@ -621,6 +643,13 @@ static void gst_play_bin3_deep_element_added (GstBin * playbin,
61 static gboolean gst_play_bin3_send_event (GstElement * element,
62     GstEvent * event);
63
64+static GstTagList *gst_play_bin3_get_video_tags (GstPlayBin3 * playbin,
65+    gint stream);
66+static GstTagList *gst_play_bin3_get_audio_tags (GstPlayBin3 * playbin,
67+    gint stream);
68+static GstTagList *gst_play_bin3_get_text_tags (GstPlayBin3 * playbin,
69+    gint stream);
70+
71 static GstSample *gst_play_bin3_convert_sample (GstPlayBin3 * playbin,
72     GstCaps * caps);
73
74@@ -755,6 +784,36 @@ gst_play_bin3_class_init (GstPlayBin3Class * klass)
75           GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS,
76           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
77
78+  g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
79+      g_param_spec_int ("n-video", "Number Video",
80+          "Total number of video streams", 0, G_MAXINT, 0,
81+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
82+
83+  g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
84+      g_param_spec_int ("current-video", "Current Video",
85+          "Currently playing video stream (-1 = auto)",
86+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
87+
88+  g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
89+      g_param_spec_int ("n-audio", "Number Audio",
90+          "Total number of audio streams", 0, G_MAXINT, 0,
91+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
92+
93+  g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
94+      g_param_spec_int ("current-audio", "Current audio",
95+          "Currently playing audio stream (-1 = auto)",
96+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
97+
98+  g_object_class_install_property (gobject_klass, PROP_N_TEXT,
99+      g_param_spec_int ("n-text", "Number Text",
100+          "Total number of text streams", 0, G_MAXINT, 0,
101+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
102+
103+  g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
104+      g_param_spec_int ("current-text", "Current Text",
105+          "Currently playing text stream (-1 = auto)",
106+          -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
107+
108   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
109       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
110           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
111@@ -1024,6 +1083,41 @@ gst_play_bin3_class_init (GstPlayBin3Class * klass)
112       g_signal_new ("element-setup", G_TYPE_FROM_CLASS (klass),
113       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
114
115+  gst_play_bin3_signals[SIGNAL_VIDEO_CHANGED] =
116+      g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
117+      G_SIGNAL_RUN_LAST,
118+      G_STRUCT_OFFSET (GstPlayBin3Class, video_changed), NULL, NULL,
119+      g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
120+
121+  gst_play_bin3_signals[SIGNAL_AUDIO_CHANGED] =
122+      g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
123+      G_SIGNAL_RUN_LAST,
124+      G_STRUCT_OFFSET (GstPlayBin3Class, audio_changed), NULL, NULL,
125+      g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
126+
127+  gst_play_bin3_signals[SIGNAL_TEXT_CHANGED] =
128+      g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
129+      G_SIGNAL_RUN_LAST,
130+      G_STRUCT_OFFSET (GstPlayBin3Class, text_changed), NULL, NULL,
131+      g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE);
132+
133+  gst_play_bin3_signals[SIGNAL_GET_VIDEO_TAGS] =
134+      g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass),
135+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
136+      G_STRUCT_OFFSET (GstPlayBin3Class, get_video_tags), NULL, NULL,
137+      g_cclosure_marshal_generic, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
138+
139+  gst_play_bin3_signals[SIGNAL_GET_AUDIO_TAGS] =
140+      g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass),
141+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
142+      G_STRUCT_OFFSET (GstPlayBin3Class, get_audio_tags), NULL, NULL,
143+      g_cclosure_marshal_generic, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
144+
145+  gst_play_bin3_signals[SIGNAL_GET_TEXT_TAGS] =
146+      g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass),
147+      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
148+      G_STRUCT_OFFSET (GstPlayBin3Class, get_text_tags), NULL, NULL,
149+      g_cclosure_marshal_generic, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
150   /**
151    * GstPlayBin3::convert-sample
152    * @playbin: a #GstPlayBin3
153@@ -1045,6 +1139,10 @@ gst_play_bin3_class_init (GstPlayBin3Class * klass)
154       G_STRUCT_OFFSET (GstPlayBin3Class, convert_sample), NULL, NULL,
155       NULL, GST_TYPE_SAMPLE, 1, GST_TYPE_CAPS);
156
157+  klass->get_video_tags = gst_play_bin3_get_video_tags;
158+  klass->get_audio_tags = gst_play_bin3_get_audio_tags;
159+  klass->get_text_tags = gst_play_bin3_get_text_tags;
160+
161   klass->convert_sample = gst_play_bin3_convert_sample;
162
163   gst_element_class_set_static_metadata (gstelement_klass,
164@@ -1559,6 +1657,72 @@ get_group (GstPlayBin3 * playbin)
165   return result;
166 }
167
168+static GstTagList *
169+get_tags (GstPlayBin3 * playbin, gint type, gint stream)
170+{
171+  GstTagList *result;
172+  GPtrArray *channels;
173+  GstPad *sinkpad;
174+
175+  switch (type) {
176+    case PLAYBIN_STREAM_AUDIO:
177+      channels = playbin->combiner[PLAYBIN_STREAM_AUDIO].streams;
178+      break;
179+    case PLAYBIN_STREAM_VIDEO:
180+      channels = playbin->combiner[PLAYBIN_STREAM_VIDEO].streams;
181+      break;
182+    case PLAYBIN_STREAM_TEXT:
183+      channels = playbin->combiner[PLAYBIN_STREAM_TEXT].streams;
184+      break;
185+    default:
186+      channels = NULL;
187+      break;
188+  }
189+
190+  if (!channels || stream >= channels->len)
191+    return NULL;
192+
193+  sinkpad = g_ptr_array_index (channels, stream);
194+  g_object_get (sinkpad, "tags", &result, NULL);
195+
196+  return result;
197+}
198+
199+static GstTagList *
200+gst_play_bin3_get_video_tags (GstPlayBin3 * playbin, gint stream)
201+{
202+  GstTagList *result;
203+
204+  GST_PLAY_BIN3_LOCK (playbin);
205+  result = get_tags (playbin, PLAYBIN_STREAM_VIDEO, stream);
206+  GST_PLAY_BIN3_UNLOCK (playbin);
207+
208+  return result;
209+}
210+
211+static GstTagList *
212+gst_play_bin3_get_audio_tags (GstPlayBin3 * playbin, gint stream)
213+{
214+  GstTagList *result;
215+
216+  GST_PLAY_BIN3_LOCK (playbin);
217+  result = get_tags (playbin, PLAYBIN_STREAM_AUDIO, stream);
218+  GST_PLAY_BIN3_UNLOCK (playbin);
219+
220+  return result;
221+}
222+
223+static GstTagList *
224+gst_play_bin3_get_text_tags (GstPlayBin3 * playbin, gint stream)
225+{
226+  GstTagList *result;
227+
228+  GST_PLAY_BIN3_LOCK (playbin);
229+  result = get_tags (playbin, PLAYBIN_STREAM_TEXT, stream);
230+  GST_PLAY_BIN3_UNLOCK (playbin);
231+
232+  return result;
233+}
234
235 static GstSample *
236 gst_play_bin3_convert_sample (GstPlayBin3 * playbin, GstCaps * caps)
237@@ -1772,6 +1936,15 @@ gst_play_bin3_set_property (GObject * object, guint prop_id,
238         GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
239       }
240       break;
241+    case PROP_CURRENT_VIDEO:
242+      gst_play_bin3_set_current_video_stream (playbin, g_value_get_int (value));
243+      break;
244+    case PROP_CURRENT_AUDIO:
245+      gst_play_bin3_set_current_audio_stream (playbin, g_value_get_int (value));
246+      break;
247+    case PROP_CURRENT_TEXT:
248+      gst_play_bin3_set_current_text_stream (playbin, g_value_get_int (value));
249+      break;
250     case PROP_SUBTITLE_ENCODING:
251       gst_play_bin3_set_encoding (playbin, g_value_get_string (value));
252       break;
253@@ -1960,6 +2133,57 @@ gst_play_bin3_get_property (GObject * object, guint prop_id, GValue * value,
254     case PROP_FLAGS:
255       g_value_set_flags (value, gst_play_bin3_get_flags (playbin));
256       break;
257+    case PROP_N_VIDEO:
258+    {
259+      gint n_video;
260+
261+      GST_PLAY_BIN3_LOCK (playbin);
262+      n_video =
263+          (playbin->combiner[PLAYBIN_STREAM_VIDEO].streams ? playbin->
264+          combiner[PLAYBIN_STREAM_VIDEO].streams->len : 0);
265+      g_value_set_int (value, n_video);
266+      GST_PLAY_BIN3_UNLOCK (playbin);
267+      break;
268+    }
269+    case PROP_CURRENT_VIDEO:
270+      GST_PLAY_BIN3_LOCK (playbin);
271+      g_value_set_int (value, playbin->current_video);
272+      GST_PLAY_BIN3_UNLOCK (playbin);
273+      break;
274+    case PROP_N_AUDIO:
275+    {
276+      gint n_audio;
277+
278+      GST_PLAY_BIN3_LOCK (playbin);
279+      n_audio =
280+          (playbin->combiner[PLAYBIN_STREAM_AUDIO].streams ? playbin->
281+          combiner[PLAYBIN_STREAM_AUDIO].streams->len : 0);
282+      g_value_set_int (value, n_audio);
283+      GST_PLAY_BIN3_UNLOCK (playbin);
284+      break;
285+    }
286+    case PROP_CURRENT_AUDIO:
287+      GST_PLAY_BIN3_LOCK (playbin);
288+      g_value_set_int (value, playbin->current_audio);
289+      GST_PLAY_BIN3_UNLOCK (playbin);
290+      break;
291+    case PROP_N_TEXT:
292+    {
293+      gint n_text;
294+
295+      GST_PLAY_BIN3_LOCK (playbin);
296+      n_text =
297+          (playbin->combiner[PLAYBIN_STREAM_TEXT].streams ? playbin->
298+          combiner[PLAYBIN_STREAM_TEXT].streams->len : 0);
299+      g_value_set_int (value, n_text);
300+      GST_PLAY_BIN3_UNLOCK (playbin);
301+      break;
302+    }
303+    case PROP_CURRENT_TEXT:
304+      GST_PLAY_BIN3_LOCK (playbin);
305+      g_value_set_int (value, playbin->current_text);
306+      GST_PLAY_BIN3_UNLOCK (playbin);
307+      break;
308     case PROP_SUBTITLE_ENCODING:
309       GST_PLAY_BIN3_LOCK (playbin);
310       g_value_take_string (value,
311@@ -2569,9 +2793,7 @@ gst_play_bin3_handle_message (GstBin * bin, GstMessage * msg)
312       if (target_group)
313         gst_object_replace ((GstObject **) & target_group->collection,
314             (GstObject *) collection);
315-      /* FIXME: Only do the following if it's the current group? */
316-      if (target_group == playbin->curr_group)
317-        update_combiner_info (playbin, target_group->collection);
318+      update_combiner_info (playbin, target_group->collection);
319       if (pstate)
320         playbin->do_stream_selections = FALSE;
321       do_stream_selection (playbin, target_group);
322@@ -3068,6 +3290,8 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstSourceGroup * group)
323   gchar *pad_name;
324   GstPlayBin3 *playbin = group->playbin;
325
326+  gboolean changed = FALSE;
327+
328   GST_PLAY_BIN3_SHUTDOWN_LOCK (playbin, shutdown);
329
330   pad_name = gst_object_get_name (GST_OBJECT (pad));
331@@ -3096,7 +3320,8 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstSourceGroup * group)
332
333   combine = &playbin->combiner[pb_stream_type];
334
335-  combiner_control_pad (playbin, combine, pad);
336+  if (combiner_control_pad (playbin, combine, pad))
337+    changed = combine->combiner ? TRUE : FALSE;
338
339   control_source_pad (group, pad, combine->stream_type);
340
341@@ -3111,6 +3336,29 @@ pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstSourceGroup * group)
342
343   GST_PLAY_BIN3_SHUTDOWN_UNLOCK (playbin);
344
345+  if (changed) {
346+    int signal;
347+
348+    switch (combine->type) {
349+      case GST_PLAY_SINK_TYPE_VIDEO:
350+        signal = SIGNAL_VIDEO_CHANGED;
351+        break;
352+      case GST_PLAY_SINK_TYPE_AUDIO:
353+        signal = SIGNAL_AUDIO_CHANGED;
354+        break;
355+      case GST_PLAY_SINK_TYPE_TEXT:
356+        signal = SIGNAL_TEXT_CHANGED;
357+        break;
358+      default:
359+        signal = -1;
360+    }
361+
362+    if (signal >= 0) {
363+      g_signal_emit (G_OBJECT (playbin), gst_play_bin3_signals[signal], 0,
364+          NULL);
365+    }
366+  }
367+
368   return;
369
370   /* ERRORS */
371--
3722.20.1
373
374