Merge branch 'master' into 0.11
[platform/upstream/gst-plugins-base.git] / gst / playback / gstsubtitleoverlay.c
index c39ace8..0cb7213 100644 (file)
@@ -29,7 +29,7 @@
  * <refsect2>
  * <title>Examples</title>
  * |[
- * gst-launch -v filesrc location=test.mkv ! matroskademux name=demux ! "video/x-h264" ! queue2 ! decodebin2 ! subtitleoverlay name=overlay ! ffmpegcolorspace ! autovideosink  demux. ! "video/x-dvd-subpicture" ! queue2 ! overlay.
+ * gst-launch -v filesrc location=test.mkv ! matroskademux name=demux ! "video/x-h264" ! queue2 ! decodebin ! subtitleoverlay name=overlay ! videoconvert ! autovideosink  demux. ! "video/x-dvd-subpicture" ! queue2 ! overlay.
  * ]| This will play back the given Matroska file with h264 video and subpicture subtitles.
  * </refsect2>
  */
@@ -79,11 +79,8 @@ enum
   PROP_SUBTITLE_ENCODING
 };
 
-GST_BOILERPLATE (GstSubtitleOverlay, gst_subtitle_overlay, GstBin,
-    GST_TYPE_BIN);
-
-static void _pad_blocked_cb (GstPad * pad, gboolean blocked,
-    gpointer user_data);
+#define gst_subtitle_overlay_parent_class parent_class
+G_DEFINE_TYPE (GstSubtitleOverlay, gst_subtitle_overlay, GST_TYPE_BIN);
 
 static GQuark _subtitle_overlay_event_marker_id = 0;
 
@@ -91,11 +88,10 @@ static void
 do_async_start (GstSubtitleOverlay * self)
 {
   if (!self->do_async) {
-    GstMessage *msg =
-        gst_message_new_async_start (GST_OBJECT_CAST (self), FALSE);
+    GstMessage *msg = gst_message_new_async_start (GST_OBJECT_CAST (self));
 
     GST_DEBUG_OBJECT (self, "Posting async-start");
-    parent_class->handle_message (GST_BIN_CAST (self), msg);
+    GST_BIN_CLASS (parent_class)->handle_message (GST_BIN_CAST (self), msg);
     self->do_async = TRUE;
   }
 }
@@ -104,14 +100,65 @@ static void
 do_async_done (GstSubtitleOverlay * self)
 {
   if (self->do_async) {
-    GstMessage *msg = gst_message_new_async_done (GST_OBJECT_CAST (self));
+    GstMessage *msg =
+        gst_message_new_async_done (GST_OBJECT_CAST (self), FALSE);
 
     GST_DEBUG_OBJECT (self, "Posting async-done");
-    parent_class->handle_message (GST_BIN_CAST (self), msg);
+    GST_BIN_CLASS (parent_class)->handle_message (GST_BIN_CAST (self), msg);
     self->do_async = FALSE;
   }
 }
 
+static GstProbeReturn
+_pad_blocked_cb (GstPad * pad, GstProbeType type, gpointer type_data,
+    gpointer user_data);
+
+static void
+block_video (GstSubtitleOverlay * self)
+{
+  if (self->video_block_id != 0)
+    return;
+
+  if (self->video_block_pad) {
+    self->video_block_id =
+        gst_pad_add_probe (self->video_block_pad, GST_PROBE_TYPE_BLOCK,
+        _pad_blocked_cb, self, NULL);
+  }
+}
+
+static void
+unblock_video (GstSubtitleOverlay * self)
+{
+  if (self->video_block_id) {
+    gst_pad_remove_probe (self->video_block_pad, self->video_block_id);
+    self->video_sink_blocked = FALSE;
+    self->video_block_id = 0;
+  }
+}
+
+static void
+block_subtitle (GstSubtitleOverlay * self)
+{
+  if (self->subtitle_block_id != 0)
+    return;
+
+  if (self->subtitle_block_pad) {
+    self->subtitle_block_id =
+        gst_pad_add_probe (self->subtitle_block_pad, GST_PROBE_TYPE_BLOCK,
+        _pad_blocked_cb, self, NULL);
+  }
+}
+
+static void
+unblock_subtitle (GstSubtitleOverlay * self)
+{
+  if (self->subtitle_block_id) {
+    gst_pad_remove_probe (self->subtitle_block_pad, self->subtitle_block_id);
+    self->subtitle_sink_blocked = FALSE;
+    self->subtitle_block_id = 0;
+  }
+}
+
 static void
 gst_subtitle_overlay_finalize (GObject * object)
 {
@@ -185,7 +232,7 @@ _is_raw_video (GstStructure * s)
 
   name = gst_structure_get_name (s);
 
-  if (g_str_has_prefix (name, "video/x-raw-"))
+  if (g_str_has_prefix (name, "video/x-raw"))
     return TRUE;
   return FALSE;
 }
