ges: Fix interlaced stream playback
authorThibault Saunier <tsaunier@igalia.com>
Fri, 17 Apr 2020 16:35:26 +0000 (12:35 -0400)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 17 Apr 2020 17:24:45 +0000 (13:24 -0400)
Negotiation was failling as `videoflip` was not allowing not
progressive interlacing.

Also avoid adding a deinterlace element when it is useless.

ges/ges-video-source.c
ges/ges-video-uri-source.c

index b306367..72ccd80 100644 (file)
@@ -87,24 +87,14 @@ _set_priority (GESTimelineElement * element, guint32 priority)
   return res;
 }
 
-static void
-post_missing_element_message (GstElement * element, const gchar * name)
-{
-  GstMessage *msg;
-
-  msg = gst_missing_element_message_new (element, name);
-  gst_element_post_message (element, msg);
-}
-
 static gboolean
 ges_video_source_create_filters (GESVideoSource * self, GPtrArray * elements,
     gboolean needs_converters)
 {
   GESTrackElement *trksrc = GES_TRACK_ELEMENT (self);
-  GstElement *positioner, *videoflip, *capsfilter, *deinterlace;
-  const gchar *positioner_props[] =
-      { "alpha", "posx", "posy", "width", "height", NULL };
-  const gchar *deinterlace_props[] = { "mode", "fields", "tff", NULL };
+  GstElement *positioner, *videoflip, *capsfilter;
+  const gchar *positioner_props[]
+  = { "alpha", "posx", "posy", "width", "height", NULL };
   const gchar *videoflip_props[] = { "video-direction", NULL };
 
   g_ptr_array_add (elements, gst_element_factory_make ("queue", NULL));
@@ -116,6 +106,9 @@ ges_video_source_create_filters (GESVideoSource * self, GPtrArray * elements,
       G_MAXUINT - GES_TIMELINE_ELEMENT_PRIORITY (self), NULL);
   g_ptr_array_add (elements, positioner);
 
+  if (needs_converters)
+    g_ptr_array_add (elements, gst_element_factory_make ("videoconvert", NULL));
+
   /* If there's image-orientation tag, make sure the image is correctly oriented
    * before we scale it. */
   videoflip = gst_element_factory_make ("videoflip", "track-element-videoflip");
@@ -130,6 +123,7 @@ ges_video_source_create_filters (GESVideoSource * self, GPtrArray * elements,
   }
   g_ptr_array_add (elements, gst_element_factory_make ("videorate",
           "track-element-videorate"));
+
   capsfilter =
       gst_element_factory_make ("capsfilter", "track-element-capsfilter");
   g_ptr_array_add (elements, capsfilter);
@@ -142,21 +136,6 @@ ges_video_source_create_filters (GESVideoSource * self, GPtrArray * elements,
   ges_track_element_add_children_props (trksrc, videoflip, NULL, NULL,
       videoflip_props);
 
-  deinterlace = gst_element_factory_make ("deinterlace", "deinterlace");
-  if (deinterlace == NULL) {
-    post_missing_element_message (ges_track_element_get_nleobject (trksrc),
-        "deinterlace");
-
-    GST_ELEMENT_WARNING (ges_track_element_get_nleobject (trksrc), CORE,
-        MISSING_PLUGIN,
-        ("Missing element '%s' - check your GStreamer installation.",
-            "deinterlace"), ("deinterlacing won't work"));
-  } else {
-    g_ptr_array_add (elements, deinterlace);
-    ges_track_element_add_children_props (trksrc, deinterlace, NULL, NULL,
-        deinterlace_props);
-  }
-
   self->priv->positioner = GST_FRAME_POSITIONNER (positioner);
   self->priv->positioner->scale_in_compositor =
       !GES_VIDEO_SOURCE_GET_CLASS (self)->ABI.abi.disable_scale_in_compositor;
index dea68f9..0595cea 100644 (file)
@@ -223,6 +223,14 @@ _find_positioner (GstElement * a, GstElement * b)
       "framepositioner");
 }
 
+static void
+post_missing_element_message (GstElement * element, const gchar * name)
+{
+  GstMessage *msg;
+
+  msg = gst_missing_element_message_new (element, name);
+  gst_element_post_message (element, msg);
+}
 
 /* GObject VMethods */
 static gboolean
@@ -230,12 +238,39 @@ ges_video_uri_source_create_filters (GESVideoSource * source,
     GPtrArray * elements, gboolean needs_converters)
 {
   GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (source));
+  GstDiscovererVideoInfo *info =
+      GST_DISCOVERER_VIDEO_INFO (ges_uri_source_asset_get_stream_info
+      (GES_URI_SOURCE_ASSET (asset)));
 
   g_assert (GES_IS_URI_SOURCE_ASSET (asset));
   if (!GES_VIDEO_SOURCE_CLASS (ges_video_uri_source_parent_class)
       ->ABI.abi.create_filters (source, elements, needs_converters))
     return FALSE;
 
+  if (gst_discoverer_video_info_is_interlaced (info)) {
+    const gchar *deinterlace_props[] = { "mode", "fields", "tff", NULL };
+    GstElement *deinterlace =
+        gst_element_factory_make ("deinterlace", "deinterlace");
+
+    if (deinterlace == NULL) {
+      post_missing_element_message (ges_track_element_get_nleobject
+          (GES_TRACK_ELEMENT (source)), "deinterlace");
+
+      GST_ELEMENT_WARNING (ges_track_element_get_nleobject (GES_TRACK_ELEMENT
+              (source)), CORE, MISSING_PLUGIN,
+          ("Missing element '%s' - check your GStreamer installation.",
+              "deinterlace"), ("deinterlacing won't work"));
+    } else {
+      /* Right after the queue */
+      g_ptr_array_insert (elements, 1, gst_element_factory_make ("videoconvert",
+              NULL));
+      g_ptr_array_insert (elements, 2, deinterlace);
+      ges_track_element_add_children_props (GES_TRACK_ELEMENT (source),
+          deinterlace, NULL, NULL, deinterlace_props);
+    }
+
+  }
+
   if (ges_uri_source_asset_is_image (GES_URI_SOURCE_ASSET (asset))) {
     guint i;