1. 初始化GStreamer并查询硬件编解码器

任务目标

在嵌入式Linux平台上初始化GStreamer框架,并通过标准API枚举系统中可用的硬件视频编解码器(如VPU、VA-API、V4L2 M2M等),输出其名称与能力方向(编码/解码),为后续硬件编解码管线搭建提供能力探测基础。

环境依赖

  • GStreamer核心库(≥1.14),开发头文件:libgstreamer1.0-dev
  • 可选插件包(用于暴露硬件元素):gstreamer1.0-plugins-good/bad/ugly、gstreamer1.0-vaapi(Intel/AMD)、gstreamer1.0-plugins-base
  • 编译工具:gcc、pkg-config

核心实现

通过gst_init()完成框架初始化,调用gst_registry_get_feature_list()遍历所有已注册插件功能,筛选名称中包含硬件编解码特征关键字(如vaapi、v4l2、mfx、nv等)的元素,并利用gst_element_factory_get_metadata()获取其能力描述。代码实现如下:

#include <gst/gst.h>
#include <string.h>
#include <stdio.h>

static gboolean is_hw_codec(const gchar *name) {
    const gchar *keywords[] = {"vaapi", "v4l2", "mfx", "nvdec", "nvenc", "omx", "vpu", NULL};
    for (int i = 0; keywords[i]; i++) {
        if (strstr(name, keywords[i])) return TRUE;
    }
    return FALSE;
}

int main(int argc, char *argv[]) {
    gst_init(&argc, &argv);

    GstRegistry *registry = gst_registry_get();
    GList *features = gst_registry_get_feature_list(registry, GST_TYPE_ELEMENT_FACTORY);
    GList *iter;

    printf("=== 硬件编解码器探测结果 ===\n");
    gint count = 0;

    for (iter = features; iter; iter = g_list_next(iter)) {
        GstElementFactory *factory = GST_ELEMENT_FACTORY(iter->data);
        const gchar *name = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_LONGNAME);
        const gchar *klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
        const gchar *factory_name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));

        if (is_hw_codec(factory_name)) {
            gboolean is_encoder = (strstr(klass, "Encoder") != NULL);
            gboolean is_decoder = (strstr(klass, "Decoder") != NULL);
            if (is_encoder || is_decoder) {
                printf("[%s]\n", factory_name);
                printf("  描述: %s\n", name ? name : "N/A");
                printf("  类型: %s\n", is_encoder && is_decoder ? "编解码器" :
                       is_encoder ? "编码器" : "解码器");
                printf("  分类: %s\n\n", klass ? klass : "N/A");
                count++;
            }
        }
    }

    if (count == 0) {
        printf("未检测到硬件编解码器。请确认:\n");
        printf("  1. 已安装gstreamer1.0-vaapi或v4l2插件\n");
        printf("  2. 硬件驱动已正确加载(/dev/video*或/dev/dri/*)\n");
    } else {
        printf("共发现 %d 个硬件编解码元素\n", count);
    }

    g_list_free_full(features, (GDestroyNotify)gst_object_unref);
    return 0;
}

编译与运行

gcc hw_codec_probe.c -o hw_codec_probe $(pkg-config --cflags --libs gstreamer-1.0)
./hw_codec_probe

验证方法

  • 通过条件:程序正常退出且退出码为0;若平台确有硬件编解码器,输出列表中应包含对应元素名称(如vaapih264enc、v4l2h264dec),且类型标注正确。
  • 交叉验证:执行gst-inspect-1.0 | grep -E "vaapi|v4l2",对比输出结果应与本程序发现的硬件元素一致。
  • 无硬件环境:若输出“未检测到硬件编解码器”,说明当前平台无可用硬件加速插件或驱动未加载,此时程序行为正确。

常见问题

  • 编译报错找不到头文件:确认已安装libgstreamer1.0-dev,且pkg-config路径正确。
  • 检测不到硬件元素:先运行gst-inspect-1.0 vaapi或gst-inspect-1.0 v4l2确认插件已加载;若插件缺失,安装对应插件包后重试。
  • 关键字覆盖不全:部分平台使用私有命名(如mpph264enc),可自行在keywords数组中追加特征串后重新编译。