validate: media-check: Add a way to skip pluggin parsers
authorThibault Saunier <tsaunier@igalia.com>
Fri, 25 May 2018 13:35:10 +0000 (15:35 +0200)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 15 Jun 2018 16:05:14 +0000 (12:05 -0400)
This is useful when you want to check only the demuxer output.

- Keep the information in the media file so that we can launch media-check
  with the proper arguments in the launcher. Update it accordingly.
- Refactor compare_streams to simplify it, which in the end leads to
  reporting all the issues instead of exiting on the first one.

validate/gst/validate/gst-validate-enum-types.h.template
validate/gst/validate/media-descriptor-parser.c
validate/gst/validate/media-descriptor-writer.c
validate/gst/validate/media-descriptor-writer.h
validate/gst/validate/media-descriptor.c
validate/gst/validate/media-descriptor.h
validate/launcher/apps/gstvalidate.py
validate/launcher/baseclasses.py
validate/tools/gst-validate-media-check.c

index f28a284..08a80cb 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <glib-object.h>
 #include <gst/validate/validate.h>
+#include <gst/validate/media-descriptor-writer.h>
 
 G_BEGIN_DECLS
 /*** END file-header ***/
index ed2c1b5..70af7eb 100644 (file)
@@ -165,7 +165,7 @@ deserialize_framenode (const gchar ** names, const gchar ** values)
 #define IF_SET_UINT64_FIELD(name,fieldname) \
     if (g_strcmp0 (names[i], name) == 0) { \
       if (g_strcmp0 (values[i], "unknown") == 0)  \
-        framenode->fieldname = GST_VALIDATE_UKNOWN_UINT64; \
+        framenode->fieldname = GST_VALIDATE_UNKNOWN_UINT64; \
       else\
         framenode->fieldname = g_ascii_strtoull (values[i], NULL, 0); \
     }
@@ -184,7 +184,7 @@ deserialize_framenode (const gchar ** names, const gchar ** values)
       if (!g_ascii_strcasecmp (values[i], "true"))
         framenode->is_keyframe = TRUE;
       else if (!g_ascii_strcasecmp (values[i], "unknown"))
-        framenode->is_keyframe = GST_VALIDATE_UKNOWN_BOOL;
+        framenode->is_keyframe = GST_VALIDATE_UNKNOWN_BOOL;
       else
         framenode->is_keyframe = FALSE;
     }
index 4c93f31..8cd5b80 100644 (file)
@@ -35,6 +35,7 @@ G_DEFINE_TYPE (GstValidateMediaDescriptorWriter,
 #define STR_APPEND3(arg) STR_APPEND((arg), 6)
 #define STR_APPEND4(arg) STR_APPEND((arg), 8)
 
+#define FLAG_IS_SET(writer,flag)       ((writer->priv->flags & (flag)) == (flag))
 
 enum
 {
@@ -50,6 +51,7 @@ struct _GstValidateMediaDescriptorWriterPrivate
   GMainLoop *loop;
 
   GList *parsers;
+  GstValidateMediaDescriptorWriterFlags flags;
 };
 
 static void
@@ -127,9 +129,9 @@ serialize_filenode (GstValidateMediaDescriptorWriter * writer)
       * filenode = ((GstValidateMediaDescriptor *) writer)->filenode;
 
   tmpstr = g_markup_printf_escaped ("<file duration=\"%" G_GUINT64_FORMAT
-      "\" frame-detection=\"%i\" uri=\"%s\" seekable=\"%s\">\n",
-      filenode->duration, filenode->frame_detection, filenode->uri,
-      filenode->seekable ? "true" : "false");
+      "\" frame-detection=\"%i\" skip-parsers=\"%i\" uri=\"%s\" seekable=\"%s\">\n",
+      filenode->duration, filenode->frame_detection, filenode->skip_parsers,
+      filenode->uri, filenode->seekable ? "true" : "false");
 
   if (filenode->caps)
     caps_str = gst_caps_to_string (filenode->caps);
@@ -230,6 +232,33 @@ gst_validate_media_descriptor_writer_new (GstValidateRunner * runner,
   return writer;
 }
 
