一、GStreamer的准确定位

1.1 中间件定义与GStreamer的位置

/**
 * @brief 中间件定义与GStreamer定位分析
 * 
 * 核心:GStreamer是**多媒体框架**,属于**应用层中间件**
 * 
 * 中间件分类:
 * ┌─────────────────────────────────────────────────────────────────────────────────┐
 * │                           中间件分层定位                                        │
 * ├─────────────────────────────────────────────────────────────────────────────────┤
 * │                                                                                 │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                    业务应用层 (Application)                              │   │
 * │  │  视频会议App │ 安防监控平台 │ 直播平台 │ 视频编辑器                      │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │                                      ▼                                          │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                    应用层中间件 (Application Middleware)                 │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │  GStreamer │ FFmpeg │ DirectShow │ MediaFoundation              │   │   │
 * │  │  │  (多媒体框架) (编解码库) (Windows)  (Windows)                   │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────┘   │   │
 * │  │  职责: Pipeline构建、插件管理、媒体同步、格式转换                        │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │                                      ▼                                          │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                    通信中间件 (Communication Middleware)                 │   │
 * │  │  DDS │ ZeroMQ │ RabbitMQ │ Kafka                                       │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │                                      ▼                                          │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                    系统中间件 (System Middleware)                        │   │
 * │  │  Android HAL │ V4L2 │ ALSA │ OpenMAX │ VAAPI                           │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │                                      ▼                                          │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                         操作系统内核 (Kernel)                            │   │
 * │  │  Linux Kernel │ Drivers │ DMA │ V4L2 Core │ ALSA Core                   │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * └─────────────────────────────────────────────────────────────────────────────────┘
 * @endverbatim
 */
​
/**
 * @brief GStreamer作为中间件的核心特征
 * 
 * 1. 抽象硬件差异: 统一API屏蔽V4L2/ALSA/VAAPI等底层差异
 * 2. 提供标准接口: Element/Pad/Bin/Pipeline等编程模型
 * 3. 插件化架构: 动态加载,功能可扩展
 * 4. 跨平台: Linux/Windows/macOS/iOS/Android
 * 5. 语言绑定: C/C++/Python/JavaScript/Go等
 */

二、GStreamer架构深度剖析

2.1 GStreamer核心架构图

