Ваш код неверен в нескольких отношениях, поэтому мой ответ такой длинный.
Прежде всего, gst_pipeline_new
возвращает GstElement*
не GstPipeline*
:
- pipeline = gst_pipeline_new("PIPELINE");
+ GstElement *pipeline = gst_pipeline_new("PIPELINE");
Bin = GST_BIN(pipeline);
- bus = gst_pipeline_get_bus(pipeline);
+ bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
Тогда ваш конвейер неверен: вы пытаетесь декодировать оба потока (аудио и видео) с одним decodebin
, но вам нужно два.Создайте его и не забудьте добавить его в корзину:
videoqueue = gst_element_factory_make("queue","Queue for video");
+ audio_decoder = gst_element_factory_make("decodebin","a_decodebin");
video_decoder = gst_element_factory_make("decodebin","decoderbin");//"Vorbis audio decoder","vorbis");
- gst_bin_add_many(Bin,demuxer,audioqueue,videoqueue,audio_convertor,video_decoder,video_convertor,audio_sink,video_sink,NULL);
+ gst_bin_add_many(
+ Bin,
+ demuxer,
+ audioqueue,videoqueue,
+ audio_decoder,audio_convertor,
+ video_decoder,video_convertor,
+ audio_sink,video_sink,
+ NULL);
И, кстати, лучше использовать decodebin2
, поскольку decodebin
устарело.
ТогдаВы динамически связываете некоторые элементы: демультиплексор в очередь и декодер в конверторы.Следовательно, вы не должны создавать связь между декодером и конвертерами с помощью gst_element_link_many
:
gst_element_link(source,demuxer);
- gst_element_link_many(audioqueue,video_decoder,audio_convertor,audio_sink,NULL);
- gst_element_link_many(videoqueue,video_decoder,video_convertor,video_sink,NULL);
+ gst_element_link_many(audioqueue,audio_decoder,NULL);
+ gst_element_link_many(audio_convertor,audio_sink,NULL);
+ gst_element_link_many(videoqueue,video_decoder,NULL);
+ gst_element_link_many(video_convertor,video_sink,NULL);
И, конечно, поскольку мы добавили audio_decoder
декодер, нам нужно обработать его сигнал создания пэда:
+ g_signal_connect(audio_decoder,"new-decoded-pad",G_CALLBACK(dynamic_decodepad),NULL);
g_signal_connect(video_decoder,"new-decoded-pad",G_CALLBACK(dynamic_decodepad),NULL);
А теперь мы в самой интересной части.
void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
{
GstPad *audiodemuxsink;
GstPad *videodemuxsink;
GstElement *decoder = (GstElement *)data;
g_print(" In dynamic ADDING PAD\n");
audiodemuxsink = gst_element_get_static_pad(audioqueue,"sink");
gst_pad_link(pad,audiodemuxsink );
videodemuxsink = gst_element_get_static_pad(videoqueue,"sink");
gst_pad_link(pad,videodemuxsink );
g_print(" In dynamic ADDING PAD2\n");
}
Это совершенно неправильно!dynamic_addpad
вызывается при создании каждого пэда.avidemux
обычно создает две панели (по одной для каждого потока данных): «audio_00» и «video_00».Итак, dynamic_addpad
будет вызываться дважды, и нам нужно различать, что связывать, в зависимости от имени пэда:
void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
{
char* pad_name = gst_pad_get_name(pad);
g_print(" In dynamic ADDING PAD %s\n", pad_name);
if (g_str_has_prefix(pad_name,"audio")) {
GstPad *audiodemuxsink = gst_element_get_static_pad(audioqueue,"sink");
gst_pad_link(pad,audiodemuxsink );
}
else if (g_str_has_prefix(pad_name,"video")) {
GstPad *videodemuxsink = gst_element_get_static_pad(videoqueue,"sink");
gst_pad_link(pad,videodemuxsink );
}
g_free (pad_name);
}
Почти то же самое для dynamic_decodepad
.Поскольку декодер создает только один пэд src, будет проще создавать отдельные обработчики для video_decoder
и audio_decoder
.
Но по педагогическим причинам я сделаю это в одной функции.Теперь мы можем различить, какой элемент подключать к пэду по заглавным буквам.
void dynamic_decodepad (GstElement* object, GstPad* pad, gboolean arg1,gpointer user_data)
{
GstPad* videoconvertsink = gst_element_get_static_pad(video_convertor,"sink");
if (gst_pad_can_link(pad,videoconvertsink)) {
gst_pad_link(pad,videoconvertsink);
}
GstPad* audioconvertsink = gst_element_get_static_pad(audio_convertor,"sink");
if (gst_pad_can_link(pad,audioconvertsink)) {
gst_pad_link(pad,audioconvertsink);
}
}
gst_pad_can_link
не будет работать в dynamic_addpath
, потому что можно подключить элемент query
как к «audio_00», так и к «video_00».".
Вот и все.Не стесняйтесь спрашивать, если у вас есть другие вопросы.