+static GstCaps *
+strip_caps_to_avoid_parsers (GstValidateMediaDescriptorWriter * writer,
+    GstCaps * caps)
+{
+  gint i;
+  GstStructure *structure, *new_struct;
+  GstCaps *stripped;
+
+  /* If parsers are wanted, use exactly the caps reported by the discoverer (which also
+   * plugs parsers). */
+  if (!FLAG_IS_SET (writer,
+          GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NO_PARSER))
+    return gst_caps_copy (caps);
+
+  /* Otherwise use the simplest version of those caps (with the names only),
+   * meaning that decodebin will never plug any parser */
+  stripped = gst_caps_new_empty ();
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    structure = gst_caps_get_structure (caps, i);
+    new_struct = gst_structure_new_empty (gst_structure_get_name (structure));
+
+    gst_caps_append_structure (stripped, new_struct);
+  }
+
+  return stripped;
+}
+
 static gboolean
     gst_validate_media_descriptor_writer_add_stream
     (GstValidateMediaDescriptorWriter * writer, GstDiscovererStreamInfo * info)
@@ -295,10 +324,10 @@ static gboolean
   }
 
   if (writer->priv->raw_caps == NULL)
-    writer->priv->raw_caps = gst_caps_copy (caps);
+    writer->priv->raw_caps = strip_caps_to_avoid_parsers (writer, caps);
   else {
     writer->priv->raw_caps = gst_caps_merge (writer->priv->raw_caps,
-        gst_caps_copy (caps));
+        strip_caps_to_avoid_parsers (writer, caps));
   }
   g_free (capsstr);
 
@@ -404,6 +433,10 @@ _get_parser (GstValidateMediaDescriptorWriter * writer, GstPad * pad)
   GstElementFactory *parserfact = NULL;
   GstCaps *format;
 
+  if (FLAG_IS_SET (writer,
+          GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NO_PARSER))
+    return NULL;
+
   format = gst_pad_get_current_caps (pad);
 
   GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format);
@@ -604,7 +637,8 @@ _run_frame_analysis (GstValidateMediaDescriptorWriter * writer,
 
 GstValidateMediaDescriptorWriter *
 gst_validate_media_descriptor_writer_new_discover (GstValidateRunner * runner,
-    const gchar * uri, gboolean full, gboolean handle_g_logs, GError ** err)
+    const gchar * uri, GstValidateMediaDescriptorWriterFlags flags,
+    GError ** err)
 {
   GList *tmp, *streams = NULL;
   GstDiscovererInfo *info = NULL;
@@ -670,7 +704,9 @@ gst_validate_media_descriptor_writer_new_discover (GstValidateRunner * runner,
         gst_discoverer_info_get_duration (info),
         gst_discoverer_info_get_seekable (info));
 
-    if (handle_g_logs)
+    writer->priv->flags = flags;
+    if (FLAG_IS_SET (writer,
+            GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_HANDLE_GLOGS))
       gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (writer));
 
     tags = gst_discoverer_info_get_tags (info);