/**
 * @brief GStreamer完整架构 -深度
 * 
 * @verbatim
 * ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
 * │                              GStreamer 架构全景图                                              │
 * ├─────────────────────────────────────────────────────────────────────────────────────────────────┤
 * │                                                                                                 │
 * │  ┌─────────────────────────────────────────────────────────────────────────────────────────┐   │
 * │  │                           Application Layer                                             │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │  gst-launch-1.0 │ 自定义C程序 │ Python (gi) │  JavaScript (WebRTC)              │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  └─────────────────────────────────────────────────────────────────────────────────────────┘   │
 * │                                              │                                                  │
 * │                                              ▼                                                  │
 * │  ┌─────────────────────────────────────────────────────────────────────────────────────────┐   │
 * │  │                           GStreamer Core Library                                       │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │  GstObject (基类)                                                               │   │   │
 * │  │  │      ├── GstElement (元素) ── 基本处理单元                                      │   │   │
 * │  │  │      │       ├── GstBin (箱子) ── 容器,包含多个元素                            │   │   │
 * │  │  │      │       └── GstPipeline (管道) ── 顶层容器,管理时钟和总线                 │   │   │
 * │  │  │      ├── GstPad (垫) ── 元素的输入输出端口                                      │   │   │
 * │  │  │      └── GstBuffer (缓冲区) ── 数据容器                                         │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │  GstBus (总线) ── 消息传递机制                                                  │   │   │
 * │  │  │  GstClock (时钟) ── 全局时间同步                                                 │   │   │
 * │  │  │  GstRegistry (注册表) ── 插件管理                                                │   │   │
 * │  │  │  GstContext (上下文) ── 共享资源管理 (如GPU上下文)                               │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  └─────────────────────────────────────────────────────────────────────────────────────────┘   │
 * │                                              │                                                  │
 * │                                              ▼                                                  │
 * │  ┌─────────────────────────────────────────────────────────────────────────────────────────┐   │
 * │  │                           Plugin System (插件系统)                                     │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │                         gst-plugins-base (核心插件)                              │   │   │
 * │  │  │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐                    │   │   │
 * │  │  │  │  audiosrc       │ │  videotestsrc   │ │  audiosink      │                    │   │   │
 * │  │  │  │  videosrc       │ │  appsrc         │ │  videosink      │                    │   │   │
 * │  │  │  └─────────────────┘ └─────────────────┘ └─────────────────┘                    │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │                         gst-plugins-good (高质量插件)                           │   │   │
 * │  │  │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐                    │   │   │
 * │  │  │  │  v4l2src        │ │  alsasrc        │ │  videoconvert   │                    │   │   │
 * │  │  │  │  v4l2sink       │ │  alsasink       │ │  videoscale     │                    │   │   │
 * │  │  │  │  rtpmanager     │ │  rtspclientsink │ │  matroskamux    │                    │   │   │
 * │  │  │  └─────────────────┘ └─────────────────┘ └─────────────────┘                    │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │                         gst-plugins-bad (高质量/专利限制)                       │   │   │
 * │  │  │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐                    │   │   │
 * │  │  │  │  h264parse      │ │  mpegtsmux      │ │  webrtcdsp      │                    │   │   │
 * │  │  │  │  h265parse      │ │  dashsink       │ │  voaacenc       │                    │   │   │
 * │  │  │  └─────────────────┘ └─────────────────┘ └─────────────────┘                    │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │                         gst-plugins-ugly (许可证问题)                           │   │   │
 * │  │  │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐                    │   │   │
 * │  │  │  │  x264enc        │ │  lame           │ │  mpeg2dec       │                    │   │   │
 * │  │  │  └─────────────────┘ └─────────────────┘ └─────────────────┘                    │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │                         gst-omx (硬件加速)                                      │   │   │
 * │  │  │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐                    │   │   │
 * │  │  │  │  omxh264enc     │ │  omxh264dec     │ │  omxh265enc     │                    │   │   │
 * │  │  │  └─────────────────┘ └─────────────────┘ └─────────────────┘                    │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────────────────────┘   │   │
 * │  └─────────────────────────────────────────────────────────────────────────────────────────┘   │
 * │                                              │                                                  │
 * │                                              ▼                                                  │
 * │  ┌─────────────────────────────────────────────────────────────────────────────────────────┐   │
 * │  │                           Hardware Abstraction Layer                                   │   │
 * │  │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐       │   │
 * │  │  │  V4L2           │ │  ALSA           │ │  VAAPI          │ │  OpenMAX        │       │   │
 * │  │  │  (Video4Linux)  │ │  (Advanced     │ │  (Video         │ │  (Hardware      │       │   │
 * │  │  │                 │ │   Linux Sound) │ │   Acceleration) │ │   Acceleration) │       │   │
 * │  │  └─────────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘       │   │
 * │  └─────────────────────────────────────────────────────────────────────────────────────────┘   │
 * └─────────────────────────────────────────────────────────────────────────────────────────────────┘
 * @endverbatim
 */

2.2 GStreamer核心数据结构

/**
 * @file gst/gst.h
 * @brief GStreamer核心数据结构
 */
​
/**
 * @struct GstElement
 * @brief 元素 - Pipeline中的基本处理单元
 * 
 * 元素类型:
 * - Source: 数据源 (v4l2src, alsasrc, filesrc)
 * - Filter: 数据处理 (videoconvert, videoscale, x264enc)
 * - Sink: 数据汇 (autovideosink, filesink, rtspclientsink)
 */
struct _GstElement {
    GstObject parent;               // 父对象
    
    /* 工厂信息 */
    GstElementFactory *factory;     // 元素工厂
    gchar *name;                    // 元素名称
    
    /* Pad管理 */
    GList *sinkpads;                // 输入Pad列表
    GList *srcpads;                 // 输出Pad列表
    
    /* 状态管理 */
    GstState current_state;         // 当前状态
    GstState pending_state;         // 待处理状态
    GstState target_state;          // 目标状态
    
    /* 总线 */
    GstBus *bus;                    // 消息总线
    
    /* 线程管理 */
    GstTask *task;                  // 异步任务
    
    /* 时钟 */
    GstClock *clock;                // 元素时钟
    
    /* 锁 */
    GMutex *state_lock;
    GCond *state_cond;
};
​
/**
 * @struct GstPad
 * @brief 垫 - 元素的连接点
 * 
 * Pad类型:
 * - Sink Pad: 接收数据 (元素输入端)
 * - Source Pad: 发送数据 (元素输出端)
 */
