subtitleoverlay: add suport for hardware accelerated videos

Don't plug converters for non-raw video.
This commit is contained in:
Thibault Saunier 2011-11-23 15:43:46 -03:00 committed by Tim-Philipp Müller
parent 7d20a7bdb9
commit 8728023f00

View file

@ -193,11 +193,12 @@ _is_raw_video (GstStructure * s)
} }
static gboolean static gboolean
_is_raw_video_pad (GstPad * pad) _is_video_pad (GstPad * pad, gboolean * hw_accelerated)
{ {
GstPad *peer = gst_pad_get_peer (pad); GstPad *peer = gst_pad_get_peer (pad);
GstCaps *caps; GstCaps *caps;
gboolean raw = TRUE; gboolean ret;
const gchar *name;
if (peer) { if (peer) {
caps = gst_pad_get_negotiated_caps (peer); caps = gst_pad_get_negotiated_caps (peer);
@ -209,11 +210,27 @@ _is_raw_video_pad (GstPad * pad)
caps = gst_pad_get_caps_reffed (pad); caps = gst_pad_get_caps_reffed (pad);
} }
raw = _is_raw_video (gst_caps_get_structure (caps, 0));
name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
if (g_str_has_prefix (name, "video/x-raw-")) {
ret = TRUE;
if (hw_accelerated)
*hw_accelerated = FALSE;
} else if (g_str_has_prefix (name, "video/x-surface")) {
ret = TRUE;
if (hw_accelerated)
*hw_accelerated = TRUE;
} else {
ret = FALSE;
if (hw_accelerated)
*hw_accelerated = FALSE;
}
gst_caps_unref (caps); gst_caps_unref (caps);
return raw; return ret;
} }
static GstCaps * static GstCaps *
@ -853,7 +870,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
for (l = factories; l; l = l->next) { for (l = factories; l; l = l->next) {
GstElementFactory *factory = l->data; GstElementFactory *factory = l->data;
gboolean is_renderer = _is_renderer (factory); gboolean is_video, is_hw, is_renderer = _is_renderer (factory);
GstElement *element; GstElement *element;
GstPad *sink, *src; GstPad *sink, *src;
@ -884,6 +901,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
element = is_renderer ? self->renderer : self->parser; 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 /* If this is a parser, create textoverlay and link video and the parser to it
* Else link the renderer to the output colorspace */ * Else link the renderer to the output colorspace */
if (!is_renderer) { if (!is_renderer) {
@ -961,84 +979,113 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
gst_object_unref (sink); gst_object_unref (sink);
gst_object_unref (src); gst_object_unref (src);
if (G_UNLIKELY (!_create_element (self, &self->post_colorspace, /* If we are working with video/x-surface, we do not add
COLORSPACE, NULL, "post-colorspace", FALSE))) { * colorspace conversion elements */
continue; if (is_video && !is_hw) {
} if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
COLORSPACE, NULL, "post-colorspace", FALSE))) {
continue;
}
src = gst_element_get_static_pad (overlay, "src"); src = gst_element_get_static_pad (overlay, "src");
if (G_UNLIKELY (!src)) { if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from overlay"); GST_WARNING_OBJECT (self, "Can't get src pad from overlay");
continue; continue;
} }
sink = gst_element_get_static_pad (self->post_colorspace, "sink"); sink = gst_element_get_static_pad (self->post_colorspace, "sink");
if (G_UNLIKELY (!sink)) { if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE); GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
gst_object_unref (src); gst_object_unref (src);
continue; continue;
} }
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link overlay with " COLORSPACE); 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 (src);
gst_object_unref (sink); gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace, if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
COLORSPACE, NULL, "pre-colorspace", FALSE))) { "identity", NULL, "pre-colorspace", FALSE))) {
continue; continue;
} }
sink = gst_element_get_static_pad (overlay, "video_sink"); sink = gst_element_get_static_pad (overlay, "video_sink");
if (G_UNLIKELY (!sink)) { if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from textoverlay"); GST_WARNING_OBJECT (self, "Can't get video sink from textoverlay");
continue; continue;
} }
src = gst_element_get_static_pad (self->pre_colorspace, "src"); src = gst_element_get_static_pad (self->pre_colorspace, "src");
if (G_UNLIKELY (!src)) { if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE); GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
gst_object_unref (sink); gst_object_unref (sink);
continue; continue;
} }
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to textoverlay"); 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 (src);
gst_object_unref (sink); gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
/* Set src ghostpad target */ /* Set src ghostpad target */
src = gst_element_get_static_pad (self->post_colorspace, "src"); src = gst_element_get_static_pad (self->post_colorspace, "src");
if (G_UNLIKELY (!src)) { if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE); GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
continue; continue;
} }
if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
(self->srcpad), src))) { (self->srcpad), src))) {
GST_WARNING_OBJECT (self, "Can't set srcpad target"); GST_WARNING_OBJECT (self, "Can't set srcpad target");
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); gst_object_unref (src);
continue;
} }
gst_object_unref (src);
/* Send segments to the parser/overlay if necessary. These are not sent /* Send segments to the parser/overlay if necessary. These are not sent
* outside this element because of the proxy pad event function */ * outside this element because of the proxy pad event function */
if (self->video_segment.format != GST_FORMAT_UNDEFINED) { if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
GstEvent *event1, *event2; GstEvent *event1, *event2;
sink = gst_element_get_static_pad (self->pre_colorspace, "sink"); if (is_video) {
if (G_UNLIKELY (!sink)) { sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE); if (G_UNLIKELY (!sink)) {
continue; 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, _generate_update_newsegment_event (&self->video_segment, &event1,
@ -1079,10 +1126,19 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
} }
/* Set the sink ghostpad targets */ /* Set the sink ghostpad targets */
sink = gst_element_get_static_pad (self->pre_colorspace, "sink"); if (is_video && !is_hw) {
if (G_UNLIKELY (!sink)) { sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE); if (G_UNLIKELY (!sink)) {
continue; 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 if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST
@ -1110,7 +1166,6 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
} else { } else {
const gchar *name = const gchar *name =
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)); gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory));
gboolean is_raw_video = _is_raw_video_pad (self->video_sinkpad);
if (strcmp (name, "textoverlay") == 0) { if (strcmp (name, "textoverlay") == 0) {
/* Set some textoverlay specific properties */ /* Set some textoverlay specific properties */
@ -1130,82 +1185,96 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
g_object_set (self->renderer, "font-desc", self->font_desc, NULL); g_object_set (self->renderer, "font-desc", self->font_desc, NULL);
} }
if (is_raw_video) { if (is_video) {
/* First check that renderer also supports raw video */ gboolean render_is_hw;
/* First check that renderer also supports the video format */
sink = _get_video_pad (element); sink = _get_video_pad (element);
if (G_UNLIKELY (!sink)) { if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer"); GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
continue; continue;
} }
if (G_UNLIKELY (!_is_raw_video_pad (sink))) { if (is_video != _is_video_pad (sink, &render_is_hw) ||
GST_DEBUG_OBJECT (self, "Renderer doesn't support raw video"); is_hw != render_is_hw) {
GST_DEBUG_OBJECT (self, "Renderer doesn't support %s video",
is_hw ? "surface" : "raw");
gst_object_unref (sink); gst_object_unref (sink);
continue; continue;
} }
gst_object_unref (sink); gst_object_unref (sink);
/* First link everything internally */ if (!is_hw) {
if (G_UNLIKELY (!_create_element (self, &self->post_colorspace, /* First link everything internally */
COLORSPACE, NULL, "post-colorspace", FALSE))) { if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
continue; COLORSPACE, NULL, "post-colorspace", FALSE))) {
} continue;
src = gst_element_get_static_pad (element, "src"); }
if (G_UNLIKELY (!src)) { src = gst_element_get_static_pad (element, "src");
GST_WARNING_OBJECT (self, "Can't get src pad from renderer"); if (G_UNLIKELY (!src)) {
continue; GST_WARNING_OBJECT (self, "Can't get src pad from renderer");
} continue;
}
sink = gst_element_get_static_pad (self->post_colorspace, "sink"); sink = gst_element_get_static_pad (self->post_colorspace, "sink");
if (G_UNLIKELY (!sink)) { if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE); GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
gst_object_unref (src); gst_object_unref (src);
continue; continue;
} }
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link renderer with " COLORSPACE); 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 (src);
gst_object_unref (sink); gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace, if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
COLORSPACE, NULL, "pre-colorspace", FALSE))) { COLORSPACE, NULL, "pre-colorspace", FALSE))) {
continue; continue;
} }
sink = _get_video_pad (element); sink = _get_video_pad (element);
if (G_UNLIKELY (!sink)) { if (G_UNLIKELY (!sink)) {
GST_WARNING_OBJECT (self, "Can't get video sink from renderer"); GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
continue; continue;
} }
src = gst_element_get_static_pad (self->pre_colorspace, "src"); src = gst_element_get_static_pad (self->pre_colorspace, "src");
if (G_UNLIKELY (!src)) { if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE); GST_WARNING_OBJECT (self, "Can't get srcpad from " COLORSPACE);
gst_object_unref (sink); gst_object_unref (sink);
continue; continue;
} }
if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
GST_WARNING_OBJECT (self, "Can't link " COLORSPACE " to renderer"); 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 (src);
gst_object_unref (sink); gst_object_unref (sink);
continue;
}
gst_object_unref (src);
gst_object_unref (sink);
/* Set src ghostpad target */ /* Set src ghostpad target */
src = gst_element_get_static_pad (self->post_colorspace, "src"); src = gst_element_get_static_pad (self->post_colorspace, "src");
if (G_UNLIKELY (!src)) { if (G_UNLIKELY (!src)) {
GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE); GST_WARNING_OBJECT (self, "Can't get src pad from " COLORSPACE);
continue; 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 raw video pad */ } else { /* No video pad */
GstCaps *allowed_caps, *video_caps = NULL; GstCaps *allowed_caps, *video_caps = NULL;
GstPad *video_peer; GstPad *video_peer;
gboolean can_intersect = FALSE; gboolean can_intersect = FALSE;