
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 可以做到音视频互不影响,更适合实时通信场景。