struct _GstPad {
    GstObject parent;
    
    /* Pad信息 */
    gchar *name;                    // Pad名称
    GstPadDirection direction;      // 方向 (SRC/SINK)
    GstPadTemplate *padtemplate;    // Pad模板
    
    /* 所属元素 */
    GstElement *parent;             // 所属元素
    
    /* 连接信息 */
    GstPad *peer;                   // 连接的对面Pad
    
    /* 数据流 */
    GstCaps *caps;                  // 支持的格式
    GstPadMode mode;                // 激活模式 (PUSH/POLL)
    
    /* 回调函数 */
    GstPadEventFunction eventfunc;  // 事件处理
    GstPadQueryFunction queryfunc;  // 查询处理
    GstPadLinkFunction linkfunc;    // 链接处理
    
    /* 数据流处理 */
    GstPadChainFunction chainfunc;  // PUSH模式回调
    GstPadGetRangeFunction getrangefunc; // POLL模式回调
};
​
/**
 * @struct GstBuffer
 * @brief 缓冲区 - 数据容器
 * 
 * GStreamer的缓冲区管理:
 * - 零拷贝: 通过引用计数共享数据
 * - 内存池: 预分配减少分配开销
 * - 元数据: 时间戳、标志位等
 */
struct _GstBuffer {
    GstMiniObject mini_object;      // 引用计数基类
    
    /* 时间戳 */
    GstClockTime pts;               // 显示时间戳
    GstClockTime dts;               // 解码时间戳
    GstClockTime duration;          // 持续时间
    
    /* 缓冲区标志 */
    GstBufferFlags flags;           // 关键帧、不连续等标志
    
    /* 内存管理 */
    GstMemory *memory;              // 内存块链表
    guint n_memory;                 // 内存块数量
    
    /* 元数据 */
    GList *metadata;                // 元数据列表 (如ROI信息)
    
    /* 缓冲区池 */
    GstBufferPool *pool;            // 所属缓冲区池
    gsize size;                     // 数据大小
    
    /* 偏移量 */
    gsize offset;                   // 数据偏移
    gsize offset_end;               // 数据结束偏移
};

三、GStreamer插件系统与中间件集成

3.1 自定义GStreamer插件 - 集成V4L2多路摄像头

/**
 * @file gst-rkcamsrc.c
 * @brief 自定义GStreamer Source元素 - 集成16路摄像头
 * 
 * 理解如何将底层驱动封装为GStreamer插件
 */
​
#include <gst/gst.h>
#include <gst/video/video.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
​
GST_DEBUG_CATEGORY_STATIC(gst_rkcamsrc_debug);
#define GST_CAT_DEFAULT gst_rkcamsrc_debug
​
/**
 * @struct GstRkCamSrc
 * @brief 自定义Source元素 - 封装RK3588多路摄像头
 */
typedef struct _GstRkCamSrc {
    GstElement element;                     // 父元素
    
    /* 属性 */
    gchar *device;                          // 设备路径 (/dev/video0-15)
    guint stream_id;                        // 流ID (0-15)
    guint width;                            // 宽度
    guint height;                           // 高度
    guint framerate_n;                      // 帧率分子
    guint framerate_d;                      // 帧率分母
    
    /* 内部状态 */
    gint video_fd;                          // V4L2文件描述符
    gboolean is_open;                       // 是否已打开
    
    /* 缓冲区管理 */
    struct v4l2_buffer v4l2_buf;            // V4L2缓冲区
    struct v4l2_format v4l2_fmt;            // V4L2格式
    
    /* GStreamer特有 */
    GstPad *srcpad;                         // 源Pad
    GstBufferPool *pool;                    // 缓冲区池
    GstAllocator *allocator;                // 内存分配器
    
    /* 统计 */
    guint64 frames_produced;                // 已产生帧数
    guint64 frames_dropped;                 // 丢帧数
} GstRkCamSrc;
​
typedef struct _GstRkCamSrcClass {
    GstElementClass parent_class;           // 父类
} GstRkCamSrcClass;
​
/* 元素工厂注册 */
GType gst_rkcamsrc_get_type(void);
GST_ELEMENT_REGISTER_DECLARE(rkcamsrc);
​
/* 支持的格式列表 */
static const struct {
    gint v4l2_pixfmt;
    gint gst_video_format;
} format_map[] = {
    {V4L2_PIX_FMT_NV12, GST_VIDEO_FORMAT_NV12},
    {V4L2_PIX_FMT_YUYV, GST_VIDEO_FORMAT_YUY2},
    {V4L2_PIX_FMT_UYVY, GST_VIDEO_FORMAT_UYVY},
};
​
/**
 * @brief 元素状态改变处理 - 打开/关闭设备
 */