@@ -193,19 +240,8 @@ _is_raw_video (GstStructure * s)
 static gboolean
 _is_raw_video_pad (GstPad * pad)
 {
-  GstPad *peer = gst_pad_get_peer (pad);
-  GstCaps *caps;
-  gboolean raw = TRUE;
-
-  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);
-  }
+  GstCaps *caps = gst_pad_get_current_caps (pad);
+  gboolean raw;
 
   raw = _is_raw_video (gst_caps_get_structure (caps, 0));
 
@@ -531,26 +567,16 @@ _remove_element (GstSubtitleOverlay * self, GstElement ** element)
 }
 
 static void
-_generate_update_newsegment_event (GstSegment * segment, GstEvent ** event1,
-    GstEvent ** event2)
+_generate_update_segment_event (GstSegment * segment, GstEvent ** event1)
 {
   GstEvent *event;
+  GstStructure *structure;
 
-  *event1 = NULL;
-  *event2 = NULL;
-
-  event = gst_event_new_new_segment_full (FALSE, segment->rate,
-      segment->applied_rate, segment->format, 0, segment->accum, 0);
-  gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
+  event = gst_event_new_segment (segment);
+  structure = gst_event_writable_structure (event);
+  gst_structure_id_set (structure, _subtitle_overlay_event_marker_id,
       G_TYPE_BOOLEAN, TRUE, NULL);
   *event1 = event;
-
-  event = gst_event_new_new_segment_full (FALSE, segment->rate,
-      segment->applied_rate, segment->format,
-      segment->start, segment->stop, segment->time);
-  gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
-      G_TYPE_BOOLEAN, TRUE, NULL);
-  *event2 = event;
 }
 
 static gboolean
@@ -614,17 +640,12 @@ _setup_passthrough (GstSubtitleOverlay * self)
   /* Send segment to the identity. This is dropped because identity
    * is not linked downstream yet */
   if (self->video_segment.format != GST_FORMAT_UNDEFINED) {
-    GstEvent *event1, *event2;
+    GstEvent *event1;
 
-    _generate_update_newsegment_event (&self->video_segment, &event1, &event2);
-    GST_DEBUG_OBJECT (self,
-        "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
-        event1->structure);
+    _generate_update_segment_event (&self->video_segment, &event1);
     GST_DEBUG_OBJECT (self,
-        "Pushing video update newsegment event: %" GST_PTR_FORMAT,
-        event2->structure);
+        "Pushing video segment event: %" GST_PTR_FORMAT, event1);
     gst_pad_send_event (sink, event1);
-    gst_pad_send_event (sink, event2);
   }
 
   /* Link sink ghostpads to identity */
@@ -641,12 +662,8 @@ _setup_passthrough (GstSubtitleOverlay * self)
 
 out:
   /* Unblock pads */
-  gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
-      _pad_blocked_cb, self, NULL);
-
-  if (self->subtitle_sink_blocked)
-    gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
-        _pad_blocked_cb, self, NULL);
+  unblock_video (self);
+  unblock_subtitle (self);
 
   return TRUE;
 }