@@ -704,7 +740,7 @@ gst_validate_media_descriptor_writer_new_discover (GstValidateRunner * runner,
   gst_discoverer_stream_info_list_free (streams);
 
 
-  if (full == TRUE)
+  if (FLAG_IS_SET (writer, GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_FULL))
     _run_frame_analysis (writer, runner, uri);
 
 out:
@@ -883,15 +919,20 @@ gst_validate_media_descriptor_writer_add_frame (GstValidateMediaDescriptorWriter
   GstMapInfo map;
   gchar *checksum;
   guint id;
+  GstSegment *segment;
   GstValidateMediaFrameNode *fnode;
-  GstSegment * segment;
+  GstValidateMediaFileNode *filenode;
 
   g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_WRITER (writer),
       FALSE);
   g_return_val_if_fail (((GstValidateMediaDescriptor *) writer)->filenode,
       FALSE);
 
-  ((GstValidateMediaDescriptor *) writer)->filenode->frame_detection = TRUE;
+  filenode = ((GstValidateMediaDescriptor *) writer)->filenode;
+  filenode->frame_detection = TRUE;
+  filenode->skip_parsers =
+      FLAG_IS_SET (writer,
+      GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NO_PARSER);
   GST_VALIDATE_MEDIA_DESCRIPTOR_LOCK (writer);
   streamnode =
       gst_validate_media_descriptor_find_stream_node_by_pad (
@@ -918,7 +959,7 @@ gst_validate_media_descriptor_writer_add_frame (GstValidateMediaDescriptorWriter
   fnode->dts = GST_BUFFER_DTS (buf);
 
   g_assert (streamnode->segments);
-  segment = &((GstValidateSegmentNode *)streamnode->segments->data)->segment;
+  segment = &((GstValidateSegmentNode *) streamnode->segments->data)->segment;
   fnode->running_time =
       gst_segment_to_running_time (segment, GST_FORMAT_TIME,
       GST_BUFFER_PTS (buf));
index 0c5712a..607d978 100644 (file)
@@ -56,11 +56,18 @@ typedef struct {
 
 } GstValidateMediaDescriptorWriterClass;
 
+typedef enum
+{
+    GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NONE         = 1 << 0,
+    GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NO_PARSER    = 1 << 1,
+    GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_FULL         = 1 << 2,
+    GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_HANDLE_GLOGS = 1 << 3,
+} GstValidateMediaDescriptorWriterFlags;
+
 GST_VALIDATE_API
 GstValidateMediaDescriptorWriter * gst_validate_media_descriptor_writer_new_discover (GstValidateRunner *runner,
                                                                      const gchar *uri,
-                                                                     gboolean full,
-                                                                     gboolean handle_g_logs,
+                                                                     GstValidateMediaDescriptorWriterFlags flags,
                                                                      GError **err);
 
 GST_VALIDATE_API
index 8d6e365..0cbae09 100644 (file)
@@ -465,13 +465,13 @@ compare_frames (GstValidateMediaDescriptor * ref,
     return FALSE; \
   }
 
-  CHECK_FRAME_FIELD (pts, "%" G_GUINT64_FORMAT, GST_VALIDATE_UKNOWN_UINT64);
-  CHECK_FRAME_FIELD (dts, "%" G_GUINT64_FORMAT, GST_VALIDATE_UKNOWN_UINT64);
+  CHECK_FRAME_FIELD (pts, "%" G_GUINT64_FORMAT, GST_VALIDATE_UNKNOWN_UINT64);
+  CHECK_FRAME_FIELD (dts, "%" G_GUINT64_FORMAT, GST_VALIDATE_UNKNOWN_UINT64);
   CHECK_FRAME_FIELD (duration, "%" G_GUINT64_FORMAT,
-      GST_VALIDATE_UKNOWN_UINT64);
+      GST_VALIDATE_UNKNOWN_UINT64);
   CHECK_FRAME_FIELD (running_time, "%" G_GUINT64_FORMAT,
-      GST_VALIDATE_UKNOWN_UINT64);
-  CHECK_FRAME_FIELD (is_keyframe, "%d", GST_VALIDATE_UKNOWN_BOOL);
+      GST_VALIDATE_UNKNOWN_UINT64);
+  CHECK_FRAME_FIELD (is_keyframe, "%d", GST_VALIDATE_UNKNOWN_BOOL);
 
   return TRUE;
 }
@@ -526,42 +526,39 @@ caps_cleanup_parsing_fields (GstCaps * caps)
   return res;
 }
 
