mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 09:41:07 +00:00
scripts: Add a script to validate video formats list
These lists have complex ordering and are error prone even for trained reviewers. This tool will parse the specified define in the specified file and determin if there is any error, unknown formats or miss-ordering. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5304>
This commit is contained in:
parent
b7ded81f7b
commit
63b8a5f22d
1 changed files with 145 additions and 0 deletions
145
scripts/sort_video_formats.py
Executable file
145
scripts/sort_video_formats.py
Executable file
|
@ -0,0 +1,145 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import gi
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
gi.require_version("Gst", "1.0")
|
||||||
|
gi.require_version("GstVideo", "1.0")
|
||||||
|
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import Gst, GstVideo
|
||||||
|
|
||||||
|
|
||||||
|
def video_format_exists(f):
|
||||||
|
return GstVideo.video_format_from_string(f) != GstVideo.VideoFormat.UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
|
def video_format_info_from_string(s):
|
||||||
|
f = GstVideo.video_format_from_string(s)
|
||||||
|
return GstVideo.video_format_get_info(f)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_format_from_c(token, filename):
|
||||||
|
code = open(filename).read().splitlines()
|
||||||
|
token_found = False
|
||||||
|
formats = None
|
||||||
|
|
||||||
|
for idx, line in enumerate(code):
|
||||||
|
if formats is None:
|
||||||
|
match = f"#define {token}"
|
||||||
|
if line.startswith(match):
|
||||||
|
formats = []
|
||||||
|
line = line[len(match):]
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
tmp = line.replace("\\", "")\
|
||||||
|
.replace("\"", "")\
|
||||||
|
.replace(",", " ")\
|
||||||
|
.replace("{", " ")\
|
||||||
|
.replace("}", " ")\
|
||||||
|
.split()
|
||||||
|
for f in tmp:
|
||||||
|
if not video_format_exists(f):
|
||||||
|
basename = os.path.basename(filename)
|
||||||
|
print(f"WARNING: {basename}:{idx}: unknown format {f}")
|
||||||
|
|
||||||
|
formats += tmp
|
||||||
|
|
||||||
|
if line[-1] != "\\":
|
||||||
|
break
|
||||||
|
|
||||||
|
if formats is None:
|
||||||
|
print(f"Define for {token} not found in {filename}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
formats = list(filter(video_format_exists, formats))
|
||||||
|
|
||||||
|
return [video_format_info_from_string(f) for f in formats]
|
||||||
|
|
||||||
|
|
||||||
|
def score_endian(fmt, endian):
|
||||||
|
score = 0
|
||||||
|
if fmt.flags & GstVideo.VideoFormatFlags.LE:
|
||||||
|
score = 1
|
||||||
|
if endian == "LE":
|
||||||
|
return -score
|
||||||
|
else:
|
||||||
|
return score
|
||||||
|
|
||||||
|
|
||||||
|
def sort_video_formats(formats, endian):
|
||||||
|
return sorted(formats, key=lambda x: (-x.n_components,
|
||||||
|
[-d for d in x.depth],
|
||||||
|
x.w_sub,
|
||||||
|
x.h_sub,
|
||||||
|
-x.n_planes,
|
||||||
|
score_endian(x, endian),
|
||||||
|
[-s for s in x.pixel_stride],
|
||||||
|
(x.flags & GstVideo.VideoFormatFlags.COMPLEX),
|
||||||
|
not (x.flags & GstVideo.VideoFormatFlags.YUV),
|
||||||
|
x.name))
|
||||||
|
|
||||||
|
|
||||||
|
def video_formats_to_c(token, formats, bracket):
|
||||||
|
s = [f'#define {token} "']
|
||||||
|
|
||||||
|
if bracket:
|
||||||
|
s[-1] += "{ "
|
||||||
|
|
||||||
|
for f in formats:
|
||||||
|
if len(s[-1]) > 80 - len(f.name) - len(', " \\'):
|
||||||
|
s[-1] += ', " \\'
|
||||||
|
s.append(' "')
|
||||||
|
if s[-1][-2:] not in (' "', '{ '):
|
||||||
|
s[-1] += ", "
|
||||||
|
s[-1] += f.name
|
||||||
|
|
||||||
|
if bracket:
|
||||||
|
s[-1] += " }"
|
||||||
|
|
||||||
|
s[-1] += '"'
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def generate_c_code(token, formats_be, formats_le, bracket):
|
||||||
|
s = ["#if G_BYTE_ORDER == G_BIG_ENDIAN"]
|
||||||
|
s += video_formats_to_c(token, formats_be, bracket)
|
||||||
|
s += ["#elif G_BYTE_ORDER == G_LITTLE_ENDIAN"]
|
||||||
|
s += video_formats_to_c(token, formats_le, bracket)
|
||||||
|
s += ["#endif"]
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
formats = parse_format_from_c(args.token, args.filename)
|
||||||
|
if formats is None:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
formats_be = sort_video_formats(formats, "BE")
|
||||||
|
formats_le = sort_video_formats(formats, "LE")
|
||||||
|
|
||||||
|
# We only check BE order as the list are now generated
|
||||||
|
if formats_be == formats:
|
||||||
|
print("Formats are properly ordered.")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
basename = os.path.basename(args.filename)
|
||||||
|
print(f"ERROR: Formats order differ for {args.token} in {args.filename}")
|
||||||
|
print("This can be fixed by replacing the define with:\n")
|
||||||
|
for c_line in generate_c_code(args.token, formats_be, formats_le,
|
||||||
|
args.bracket):
|
||||||
|
print(c_line)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
Gst.init(None)
|
||||||
|
parser = argparse.ArgumentParser(prog='sort_video_formats',
|
||||||
|
description='Sort video formats list')
|
||||||
|
parser.add_argument('token')
|
||||||
|
parser.add_argument('filename')
|
||||||
|
parser.add_argument('-b', '--bracket', action='store_true')
|
||||||
|
args = parser.parse_args()
|
||||||
|
sys.exit(main(args))
|
Loading…
Reference in a new issue