Skip to content

Commit

Permalink
Create a test suite for H264 SVC group (#177)
Browse files Browse the repository at this point in the history
Create a test suite for H264 SVC group
  • Loading branch information
rsanchez87 authored Jul 22, 2024
1 parent 34670ba commit 2790984
Show file tree
Hide file tree
Showing 5 changed files with 1,798 additions and 66 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ Check out the JSON format they follow in the [test_suites](test_suites)
directory. Add a new json file within, Fluster will automatically pick it
up.
There is also a [generator script](scripts/gen_jct_vc.py) for the [conformance
There is also a [generator script (H.265, H.266)](scripts/gen_jvet_jctvc.py) and a [generator script (H.264)](scripts/gen_jvt.py) for the [conformance
test suites](#test_suites) that you can use as a base to generate automatically
new ones.
Expand Down
47 changes: 47 additions & 0 deletions fluster/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,53 @@ def normalize_path(path: str) -> str:
return path


def find_by_ext(
dest_dir: str, exts: List[str], excludes: Optional[List[str]] = None
) -> Optional[str]:
"""Return name by file extension"""
excludes = excludes or []

# Respect the priority for extensions
for ext in exts:
for subdir, _, files in os.walk(dest_dir):
for filename in files:
excluded = False
filepath = os.path.join(subdir, filename)
if not filepath.endswith(ext) or "__MACOSX" in filepath:
continue
for excl in excludes:
if excl in filepath:
excluded = True
break
if not excluded:
return filepath
return None


def find_by_ext_multiple(
dest_dir: str, exts: List[str], excludes: Optional[List[str]] = None
) -> List[str]:
"""Return multiple names by file extension"""
excludes = excludes or []
found_files = []

# Respect the priority for extensions
for ext in exts:
for subdir, _, files in os.walk(dest_dir):
for filename in files:
excluded = False
filepath = os.path.join(subdir, filename)
if not filepath.endswith(ext) or "__MACOSX" in filepath:
continue
for excl in excludes:
if excl in filepath:
excluded = True
break
if not excluded:
found_files.append(filepath)
return found_files


def _linux_user_data_dir(appname: str) -> str:
"""Return data directory tied to the user"""
path = os.environ.get("XDG_DATA_HOME", "")
Expand Down
74 changes: 9 additions & 65 deletions scripts/gen_jct_vc.py → scripts/gen_jvet_jctvc.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,9 @@
BASE_URL = "https://www.itu.int/"
H266_URL = BASE_URL + "wftp3/av-arch/jvet-site/bitstream_exchange/VVC/draft_conformance/"
H265_URL = BASE_URL + "wftp3/av-arch/jctvc-site/bitstream_exchange/draft_conformance/"
H264_URL = BASE_URL + "wftp3/av-arch/jvt-site/draft_conformance/"
BITSTREAM_EXTS = (
".bin",
".bit",
".264",
".h264",
".jvc",
".jsv",
".jvt",
".avc",
".26l",
".bits",
)
MD5_EXTS = ("yuv_2.md5", "yuv.md5", ".md5", "md5.txt", "md5sum.txt")
MD5_EXCLUDES = (".bin.md5", "bit.md5")
Expand Down Expand Up @@ -76,7 +67,7 @@ def handle_starttag(self, tag, attrs):
self.links.append(base_url + value)


class JCTVTGenerator:
class JVETJCTVCGenerator:
"""Generates a test suite from the conformance bitstreams"""

def __init__(
Expand Down Expand Up @@ -140,7 +131,7 @@ def generate(self, download, jobs):
test_suite.resources_dir, test_suite.name, test_vector.name
)
dest_path = os.path.join(dest_dir, os.path.basename(test_vector.source))
test_vector.input_file = self._find_by_ext(dest_dir, BITSTREAM_EXTS)
test_vector.input_file = utils.find_by_ext(dest_dir, BITSTREAM_EXTS)
absolute_input_path = test_vector.input_file
test_vector.input_file = test_vector.input_file.replace(
os.path.join(
Expand Down Expand Up @@ -192,21 +183,12 @@ def generate(self, download, jobs):

if self.codec == Codec.H265:
self._fill_checksum_h265(test_vector, dest_dir)
elif self.codec == Codec.H264:
if self.name != "Professional_profiles":
self._fill_checksum_h264(test_vector, dest_dir)

test_suite.to_json_file(output_filepath)
print("Generate new test suite: " + test_suite.name + ".json")

def _fill_checksum_h264(self, test_vector, dest_dir):
raw_file = self._find_by_ext(dest_dir, RAW_EXTS)
if raw_file is None:
raise Exception(f"RAW file not found in {dest_dir}")
test_vector.result = utils.file_checksum(raw_file)

def _fill_checksum_h265(self, test_vector, dest_dir):
checksum_file = self._find_by_ext(dest_dir, MD5_EXTS, MD5_EXCLUDES)
checksum_file = utils.find_by_ext(dest_dir, MD5_EXTS, MD5_EXCLUDES)
if checksum_file is None:
raise Exception("MD5 not found")
with open(checksum_file, "r") as checksum_file:
Expand Down Expand Up @@ -251,26 +233,6 @@ def _fill_checksum_h265(self, test_vector, dest_dir):
assert len(test_vector.result) == 32 and re.search(
r"^[a-fA-F0-9]{32}$", test_vector.result) is not None, f"{test_vector.result} is not a valid MD5 hash"

@staticmethod
def _find_by_ext(dest_dir, exts, excludes=None):
excludes = excludes or []

# Respect the priority for extensions
for ext in exts:
for subdir, _, files in os.walk(dest_dir):
for filename in files:
excluded = False
filepath = subdir + os.sep + filename
if not filepath.endswith(ext) or "__MACOSX" in filepath:
continue
for excl in excludes:
if excl in filepath:
excluded = True
break
if not excluded:
return filepath
return None


if __name__ == "__main__":
parser = argparse.ArgumentParser()
Expand All @@ -288,7 +250,7 @@ def _find_by_ext(dest_dir, exts, excludes=None):
default=2 * multiprocessing.cpu_count(),
)
args = parser.parse_args()
generator = JCTVTGenerator(
generator = JVETJCTVCGenerator(
"HEVC_v1",
"JCT-VC-HEVC_V1",
Codec.H265,
Expand All @@ -297,7 +259,7 @@ def _find_by_ext(dest_dir, exts, excludes=None):
)
generator.generate(not args.skip_download, args.jobs)

generator = JCTVTGenerator(
generator = JVETJCTVCGenerator(
"RExt",
"JCT-VC-RExt",
Codec.H265,
Expand All @@ -307,7 +269,7 @@ def _find_by_ext(dest_dir, exts, excludes=None):
)
generator.generate(not args.skip_download, args.jobs)

generator = JCTVTGenerator(
generator = JVETJCTVCGenerator(
"SCC",
"JCT-VC-SCC",
Codec.H265,
Expand All @@ -317,7 +279,7 @@ def _find_by_ext(dest_dir, exts, excludes=None):
)
generator.generate(not args.skip_download, args.jobs)

generator = JCTVTGenerator(
generator = JVETJCTVCGenerator(
"MV-HEVC",
"JCT-VC-MV-HEVC",
Codec.H265,
Expand All @@ -327,29 +289,11 @@ def _find_by_ext(dest_dir, exts, excludes=None):
)
generator.generate(not args.skip_download, args.jobs)

generator = JCTVTGenerator(
"AVCv1",
"JVT-AVC_V1",
Codec.H264,
"JVT AVC version 1",
H264_URL
)
generator.generate(not args.skip_download, args.jobs)

generator = JCTVTGenerator(
generator = JVETJCTVCGenerator(
'draft6',
'JVET-VVC_draft6',
Codec.H266,
'JVET VVC draft6',
H266_URL)
generator.generate(not args.skip_download, args.jobs)

generator = JCTVTGenerator(
"Professional_profiles",
"JVT-Professional_profiles_V1",
Codec.H264,
"JVT professional profiles version 1",
H264_URL,
True
H266_URL
)
generator.generate(not args.skip_download, args.jobs)
Loading

0 comments on commit 2790984

Please sign in to comment.