Naw*_*waz 1 c++ video gstreamer media-player
我为每个 Gstreamer 类型编写了 C++ 包装器。它们简单直观,所以我认为不需要在此处发布它们的实现(尽管我可以在需要时发布它们(也许在 github 上))。
我面临的问题是我开始播放视频(并同时使用 gst tee 元素将其保存到文件中)......在播放时,我暂停(来自不同的线程),效果很好。但是,当我想恢复它时,它不起作用:
void pause()
{
_pipeline.state(GST_STATE_PAUSED)
}
void resume()
{
_pipeline.state(GST_STATE_PLAYING);
}
Run Code Online (Sandbox Code Playgroud)
这是play()我创建管道并将其状态设置为 GST_STATE_PLAYING的函数。
int play(std::string const & source_path, std::string const & save_as_file)
{
gst::element source(source_path.substr(0,4) == "http" ? "souphttpsrc" : "filesrc", "media-source");
gst::element demuxer("decodebin", "decoder");
gst::element vconv("videoconvert", "vconverter");
gst::element vsink("autovideosink", "video-output");
gst::element aconv("audioconvert", "aconverter");
gst::element asink("autoaudiosink", "audio-output");
gst::element filesink("filesink", "file-sink");
gst::element fq("queue", "file-queqe");
gst::element tee("tee", "media-tee");
gst::element aq("queue", "audio-queue");
gst::element vq("queue", "video-queue");
source.set("location", source_path.c_str());
gst::bus bus = _pipeline.bus();
guint bus_watch_id = _session.add_watch(bus);
_pipeline.add(source, demuxer, vconv, vsink, aconv, asink, filesink, tee,fq, aq, vq);
gst::element::link(source, tee);
gst::element::link(vq, vconv, vsink);
gst::element::link(aq, aconv, asink);
gst::pad tee_src_pad = tee.request_pad("src_%u");
gst::pad demuxer_sink_pad = demuxer.static_pad("sink");
gst::pad::link(tee_src_pad, demuxer_sink_pad);
filesink.set("location", save_as_file.c_str());
gst::element::link(fq, filesink);
gst::pad tee_src_pad2 = tee.request_pad("src_%u");
gst::pad fq_pad = fq.static_pad ("sink");
gst::pad::link(tee_src_pad2, fq_pad);
gst::element::dynamic_link(demuxer, aq);
gst::element::dynamic_link(demuxer, vq);
g_print ("Now playing: %s\n", source_path.c_str());
_pipeline.state(GST_STATE_PLAYING);
//code
_session.run()
//cleanup
}
Run Code Online (Sandbox Code Playgroud)
如果有人可以帮助我找出解决此问题的方法,我将不胜感激。
我正在使用其句柄在 Qt 小部件上播放视频并将其传递给 gstreamer 视频叠加层。
从发球台出来的每个分支上是否都有队列元素?一个用于文件,一个用于解码?您还可以尝试弄乱文件接收器上的“同步”属性。也许将其设置为true。
纳瓦兹编辑。
由于这个答案首先给了我几个方向,而且几乎是一个非常接近解决方案的方向,因此它值得我为这个问题设置的赏金。但在此之前,这是解决方案(解释在我的答案中 - Nawaz)。
gst::element filesink("filesink", "file-sink");
filesink.set("async", gboolean(FALSE));
Run Code Online (Sandbox Code Playgroud)
希望对其他人也有帮助。
我自己找到了答案。我尝试将所有元素的状态打印为:
void print_status_of_all()
{
auto it = gst_bin_iterate_elements(GST_BIN(_pipeline.raw()));
GValue value = G_VALUE_INIT;
for(GstIteratorResult r = gst_iterator_next(it, &value); r != GST_ITERATOR_DONE; r = gst_iterator_next(it, &value))
{
if ( r == GST_ITERATOR_OK )
{
GstElement *e = static_cast<GstElement*>(g_value_peek_pointer(&value));
GstState current, pending;
auto ret = gst_element_get_state(e, ¤t, &pending, 100000);
g_print("%s(%s), status = %s, pending = %s\n", G_VALUE_TYPE_NAME(&value), gst_element_get_name(e), gst_element_state_get_name(current), gst_element_state_get_name(pending));
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后它帮助我弄清楚所有元素的状态都从 PLAYING 更改为 PAUSED 并从 PAUSED 更改为 PLAYING,没有任何挂起状态,除了 filesink状态保持在 PLAYING 和挂起 PAUSED 状态的元素(这是因为它试图更改它是异步的)——这最终引导我找到了async的属性,GstBaseSink它是 的基类filesink。我只是将其设置为FALSE:
gst::element filesink("filesink", "file-sink");
filesink.set("async", gboolean(FALSE));
Run Code Online (Sandbox Code Playgroud)
就是这样。现在,暂停和恢复效果很好 -所有元素的状态都从“播放”变为“暂停”,从“暂停”变为“播放”,没有任何待处理状态!