@@ -717,25 +734,21 @@ _has_font_desc_property (GstElement * element)
   return (pspec && pspec->value_type == G_TYPE_STRING);
 }
 
-static void
-_pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
+static GstProbeReturn
+_pad_blocked_cb (GstPad * pad, GstProbeType type, gpointer type_data,
+    gpointer user_data)
 {
   GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY_CAST (user_data);
   GstCaps *subcaps;
   GList *l, *factories = NULL;
 
-  GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked);
+  GST_DEBUG_OBJECT (pad, "Pad blocked");
 
   GST_SUBTITLE_OVERLAY_LOCK (self);
   if (pad == self->video_block_pad)
-    self->video_sink_blocked = blocked;
+    self->video_sink_blocked = TRUE;
   else if (pad == self->subtitle_block_pad)
-    self->subtitle_sink_blocked = blocked;
-
-  if (!blocked) {
-    GST_SUBTITLE_OVERLAY_UNLOCK (self);
-    return;
-  }
+    self->subtitle_sink_blocked = TRUE;
 
   /* Now either both or the video sink are blocked */
 
@@ -746,9 +759,9 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 
     peer = gst_pad_get_peer (self->subtitle_sinkpad);
     if (peer) {
-      subcaps = gst_pad_get_negotiated_caps (peer);
+      subcaps = gst_pad_get_current_caps (peer);
       if (!subcaps) {
-        subcaps = gst_pad_get_caps_reffed (peer);
+        subcaps = gst_pad_get_caps (peer, NULL);
         if (!gst_caps_is_fixed (subcaps)) {
           gst_caps_unref (subcaps);
           subcaps = NULL;
@@ -788,12 +801,8 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
       gst_object_unref (target);
 
       /* Unblock pads */
-      gst_pad_set_blocked_async_full (self->video_block_pad, FALSE,
-          _pad_blocked_cb, self, NULL);
-
-      if (self->subtitle_sink_blocked)
-        gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE,
-            _pad_blocked_cb, self, NULL);
+      unblock_video (self);
+      unblock_subtitle (self);
       goto out;
     } else if (target) {
       gst_object_unref (target);
@@ -802,8 +811,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 
   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, self, NULL);
+    block_video (self);
     goto out;
   }
 
@@ -882,23 +890,26 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
       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);
+        video_caps = gst_pad_get_current_caps (video_peer);
         if (!video_caps) {
-          video_caps = gst_pad_get_caps_reffed (video_peer);
+          video_caps = gst_pad_get_caps (video_peer, NULL);
           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) {
+          GstVideoInfo info;
+
+          if (gst_video_info_from_caps (&info, video_caps)) {
+            if (self->fps_n != info.fps_n || self->fps_d != info.fps_d) {
+              GST_DEBUG_OBJECT (self, "New video fps: %d/%d", info.fps_n,
+                  info.fps_d);
+              self->fps_n = info.fps_n;
+              self->fps_d = info.fps_d;
+            }
           }
         }
 
