This commit is contained in:
2026-05-06 23:44:13 +02:00
parent a5f787d80f
commit fd7038b853
1574 changed files with 365439 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------
#
# Copyright (C) 2023 The Khronos Group Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-------------------------------------------------------------------------
#
# Generate checksums from a sequence of YV12 YUV frames as produced by
# the Fraunhofer reference decoders.
#
# The reference checksums were generated using the Fluster testing
# framework (git@github.com:fluendo/fluster.git @
# fd2a3aec596ba5437b4c3364111938531a4b5f92) to build the Fraunhofer
# reference decoders,
#
# ~/src/fluster $ make h26[45]_reference_decoder
#
# Then, to generate references for H.264 test content,
#
# $ cd ~/src/vk-gl-cts/external/vulkancts/data/vulkan/video/
# $ ~/src/fluster/contrib/JM/bin/umake/gcc-12.2/x86_64/release/ldecod -s -i clip-a.h264 -o clip-a.out
# $ python frame_checksums.py clip-a.out 176 144 ; rm clip-a.out
#
# To generate the H.265 YUV files, change the reference decoder line above to,
#
# $ ~/src/fluster/contrib/HM/bin/umake/gcc-12.2/x86_64/release/TAppDecoder -b jellyfish-250-mbps-4k-uhd-GOB-IPB13.h265 -o jellyfish265.out
#
# The h264_resolution_change example was specially handled, since
# it's actually a non-conformant bitstream according to the reference
# decoders. There are two streams of different resolution
# concatenated together in the test vector. They were manually cut
# out and each independent stream was passed through the above
# process to generate the checksums.
#
import os
import sys
import hashlib
def print_help():
help_text = """Usage: frame_checksums.py [OPTIONS] yuvFile width height
Generate MD5 checksums from YUV frames in C array format.
Arguments:
yuvFile YUV file to process (YV12 format)
width Frame width in pixels
height Frame height in pixels
Options:
-a NAME C array name (default: frameChecksums)
-n NUM Process only first NUM frames
-h, --help Show this help message and exit
Examples:
python frame_checksums.py clip-a.out 176 144
python frame_checksums.py -n 30 -a clipAChecksums clip-a.out 176 144
"""
print(help_text)
sys.exit(0)
# Parse command line arguments
yuv_filename = None
width = None
height = None
array_name = "frameChecksums"
frame_limit = None
i = 1
while i < len(sys.argv):
if sys.argv[i] in ('-h', '--help'):
print_help()
elif sys.argv[i] == '-n' and i + 1 < len(sys.argv):
frame_limit = int(sys.argv[i + 1])
i += 2
elif sys.argv[i] == '-a' and i + 1 < len(sys.argv):
array_name = sys.argv[i + 1]
i += 2
elif yuv_filename is None:
yuv_filename = sys.argv[i]
i += 1
elif width is None:
width = int(sys.argv[i])
i += 1
elif height is None:
height = int(sys.argv[i])
i += 1
else:
i += 1
if yuv_filename is None or width is None or height is None:
print("Usage: frame_checksums.py [OPTIONS] yuvFile width height")
print("Use -h or --help for more information")
sys.exit(1)
def checksum(bs: bytes) -> str:
md5 = hashlib.md5()
md5.update(bs)
return md5.hexdigest()
file_size = os.path.getsize(yuv_filename)
# This assumes the YCrCb format is YV12, as produced by the Fraunhofer
# reference decoders.
frame_size = int(width * height * 1.5)
n_frames = file_size // frame_size
# Apply frame limit if specified
if frame_limit is not None:
n_frames = min(n_frames, frame_limit)
md5_hashes = []
with open(yuv_filename, 'rb') as f:
print("Computing checksums for ", n_frames, " frames", file=sys.stderr)
for frame in range(n_frames):
md5_hashes.append(checksum(f.read(frame_size)))
# Output in C array format (3 hashes per line)
print(f"static const char *{array_name}[{n_frames}] = {{")
for i in range(0, n_frames, 3):
# Get up to 3 hashes for this line
line_hashes = md5_hashes[i:i+3]
formatted_hashes = ', '.join(f'"{h}"' for h in line_hashes)
# Add comma after line unless it's the last line
line_end = ',' if i + 3 < n_frames else ''
print(f" {formatted_hashes}{line_end}")
print("};")
print("", file=sys.stderr)
+157
View File
@@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------
#
# Copyright (C) 2023 The Khronos Group Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-------------------------------------------------------------------------
#
# Generate MD5 checksums from video frames using ffmpeg.
#
# This script uses ffmpeg's framemd5 muxer to calculate MD5 checksums
# for each frame. This provides an alternative to the Fraunhofer reference
# decoder approach used in frame_checksums.py.
#
# Usage:
# python frame_checksums_ffmpeg.py <video_file>
#
# Example:
# python frame_checksums_ffmpeg.py clip-a.h264
#
# Requirements:
# - ffmpeg must be installed and available in PATH
#
# The script outputs MD5 checksums in C array format, matching the style
# used in vktVideoClipInfo.cpp (3 checksums per line).
#
import sys
import subprocess
import os
def print_help():
help_text = """Usage: frame_checksums_ffmpeg.py [OPTIONS] videoFile
Generate MD5 checksums from video frames using ffmpeg in C array format.
Arguments:
videoFile Video file to process (H.264, H.265, etc.)
Options:
-a NAME C array name (default: frameChecksums)
-n NUM Process only first NUM frames
-h, --help Show this help message and exit
Requirements:
- ffmpeg must be installed and available in PATH
Examples:
python frame_checksums_ffmpeg.py clip-a.h264
"""
print(help_text)
sys.exit(0)
# Parse command line arguments
video_filename = None
array_name = "frameChecksums"
frame_limit = None
i = 1
while i < len(sys.argv):
if sys.argv[i] in ('-h', '--help'):
print_help()
elif sys.argv[i] == '-n' and i + 1 < len(sys.argv):
frame_limit = int(sys.argv[i + 1])
i += 2
elif sys.argv[i] == '-a' and i + 1 < len(sys.argv):
array_name = sys.argv[i + 1]
i += 2
elif video_filename is None:
video_filename = sys.argv[i]
i += 1
else:
i += 1
if video_filename is None:
print("Usage: frame_checksums_ffmpeg.py [OPTIONS] videoFile")
print("Use -h or --help for more information")
sys.exit(1)
if not os.path.exists(video_filename):
print(f"Error: File '{video_filename}' not found", file=sys.stderr)
sys.exit(1)
try:
# Use ffmpeg to generate frame MD5 checksums
# The -f framemd5 output format generates MD5 for each frame
# Output to stdout (-) so we can parse it directly
cmd = [
'ffmpeg',
'-i', video_filename,
]
# Add frame limit if specified
if frame_limit is not None:
cmd.extend(['-vframes', str(frame_limit)])
cmd.extend(['-f', 'framemd5', '-'])
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
# Parse the framemd5 output
# Format is: stream#, frame#, pts, duration, size, md5
# Example: 0, 0, 0, 1, 38016, 6b5e29f8f5f4e3d4f8c9e7b8a4d6c3f2
md5_hashes = []
for line in result.stdout.split('\n'):
line = line.strip()
# Skip comments and empty lines
if not line or line.startswith('#'):
continue
# Parse the line and extract the MD5 (last field)
parts = line.split(',')
if len(parts) >= 6:
md5_hash = parts[-1].strip()
md5_hashes.append(md5_hash)
frame_count = len(md5_hashes)
print(f"Computing checksums for {frame_count} frames", file=sys.stderr)
# Output in C array format (3 hashes per line)
print(f"static const char *{array_name}[{frame_count}] = {{")
for i in range(0, frame_count, 3):
# Get up to 3 hashes for this line
line_hashes = md5_hashes[i:i+3]
formatted_hashes = ', '.join(f'"{h}"' for h in line_hashes)
# Add comma after line unless it's the last line
line_end = ',' if i + 3 < frame_count else ''
print(f" {formatted_hashes}{line_end}")
print("};")
print(f"", file=sys.stderr)
except subprocess.CalledProcessError as e:
print(f"Error running ffmpeg: {e}", file=sys.stderr)
if e.stderr:
print(f"ffmpeg stderr: {e.stderr}", file=sys.stderr)
sys.exit(1)
except FileNotFoundError:
print("Error: ffmpeg not found. Please install ffmpeg.", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Error processing video: {e}", file=sys.stderr)
sys.exit(1)