• Members 4 posts
    2025年8月25日 16:45

    你好,我在使用沐曦的N260和NVIDIA的RTX3090使用av库进行硬件解码的时候发现,3090的显存增加了300MB作用,而N260的显存才增加了50MB左右,这是为什么

  • Members 37 posts
    2025年8月25日 16:48

    尊敬的开发者您好,麻烦您给出操作系统,系统内核,mx-smi信息,docker info信息,镜像名称,容器启动命令,程序代码,程序运行命令

  • Members 4 posts
    2025年8月25日 16:53

    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()
    
  • Members 37 posts
    2025年8月25日 16:55

    尊敬的开发者您好,麻烦您给出沐曦卡操作系统,系统内核,mx-smi信息,docker info信息,镜像名称,容器启动命令,程序代码,程序运行命令

  • Members 4 posts
    2025年8月25日 17:02

    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()
    
    image.png

    PNG, 21.1 KB, uploaded by Vayne on 2025年8月25日.