@@ -1021,7 +1032,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
       /* 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;
+        GstEvent *event1;
 
         sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
         if (G_UNLIKELY (!sink)) {
@@ -1029,22 +1040,16 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
           continue;
         }
 
-        _generate_update_newsegment_event (&self->video_segment, &event1,
-            &event2);
-        GST_DEBUG_OBJECT (self,
-            "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
-            event1->structure);
+        _generate_update_segment_event (&self->video_segment, &event1);
         GST_DEBUG_OBJECT (self,
-            "Pushing video update newsegment event: %" GST_PTR_FORMAT,
-            event2->structure);
+            "Pushing video segment event: %" GST_PTR_FORMAT, event1);
         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;
+        GstEvent *event1;
 
         sink = gst_element_get_static_pad (element, "sink");
         if (G_UNLIKELY (!sink)) {
@@ -1052,16 +1057,10 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
           continue;
         }
 
-        _generate_update_newsegment_event (&self->subtitle_segment, &event1,
-            &event2);
+        _generate_update_segment_event (&self->subtitle_segment, &event1);
         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);
+            "Pushing subtitle segment event: %" GST_PTR_FORMAT, event1);
         gst_pad_send_event (sink, event1);
-        gst_pad_send_event (sink, event2);
 
         gst_object_unref (sink);
       }
@@ -1200,9 +1199,9 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
 
         video_peer = gst_pad_get_peer (self->video_sinkpad);
         if (video_peer) {
-          video_caps = gst_pad_get_negotiated_caps (video_peer);
+          video_caps = gst_pad_get_current_caps (video_peer);
           if (!video_caps) {
-            video_caps = gst_pad_get_caps_reffed (video_peer);
+            video_caps = gst_pad_get_caps (video_peer, NULL);
           }
           gst_object_unref (video_peer);
         }
@@ -1212,7 +1211,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
           GST_WARNING_OBJECT (self, "Can't get video sink from renderer");
           continue;
         }
-        allowed_caps = gst_pad_get_caps_reffed (sink);
+        allowed_caps = gst_pad_get_caps (sink, NULL);
         gst_object_unref (sink);
 
         if (allowed_caps && video_caps)
@@ -1248,7 +1247,7 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
       /* 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;
+        GstEvent *event1;
 
         sink = gst_element_get_static_pad (self->pre_colorspace, "sink");
         if (G_UNLIKELY (!sink)) {
@@ -1256,21 +1255,15 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
           continue;
         }
 
-        _generate_update_newsegment_event (&self->video_segment, &event1,
-            &event2);
-        GST_DEBUG_OBJECT (self,
-            "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT,
-            event1->structure);
+        _generate_update_segment_event (&self->video_segment, &event1);
         GST_DEBUG_OBJECT (self,
-            "Pushing video update newsegment event: %" GST_PTR_FORMAT,
-            event2->structure);
+            "Pushing video segment event: %" GST_PTR_FORMAT, event1);
         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;
+        GstEvent *event1;
 
         sink = _get_sub_pad (element);
         if (G_UNLIKELY (!sink)) {
@@ -1278,16 +1271,10 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
           continue;
         }
 
-        _generate_update_newsegment_event (&self->subtitle_segment, &event1,
-            &event2);
+        _generate_update_segment_event (&self->subtitle_segment, &event1);
         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);
+            "Pushing subtitle segment event: %" GST_PTR_FORMAT, event1);
         gst_pad_send_event (sink, event1);
-        gst_pad_send_event (sink, event2);
         gst_object_unref (sink);
       }
 
@@ -1341,10 +1328,8 @@ _pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
     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);
+    unblock_video (self);
+    unblock_subtitle (self);
     do_async_done (self);
   }
 
@@ -1352,6 +1337,8 @@ out:
   if (factories)
     gst_plugin_feature_list_free (factories);
   GST_SUBTITLE_OVERLAY_UNLOCK (self);
+
+  return GST_PROBE_OK;
 }
 
 static GstStateChangeReturn
@@ -1373,10 +1360,8 @@ gst_subtitle_overlay_change_state (GstElement * element,
 
       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, self, NULL);
-      gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
-          _pad_blocked_cb, self, NULL);
+      block_video (self);
+      block_subtitle (self);
       GST_SUBTITLE_OVERLAY_UNLOCK (self);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
@@ -1425,9 +1410,7 @@ gst_subtitle_overlay_change_state (GstElement * element,
       do_async_done (self);
 
       break;
-    case GST_STATE_CHANGE_READY_TO_NULL:{
-      GstPad *pad;
-
+    case GST_STATE_CHANGE_READY_TO_NULL:
       GST_DEBUG_OBJECT (self, "State change READY->NULL");
 
       GST_SUBTITLE_OVERLAY_LOCK (self);
@@ -1440,17 +1423,8 @@ gst_subtitle_overlay_change_state (GstElement * element,
           NULL);
 
       /* Unblock pads */
