| # RTC frame size variation analyzer |
| # Usage: |
| # 1. Config with "-DCONFIG_OUTPUT_FRAME_SIZE=1". |
| # 2. Build aomenc. Encode a file, and generate output file: frame_sizes.csv |
| # 3. Run: python ./frame_size.py frame_sizes.csv target-bitrate fps |
| # Where target-bitrate: Bitrate (kbps), and fps is frame per second. |
| # Example: python ../aom/tools/frame_size_variation_analyzer.py frame_sizes.csv |
| # 1000 30 |
| |
| import numpy as np |
| import csv |
| import sys |
| import matplotlib.pyplot as plt |
| |
| # return the moving average |
| def moving_average(x, w): |
| return np.convolve(x, np.ones(w), 'valid') / w |
| |
| def frame_size_analysis(filename, target_br, fps): |
| tbr = target_br * 1000 / fps |
| |
| with open(filename, 'r') as infile: |
| raw_data = list(csv.reader(infile, delimiter=',')) |
| |
| data = np.array(raw_data).astype(float) |
| fsize = data[:, 0].astype(float) # frame size |
| qindex = data[:, 1].astype(float) # qindex |
| |
| # Frame bit rate mismatch |
| mismatch = np.absolute(fsize - np.full(fsize.size, tbr)) |
| |
| # Count how many frames are more than 2.5x of frame target bit rate. |
| tbr_thr = tbr * 2.5 |
| cnt = 0 |
| idx = np.arange(fsize.size) |
| for i in idx: |
| if fsize[i] > tbr_thr: |
| cnt = cnt + 1 |
| |
| # Use the 15-frame moving window |
| win = 15 |
| avg_fsize = moving_average(fsize, win) |
| win_mismatch = np.absolute(avg_fsize - np.full(avg_fsize.size, tbr)) |
| |
| print('[Target frame rate (bit)]:', "%.2f"%tbr) |
| print('[Average frame rate (bit)]:', "%.2f"%np.average(fsize)) |
| print('[Frame rate standard deviation]:', "%.2f"%np.std(fsize)) |
| print('[Max/min frame rate (bit)]:', "%.2f"%np.max(fsize), '/', "%.2f"%np.min(fsize)) |
| print('[Average frame rate mismatch (bit)]:', "%.2f"%np.average(mismatch)) |
| print('[Number of frames (frame rate > 2.5x of target frame rate)]:', cnt) |
| print(' Moving window size:', win) |
| print('[Moving average frame rate mismatch (bit)]:', "%.2f"%np.average(win_mismatch)) |
| print('------------------------------') |
| |
| figure, axis = plt.subplots(2) |
| x = np.arange(fsize.size) |
| axis[0].plot(x, fsize, color='blue') |
| axis[0].set_title("frame sizes") |
| axis[1].plot(x, qindex, color='blue') |
| axis[1].set_title("frame qindex") |
| plt.tight_layout() |
| |
| # Save the plot |
| plotname = filename + '.png' |
| plt.savefig(plotname) |
| plt.show() |
| |
| if __name__ == '__main__': |
| if (len(sys.argv) < 4): |
| print(sys.argv[0], 'input_file, target_bitrate, fps') |
| sys.exit() |
| target_br = int(sys.argv[2]) |
| fps = int(sys.argv[3]) |
| frame_size_analysis(sys.argv[1], target_br, fps) |