diff options
Diffstat (limited to 'dom/media/test/reftest/gen_combos.py')
-rw-r--r-- | dom/media/test/reftest/gen_combos.py | 257 |
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)}") |