GStreamer 使用 valve 分别控制音视频流的暂停与恢复

1. 需求背景

在 GStreamer 中,如果一条 pipeline 同时包含 audio 和 video 两路流,往往需要单独控制 其中某一路的暂停与恢复,而不是整条 pipeline 一起暂停。此时可以使用 GStreamer 的 valve 元件:为两路流分别定义一个 valve,再通过控制 valve 的 drop 属性实现放行或丢弃。

2. 在 pipeline 中定义 valve

下面的 pipeline 描述中,分别为 video 和 audio 定义了一个 valve:

c 复制代码
// valve 专门负责 GStreamer 的 audio/video 数据放行
std::string pipline_desc =
    "videotestsrc is-live=true pattern=ball ! videoconvert ! queue ! "
    "valve name=video_valve drop=false ! "
    "vp8enc deadline=1 ! rtpvp8pay name=rtp_video_pay pt=96 ! queue name=vsrc_queue "

    "audiotestsrc is-live=true ! audioconvert ! audioresample ! queue ! "
    "valve name=audio_valve drop=false ! "
    "opusenc ! rtpopuspay name=rtp_audio_pay pt=111 ! queue name=asrc_queue "
    "webrtcbin name=webrtcbin bundle-policy=max-bundle stun-server=" STUN_SERVER;

其中分别为 audio 和 video 定义了 valve:

c 复制代码
valve name=video_valve
valve name=audio_valve

3. 获取 valve 元件

pipeline 构建完成后,通过元件名称取出对应的 GstElement:

c 复制代码
static GstElement *g_video_valve = NULL;
static GstElement *g_audio_valve = NULL;

...
...
...
g_video_valve = gst_bin_get_by_name(GST_BIN(g_pipeline), "video_valve");
g_audio_valve = gst_bin_get_by_name(GST_BIN(g_pipeline), "audio_valve");

4. 按 all / video / audio 细分控制

拿到 valve 之后,就可以按 kind 参数分别控制整条 pipeline、video 流或 audio 流:

c 复制代码
else if (cmd == "set-media-flow")
{
    LOG_INFO("收到媒体设置信令");
    std::string kind = data.value("kind", "all");
    bool enabled = data.value("enabled", false);
    LOG_INFO("kind:%s, enabled=%d \n", kind.c_str(), enabled);

    GstState curr_state;
    gst_element_get_state(g_pipeline, &curr_state, NULL, 100 * 1000);

    if (enabled == 1)
    {
        if (kind == "all")
        {
            gst_element_set_state(g_pipeline, GST_STATE_PLAYING);
        }
        else if (kind == "video")
        {
            g_object_set(g_video_valve, "drop", FALSE, NULL);
        }
        else if (kind == "audio")
        {
            g_object_set(g_audio_valve, "drop", FALSE, NULL);
        }
    }
    else if (enabled == 0)
    {
        if (kind == "all")
        {
            gst_element_set_state(g_pipeline, GST_STATE_PAUSED);
        }
        else if (kind == "video")
        {
            g_object_set(g_video_valve, "drop", TRUE, NULL);
        }
        else if (kind == "audio")
        {
            g_object_set(g_audio_valve, "drop", TRUE, NULL);
        }
    }
}

5. 小结

  • valve 的 drop=true 表示丢弃该路数据,drop=false 表示正常放行。
  • 通过 gst_bin_get_by_name 按名称获取 valve 元件,即可在运行时动态切换。
  • 相比直接暂停整条 pipeline,使用 valve 可以做到音视频互不影响,更适合实时通信场景。
相关推荐
辰辰观影1 小时前
无广告播放器推荐来啦
音视频
一条破秋裤2 小时前
基于 Hi3516CV610 的立定跳远视频测量系统调研与实施方案
arm开发·音视频
2601_966827452 小时前
视频里的特效字幕怎么翻译?外挂字幕与AI字幕一键处理教程
音视频
八月的雨季 最後的冰吻3 小时前
音视频面试--延迟优化
面试·职场和发展·音视频
智能直播4 小时前
MEDAI-W2_Tinyalsa音频_HDMI输出_CSDN文章
音视频·实时音视频·视频编解码
狗凯之家源码网16 小时前
吃瓜主题 3.0 视频源码深度评测与实战指南
音视频
美狐美颜sdk20 小时前
视频美颜SDK中的YUV与RGBA格式有什么区别?直播APP开发解析
人工智能·计算机视觉·音视频·美颜sdk·直播美颜sdk·视频美颜sdk
音视频牛哥21 小时前
不止于超低延迟:SmartMediaKit iOS Unity3D RTSP/RTMP 播放器的核心竞争力
音视频·unity3d rtsp播放器·unity3d rtmp播放器·smartmediakit·ios unity rtsp·ios unity rtmp·unity3d ios播放器
辰辰观影1 天前
网盘视频播放器怎么选?2026全平台推荐
经验分享·音视频