static GstStateChangeReturn gst_rkcamsrc_change_state(GstElement *element,
                                                       GstStateChange transition)
{
    GstRkCamSrc *src = GST_RKCAMSRC(element);
    GstStateChangeReturn ret;
    
    switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
        /* 打开V4L2设备 */
        src->video_fd = open(src->device, O_RDWR);
        if (src->video_fd < 0) {
            GST_ELEMENT_ERROR(src, RESOURCE, OPEN_READ,
                              ("Failed to open device %s", src->device),
                              ("%s", g_strerror(errno)));
            return GST_STATE_CHANGE_FAILURE;
        }
        
        /* 查询设备能力 */
        struct v4l2_capability cap;
        if (ioctl(src->video_fd, VIDIOC_QUERYCAP, &cap) < 0) {
            GST_ELEMENT_ERROR(src, RESOURCE, READ,
                              ("Failed to query capabilities"),
                              ("%s", g_strerror(errno)));
            close(src->video_fd);
            return GST_STATE_CHANGE_FAILURE;
        }
        
        GST_INFO("Opened device: %s, driver: %s", 
                 src->device, cap.driver);
        break;
        
    case GST_STATE_CHANGE_READY_TO_PAUSED:
        /* 配置格式 */
        memset(&src->v4l2_fmt, 0, sizeof(src->v4l2_fmt));
        src->v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        src->v4l2_fmt.fmt.pix.width = src->width;
        src->v4l2_fmt.fmt.pix.height = src->height;
        src->v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
        src->v4l2_fmt.fmt.pix.field = V4L2_FIELD_NONE;
        
        if (ioctl(src->video_fd, VIDIOC_S_FMT, &src->v4l2_fmt) < 0) {
            GST_ELEMENT_ERROR(src, RESOURCE, SETTINGS,
                              ("Failed to set format"),
                              ("%s", g_strerror(errno)));
            return GST_STATE_CHANGE_FAILURE;
        }
        
        /* 请求缓冲区 */
        struct v4l2_requestbuffers reqbuf;
        memset(&reqbuf, 0, sizeof(reqbuf));
        reqbuf.count = 8;
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        reqbuf.memory = V4L2_MEMORY_MMAP;
        
        if (ioctl(src->video_fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
            GST_ELEMENT_ERROR(src, RESOURCE, NO_SPACE_LEFT,
                              ("Failed to request buffers"),
                              ("%s", g_strerror(errno)));
            return GST_STATE_CHANGE_FAILURE;
        }
        
        GST_INFO("Allocated %d buffers", reqbuf.count);
        break;
        
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
        /* 启动流 */
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(src->video_fd, VIDIOC_STREAMON, &type) < 0) {
            GST_ELEMENT_ERROR(src, RESOURCE, FAILED,
                              ("Failed to start streaming"),
                              ("%s", g_strerror(errno)));
            return GST_STATE_CHANGE_FAILURE;
        }
        
        GST_INFO("Stream started for camera %d", src->stream_id);
        break;
        
    default:
        break;
    }
    
    ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
    
    switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
        /* 停止流 */
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        ioctl(src->video_fd, VIDIOC_STREAMOFF, &type);
        break;
        
    case GST_STATE_CHANGE_PAUSED_TO_READY:
        /* 释放缓冲区 */
        struct v4l2_requestbuffers reqbuf;
        memset(&reqbuf, 0, sizeof(reqbuf));
        reqbuf.count = 0;
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        reqbuf.memory = V4L2_MEMORY_MMAP;
        ioctl(src->video_fd, VIDIOC_REQBUFS, &reqbuf);
        break;
        
    case GST_STATE_CHANGE_READY_TO_NULL:
        /* 关闭设备 */
        close(src->video_fd);
        break;
        
    default:
        break;
    }
    
    return ret;
}
​
/**
 * @brief 创建缓冲区 - 从V4L2获取一帧
 */
