mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
playbin2: Send flush events when changing subtitle tracks and use new input-selector modes for subtitle tracks
For audio/video we should flush too for fastest stream switches but this currently isn't possible because the flushes would need to go to the sink, which then causes state changes and causes all timing information to be changed. Should work out of the box in 0.11 with the flush-stop that doesn't reset the times. Conflicts: gst/playback/gstplaybin2.c gst/playback/gstplaysink.c gst/playback/gstsubtitleoverlay.c
This commit is contained in:
parent
9d2e50136e
commit
88d3b7aeee
3 changed files with 331 additions and 98 deletions
|
@ -410,8 +410,14 @@ struct _GstPlayBin
|
||||||
* input-selector, so that we only post a
|
* input-selector, so that we only post a
|
||||||
* warning once */
|
* warning once */
|
||||||
|
|
||||||
gboolean pending_flush_finish; /* whether we are pending to send a custom
|
gboolean video_pending_flush_finish; /* whether we are pending to send a custom
|
||||||
* subtitleoverlay-flush-subtitle-finish event
|
* custom-video-flush-finish event
|
||||||
|
* on pad activation */
|
||||||
|
gboolean audio_pending_flush_finish; /* whether we are pending to send a custom
|
||||||
|
* custom-audio-flush-finish event
|
||||||
|
* on pad activation */
|
||||||
|
gboolean text_pending_flush_finish; /* whether we are pending to send a custom
|
||||||
|
* custom-subtitle-flush-finish event
|
||||||
* on pad activation */
|
* on pad activation */
|
||||||
|
|
||||||
GstElement *audio_sink; /* configured audio sink, or NULL */
|
GstElement *audio_sink; /* configured audio sink, or NULL */
|
||||||
|
@ -1667,6 +1673,28 @@ get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_playbin2_send_custom_event (GstObject * selector, const gchar * event_name)
|
||||||
|
{
|
||||||
|
GstPad *src;
|
||||||
|
GstPad *peer;
|
||||||
|
GstStructure *s;
|
||||||
|
GstEvent *event;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
|
||||||
|
peer = gst_pad_get_peer (src);
|
||||||
|
if (peer) {
|
||||||
|
s = gst_structure_new_empty (event_name);
|
||||||
|
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
|
||||||
|
gst_pad_send_event (peer, event);
|
||||||
|
gst_object_unref (peer);
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
gst_object_unref (src);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
|
gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
|
||||||
{
|
{
|
||||||
|
@ -1698,8 +1726,19 @@ gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
|
||||||
GstObject *selector;
|
GstObject *selector;
|
||||||
|
|
||||||
if ((selector = gst_pad_get_parent (sinkpad))) {
|
if ((selector = gst_pad_get_parent (sinkpad))) {
|
||||||
/* activate the selected pad */
|
GstPad *old_sinkpad;
|
||||||
g_object_set (selector, "active-pad", sinkpad, NULL);
|
|
||||||
|
g_object_get (selector, "active-pad", &old_sinkpad, NULL);
|
||||||
|
|
||||||
|
if (old_sinkpad != sinkpad) {
|
||||||
|
if (gst_playbin2_send_custom_event (selector,
|
||||||
|
"playsink-custom-video-flush"))
|
||||||
|
playbin->video_pending_flush_finish = TRUE;
|
||||||
|
|
||||||
|
/* activate the selected pad */
|
||||||
|
g_object_set (selector, "active-pad", sinkpad, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
gst_object_unref (selector);
|
gst_object_unref (selector);
|
||||||
}
|
}
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
|
@ -1745,8 +1784,18 @@ gst_play_bin_set_current_audio_stream (GstPlayBin * playbin, gint stream)
|
||||||
GstObject *selector;
|
GstObject *selector;
|
||||||
|
|
||||||
if ((selector = gst_pad_get_parent (sinkpad))) {
|
if ((selector = gst_pad_get_parent (sinkpad))) {
|
||||||
/* activate the selected pad */
|
GstPad *old_sinkpad;
|
||||||
g_object_set (selector, "active-pad", sinkpad, NULL);
|
|
||||||
|
g_object_get (selector, "active-pad", &old_sinkpad, NULL);
|
||||||
|
|
||||||
|
if (old_sinkpad != sinkpad) {
|
||||||
|
if (gst_playbin2_send_custom_event (selector,
|
||||||
|
"playsink-custom-audio-flush"))
|
||||||
|
playbin->audio_pending_flush_finish = TRUE;
|
||||||
|
|
||||||
|
/* activate the selected pad */
|
||||||
|
g_object_set (selector, "active-pad", sinkpad, NULL);
|
||||||
|
}
|
||||||
gst_object_unref (selector);
|
gst_object_unref (selector);
|
||||||
}
|
}
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
|
@ -1889,7 +1938,7 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
|
||||||
|
|
||||||
if (old_sinkpad != sinkpad) {
|
if (old_sinkpad != sinkpad) {
|
||||||
gboolean need_unblock, need_block, need_seek;
|
gboolean need_unblock, need_block, need_seek;
|
||||||
GstPad *src, *peer = NULL, *oldpeer = NULL;
|
GstPad *peer = NULL, *oldpeer = NULL;
|
||||||
GstElement *parent_element = NULL, *old_parent_element = NULL;
|
GstElement *parent_element = NULL, *old_parent_element = NULL;
|
||||||
|
|
||||||
/* Now check if we need to seek the suburidecodebin to the beginning
|
/* Now check if we need to seek the suburidecodebin to the beginning
|
||||||
|
@ -1926,22 +1975,9 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
|
||||||
gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
|
gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
|
if (gst_playbin2_send_custom_event (selector,
|
||||||
peer = gst_pad_get_peer (src);
|
"playsink-custom-subtitle-flush"))
|
||||||
if (peer) {
|
playbin->text_pending_flush_finish = TRUE;
|
||||||
GstStructure *s;
|
|
||||||
GstEvent *event;
|
|
||||||
/* Flush the subtitle renderer to remove any
|
|
||||||
* currently displayed subtitles. This event will
|
|
||||||
* never travel outside subtitleoverlay!
|
|
||||||
*/
|
|
||||||
s = gst_structure_new_empty ("subtitleoverlay-flush-subtitle");
|
|
||||||
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
|
|
||||||
gst_pad_send_event (peer, event);
|
|
||||||
playbin->pending_flush_finish = TRUE;
|
|
||||||
gst_object_unref (peer);
|
|
||||||
}
|
|
||||||
gst_object_unref (src);
|
|
||||||
|
|
||||||
/* activate the selected pad */
|
/* activate the selected pad */
|
||||||
g_object_set (selector, "active-pad", sinkpad, NULL);
|
g_object_set (selector, "active-pad", sinkpad, NULL);
|
||||||
|
@ -2568,38 +2604,39 @@ selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
|
||||||
property = "current-video";
|
property = "current-video";
|
||||||
playbin->current_video = get_current_stream_number (playbin,
|
playbin->current_video = get_current_stream_number (playbin,
|
||||||
group->video_channels);
|
group->video_channels);
|
||||||
|
|
||||||
|
if (playbin->video_pending_flush_finish) {
|
||||||
|
playbin->video_pending_flush_finish = FALSE;
|
||||||
|
GST_PLAY_BIN_UNLOCK (playbin);
|
||||||
|
gst_playbin2_send_custom_event (GST_OBJECT (selector),
|
||||||
|
"playsink-custom-video-flush-finish");
|
||||||
|
goto notify;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GST_PLAY_SINK_TYPE_AUDIO:
|
case GST_PLAY_SINK_TYPE_AUDIO:
|
||||||
case GST_PLAY_SINK_TYPE_AUDIO_RAW:
|
case GST_PLAY_SINK_TYPE_AUDIO_RAW:
|
||||||
property = "current-audio";
|
property = "current-audio";
|
||||||
playbin->current_audio = get_current_stream_number (playbin,
|
playbin->current_audio = get_current_stream_number (playbin,
|
||||||
group->audio_channels);
|
group->audio_channels);
|
||||||
|
|
||||||
|
if (playbin->audio_pending_flush_finish) {
|
||||||
|
playbin->audio_pending_flush_finish = FALSE;
|
||||||
|
GST_PLAY_BIN_UNLOCK (playbin);
|
||||||
|
gst_playbin2_send_custom_event (GST_OBJECT (selector),
|
||||||
|
"playsink-custom-audio-flush-finish");
|
||||||
|
goto notify;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GST_PLAY_SINK_TYPE_TEXT:
|
case GST_PLAY_SINK_TYPE_TEXT:
|
||||||
property = "current-text";
|
property = "current-text";
|
||||||
playbin->current_text = get_current_stream_number (playbin,
|
playbin->current_text = get_current_stream_number (playbin,
|
||||||
group->text_channels);
|
group->text_channels);
|
||||||
|
|
||||||
if (playbin->pending_flush_finish) {
|
if (playbin->text_pending_flush_finish) {
|
||||||
GstEvent *ev;
|
playbin->text_pending_flush_finish = FALSE;
|
||||||
GstStructure *s;
|
|
||||||
GstPad *src, *peer;
|
|
||||||
|
|
||||||
playbin->pending_flush_finish = FALSE;
|
|
||||||
GST_PLAY_BIN_UNLOCK (playbin);
|
GST_PLAY_BIN_UNLOCK (playbin);
|
||||||
|
gst_playbin2_send_custom_event (GST_OBJECT (selector),
|
||||||
/* Flush the subtitle renderer to remove any
|
"playsink-custom-subtitle-flush-finish");
|
||||||
* currently displayed subtitles. This event will
|
|
||||||
* never travel outside subtitleoverlay!
|
|
||||||
*/
|
|
||||||
src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
|
|
||||||
peer = gst_pad_get_peer (src);
|
|
||||||
s = gst_structure_new_empty ("subtitleoverlay-flush-subtitle-finish");
|
|
||||||
ev = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
|
|
||||||
gst_pad_send_event (peer, ev);
|
|
||||||
gst_object_unref (peer);
|
|
||||||
gst_object_unref (src);
|
|
||||||
|
|
||||||
goto notify;
|
goto notify;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2796,7 +2833,12 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
|
||||||
(_("Missing element '%s' - check your GStreamer installation."),
|
(_("Missing element '%s' - check your GStreamer installation."),
|
||||||
"input-selector"), (NULL));
|
"input-selector"), (NULL));
|
||||||
} else {
|
} else {
|
||||||
g_object_set (select->selector, "sync-streams", TRUE, NULL);
|
/* sync-mode=1, use clock */
|
||||||
|
if (select->type == GST_PLAY_SINK_TYPE_TEXT)
|
||||||
|
g_object_set (select->selector, "sync-streams", TRUE,
|
||||||
|
"sync-mode", 1, "cache-buffers", TRUE, NULL);
|
||||||
|
else
|
||||||
|
g_object_set (select->selector, "sync-streams", TRUE, NULL);
|
||||||
|
|
||||||
g_signal_connect (select->selector, "notify::active-pad",
|
g_signal_connect (select->selector, "notify::active-pad",
|
||||||
G_CALLBACK (selector_active_pad_changed), playbin);
|
G_CALLBACK (selector_active_pad_changed), playbin);
|
||||||
|
|
|
@ -257,10 +257,24 @@ struct _GstPlaySink
|
||||||
GList *colorbalance_channels; /* CONTRAST, BRIGHTNESS, HUE, SATURATION */
|
GList *colorbalance_channels; /* CONTRAST, BRIGHTNESS, HUE, SATURATION */
|
||||||
gint colorbalance_values[4];
|
gint colorbalance_values[4];
|
||||||
|
|
||||||
|
/* sending audio/video flushes break stream changes when the pipeline
|
||||||
|
* is paused and played again in 0.10 */
|
||||||
|
#if 0
|
||||||
|
GstSegment video_segment;
|
||||||
|
gboolean video_custom_flush_finished;
|
||||||
|
gboolean video_ignore_wrong_state;
|
||||||
|
gboolean video_pending_flush;
|
||||||
|
|
||||||
|
GstSegment audio_segment;
|
||||||
|
gboolean audio_custom_flush_finished;
|
||||||
|
gboolean audio_ignore_wrong_state;
|
||||||
|
gboolean audio_pending_flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
GstSegment text_segment;
|
GstSegment text_segment;
|
||||||
gboolean custom_flush_finished;
|
gboolean text_custom_flush_finished;
|
||||||
gboolean ignore_wrong_state;
|
gboolean text_ignore_wrong_state;
|
||||||
gboolean pending_flush_stop;
|
gboolean text_pending_flush;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstPlaySinkClass
|
struct _GstPlaySinkClass
|
||||||
|
@ -344,6 +358,21 @@ static GstStateChangeReturn gst_play_sink_change_state (GstElement * element,
|
||||||
|
|
||||||
static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message);
|
static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message);
|
||||||
|
|
||||||
|
/* sending audio/video flushes break stream changes when the pipeline
|
||||||
|
* is paused and played again in 0.10 */
|
||||||
|
#if 0
|
||||||
|
static gboolean gst_play_sink_video_sink_event (GstPad * pad, GstEvent * event);
|
||||||
|
static GstFlowReturn gst_play_sink_video_sink_chain (GstPad * pad,
|
||||||
|
GstBuffer * buffer);
|
||||||
|
static gboolean gst_play_sink_audio_sink_event (GstPad * pad, GstEvent * event);
|
||||||
|
static GstFlowReturn gst_play_sink_audio_sink_chain (GstPad * pad,
|
||||||
|
GstBuffer * buffer);
|
||||||
|
#endif
|
||||||
|
static gboolean gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event);
|
||||||
|
static GstFlowReturn gst_play_sink_text_sink_chain (GstPad * pad,
|
||||||
|
GstObject * parent, GstBuffer * buffer);
|
||||||
|
|
||||||
static void notify_volume_cb (GObject * object, GParamSpec * pspec,
|
static void notify_volume_cb (GObject * object, GParamSpec * pspec,
|
||||||
GstPlaySink * playsink);
|
GstPlaySink * playsink);
|
||||||
static void notify_mute_cb (GObject * object, GParamSpec * pspec,
|
static void notify_mute_cb (GObject * object, GParamSpec * pspec,
|
||||||
|
@ -1690,8 +1719,17 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
|
||||||
|
|
||||||
pad = gst_element_get_static_pad (head, "sink");
|
pad = gst_element_get_static_pad (head, "sink");
|
||||||
chain->sinkpad = gst_ghost_pad_new ("sink", pad);
|
chain->sinkpad = gst_ghost_pad_new ("sink", pad);
|
||||||
gst_object_unref (pad);
|
|
||||||
|
|
||||||
|
/* sending audio/video flushes break stream changes when the pipeline
|
||||||
|
* is paused and played again in 0.10 */
|
||||||
|
#if 0
|
||||||
|
gst_pad_set_event_function (chain->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_video_sink_event));
|
||||||
|
gst_pad_set_chain_function (chain->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_video_sink_chain));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gst_object_unref (pad);
|
||||||
gst_element_add_pad (chain->chain.bin, chain->sinkpad);
|
gst_element_add_pad (chain->chain.bin, chain->sinkpad);
|
||||||
|
|
||||||
return chain;
|
return chain;
|
||||||
|
@ -1858,37 +1896,52 @@ _generate_update_newsegment_event (GstPad * pad, GstSegment * segment,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
|
gst_play_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event,
|
||||||
GstEvent * event)
|
const gchar * sink_type,
|
||||||
|
gboolean * sink_ignore_wrong_state,
|
||||||
|
gboolean * sink_custom_flush_finished,
|
||||||
|
gboolean * sink_pending_flush, GstSegment * sink_segment)
|
||||||
{
|
{
|
||||||
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
const GstStructure *structure = gst_event_get_structure (event);
|
const GstStructure *structure = gst_event_get_structure (event);
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
|
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && structure) {
|
||||||
structure
|
gchar *custom_flush;
|
||||||
&& strcmp (gst_structure_get_name (structure),
|
gchar *custom_flush_finish;
|
||||||
"subtitleoverlay-flush-subtitle") == 0) {
|
|
||||||
GST_DEBUG_OBJECT (pad,
|
custom_flush = g_strdup_printf ("playsink-custom-%s-flush", sink_type);
|
||||||
"Custom subtitle flush event received, marking to flush text");
|
custom_flush_finish =
|
||||||
GST_PLAY_SINK_LOCK (playsink);
|
g_strdup_printf ("playsink-custom-%s-flush-finish", sink_type);
|
||||||
playsink->ignore_wrong_state = TRUE;
|
if (strcmp (gst_structure_get_name (structure), custom_flush) == 0) {
|
||||||
playsink->custom_flush_finished = FALSE;
|
GST_DEBUG_OBJECT (pad,
|
||||||
GST_PLAY_SINK_UNLOCK (playsink);
|
"Custom %s flush event received, marking to flush %s", sink_type,
|
||||||
} else if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
|
sink_type);
|
||||||
structure && strcmp (gst_structure_get_name (structure),
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
"subtitleoverlay-flush-subtitle-finish") == 0) {
|
*sink_ignore_wrong_state = TRUE;
|
||||||
GST_DEBUG_OBJECT (pad, "Custom subtitle flush finish event received");
|
*sink_custom_flush_finished = FALSE;
|
||||||
GST_PLAY_SINK_LOCK (playsink);
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
playsink->pending_flush_stop = TRUE;
|
} else if (strcmp (gst_structure_get_name (structure),
|
||||||
playsink->custom_flush_finished = TRUE;
|
custom_flush_finish) == 0) {
|
||||||
GST_PLAY_SINK_UNLOCK (playsink);
|
GST_DEBUG_OBJECT (pad, "Custom %s flush finish event received",
|
||||||
|
sink_type);
|
||||||
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
|
*sink_pending_flush = TRUE;
|
||||||
|
*sink_custom_flush_finished = TRUE;
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (custom_flush);
|
||||||
|
g_free (custom_flush_finish);
|
||||||
} else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
|
} else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
|
||||||
GST_DEBUG_OBJECT (pad,
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
"Resetting text segment because of flush-stop event");
|
GST_DEBUG_OBJECT (pad, "Resetting %s segment because of flush-stop event",
|
||||||
gst_segment_init (&playsink->text_segment, GST_FORMAT_UNDEFINED);
|
sink_type);
|
||||||
|
gst_segment_init (sink_segment, GST_FORMAT_UNDEFINED);
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad, "Forwarding event %" GST_PTR_FORMAT, event);
|
||||||
ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
|
ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
|
if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
|
||||||
|
@ -1897,17 +1950,21 @@ gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
|
||||||
gst_event_parse_segment (event, &segment);
|
gst_event_parse_segment (event, &segment);
|
||||||
GST_DEBUG_OBJECT (pad, "Segment event: %" GST_SEGMENT_FORMAT, segment);
|
GST_DEBUG_OBJECT (pad, "Segment event: %" GST_SEGMENT_FORMAT, segment);
|
||||||
|
|
||||||
if (playsink->text_segment.format != segment->format) {
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
GST_DEBUG_OBJECT (pad, "Text segment format changed: %s -> %s",
|
if (sink_segment->format != segment->format) {
|
||||||
gst_format_get_name (playsink->text_segment.format),
|
GST_DEBUG_OBJECT (pad, "%s segment format changed: %s -> %s",
|
||||||
|
sink_type,
|
||||||
|
gst_format_get_name (sink_segment->format),
|
||||||
gst_format_get_name (segment->format));
|
gst_format_get_name (segment->format));
|
||||||
|
gst_segment_init (sink_segment, segment->format);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pad, "Old text segment: %" GST_SEGMENT_FORMAT,
|
GST_DEBUG_OBJECT (pad, "Old %s segment: %" GST_SEGMENT_FORMAT,
|
||||||
&playsink->text_segment);
|
sink_type, sink_segment);
|
||||||
gst_segment_copy_into (segment, &playsink->text_segment);
|
gst_segment_copy_into (&playsink->text_segment, sink_segment);
|
||||||
GST_DEBUG_OBJECT (pad, "New text segment: %" GST_SEGMENT_FORMAT,
|
GST_DEBUG_OBJECT (pad, "New %s segment: %" GST_SEGMENT_FORMAT,
|
||||||
&playsink->text_segment);
|
sink_type, sink_segment);
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
@ -1916,8 +1973,11 @@ gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
|
gst_play_sink_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer,
|
||||||
GstBuffer * buffer)
|
const gchar * sink_type,
|
||||||
|
gboolean * sink_ignore_wrong_state,
|
||||||
|
gboolean * sink_custom_flush_finished,
|
||||||
|
gboolean * sink_pending_flush, GstSegment * sink_segment)
|
||||||
{
|
{
|
||||||
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
||||||
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
||||||
|
@ -1925,13 +1985,29 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
|
||||||
|
|
||||||
GST_PLAY_SINK_LOCK (playsink);
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
|
|
||||||
if (playsink->pending_flush_stop) {
|
if (*sink_pending_flush) {
|
||||||
GstSegment text_segment;
|
GstSegment segment_copy;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
|
|
||||||
/* it will be replaced in flush_stop */
|
*sink_pending_flush = FALSE;
|
||||||
text_segment = playsink->text_segment;
|
|
||||||
|
/* sink_segment will be updated in flush */
|
||||||
|
segment_copy = *sink_segment;
|
||||||
|
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
|
|
||||||
|
/* make the bin drop all cached data.
|
||||||
|
* This event will be dropped on the src pad, if any. */
|
||||||
|
event = gst_event_new_flush_start ();
|
||||||
|
structure = gst_event_writable_structure (event);
|
||||||
|
gst_structure_id_set (structure,
|
||||||
|
_playsink_reset_segment_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad,
|
||||||
|
"Pushing %s flush-start event with reset segment marker set: %"
|
||||||
|
GST_PTR_FORMAT, sink_type, event);
|
||||||
|
gst_pad_send_event (pad, event);
|
||||||
|
|
||||||
/* make queue drop all cached data.
|
/* make queue drop all cached data.
|
||||||
* This event will be dropped on the src pad. */
|
* This event will be dropped on the src pad. */
|
||||||
|
@ -1941,35 +2017,35 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
|
||||||
_playsink_reset_segment_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
|
_playsink_reset_segment_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pad,
|
GST_DEBUG_OBJECT (pad,
|
||||||
"Pushing flush-stop event with reset segment marker set: %"
|
"Pushing %s flush-stop event with reset segment marker set: %"
|
||||||
GST_PTR_FORMAT, event);
|
GST_PTR_FORMAT, sink_type, event);
|
||||||
gst_pad_send_event (pad, event);
|
gst_pad_send_event (pad, event);
|
||||||
|
|
||||||
/* Re-sync queue segment info after flush-stop.
|
/* Re-sync queue segment info after flush-stop.
|
||||||
* This event will be dropped on the src pad. */
|
* This event will be dropped on the src pad. */
|
||||||
if (text_segment.format != GST_FORMAT_UNDEFINED) {
|
if (sink_segment->format != GST_FORMAT_UNDEFINED) {
|
||||||
GstEvent *event1;
|
GstEvent *event1;
|
||||||
|
|
||||||
_generate_update_newsegment_event (pad, &text_segment, &event1);
|
_generate_update_newsegment_event (pad, sink_segment, &event1);
|
||||||
GST_DEBUG_OBJECT (playsink,
|
GST_DEBUG_OBJECT (playsink,
|
||||||
"Pushing segment event with reset "
|
"Pushing segment event with reset "
|
||||||
"segment marker set: %" GST_PTR_FORMAT, event1);
|
"segment marker set: %" GST_PTR_FORMAT, event1);
|
||||||
gst_pad_send_event (pad, event1);
|
gst_pad_send_event (pad, event1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
playsink->pending_flush_stop = FALSE;
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
}
|
}
|
||||||
GST_PLAY_SINK_UNLOCK (playsink);
|
|
||||||
|
|
||||||
ret = gst_proxy_pad_chain_default (pad, parent, buffer);
|
ret = gst_proxy_pad_chain_default (pad, parent, buffer);
|
||||||
|
|
||||||
GST_PLAY_SINK_LOCK (playsink);
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
if (ret == GST_FLOW_FLUSHING && playsink->ignore_wrong_state) {
|
if (ret == GST_FLOW_FLUSHING && *sink_ignore_wrong_state) {
|
||||||
GST_DEBUG_OBJECT (pad, "Ignoring wrong state during flush");
|
GST_DEBUG_OBJECT (pad, "Ignoring wrong state for %s during flush",
|
||||||
if (playsink->custom_flush_finished) {
|
sink_type);
|
||||||
GST_DEBUG_OBJECT (pad,
|
if (*sink_custom_flush_finished) {
|
||||||
"custom flush finished, stop ignoring wrong state");
|
GST_DEBUG_OBJECT (pad, "Custom flush finished, stop ignoring "
|
||||||
playsink->ignore_wrong_state = FALSE;
|
"wrong state for %s", sink_type);
|
||||||
|
*sink_ignore_wrong_state = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
|
@ -1981,6 +2057,111 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sending audio/video flushes break stream changes when the pipeline
|
||||||
|
* is paused and played again in 0.10 */
|
||||||
|
#if 0
|
||||||
|
static gboolean
|
||||||
|
gst_play_sink_video_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_play_sink_sink_event (pad, event, "video",
|
||||||
|
&playsink->video_ignore_wrong_state,
|
||||||
|
&playsink->video_custom_flush_finished,
|
||||||
|
&playsink->video_pending_flush, &playsink->video_segment);
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
gst_object_unref (tbin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_play_sink_video_sink_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_play_sink_sink_chain (pad, buffer, "video",
|
||||||
|
&playsink->video_ignore_wrong_state,
|
||||||
|
&playsink->video_custom_flush_finished,
|
||||||
|
&playsink->video_pending_flush, &playsink->video_segment);
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
gst_object_unref (tbin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_play_sink_audio_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_play_sink_sink_event (pad, event, "audio",
|
||||||
|
&playsink->audio_ignore_wrong_state,
|
||||||
|
&playsink->audio_custom_flush_finished,
|
||||||
|
&playsink->audio_pending_flush, &playsink->audio_segment);
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
gst_object_unref (tbin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_play_sink_audio_sink_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_play_sink_sink_chain (pad, buffer, "audio",
|
||||||
|
&playsink->audio_ignore_wrong_state,
|
||||||
|
&playsink->audio_custom_flush_finished,
|
||||||
|
&playsink->audio_pending_flush, &playsink->audio_segment);
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
gst_object_unref (tbin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event)
|
||||||
|
{
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gst_play_sink_sink_event (pad, parent, event, "subtitle",
|
||||||
|
&playsink->text_ignore_wrong_state,
|
||||||
|
&playsink->text_custom_flush_finished,
|
||||||
|
&playsink->text_pending_flush, &playsink->text_segment);
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
|
||||||
|
GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
|
||||||
|
|
||||||
|
ret = gst_play_sink_sink_chain (pad, parent, buffer, "subtitle",
|
||||||
|
&playsink->text_ignore_wrong_state,
|
||||||
|
&playsink->text_custom_flush_finished,
|
||||||
|
&playsink->text_pending_flush, &playsink->text_segment);
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_play_sink_text_src_event (GstPad * pad, GstObject * parent,
|
gst_play_sink_text_src_event (GstPad * pad, GstObject * parent,
|
||||||
GstEvent * event)
|
GstEvent * event)
|
||||||
|
@ -2439,6 +2620,16 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
|
||||||
GST_DEBUG_OBJECT (playsink, "ghosting sink pad");
|
GST_DEBUG_OBJECT (playsink, "ghosting sink pad");
|
||||||
pad = gst_element_get_static_pad (head, "sink");
|
pad = gst_element_get_static_pad (head, "sink");
|
||||||
chain->sinkpad = gst_ghost_pad_new ("sink", pad);
|
chain->sinkpad = gst_ghost_pad_new ("sink", pad);
|
||||||
|
|
||||||
|
/* sending audio/video flushes break stream changes when the pipeline
|
||||||
|
* is paused and played again in 0.10 */
|
||||||
|
#if 0
|
||||||
|
gst_pad_set_event_function (chain->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_audio_sink_event));
|
||||||
|
gst_pad_set_chain_function (chain->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_audio_sink_chain));
|
||||||
|
#endif
|
||||||
|
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
gst_element_add_pad (chain->chain.bin, chain->sinkpad);
|
gst_element_add_pad (chain->chain.bin, chain->sinkpad);
|
||||||
|
|
||||||
|
|
|
@ -2066,7 +2066,7 @@ gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstObject * parent,
|
||||||
GST_DEBUG_OBJECT (pad, "Got event %" GST_PTR_FORMAT, event);
|
GST_DEBUG_OBJECT (pad, "Got event %" GST_PTR_FORMAT, event);
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
|
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
|
||||||
gst_event_has_name (event, "subtitleoverlay-flush-subtitle")) {
|
gst_event_has_name (event, "playsink-custom-subtitle-flush")) {
|
||||||
GST_DEBUG_OBJECT (pad, "Custom subtitle flush event");
|
GST_DEBUG_OBJECT (pad, "Custom subtitle flush event");
|
||||||
GST_SUBTITLE_OVERLAY_LOCK (self);
|
GST_SUBTITLE_OVERLAY_LOCK (self);
|
||||||
self->subtitle_flush = TRUE;
|
self->subtitle_flush = TRUE;
|
||||||
|
|
Loading…
Reference in a new issue