You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

尝试将Gst Buffer内存复制到Torch Tensor时出现段错误

问题分析与解决方案

核心问题定位

段错误的根源大概率是OpenCV Mat构造时未考虑GStreamer Buffer的内存对齐/步长,导致Mat访问了非法内存区域,后续Torch Tensor的clone操作触发内存访问错误。此外代码中还有提前读取未初始化变量的问题,会干扰调试。

具体问题点

  1. 提前读取未初始化的map变量:在gst_buffer_map前就打印map.size,此时map是未初始化的垃圾值,完全无意义。
  2. OpenCV Mat构造忽略GStreamer的内存步长:GStreamer的Buffer为了内存对齐,每行数据会有额外的padding字节(即map.stride不等于width*channels),直接用默认步长构造Mat会导致后续内存越界访问,虽然OpenCV的imwrite能正常执行,但内存已被破坏,触发后续Torch操作的段错误。
  3. 硬编码尺寸风险:代码中固定写死1920x2560,若GStreamer管道实际输出的尺寸不符,会直接导致内存访问错误。

修复代码

static GstPadProbeReturn on_probe(
    GstPad *pad, GstPadProbeInfo *info, gpointer user_data
) {
    GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
    if (!buffer) return GST_PAD_PROBE_OK;

    GstMapInfo map;
    FrameInfo *fr = static_cast<FrameInfo*>(user_data);
    std::ostringstream file_name;
    file_name << "image";

    // 先获取并验证当前Pad的实际Caps,避免硬编码错误
    gint width = 0, height = 0;
    const gchar *format = nullptr;
    GstCaps *caps = gst_pad_get_current_caps(pad);
    if (caps) {
        GstStructure *s = gst_caps_get_structure(caps, 0);
        gst_structure_get_int(s, "width", &width);
        gst_structure_get_int(s, "height", &height);
        format = gst_structure_get_string(s, "format");
        gst_caps_unref(caps);
    }

    // 验证格式和尺寸是否符合预期
    if (width != 2560 || height != 1920 || g_strcmp0(format, "RGB") != 0) {
        std::cerr << "Unexpected caps: " << width << "x" << height << ", format=" << format << std::endl;
        return GST_PAD_PROBE_OK;
    }

    if (gst_buffer_map(buffer, &map, GST_MAP_READ)) {
        // 现在打印有效map信息
        std::cout << "Buffer size: " << map.size << ", stride: " << map.stride << std::endl;

        // 关键修复:传入GStreamer的实际步长给OpenCV Mat
        cv::Mat frame(height, width, CV_8UC3, map.data, map.stride);
        cv::cvtColor(frame, frame, cv::COLOR_RGB2BGR);
        
        cv::Mat norm_frame;
        frame.convertTo(norm_frame, CV_32FC3, 1.0f / 255.0f);

        file_name << fr->frame_no << ".png";
        bool success = cv::imwrite(file_name.str(), frame);
        if (!success) { 
            std::cerr << "Failed to write image";
        }

        // 构造Tensor并clone(此时norm_frame内存是安全的)
        at::Tensor tensor = torch::from_blob(
            norm_frame.data, {1, norm_frame.rows, norm_frame.cols, 3}, at::kFloat
        ).clone();
        tensor = tensor.permute({0, 3, 1, 2});

        // 执行模型推理
        torch::jit::IValue output = fr->model.forward({tensor});

        fr->frame_no++;
        gst_buffer_unmap(buffer, &map);
    }   

    GstClockTime pts = GST_BUFFER_PTS(buffer);
    std::cout << "Buffer PTS: " << GST_TIME_AS_MSECONDS(pts) << " ms" << std::endl;

    return GST_PAD_PROBE_OK;
}

额外建议

  • 若模型运行在GPU上,需确保Tensor正确移动到GPU:tensor = tensor.to(at::kCUDA);,同时确认模型已加载到GPU。
  • 检查FrameInfo中的model是否正确初始化(TorchScript模型是否成功加载,无空指针)。
  • 若段错误仍存在,可使用gdb或valgrind定位具体的内存访问错误点,确认是Torch侧还是OpenCV侧的问题。

内容的提问来源于stack exchange,提问作者vizn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:27:36