#include <gst/video/video.h>
#include <string.h>
+#include "gst/glib-compat-private.h"
+
GST_DEBUG_CATEGORY_STATIC (subtitle_overlay_debug);
#define GST_CAT_DEFAULT subtitle_overlay_debug
"subtitle_sink", "subtitle"
};
+static inline gboolean
+_is_raw_video (GstStructure * s)
+{
+ const gchar *name;
+
+ name = gst_structure_get_name (s);
+
+ if (g_str_has_prefix (name, "video/x-raw-"))
+ return TRUE;
+ return FALSE;
+}
+
+static gboolean
+_is_video_pad (GstPad * pad, gboolean * hw_accelerated)
+{
+ GstPad *peer = gst_pad_get_peer (pad);
+ GstCaps *caps;
+ gboolean ret;
+ const gchar *name;
+
+ if (peer) {
+ caps = gst_pad_get_negotiated_caps (peer);
+ if (!caps) {
+ caps = gst_pad_get_caps_reffed (peer);
+ }
+ gst_object_unref (peer);
+ } else {
+ caps = gst_pad_get_caps_reffed (pad);
+ }
+
+
+ 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);
+
+ return ret;
+}
+
static GstCaps *
_get_sub_caps (GstElementFactory * factory)
{
templ_caps = _get_sub_caps (factory);
if (is_renderer && have_video_sink && templ_caps) {
- GstCaps *tmp;
-
GST_DEBUG ("Found renderer element %s (%s) with caps %" GST_PTR_FORMAT,
gst_element_factory_get_longname (factory),
gst_plugin_feature_get_name (feature), templ_caps);
- tmp = gst_caps_union (*subcaps, templ_caps);
- gst_caps_unref (templ_caps);
- gst_caps_replace (subcaps, tmp);
- gst_caps_unref (tmp);
+ gst_caps_merge (*subcaps, templ_caps);
return TRUE;
} else if (!is_renderer && !have_video_sink && templ_caps) {
- GstCaps *tmp;
-
GST_DEBUG ("Found parser element %s (%s) with caps %" GST_PTR_FORMAT,
gst_element_factory_get_longname (factory),
gst_plugin_feature_get_name (feature), templ_caps);
- tmp = gst_caps_union (*subcaps, templ_caps);
- gst_caps_unref (templ_caps);
- gst_caps_replace (subcaps, tmp);
- gst_caps_unref (tmp);
+ gst_caps_merge (*subcaps, templ_caps);
return TRUE;
} else {
if (templ_caps)
}
static gboolean
-_filter_factories_for_caps (GstElementFactory * factory, const GstCaps * caps)
+check_factory_for_caps (GstElementFactory * factory, const GstCaps * caps)
{
GstCaps *fcaps = _get_sub_caps (factory);
gboolean ret = (fcaps) ? gst_caps_can_intersect (fcaps, caps) : FALSE;
return ret;
}
+static GList *
+gst_subtitle_overlay_get_factories_for_caps (const GList * list,
+ const GstCaps * caps)
+{
+ const GList *walk = list;
+ GList *result = NULL;
+
+ while (walk) {
+ GstElementFactory *factory = walk->data;
+
+ walk = g_list_next (walk);
+
+ if (check_factory_for_caps (factory, caps)) {
+ result = g_list_prepend (result, factory);
+ }
+ }
+
+ return result;
+}
+
static gint
_sort_by_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
{
out:
/* Unblock pads */
gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
if (self->subtitle_sink_blocked)
gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
return TRUE;
}
/* Unblock pads */
gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
if (self->subtitle_sink_blocked)
gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
goto out;
} else if (target) {
gst_object_unref (target);
if (self->subtitle_sink_blocked && !self->video_sink_blocked) {
GST_DEBUG_OBJECT (self, "Subtitle sink blocked but video not blocked");
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
goto out;
}
g_mutex_lock (self->factories_lock);
gst_subtitle_overlay_update_factory_list (self);
if (subcaps) {
- factories = gst_filter_run (self->factories,
- (GstFilterFunc) _filter_factories_for_caps, FALSE, subcaps);
+ factories =
+ gst_subtitle_overlay_get_factories_for_caps (self->factories, subcaps);
if (!factories) {
GstMessage *msg;
for (l = factories; l; l = l->next) {
GstElementFactory *factory = l->data;
- gboolean is_renderer = _is_renderer (factory);
+ gboolean is_video, is_hw, is_renderer = _is_renderer (factory);
GstElement *element;
GstPad *sink, *src;
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) {
gst_object_unref (sink);
gst_object_unref (src);
- if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
- "ffmpegcolorspace", NULL, "post-colorspace", FALSE))) {
- continue;
- }
+ /* 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;
+ }
- src = gst_element_get_static_pad (overlay, "src");
- if (G_UNLIKELY (!src)) {
- GST_WARNING_OBJECT (self, "Can't get src pad from overlay");
- continue;
- }
+ src = gst_element_get_static_pad (overlay, "src");
+ if (G_UNLIKELY (!src)) {
+ GST_WARNING_OBJECT (self, "Can't get src pad from overlay");
+ 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 ffmpegcolorspace");
- gst_object_unref (src);
- 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 overlay with ffmpegcolorspace");
+ 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);
- continue;
- }
- gst_object_unref (src);
- gst_object_unref (sink);
- if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
- "ffmpegcolorspace", NULL, "pre-colorspace", FALSE))) {
- continue;
- }
+ if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
+ "identity", NULL, "pre-colorspace", FALSE))) {
+ continue;
+ }
- 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;
- }
+ 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;
+ }
- src = gst_element_get_static_pad (self->pre_colorspace, "src");
- if (G_UNLIKELY (!src)) {
- GST_WARNING_OBJECT (self, "Can't get srcpad from ffmpegcolorspace");
- gst_object_unref (sink);
- 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 ffmpegcolorspace to textoverlay");
+ 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);
- 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 ffmpegcolorspace");
- continue;
- }
+ /* 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;
+ }
- 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 (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);
+ } 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);
- continue;
}
- gst_object_unref (src);
/* 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;
- sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
- if (G_UNLIKELY (!sink)) {
- GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace");
- continue;
+ 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,
}
/* Set the sink ghostpad targets */
- sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
- if (G_UNLIKELY (!sink)) {
- GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace");
- continue;
+ 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
g_object_set (self->renderer, "font-desc", self->font_desc, NULL);
}
- /* First link everything internally */
- if (G_UNLIKELY (!_create_element (self, &self->post_colorspace,
- "ffmpegcolorspace", NULL, "post-colorspace", FALSE))) {
- continue;
- }
+ if (is_video) {
+ gboolean render_is_hw;
- 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 ffmpegcolorspace");
- gst_object_unref (src);
- continue;
- }
+ /* 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 (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
- GST_WARNING_OBJECT (self, "Can't link renderer with ffmpegcolorspace");
- gst_object_unref (src);
+ 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);
- continue;
- }
- gst_object_unref (src);
- gst_object_unref (sink);
- if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace,
- "ffmpegcolorspace", NULL, "pre-colorspace", FALSE))) {
- continue;
- }
+ 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 = _get_video_pad (element);
- if (G_UNLIKELY (!sink)) {
- GST_WARNING_OBJECT (self, "Can't get video sink 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;
+ }
- src = gst_element_get_static_pad (self->pre_colorspace, "src");
- if (G_UNLIKELY (!src)) {
- GST_WARNING_OBJECT (self, "Can't get srcpad from ffmpegcolorspace");
- gst_object_unref (sink);
- 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 (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) {
- GST_WARNING_OBJECT (self, "Can't link ffmpegcolorspace to renderer");
- gst_object_unref (src);
+ 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);
- 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 ffmpegcolorspace");
- continue;
+ 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
sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
if (G_UNLIKELY (!sink)) {
- GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace");
+ GST_WARNING_OBJECT (self, "Can't get sink pad from " COLORSPACE);
continue;
}
}
/* Set the sink ghostpad targets */
- sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
- if (G_UNLIKELY (!sink)) {
- GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace");
- continue;
+ 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
} else {
GST_DEBUG_OBJECT (self, "Everything worked, unblocking pads");
gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
do_async_done (self);
}
GST_SUBTITLE_OVERLAY_LOCK (self);
/* Set the internal pads to blocking */
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_DEBUG_OBJECT (self, "State change PAUSED->READY");
+
+ /* Set the pads back to blocking state */
+ GST_SUBTITLE_OVERLAY_LOCK (self);
+ gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
+ _pad_blocked_cb, self, NULL);
+ gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
+ _pad_blocked_cb, self, NULL);
+ GST_SUBTITLE_OVERLAY_UNLOCK (self);
+
do_async_done (self);
break;
if (self->video_block_pad) {
pad = self->video_block_pad;
gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb,
- gst_object_ref (self), (GDestroyNotify) gst_object_unref);
+ self, NULL);
}
if (self->subtitle_block_pad) {
pad = self->subtitle_block_pad;
gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb,
- gst_object_ref (self), (GDestroyNotify) gst_object_unref);
+ self, NULL);
}
/* Remove elements */
self->subtitle_error = TRUE;
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
}
}
g_object_set (self->renderer, self->silent_property, silent, NULL);
} else {
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
}
GST_SUBTITLE_OVERLAY_UNLOCK (self);
break;
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&srctemplate));
+ gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&video_sinktemplate));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&subtitle_sinktemplate));
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &video_sinktemplate);
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &subtitle_sinktemplate);
gst_element_class_set_details_simple (gstelement_class, "Subtitle Overlay",
"Video/Overlay/Subtitle",
return GST_FLOW_ERROR;
}
- ret = self->src_proxy_chain (proxypad, buffer);
+ ret = gst_proxy_pad_chain_default (proxypad, buffer);
if (IS_VIDEO_CHAIN_IGNORE_ERROR (ret)) {
GST_ERROR_OBJECT (self, "Downstream chain error: %s",
event = NULL;
ret = TRUE;
} else {
- ret = self->src_proxy_event (proxypad, event);
+ ret = gst_proxy_pad_event_default (proxypad, event);
event = NULL;
}
gst_subtitle_overlay_video_sink_setcaps (GstPad * pad, GstCaps * caps)
{
GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
+ GstPad *target;
gboolean ret = TRUE;
gint fps_n, fps_d;
GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps);
+ target = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->video_sinkpad));
+
+ GST_SUBTITLE_OVERLAY_LOCK (self);
+
+ if (!target || !gst_pad_accept_caps (target, caps)) {
+ GST_DEBUG_OBJECT (pad, "Target did not accept caps -- reconfiguring");
+
+ gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
+ _pad_blocked_cb, self, NULL);
+
+ gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
+ _pad_blocked_cb, self, NULL);
+ }
+
if (!gst_video_parse_caps_framerate (caps, &fps_n, &fps_d)) {
GST_ERROR_OBJECT (pad, "Failed to parse framerate from caps");
ret = FALSE;
+ GST_SUBTITLE_OVERLAY_UNLOCK (self);
goto out;
}
- GST_SUBTITLE_OVERLAY_LOCK (self);
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;
}
GST_SUBTITLE_OVERLAY_UNLOCK (self);
- ret = self->video_sink_setcaps (pad, caps);
+ ret = gst_ghost_pad_setcaps_default (pad, caps);
out:
+ if (target)
+ gst_object_unref (target);
gst_object_unref (self);
return ret;
}
self->fps_n = self->fps_d = 0;
}
- ret = self->video_sink_event (pad, gst_event_ref (event));
+ ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
gboolean update;
if (format != GST_FORMAT_TIME) {
GST_ERROR_OBJECT (pad, "Newsegment event in non-time format: %s",
gst_format_get_name (format));
- gst_object_unref (event);
+ gst_event_unref (event);
gst_object_unref (self);
return FALSE;
}
gst_subtitle_overlay_video_sink_chain (GstPad * pad, GstBuffer * buffer)
{
GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (GST_PAD_PARENT (pad));
- GstFlowReturn ret = self->video_sink_chain (pad, buffer);
+ GstFlowReturn ret = gst_proxy_pad_chain_default (pad, buffer);
if (G_UNLIKELY (self->downstream_chain_error) || self->passthrough_identity) {
return ret;
GST_SUBTITLE_OVERLAY_LOCK (self);
self->subtitle_error = TRUE;
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
return GST_FLOW_OK;
gst_buffer_unref (buffer);
return GST_FLOW_OK;
} else {
- GstFlowReturn ret = self->subtitle_sink_chain (pad, buffer);
+ GstFlowReturn ret = gst_proxy_pad_chain_default (pad, buffer);
if (IS_SUBTITLE_CHAIN_IGNORE_ERROR (ret)) {
GST_DEBUG_OBJECT (self, "Subtitle chain error: %s",
GST_SUBTITLE_OVERLAY_LOCK (self);
self->subtitle_error = TRUE;
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
return GST_FLOW_OK;
gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps)
{
GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad);
- gboolean ret = gst_caps_can_intersect (caps, othercaps);
+ gboolean ret = gst_caps_is_subset (caps, othercaps);
gst_caps_unref (othercaps);
if (target && gst_pad_accept_caps (target, caps)) {
GST_DEBUG_OBJECT (pad, "Target accepts caps");
- ret = self->subtitle_sink_setcaps (pad, caps);
+ ret = gst_ghost_pad_setcaps_default (pad, caps);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
goto out;
}
self->subtitle_error = FALSE;
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
out:
self->subtitle_error = FALSE;
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
gst_caps_unref (caps);
}
- ret = self->subtitle_sink_link (pad, peer);
+ ret = gst_ghost_pad_link_default (pad, peer);
gst_object_unref (self);
return ret;
GST_DEBUG_OBJECT (pad, "Pad unlinking");
gst_caps_replace (&self->subcaps, NULL);
- self->subtitle_sink_unlink (pad);
+ gst_ghost_pad_unlink_default (pad);
GST_SUBTITLE_OVERLAY_LOCK (self);
self->subtitle_error = FALSE;
if (self->subtitle_block_pad)
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
if (self->video_block_pad)
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
gst_object_unref (self);
self->subtitle_error = FALSE;
if (self->subtitle_block_pad)
gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
if (self->video_block_pad)
gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
- _pad_blocked_cb, gst_object_ref (self),
- (GDestroyNotify) gst_object_unref);
+ _pad_blocked_cb, self, NULL);
GST_SUBTITLE_OVERLAY_UNLOCK (self);
gst_event_unref (event);
break;
}
- ret = self->subtitle_sink_event (pad, gst_event_ref (event));
+ ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
gboolean update;
GstSubtitleOverlayClass * klass)
{
GstPadTemplate *templ;
- GstIterator *it;
GstPad *proxypad = NULL;
self->lock = g_mutex_new ();
templ = gst_static_pad_template_get (&srctemplate);
self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ);
- it = gst_pad_iterate_internal_links (self->srcpad);
- if (G_UNLIKELY (!it
- || gst_iterator_next (it, (gpointer) & proxypad) != GST_ITERATOR_OK
- || proxypad == NULL)) {
- GST_ERROR_OBJECT (self, "Failed to get proxypad of srcpad");
- } else {
- self->src_proxy_event = GST_PAD_EVENTFUNC (proxypad);
- gst_pad_set_event_function (proxypad,
- GST_DEBUG_FUNCPTR (gst_subtitle_overlay_src_proxy_event));
- self->src_proxy_chain = GST_PAD_CHAINFUNC (proxypad);
- gst_pad_set_chain_function (proxypad,
- GST_DEBUG_FUNCPTR (gst_subtitle_overlay_src_proxy_chain));
- gst_object_unref (proxypad);
- }
- if (it)
- gst_iterator_free (it);
+ gst_object_unref (templ);
+
+ proxypad =
+ GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->srcpad)));
+ gst_pad_set_event_function (proxypad,
+ GST_DEBUG_FUNCPTR (gst_subtitle_overlay_src_proxy_event));
+ gst_pad_set_chain_function (proxypad,
+ GST_DEBUG_FUNCPTR (gst_subtitle_overlay_src_proxy_chain));
+ gst_object_unref (proxypad);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad);
templ = gst_static_pad_template_get (&video_sinktemplate);
self->video_sinkpad =
gst_ghost_pad_new_no_target_from_template ("video_sink", templ);
- self->video_sink_event = GST_PAD_EVENTFUNC (self->video_sinkpad);
+ gst_object_unref (templ);
gst_pad_set_event_function (self->video_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_event));
- self->video_sink_setcaps = GST_PAD_SETCAPSFUNC (self->video_sinkpad);
gst_pad_set_setcaps_function (self->video_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_setcaps));
- self->video_sink_chain = GST_PAD_CHAINFUNC (self->video_sinkpad);
gst_pad_set_chain_function (self->video_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_chain));
- proxypad = NULL;
- it = gst_pad_iterate_internal_links (self->video_sinkpad);
- if (G_UNLIKELY (!it
- || gst_iterator_next (it, (gpointer) & proxypad) != GST_ITERATOR_OK
- || proxypad == NULL)) {
- GST_ERROR_OBJECT (self,
- "Failed to get internally linked pad from video sinkpad");
- }
- if (it)
- gst_iterator_free (it);
+ proxypad =
+ GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
+ (self->video_sinkpad)));
self->video_block_pad = proxypad;
+ gst_object_unref (proxypad);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->video_sinkpad);
templ = gst_static_pad_template_get (&subtitle_sinktemplate);
self->subtitle_sinkpad =
gst_ghost_pad_new_no_target_from_template ("subtitle_sink", templ);
- self->subtitle_sink_link = GST_PAD_LINKFUNC (self->subtitle_sinkpad);
+ gst_object_unref (templ);
gst_pad_set_link_function (self->subtitle_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_link));
- self->subtitle_sink_unlink = GST_PAD_UNLINKFUNC (self->subtitle_sinkpad);
gst_pad_set_unlink_function (self->subtitle_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_unlink));
- self->subtitle_sink_event = GST_PAD_EVENTFUNC (self->subtitle_sinkpad);
gst_pad_set_event_function (self->subtitle_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_event));
- self->subtitle_sink_setcaps = GST_PAD_SETCAPSFUNC (self->subtitle_sinkpad);
gst_pad_set_setcaps_function (self->subtitle_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_setcaps));
- self->subtitle_sink_chain = GST_PAD_CHAINFUNC (self->subtitle_sinkpad);
gst_pad_set_chain_function (self->subtitle_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_chain));
gst_pad_set_getcaps_function (self->subtitle_sinkpad,
GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_acceptcaps));
gst_pad_set_bufferalloc_function (self->subtitle_sinkpad, NULL);
- proxypad = NULL;
- it = gst_pad_iterate_internal_links (self->subtitle_sinkpad);
- if (G_UNLIKELY (!it
- || gst_iterator_next (it, (gpointer) & proxypad) != GST_ITERATOR_OK
- || proxypad == NULL)) {
- GST_ERROR_OBJECT (self,
- "Failed to get internally linked pad from subtitle sinkpad");
- }
- if (it)
- gst_iterator_free (it);
+ proxypad =
+ GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD
+ (self->subtitle_sinkpad)));
self->subtitle_block_pad = proxypad;
+ gst_object_unref (proxypad);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->subtitle_sinkpad);