mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-29 01:35:06 +00:00
validate:launcher: Add a generator to generate test for frame accurate seeking
This commit is contained in:
parent
30ceb4ef40
commit
0b41b8a8c0
|
@ -27,7 +27,9 @@ import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import configparser
|
import configparser
|
||||||
import json
|
import json
|
||||||
from launcher.loggable import Loggable
|
import glob
|
||||||
|
import math
|
||||||
|
from launcher.loggable import Loggable, error
|
||||||
|
|
||||||
from launcher.baseclasses import GstValidateTest, Test, \
|
from launcher.baseclasses import GstValidateTest, Test, \
|
||||||
ScenarioManager, NamedDic, GstValidateTestsGenerator, \
|
ScenarioManager, NamedDic, GstValidateTestsGenerator, \
|
||||||
|
@ -36,7 +38,8 @@ from launcher.baseclasses import GstValidateTest, Test, \
|
||||||
|
|
||||||
from launcher.utils import path2url, url2path, DEFAULT_TIMEOUT, which, \
|
from launcher.utils import path2url, url2path, DEFAULT_TIMEOUT, which, \
|
||||||
GST_SECOND, Result, Protocols, mkdir, printc, Colors, get_data_file, \
|
GST_SECOND, Result, Protocols, mkdir, printc, Colors, get_data_file, \
|
||||||
kill_subprocess, format_config_template, get_fakesink_for_media_type
|
kill_subprocess, format_config_template, get_fakesink_for_media_type, \
|
||||||
|
parse_gsttimeargs, GstCaps
|
||||||
|
|
||||||
#
|
#
|
||||||
# Private global variables #
|
# Private global variables #
|
||||||
|
@ -337,6 +340,8 @@ class GstValidatePipelineTestsGenerator(GstValidateTestsGenerator):
|
||||||
scenarios_to_iterate = scenarios
|
scenarios_to_iterate = scenarios
|
||||||
|
|
||||||
config_files = extra_data.get('config_files')
|
config_files = extra_data.get('config_files')
|
||||||
|
mediainfo = extra_data.get(
|
||||||
|
'media_info', FakeMediaDescriptor(extra_data, pipeline))
|
||||||
for scenario in scenarios_to_iterate:
|
for scenario in scenarios_to_iterate:
|
||||||
if isinstance(scenario, str):
|
if isinstance(scenario, str):
|
||||||
tmpscenario = self.test_manager.scenarios_manager.get_scenario(
|
tmpscenario = self.test_manager.scenarios_manager.get_scenario(
|
||||||
|
@ -345,7 +350,6 @@ class GstValidatePipelineTestsGenerator(GstValidateTestsGenerator):
|
||||||
raise RuntimeError("Could not find scenario file: %s" % scenario)
|
raise RuntimeError("Could not find scenario file: %s" % scenario)
|
||||||
scenario = tmpscenario
|
scenario = tmpscenario
|
||||||
|
|
||||||
mediainfo = FakeMediaDescriptor(extra_data, pipeline)
|
|
||||||
if not mediainfo.is_compatible(scenario):
|
if not mediainfo.is_compatible(scenario):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -470,6 +474,98 @@ class GstValidatePlaybinTestsGenerator(GstValidatePipelineTestsGenerator):
|
||||||
rtsp2=True))
|
rtsp2=True))
|
||||||
|
|
||||||
|
|
||||||
|
class GstValidateCheckAccurateSeekingTestGenerator(GstValidatePipelineTestsGenerator):
|
||||||
|
def __new__(cls, name, test_manager, media_infos, extra_data=None):
|
||||||
|
pipelines = {}
|
||||||
|
|
||||||
|
for path, reference_frame_dir in media_infos:
|
||||||
|
media_info = GstValidateMediaDescriptor(path)
|
||||||
|
media_info.set_protocol("file")
|
||||||
|
if not media_info:
|
||||||
|
error("GstValidateCheckAccurateSeekingTestGenerator",
|
||||||
|
"Could not create a media info file from %s" % path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if media_info.is_image():
|
||||||
|
error("GstValidateCheckAccurateSeekingTestGenerator",
|
||||||
|
"%s is an image, can't run accurate seeking tests" % path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if media_info.get_num_tracks("video") < 1:
|
||||||
|
error("GstValidateCheckAccurateSeekingTestGenerator",
|
||||||
|
"%s is not a video, can't run accurate seeking tests" % path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if media_info.get_num_tracks("video") < 1:
|
||||||
|
error("GstValidateCheckAccurateSeekingTestGenerator",
|
||||||
|
"No video track, can't run accurate seeking tests" % path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if test_manager.options.validate_generate_ssim_reference_files:
|
||||||
|
scenario = None
|
||||||
|
test_name = media_info.get_clean_name() + '.generate_reference_files'
|
||||||
|
config = [
|
||||||
|
'validatessim, element-name="videoconvert", output-dir="%s"' % reference_frame_dir]
|
||||||
|
else:
|
||||||
|
test_name = media_info.get_clean_name()
|
||||||
|
framerate, scenario = cls.generate_scenario(test_manager.options, reference_frame_dir, media_info)
|
||||||
|
if scenario is None:
|
||||||
|
error("GstValidateCheckAccurateSeekingTestGenerator",
|
||||||
|
"Could not generate test for media info: %s" % path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
config = [
|
||||||
|
'%(ssim)s, element-name="videoconvert", reference-images-dir="' + \
|
||||||
|
reference_frame_dir + '", framerate=%d/%d' % (framerate.numerator, framerate.denominator)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
pipelines[test_name] = {
|
||||||
|
"pipeline": "uridecodebin uri=" + media_info.get_uri() + " ! deinterlace ! video/x-raw,interlace-mode=progressive ! videoconvert name=videoconvert ! %(videosink)s",
|
||||||
|
"media_info": media_info,
|
||||||
|
"config": config,
|
||||||
|
}
|
||||||
|
|
||||||
|
if scenario:
|
||||||
|
pipelines[test_name]["scenarios"] = [scenario]
|
||||||
|
|
||||||
|
return GstValidatePipelineTestsGenerator.from_dict(test_manager, name, pipelines, extra_data=extra_data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_scenario(cls, options, reference_frame_dir, media_info):
|
||||||
|
actions = [
|
||||||
|
"description, seek=true, handles-states=true, needs_preroll=true",
|
||||||
|
"pause",
|
||||||
|
]
|
||||||
|
|
||||||
|
framerate = None
|
||||||
|
for track_type, caps in media_info.get_tracks_caps():
|
||||||
|
if track_type == 'video':
|
||||||
|
for struct, _ in GstCaps.new_from_str(caps):
|
||||||
|
framerate = struct["framerate"]
|
||||||
|
if framerate:
|
||||||
|
break
|
||||||
|
assert framerate
|
||||||
|
|
||||||
|
n_frames = int((media_info.get_duration() * framerate.numerator) / (GST_SECOND * framerate.denominator))
|
||||||
|
frames_timestamps = [math.ceil(i * framerate.denominator * GST_SECOND / framerate.numerator) for i in range(n_frames)]
|
||||||
|
# Ensure tests are not longer than long_limit, empirically considering we take 0.2 secs per frames.
|
||||||
|
acceptable_n_frames = options.long_limit * 5
|
||||||
|
if n_frames > acceptable_n_frames:
|
||||||
|
n_frames_per_groups = int(acceptable_n_frames / 3)
|
||||||
|
frames_timestamps = frames_timestamps[0:n_frames_per_groups] \
|
||||||
|
+ frames_timestamps[int(n_frames / 2 - int(n_frames_per_groups / 2)):int(n_frames / 2 + int(n_frames_per_groups / 2))] \
|
||||||
|
+ frames_timestamps[-n_frames_per_groups:n_frames]
|
||||||
|
|
||||||
|
actions += ['seek, flags=flush+accurate, start=(guint64)%s' % ts for ts in frames_timestamps]
|
||||||
|
actions += ['stop']
|
||||||
|
|
||||||
|
return framerate, {
|
||||||
|
"name": "check_accurate_seek",
|
||||||
|
"actions": actions,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class GstValidateMixerTestsGenerator(GstValidatePipelineTestsGenerator):
|
class GstValidateMixerTestsGenerator(GstValidatePipelineTestsGenerator):
|
||||||
|
|
||||||
def __init__(self, name, test_manager, mixer, media_type, converter="",
|
def __init__(self, name, test_manager, mixer, media_type, converter="",
|
||||||
|
@ -837,6 +933,7 @@ class GstValidateTestManager(GstValidateBaseTestManager):
|
||||||
GstValidatePipelineTestsGenerator = GstValidatePipelineTestsGenerator
|
GstValidatePipelineTestsGenerator = GstValidatePipelineTestsGenerator
|
||||||
GstValidatePlaybinTestsGenerator = GstValidatePlaybinTestsGenerator
|
GstValidatePlaybinTestsGenerator = GstValidatePlaybinTestsGenerator
|
||||||
GstValidateMixerTestsGenerator = GstValidateMixerTestsGenerator
|
GstValidateMixerTestsGenerator = GstValidateMixerTestsGenerator
|
||||||
|
GstValidateCheckAccurateSeekingTestGenerator = GstValidateCheckAccurateSeekingTestGenerator
|
||||||
GstValidateLaunchTest = GstValidateLaunchTest
|
GstValidateLaunchTest = GstValidateLaunchTest
|
||||||
GstValidateMediaCheckTest = GstValidateMediaCheckTest
|
GstValidateMediaCheckTest = GstValidateMediaCheckTest
|
||||||
GstValidateTranscodingTest = GstValidateTranscodingTest
|
GstValidateTranscodingTest = GstValidateTranscodingTest
|
||||||
|
@ -875,6 +972,9 @@ not been tested and explicitely activated if you set use --wanted-tests ALL""")
|
||||||
group.add_argument("--validate-enable-iqa-tests", dest="validate_enable_iqa_tests",
|
group.add_argument("--validate-enable-iqa-tests", dest="validate_enable_iqa_tests",
|
||||||
help="Enable Image Quality Assessment validation tests.",
|
help="Enable Image Quality Assessment validation tests.",
|
||||||
default=False, action='store_true')
|
default=False, action='store_true')
|
||||||
|
group.add_argument("--validate-generate-ssim-reference-files",
|
||||||
|
help="(re)generate ssim reference image files.",
|
||||||
|
default=False, action='store_true')
|
||||||
|
|
||||||
def print_valgrind_bugs(self):
|
def print_valgrind_bugs(self):
|
||||||
# Look for all the 'pending' bugs in our supp file
|
# Look for all the 'pending' bugs in our supp file
|
||||||
|
@ -972,10 +1072,8 @@ not been tested and explicitely activated if you set use --wanted-tests ALL""")
|
||||||
if is_push or is_skipped:
|
if is_push or is_skipped:
|
||||||
if not os.path.exists(media_info):
|
if not os.path.exists(media_info):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if is_push:
|
if is_push:
|
||||||
uri = "push" + uri
|
uri = "push" + uri
|
||||||
|
|
||||||
args = GstValidateBaseTestManager.MEDIA_CHECK_COMMAND.split(" ")
|
args = GstValidateBaseTestManager.MEDIA_CHECK_COMMAND.split(" ")
|
||||||
args.append(uri)
|
args.append(uri)
|
||||||
if os.path.isfile(media_info) and not self.options.update_media_info and not is_skipped:
|
if os.path.isfile(media_info) and not self.options.update_media_info and not is_skipped:
|
||||||
|
@ -1076,7 +1174,7 @@ not been tested and explicitely activated if you set use --wanted-tests ALL""")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if options.validate_uris:
|
if options.validate_uris or options.validate_generate_ssim_reference_files:
|
||||||
self.check_testslist = False
|
self.check_testslist = False
|
||||||
|
|
||||||
super(GstValidateTestManager, self).set_settings(
|
super(GstValidateTestManager, self).set_settings(
|
||||||
|
|
|
@ -2537,7 +2537,6 @@ class GstValidateMediaDescriptor(MediaDescriptor):
|
||||||
for stream in streams:
|
for stream in streams:
|
||||||
self._track_caps.append(
|
self._track_caps.append(
|
||||||
(stream.attrib["type"], stream.attrib["caps"]))
|
(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._skip_parsers = bool(int(media_xml.attrib.get('skip-parsers', 0)))
|
||||||
self._has_frames = bool(int(media_xml.attrib["frame-detection"]))
|
self._has_frames = bool(int(media_xml.attrib["frame-detection"]))
|
||||||
self._duration = int(media_xml.attrib["duration"])
|
self._duration = int(media_xml.attrib["duration"])
|
||||||
|
@ -2682,7 +2681,8 @@ class GstValidateMediaDescriptor(MediaDescriptor):
|
||||||
|
|
||||||
def get_clean_name(self):
|
def get_clean_name(self):
|
||||||
name = os.path.basename(self.get_path())
|
name = os.path.basename(self.get_path())
|
||||||
name = re.sub("\.stream_info|\.media_info", "", name)
|
regex = '|'.join(['\\.%s$' % ext for ext in [self.SKIPPED_MEDIA_INFO_EXT, self.MEDIA_INFO_EXT, self.PUSH_MEDIA_INFO_EXT, self.STREAM_INFO_EXT]])
|
||||||
|
name = re.sub(regex, "", name)
|
||||||
|
|
||||||
return name.replace('.', "_")
|
return name.replace('.', "_")
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue