import re
import matplotlib.pyplot as plt
from datetime import datetime
import os
import shutil
# 设置序号常量
SEQUENCE_NUMBER = "static-change-20fps-20I-1500k-0ms-000-0k-2s-q250" # FPS-I_ratio-bandwidth-delay-loss-burst-
# SEQUENCE_NUMBER = "dynamic-change-20fps-20I-2000k-0ms-000-0k-2s" # FPS-I_ratio-bandwidth-delay-loss-burst
# SEQUENCE_NUMBER = "static-original-20fps-20I-1500k-0ms-000-0k-2s-q250" # FPS-I_ratio-bandwidth-delay-loss-burst-
# ======== 帧图表局部视图坐标范围参数设置 ========
FRAME_LOCAL_X_MIN = 0 # 局部视图X轴最小值
FRAME_LOCAL_X_MAX = None # 局部视图X轴最大值
TIME_X_MIN = 0
TIME_X_MAX = None
TIME_RANGE_START = 0 # 积分计算起始时间
TIME_RANGE_END = 240 # 积分计算结束时间(单位:秒)
PLOT_ACK_BITRATE = True # 是否绘制ACK比特率
def create_sequence_folder():
"""
创建序号命名的文件夹,如果不存在则创建
"""
folder_name = f"{SEQUENCE_NUMBER}"
if not os.path.exists(folder_name):
os.makedirs(folder_name)
print(f"Created folder: {folder_name}")
else:
print(f"Folder already exists: {folder_name}")
return folder_name
def parse_sender_log(filename):
"""
解析sender.log文件, 提取时间戳、比特率、丢包率、T、gamma和RTT
"""
timestamps = []
bitrates = []
loss_timestamps = []
loss_rates = []
t_timestamps = []
t_values = []
gamma_values = []
rtt_timestamps = []
rtt_values = []
frame_timestamps = [] # 新增:存储帧时间戳
frame_ids = [] # 新增:存储帧ID
frame_sizes = [] # 新增:存储帧大小
loss_bitrate_timestamps = []
loss_bitrates = []
delay_bitrate_timestamps = []
delay_bitrates = []
ack_bitrate_timestamps = []
ack_bitrates = []
delta_timestamps = []
send_deltas = []
arrival_deltas = []
delay_deltas = [] # 存储计算出的delay_delta值
# 正则表达式匹配sender日志格式
bitrate_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*sender change bitrate, bitrate = (\d+)bps'
loss_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*fraction_loss = (\d+), packets_num = \d+'
t_gamma_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*T = ([\d.]+), gamma = ([\d.]+)'
rtt_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*razor sender rtt = (\d+)ms'
frame_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*frame id\s*=\s*(\d+),\s*frame size\s*=\s*(\d+)' # 新增帧数据匹配
loss_bitrate_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*sender_estimation_update.*new_loss_bitrate = (\d+)'
delay_bitrate_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*sender_estimation_update_delay_base, bitrate = (\d+)'
ack_bitrate_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*input->incoming_bitrate = (\d+)'
delta_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*send_delta = (\d+), arrival_delta = (\d+)'
try:
with open(filename, 'r', encoding='utf-8') as file:
for line in file:
# 匹配比特率信息
bitrate_match = re.search(bitrate_pattern, line)
if bitrate_match:
timestamp_str = bitrate_match.group(1)
bitrate_bps = int(bitrate_match.group(2))
# 解析时间戳
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
# 转换为kbps
bitrate_kbps = bitrate_bps / 1000
timestamps.append(timestamp)
bitrates.append(bitrate_kbps)
# 匹配丢包率信息
loss_match = re.search(loss_pattern, line)
if loss_match:
timestamp_str = loss_match.group(1)
fraction_loss = int(loss_match.group(2))
# 解析时间戳
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
# 计算丢包率百分比 (fraction_loss / 256 * 100)
# print(f"line: {line}, fraction_lost: {fraction_loss}");
loss_percentage = (fraction_loss / 256) * 100
loss_timestamps.append(timestamp)
loss_rates.append(loss_percentage)
# 匹配T和gamma信息
t_gamma_match = re.search(t_gamma_pattern, line)
if t_gamma_match:
timestamp_str = t_gamma_match.group(1)
t_value = float(t_gamma_match.group(2))
gamma_value = float(t_gamma_match.group(3))
# 解析时间戳
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
t_timestamps.append(timestamp)
t_values.append(t_value)
gamma_values.append(gamma_value)
# 匹配RTT信息
rtt_match = re.search(rtt_pattern, line)
if rtt_match:
timestamp_str = rtt_match.group(1)
rtt_ms = int(rtt_match.group(2))
# 解析时间戳
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
rtt_timestamps.append(timestamp)
rtt_values.append(rtt_ms)
# 新增:匹配帧数据(无需时间戳)
frame_match = re.search(frame_pattern, line)
if frame_match:
timestamp_str = frame_match.group(1) # 提取时间戳
frame_id = int(frame_match.group(2))
frame_size = int(frame_match.group(3))
# 解析时间戳
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
frame_timestamps.append(timestamp)
frame_ids.append(frame_id)
frame_sizes.append(frame_size)
# if frame_id < 100:
# print(f"frame_id:{frame_id}, frame_size:{frame_size}")
# 匹配loss-based比特率
loss_bitrate_match = re.search(loss_bitrate_pattern, line)
if loss_bitrate_match:
timestamp_str = loss_bitrate_match.group(1)
bitrate_bps = int(loss_bitrate_match.group(2))
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
loss_bitrate_kbps = bitrate_bps / 1000
loss_bitrate_timestamps.append(timestamp)
loss_bitrates.append(loss_bitrate_kbps)
# 匹配delay-based比特率
delay_bitrate_match = re.search(delay_bitrate_pattern, line)
if delay_bitrate_match:
timestamp_str = delay_bitrate_match.group(1)
bitrate_bps = int(delay_bitrate_match.group(2))
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
delay_bitrate_kbps = bitrate_bps / 1000
delay_bitrate_timestamps.append(timestamp)
delay_bitrates.append(delay_bitrate_kbps)
# 匹配ACK比特率信息
ack_match = re.search(ack_bitrate_pattern, line)
if ack_match:
timestamp_str = ack_match.group(1)
bitrate_bps = int(ack_match.group(2))
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
bitrate_kbps = bitrate_bps / 1000
ack_bitrate_timestamps.append(timestamp)
ack_bitrates.append(bitrate_kbps)
# 匹配send_delta和arrival_delta信息
delta_match = re.search(delta_pattern, line)
if delta_match:
timestamp_str = delta_match.group(1)
send_delta_val = int(delta_match.group(2))
arrival_delta_val = int(delta_match.group(3))
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
# 计算delay_delta
delay_delta_val = arrival_delta_val - send_delta_val
delta_timestamps.append(timestamp)
send_deltas.append(send_delta_val)
arrival_deltas.append(arrival_delta_val)
delay_deltas.append(delay_delta_val)
return (timestamps, bitrates, loss_timestamps, loss_rates, t_timestamps, t_values, gamma_values, rtt_timestamps, rtt_values,
frame_timestamps, frame_ids, frame_sizes, loss_bitrate_timestamps, loss_bitrates, delay_bitrate_timestamps, delay_bitrates,
ack_bitrate_timestamps, ack_bitrates, delta_timestamps, delay_deltas)
except FileNotFoundError:
print(f"Error: File '{filename}' not found.")
return [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []
except Exception as e:
print(f"Error reading file: {e}")
return [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []
def parse_bandwidth_log(filename, base_time):
"""
解析bandwidth.log文件, 提取时间戳和带宽
base_time: 基准时间,用于计算相对时间
"""
timestamps = []
bandwidths = []
config_lines = []
# 正则表达式匹配bandwidth日志格式
pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*bandwidth=([\d.]+)kbps'
try:
with open(filename, 'r', encoding='utf-8') as file:
lines = file.readlines()
# 提取前8行的配置信息
for i in range(min(8, len(lines))):
line = lines[i].strip()
if line.startswith('# bandwidth:') or line.startswith('# delay:') or line.startswith('# burst:'):
config_lines.append(line)
# 继续处理所有行的数据
for line in lines:
match = re.search(pattern, line)
if match:
timestamp_str = match.group(1)
bandwidth_kbps = float(match.group(2))
# 解析时间戳
timestamp = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
# 计算相对时间(秒)
relative_time = (timestamp - base_time).total_seconds()
timestamps.append(relative_time)
bandwidths.append(bandwidth_kbps)
return timestamps, bandwidths, config_lines
except FileNotFoundError:
print(f"Error: File '{filename}' not found.")
return [], [], []
except Exception as e:
print(f"Error reading file: {e}")
return [], [], []
def calculate_bandwidth_utilization(times, bitrates, bandwidth_times, bandwidth_values, start_time, end_time):
"""
计算带宽利用率
:param times: 发送比特率时间序列
:param bitrates: 发送比特率值序列
:param bandwidth_times: 带宽时间序列
:param bandwidth_values: 带宽值序列
:param start_time: 积分起始时间
:param end_time: 积分结束时间
:return: 带宽利用率百分比(float)
"""
# 计算发送比特率在时间区间内的积分(梯形法)
sender_integral = 0
prev_t, prev_v = None, None
for t, v in zip(times, bitrates):
if start_time <= t <= end_time:
if prev_t is not None:
dt = t - prev_t
avg_bitrate = (prev_v + v) / 2
sender_integral += dt * avg_bitrate
prev_t, prev_v = t, v
# 计算带宽在时间区间内的积分
bw_integral = 0
prev_t, prev_v = None, None
for t, v in zip(bandwidth_times, bandwidth_values):
if start_time <= t <= end_time:
if prev_t is not None:
dt = t - prev_t
avg_bw = (prev_v + v) / 2
bw_integral += dt * avg_bw
prev_t, prev_v = t, v
# 计算利用率百分比
if bw_integral > 0:
utilization = (sender_integral / bw_integral) * 100
else:
utilization = 0
return utilization
def plot_bitrate_bandwidth(sender_timestamps, sender_bitrates,
bandwidth_timestamps, bandwidth_bandwidths,
config_lines, output_filename):
"""
绘制比特率和带宽随时间变化的图表
"""
if not sender_timestamps and not bandwidth_timestamps:
print("No bitrate and bandwidth data to plot.")
return
# 计算带宽利用率
utilization = calculate_bandwidth_utilization(
sender_timestamps, sender_bitrates,
bandwidth_timestamps, bandwidth_bandwidths,
TIME_RANGE_START, TIME_RANGE_END
)
# 创建图表
plt.figure(figsize=(12, 6))
# 绘制比特率曲线
if sender_timestamps:
plt.plot(sender_timestamps, sender_bitrates, 'b-', linewidth=1.5, label='Bitrate')
# 绘制带宽曲线
if bandwidth_timestamps:
plt.plot(bandwidth_timestamps, bandwidth_bandwidths, 'r-', linewidth=1.5, label='Bandwidth')
plt.xlabel('Time (s)')
plt.ylabel('Rate (kbps)')
plt.title('Bitrate and Bandwidth over Time')
plt.grid(True, alpha=0.3)
plt.legend()
plt.ticklabel_format(style='plain', axis='y')
# 添加带宽利用率信息
utilization_text = f"Bandwidth Utilization ({TIME_RANGE_START}-{TIME_RANGE_END}s): {utilization:.2f}%"
plt.annotate(utilization_text, xy=(0.98, 0.02), xycoords='axes fraction',
ha='right', va='bottom', fontsize=10,
bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="gray", alpha=0.8))
# 在图片正上方添加配置信息
if config_lines:
# 合并三行配置信息为一行
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
# 自动调整布局,为顶部标题留出空间
plt.tight_layout(rect=[0, 0, 1, 0.96])
# 保存图片
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Bitrate/Bandwidth plot saved as: {output_filename}")
plt.close()
print(f"Bandwidth Utilization: {utilization:.2f}%") # 控制台输出利用率
def plot_loss(loss_timestamps, loss_rates, config_lines, output_filename):
"""
绘制丢包率随时间变化的图表
"""
if not loss_timestamps:
print("No loss data to plot.")
return
# 创建图表
plt.figure(figsize=(12, 6))
# 绘制丢包率曲线
plt.plot(loss_timestamps, loss_rates, 'g-', linewidth=1.5, label='Packet Loss')
plt.xlabel('Time (s)')
plt.ylabel('Packet Loss (%)')
plt.title('Packet Loss over Time')
plt.grid(True, alpha=0.3)
plt.legend()
# 在图片正上方添加配置信息
if config_lines:
# 合并三行配置信息为一行
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
# 自动调整布局,为顶部标题留出空间
plt.tight_layout(rect=[0, 0, 1, 0.96])
# 保存图片
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Loss plot saved as: {output_filename}")
plt.close()
def plot_t_gamma(t_timestamps, t_values, gamma_values, config_lines, output_filename):
"""
绘制T、gamma和-gamma随时间变化的图表
"""
if not t_timestamps:
print("No T and gamma data to plot.")
return
# 创建图表
plt.figure(figsize=(12, 6))
# 计算-gamma值
neg_gamma_values = [-gamma for gamma in gamma_values]
# 绘制T、gamma和-gamma曲线
# 使用同一种颜色(绿色)但不同线型
plt.plot(t_timestamps, t_values, 'b-', linewidth=1.5, label='T')
plt.plot(t_timestamps, gamma_values, 'g-', linewidth=1.5, label='gamma')
plt.plot(t_timestamps, neg_gamma_values, 'g--', linewidth=1.5, label='-gamma') # 使用虚线
plt.xlabel('Time (s)')
plt.ylabel('Value')
plt.title('T, gamma and -gamma over Time')
plt.grid(True, alpha=0.3)
plt.legend()
# 在图片正上方添加配置信息
if config_lines:
# 合并三行配置信息为一行
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
# 自动调整布局,为顶部标题留出空间
plt.tight_layout(rect=[0, 0, 1, 0.96])
# 保存图片
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"T/gamma plot saved as: {output_filename}")
plt.close()
def plot_rtt(rtt_timestamps, rtt_values, config_lines, output_filename):
"""
绘制RTT随时间变化的图表
"""
if not rtt_timestamps:
print("No RTT data to plot.")
return
# 创建图表
plt.figure(figsize=(12, 6))
# 绘制RTT曲线
plt.plot(rtt_timestamps, rtt_values, 'purple', linewidth=1.5, label='RTT')
plt.xlabel('Time (s)')
plt.ylabel('RTT (ms)')
plt.title('Round Trip Time (RTT) over Time')
plt.grid(True, alpha=0.3)
plt.legend()
# 在图片正上方添加配置信息
if config_lines:
# 合并三行配置信息为一行
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
# 自动调整布局,为顶部标题留出空间
plt.tight_layout(rect=[0, 0, 1, 0.96])
# 保存图片
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"RTT plot saved as: {output_filename}")
plt.close()
# 新增帧大小绘图函数
def plot_frame_size(frame_ids, frame_sizes, config_lines, output_filename):
"""
绘制帧大小随帧ID变化的图表
"""
if not frame_ids:
print("No frame data to plot.")
return
# 创建图表
plt.figure(figsize=(12, 6))
plt.plot(frame_ids, frame_sizes, 'm-', linewidth=1.5)
plt.xlabel('Frame ID')
plt.ylabel('Frame Size (Bytes)')
plt.title('Frame Size per Frame ID')
plt.grid(True, alpha=0.3)
if FRAME_LOCAL_X_MAX != None:
plt.xlim(FRAME_LOCAL_X_MIN, FRAME_LOCAL_X_MAX)
# 在图片正上方添加配置信息
if config_lines:
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
# 自动调整布局
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Frame size plot saved as: {output_filename}")
plt.close()
# 新增复合比特率图表绘制函数
def plot_all_bitrates(sender_times, sender_bitrates,
loss_bitrate_times, loss_bitrates,
delay_bitrate_times, delay_bitrates,
ack_bitrate_times, ack_bitrates, # 新增参数
config_lines, output_filename):
"""
绘制三种比特率随时间变化的复合图表
新增: 可选绘制ACK比特率
"""
plt.figure(figsize=(12, 6))
# 绘制三种比特率曲线
if sender_times:
plt.plot(sender_times, sender_bitrates, 'b-', linewidth=1.5, label='Suggest Bitrate')
if loss_bitrate_times:
plt.plot(loss_bitrate_times, loss_bitrates, 'g-', linewidth=1.5, label='Loss Bitrate')
if delay_bitrate_times:
plt.plot(delay_bitrate_times, delay_bitrates, 'r-', linewidth=1.5, label='Delay Bitrate')
# 根据开关绘制ACK比特率
if PLOT_ACK_BITRATE and ack_bitrate_times and ack_bitrates:
plt.plot(ack_bitrate_times, ack_bitrates, 'c-', linewidth=1.5, label='ACK Bitrate') # 青色
plt.xlabel('Time (s)')
plt.ylabel('Bitrate (kbps)')
plt.title('Comparison of Bitrate Estimation Methods')
plt.grid(True, alpha=0.3)
plt.legend()
plt.ticklabel_format(style='plain', axis='y')
# 添加配置信息
if config_lines:
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Composite bitrate plot saved as: {output_filename}")
plt.close()
# 新增delay_delta绘图函数
def plot_delay_delta(timestamps, delay_deltas, config_lines, output_filename):
"""
绘制delay_delta随时间变化的图表
"""
if not timestamps:
print("No delay delta data to plot.")
return
plt.figure(figsize=(12, 6))
plt.plot(timestamps, delay_deltas, 'm-', linewidth=1.5, label='Delay Delta')
plt.xlabel('Time (s)')
plt.ylabel('Delay Delta (ms)')
plt.title('Packet Delay Variation over Time')
plt.grid(True, alpha=0.3)
plt.legend()
# 添加配置信息
if config_lines:
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
plt.suptitle(combined_config, fontsize=12, y=0.98)
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Delay delta plot saved as: {output_filename}")
plt.close()
# 新增绘图函数:比特率与帧大小随时间变化(上下子图)
def plot_bitrate_and_frame(bitrate_times, bitrates, frame_times, frame_sizes, config_lines, output_filename):
"""
绘制比特率和帧大小随时间变化的上下子图
"""
if not bitrate_times or not frame_times:
print("No valid data for bitrate and frame plot.")
return
# 创建图表(上下两个子图)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
# 上子图:比特率
ax1.plot(bitrate_times, bitrates, 'b-', linewidth=1.5)
ax1.set_ylabel('Bitrate (kbps)')
ax1.grid(True, alpha=0.3)
ax1.ticklabel_format(style='plain', axis='y')
# 下子图:帧大小
ax2.plot(frame_times, frame_sizes, 'm-', linewidth=1.5)
ax2.set_xlabel('Time (s)')
ax2.set_ylabel('Frame Size (bytes)')
ax2.grid(True, alpha=0.3)
if TIME_X_MAX != None:
for ax in [ax1, ax2]:
ax.set_xlim(TIME_X_MIN, TIME_X_MAX)
# 设置全局标题
plt.suptitle('Bitrate and Frame Size over Time', fontsize=14)
# 添加配置信息
if config_lines:
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
fig.text(0.5, 0.93, combined_config, fontsize=10, ha='center')
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Bitrate and frame size plot saved as: {output_filename}")
plt.close()
# 新增绘图函数:比特率、帧大小和gamma三子图
def plot_bitrate_frame_gamma(bitrate_times, bitrates,
frame_times, frame_sizes,
t_times, t_values, gamma_values,
config_lines, output_filename):
"""
绘制比特率、帧大小和gamma随时间变化的三子图
横坐标范围限制在10-20秒
"""
if not bitrate_times or not frame_times or not t_times:
print("No valid data for composite plot.")
return
# 创建三个子图(3行1列)
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(12, 12), sharex=True)
# 上子图:比特率
ax1.plot(bitrate_times, bitrates, 'b-', linewidth=1.5)
ax1.set_ylabel('Bitrate (kbps)')
ax1.grid(True, alpha=0.3)
ax1.ticklabel_format(style='plain', axis='y')
# 中子图:帧大小
ax2.plot(frame_times, frame_sizes, 'm-', linewidth=1.5)
ax2.set_ylabel('Frame Size (bytes)')
ax2.grid(True, alpha=0.3)
# 下子图:T、gamma和-gamma
neg_gamma_values = [-gamma for gamma in gamma_values]
ax3.plot(t_times, t_values, 'b-', linewidth=1.5, label='T')
ax3.plot(t_times, gamma_values, 'g-', linewidth=1.5, label='gamma')
ax3.plot(t_times, neg_gamma_values, 'g--', linewidth=1.5, label='-gamma')
ax3.set_xlabel('Time (s)')
ax3.set_ylabel('Value')
ax3.grid(True, alpha=0.3)
ax3.legend(loc='upper right')
# 设置所有子图的横坐标范围
if TIME_X_MAX != None:
for ax in [ax1, ax2, ax3]:
ax.set_xlim(TIME_X_MIN, TIME_X_MAX)
# 设置全局标题
plt.suptitle('Bitrate, Frame Size and Gamma', fontsize=14)
# 添加配置信息
if config_lines:
combined_config = " | ".join([line.replace("# ", "") for line in config_lines])
fig.text(0.5, 0.93, combined_config, fontsize=10, ha='center')
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.savefig(output_filename, dpi=300, bbox_inches='tight')
print(f"Composite plot saved as: {output_filename}")
plt.close()
def rename_and_move_log_files(folder_name):
"""
重命名日志文件并移动到指定文件夹,然后删除原始文件
"""
try:
if os.path.exists('sender.log'):
new_sender_name = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_sender.log")
shutil.copy2('sender.log', new_sender_name)
print(f"Sender log file moved to: {new_sender_name} and original deleted")
if os.path.exists('bandwidth.log'):
new_bandwidth_name = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_bandwidth.log")
shutil.copy2('bandwidth.log', new_bandwidth_name)
print(f"Bandwidth log file moved to: {new_bandwidth_name} and original deleted")
except Exception as e:
print(f"Error renaming and moving log files: {e}")
def extract_target_bitrate_lines(input_file, output_file):
"""
从日志文件中提取包含'target_bitrate_kbps'的行
:param input_file: 输入日志文件路径
:param output_file: 输出文件路径
"""
try:
with open(input_file, 'r', encoding='utf-8') as f_in:
# 一次性读取所有符合条件的行(内存足够时)
target_lines = [line for line in f_in if 'target_bitrate_kbps' in line]
with open(output_file, 'w', encoding='utf-8') as f_out:
f_out.writelines(target_lines)
print(f"成功提取 {len(target_lines)} 行数据到 {output_file}")
except FileNotFoundError:
print(f"错误:文件 {input_file} 不存在")
except Exception as e:
print(f"处理失败:{str(e)}")
def main():
# 创建序号文件夹
folder_name = create_sequence_folder()
# 输入文件名
sender_filename = 'sender.log'
bandwidth_filename = 'bandwidth.log'
# 解析sender.log文件
print(f"Parsing sender log file: {sender_filename}")
# 接收所有解析结果
(
sender_timestamps, sender_bitrates,
loss_timestamps, loss_rates,
t_timestamps, t_values, gamma_values,
rtt_timestamps, rtt_values,
frame_timestamps, frame_ids, frame_sizes,
loss_bitrate_timestamps, loss_bitrates,
delay_bitrate_timestamps, delay_bitrates,
ack_bitrate_timestamps, ack_bitrates, # 新增
delta_timestamps, delay_deltas # 新增
) = parse_sender_log(sender_filename)
# 检查是否返回有效数据
if not any([
sender_timestamps, loss_timestamps,
t_timestamps, rtt_timestamps,
loss_bitrate_timestamps, delay_bitrate_timestamps
]):
print("No valid data found in sender.log.")
return
# 获取基准时间(所有时间戳中的最小值)
all_timestamps = []
if sender_timestamps:
all_timestamps.extend(sender_timestamps)
if loss_timestamps:
all_timestamps.extend(loss_timestamps)
if t_timestamps:
all_timestamps.extend(t_timestamps)
if rtt_timestamps:
all_timestamps.extend(rtt_timestamps)
if loss_bitrate_timestamps:
all_timestamps.extend(loss_bitrate_timestamps)
if delay_bitrate_timestamps:
all_timestamps.extend(delay_bitrate_timestamps)
if ack_bitrate_timestamps:
all_timestamps.extend(ack_bitrate_timestamps)
if delta_timestamps:
all_timestamps.extend(delta_timestamps)
if frame_timestamps:
all_timestamps.extend(frame_timestamps)
if all_timestamps:
base_time = min(all_timestamps)
else:
print("No valid timestamps found.")
return
# 计算相对时间
sender_relative_times = [(ts - base_time).total_seconds() for ts in sender_timestamps]
loss_relative_times = [(ts - base_time).total_seconds() for ts in loss_timestamps]
t_relative_times = [(ts - base_time).total_seconds() for ts in t_timestamps]
rtt_relative_times = [(ts - base_time).total_seconds() for ts in rtt_timestamps]
loss_bitrate_relative_times = [(ts - base_time).total_seconds() for ts in loss_bitrate_timestamps]
delay_bitrate_relative_times = [(ts - base_time).total_seconds() for ts in delay_bitrate_timestamps]
# 计算新数据的相对时间
ack_bitrate_relative_times = [(ts - base_time).total_seconds() for ts in ack_bitrate_timestamps]
delta_relative_times = [(ts - base_time).total_seconds() for ts in delta_timestamps]
frame_relative_times = [(ts - base_time).total_seconds() for ts in frame_timestamps]
if sender_timestamps:
print(f"Found {len(sender_timestamps)} bitrate data points")
print(f"Bitrate time range: {sender_relative_times[0]:.2f}s to {sender_relative_times[-1]:.2f}s")
print(f"Bitrate range: {min(sender_bitrates):.2f} kbps to {max(sender_bitrates):.2f} kbps")
if loss_timestamps:
print(f"Found {len(loss_timestamps)} packet loss data points")
print(f"Loss time range: {loss_relative_times[0]:.2f}s to {loss_relative_times[-1]:.2f}s")
print(f"Loss rate range: {min(loss_rates):.2f}% to {max(loss_rates):.2f}%")
if t_timestamps:
print(f"Found {len(t_timestamps)} T/gamma data points")
print(f"T/gamma time range: {t_relative_times[0]:.2f}s to {t_relative_times[-1]:.2f}s")
print(f"T range: {min(t_values):.4f} to {max(t_values):.4f}")
print(f"Gamma range: {min(gamma_values):.4f} to {max(gamma_values):.4f}")
if rtt_timestamps:
print(f"Found {len(rtt_timestamps)} RTT data points")
print(f"RTT time range: {rtt_relative_times[0]:.2f}s to {rtt_relative_times[-1]:.2f}s")
print(f"RTT range: {min(rtt_values):.2f} ms to {max(rtt_values):.2f} ms")
# 打印新增数据信息
if loss_bitrate_timestamps:
print(f"Found {len(loss_bitrate_timestamps)} loss-based bitrate data points")
print(f"Loss-based bitrate range: {min(loss_bitrates):.2f} kbps to {max(loss_bitrates):.2f} kbps")
if delay_bitrate_timestamps:
print(f"Found {len(delay_bitrate_timestamps)} delay-based bitrate data points")
print(f"Delay-based bitrate range: {min(delay_bitrates):.2f} kbps to {max(delay_bitrates):.2f} kbps")
if ack_bitrate_timestamps:
print(f"Found {len(ack_bitrate_timestamps)} ACK bitrate data points")
print(f"ACK bitrate range: {min(ack_bitrates):.2f} kbps to {max(ack_bitrates):.2f} kbps")
if delta_timestamps:
print(f"Found {len(delta_timestamps)} delay delta data points")
print(f"Delay delta range: {min(delay_deltas):.2f} ms to {max(delay_deltas):.2f} ms")
if frame_timestamps:
print(f"Found {len(frame_timestamps)} frame data points")
print(f"Frame time range: {frame_relative_times[0]:.2f}s to {frame_relative_times[-1]:.2f}s")
# 解析bandwidth.log文件
print(f"Parsing bandwidth log file: {bandwidth_filename}")
bandwidth_timestamps, bandwidth_bandwidths, config_lines = parse_bandwidth_log(bandwidth_filename, base_time)
if bandwidth_timestamps:
print(f"Found {len(bandwidth_timestamps)} bandwidth data points")
print(f"Bandwidth time range: {bandwidth_timestamps[0]:.2f}s to {bandwidth_timestamps[-1]:.2f}s")
print(f"Bandwidth range: {min(bandwidth_bandwidths):.2f} kbps to {max(bandwidth_bandwidths):.2f} kbps")
else:
print("No valid data found in bandwidth.log")
if config_lines:
print("Found configuration lines in bandwidth.log:")
for line in config_lines:
print(f" {line}")
# 生成输出文件名(使用序号前缀,并放在文件夹内)
bitrate_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_bitrate.png")
loss_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_loss.png")
t_gamma_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_t_gamma.png")
rtt_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_rtt.png")
framesize_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_framesize.png")
delay_delta_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_delay_delta.png")
# 新增复合图表输出路径
all_bitrate_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_all_bitrate.png")
frame_bitrate_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_frame_bitrate.png")
composite_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_bitrate_frame_gamma.png")
queue_output_filename = os.path.join(folder_name, f"{SEQUENCE_NUMBER}_queue_bitrate.txt")
# 绘制比特率和带宽图表
plot_bitrate_bandwidth(
sender_relative_times, sender_bitrates,
bandwidth_timestamps, bandwidth_bandwidths,
config_lines, bitrate_output_filename
)
# 绘制丢包率图表
plot_loss(
loss_relative_times, loss_rates,
config_lines, loss_output_filename
)
# 绘制T、gamma和-gamma图表
plot_t_gamma(
t_relative_times, t_values, gamma_values,
config_lines, t_gamma_output_filename
)
# 绘制RTT图表
plot_rtt(
rtt_relative_times, rtt_values,
config_lines, rtt_output_filename
)
# 新增:绘制帧大小图表
plot_frame_size(
frame_ids, frame_sizes,
config_lines, framesize_output_filename
)
# 绘制复合比特率图表(增加新参数)
plot_all_bitrates(
sender_relative_times, sender_bitrates,
loss_bitrate_relative_times, loss_bitrates,
delay_bitrate_relative_times, delay_bitrates,
ack_bitrate_relative_times, ack_bitrates, # 新增ACK比特率数据
config_lines, all_bitrate_output_filename
)
# 绘制delay_delta图表
plot_delay_delta(
delta_relative_times, delay_deltas,
config_lines, delay_delta_output_filename
)
# 调用新增的绘图函数
if sender_relative_times and frame_relative_times:
plot_bitrate_and_frame(
sender_relative_times, sender_bitrates,
frame_relative_times, frame_sizes,
config_lines, frame_bitrate_output_filename
)
# 调用新增的复合绘图函数
if (sender_relative_times and frame_relative_times and t_relative_times):
plot_bitrate_frame_gamma(
sender_relative_times, sender_bitrates,
frame_relative_times, frame_sizes,
t_relative_times, t_values, gamma_values,
config_lines, composite_output_filename
)
extract_target_bitrate_lines(sender_filename, queue_output_filename);
# 重命名日志文件并移动到文件夹,然后删除原始文件
rename_and_move_log_files(folder_name)
if __name__ == "__main__":
main()
修改代码,从sender.log中新增匹配:2025-11-01 17:42:53.069 pace_sender.c:132 pacer_queue_bytes = 5808bytes。提取pacer_queue_bytes 随时间的变化,提供修改的代码部分
最新发布