简体   繁体   English

使用gstreamer暂停后如何恢复播放?

[英]How to resume playing after paused using gstreamer?

I've written C++ wrapper for each Gstreamer types. 我已经为每种Gstreamer类型编写了C ++包装器。 They're simple and intuitive, so I don't think their implementation needs to be posted here (though I could post them (maybe at github) if need arises). 它们简单直观,因此我认为它们的实现不需要在此处发布(尽管如有需要,我可以将它们发布(也许在github上))。

The problem I'm facing is that I start playing a video (and simulteneously saving it to a file using gst tee element)....and while it is playing, I pause (from different thread) which is working great. 我面临的问题是我开始播放视频(并同时使用gst tee元素将其保存到文件中)....并且在播放时,我暂停了(从其他线程执行),效果很好。 However, when I want to resume it, it doesn't work: 但是,当我想恢复它时,它不起作用:

void pause()
{
    _pipeline.state(GST_STATE_PAUSED)
}

void resume()
{
    _pipeline.state(GST_STATE_PLAYING);
}

And here is the play() function where I create the pipeline and set it state to GST_STATE_PLAYING. 这是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
}

I'd appreciate if anybody could help me figuring out the solution to this problem. 如果有人可以帮助我解决此问题的解决方案,我将不胜感激。

I'm playing the video on Qt widget using its handle and passing it to gstreamer video overlay. 我正在使用其手柄在Qt小部件上播放视频,并将其传递到gstreamer视频叠加层。

Do you have queue elements on each branch that comes off the tee? 发球台上的每个分支上都有队列元素吗? One for the file and one for the decode? 一个用于文件,另一个用于解码? You could also try messing around with the "sync" property on the filesink. 您也可以尝试在filesink上弄乱“ sync”属性。 Maybe set it to true. 也许将其设置为true。


Edited by Nawaz . Nawaz编辑。

Since this answer first gave me few directions and almost a very-near-to-the-solution direction, it deserves the bounty I've set for this question. 由于此答案首先给了我很少的指导,几乎是解决问题的几乎指导,因此,我应该为此问题设置赏金。 But before that, here is the solution (explanation is in my answer - Nawaz). 但是在此之前,这是解决方案(我的回答是解释-Nawaz)。

gst::element filesink("filesink", "file-sink");
filesink.set("async", gboolean(FALSE));

Hope that helps other as well. 希望对其他人也有帮助。

I found the answer myself. 我自己找到了答案。 I tried to print the status of all the elements as: 我试图将所有元素的状态打印为:

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, &current, &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));
         }
    }
}

And then it helped me figured out that the status of all the elements were changing from PLAYING to PAUSED and PAUSED to PLAYING, without any pending state, except filesink element whose state remains at PLAYING and a pending PAUSED state (which is because it attempts to change it asynchronously) — that eventually led me to the async property of the GstBaseSink which is the base class of filesink . 然后,它帮助我弄清楚了所有元素的状态都从PLAYING变为PAUSED以及PAUSED变为PLAYING,没有任何挂起状态, 除了 filesink元素的状态仍为PLAYING和挂起的PAUSED状态(这是因为它试图改变它异步) -这最终导致我到async的财产GstBaseSink这是基类的filesink I just set it to FALSE as: 我只是将其设置为FALSE为:

gst::element filesink("filesink", "file-sink");
filesink.set("async", gboolean(FALSE));

That's it. 而已。 Now pause and resume works great — status of all the elements change to PLAYING to PAUSED and PAUSED to PLAYING, without any pending state! 现在,暂停和恢复效果很好- 所有元素的状态变为“正在播放”到“暂停”,而“暂停”到“播放”,没有任何待处理状态!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM