subtitleoverlay: Refactor autoplugging code and select overlay element by rank too

Previously we always used textoverlay for rendering the output of
a parser, now the same code as for the renderers is used and the
element with the highest rank is used.

Fixes bug #663822.
This commit is contained in:
Sebastian Dröge 2011-12-13 13:20:24 +01:00
parent 739de5fbf9
commit 87a4cbd0e3

View file

@ -746,6 +746,277 @@ _has_font_desc_property (GstElement * element)
return (pspec && pspec->value_type == G_TYPE_STRING);
}
static gboolean
_setup_parser (GstSubtitleOverlay * self)
{
GstPad *video_peer;
/* Try to get the latest video framerate */
video_peer = gst_pad_get_peer (self->video_sinkpad);
if (video_peer) {
GstCaps *video_caps;
gint fps_n, fps_d;
video_caps = gst_pad_get_negotiated_caps (video_peer);
if (!video_caps) {
video_caps = gst_pad_get_caps_reffed (video_peer);
if (!gst_caps_is_fixed (video_caps)) {
gst_caps_unref (video_caps);
video_caps = NULL;
}
}
if (video_caps
&& gst_video_parse_caps_framerate (video_caps, &fps_n, &fps_d)) {
if (self->fps_n != fps_n || self->fps_d != fps_d) {
GST_DEBUG_OBJECT (self, "New video fps: %d/%d", fps_n, fps_d);
self->fps_n = fps_n;
self->fps_d = fps_d;
}
}
if (video_caps)
gst_caps_unref (video_caps);
gst_object_unref (video_peer);
}
if (_has_subtitle_encoding_property (self->parser))
g_object_set (self->parser, "subtitle-encoding", self->encoding, NULL);
/* Try to set video fps on the parser */
gst_subtitle_overlay_set_fps (self);
return TRUE;
}
static gboolean
_setup_renderer (GstSubtitleOverlay * self, GstElement * renderer)
{
GstElementFactory *factory = gst_element_get_factory (renderer);
const gchar *name =
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory));
if (strcmp (name, "textoverlay") == 0) {
/* Set some textoverlay specific properties */
g_object_set (G_OBJECT (renderer),
"halign", "center", "valign", "bottom", "wait-text", FALSE, NULL);
if (self->font_desc)
g_object_set (G_OBJECT (renderer), "font-desc", self->font_desc, NULL);
self->silent_property = "silent";
self->silent_property_invert = FALSE;
} else {
self->silent_property =
_get_silent_property (renderer, &self->silent_property_invert);
if (_has_subtitle_encoding_property (renderer))
g_object_set (renderer, "subtitle-encoding", self->encoding, NULL);
if (_has_font_desc_property (renderer))
g_object_set (renderer, "font-desc", self->font_desc, NULL);
}
return TRUE;
}
/* subtitle_src==NULL means: use subtitle_sink ghostpad */
static gboolean
_link_renderer (GstSubtitleOverlay * self, GstElement * renderer,
GstPad * subtitle_src)
{
GstPad *sink, *src;
gboolean is_video, is_hw;
is_video = _is_video_pad (self->video_sinkpad, &is_hw);
if (is_video) {
gboolean render_is_hw;
/* First check that renderer also supports the video format */
sink = _get_video_pad (renderer);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
return FALSE;
}
if (is_video != _is_video_pad (sink, &render_is_hw) ||
is_hw != render_is_hw) {
GST_DEBUG_OBJECT (self, "Renderer doesn't support %s video",
is_hw ? "surface" : "raw");
gst_object_unref (sink);
return FALSE;
}
gst_object_unref (sink);
if (!is_hw) {
/* First link everything internally */
if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
COLORSPACE, NULL, "post-colorspace", FALSE))) {
return FALSE;
}
src = gst_element_get_static_pad (renderer, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
return FALSE;
}
sink = gst_element_get_static_pad (self->post_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
gst_object_unref (src);
return FALSE;
}
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link renderer with " COLORSPACE);
gst_object_unref (src);
gst_object_unref (sink);
return FALSE;
}
gst_object_unref (src);
gst_object_unref (sink);
if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
COLORSPACE, NULL, "pre-colorspace", FALSE))) {
return FALSE;
}
sink = _get_video_pad (renderer);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
return FALSE;
}
src = gst_element_get_static_pad (self->pre_colorspace, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
gst_object_unref (sink);
return FALSE;
}
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to renderer");
gst_object_unref (src);
gst_object_unref (sink);
return FALSE;
}
gst_object_unref (src);
gst_object_unref (sink);
/* Set src ghostpad target */
src = gst_element_get_static_pad (self->post_colorspace, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
return FALSE;
}
} else {
/* Set src ghostpad target in the harware accelerated case */
src = gst_element_get_static_pad (renderer, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
return FALSE;
}
}
} else { /* No video pad */
GstCaps *allowed_caps, *video_caps = NULL;
GstPad *video_peer;
gboolean can_intersect = FALSE;
video_peer = gst_pad_get_peer (self->video_sinkpad);
if (video_peer) {
video_caps = gst_pad_get_negotiated_caps (video_peer);
if (!video_caps) {
video_caps = gst_pad_get_caps_reffed (video_peer);
}
gst_object_unref (video_peer);
}
sink = _get_video_pad (renderer);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
return FALSE;
}
allowed_caps = gst_pad_get_caps_reffed (sink);
gst_object_unref (sink);
if (allowed_caps && video_caps)
can_intersect = gst_caps_can_intersect (allowed_caps, video_caps);
if (allowed_caps)
gst_caps_unref (allowed_caps);
if (video_caps)
gst_caps_unref (video_caps);
if (G_UNLIKELY (!can_intersect)) {
GST_WARNING_OBJECT (self, "Renderer with custom caps is not "
"compatible with video stream");
return FALSE;
}
src = gst_element_get_static_pad (renderer, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
return FALSE;
}
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->srcpad), src))) {
GST_WARNING_OBJECT (self, "Can't set srcpad target");
gst_object_unref (src);
return FALSE;
}
gst_object_unref (src);
/* Set the sink ghostpad targets */
if (self->pre_colorspace) {
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
return FALSE;
}
} else {
sink = _get_video_pad (renderer);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from %" GST_PTR_FORMAT,
renderer);
return FALSE;
}
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->video_sinkpad), sink))) {
GST_WARNING_OBJECT (self, "Can't set video sinkpad target");
gst_object_unref (sink);
return FALSE;
}
gst_object_unref (sink);
sink = _get_sub_pad (renderer);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Failed to get subpad");
return FALSE;
}
if (subtitle_src) {
if (G_UNLIKELY (gst_pad_link (subtitle_src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Failed to link subtitle srcpad with renderer");
gst_object_unref (sink);
return FALSE;
}
} else {
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->subtitle_sinkpad), sink))) {
GST_WARNING_OBJECT (self, "Failed to set subtitle sink target");
gst_object_unref (sink);
return FALSE;
}
}
gst_object_unref (sink);
return TRUE;
}
static void
_pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
{
@ -870,8 +1141,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
for (l = factories; l; l = l->next) {
GstElementFactory *factory = l->data;
gboolean is_video, is_hw, is_renderer = _is_renderer (factory);
GstElement *element;
gboolean is_renderer = _is_renderer (factory);
GstPad *sink, *src;
/* Unlink & destroy everything */
@ -899,519 +1169,114 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
"parser", FALSE))))
continue;
element = is_renderer ? self->renderer : self->parser;
is_video = _is_video_pad (self->video_sinkpad, &is_hw);
/* If this is a parser, create textoverlay and link video and the parser to it
* Else link the renderer to the output colorspace */
if (!is_renderer) {
GstElement *overlay;
GstPad *video_peer;
GstCaps *parser_caps;
GList *overlay_factories, *k;
/* Try to get the latest video framerate */
video_peer = gst_pad_get_peer (self->video_sinkpad);
if (video_peer) {
GstCaps *video_caps;
gint fps_n, fps_d;
video_caps = gst_pad_get_negotiated_caps (video_peer);
if (!video_caps) {
video_caps = gst_pad_get_caps_reffed (video_peer);
if (!gst_caps_is_fixed (video_caps)) {
gst_caps_unref (video_caps);
video_caps = NULL;
}
}
if (video_caps
&& gst_video_parse_caps_framerate (video_caps, &fps_n, &fps_d)) {
if (self->fps_n != fps_n || self->fps_d != fps_d) {
GST_DEBUG_OBJECT (self, "New video fps: %d/%d", fps_n, fps_d);
self->fps_n = fps_n;
self->fps_d = fps_d;
}
}
if (video_caps)
gst_caps_unref (video_caps);
gst_object_unref (video_peer);
}
if (_has_subtitle_encoding_property (self->parser))
g_object_set (self->parser, "subtitle-encoding", self->encoding, NULL);
/* Try to set video fps on the parser */
gst_subtitle_overlay_set_fps (self);
/* First link everything internally */
if (G_UNLIKELY (!_create_element (self, &self->overlay, "textoverlay",
NULL, "overlay", FALSE))) {
if (!_setup_parser (self))
continue;
}
overlay = self->overlay;
self->silent_property = "silent";
self->silent_property_invert = FALSE;
/* Set some properties */
g_object_set (G_OBJECT (overlay),
"halign", "center", "valign", "bottom", "wait-text", FALSE, NULL);
if (self->font_desc)
g_object_set (G_OBJECT (overlay), "font-desc", self->font_desc, NULL);
src = gst_element_get_static_pad (element, "src");
if (G_UNLIKELY (!src)) {
continue;
}
sink = gst_element_get_static_pad (overlay, "text_sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get text sink from textoverlay");
gst_object_unref (src);
continue;
}
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link parser to textoverlay");
gst_object_unref (sink);
gst_object_unref (src);
continue;
}
gst_object_unref (sink);
/* Find our factories */
src = gst_element_get_static_pad (self->parser, "src");
parser_caps = gst_pad_get_caps_reffed (src);
gst_object_unref (src);
/* If we are working with video/x-surface, we do not add
* colorspace conversion elements */
if (is_video && !is_hw) {
if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
COLORSPACE, NULL, "post-colorspace", FALSE))) {
continue;
}
g_assert (parser_caps != NULL);
src = gst_element_get_static_pad (overlay, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from overlay");
continue;
}
g_mutex_lock (self->factories_lock);
gst_subtitle_overlay_update_factory_list (self);
GST_DEBUG_OBJECT (self,
"Searching overlay factories for caps %" GST_PTR_FORMAT, parser_caps);
overlay_factories =
gst_subtitle_overlay_get_factories_for_caps (self->factories,
parser_caps);
g_mutex_unlock (self->factories_lock);
sink = gst_element_get_static_pad (self->post_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
gst_object_unref (src);
continue;
}
if (!overlay_factories) {
GST_WARNING_OBJECT (self,
"Found no suitable overlay factories for caps %" GST_PTR_FORMAT,
parser_caps);
gst_caps_unref (parser_caps);
continue;
}
gst_caps_unref (parser_caps);
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link overlay with " COLORSPACE);
gst_object_unref (src);
gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
/* Sort the factories by rank */
overlay_factories =
g_list_sort (overlay_factories, (GCompareFunc) _sort_by_ranks);
if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
"identity", NULL, "pre-colorspace", FALSE))) {
continue;
}
for (k = overlay_factories; k; k = k->next) {
GstElementFactory *overlay_factory = k->data;
sink = gst_element_get_static_pad (overlay, "video_sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from textoverlay");
continue;
}
GST_DEBUG_OBJECT (self, "Trying overlay factory '%s'",
GST_STR_NULL (gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST
(overlay_factory))));
src = gst_element_get_static_pad (self->pre_colorspace, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
gst_object_unref (sink);
continue;
}
/* Try this factory and link it, otherwise unlink everything
* again and remove the overlay. Up to this point only the
* parser was instantiated and setup, nothing was linked
*/
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to textoverlay");
gst_object_unref (src);
gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL);
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->video_sinkpad),
NULL);
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad),
NULL);
self->silent_property = NULL;
_remove_element (self, &self->post_colorspace);
_remove_element (self, &self->overlay);
_remove_element (self, &self->pre_colorspace);
/* Set src ghostpad target */
src = gst_element_get_static_pad (self->post_colorspace, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
if (!_create_element (self, &self->overlay, NULL, overlay_factory,
"overlay", FALSE))
continue;
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->srcpad), src))) {
GST_WARNING_OBJECT (self, "Can't set srcpad target");
if (!_setup_renderer (self, self->overlay))
continue;
src = gst_element_get_static_pad (self->parser, "src");
if (!_link_renderer (self, self->overlay, src)) {
gst_object_unref (src);
continue;
}
gst_object_unref (src);
} else if (is_hw) {
GST_DEBUG_OBJECT (self,
"Is Hardware, not adding colorspace converters, ");
/* Set src ghostpad target */
src = gst_element_get_static_pad (self->overlay, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from textoverlay");
continue;
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->srcpad), src))) {
GST_WARNING_OBJECT (self, "Can't set srcpad target");
gst_object_unref (src);
continue;
}
gst_object_unref (src);
/* Everything done here, go out of loop */
break;
}
/* Send segments to the parser/overlay if necessary. These are not sent
* outside this element because of the proxy pad event function */
if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2;
if (overlay_factories)
gst_plugin_feature_list_free (overlay_factories);
if (is_video) {
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
continue;
}
} else {
sink = gst_element_get_static_pad (self->overlay, "video_sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from textoverlay");
continue;
}
}
_generate_update_newsegment_event (&self->video_segment, &event1,
&event2);
GST_DEBUG_OBJECT (self,
"Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
event1->structure);
GST_DEBUG_OBJECT (self,
"Pushing video update newsegment event: %" GST_PTR_FORMAT,
event2->structure);
gst_pad_send_event (sink, event1);
gst_pad_send_event (sink, event2);
gst_object_unref (sink);
if (G_UNLIKELY (k == NULL)) {
GST_WARNING_OBJECT (self, "Failed to find usable overlay factory");
continue;
}
if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2;
sink = gst_element_get_static_pad (element, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Failed to get subpad");
continue;
}
_generate_update_newsegment_event (&self->subtitle_segment, &event1,
&event2);
GST_DEBUG_OBJECT (self,
"Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT,
event1->structure);
GST_DEBUG_OBJECT (self,
"Pushing subtitle update newsegment event: %" GST_PTR_FORMAT,
event2->structure);
gst_pad_send_event (sink, event1);
gst_pad_send_event (sink, event2);
gst_object_unref (sink);
}
/* Set the sink ghostpad targets */
if (is_video && !is_hw) {
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
continue;
}
} else if (is_video && is_hw) {
GST_DEBUG_OBJECT (self, "Setting ghostpad to overlay video sink");
sink = gst_element_get_static_pad (self->overlay, "video_sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from overlay");
continue;
}
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->video_sinkpad), sink))) {
GST_WARNING_OBJECT (self, "Can't set video sinkpad target");
/* Now link subtitle sinkpad of the bin and the parser */
sink = gst_element_get_static_pad (self->parser, "sink");
if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->subtitle_sinkpad), sink)) {
gst_object_unref (sink);
continue;
}
gst_object_unref (sink);
/* Link subtitle identity to subtitle pad of our element */
sink = gst_element_get_static_pad (element, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Failed to get subpad");
continue;
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->subtitle_sinkpad), sink))) {
GST_WARNING_OBJECT (self, "Failed to set subtitle sink target");
gst_object_unref (sink);
continue;
}
gst_object_unref (sink);
/* Everything done here, go out of loop */
break;
} else {
const gchar *name =
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory));
/* Is renderer factory */
if (strcmp (name, "textoverlay") == 0) {
/* Set some textoverlay specific properties */
g_object_set (G_OBJECT (element),
"halign", "center", "valign", "bottom", "wait-text", FALSE, NULL);
if (self->font_desc)
g_object_set (G_OBJECT (element), "font-desc", self->font_desc, NULL);
self->silent_property = "silent";
self->silent_property_invert = FALSE;
} else {
self->silent_property =
_get_silent_property (element, &self->silent_property_invert);
if (_has_subtitle_encoding_property (self->renderer))
g_object_set (self->renderer, "subtitle-encoding", self->encoding,
NULL);
if (_has_font_desc_property (self->renderer))
g_object_set (self->renderer, "font-desc", self->font_desc, NULL);
}
if (is_video) {
gboolean render_is_hw;
/* First check that renderer also supports the video format */
sink = _get_video_pad (element);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
continue;
}
if (is_video != _is_video_pad (sink, &render_is_hw) ||
is_hw != render_is_hw) {
GST_DEBUG_OBJECT (self, "Renderer doesn't support %s video",
is_hw ? "surface" : "raw");
gst_object_unref (sink);
continue;
}
gst_object_unref (sink);
if (!is_hw) {
/* First link everything internally */
if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
COLORSPACE, NULL, "post-colorspace", FALSE))) {
continue;
}
src = gst_element_get_static_pad (element, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
continue;
}
sink = gst_element_get_static_pad (self->post_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
gst_object_unref (src);
continue;
}
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link renderer with " COLORSPACE);
gst_object_unref (src);
gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
COLORSPACE, NULL, "pre-colorspace", FALSE))) {
continue;
}
sink = _get_video_pad (element);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
continue;
}
src = gst_element_get_static_pad (self->pre_colorspace, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
gst_object_unref (sink);
continue;
}
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to renderer");
gst_object_unref (src);
gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
/* Set src ghostpad target */
src = gst_element_get_static_pad (self->post_colorspace, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
continue;
}
} else {
/* Set src ghostpad target in the harware accelerated case */
src = gst_element_get_static_pad (self->renderer, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
continue;
}
}
} else { /* No video pad */
GstCaps *allowed_caps, *video_caps = NULL;
GstPad *video_peer;
gboolean can_intersect = FALSE;
video_peer = gst_pad_get_peer (self->video_sinkpad);
if (video_peer) {
video_caps = gst_pad_get_negotiated_caps (video_peer);
if (!video_caps) {
video_caps = gst_pad_get_caps_reffed (video_peer);
}
gst_object_unref (video_peer);
}
sink = _get_video_pad (element);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
continue;
}
allowed_caps = gst_pad_get_caps_reffed (sink);
gst_object_unref (sink);
if (allowed_caps && video_caps)
can_intersect = gst_caps_can_intersect (allowed_caps, video_caps);
if (allowed_caps)
gst_caps_unref (allowed_caps);
if (video_caps)
gst_caps_unref (video_caps);
if (G_UNLIKELY (!can_intersect)) {
GST_WARNING_OBJECT (self, "Renderer with custom caps is not "
"compatible with video stream");
continue;
}
src = gst_element_get_static_pad (element, "src");
if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
continue;
}
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->srcpad), src))) {
GST_WARNING_OBJECT (self, "Can't set srcpad target");
gst_object_unref (src);
if (!_setup_renderer (self, self->renderer))
continue;
}
gst_object_unref (src);
/* Send segments to the renderer if necessary. These are not sent
* outside this element because of the proxy pad event handler */
if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2;
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
continue;
}
_generate_update_newsegment_event (&self->video_segment, &event1,
&event2);
GST_DEBUG_OBJECT (self,
"Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
event1->structure);
GST_DEBUG_OBJECT (self,
"Pushing video update newsegment event: %" GST_PTR_FORMAT,
event2->structure);
gst_pad_send_event (sink, event1);
gst_pad_send_event (sink, event2);
gst_object_unref (sink);
}
if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2;
sink = _get_sub_pad (element);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Failed to get subpad");
continue;
}
_generate_update_newsegment_event (&self->subtitle_segment, &event1,
&event2);
GST_DEBUG_OBJECT (self,
"Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT,
event1->structure);
GST_DEBUG_OBJECT (self,
"Pushing subtitle update newsegment event: %" GST_PTR_FORMAT,
event2->structure);
gst_pad_send_event (sink, event1);
gst_pad_send_event (sink, event2);
gst_object_unref (sink);
}
/* Set the sink ghostpad targets */
if (self->pre_colorspace) {
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
continue;
}
} else {
sink = _get_video_pad (element);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from %" GST_PTR_FORMAT,
element);
continue;
}
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->video_sinkpad), sink))) {
GST_WARNING_OBJECT (self, "Can't set video sinkpad target");
gst_object_unref (sink);
/* subtitle_src==NULL means: use subtitle_sink ghostpad */
if (!_link_renderer (self, self->renderer, NULL))
continue;
}
gst_object_unref (sink);
sink = _get_sub_pad (element);
if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Failed to get subpad");
continue;
}
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->subtitle_sinkpad), sink))) {
GST_WARNING_OBJECT (self, "Failed to set subtitle sink target");
gst_object_unref (sink);
continue;
}
gst_object_unref (sink);
/* Everything done here, go out of loop */
break;
}
break;
}
if (G_UNLIKELY (l == NULL)) {
@ -1420,15 +1285,62 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
self->subtitle_error = TRUE;
_setup_passthrough (self);
do_async_done (self);
} else {
GST_DEBUG_OBJECT (self, "Everything worked, unblocking pads");
gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
_pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
_pad_blocked_cb, self, NULL);
do_async_done (self);
goto out;
}
/* Send segments to the renderer if necessary. These are not sent
* outside this element because of the proxy pad event handler */
if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2;
GstPad *sink;
if (self->pre_colorspace) {
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
} else {
sink = _get_video_pad ((self->renderer) ? self->renderer : self->overlay);
}
_generate_update_newsegment_event (&self->video_segment, &event1, &event2);
GST_DEBUG_OBJECT (self,
"Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
event1->structure);
GST_DEBUG_OBJECT (self,
"Pushing video update newsegment event: %" GST_PTR_FORMAT,
event2->structure);
gst_pad_send_event (sink, event1);
gst_pad_send_event (sink, event2);
gst_object_unref (sink);
}
if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2;
GstPad *sink;
if (self->renderer)
sink = _get_sub_pad (self->renderer);
else
sink = gst_element_get_static_pad (self->parser, "sink");
_generate_update_newsegment_event (&self->subtitle_segment, &event1,
&event2);
GST_DEBUG_OBJECT (self,
"Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT,
event1->structure);
GST_DEBUG_OBJECT (self,
"Pushing subtitle update newsegment event: %" GST_PTR_FORMAT,
event2->structure);
gst_pad_send_event (sink, event1);
gst_pad_send_event (sink, event2);
gst_object_unref (sink);
}
GST_DEBUG_OBJECT (self, "Everything worked, unblocking pads");
gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
_pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
_pad_blocked_cb, self, NULL);
do_async_done (self);
out:
if (factories)
gst_plugin_feature_list_free (factories);
@ -1790,8 +1702,8 @@ gst_subtitle_overlay_src_proxy_event (GstPad * proxypad, GstEvent * event)
s = gst_event_get_structure (event);
if (s && gst_structure_id_has_field (s, _subtitle_overlay_event_marker_id)) {
GST_DEBUG_OBJECT (ghostpad, "Dropping event with marker: %" GST_PTR_FORMAT,
event->structure);
GST_DEBUG_OBJECT (ghostpad,
"Dropping event with marker: %" GST_PTR_FORMAT, event->structure);
gst_event_unref (event);
event = NULL;
ret = TRUE;
@ -2161,8 +2073,8 @@ gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstEvent * event)
gst_structure_set_parent_refcount (event->structure,
&event->mini_object.refcount);
}
gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
G_TYPE_BOOLEAN, TRUE, NULL);
gst_structure_id_set (event->structure,
_subtitle_overlay_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
break;
default:
break;