-      if (self->video_block_pad) {
-        pad = self->video_block_pad;
-        gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb,
-            self, NULL);
-      }
-
-      if (self->subtitle_block_pad) {
-        pad = self->subtitle_block_pad;
-        gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb,
-            self, NULL);
-      }
+      unblock_video (self);
+      unblock_subtitle (self);
 
       /* Remove elements */
       self->silent_property = NULL;
@@ -1463,7 +1437,6 @@ gst_subtitle_overlay_change_state (GstElement * element,
       GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
       break;
-    }
     default:
       break;
   }
@@ -1508,11 +1481,8 @@ gst_subtitle_overlay_handle_message (GstBin * bin, GstMessage * message)
       GST_SUBTITLE_OVERLAY_LOCK (self);
       self->subtitle_error = TRUE;
 
-      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);
+      block_subtitle (self);
+      block_video (self);
       GST_SUBTITLE_OVERLAY_UNLOCK (self);
     }
   }
@@ -1567,11 +1537,8 @@ gst_subtitle_overlay_set_property (GObject * object, guint prop_id,
         else if (self->renderer)
           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, self, NULL);
-
-        gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
-            _pad_blocked_cb, self, NULL);
+        block_subtitle (self);
+        block_video (self);
       }
       GST_SUBTITLE_OVERLAY_UNLOCK (self);
       break;
@@ -1603,25 +1570,6 @@ gst_subtitle_overlay_set_property (GObject * object, guint prop_id,
 }
 
 static void
-gst_subtitle_overlay_base_init (gpointer g_class)
-{
-  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_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_set_details_simple (gstelement_class, "Subtitle Overlay",
-      "Video/Overlay/Subtitle",
-      "Overlays a video stream with subtitles",
-      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-}
-
-static void
 gst_subtitle_overlay_class_init (GstSubtitleOverlayClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
@@ -1653,6 +1601,19 @@ gst_subtitle_overlay_class_init (GstSubtitleOverlayClass * klass)
           "ISO-8859-15 will be assumed.", NULL,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&srctemplate));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&video_sinktemplate));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&subtitle_sinktemplate));
+
+  gst_element_class_set_details_simple (element_class, "Subtitle Overlay",
+      "Video/Overlay/Subtitle",
+      "Overlays a video stream with subtitles",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
   element_class->change_state =
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_change_state);
 
@@ -1711,7 +1672,7 @@ 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);
+        event);
     gst_event_unref (event);
     event = NULL;
     ret = TRUE;
@@ -1731,50 +1692,47 @@ out:
 }
 
 static gboolean
-gst_subtitle_overlay_video_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_subtitle_overlay_video_sink_setcaps (GstSubtitleOverlay * self,
+    GstCaps * caps)
 {
-  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
   GstPad *target;
   gboolean ret = TRUE;
-  gint fps_n, fps_d;
+  GstVideoInfo info;
 
-  GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps);
+  GST_DEBUG_OBJECT (self, "Setting caps: %" GST_PTR_FORMAT, caps);
+
+  if (!gst_video_info_from_caps (&info, caps)) {
+    GST_ERROR_OBJECT (self, "Failed to parse caps");
+    ret = FALSE;
+    GST_SUBTITLE_OVERLAY_UNLOCK (self);
+    goto out;
+  }
 
   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);
-  }
+    GST_DEBUG_OBJECT (target, "Target did not accept caps -- reconfiguring");
 
-  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;
+    block_subtitle (self);
+    block_video (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;
-    self->fps_d = fps_d;
+  GST_SUBTITLE_OVERLAY_LOCK (self);
+  if (self->fps_n != info.fps_n || self->fps_d != info.fps_d) {
+    GST_DEBUG_OBJECT (self, "New video fps: %d/%d", info.fps_n, info.fps_d);
+    self->fps_n = info.fps_n;
+    self->fps_d = info.fps_d;
     gst_subtitle_overlay_set_fps (self);
   }
   GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
-  ret = gst_ghost_pad_setcaps_default (pad, caps);
-
-out:
   if (target)
     gst_object_unref (target);
-  gst_object_unref (self);
+
+out:
+
   return ret;
 }
 
