diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_tools/compare_videos.py | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_tools/compare_videos.py')
-rwxr-xr-x | third_party/libwebrtc/rtc_tools/compare_videos.py | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_tools/compare_videos.py b/third_party/libwebrtc/rtc_tools/compare_videos.py new file mode 100755 index 0000000000..a54eb42979 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/compare_videos.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import json +import optparse +import os +import shutil +import subprocess +import sys +import tempfile + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Chrome browsertests will throw away stderr; avoid that output gets lost. +sys.stderr = sys.stdout + + +def _ParseArgs(): + """Registers the command-line options.""" + usage = 'usage: %prog [options]' + parser = optparse.OptionParser(usage=usage) + + parser.add_option('--label', + type='string', + default='MY_TEST', + help=('Label of the test, used to identify different ' + 'tests. Default: %default')) + parser.add_option('--ref_video', + type='string', + help='Reference video to compare with (YUV).') + parser.add_option('--test_video', + type='string', + help=('Test video to be compared with the reference ' + 'video (YUV).')) + parser.add_option('--frame_analyzer', + type='string', + help='Path to the frame analyzer executable.') + parser.add_option('--aligned_output_file', + type='string', + help='Path for output aligned YUV or Y4M file.') + parser.add_option('--vmaf', type='string', help='Path to VMAF executable.') + parser.add_option('--vmaf_model', + type='string', + help='Path to VMAF model.') + parser.add_option('--vmaf_phone_model', + action='store_true', + help='Whether to use phone model in VMAF.') + parser.add_option( + '--yuv_frame_width', + type='int', + default=640, + help='Width of the YUV file\'s frames. Default: %default') + parser.add_option( + '--yuv_frame_height', + type='int', + default=480, + help='Height of the YUV file\'s frames. Default: %default') + parser.add_option('--chartjson_result_file', + type='str', + default=None, + help='Where to store perf results in chartjson format.') + options, _ = parser.parse_args() + + if not options.ref_video: + parser.error('You must provide a path to the reference video!') + if not os.path.exists(options.ref_video): + parser.error('Cannot find the reference video at %s' % + options.ref_video) + + if not options.test_video: + parser.error('You must provide a path to the test video!') + if not os.path.exists(options.test_video): + parser.error('Cannot find the test video at %s' % options.test_video) + + if not options.frame_analyzer: + parser.error( + 'You must provide the path to the frame analyzer executable!') + if not os.path.exists(options.frame_analyzer): + parser.error('Cannot find frame analyzer executable at %s!' % + options.frame_analyzer) + + if options.vmaf and not options.vmaf_model: + parser.error('You must provide a path to a VMAF model to use VMAF.') + + return options + + +def _DevNull(): + """On Windows, sometimes the inherited stdin handle from the parent process + fails. Workaround this by passing null to stdin to the subprocesses commands. + This function can be used to create the null file handler. + """ + return open(os.devnull, 'r') + + +def _RunFrameAnalyzer(options, yuv_directory=None): + """Run frame analyzer to compare the videos and print output.""" + cmd = [ + options.frame_analyzer, + '--label=%s' % options.label, + '--reference_file=%s' % options.ref_video, + '--test_file=%s' % options.test_video, + '--width=%d' % options.yuv_frame_width, + '--height=%d' % options.yuv_frame_height, + ] + if options.chartjson_result_file: + cmd.append('--chartjson_result_file=%s' % + options.chartjson_result_file) + if options.aligned_output_file: + cmd.append('--aligned_output_file=%s' % options.aligned_output_file) + if yuv_directory: + cmd.append('--yuv_directory=%s' % yuv_directory) + frame_analyzer = subprocess.Popen(cmd, + stdin=_DevNull(), + stdout=sys.stdout, + stderr=sys.stderr) + frame_analyzer.wait() + if frame_analyzer.returncode != 0: + print('Failed to run frame analyzer.') + return frame_analyzer.returncode + + +def _RunVmaf(options, yuv_directory, logfile): + """ Run VMAF to compare videos and print output. + + The yuv_directory is assumed to have been populated with a reference and test + video in .yuv format, with names according to the label. + """ + cmd = [ + options.vmaf, + 'yuv420p', + str(options.yuv_frame_width), + str(options.yuv_frame_height), + os.path.join(yuv_directory, "ref.yuv"), + os.path.join(yuv_directory, "test.yuv"), + options.vmaf_model, + '--log', + logfile, + '--log-fmt', + 'json', + ] + if options.vmaf_phone_model: + cmd.append('--phone-model') + + vmaf = subprocess.Popen(cmd, + stdin=_DevNull(), + stdout=sys.stdout, + stderr=sys.stderr) + vmaf.wait() + if vmaf.returncode != 0: + print('Failed to run VMAF.') + return 1 + + # Read per-frame scores from VMAF output and print. + with open(logfile) as f: + vmaf_data = json.load(f) + vmaf_scores = [] + for frame in vmaf_data['frames']: + vmaf_scores.append(frame['metrics']['vmaf']) + print('RESULT VMAF: %s=' % options.label, vmaf_scores) + + return 0 + + +def main(): + """The main function. + + A simple invocation is: + ./webrtc/rtc_tools/compare_videos.py + --ref_video=<path_and_name_of_reference_video> + --test_video=<path_and_name_of_test_video> + --frame_analyzer=<path_and_name_of_the_frame_analyzer_executable> + + Running vmaf requires the following arguments: + --vmaf, --vmaf_model, --yuv_frame_width, --yuv_frame_height + """ + options = _ParseArgs() + + if options.vmaf: + try: + # Directory to save temporary YUV files for VMAF in frame_analyzer. + yuv_directory = tempfile.mkdtemp() + _, vmaf_logfile = tempfile.mkstemp() + + # Run frame analyzer to compare the videos and print output. + if _RunFrameAnalyzer(options, yuv_directory=yuv_directory) != 0: + return 1 + + # Run VMAF for further video comparison and print output. + return _RunVmaf(options, yuv_directory, vmaf_logfile) + finally: + shutil.rmtree(yuv_directory) + os.remove(vmaf_logfile) + else: + return _RunFrameAnalyzer(options) + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) |