static GstFlowReturn gst_rkcamsrc_create(GstPad *pad,
                                          GstObject *parent,
                                          GstBuffer **buffer)
{
    GstRkCamSrc *src = GST_RKCAMSRC(parent);
    struct v4l2_buffer v4l2_buf;
    struct v4l2_plane planes[VIDEO_MAX_PLANES];
    GstMemory *mem;
    int ret;
    
    /* 从V4L2出队缓冲区 */
    memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    v4l2_buf.memory = V4L2_MEMORY_MMAP;
    v4l2_buf.m.planes = planes;
    v4l2_buf.length = 1;
    
    ret = ioctl(src->video_fd, VIDIOC_DQBUF, &v4l2_buf);
    if (ret < 0) {
        if (errno == EAGAIN) {
            return GST_FLOW_EOS;
        }
        GST_ELEMENT_ERROR(src, RESOURCE, READ,
                          ("Failed to dequeue buffer"),
                          ("%s", g_strerror(errno)));
        return GST_FLOW_ERROR;
    }
    
    /* 创建GStreamer缓冲区 - 零拷贝 */
    *buffer = gst_buffer_new();
    
    /* 包装V4L2缓冲区到GStreamer内存 */
    mem = gst_memory_new_wrapped(GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS,
                                  src->v4l2_buf.start,
                                  src->v4l2_buf.bytesused,
                                  0,
                                  src->v4l2_buf.bytesused,
                                  NULL, NULL);
    gst_buffer_append_memory(*buffer, mem);
    
    /* 设置时间戳 */
    GST_BUFFER_PTS(*buffer) = v4l2_buf.timestamp.tv_sec * GST_SECOND +
                               v4l2_buf.timestamp.tv_usec * GST_USECOND;
    GST_BUFFER_DURATION(*buffer) = gst_util_uint64_scale_int(
        GST_SECOND, src->framerate_d, src->framerate_n);
    
    /* 设置标志 */
    if (v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
        GST_BUFFER_FLAG_SET(*buffer, GST_BUFFER_FLAG_DELTA_UNIT);
    }
    
    /* 重新入队缓冲区 */
    ret = ioctl(src->video_fd, VIDIOC_QBUF, &v4l2_buf);
    if (ret < 0) {
        GST_WARNING("Failed to requeue buffer: %s", g_strerror(errno));
    }
    
    src->frames_produced++;
    
    return GST_FLOW_OK;
}
​
/**
 * @brief 元素初始化
 */
static void gst_rkcamsrc_init(GstRkCamSrc *src)
{
    /* 创建源Pad */
    src->srcpad = gst_pad_new("src", GST_PAD_SRC);
    gst_pad_set_chain_function(src->srcpad, NULL);
    gst_pad_set_getrange_function(src->srcpad, gst_rkcamsrc_create);
    gst_element_add_pad(GST_ELEMENT(src), src->srcpad);
    
    /* 设置默认值 */
    src->device = g_strdup("/dev/video0");
    src->width = 1920;
    src->height = 1080;
    src->framerate_n = 30;
    src->framerate_d = 1;
    
    src->frames_produced = 0;
    src->frames_dropped = 0;
}
​
/**
 * @brief 元素工厂注册
 */
static void gst_rkcamsrc_class_init(GstRkCamSrcClass *klass)
{
    GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
    GstPadTemplate *templ;
    
    /* 设置元素信息 */
    gst_element_class_set_static_metadata(element_class,
        "RK3588 Camera Source",
        "Source/Video",
        "Captures video from RK3588 camera interface",
        "Your Name <email@example.com>");
    
    /* 创建Pad模板 */
    templ = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS,
                                  gst_caps_from_string(
                                      "video/x-raw, "
                                      "format=(string)NV12, "
                                      "width=(int)[1,4096], "
                                      "height=(int)[1,4096], "
                                      "framerate=(fraction)[0/1,240/1]"));
    gst_element_class_add_pad_template(element_class, templ);
    
    /* 设置属性 */
    g_object_class_install_property(
        G_OBJECT_CLASS(klass),
        PROP_DEVICE,
        g_param_spec_string("device", "Device",
                            "V4L2 device path",
                            "/dev/video0",
                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
    
    /* 设置状态转换函数 */
    element_class->change_state = GST_DEBUG_FUNCPTR(gst_rkcamsrc_change_state);
}
​
/* 注册插件 */
static gboolean plugin_init(GstPlugin *plugin)
{
    return gst_element_register(plugin, "rkcamsrc", GST_RANK_PRIMARY,
                                 GST_TYPE_RKCAMSRC);
}
​
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR,
                  rkcamsrc, "RK3588 Camera Source Plugin",
                  plugin_init, VERSION, "LGPL", "GStreamer", "https://gstreamer.freedesktop.org")

