mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
gstplaysink: Properly reset chain when receiving a custom flush event.
https://bugzilla.gnome.org/show_bug.cgi?id=638168 Conflicts: gst/playback/gstplaysink.c
This commit is contained in:
parent
0dfb331cfd
commit
bd5cfff9de
1 changed files with 166 additions and 0 deletions
|
@ -256,6 +256,9 @@ struct _GstPlaySink
|
||||||
GstColorBalance *colorbalance_element;
|
GstColorBalance *colorbalance_element;
|
||||||
GList *colorbalance_channels; /* CONTRAST, BRIGHTNESS, HUE, SATURATION */
|
GList *colorbalance_channels; /* CONTRAST, BRIGHTNESS, HUE, SATURATION */
|
||||||
gint colorbalance_values[4];
|
gint colorbalance_values[4];
|
||||||
|
|
||||||
|
GstSegment text_segment;
|
||||||
|
gboolean text_flush;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstPlaySinkClass
|
struct _GstPlaySinkClass
|
||||||
|
@ -346,6 +349,8 @@ static void notify_mute_cb (GObject * object, GParamSpec * pspec,
|
||||||
|
|
||||||
static void update_av_offset (GstPlaySink * playsink);
|
static void update_av_offset (GstPlaySink * playsink);
|
||||||
|
|
||||||
|
static GQuark _playsink_reset_segment_event_marker_id = 0;
|
||||||
|
|
||||||
/* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
|
||||||
static void gst_play_sink_overlay_init (gpointer g_iface,
|
static void gst_play_sink_overlay_init (gpointer g_iface,
|
||||||
|
@ -572,6 +577,9 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
|
||||||
|
|
||||||
klass->reconfigure = GST_DEBUG_FUNCPTR (gst_play_sink_reconfigure);
|
klass->reconfigure = GST_DEBUG_FUNCPTR (gst_play_sink_reconfigure);
|
||||||
klass->convert_sample = GST_DEBUG_FUNCPTR (gst_play_sink_convert_sample);
|
klass->convert_sample = GST_DEBUG_FUNCPTR (gst_play_sink_convert_sample);
|
||||||
|
|
||||||
|
_playsink_reset_segment_event_marker_id =
|
||||||
|
g_quark_from_static_string ("gst-playsink-reset-segment-event-marker");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1834,6 +1842,152 @@ setup_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_generate_update_newsegment_event (GstPad * pad, GstSegment * segment,
|
||||||
|
GstEvent ** event1)
|
||||||
|
{
|
||||||
|
GstEvent *event;
|
||||||
|
GstStructure *structure;
|
||||||
|
event = gst_event_new_segment (segment);
|
||||||
|
structure = gst_event_writable_structure (event);
|
||||||
|
gst_structure_id_set (structure,
|
||||||
|
_playsink_reset_segment_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
|
||||||
|
*event1 = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
const GstStructure *structure = gst_event_get_structure (event);
|
||||||
|
|
||||||
|
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
|
||||||
|
structure
|
||||||
|
&& strcmp (gst_structure_get_name (structure),
|
||||||
|
"subtitleoverlay-flush-subtitle") == 0) {
|
||||||
|
GST_DEBUG_OBJECT (pad,
|
||||||
|
"Custom subtitle flush event received, marking to flush text");
|
||||||
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
|
playsink->text_flush = TRUE;
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
|
} else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
|
||||||
|
GST_DEBUG_OBJECT (pad,
|
||||||
|
"Resetting text segment because of flush-stop event");
|
||||||
|
gst_segment_init (&playsink->text_segment, GST_FORMAT_UNDEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
|
||||||
|
|
||||||
|
if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
|
||||||
|
const GstSegment *segment;
|
||||||
|
|
||||||
|
gst_event_parse_segment (event, &segment);
|
||||||
|
GST_DEBUG_OBJECT (pad, "Segment event: %" GST_SEGMENT_FORMAT, segment);
|
||||||
|
|
||||||
|
if (playsink->text_segment.format != segment->format) {
|
||||||
|
GST_DEBUG_OBJECT (pad, "Text segment format changed: %s -> %s",
|
||||||
|
gst_format_get_name (playsink->text_segment.format),
|
||||||
|
gst_format_get_name (segment->format));
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad, "Old text segment: %" GST_SEGMENT_FORMAT,
|
||||||
|
&playsink->text_segment);
|
||||||
|
gst_segment_copy_into (segment, &playsink->text_segment);
|
||||||
|
GST_DEBUG_OBJECT (pad, "New text segment: %" GST_SEGMENT_FORMAT,
|
||||||
|
&playsink->text_segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_event_unref (event);
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
|
||||||
|
GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
|
||||||
|
GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
|
||||||
|
|
||||||
|
GstFlowReturn ret = gst_proxy_pad_chain_default (pad, parent, buffer);
|
||||||
|
|
||||||
|
if (ret == GST_FLOW_FLUSHING && playsink->text_flush) {
|
||||||
|
GstEvent *event;
|
||||||
|
GstSegment *text_segment;
|
||||||
|
GstStructure *structure;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad,
|
||||||
|
"Ignoring wrong state due to flush text being marked");
|
||||||
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
|
playsink->text_flush = FALSE;
|
||||||
|
text_segment = gst_segment_copy (&playsink->text_segment);
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
|
|
||||||
|
/* make queue drop all cached data.
|
||||||
|
* This event will be dropped on the src pad. */
|
||||||
|
event = gst_event_new_flush_stop (TRUE);
|
||||||
|
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 (playsink,
|
||||||
|
"Pushing flush-stop event with reset segment marker set: %"
|
||||||
|
GST_PTR_FORMAT, structure);
|
||||||
|
gst_pad_send_event (pad, event);
|
||||||
|
|
||||||
|
/* Re-sync queue segment info after flush-stop.
|
||||||
|
* This event will be dropped on the src pad. */
|
||||||
|
if (text_segment->format != GST_FORMAT_UNDEFINED) {
|
||||||
|
GstEvent *event1;
|
||||||
|
|
||||||
|
_generate_update_newsegment_event (pad, text_segment, &event1);
|
||||||
|
GST_DEBUG_OBJECT (playsink,
|
||||||
|
"Pushing segment event with reset "
|
||||||
|
"segment marker set: %" GST_PTR_FORMAT, event1);
|
||||||
|
gst_pad_send_event (pad, event1);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_segment_free (text_segment);
|
||||||
|
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (playsink);
|
||||||
|
gst_object_unref (tbin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_play_sink_text_src_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
const GstStructure *structure;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad, "Got event %" GST_PTR_FORMAT, event);
|
||||||
|
|
||||||
|
structure = gst_event_get_structure (event);
|
||||||
|
|
||||||
|
if (structure &&
|
||||||
|
gst_structure_id_has_field (structure,
|
||||||
|
_playsink_reset_segment_event_marker_id)) {
|
||||||
|
/* the events marked with a reset segment marker
|
||||||
|
* are sent internally to reset the queue and
|
||||||
|
* must be dropped here */
|
||||||
|
GST_DEBUG_OBJECT (pad, "Dropping event with reset "
|
||||||
|
"segment marker set: %" GST_PTR_FORMAT, event);
|
||||||
|
ret = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
|
||||||
|
|
||||||
|
out:
|
||||||
|
gst_event_unref (event);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* make an element for playback of video with subtitles embedded.
|
/* make an element for playback of video with subtitles embedded.
|
||||||
* Only used for *raw* video streams.
|
* Only used for *raw* video streams.
|
||||||
*
|
*
|
||||||
|
@ -2027,11 +2181,21 @@ gen_text_chain (GstPlaySink * playsink)
|
||||||
if (textsinkpad) {
|
if (textsinkpad) {
|
||||||
chain->textsinkpad = gst_ghost_pad_new ("text_sink", textsinkpad);
|
chain->textsinkpad = gst_ghost_pad_new ("text_sink", textsinkpad);
|
||||||
gst_object_unref (textsinkpad);
|
gst_object_unref (textsinkpad);
|
||||||
|
|
||||||
|
gst_pad_set_event_function (chain->textsinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_text_sink_event));
|
||||||
|
gst_pad_set_chain_function (chain->textsinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_text_sink_chain));
|
||||||
|
|
||||||
gst_element_add_pad (chain->chain.bin, chain->textsinkpad);
|
gst_element_add_pad (chain->chain.bin, chain->textsinkpad);
|
||||||
}
|
}
|
||||||
if (srcpad) {
|
if (srcpad) {
|
||||||
chain->srcpad = gst_ghost_pad_new ("src", srcpad);
|
chain->srcpad = gst_ghost_pad_new ("src", srcpad);
|
||||||
gst_object_unref (srcpad);
|
gst_object_unref (srcpad);
|
||||||
|
|
||||||
|
gst_pad_set_event_function (chain->srcpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_play_sink_text_src_event));
|
||||||
|
|
||||||
gst_element_add_pad (chain->chain.bin, chain->srcpad);
|
gst_element_add_pad (chain->chain.bin, chain->srcpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3954,6 +4118,8 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
playsink = GST_PLAY_SINK (element);
|
playsink = GST_PLAY_SINK (element);
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
|
gst_segment_init (&playsink->text_segment, GST_FORMAT_UNDEFINED);
|
||||||
|
|
||||||
playsink->need_async_start = TRUE;
|
playsink->need_async_start = TRUE;
|
||||||
/* we want to go async to PAUSED until we managed to configure and add the
|
/* we want to go async to PAUSED until we managed to configure and add the
|
||||||
* sinks */
|
* sinks */
|
||||||
|
|
Loading…
Reference in a new issue