@@ -1784,45 +1742,53 @@ gst_subtitle_overlay_video_sink_event (GstPad * pad, GstEvent * event)
   GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
   gboolean ret;
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
-    GST_DEBUG_OBJECT (pad,
-        "Resetting video segment because of flush-stop event");
-    gst_segment_init (&self->video_segment, GST_FORMAT_UNDEFINED);
-    self->fps_n = self->fps_d = 0;
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_STOP:
+    {
+      GST_DEBUG_OBJECT (pad,
+          "Resetting video segment because of flush-stop event");
+      gst_segment_init (&self->video_segment, GST_FORMAT_UNDEFINED);
+      self->fps_n = self->fps_d = 0;
+      break;
+    }
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      ret = gst_subtitle_overlay_video_sink_setcaps (self, caps);
+      if (!ret)
+        goto done;
+      break;
+    }
+    default:
+      break;
   }
 
   ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
-    gboolean update;
-    gdouble rate, applied_rate;
-    GstFormat format;
-    gint64 start, stop, position;
-
-    GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT,
-        event->structure);
-    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-        &format, &start, &stop, &position);
-
-    if (format != GST_FORMAT_TIME) {
-      GST_ERROR_OBJECT (pad, "Newsegment event in non-time format: %s",
-          gst_format_get_name (format));
-      gst_event_unref (event);
-      gst_object_unref (self);
-      return FALSE;
-    }
+  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+    GST_DEBUG_OBJECT (pad, "segment event: %" GST_PTR_FORMAT, event);
+    gst_event_copy_segment (event, &self->video_segment);
 
-    GST_DEBUG_OBJECT (pad, "Old video segment: %" GST_SEGMENT_FORMAT,
-        &self->video_segment);
-    gst_segment_set_newsegment_full (&self->video_segment, update, rate,
-        applied_rate, format, start, stop, position);
-    GST_DEBUG_OBJECT (pad, "New video segment: %" GST_SEGMENT_FORMAT,
-        &self->video_segment);
+    if (self->video_segment.format != GST_FORMAT_TIME)
+      goto invalid_format;
   }
 
+done:
   gst_event_unref (event);
   gst_object_unref (self);
+
   return ret;
+
+  /* ERRORS */
+invalid_format:
+  {
+    GST_ERROR_OBJECT (pad, "Newsegment event in non-time format: %s",
+        gst_format_get_name (self->video_segment.format));
+    ret = FALSE;
+    goto done;
+  }
 }
 
 static GstFlowReturn
@@ -1838,11 +1804,8 @@ gst_subtitle_overlay_video_sink_chain (GstPad * pad, GstBuffer * buffer)
         gst_flow_get_name (ret));
     GST_SUBTITLE_OVERLAY_LOCK (self);
     self->subtitle_error = TRUE;
-    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);
+    block_subtitle (self);
+    block_video (self);
     GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
     return GST_FLOW_OK;
@@ -1867,11 +1830,8 @@ gst_subtitle_overlay_subtitle_sink_chain (GstPad * pad, GstBuffer * buffer)
           gst_flow_get_name (ret));
       GST_SUBTITLE_OVERLAY_LOCK (self);
       self->subtitle_error = TRUE;
-      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);
+      block_subtitle (self);
+      block_video (self);
       GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
       return GST_FLOW_OK;
@@ -1882,7 +1842,7 @@ gst_subtitle_overlay_subtitle_sink_chain (GstPad * pad, GstBuffer * buffer)
 }
 
 static GstCaps *
-gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad)
+gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad, GstCaps * filter)
 {
   GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
   GstCaps *ret;
@@ -1890,6 +1850,10 @@ gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad)
   g_mutex_lock (self->factories_lock);
   if (G_UNLIKELY (!gst_subtitle_overlay_update_factory_list (self)))
     ret = GST_CAPS_NONE;
+  else if (filter)
+    ret =
+        gst_caps_intersect_full (filter, self->factory_caps,
+        GST_CAPS_INTERSECT_FIRST);
   else
     ret = gst_caps_ref (self->factory_caps);
   g_mutex_unlock (self->factories_lock);
