【问题标题】:How to resume playing after paused using gstreamer?使用gstreamer暂停后如何恢复播放?
【发布时间】:2014-12-18 13:16:40
【问题描述】:

我为每种 Gstreamer 类型编写了 C++ 包装器。它们简单直观,所以我认为不需要在此处发布它们的实现(尽管如果需要,我可以发布它们(也许在 github 上))。

我面临的问题是我开始播放视频(并同时使用 gst tee 元素将其保存到文件中)......并且在播放时,我暂停(从不同的线程),这很好用.但是,当我想恢复它时,它不起作用:

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

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

这是我创建管道并将其状态设置为 GST_STATE_PLAYING 的 play() 函数。

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
}

如果有人能帮我找出解决这个问题的方法,我将不胜感激。

我正在使用 Qt 小部件的句柄播放视频并将其传递给 gstreamer 视频叠加层。

【问题讨论】:

  • 管道的实际状态是否变回正在播放?如果是这样,您可能需要重新显示叠加层。
  • 你能在更简单的管道上测试你的暂停/恢复代码吗,比如没有 tee 的简单 videotestsrc?我对 GStreamer 的经验是,你的管道越复杂,像这样的简单命令就越不可能起作用。解释“暂停”应该在所有元素中做什么的方法太多了。例如mp4 多路复用器应如何处理暂停流上的时间戳?创建一个长时间运行的冻结帧,还是从用户离开的地方继续?那么如果你有 mp4 muxer 和 matroska muxer 实现不同的行为呢?那种东西。
  • @mpr: 哇...如果我删除 tee 元素(连同整个分支),那么暂停/恢复效果很好。我还注意到当我使用 tee 时,pause 确实会暂停播放,但它不会改变状态(状态保持在 *_PLAYING)
  • @BenjaminTrent:不,它不会改变任何状态。即使我暂停,它也不会将状态更改为 *_PAUSED。状态停留在 *_PLAYING。但是如果我删除 tee 元素,暂停/恢复效果很好(状态也会改变)。
  • 您真的认为这可能是 Qt 问题吗?如果没有,请您删除Qt标签吗?让我担心的是,我在你的 sn-p 中没有看到一个 Q

标签: c++ video media-player gstreamer


【解决方案1】:

从 T 恤上出来的每个分支上都有队列元素吗?一个用于文件,一个用于解码?您也可以尝试使用文件接收器上的“同步”属性。也许将其设置为 true。


Nawaz编辑。

因为这个答案首先给了我几个方向,几乎是一个非常接近解决方案的方向,它值得我为这个问题设置的赏金。但在此之前,这是解决方案(解释在我的回答中 - Nawaz)。

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

希望对其他人也有帮助。

【讨论】:

  • 分支变成这样:source -> tee(在 tee 处变成两个分支)。然后tee-> demuxer -> audio-queue/video-queue-> audio-sink/video-sink。和其他分支,tee-> file-queue->file-sink.
  • 顺便说一句,我在文件接收器上看不到 sync 属性:gstreamer.freedesktop.org/data/doc/gstreamer/head/…
  • 在 tee 和 demuxer 之间添加一个队列。
  • 好的。让我试试。顺便说一句,您能解释一下为什么您认为需要这样做吗?
  • 老实说,我不知道,但文档说要这样组织你的 T 恤。 gstreamer.freedesktop.org/data/doc/gstreamer/head/…
【解决方案2】:

我自己找到了答案。我尝试将所有元素的状态打印为:

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));
         }
    }
}

然后它帮助我弄清楚所有元素的状态都从 PLAYING 变为 PAUSED 和 PAUSED 变为 PLAYING,没有任何待处理状态,除了 filesink 元素的状态保持在 PLAYING和一个挂起的 PAUSED 状态(这是因为它试图异步更改它)——最终导致我找到 GstBaseSinkasync 属性,它是 filesink 的基类。我只是将其设置为FALSE

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

就是这样。现在暂停和恢复效果很好 - 所有元素的状态从 PLAYING 变为 PAUSED 和 PAUSED 变为 PLAYING,没有任何挂起状态!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-21
    • 2021-09-02
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多