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

Qt C++结合GStreamer开发如何将GstSample转换为QImage

GstSample转QImage正确实现方案

你当前代码输出乱码的核心原因有两个:

  • pipeline未配置颜色空间转换和格式约束,appsink拿到的帧格式、宽高都是默认值,和你硬编码的QImage参数完全不匹配
  • 没有从GstSample的配置信息中提取实际的帧参数,直接写死宽高、像素格式,肯定无法正确解析数据

第一步:修改pipeline配置,统一输出QImage兼容的格式

你需要在源和appsink之间增加videoconvert元素做颜色格式转换,同时给appsink设置caps约束,强制输出QImage原生支持的像素格式,避免后续额外做格式映射。
修改后的pipeline初始化代码如下:

/* Initialize GStreamer */
gst_init (NULL, NULL);

/* Create the elements */
GstElement * source = gst_element_factory_make ("videotestsrc", "source");
GstElement * videoconvert = gst_element_factory_make("videoconvert", "convert");
GstElement * sink = gst_element_factory_make ("appsink", "sink");
GstAppSink *appsink = GST_APP_SINK(sink);

/* Create the empty pipeline */
GstElement * pipeline = gst_pipeline_new ("test-pipeline");

if (!pipeline || !source || !videoconvert || !sink) {
    g_printerr ("Not all elements could be created.\n");
    return ;
}

/* Build the pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, videoconvert, sink, NULL);
if (gst_element_link_many (source, videoconvert, sink, NULL) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return ;
}

/* 配置appsink输出格式:强制为RGBA8888,和QImage原生格式对应 */
GstCaps *caps = gst_caps_new_simple("video/x-raw",
    "format", G_TYPE_STRING, "RGBA",
    NULL);
g_object_set(appsink, "caps", caps, "drop", TRUE, "max-buffers", 3, NULL);
gst_caps_unref(caps);

/* Modify the source's properties */
g_object_set (source, "pattern", 0, NULL);

/* Start playing */
GstStateChangeReturn ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return;
}

第二步:从GstSample提取参数生成QImage

拿到sample后先从其附带的caps信息中读取实际的帧宽高,不要硬编码参数,同时注意资源释放避免内存泄漏:

GstSample *sample = nullptr;
do{
    sample = gst_app_sink_pull_sample(appsink);
    if (!sample) {
        printf("sample is NULL\n");
    }else{
        GstBuffer * buffer = gst_sample_get_buffer(sample);
        GstMapInfo info;
        if(gst_buffer_map(buffer, &info, GST_MAP_READ)){
            // 从sample的配置信息中读取实际帧宽高
            GstCaps *sample_caps = gst_sample_get_caps(sample);
            GstStructure *struc = gst_caps_get_structure(sample_caps, 0);
            int width, height;
            gst_structure_get_int(struc, "width", &width);
            gst_structure_get_int(struc, "height", &height);

            // 生成QImage,格式和我们之前设置的RGBA对应
            // 注意:如果需要长期持有QImage,需要调用.copy(),因为info.data会在buffer释放后失效
            QImage image((const uchar*)info.data, width, height, QImage::Format_RGBA8888);
            // 可按需转换为无alpha通道的RGB格式
            QImage rgbImage = image.convertToFormat(QImage::Format_RGB888);
            rgbImage.save("out.jpg");

            gst_buffer_unmap(buffer, &info);
        }
        gst_sample_unref(sample); // 必须释放sample,否则会出现内存泄漏
    }
}while(sample);

注意事项

  • 后续对接RTSP源时,把videotestsrc替换为rtspsrc + 解封装、解码链路再接videoconvert即可正常工作
  • 拉帧循环不要放在Qt UI主线程执行,建议放到独立工作线程运行,避免阻塞界面

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:42:01