-/*  Return -1 if not found 1 if OK 0 if an error occured */
-static gint
+/*  Return TRUE if found FALSE otherwise */
+static gboolean
 compare_streams (GstValidateMediaDescriptor * ref,
     GstValidateMediaStreamNode * rstream, GstValidateMediaStreamNode * cstream)
 {
-  if (stream_id_is_equal (ref->filenode->uri, rstream->id, cstream->id)) {
-    GstCaps *rcaps = caps_cleanup_parsing_fields (rstream->caps),
-        *ccaps = caps_cleanup_parsing_fields (cstream->caps);
-
-    if (!gst_caps_is_equal (rcaps, ccaps)) {
-      gchar *rcaps_str = gst_caps_to_string (rcaps),
-          *ccaps_str = gst_caps_to_string (ccaps);
-      GST_VALIDATE_REPORT (ref, FILE_PROFILE_INCORRECT,
-          "Reference descriptor for stream %s has caps: %s"
-          " but compared stream %s has caps: %s",
-          rstream->id, rcaps_str, cstream->id, ccaps_str);
-      gst_caps_unref (rcaps);
-      gst_caps_unref (ccaps);
-      g_free (rcaps_str);
-      g_free (ccaps_str);
-      return 0;
-    }
+  GstCaps *rcaps, *ccaps;
 
-    gst_caps_unref (rcaps);
-    gst_caps_unref (ccaps);
-    /* We ignore the return value on purpose as this is not critical */
-    compare_tags (ref, rstream, cstream);
+  if (!stream_id_is_equal (ref->filenode->uri, rstream->id, cstream->id))
+    return FALSE;
 
-    compare_segment_list (ref, rstream, cstream);
+  rcaps = caps_cleanup_parsing_fields (rstream->caps);
+  ccaps = caps_cleanup_parsing_fields (cstream->caps);
 
-    if (compare_frames_list (ref, rstream, cstream))
-      return 1;
-    return 0;
+  if (!gst_caps_is_equal (rcaps, ccaps)) {
+    gchar *rcaps_str = gst_caps_to_string (rcaps),
+        *ccaps_str = gst_caps_to_string (ccaps);
+    GST_VALIDATE_REPORT (ref, FILE_PROFILE_INCORRECT,
+        "Reference descriptor for stream %s has caps: %s"
+        " but compared stream %s has caps: %s",
+        rstream->id, rcaps_str, cstream->id, ccaps_str);
+    g_free (rcaps_str);
+    g_free (ccaps_str);
   }
 
-  return -1;
+  gst_caps_unref (rcaps);
+  gst_caps_unref (ccaps);
+  /* We ignore the return value on purpose as this is not critical */
+  compare_tags (ref, rstream, cstream);
+
+  compare_segment_list (ref, rstream, cstream);
+  compare_frames_list (ref, rstream, cstream);
+
+  return TRUE;
 }
 
 gboolean
@@ -598,25 +595,20 @@ gst_validate_media_descriptors_compare (GstValidateMediaDescriptor * ref,
   for (rstream_list = rfilenode->streams; rstream_list;
       rstream_list = rstream_list->next) {
     GList *cstream_list;
-    gint sfound = -1;
+    gboolean sfound = FALSE;
 
     for (cstream_list = cfilenode->streams; cstream_list;
         cstream_list = cstream_list->next) {
 
       sfound = compare_streams (ref, rstream_list->data, cstream_list->data);
-      if (sfound == 0) {
-        return FALSE;
-      } else if (sfound == 1) {
+      if (sfound)
         break;
-      }
     }
 
-    if (sfound == -1) {
+    if (!sfound) {
       GST_VALIDATE_REPORT (ref, FILE_PROFILE_INCORRECT,
           "Could not find stream %s in the compared descriptor",
           ((GstValidateMediaStreamNode *) rstream_list->data)->id);
-
-      return FALSE;
     }
   }
 
index 45ccb37..32e0d45 100644 (file)
@@ -29,8 +29,8 @@
 
 G_BEGIN_DECLS
 
-#define GST_VALIDATE_UKNOWN_UINT64 (G_MAXUINT64 - 2)
-#define GST_VALIDATE_UKNOWN_BOOL (G_MAXUINT32 - 2)
+#define GST_VALIDATE_UNKNOWN_UINT64 (G_MAXUINT64 - 2)
+#define GST_VALIDATE_UNKNOWN_BOOL (G_MAXUINT32 - 2)
 typedef struct
 {
   /* Children */
@@ -55,6 +55,7 @@ typedef struct
   gchar *uri;
   GstClockTime duration;
   gboolean frame_detection;
+  gboolean skip_parsers;
   gboolean seekable;
 
   GstCaps *caps;
index 1c8e679..ffeb5e4 100644 (file)
@@ -483,6 +483,9 @@ class GstValidateMediaCheckTest(GstValidateTest):
         self.add_arguments(self._uri, "--expected-results",
                            self._media_info_path)
 
+        if self.media_descriptor.skip_parsers():
+            self.add_arguments("--skip-parsers")
+
 
 class GstValidateTranscodingTest(GstValidateTest, GstValidateEncodingTestInterface):
     scenarios_manager = ScenarioManager()
index 41f66ad..c7f7c17 100644 (file)
@@ -2068,6 +2068,9 @@ class MediaDescriptor(Loggable):
     def get_media_filepath(self):
         raise NotImplemented
 
+    def skip_parsers(self):
+        return False
+
     def get_caps(self):
         raise NotImplemented
 
@@ -2168,6 +2171,9 @@ class GstValidateMediaDescriptor(MediaDescriptor):
         self.set_protocol(urllib.parse.urlparse(
             urllib.parse.urlparse(self.get_uri()).scheme).scheme)
 
+    def skip_parsers(self):
+        return self._skip_parsers
+
     def _extract_data(self, media_xml):
         # Extract the information we need from the xml
         self._caps = media_xml.findall("streams")[0].attrib["caps"]
@@ -2181,6 +2187,7 @@ class GstValidateMediaDescriptor(MediaDescriptor):
                 self._track_caps.append(
                     (stream.attrib["type"], stream.attrib["caps"]))
         self._uri = media_xml.attrib["uri"]
+        self._skip_parsers = bool(int(media_xml.attrib.get('skip-parsers', 0)))
         self._duration = int(media_xml.attrib["duration"])
         self._protocol = media_xml.get("protocol", None)
         self._is_seekable = media_xml.attrib["seekable"].lower() == "true"
@@ -2205,19 +2212,20 @@ class GstValidateMediaDescriptor(MediaDescriptor):
 
         descriptor_path = "%s.%s" % (
             media_path, GstValidateMediaDescriptor.MEDIA_INFO_EXT)
+        args = GstValidateBaseTestManager.MEDIA_CHECK_COMMAND.split(" ")
+        args.append(uri)
         if include_frames == 2:
             try:
                 media_xml = ET.parse(descriptor_path).getroot()
-                frames = media_xml.findall('streams/stream/frame')
-                include_frames = bool(frames)
+
+                include_frames = bool(int(media_xml.attrib["frame-detection"]))
+                if bool(int(media_xml.attrib.get("skip-parsers"))):
+                    args.append("--skip-parsers")
             except FileNotFoundError:
                 pass
         else:
             include_frames = bool(include_frames)
 
-        args = GstValidateBaseTestManager.MEDIA_CHECK_COMMAND.split(" ")
-        args.append(uri)
-
         args.extend(["--output-file", descriptor_path])
         if include_frames:
             args.extend(["--full"])
index 47ad62b..3a6a53b 100644 (file)
@@ -44,9 +44,12 @@ main (int argc, gchar ** argv)
   guint ret = 0;
   GError *err = NULL;
   gboolean full = FALSE;
+  gboolean skip_parsers = FALSE;
   gchar *output_file = NULL;
   gchar *expected_file = NULL;
   gchar *output = NULL;
+  GstValidateMediaDescriptorWriterFlags writer_flags =
+      GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_HANDLE_GLOGS;
   GstValidateMediaDescriptorWriter *writer = NULL;
   GstValidateRunner *runner = NULL;
   GstValidateMediaDescriptorParser *reference = NULL;
@@ -62,6 +65,9 @@ main (int argc, gchar ** argv)
           &expected_file, "Path to file containing the expected results "
           "(or the last results found) for comparison with new results",
         NULL},
+    {"skip-parsers", 's', 0, G_OPTION_ARG_NONE,
+          &skip_parsers, "Do not plug a parser after demuxer.",
+        NULL},
     {NULL}
   };
 
@@ -116,9 +122,16 @@ main (int argc, gchar ** argv)
       full = TRUE;              /* Reference has frame info, activate to do comparison */
   }
 
+  if (full)
+    writer_flags |= GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_FULL;
+
+  if (skip_parsers)
+    writer_flags |= GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NO_PARSER;
+
+
   writer =
-      gst_validate_media_descriptor_writer_new_discover (runner, argv[1], full,
-      TRUE, NULL);
+      gst_validate_media_descriptor_writer_new_discover (runner, argv[1],
+      writer_flags, NULL);
   if (writer == NULL) {
     g_print ("Could not discover file: %s\n", argv[1]);
     ret = 1;