2024-01-09 20:47:16 -05:00
# Copyright (c) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
2023-12-05 05:43:33 -08:00
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from datetime import datetime
from subprocess import Popen , PIPE
import argparse
import os
import shutil
import sys
import platform
import glob
import pandas as pd
from pathlib import Path
__license__ = " MIT "
__version__ = " 1.0 "
__status__ = " Shipping "
def shell ( cmd ) :
p = Popen ( cmd , shell = True , stdout = PIPE , stderr = PIPE )
output = p . communicate ( ) [ 0 ] [ 0 : - 1 ]
return output
def write_formatted ( output , f ) :
f . write ( " ```` \n " )
f . write ( " %s \n \n " % output )
f . write ( " ```` \n " )
def strip_libtree_addresses ( lib_tree ) :
return lib_tree
def iter_files ( path ) :
2024-08-22 10:04:58 -04:00
file_list = path . rglob ( ' * ' )
sorted_file_list = sorted ( file_list )
for item in sorted_file_list :
if item . is_file ( ) :
yield item
2024-08-27 21:39:43 -04:00
def print_bitrate ( current_file ) :
file_name = str ( current_file )
mbps_pos = file_name . find ( " mbps " )
if ( mbps_pos != - 1 ) :
fps_pos = file_name . find ( " fps_ " )
if ( fps_pos != - 1 ) :
bit_rate = file_name [ fps_pos + 4 : mbps_pos ]
else :
bit_rate = " n/a "
else :
bit_rate = " n/a "
orig_stdout = sys . stdout
sys . stdout = open ( resultsPath + ' /rocDecode_output.log ' , ' a ' )
print ( " Bitrate: " , bit_rate )
sys . stdout = orig_stdout
2023-12-05 05:43:33 -08:00
# Import arguments
parser = argparse . ArgumentParser ( )
parser . add_argument ( ' --rocDecode_directory ' , type = str , default = ' ' ,
2023-12-12 07:34:31 -08:00
help = ' The rocDecode Directory - required ' )
2023-12-05 05:43:33 -08:00
parser . add_argument ( ' --gpu_device_id ' , type = int , default = 0 ,
help = ' The GPU device ID that will be used to run the test on it - optional (default:0 [range:0 - N-1] N = total number of available GPUs on a machine) ' )
parser . add_argument ( ' --files_directory ' , type = str , default = ' ' ,
help = ' The path to a dirctory containing one or more supported files for decoding (e.g., mp4, mov, etc.) - required ' )
parser . add_argument ( ' --sample_mode ' , type = int , default = 0 ,
help = ' The sample to run - optional (default:0 [range:0-1] 0: videoDecode, 1: videoDecodePerf) ' )
2024-08-12 09:39:43 -04:00
parser . add_argument ( ' --num_threads ' , type = int , default = 1 ,
help = ' The number of threads is only for the videoDecodePerf sample (sample_mode = 1) - optional (default:1) ' )
parser . add_argument ( ' --max_num_decoded_frames ' , type = int , default = 0 ,
help = ' The max number of decoded frames. Useful for partial decoding of a long stream. - optional (default:0, meaning no limit) ' )
2023-12-05 05:43:33 -08:00
args = parser . parse_args ( )
rocDecodeDirectory = args . rocDecode_directory
gpuDeviceID = args . gpu_device_id
filesDir = args . files_directory
filesDirPath = Path ( filesDir )
sampleMode = args . sample_mode
numThreads = args . num_threads
2024-08-12 09:39:43 -04:00
maxNumFrames = args . max_num_decoded_frames
2023-12-05 05:43:33 -08:00
print ( " \n runrocDecodeTests V " + __version__ + " \n " )
# rocDecode Application
scriptPath = os . path . dirname ( os . path . realpath ( __file__ ) )
if sampleMode == 0 :
rocDecode_exe = rocDecodeDirectory + ' /samples/videoDecode/build/videodecode '
resultsPath = scriptPath + ' /rocDecode_videoDecode_results '
elif sampleMode == 1 :
rocDecode_exe = rocDecodeDirectory + ' /samples/videoDecodePerf/build/videodecodeperf '
resultsPath = scriptPath + ' /rocDecode_videoDecodePerf_results '
run_rocDecode_app = os . path . abspath ( rocDecode_exe )
os . system ( ' (mkdir -p ' + resultsPath + ' ) ' )
if ( os . path . isfile ( run_rocDecode_app ) ) :
print ( " STATUS: rocDecode path - " + run_rocDecode_app + " \n " )
else :
print ( " \n ERROR: rocDecode Executable Not Found \n " )
exit ( )
2023-12-12 07:34:31 -08:00
if os . path . exists ( filesDir ) and not os . path . isfile ( filesDir ) :
# Checking if the directory is empty or not
if not os . listdir ( filesDir ) :
print ( " \n ERROR: Empty directory - no videos to decode " )
exit ( )
else :
print ( " \n ERROR: The input directory path is either for a file or directory does not exist! " )
exit ( )
2023-12-05 05:43:33 -08:00
# Get cwd
cwd = os . getcwd ( )
if os . path . exists ( resultsPath + ' /rocDecode_output.log ' ) :
os . remove ( resultsPath + ' /rocDecode_output.log ' )
if os . path . exists ( resultsPath + ' /rocDecode_test_results.csv ' ) :
os . remove ( resultsPath + ' /rocDecode_test_results.csv ' )
if sampleMode == 0 :
for current_file in iter_files ( filesDirPath ) :
2024-08-27 21:39:43 -04:00
print_bitrate ( current_file )
2024-08-12 09:39:43 -04:00
os . system ( run_rocDecode_app + ' -i ' + str ( current_file ) + ' -d ' + str ( gpuDeviceID ) + ' -f ' + str ( maxNumFrames ) + ' | tee -a ' + resultsPath + ' /rocDecode_output.log ' )
2023-12-05 05:43:33 -08:00
print ( " \n \n " )
orig_stdout = sys . stdout
sys . stdout = open ( resultsPath + ' /rocDecode_test_results.csv ' , ' a ' )
2024-09-16 15:27:10 -04:00
echo_1 = ' File Name, Codec, Video Size, Bit Depth, Bit rate (Mb/s), Total Frames, Average decoding time per frame (ms), Avg FPS '
2023-12-05 05:43:33 -08:00
print ( echo_1 )
sys . stdout = orig_stdout
2024-08-27 21:39:43 -04:00
runAwk_csv = r ''' awk ' /Bitrate: / { bitRate=$2; next}
/info: Input file: / { filename=$4; next}
2023-12-05 05:43:33 -08:00
/info: Using GPU device 0 - AMD Radeon Graphics[gfx1030] on PCI bus 0d:00.0/ {next}
/info: decoding started, please wait!/ {next}
/Input Video Information/ {next}
/ \ tCodec : / { codec=$3; next}
/ \ tSequence : / {next}
/ \ tCoded size : / {next}
/ \ tDisplay area : / {next}
/ \ tChroma : / {next}
/ \ tBit depth : / { bitDepth=$4; next}
/Video Decoding Params:/ {next}
/ \ tNum Surfaces : / {next}
/ \ tCrop : / {next}
2024-08-27 21:39:43 -04:00
/ \ tResize : / { videoSize=$3; next}
2023-12-05 05:43:33 -08:00
/^$/ {next}
2024-08-20 17:43:33 -04:00
/info: Total pictures decoded: / { totalFrames=$5; next}
/info: avg decoding time per picture: / { timePerFrame=$7; next}
2024-08-27 21:39:43 -04:00
/info: avg decode FPS: / { printf( " %s , %s , %s , %d , %s , %d , %f , %f \ n " , filename, codec, videoSize, bitDepth, bitRate, totalFrames, timePerFrame, $5) } ' rocDecode_videoDecode_results/rocDecode_output.log >> rocDecode_videoDecode_results/rocDecode_test_results.csv '''
2023-12-05 05:43:33 -08:00
os . system ( runAwk_csv )
elif sampleMode == 1 :
for current_file in iter_files ( filesDirPath ) :
2024-08-27 21:39:43 -04:00
print_bitrate ( current_file )
2024-08-12 09:39:43 -04:00
os . system ( run_rocDecode_app + ' -i ' + str ( current_file ) + ' -t ' + str ( numThreads ) + ' -f ' + str ( maxNumFrames ) + ' | tee -a ' + resultsPath + ' /rocDecode_output.log ' )
2023-12-05 05:43:33 -08:00
print ( " \n \n " )
orig_stdout = sys . stdout
sys . stdout = open ( resultsPath + ' /rocDecode_test_results.csv ' , ' a ' )
2024-09-16 15:27:10 -04:00
echo_1 = ' File Name, Num Threads, Codec, Video Size, Bit Depth, Bit rate (Mb/s), Total Frames, Average decoding time per frame (ms), Avg FPS '
2023-12-05 05:43:33 -08:00
print ( echo_1 )
sys . stdout = orig_stdout
2024-08-27 21:39:43 -04:00
runAwk_csv = r ''' awk ' /Bitrate: / { bitRate=$2; next}
/info: Input file: / { filename=$4; next}
2023-12-05 05:43:33 -08:00
/info: Number of threads: / { numThreads=$5; next}
/info: Using GPU device 0 - AMD Radeon Graphics[gfx1030] on PCI bus 0d:00.0/ {next}
/info: decoding started, please wait!/ {next}
/Input Video Information/ {next}
/ \ tCodec : / { codec=$3; next}
/ \ tSequence : / {next}
/ \ tCoded size : / {next}
/ \ tDisplay area : / {next}
/ \ tChroma : / {next}
/ \ tBit depth : / { bitDepth=$4; next}
/Video Decoding Params:/ {next}
/ \ tNum Surfaces : / {next}
/ \ tCrop : / {next}
2024-08-27 21:39:43 -04:00
/ \ tResize : / { videoSize=$3; next}
2023-12-05 05:43:33 -08:00
/^$/ {next}
2024-08-20 17:43:33 -04:00
/info: Total pictures decoded: / { totalFrames=$5; next}
/info: avg decoding time per picture: / { timePerFrame=$7; next}
2024-08-27 21:39:43 -04:00
/info: avg decode FPS: / { printf( " %s , %d , %s , %s , %d , %s , %d , %f , %f \ n " , filename, numThreads, codec, videoSize, bitDepth, bitRate, totalFrames, timePerFrame, $5) } ' rocDecode_videoDecodePerf_results/rocDecode_output.log >> rocDecode_videoDecodePerf_results/rocDecode_test_results.csv '''
2023-12-05 05:43:33 -08:00
sys . stdout = orig_stdout
os . system ( runAwk_csv )
# get data
platform_name = platform . platform ( )
platform_name_fq = shell ( ' hostname --all-fqdns ' )
platform_ip = shell ( ' hostname -I ' ) [ 0 : - 1 ] # extra trailing space
file_dtstr = datetime . now ( ) . strftime ( " % Y % m %d " )
reportFilename = ' rocDecode_report_ %s _ %s .md ' % ( platform_name , file_dtstr )
report_dtstr = datetime . now ( ) . strftime ( " % Y- % m- %d % H: % M: % S % Z " )
sys_info = shell ( ' inxi -c0 -S ' )
cpu_info = shell ( ' inxi -c0 -C ' )
gpu_info = shell ( ' inxi -c0 -G ' )
memory_info = shell ( ' inxi -c 0 -m ' )
board_info = shell ( ' inxi -c0 -M ' )
lib_tree = shell ( ' ldd ' + run_rocDecode_app )
lib_tree = strip_libtree_addresses ( lib_tree )
# Load the data
df = pd . read_csv ( resultsPath + ' /rocDecode_test_results.csv ' )
# Generate the markdown table
print ( df . to_markdown ( index = False ) )
# Write Report
with open ( reportFilename , ' w ' ) as f :
f . write ( " rocDecode app report \n " )
f . write ( " ================================ \n " )
f . write ( " \n " )
f . write ( " Generated: %s \n " % report_dtstr )
f . write ( " \n " )
f . write ( " Platform: %s ( %s ) \n " % ( platform_name_fq , platform_ip ) )
f . write ( " -------- \n " )
f . write ( " \n " )
write_formatted ( sys_info , f )
write_formatted ( cpu_info , f )
write_formatted ( gpu_info , f )
write_formatted ( board_info , f )
write_formatted ( memory_info , f )
f . write ( " \n \n Benchmark Report \n " )
f . write ( " -------- \n " )
f . write ( " \n " )
f . write ( " \n " )
f . write ( df . to_markdown ( index = False ) )
f . write ( " \n " )
f . write ( " \n " )
f . write ( " Dynamic Libraries Report \n " )
f . write ( " ----------------- \n " )
f . write ( " \n " )
write_formatted ( lib_tree , f )
f . write ( " \n " )
f . write (
2024-01-09 20:47:16 -05:00
" \n \n --- \n **Copyright (c) 2023 - 2024 AMD ROCm rocDecode app -- run_rocDecode_tests.py V- " + __version__ + " ** \n " )
2023-12-05 05:43:33 -08:00
f . write ( " \n " )
# report file
reportFileDir = os . path . abspath ( reportFilename )
print ( " \n STATUS: Output Report File - " + reportFileDir )
print ( " \n run_rocDecode_tests.py completed - V " + __version__ + " \n " )