@@ -1904,7 +1868,7 @@ gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad)
 static gboolean
 gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps)
 {
-  GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad);
+  GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad, NULL);
   gboolean ret = gst_caps_is_subset (caps, othercaps);
 
   gst_caps_unref (othercaps);
@@ -1913,13 +1877,13 @@ gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps)
 }
 
 static gboolean
-gst_subtitle_overlay_subtitle_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_subtitle_overlay_subtitle_sink_setcaps (GstSubtitleOverlay * self,
+    GstCaps * caps)
 {
-  GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
   gboolean ret = TRUE;
   GstPad *target = NULL;;
 
-  GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps);
+  GST_DEBUG_OBJECT (self, "Setting caps: %" GST_PTR_FORMAT, caps);
 
   target =
       gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad));
@@ -1928,27 +1892,22 @@ gst_subtitle_overlay_subtitle_sink_setcaps (GstPad * pad, GstCaps * caps)
   gst_caps_replace (&self->subcaps, caps);
 
   if (target && gst_pad_accept_caps (target, caps)) {
-    GST_DEBUG_OBJECT (pad, "Target accepts caps");
-    ret = gst_ghost_pad_setcaps_default (pad, caps);
+    GST_DEBUG_OBJECT (self, "Target accepts caps");
     GST_SUBTITLE_OVERLAY_UNLOCK (self);
     goto out;
   }
 
-  GST_DEBUG_OBJECT (pad, "Target did not accept caps");
+  GST_DEBUG_OBJECT (self, "Target did not accept caps");
 
   self->subtitle_error = FALSE;
-
-  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);
+  block_subtitle (self);
+  block_video (self);
   GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
 out:
   if (target)
     gst_object_unref (target);
-  gst_object_unref (self);
+
   return ret;
 }
 
@@ -1961,9 +1920,9 @@ gst_subtitle_overlay_subtitle_sink_link (GstPad * pad, GstPad * peer)
 
   GST_DEBUG_OBJECT (pad, "Linking pad to peer %" GST_PTR_FORMAT, peer);
 
-  caps = gst_pad_get_negotiated_caps (peer);
+  caps = gst_pad_get_current_caps (peer);
   if (!caps) {
-    caps = gst_pad_get_caps_reffed (peer);
+    caps = gst_pad_get_caps (peer, NULL);
     if (!gst_caps_is_fixed (caps)) {
       gst_caps_unref (caps);
       caps = NULL;
@@ -1977,11 +1936,8 @@ gst_subtitle_overlay_subtitle_sink_link (GstPad * pad, GstPad * peer)
 
     self->subtitle_error = FALSE;
 
-    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);
+    block_subtitle (self);
+    block_video (self);
     GST_SUBTITLE_OVERLAY_UNLOCK (self);
     gst_caps_unref (caps);
   }
@@ -2010,13 +1966,8 @@ gst_subtitle_overlay_subtitle_sink_unlink (GstPad * 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, self, NULL);
-
-  if (self->video_block_pad)
-    gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
-        _pad_blocked_cb, self, NULL);
+  block_subtitle (self);
+  block_video (self);
   GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
   gst_object_unref (self);
@@ -2027,90 +1978,63 @@ gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstEvent * event)
 {
   GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad));
   gboolean ret;
-  GstFormat format;
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
-      event->structure
-      && strcmp (gst_structure_get_name (event->structure),
-          "subtitleoverlay-flush-subtitle") == 0) {
+      gst_event_has_name (event, "subtitleoverlay-flush-subtitle")) {
     GST_DEBUG_OBJECT (pad, "Custom subtitle flush event");
     GST_SUBTITLE_OVERLAY_LOCK (self);
     self->subtitle_flush = TRUE;
     self->subtitle_error = FALSE;
-    if (self->subtitle_block_pad)
-      gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
-          _pad_blocked_cb, self, NULL);
-    if (self->video_block_pad)
-      gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
-          _pad_blocked_cb, self, NULL);
+    block_subtitle (self);
+    block_video (self);
     GST_SUBTITLE_OVERLAY_UNLOCK (self);
 
     gst_event_unref (event);
     event = NULL;
     ret = TRUE;
     goto out;
