Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
569 views
in Technique[技术] by (71.8m points)

c++ - How to resume playing after paused using gstreamer?

I've written C++ wrapper for each Gstreamer types. 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).

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. 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.

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
", 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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. Maybe set it to true.


Edited by 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).

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

Hope that helps other as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...