系统内核为5.15.0-72-generic
系统内核为5.15.0-72-generic
N260
Ubuntu22.04
mx-smi的信息见下图
docker info
Client: Docker Engine - Community
Version: 27.4.0
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.19.2
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.31.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 32
Running: 12
Paused: 0
Stopped: 20
Images: 59
Server Version: 27.4.0
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 88bf19b2105c8b17560993bee28a01ddc2f97182
runc version: v1.2.2-0-g7cb3632
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 5.15.0-72-generic
Operating System: Ubuntu 22.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 104
Total Memory: 251.5GiB
Name: ictrek
ID: 15ce4c68-5b5c-4e19-80ea-746f67744c6d
Docker Root Dir: /nfs/docker-data
Debug Mode: false
Experimental: false
Insecure Registries:
harbor.testplatform.com:8443
127.0.0.0/8
Registry Mirrors:
https://82m9ar63.mirror.aliyuncs.com/
https://ccr.ccs.tencentyun.com/
https://docker.gs/
https://harbor.testplatform.com:8443/
https://docker.m.daocloud.io/
https://docker.1ms.run/
https://docker.xuanyuan.me/
Live Restore Enabled: false
Default Address Pools:
Base: 192.168.0.0/16, Size: 24
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
镜像为自己定义的
ffmpeg的版本为4.4.2
PyAV的版本为12.2.0
程序代码:
import av
import argparse
import logging
def parase_and_check():
"""解析命令行参数并检查环境"""
# 移除了 --output 参数,因为我们不再写入文件
parser = argparse.ArgumentParser(description='视频硬件解码工具(使用MXVID)')
parser.add_argument('-i', '--input', required=True, help='输入RTSP URL或文件路径')
args = parser.parse_args()
# 检查 h264_mxvid 解码器是否可用
if 'h264_mxvid' not in av.codecs_available:
print("致命错误: h264_mxvid 硬件解码器不可用。请检查驱动和PyAV环境。")
exit()
else:
print("成功检测到 h264_mxvid 解码器!")
# 设置日志级别,可以帮助调试
av.logging.set_level(av.logging.INFO)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
return args
def get_nal_unit_type(packet_data):
"""从H.264数据包中解析NAL单元类型"""
# 确保packet_data是bytes类型
if not isinstance(packet_data, bytes):
packet_data = bytes(packet_data)
start_code_len = 4 if packet_data.startswith(b"\x00\x00\x00\x01") else 3
# 增加长度检查,防止索引越界
if len(packet_data) <= start_code_len:
return -1 # 无效或不完整的数据包
nal_header = packet_data[start_code_len]
nal_unit_type = nal_header & 0x1F # 低 5 位是类型
return nal_unit_type
def hardware_decode_only(input_file):
"""
使用指定的硬件解码器进行解码,但不进行任何编码或写入操作。
"""
container = None
try:
logging.info(f"正在打开输入流: {input_file}")
options = {
'rtsp_transport': 'tcp',
'fflags': 'nobuffer',
'flags': 'low_delay',
}
container = av.open(input_file, options=options)
video_stream = container.streams.video[0]
logging.info(f"视频流信息: {video_stream.width}x{video_stream.height} @ {video_stream.average_rate} fps")
logging.info("正在创建 h264_mxvid 硬件解码器上下文...")
codec_ctx = av.CodecContext.create("h264_mxvid", "r")
logging.info("硬件解码器创建成功!")
frame_count = 0
pps_sps_ready = False # 使用更清晰的变量名
logging.info("开始解码视频流,等待第一个SPS NAL单元...")
for demux_packet in container.demux(video_stream):
# 您的原始逻辑:等待SPS/PPS以确保解码器可以正确初始化
if not pps_sps_ready:
nal_type = get_nal_unit_type(demux_packet)
if nal_type == 7: # NAL unit type 7 is SPS
logging.info("检测到SPS,开始正式解码!")
pps_sps_ready = True
# 只有在接收到SPS后才开始送入数据包进行解码
if pps_sps_ready:
try:
# 将数据包送入解码器
for frame in codec_ctx.decode(demux_packet):
# 解码成功,我们只计数,不做其他任何事
frame_count += 1
# 为了不在控制台刷屏太快,每100帧打印一次进度
if frame_count % 100 == 0:
print(f"已成功解码 {frame_count} 帧...")
except Exception as e:
# 捕获解码单帧时可能发生的错误
logging.warning(f"解码一帧时出错,已跳过: {e}")
continue
# --- 移除了所有与输出、编码、mux相关的代码 ---
print("\n------------------------------------")
logging.info(f"解码流程完成,共解码 {frame_count} 帧。")
return True
except Exception as e:
logging.error(f"发生严重错误: {e}", exc_info=True)
return False
finally:
# 确保输入容器总是被关闭
if container:
container.close()
logging.info("输入流已关闭,资源已释放。")
def main():
"""主程序入口"""
args = parase_and_check()
if hardware_decode_only(args.input):
print("\n任务成功完成!")
else:
print("\n任务失败。")
if __name__ == "__main__":
main()
RTX 3090
Ubuntu18.04
docker info
Client:
Debug Mode: false
Server:
Containers: 48
Running: 43
Paused: 0
Stopped: 5
Images: 66
Server Version: 19.03.12
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: systemd
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: nvidia runc
Default Runtime: nvidia
Init Binary: docker-init
containerd version: 7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
runc version: v1.1.14-0-g2c9f560
init version: fec3683
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 5.15.0-139-generic
Operating System: Ubuntu 20.04.6 LTS
OSType: linux
Architecture: x86_64
CPUs: 48
Total Memory: 251.5GiB
Name: leatop-225
ID: EPP5:RNZH:YKB7:EBCF:AQGF:3UTC:5PJ7:PR4K:YES4:I42B:TK3A:K6V5
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
harbor.dubhe.com
127.0.0.0/8
Registry Mirrors:
https://hub.geekery.cn/
https://ghcr.geekery.cn/
https://hub.uuuadc.top/
https://docker.anyhub.us.kg/
https://hub-mirror.c.163.com/
https://registry.aliyuncs.com/
https://docker.mirrors.ustc.edu.cn/
https://6kx4zyno.mirror.aliyuncs.com/
https://mirrors.tuna.tsinghua.edu.cn/
Live Restore Enabled: true
镜像使用的是自己的
ffmpeg的版本为4.3.2
PyAV的版本为14.4.0
程序代码为:
def hw_decode_only_for_monitoring(input_file):
"""
强制使用 h264_cuvid 进行硬件解码,但不进行任何后续处理。
脚本会持续运行以便于使用 nvidia-smi 进行监控。
"""
container = None
try:
options = {
'rtsp_transport': 'tcp',
'stimeout': '50000-000', # 5秒超时
}
container = av.open(input_file, options=options)
in_stream = container.streams.video[0]
logging.info(f"输入流信息: {in_stream.width}x{in_stream.height}, @ {in_stream.average_rate} fps")
# --- 1. 强制创建 h264_cuvid 解码器上下文 (您的原始逻辑) ---
decoder_ctx = av.CodecContext.create("h264_cuvid", "r")
if in_stream.codec_context.extradata:
decoder_ctx.extradata = in_stream.codec_context.extradata
logging.info("已成功创建并配置 h264_cuvid 硬件解码器。")
# --- 2. 纯解码循环 ---
FRAME_LIMIT = 1000 # 增加帧数限制,以便有足够的时间进行观察
processed_count = 0
started = False
logging.info("="*60)
logging.info("解码已开始。请现在打开另一个终端并运行 'nvidia-smi'。")
logging.info("推荐使用持续监控命令: 'watch -n 1 nvidia-smi'")
logging.info("="*60)
for packet in container.demux(video=0):
if packet.dts is None:
continue
if not started and packet.is_keyframe:
logging.info("接收到第一个关键帧,解码正在全速进行...")
started = True
if not started:
continue
if processed_count >= FRAME_LIMIT:
logging.info(f"已达到 {FRAME_LIMIT} 帧的处理上限。")
break
for frame in decoder_ctx.decode(packet):
# 我们只解码,不对解码后的帧做任何事
# The 'frame' object exists in GPU VRAM at this point.
processed_count += 1
# 为了不在控制台刷屏太快,可以只在特定间隔打印
if processed_count % 100 == 0:
print(f"已解码 {processed_count} / {FRAME_LIMIT} 帧...")
if processed_count >= FRAME_LIMIT:
break
logging.info("解码循环结束。")
# 在程序退出前暂停,给你最后一次查看nvidia-smi的机会
input("按回车键退出程序...")
except Exception as e:
logging.error(f'程序发生严重错误: {e}', exc_info=True)
finally:
# --- 3. 释放资源 ---
if container:
container.close()
logging.info("输入流容器已关闭。")
if __name__ == "__main__":
main()
你好,我在使用沐曦的N260和NVIDIA的RTX3090使用av库进行硬件解码的时候发现,3090的显存增加了300MB作用,而N260的显存才增加了50MB左右,这是为什么