launcher: Avoid variable framerate when encoding to theora
authorThibault Saunier <tsaunier@igalia.com>
Sat, 21 Mar 2020 14:57:51 +0000 (11:57 -0300)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 23 Oct 2020 15:18:40 +0000 (12:18 -0300)
It is not supported by theoraenc.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-devtools/-/merge_requests/172>

validate/launcher/apps/gstvalidate.py
validate/launcher/baseclasses.py
validate/launcher/utils.py

index d9cf6db..9a26e62 100644 (file)
@@ -150,6 +150,9 @@ class FakeMediaDescriptor(MediaDescriptor):
     def get_path(self):
         return self._infos.get('path', None)
 
+    def get_tracks_caps(self):
+        return self._info.get('tracks-caps', [])
+
     def get_media_filepath(self):
         return self._infos.get('media-filepath', None)
 
index 084803f..67c4842 100644 (file)
@@ -41,6 +41,7 @@ import random
 import shutil
 import uuid
 from itertools import cycle
+from fractions import Fraction
 
 from .utils import which
 from . import reporters
@@ -1257,14 +1258,29 @@ class GstValidateEncodingTestInterface(object):
         if audio_restriction is None:
             audio_restriction = self.combination.audio_restriction
         if self.media_descriptor is not None:
-            if self.media_descriptor.get_num_tracks("video") == 0:
+            if self.combination.video == "theora":
+                # Theoraenc doesn't support variable framerate, make sure to avoid them
+                framerate = self.media_descriptor.get_framerate()
+                if framerate == Fraction(0, 1):
+                    framerate = Fraction(30, 1)
+                    restriction = utils.GstCaps.new_from_str(video_restriction or "video/x-raw")
+                    for struct, _ in restriction:
+                        if struct.get("framerate") is None:
+                            struct.set("framerate", struct.FRACTION_TYPE, framerate)
+                    video_restriction = str(restriction)
+
+            video_presence = self.media_descriptor.get_num_tracks("video")
+            if video_presence == 0:
                 vcaps = None
 
-            if self.media_descriptor.get_num_tracks("audio") == 0:
+            audio_presence = self.media_descriptor.get_num_tracks("audio")
+            if audio_presence == 0:
                 acaps = None
 
         return self._get_profile_full(self.combination.get_muxer_caps(),
                                       vcaps, acaps,
+                                      audio_presence=audio_presence,
+                                      video_presence=video_presence,
                                       video_restriction=video_restriction,
                                       audio_restriction=audio_restriction,
                                       variable_framerate=variable_framerate)
@@ -2481,6 +2497,22 @@ class MediaDescriptor(Loggable):
     def has_frames(self):
         return False
 
+    def get_framerate(self):
+        for ttype, caps_str in self.get_tracks_caps():
+            if ttype != "video":
+                continue
+
+            caps = utils.GstCaps.new_from_str(caps_str)
+            if not caps:
+                self.warning("Could not create caps for %s" % caps_str)
+                continue
+
+            framerate = caps[0].get("framerate")
+            if framerate:
+                return framerate
+
+        return Fraction(0, 1)
+
     def get_media_filepath(self):
         raise NotImplemented
 
@@ -2511,6 +2543,9 @@ class MediaDescriptor(Loggable):
     def get_num_tracks(self, track_type):
         raise NotImplemented
 
+    def get_tracks_caps(self):
+        return []
+
     def can_play_reverse(self):
         raise NotImplemented
 
@@ -2624,6 +2659,7 @@ class GstValidateMediaDescriptor(MediaDescriptor):
             for stream in streams:
                 self._track_caps.append(
                     (stream.attrib["type"], stream.attrib["caps"]))
+
         self._skip_parsers = bool(int(media_xml.attrib.get('skip-parsers', 0)))
         self._has_frames = bool(int(media_xml.attrib["frame-detection"]))
         self._duration = int(media_xml.attrib["duration"])
index 45c0951..26dca49 100644 (file)
@@ -1007,6 +1007,7 @@ class GstStructure(Loggable):
             raise InvalidValueError(
                 name, check, "to match the regular expression {}"
                 "".format(regex.pattern))
+        return check
 
     NAME_REGEX = re.compile(NAME_FORMAT)
     KEY_REGEX = re.compile(KEY_FORMAT)
@@ -1014,15 +1015,15 @@ class GstStructure(Loggable):
 
     @classmethod
     def _check_name(cls, name):
-        cls._check_against_regex(name, cls.NAME_REGEX, "name")
+        return cls._check_against_regex(name, cls.NAME_REGEX, "name")
 
     @classmethod
     def _check_key(cls, key):
-        cls._check_against_regex(key, cls.KEY_REGEX, "key")
+        return cls._check_against_regex(key, cls.KEY_REGEX, "key")
 
     @classmethod
     def _check_type(cls, _type):
-        cls._check_against_regex(_type, cls.TYPE_REGEX, "type")
+        return cls._check_against_regex(_type, cls.TYPE_REGEX, "type")
 
     @classmethod
     def _check_unknown_typed_value(cls, value):