У меня есть конвейер GStreamer, который извлекает видео из элемента rtspsrc.Элемент rtspsrc подключается к элементу rtpjpegdepay.Я хотел бы иметь возможность изменить URL RTSP на лету.Пока что я делал:
1) отсоединение rtspsrc от элемента depay
2) создание нового исходного элемента с новым RTSP URL
3) и связывание с элементом depay.
Проблема, с которой я сталкиваюсь, заключается в том, что новый исходный элемент RTSP неправильно связывается с элементом depay, что приводит к ошибкам сегмента.Мне нужна помощь в выяснении того, как динамически изменять URL-адрес rtspsrc (пока конвейер все еще играет).
Создание конвейера:
GstBus *bus;
guint busWatchId;
GstElement *src, *depay, *parser, *decoder, *vpe, *filter, *sink;
GstCaps *vpeCaps;
m_loop = g_main_loop_new(NULL, FALSE);
//create pipeline elements
m_cameraStream = gst_pipeline_new("display_pipeline");
src = gst_element_factory_make("rtspsrc", "rtspsrc");
depay = gst_element_factory_make("rtpjpegdepay", "depay");
parser = gst_element_factory_make("jpegparse", NULL);
decoder = gst_element_factory_make("ducatijpegdec", NULL);
vpe = gst_element_factory_make("vpe", NULL);
filter = gst_element_factory_make("capsfilter", NULL);
sink = gst_element_factory_make("waylandsink", NULL);
if(!(m_cameraStream || src || depay || parser || decoder || vpe || filter || sink)){
qFatal("could not create pipeline elements");
exit(1);
}
g_object_set(G_OBJECT(src), "location", "rtsp://192.168.50.29/av0_1", "latency", 0, NULL);
g_signal_connect(src, "pad-added", G_CALLBACK(on_rtsp_pad_added), depay);
//add src caps?
vpeCaps = gst_caps_from_string("video/x-raw, format=NV12, width=800, height=480"); //change this when Tomas' patch hits
if(!vpeCaps){
qFatal("cannot create caps");
exit(1);
}
g_object_set(G_OBJECT(filter), "caps", vpeCaps, NULL);
g_object_set(G_OBJECT(sink), "sync", false, NULL);
//add and link elements to create full pipeline
gst_bin_add_many(GST_BIN(m_cameraStream), src, depay, parser, decoder, vpe, sink, NULL);
if(!gst_element_link_many(depay, parser, decoder, vpe, sink, NULL)){
qFatal("cannot link elements");
exit(1);
}
gst_caps_unref(vpeCaps);
bus = gst_pipeline_get_bus(GST_PIPELINE(m_cameraStream));
busWatchId = gst_bus_add_watch(bus, GstBusFunc(bus_call), m_loop);
gst_object_unref(bus);
rtsp-> Функция обратного связывания с удалением ссылок:
gchar *name;
GstElement *depay;
GstCaps *caps;
qDebug("on_rtsp_pad_added");
caps = gst_caps_from_string("application/x-rtp");
name = gst_pad_get_name(pad);
qDebug("on_rtsp_pad_added, rtspsrc pad name: %s", name);
depay = GST_ELEMENT(data);
if(!gst_element_link_pads_filtered(element, name, depay, "sink", caps)){
qFatal("pad_added: failed to link elements");
}
g_free(name);
gst_element_set_state(m_cameraStream, GST_STATE_PLAYING);
g_main_loop_run(m_loop);
Функция изменения источника:
qDebug("slot_changeSource");
//gst_element_set_state(m_cameraStream, GST_STATE_PAUSED); //GST_STATE_NULL: segfault in pad_added
//GST_STATE_PAUSED: pauses, never returns to playing or on_rtsp_pad_added
//GST_STATE_PLAYING(left playing): same as NULL
GstElement* rtspsrc = gst_bin_get_by_name(GST_BIN(m_cameraStream), "rtspsrc");
if(rtspsrc){
qDebug("rtspsrc found");
GstElement* depay = gst_bin_get_by_name(GST_BIN(m_cameraStream), "depay");
if(depay){
qDebug("depay found");
gst_element_unlink(rtspsrc, depay);
gst_bin_remove(GST_BIN(m_cameraStream), rtspsrc);
GstElement* newSource = gst_element_factory_make("rtspsrc", "rtspsrc");
g_object_set(G_OBJECT(newSource), "location", "rtsp://192.168.50.29/av0_1", "latency", 0, NULL);
g_signal_connect(newSource, "pad-added", G_CALLBACK(on_rtsp_pad_added), depay); //needed in the same way as the previous rtspsrc
gst_bin_add(GST_BIN(m_cameraStream), newSource);
gst_element_sync_state_with_parent(newSource);
//gst_element_set_state(m_cameraStream, GST_STATE_PLAYING);
}
gst_element_set_state(rtspsrc, GST_STATE_NULL);
gst_object_unref(rtspsrc);
}
Другие вещи, которые я пробовал:
1) Зондирование площадки src элемента rtsp, чтобы убедиться, что нетлюбые данные в элементе.Это казалось плохой идеей, поскольку элемент rtsp был бы только что создан на этом этапе.
2) Установите конвейер на PAUSED или NULL, затем измените исходный элемент.Это приводит к тому, что конвейер временно останавливается.
Ссылки:
Список рассылки Gstreamer
Документация