yes
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user