-  } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
-    gst_event_parse_new_segment_full (event, NULL, NULL, NULL,
-        &format, NULL, NULL, NULL);
-    if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED &&
-        self->subtitle_segment.format != format) {
-      GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s",
-          gst_format_get_name (self->subtitle_segment.format),
-          gst_format_get_name (format));
-      gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED);
-    }
   }
 
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      ret = gst_subtitle_overlay_subtitle_sink_setcaps (self, caps);
+      if (!ret)
+        goto out;
+      break;
+    }
     case GST_EVENT_FLUSH_STOP:
       GST_DEBUG_OBJECT (pad,
           "Resetting subtitle segment because of flush-stop");
       gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED);
       /* fall through */
     case GST_EVENT_FLUSH_START:
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     case GST_EVENT_EOS:
+    {
+      GstStructure *structure;
+
       /* Add our event marker to make sure no events from here go ever outside
        * the element, they're only interesting for our internal elements */
-      event =
-          GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST
-              (event)));
-      if (!event->structure) {
-        event->structure =
-            gst_structure_id_empty_new (_subtitle_overlay_event_marker_id);
-        gst_structure_set_parent_refcount (event->structure,
-            &event->mini_object.refcount);
-      }
-      gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
+      event = GST_EVENT_CAST (gst_event_make_writable (event));
+      structure = gst_event_writable_structure (event);
+
+      gst_structure_id_set (structure, _subtitle_overlay_event_marker_id,
           G_TYPE_BOOLEAN, TRUE, NULL);
       break;
+    }
     default:
       break;
   }
 
   ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
-    gboolean update;
-    gdouble rate, applied_rate;
-    gint64 start, stop, position;
-
-    GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT,
-        event->structure);
-    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-        &format, &start, &stop, &position);
-
-    GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT,
-        &self->subtitle_segment);
-    if (self->subtitle_segment.format != format) {
-      GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s",
-          gst_format_get_name (self->subtitle_segment.format),
-          gst_format_get_name (format));
-      gst_segment_init (&self->subtitle_segment, format);
-    }
-
-    gst_segment_set_newsegment_full (&self->subtitle_segment, update, rate,
-        applied_rate, format, start, stop, position);
+  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+    GST_DEBUG_OBJECT (pad, "segment event: %" GST_PTR_FORMAT, event);
+    gst_event_copy_segment (event, &self->subtitle_segment);
     GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT,
         &self->subtitle_segment);
   }
@@ -2122,8 +2046,7 @@ out:
 }
 
 static void
-gst_subtitle_overlay_init (GstSubtitleOverlay * self,
-    GstSubtitleOverlayClass * klass)
+gst_subtitle_overlay_init (GstSubtitleOverlay * self)
 {
   GstPadTemplate *templ;
   GstPad *proxypad = NULL;
@@ -2151,8 +2074,6 @@ gst_subtitle_overlay_init (GstSubtitleOverlay * self,
   gst_object_unref (templ);
   gst_pad_set_event_function (self->video_sinkpad,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_event));
-  gst_pad_set_setcaps_function (self->video_sinkpad,
-      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_setcaps));
   gst_pad_set_chain_function (self->video_sinkpad,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_chain));
 
@@ -2173,15 +2094,12 @@ gst_subtitle_overlay_init (GstSubtitleOverlay * self,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_unlink));
   gst_pad_set_event_function (self->subtitle_sinkpad,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_event));
-  gst_pad_set_setcaps_function (self->subtitle_sinkpad,
-      GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_setcaps));
   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_getcaps));
   gst_pad_set_acceptcaps_function (self->subtitle_sinkpad,
       GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_acceptcaps));
-  gst_pad_set_bufferalloc_function (self->subtitle_sinkpad, NULL);
 
   proxypad =
       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD