我想创建一个管道,在输入和输出不同分辨率的jpeg图像中获取rtsp流。当管道正在播放时,我想阻止某个分支,但我无法阻止该元素。
命令行如下所示:
gst-launch-1.0 -v rtspsrc location="rtsp://ip:port/live.sdp" ! rtph264depay ! h264parse ! avdec_h264 ! videorate ! video/x-raw,framerate=5/1 ! tee name=t ! queue ! videoscale ! video/x-raw,width=320,height=240 ! jpegenc ! multifilesink location=snapshot320-%05d.jpg t. ! queue ! videoscale ! video/x-raw,width=1280,height=720 ! jpegenc ! multifilesink location=snapshot1280-%05d.jpg
我希望能够阻止数据通过分支,但我无法使用tee元素。
我已经看到函数gst_pad_add_probe允许阻止元素的填充。
这就是我所做的:
1)拿到垫子:
srcpad = gst_element_get_static_pad(tee, "src");
sinkpad = gst_element_get_static_pad(tee, "sink");
2)添加探针:
gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_IDLE, &GstProbeCallback, this, NULL)
3)刷新数据:
gst_pad_send_event (sinkpad, gst_event_new_eos ());
4)解开垫子
gst_object_unref (sinkpad);
gst_object_unref (srcpad);
5)将管道设置为播放状态:
gst_element_set_state(this->pipeline, GST_STATE_PLAYING)
这是给gst_pad_add_probe的回调:
static GstPadProbeReturn
GstProbeCallback(GstPad* pad, GstPadProbeInfo* info, gpointer user_data) {
std::cout << "probe callback" << std::endl;
return GST_PAD_PROBE_DROP;
}
[更新]
如果我将探针设置在tee元素后面的队列中,那么我的所有分支都会被阻塞。 更多代码如下:
this->pipeline = gst_pipeline_new(NULL);
if (this->pipeline == NULL) {
LOG_ERR("Failed to create the pipeline", "image_configuration");
return NULL;
}
this->elements.tree.src = gst_element_factory_make("rtspsrc", NULL);
this->elements.tree.depay = gst_element_factory_make("rtph264depay", NULL);
this->elements.tree.parse = gst_element_factory_make("h264parse", NULL);
this->elements.tree.dec = gst_element_factory_make("avdec_h264", NULL);
this->elements.tree.rate = gst_element_factory_make("videorate", NULL);
this->elements.tree.ratefilter = gst_element_factory_make("capsfilter", NULL);
this->elements.tree.tee = gst_element_factory_make("tee", NULL);
for (auto& branch : this->elements.branches) {
branch.queue = gst_element_factory_make("queue", NULL);
branch.scale = gst_element_factory_make("videoscale", NULL);
branch.scalecaps = gst_element_factory_make("capsfilter", NULL);
branch.enc = gst_element_factory_make("jpegenc", NULL);
branch.sink = gst_element_factory_make("redissink", NULL);
branch.fakesink = gst_element_factory_make("fakesink", NULL);
if (not(branch.queue && branch.scale && branch.scalecaps && branch.sink && branch.enc &&
branch.fakesink)) {
LOG_ERR("Failed to create elements", "image_configuration");
return NULL;
}
}
if (!this->pipeline || !this->elements.tree.src || !this->elements.tree.depay ||
!this->elements.tree.parse || !this->elements.tree.dec || !this->elements.tree.rate ||
!this->elements.tree.ratefilter || !this->elements.tree.tee) {
LOG_ERR("Failed to create elements", "image_configuration");
return NULL;
}
this->set_rate_caps(this->elements.tree.ratefilter);
g_object_set(
this->elements.tree.src, "location", this->loc_in.c_str(), "latency", this->latency, NULL);
for (auto& branch : this->elements.branches) {
this->set_scale_caps(branch.scalecaps, branch.resolution);
g_object_set(branch.enc, "quality", 50, NULL);
g_object_set(branch.sink, "func", &send_event, NULL);
g_object_set(branch.sink, "camera_id", this->camera_id, NULL);
g_object_set(branch.sink, "is_init", TRUE, NULL);
}
gst_bin_add_many(GST_BIN(this->pipeline),
this->elements.tree.src,
this->elements.tree.depay,
this->elements.tree.parse,
this->elements.tree.dec,
this->elements.tree.rate,
this->elements.tree.ratefilter,
this->elements.tree.tee,
NULL);
for (const auto& branch : this->elements.branches) {
gst_bin_add_many(GST_BIN(this->pipeline),
branch.queue,
branch.scale,
branch.scalecaps,
branch.enc,
branch.sink,
branch.fakesink,
NULL);
}
if (!gst_element_link_many(this->elements.tree.depay,
this->elements.tree.parse,
this->elements.tree.dec,
this->elements.tree.rate,
this->elements.tree.ratefilter,
this->elements.tree.tee,
NULL)) {
LOG_ERR("Failed to link elements", "image_configuration");
return NULL;
}
g_signal_connect(
this->elements.tree.src, "pad-added", G_CALLBACK(on_pad_added), &this->elements);
for (const auto& branch : this->elements.branches) {
if (!gst_element_link_many(this->elements.tree.tee,
branch.queue,
branch.scale,
branch.scalecaps,
branch.enc,
branch.sink,
branch.fakesink,
NULL)) {
LOG_ERR("Failed to link elements", "image_configuration");
return NULL;
}
}
if (not this->launch_pipeline()) return NULL;
getchar();
std::cout << "Add probe" << std::endl;
GstPad* srcpad;
GstPad* sinkpad;
srcpad = gst_element_get_static_pad(this->elements.branches[0].queue, "src");
sinkpad = gst_element_get_static_pad(this->elements.branches[0].queue, "sink");
this->elements.branches[0].probe_id =
gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK, &GstProbeCallback, this, NULL);
gst_pad_send_event (sinkpad, gst_event_new_eos ());
gst_object_unref (sinkpad);
gst_object_unref (srcpad);
return this->pipeline;
任何帮助将不胜感激