3.2 16路摄像头GStreamer Pipeline构建

/**
 * @brief 构建16路摄像头 + 音频 + 推流的GStreamer Pipeline
 * 
 * 展示如何用GStreamer组合复杂媒体流
 */
static GstElement *build_16cam_pipeline(void)
{
    GstElement *pipeline;
    GstElement *rtsp_sink;
    GstElement *audio_src, *audio_convert, *audio_encode;
    GstElement *video_src[16];
    GstElement *video_convert[16];
    GstElement *video_encode[16];
    GstElement *tee[16];
    GstElement *queue[16];
    GstElement *compositor;  // 视频合成器
    
    pipeline = gst_pipeline_new("16cam-pipeline");
    
    /* 创建视频合成器 - 将16路合成一个画面 */
    compositor = gst_element_factory_make("compositor", "compositor");
    g_object_set(compositor, "background", "black", NULL);
    
    /* 创建RTSP sink */
    rtsp_sink = gst_element_factory_make("rtspclientsink", "rtsp-sink");
    g_object_set(rtsp_sink, "location", "rtsp://0.0.0.0:8554/stream", NULL);
    
    /* 创建16路视频源 */
    for (int i = 0; i < 16; i++) {
        char name[32];
        
        /* 创建元素 */
        sprintf(name, "camera%d", i);
        video_src[i] = gst_element_factory_make("rkcamsrc", name);
        g_object_set(video_src[i], "device", "/dev/video%d", i, NULL);
        g_object_set(video_src[i], "stream-id", i, NULL);
        
        sprintf(name, "convert%d", i);
        video_convert[i] = gst_element_factory_make("videoconvert", name);
        
        sprintf(name, "encode%d", i);
        video_encode[i] = gst_element_factory_make("x264enc", name);
        g_object_set(video_encode[i], 
                     "bitrate", 2000,
                     "speed-preset", "ultrafast",
                     "tune", "zerolatency",
                     NULL);
        
        sprintf(name, "tee%d", i);
        tee[i] = gst_element_factory_make("tee", name);
        
        sprintf(name, "queue%d", i);
        queue[i] = gst_element_factory_make("queue", name);
        g_object_set(queue[i], 
                     "max-size-buffers", 10,
                     "leaky", 2,  // 丢帧策略
                     NULL);
        
        /* 添加到Pipeline */
        gst_bin_add_many(GST_BIN(pipeline),
                         video_src[i], video_convert[i],
                         video_encode[i], tee[i], queue[i], NULL);
        
        /* 链接 */
        gst_element_link_many(video_src[i], video_convert[i],
                              video_encode[i], tee[i], NULL);
        
        /* 从tee到合成器 */
        GstPad *tee_pad = gst_element_get_request_pad(tee[i], "src_%u");
        GstPad *comp_sink = gst_element_get_static_pad(compositor, "sink_%u");
        gst_pad_link(tee_pad, comp_sink);
        gst_object_unref(tee_pad);
        
        /* 从tee到单独的RTSP流 (可选) */
        GstPad *tee_pad2 = gst_element_get_request_pad(tee[i], "src_%u");
        GstPad *queue_sink = gst_element_get_static_pad(queue[i], "sink");
        gst_pad_link(tee_pad2, queue_sink);
        gst_object_unref(tee_pad2);
    }
    
    /* 创建音频源 */
    audio_src = gst_element_factory_make("alsasrc", "audio-src");
    audio_convert = gst_element_factory_make("audioconvert", "audio-convert");
    audio_encode = gst_element_factory_make("faac", "audio-encode");
    
    gst_bin_add_many(GST_BIN(pipeline), audio_src, audio_convert,
                     audio_encode, compositor, NULL);
    
    /* 链接音频 */
    gst_element_link_many(audio_src, audio_convert, audio_encode, NULL);
    
    /* 链接视频合成器到RTSP sink */
    gst_element_link(compositor, rtsp_sink);
    
    return pipeline;
}

