summaryrefslogtreecommitdiffstats
path: root/dom/media/test/reftest/gen_combos.py
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/test/reftest/gen_combos.py')
-rw-r--r--dom/media/test/reftest/gen_combos.py257
1 files changed, 257 insertions, 0 deletions
diff --git a/dom/media/test/reftest/gen_combos.py b/dom/media/test/reftest/gen_combos.py
new file mode 100644
index 0000000000..f7e7d50fe1
--- /dev/null
+++ b/dom/media/test/reftest/gen_combos.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python3
+
+# E.g. `./gen_combos.py [--write] color_quads/720p.png`
+
+import concurrent.futures
+import pathlib
+import subprocess
+import sys
+
+ARGS = sys.argv
+SRC_PATH = pathlib.Path(ARGS.pop())
+assert SRC_PATH.exists(), "gen_combos.py [--flags] <src file path>"
+DIR = SRC_PATH.parent
+
+
+# crossCombine([{a:false},{a:5}], [{},{b:5}])
+# [{a:false}, {a:true}, {a:false,b:5}, {a:true,b:5}]
+def cross_combine(*args):
+ args = list(args)
+
+ def cross_combine2(listA, listB):
+ listC = []
+ for a in listA:
+ for b in listB:
+ c = dict()
+ c.update(a)
+ c.update(b)
+ listC.append(c)
+ return listC
+
+ res = [dict()]
+ while True:
+ try:
+ next = args.pop(0)
+ except IndexError:
+ break
+ res = cross_combine2(res, next)
+ return res
+
+
+def keyed_combiner(key, vals):
+ res = []
+ for v in vals:
+ d = dict()
+ d[key] = v
+ res.append(d)
+ return res
+
+
+# -
+
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
+# -
+
+OGG = []
+WEBM_CODECS = ["av1", "vp9"]
+
+if "--all" in ARGS:
+ OGG = cross_combine(
+ [{"ext": "ogg"}], keyed_combiner("vcodec", ["theora", "vp8", "vp9"])
+ )
+ WEBM_CODECS += ["vp8"]
+
+MP4 = cross_combine([{"ext": "mp4"}], keyed_combiner("vcodec", ["av1", "h264", "vp9"]))
+
+WEBM = cross_combine([{"ext": "webm"}], keyed_combiner("vcodec", WEBM_CODECS))
+
+# -
+
+FORMAT_LIST = set(
+ [
+ "yuv420p",
+ "yuv420p10",
+ # 'yuv420p12',
+ # 'yuv420p16be',
+ # 'yuv420p16le',
+ "gbrp",
+ ]
+)
+
+if "--all" in ARGS:
+ FORMAT_LIST |= set(
+ [
+ "yuv420p",
+ "yuv420p10",
+ "yuv420p12",
+ "yuv420p16be",
+ "yuv420p16le",
+ "yuv422p",
+ "yuv422p10",
+ "yuv422p12",
+ "yuv422p16be",
+ "yuv422p16le",
+ "yuv444p",
+ "yuv444p10",
+ "yuv444p12",
+ "yuv444p16be",
+ "yuv444p16le",
+ "yuv411p",
+ "yuv410p",
+ "yuyv422",
+ "uyvy422",
+ "rgb24",
+ "bgr24",
+ "rgb8",
+ "bgr8",
+ "rgb444be",
+ "rgb444le",
+ "bgr444be",
+ "bgr444le",
+ # 'nv12', # Encoding not different than yuv420p?
+ # 'nv21', # Encoding not different than yuv420p?
+ "gbrp",
+ "gbrp9be",
+ "gbrp9le",
+ "gbrp10be",
+ "gbrp10le",
+ "gbrp12be",
+ "gbrp12le",
+ "gbrp14be",
+ "gbrp14le",
+ "gbrp16be",
+ "gbrp16le",
+ ]
+ )
+
+FORMATS = keyed_combiner("format", list(FORMAT_LIST))
+
+RANGE = keyed_combiner("range", ["tv", "pc"])
+
+CSPACE_LIST = set(
+ [
+ "bt709",
+ # 'bt2020',
+ ]
+)
+
+if "--all" in ARGS:
+ CSPACE_LIST |= set(
+ [
+ "bt709",
+ "bt2020",
+ "bt601-6-525", # aka smpte170m NTSC
+ "bt601-6-625", # aka bt470bg PAL
+ ]
+ )
+CSPACE_LIST = list(CSPACE_LIST)
+
+# -
+
+COMBOS = cross_combine(
+ WEBM + MP4 + OGG,
+ FORMATS,
+ RANGE,
+ keyed_combiner("src_cspace", CSPACE_LIST),
+ keyed_combiner("dst_cspace", CSPACE_LIST),
+)
+
+# -
+
+print(f"{len(COMBOS)} combinations...")
+
+todo = []
+for c in COMBOS:
+ dst_name = ".".join(
+ [
+ SRC_PATH.name,
+ c["src_cspace"],
+ c["dst_cspace"],
+ c["range"],
+ c["format"],
+ c["vcodec"],
+ c["ext"],
+ ]
+ )
+
+ src_cspace = c["src_cspace"]
+
+ vf = f"scale=out_range={c['range']}"
+ vf += f",colorspace=all={c['dst_cspace']}"
+ vf += f":iall={src_cspace}"
+ args = [
+ "ffmpeg",
+ "-y",
+ # For input:
+ "-color_primaries",
+ src_cspace,
+ "-color_trc",
+ src_cspace,
+ "-colorspace",
+ src_cspace,
+ "-i",
+ SRC_PATH.as_posix(),
+ # For output:
+ "-bitexact", # E.g. don't use true random uuids
+ "-vf",
+ vf,
+ "-pix_fmt",
+ c["format"],
+ "-vcodec",
+ c["vcodec"],
+ "-crf",
+ "1", # Not-quite-lossless
+ (DIR / dst_name).as_posix(),
+ ]
+ if "-v" in ARGS or "-vv" in ARGS:
+ print("$ " + " ".join(args))
+ else:
+ print(" " + args[-1])
+
+ todo.append(args)
+
+# -
+
+with open(DIR / "reftest.list", "r") as f:
+ reftest_list_text = f.read()
+
+for args in todo:
+ vid_name = pathlib.Path(args[-1]).name
+ if vid_name not in reftest_list_text:
+ print(f"WARNING: Not in reftest.list: {vid_name}")
+
+# -
+
+if "--write" not in ARGS:
+ print("Use --write to write. Exiting...")
+ exit(0)
+
+# -
+
+
+def run_cmd(args):
+ dest = None
+ if "-vv" not in ARGS:
+ dest = subprocess.DEVNULL
+ try:
+ subprocess.run(args, stderr=dest)
+ except FileNotFoundError:
+ print("FileNotFoundError, is ffmpeg not in your PATH?")
+ raise
+
+
+with concurrent.futures.ThreadPoolExecutor() as pool:
+ fs = []
+ for cur_args in todo:
+ f = pool.submit(run_cmd, cur_args)
+ fs.append(f)
+
+ done = 0
+ for f in concurrent.futures.as_completed(fs):
+ f.result() # Raise if it raised
+ done += 1
+ sys.stdout.write(f"\rEncoded {done}/{len(todo)}")