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:
Andre Moreira Magalhaes (andrunko) 2012-05-24 11:02:59 -03:00 committed by Thiago Santos
parent 9d2e50136e
commit 88d3b7aeee
3 changed files with 331 additions and 98 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;