Commit 0cb40ca1 authored by zhyh2010's avatar zhyh2010
Browse files

Initial commit

parents
#!/usr/bin/env python3
import argparse
import subprocess
import ffmpeg
import os
import sys
V4L2_CODEC_NAMES = {
"h264": "h264_v4l2m2m",
"hevc": "hevc_v4l2m2m",
"vp9": "vp9_v4l2m2m",
"avs2": "avs2_v4l2m2m",
"mjpeg": "mjpeg_v4l2m2m",
}
CUVID_CODEC_NAMES = {
"h264": "h264_cuvid",
"hevc": "hevc_cuvid",
"vp9": "vp9_cuvid",
"avs2": "avs2_cuvid",
"mjpeg": "mjpeg_cuvid",
}
def get_input_codec(input_file):
"""获取输入文件的编码格式(小写)"""
try:
probe = ffmpeg.probe(input_file, select_streams='v:0', show_entries='stream=codec_name')
return probe['streams'][0]['codec_name'].lower()
except Exception:
return os.path.splitext(input_file)[1].replace('.', '').lower()
def run_multi_instance_benchmark(input_file, codec_type, threads, log_file_path):
"""运行多实例基准测试"""
if not os.path.isfile(input_file):
print(f"Error: Input file '{input_file}' does not exist.", file=sys.stderr)
sys.exit(1)
input_codec = get_input_codec(input_file)
if codec_type == "cuda":
stream = ffmpeg.input(input_file, hwaccel='cuda')
elif codec_type == "v4l2":
decoder = V4L2_CODEC_NAMES.get(input_codec, input_codec)
stream = ffmpeg.input(input_file, vcodec=decoder)
elif codec_type == "cuvid":
decoder = CUVID_CODEC_NAMES.get(input_codec, input_codec)
stream = ffmpeg.input(input_file, vcodec=decoder)
elif codec_type == "vaapi":
stream = ffmpeg.input(input_file, hwaccel='vaapi')
else:
print(f"Unknown codec type: {codec_type}", file=sys.stderr)
sys.exit(1)
cmd = ffmpeg.output(stream, 'pipe:', format='null').global_args('-benchmark', '-y').compile()
processes = []
print(f"Starting {threads} concurrent ffmpeg processes...", file=sys.stderr)
with open(log_file_path, 'w') as log_f:
log_f.write(f"# Multi-instance benchmark log\n")
log_f.write(f"# Command: {' '.join(cmd)}\n")
log_f.write(f"# Threads: {threads}\n\n")
for i in range(threads):
p = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=log_f)
processes.append(p)
for p in processes:
p.wait()
print("All processes finished.", file=sys.stderr)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Multi-instance FFmpeg Benchmark")
parser.add_argument("-i", "--input", required=True, help="Input video file")
parser.add_argument("-c", "--codec", default="cuda", choices=["cuda", "cuvid", "v4l2", "vaapi"], help="Codec type")
parser.add_argument("-n", "--threads", type=int, default=6, help="Number of concurrent processes")
parser.add_argument("-o", "--output", required=True, help="Output log file")
args = parser.parse_args()
run_multi_instance_benchmark(args.input, args.codec, args.threads, args.output)
\ No newline at end of file
# DCU Codec Pipeline Benchmark
DCU编解码性能测试工具 - 用于测试和评估不同编解码器后端的视频处理性能。
## 项目简介
该项目是DCU性能压测工具codecbenchmark的python实现,可作为DCU上MacCodecSDK以及ffmpeg的python api参考
## 主要功能
### 核心特性
-**多后端支持**:支持 CUDA、CUVID、V4L2、VAAPI 等多种编解码后端
-**编解码测试**:支持 H264、HEVC、VP9、AVS2、MJPEG 等格式的编解码性能测试
-**多实例并发**:支持多线程并发测试,评估系统并发处理能力
-**多分辨率支持**:支持从 720p 到 8K 的多种分辨率测试
-**位深测试**:支持 8-bit 和 10-bit 位深测试
-**详细报告**:生成 CSV 格式的性能测试报告
### 支持的编解码器
**解码器:**
- H264 (h264_cuvid/h264_v4l2m2m)
- HEVC (hevc_cuvid/hevc_v4l2m2m)
- VP9 (vp9_cuvid/vp9_v4l2m2m)
- AVS2 (avs2_cuvid/avs2_v4l2m2m)
- MJPEG (mjpeg_cuvid/mjpeg_v4l2m2m)
**编码器:**
- H264_NVENC / H264_VAAPI
- HEVC_NVENC / HEVC_VAAPI
- VP9_NVENC / VP9_VAAPI
- MJPEG_NVENC / MJPEG_VAAPI
## 环境要求
与MacCodec环境要求一致
### 依赖安装
```bash
pip install -r requirements.txt
```
主要依赖:
- ffmpeg-python
- MacCodecSDK
## 项目结构
其中测试视频文件为方便clone测试仅包含一个文件,若想参考codecBenchmark全面测试可将所有文件放入同目录下,并取消代码中的注释
```
dcu-codec-pipeline-py/
├── codecbenchmark-py/
│ ├── video_benchmark/ # 测试视频文件目录
│ │ └── sample_1920x1080_30fps_8bit.h264
│ ├── benchmark_multi_inst.py # 多实例测试模块
│ ├── video_benchmark.py # 主测试脚本
│ ├── readme.md # 项目说明
│ └── requirements.txt # 依赖列表
├── video_cuda_decode_benchmark.csv # 解码测试结果
└── video_cuda_encode_benchmark.csv # 编码测试结果
```
## 使用方法
### 基本用法
运行解码和编码性能测试:
```bash
# 使用 CUDA 后端,默认 6 线程
python video_benchmark.py
# 指定后端和线程数
python video_benchmark.py -c cuda -n 8
python video_benchmark.py -c vaapi -n 4
python video_benchmark.py -c v4l2 -n 6
```
### 命令行参数
```bash
usage: video_benchmark.py [-h] [-c {cuda,cuvid,v4l2,vaapi}] [-n THREADS]
可选参数:
-h, --help 显示帮助信息
-c, --codec 编解码后端类型
可选值: cuda, cuvid, v4l2, vaapi
默认值: cuda
-n, --threads 并发进程数量
默认值: 6
```
## 测试配置
### 解码测试文件
项目预配置了以下测试文件:
- `sample_1920x1080_30fps_8bit.h264` - 1080p 30fps H264 8bit
### 编码测试配置
支持多种分辨率和格式的编码测试:
| 分辨率 | 格式 | 位深 | 帧数 |
|--------|------|------|------|
| 1280x720 | H264/HEVC | 8-bit | 677 |
| 1920x1080 | H264/HEVC/JPEG | 8-bit | 812-2174 |
| 3840x2160 | H264/HEVC/JPEG | 8-bit | 812 |
| 7680x4320 | H264/HEVC | 8-bit | 77 |
| 1280x720 | HEVC | 10-bit | 677 |
| 1920x1080 | HEVC | 10-bit | 812 |
| 3840x2160 | HEVC | 10-bit | 812 |
| 4096x2160 | JPEG | 8-bit | 1 |
| 8192x4320 | JPEG | 8-bit | 1 |
## 输出结果
### CSV 报告文件
测试完成后会生成两个 CSV 文件:
1. **解码测试报告** (`video_{codec}_decode_benchmark.csv`)
```csv
Decode,Bit Depth,Resolution,Fps/(BMZ 1 Core),Fps/(BMZ 6 Processes)
H264,8,1920x1080,245.67,1234.56
```
2. **编码测试报告** (`video_{codec}_encode_benchmark.csv`)
```csv
Encode,Bit Depth,Resolution,Fps/(BMZ 1 Core)
H264,8,1920x1080,189.34
HEVC,10,3840x2160,95.67
```
### 性能指标说明
- **Fps/(BMZ 1 Core)**: 单核心/单进程处理的帧率(FPS)
- **Fps/(BMZ N Processes)**: N 个并发进程总处理的帧率(FPS)
## 测试流程
1. **解压测试文件**:自动从 `video_benchmark.zip` 解压测试视频
2. **解码测试**
- 单实例解码性能测试
- 多实例并发解码测试
3. **编码测试**
- 将解码后的 YUV 数据重新编码
- 测试不同格式和分辨率的编码性能
4. **结果聚合**
- 统计平均性能数据
- 生成 CSV 报告
5. **清理临时文件**:自动清理测试过程中生成的临时文件
## 示例输出
```
Processing: sample_1920x1080_30fps_8bit.h264 (Idx: 1)
-> Single instance decode: 245.67 FPS
-> Multi instance (6 processes): 1234.56 FPS
Encoding: sample_1920x1080_30fps_8bit.h264 -> H264
-> Encode performance: 189.34 FPS
Aggregating results...
Benchmark finished.
```
## 注意事项
1. **文件准备**:确保测试视频文件位于 `video_benchmark/` 目录或提供 `video_benchmark.zip`
2. **权限要求**:使用 VAAPI/V4L2 后端时可能需要访问 `/dev/dri/renderD128` 设备文件
3. **性能影响**:多实例测试会占用较多系统资源,建议根据硬件配置调整线程数
4. **日志文件**:测试过程会生成临时日志文件,测试完成后自动清理
## 故障排除
### 常见问题
**问题 1**: `FFmpeg command construction failed`
- 检查 FFmpeg 是否正确安装
- 确认选择的编解码后端是否受支持
**问题 2**: `Unknown encoder for XXX`
- 确认 FFmpeg 编译时启用了相应的编码器
- 检查硬件驱动是否正确安装
**问题 3**: 多实例测试性能异常
- 检查系统资源(GPU、内存)是否充足
- 减少并发线程数 `-n` 参数
### 日志调试
测试过程中的详细日志会保存在:
- 解码日志:`video_benchmark/{filename}.log`
- 多实例日志:`video_benchmark/{filename}_multi.log`
- 编码日志:`video_benchmark/{filename}_encode.log`
## 许可证
本项目仅供性能测试和评估使用。
## 联系方式
如有问题或建议,请提交 Issue 或联系项目维护者。
---
**版本**: 1.0
**最后更新**: 2026-02-26
\ No newline at end of file
ffmpeg-python
\ No newline at end of file
#!/usr/bin/env python3
import argparse
import subprocess
import ffmpeg
import os
import re
import csv
import zipfile
import sys
from collections import defaultdict
from benchmark_multi_inst import run_multi_instance_benchmark
# --- 配置数据 ---
DECODE_FILE_ARR = [
["sample_1920x1080_30fps_8bit.h264", "1", "812", "H264", "8", "1920x1080"],
]
ENCODE_FILE_ARR = [
["1280x720_nv12.yuv", "677", "H264", "8", "1280x720"],
["1920x1080_nv12.yuv", "812", "H264", "8", "1920x1080"],
["3840x2160_nv12.yuv", "812", "H264", "8", "3840x2160"],
["7680x4320_nv12.yuv", "77", "H264", "8", "7680x4320"],
["1280x720_nv12.yuv", "677", "HEVC", "8", "1280x720"],
["1920x1080_nv12.yuv", "812", "HEVC", "8", "1920x1080"],
["3840x2160_nv12.yuv", "812", "HEVC", "8", "3840x2160"],
["7680x4320_nv12.yuv", "77", "HEVC", "8", "7680x4320"],
["1280x720_p010le.yuv", "677", "HEVC", "10", "1280x720"],
["1920x1080_p010le.yuv", "812", "HEVC", "10", "1920x1080"],
["3840x2160_p010le.yuv", "812", "HEVC", "10", "3840x2160"],
["1920x1080_nv12.yuv", "1", "JPEG_1", "8", "1920x1080"],
["3840x2160_nv12.yuv", "1", "JPEG_1", "8", "3840x2160"],
["4096x2160_nv12.yuv", "1", "JPEG_1", "8", "4096x2160"],
["8192x4320_nv12.yuv", "1", "JPEG_1", "8", "8192x4320"],
["1920x1080_nv12.yuv", "2174", "JPEG", "8", "1920x1080"],
["1920x1080_nv12.yuv", "1701", "JPEG", "8", "1920x1080"],
["1920x1080_nv12.yuv", "2076", "JPEG", "8", "1920x1080"],
["1920x1080_nv12.yuv", "1581", "JPEG", "8", "1920x1080"],
["1920x1080_nv12.yuv", "2154", "JPEG", "8", "1920x1080"],
]
# 编解码器映射(键为小写)
NVENC_ENCODER_NAMES = {
"h264": "h264_nvenc",
"hevc": "hevc_nvenc",
"vp9": "vp9_nvenc",
"mjpeg": "mjpeg_nvenc",
}
VAAPI_ENCODER_NAMES = {
"h264": "h264_vaapi",
"hevc": "hevc_vaapi",
"vp9": "vp9_vaapi",
"mjpeg": "mjpeg_vaapi",
}
V4L2_CODEC_NAMES = {
"h264": "h264_v4l2m2m",
"hevc": "hevc_v4l2m2m",
"vp9": "vp9_v4l2m2m",
"avs2": "avs2_v4l2m2m",
"mjpeg": "mjpeg_v4l2m2m",
}
CUVID_CODEC_NAMES = {
"h264": "h264_cuvid",
"hevc": "hevc_cuvid",
"vp9": "vp9_cuvid",
"avs2": "avs2_cuvid",
"mjpeg": "mjpeg_cuvid",
}
# --- 辅助函数 ---
def parse_ffmpeg_benchmark_times(log_content):
"""解析 ffmpeg 日志获取所有 rtime 值(秒)"""
times = []
# 匹配 rtime=0.123456 (benchmark 输出的浮点秒数)
time_matches = re.findall(r'rtime=(\d+\.?\d*)', log_content)
for time_str in time_matches:
try:
total_sec = float(time_str)
times.append(total_sec)
except ValueError:
continue
# 备选:匹配 time=00:00:00.00 (时间戳格式)
if not times:
timestamp_matches = re.findall(r'time=(\d+:\d+:\d+\.\d+)', log_content)
for time_str in timestamp_matches:
parts = time_str.split(':')
if len(parts) == 3:
h, m, s = parts
s_clean = s.rstrip('s')
try:
total_sec = float(h) * 3600 + float(m) * 60 + float(s_clean)
times.append(total_sec)
except ValueError:
continue
return times
def parse_ffmpeg_log_frames(log_content):
"""获取总帧数"""
frame_matches = re.findall(r'frame=\s*(\d+)', log_content)
if frame_matches:
return int(frame_matches[-1])
return 0
def calculate_fps(frames, rtime):
if rtime > 0:
return round(frames / rtime, 2)
return 0.0
def run_ffmpeg_command(cmd, log_file_path):
"""运行 ffmpeg 命令并将 stderr 保存到日志文件(即使失败也创建文件)"""
try:
with open(log_file_path, 'w') as log_f:
process = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=log_f, text=True)
return process.returncode
except Exception as e:
# 即使出错也创建日志文件
with open(log_file_path, 'w') as log_f:
log_f.write(f"Error: {e}\n")
return -1
def extract_zip():
video_benchmark_dir = "./video_benchmark"
zip_file = "video_benchmark.zip"
if not os.path.exists(video_benchmark_dir):
if os.path.exists(zip_file):
print(f"Extracting {zip_file}...")
with zipfile.ZipFile(zip_file, 'r') as zip_ref:
zip_ref.extractall(video_benchmark_dir)
else:
print(f"Warning: {zip_file} not found. Ensure test files exist in {video_benchmark_dir}")
else:
print("video_benchmark dir exist")
def get_decoder_args(codec_type, file_ext):
"""获取解码器参数"""
file_ext_lower = file_ext.lower()
if codec_type == "cuda":
return {"hwaccel": "cuda"}
elif codec_type == "vaapi":
return {"hwaccel": "vaapi"}
elif codec_type == "v4l2":
decoder = V4L2_CODEC_NAMES.get(file_ext_lower, file_ext_lower)
return {"vcodec": decoder}
elif codec_type == "cuvid":
decoder = CUVID_CODEC_NAMES.get(file_ext_lower, file_ext_lower)
return {"vcodec": decoder}
return {}
def get_encoder_name(codec_type, file_ext):
"""获取编码器名称(修复大小写问题)"""
# 转换为小写
file_ext_lower = file_ext.lower()
# 特殊处理:H264 -> h264, HEVC -> hevc, JPEG -> mjpeg
if file_ext_lower in ["h264", "hevc", "vp9", "avs2"]:
codec_key = file_ext_lower
elif file_ext_lower in ["jpg", "jpeg", "avi", "mjpeg"]:
codec_key = "mjpeg"
else:
codec_key = file_ext_lower
if codec_type == "cuda":
return NVENC_ENCODER_NAMES.get(codec_key, "")
elif codec_type == "vaapi":
return VAAPI_ENCODER_NAMES.get(codec_key, "")
elif codec_type == "v4l2":
return V4L2_CODEC_NAMES.get(codec_key, "")
elif codec_type == "cuvid":
return CUVID_CODEC_NAMES.get(codec_key, "")
return ""
def run_single_decode_benchmark(input_file, codec_type, log_file):
"""运行单次解码测试"""
file_ext = os.path.splitext(input_file)[1].replace('.', '')
input_kwargs = get_decoder_args(codec_type, file_ext)
try:
stream = ffmpeg.input(input_file, **input_kwargs)
cmd = ffmpeg.output(stream, 'pipe:', format='null').global_args('-benchmark', '-y').compile()
run_ffmpeg_command(cmd, log_file)
return True
except Exception as e:
print(f"FFmpeg command construction failed: {e}")
return False
def run_encode_benchmark(yuv_file, output_file, resolution, codec_type, file_ext, depth, log_file):
"""运行编码测试"""
w, h = resolution.split('x')
pix_fmt = "p010le" if "10" in str(depth) else "nv12"
profile = "main10" if "10" in str(depth) else None
# 修复:获取编码器名称(处理大小写)
encoder_name = get_encoder_name(codec_type, file_ext)
if not encoder_name:
print(f"Unknown encoder for {file_ext} on {codec_type}")
# 即使失败也创建日志文件
with open(log_file, 'w') as f:
f.write(f"Error: Unknown encoder for {file_ext} on {codec_type}\n")
return False
try:
input_kwargs = {
'format': 'rawvideo',
's': f"{w}x{h}",
'pix_fmt': pix_fmt
}
global_args = ['-benchmark', '-y']
output_kwargs = {'vcodec': encoder_name}
if codec_type == "vaapi":
input_kwargs['hwaccel'] = 'vaapi'
global_args.extend(['-vaapi_device', '/dev/dri/renderD128'])
output_kwargs['vf'] = 'format=nv12,hwupload' if pix_fmt == 'nv12' else 'format=p010le,hwupload'
if profile:
output_kwargs['profile'] = profile
stream = ffmpeg.input(yuv_file, **input_kwargs)
cmd = ffmpeg.output(stream, output_file, **output_kwargs).global_args(*global_args).compile()
run_ffmpeg_command(cmd, log_file)
return True
except Exception as e:
print(f"Encode command failed: {e}")
# 即使失败也创建日志文件
with open(log_file, 'w') as f:
f.write(f"Error: {e}\n")
return False
def aggregate_results(temp_csv, final_csv, is_encode=False, threads=6):
"""聚合 CSV 结果"""
data = defaultdict(lambda: {"sum_1core": 0.0, "sum_multi": 0.0, "count": 0})
try:
with open(temp_csv, 'r', newline='') as f:
reader = csv.reader(f)
header = next(reader)
for row in reader:
if len(row) < 5:
continue
fmt = row[2].strip()
depth = row[3].strip()
res = row[4].strip()
try:
fps_1 = float(row[5]) if len(row) > 5 else 0.0
fps_multi = float(row[6]) if (not is_encode and len(row) > 6) else 0.0
except ValueError:
fps_1 = 0.0
fps_multi = 0.0
key = f"{fmt},{depth},{res}"
data[key]["sum_1core"] += fps_1
data[key]["sum_multi"] += fps_multi
data[key]["count"] += 1
except FileNotFoundError:
print(f"Warning: {temp_csv} not found.")
return
with open(final_csv, 'w', newline='') as f:
writer = csv.writer(f)
if is_encode:
writer.writerow(["Encode", "Bit Depth", "Resolution", "Fps/(BMZ 1 Core)"])
for key, val in data.items():
if val["count"] > 0:
avg_1 = val["sum_1core"] / val["count"]
parts = key.split(',')
writer.writerow([parts[0], parts[1], parts[2], f"{avg_1:.2f}"])
else:
writer.writerow(["Decode", "Bit Depth", "Resolution", "Fps/(BMZ 1 Core)", f"Fps/(BMZ {threads} Processes)"])
for key, val in data.items():
if val["count"] > 0:
avg_1 = val["sum_1core"] / val["count"]
avg_multi = val["sum_multi"] / val["count"]
parts = key.split(',')
writer.writerow([parts[0], parts[1], parts[2], f"{avg_1:.2f}", f"{avg_multi:.2f}"])
def main():
parser = argparse.ArgumentParser(description="Video Benchmark Script")
parser.add_argument("-c", "--codec", default="cuda", choices=["cuda", "cuvid", "v4l2", "vaapi"], help="Codec backend")
parser.add_argument("-n", "--threads", type=int, default=6, help="Number of concurrent processes")
args = parser.parse_args()
CODEC = args.codec
THREADS = args.threads
video_decode_benchmark_temp = f"video_{CODEC}_decode_benchmark_temp.csv"
video_decode_benchmark = f"video_{CODEC}_decode_benchmark.csv"
video_encode_benchmark_temp = f"video_{CODEC}_encode_benchmark_temp.csv"
video_encode_benchmark = f"video_{CODEC}_encode_benchmark.csv"
for f in [video_decode_benchmark_temp, video_encode_benchmark_temp]:
if os.path.exists(f):
os.remove(f)
with open(video_decode_benchmark_temp, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(["Test File", "Total Frames", "Decode", "Bit Depth", "Resolution", "Fps/(BMZ 1 Core)", f"Fps/(BMZ {THREADS} Processes)"])
with open(video_encode_benchmark_temp, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(["Test File", "Total Frames", "Encode", "Bit Depth", "Resolution", "Fps/(BMZ 1 Core)"])
extract_zip()
base_dir = "./video_benchmark"
if not DECODE_FILE_ARR:
print("Error: DECODE_FILE_ARR is empty. Please uncomment test files in script.")
return
for i, file_info in enumerate(DECODE_FILE_ARR):
filename, encode_idx, frames, format_name, depth, resolution = file_info
filepath = os.path.join(base_dir, filename)
if not os.path.exists(filepath):
print(f"Skip missing file: {filepath}")
continue
file_ext = os.path.splitext(filename)[1].replace('.', '')
base_name = os.path.splitext(filename)[0]
# 中间生成的 YUV 文件路径
yuv_filename = os.path.join(base_dir, base_name + ".yuv")
decode_log = os.path.join(base_dir, base_name + ".log")
multi_log = os.path.join(base_dir, base_name + "_multi.log")
encode_log = os.path.join(base_dir, base_name + "_encode.log")
# --- 修改点 1: 编码输出文件改为临时文件,避免覆盖原文件 ---
# 原代码:encode_result = os.path.join(base_dir, filename)
# 新代码:添加 _encoded_tmp 后缀,确保不与原文件冲突
encode_result = os.path.join(base_dir, f"{base_name}_encoded_tmp.{file_ext}")
print(f"Processing: {filename} (Idx: {encode_idx})")
# --- 解码测试 ---
success = run_single_decode_benchmark(filepath, CODEC, decode_log)
fps_single = 0.0
fps_multi = 0.0
error_occurred = False
if not success or not os.path.exists(decode_log) or os.path.getsize(decode_log) == 0:
error_occurred = True
print(f" -> Single instance failed or empty log")
else:
with open(decode_log, 'r') as f:
log_content = f.read()
d_times = parse_ffmpeg_benchmark_times(log_content)
d_frames = parse_ffmpeg_log_frames(log_content)
d_rtime = d_times[0] if d_times else 0.0
if d_rtime > 0:
fps_single = calculate_fps(d_frames, d_rtime)
else:
error_occurred = True
print(f" -> Failed to parse rtime from single log")
# 多实例
if not error_occurred:
run_multi_instance_benchmark(filepath, CODEC, THREADS, multi_log)
with open(multi_log, 'r') as f:
multi_log_content = f.read()
m_times = parse_ffmpeg_benchmark_times(multi_log_content)
if m_times:
avg_rtime = sum(m_times) / len(m_times)
fps_multi = calculate_fps(d_frames, avg_rtime) * THREADS
else:
fps_multi = 0.0
print(f" -> Failed to parse rtime from multi log")
if error_occurred:
fps_single = 0.0
fps_multi = 0.0
with open(video_decode_benchmark_temp, 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow([filename, frames, format_name.strip(), depth.strip(), resolution.strip(), fps_single, fps_multi])
# --- 编码测试 ---
if encode_idx != "n/a" and not error_occurred:
try:
idx = int(encode_idx)
if 0 <= idx < len(ENCODE_FILE_ARR):
enc_info = ENCODE_FILE_ARR[idx]
enc_yuv_name = enc_info[0]
enc_frames = enc_info[1]
enc_format = enc_info[2]
enc_depth = enc_info[3]
enc_resolution = enc_info[4]
print(f"Encoding: {filename} -> {enc_format}")
# 生成 YUV(使用与解码测试相同的解码器参数)
if not os.path.exists(yuv_filename):
try:
input_kwargs = get_decoder_args(CODEC, file_ext)
stream = ffmpeg.input(filepath, **input_kwargs)
cmd = ffmpeg.output(stream, yuv_filename, pix_fmt='nv12').global_args('-y').compile()
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except Exception as e:
print(f"YUV conversion failed: {e}")
enc_fps = 0.0
with open(video_encode_benchmark_temp, 'a', newline='') as f:
csv.writer(f).writerow([enc_yuv_name, enc_frames, enc_format.strip(), enc_depth.strip(), enc_resolution.strip(), enc_fps])
continue
# 编码 - 使用 Encode_File_Arr 中的格式
# 注意:输出文件现在是 encode_result (临时文件),不会覆盖 filepath (原文件)
run_encode_benchmark(yuv_filename, encode_result, enc_resolution, CODEC, enc_format.strip(), enc_depth, encode_log)
# 检查日志文件是否存在
if os.path.exists(encode_log):
with open(encode_log, 'r') as f:
enc_log_content = f.read()
e_frames = parse_ffmpeg_log_frames(enc_log_content)
e_times = parse_ffmpeg_benchmark_times(enc_log_content)
e_rtime = e_times[0] if e_times else 0.0
enc_fps = calculate_fps(e_frames, e_rtime)
else:
enc_fps = 0.0
print(f" -> Encode log file not created")
with open(video_encode_benchmark_temp, 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow([enc_yuv_name, enc_frames, enc_format.strip(), enc_depth.strip(), enc_resolution.strip(), enc_fps])
# --- 修改点 2: 清理临时文件 ---
# 现在 encode_result 是临时文件,可以安全删除,不会误删原文件
for f_to_rm in [yuv_filename, encode_result, encode_log]:
if os.path.exists(f_to_rm):
os.remove(f_to_rm)
except ValueError:
pass
# 清理日志
for f_to_rm in [decode_log, multi_log]:
if os.path.exists(f_to_rm):
os.remove(f_to_rm)
print("Aggregating results...")
aggregate_results(video_decode_benchmark_temp, video_decode_benchmark, is_encode=False, threads=THREADS)
aggregate_results(video_encode_benchmark_temp, video_encode_benchmark, is_encode=True, threads=THREADS)
for f in [video_decode_benchmark_temp, video_encode_benchmark_temp]:
if os.path.exists(f):
os.remove(f)
print("Benchmark finished.")
if __name__ == "__main__":
main()
\ No newline at end of file
Decode,Bit Depth,Resolution,Fps/(BMZ 1 Core),Fps/(BMZ 6 Processes)
H264,8,1920x1080,506.87,2277.36
Encode,Bit Depth,Resolution,Fps/(BMZ 1 Core)
H264,8,1920x1080,251.78
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment