Я написал оболочку C ++ для каждого типа Gstreamer. Они просты и интуитивно понятны, поэтому я не думаю, что их реализация должна быть размещена здесь (хотя я мог бы опубликовать их (возможно, на github), если возникнет такая необходимость).
Проблема, с которой я сталкиваюсь, заключается в том, что я начинаю воспроизводить видео (и одновременно сохраняю его в файл, используя элемент gst tee) …. и пока оно воспроизводится, я делаю паузу (из другого потока), которая прекрасно работает. Однако, когда я хочу возобновить это, это не работает:
void pause()
{
_pipeline.state(GST_STATE_PAUSED)
}
void resume()
{
_pipeline.state(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
}
Я был бы признателен, если бы кто-нибудь мог помочь мне найти решение этой проблемы.
Я играю видео на виджете Qt, используя его дескриптор и передаю его в оверлей видео gstreamer.
Есть ли у вас элементы очереди на каждой ветви, которая идет от тройника? Один для файла и один для декодирования? Вы также можете попробовать поэкспериментировать со свойством «sync» на файловом канале. Может быть, установите его в true.
Отредактировано Наваз.
Так как этот ответ сначала дал мне несколько указаний и почти очень-почти-к-решения Направление, оно заслуживает награды за этот вопрос. Но перед этим вот решение (объяснение в моем ответе — Наваз).
gst::element filesink("filesink", "file-sink");
filesink.set("async", gboolean(FALSE));
Надеюсь, что это помогает и другим.
Я нашел ответ сам. Я попытался напечатать статус всех элементов как:
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));
}
}
}
И затем это помогло мне выяснить, что статус всех элементов менялся с PLAYING на PAUSED и PAUSED на PLAYING без какого-либо состояния ожидания, Кроме filesink
элемент, состояние которого остается в состоянии PLAYING и в состоянии ожидания PAUSED (которое происходит потому, что он пытается изменить его асинхронно) — что в конечном итоге привело меня к async
собственность GstBaseSink
который является базовым классом filesink
, Я просто установил это FALSE
как:
gst::element filesink("filesink", "file-sink");
filesink.set("async", gboolean(FALSE));
Вот и все. Теперь пауза и резюме работает отлично — статус все элементы изменяются на PLAYING на PAUSED и PAUSED на PLAYING без состояния ожидания!