四、GStreamer与其他中间件的关系

4.1 中间件集成架构图

/**
 * @brief GStreamer在多媒体生态中的位置
 * 
 * @verbatim
 * ┌─────────────────────────────────────────────────────────────────────────────────┐
 * │                          多媒体应用生态                                         │
 * ├─────────────────────────────────────────────────────────────────────────────────┤
 * │                                                                                 │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                          Application Layer                              │   │
 * │  │  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐     │   │
 * │  │  │ 视频会议App  │ │ 安防监控平台│ │  直播平台   │ │ 视频编辑器  │     │   │
 * │  │  │ (Zoom/Teams)│ │  (IVS平台)  │ │ (OBS/Twitch)│ │ (Kdenlive) │     │   │
 * │  │  └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘     │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │                                      ▼                                          │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                      High-Level Frameworks                              │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │  WebRTC │ FFmpeg │ OpenCV │ Qt Multimedia │ Android MediaCodec │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────┘   │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │                                      ▼                                          │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                    GStreamer (应用层中间件)                             │   │
 * │  │  ┌─────────────────────────────────────────────────────────────────┐   │   │
 * │  │  │  Pipeline │ Element │ Pad │ Buffer │ Clock │ Bus │ Registry    │   │   │
 * │  │  └─────────────────────────────────────────────────────────────────┘   │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * │                                      │                                          │
 * │          ┌───────────────────────────┼───────────────────────────┐             │
 * │          ▼                           ▼                           ▼             │
 * │  ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐         │
 * │  │  System APIs    │     │  Hardware APIs  │     │  Network APIs   │         │
 * │  │  V4L2/ALSA/    │     │  VAAPI/OpenMAX/ │     │  RTP/RTSP/     │         │
 * │  │  UVC/PA        │     │  OpenGL/Vulkan  │     │  WebRTC/HLS    │         │
 * │  └─────────────────┘     └─────────────────┘     └─────────────────┘         │
 * │          │                           │                           │             │
 * │          ▼                           ▼                           ▼             │
 * │  ┌─────────────────────────────────────────────────────────────────────────┐   │
 * │  │                         Kernel / Hardware                               │   │
 * │  │  Camera │ Microphone │ GPU │ VPU │ NPU │ Network                        │   │
 * │  └─────────────────────────────────────────────────────────────────────────┘   │
 * └─────────────────────────────────────────────────────────────────────────────────┘
 * @endverbatim
 */

4.2 开源中间件对比

中间件 类型 定位 与GStreamer关系
GStreamer 多媒体框架 应用层中间件 自身就是中间件
FFmpeg 编解码库 底层库 GStreamer可作为前端调用FFmpeg插件
WebRTC 实时通信框架 应用层中间件 GStreamer可集成WebRTC(通过webrtcbin)
Live555 RTSP/RTP库 协议栈 GStreamer的rtspclientsink内部使用
PulseAudio 音频服务 系统中间件 GStreamer通过pulsesrc/pulsesink调用
OpenMAX 硬件加速API 系统中间件 GStreamer通过omx插件调用
VAAPI 视频加速API 系统中间件 GStreamer通过vaapi插件调用

五、思路

Q: GStreamer到底算不算中间件?

标准思路:

GStreamer 是中间件,具体来说是应用层多媒体中间件

理由如下:

1. 定义符合:中间件是位于操作系统和应用层之间的软件层,GStreamer正好在这个位置——它封装了V4L2/ALSA/VAAPI等系统API,向上提供统一的编程接口。

2. 抽象硬件差异:GStreamer屏蔽了底层硬件的差异,同一份代码可以在RK3588、树莓派、x86上运行,只需底层插件不同。

3. 提供标准接口:GStreamer定义了Element/Pad/Bin/Pipeline等编程模型,应用层只需关注Pipeline构建,无需关心底层实现。

4. 插件化架构:GStreamer采用插件系统,动态加载不同的Source/Filter/Sink,这是中间件的典型特征。

5. 与系统中间件的关系

  • 系统中间件(V4L2/ALSA):与内核直接交互

  • GStreamer(应用中间件):调用系统中间件,提供更高层抽象

所以,GStreamer是应用层中间件,而V4L2/ALSA是系统中间件,两者分层清晰。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