LINUX.ORG.RU

QT блокирует поток gstreamer'a

 ,


0

1

Всем здравствуйте, возникла такая проблема. Работаю с gstreamer'ом, получаю поток по rtsp с IP камеры(rtspsrc) и вывожу на экран. Если компилировать в консоли обычным gcc строкой:

gcc tt.cpp -o tt `pkg-config --cflags --libs gstreamer-0.10`
все работает прекрасно.

Но! Если создаем проект в QT и компилируем тот же самый код, ничего в нем не меняя, то появляется окно вывода с 1 кадром, далее все глохнет.

Процесс гугления ничего не дал, или может не там искал.... Не может ли кто-нибудь помочь разобраться?

Собственно проект: module.pro:

#-------------------------------------------------
#
# Module for work with cam
#
#-------------------------------------------------

QT       += core gui

SOURCES += \
    main.cpp

TARGET = module
#TEMPLATE = app

INCLUDEPATH += /opt/gstreamer-sdk/lib/pkgconfig

CONFIG += link_pkgconfig
PKGCONFIG += gstreamer-0.10 gstreamer-interfaces-0.10 glib-2.0

QMAKE_CXXFLAGS += -fpermissive

main.cpp :


#include <gst/gst.h>
#include <glib.h>

typedef struct _CustomData {
  GstElement *pipeline;
  GstElement *source;
  GstElement *sink1;
  GstElement *sink2;
  GstElement *queue;
  GstElement *queue2;
  GstElement *depay;
  GstElement *mux;
  GstElement *decode;
  GstElement *videoscale;
  GstElement *colorspace;
} CustomData;

CustomData data;

static void pad_added_handler (GstElement *src, GstPad *new_pad,
                               CustomData *data)
{
    g_debug ("Signal: pad-added");
    GstPad *sink_pad = gst_element_get_static_pad (data->queue, "sink");

    GstPadLinkReturn ret = gst_pad_link (new_pad, sink_pad);

    if (GST_PAD_LINK_FAILED (ret))
        g_print (" link failed.\n");

    else
        g_print ( " Link succeeded \n");

    gst_object_unref (sink_pad);
}

int main(int argc, char *argv[])
{
    GstBus *bus;
    GstMessage *msg;
    GstPad *tee;
    GMainLoop *loop;
    guint bus_watch_id;

    gst_init (NULL, NULL);

    loop = g_main_loop_new (NULL, FALSE);

    data.pipeline   = gst_pipeline_new ("rtsp_capture");
    data.source     = gst_element_factory_make ("rtspsrc", NULL);
    data.depay      = gst_element_factory_make ("rtph264depay", NULL);

    data.queue2     = gst_element_factory_make ("queue2", NULL);
    data.decode     = gst_element_factory_make ("ffdec_h264", NULL);
    data.colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
    data.sink1      = gst_element_factory_make ("ximagesink", NULL);

    data.queue      = gst_element_factory_make ("queue", NULL);
    data.mux        = gst_element_factory_make ("mpegtsmux", NULL);
    data.sink2      = gst_element_factory_make ("filesink", NULL);

    if (!data.pipeline  || !data.source     || !data.queue2 || !data.queue  ||
        !data.decode    || !data.colorspace || !data.sink1  || !data.mux    ||
        !data.sink2     || !data.depay   )
    {
        g_printerr ("Not all elements could be created.\n");
        //return -1;
    }

    g_object_set (data.source, "location", argv[1] , NULL);
    g_object_set (data.sink2,   "location", argv[2], NULL);
   
    bus = gst_pipeline_get_bus (GST_PIPELINE (data.pipeline));
    bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
    gst_object_unref (bus);

    gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.queue2, data.queue,
                      data.decode, data.colorspace, data.sink1, data.mux,
                      data.sink2, data.depay, NULL);

    g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);
    gst_element_link (data.queue, data.depay);
    gst_element_link (data.depay, data.decode);
    gst_element_link (data.decode, data.colorspace);
    gst_element_link (data.colorspace,  data.sink1);

    g_print ("Running...\n");
    g_main_loop_run (loop);

    g_print ("Returned, stopping playback\n");
    gst_element_set_state (data.pipeline, GST_STATE_NULL);

    g_print ("Deleting pipeline\n");
    gst_object_unref (GST_OBJECT (data.pipeline));
    g_source_remove (bus_watch_id);
    g_main_loop_unref (loop);

    return 0;
}

тут есть ряд других элементов, но на них можно не обращать внимание, т.к. они для экспериментов и комбинирования между собой.

Запуск в консоли и вывод программы:

# ./modile rtsp://*** test.mp4
Running...
 Link succeeded
//закрываем окно 
Error: Output window was closed
Returned, stopping playback
Deleting pipeline

Ответ на: комментарий от Adonai

По факту при компиляции замена gcc на g++ никак не отражается на результате. Прикрепляю строку сборки, которую генерирует QT

make: Entering directory `/home/tech/workdir/module'

g++ -c -pipe -fpermissive -g -pthread -pthread -Wall -W -D_REENTRANT -DQT_WEBKIT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I/opt/gstreamer-sdk/lib/pkgconfig -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/include/gstreamer-0.10 -I/usr/include/libxml2 -I. -o main.o main.cpp

g++  -o module main.o    -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib -pthread -lgstinterfaces-0.10 -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lxml2 -lglib-2.0 -lQtGui -lQtCore -lpthread 
{ test -n "" && DESTDIR="" || DESTDIR=.; } && test $(gdb --version | sed -e 's,[^0-9]\+\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $DESTDIR" -ex quit 'module' && test -f module.gdb-index && objcopy --add-section '.gdb_index=module.gdb-index' --set-section-flags '.gdb_index=readonly' 'module' 'module' && rm -f module.gdb-index || true

make: Leaving directory `/home/tech/workdir/module'

Just_alex ()
Ответ на: комментарий от Just_alex

Хотелось бы использовать GstXOverlay, чтобы выводить картинку в конкретный виджет, потому и QT

а как-же Phonon? пусть GStreamer остаётся, но фронтэнд пусть будет более родным для Qt.

если-ж нет и возможен только хардкод, то очевидно QApplication app(&argc,&argv) и app.exec() должны быть вместо g_main_loop_new и g_main_loop_run (loop);

разницу при прелинковке Qt библиотек можно увидить прогнав strace - неверняка какая-нить дрянь использует _init_ при загрузке и два event-loop`а (один от glib а второй,недоинициализированный от Qt) неподелили какой-нить таймер

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

не не, фонон это уже не совсем часть кутэ. Темболее фонон не дает тонко настроить ничего, да и вообще если нужно что-то серьезное, то фонон не подходит. В случае с rtsp и rtmp потоками нельзя никак убрать буфер, что дает задержку в 1-3 секунды на rtsp и 5-7 секунд rtmp.

я бы посоветовал использовать QtGstreamer, там есть впринципе всё что надо, и виджеты для оверлея и для QML и прочее. Более удобное взаимодействие с Qt вообщем. тут можешь взять http://gstreamer.freedesktop.org/modules/qt-gstreamer.html

Blastbit ()
Ответ на: комментарий от Blastbit

Спасибо за ответы, попробую и то, и другое. Хотя конечно фонон уже по предворительному просмотру выглядит не таким гибким.

Попробую и отпишусь.

Just_alex ()
Ответ на: комментарий от Blastbit

хотя вот только сейчас задумался, а эти QT билды на винде то соберутся или unix-онли? Вроде как второе. И тут остается только хардкод на gstreamer

Just_alex ()
Ответ на: комментарий от Just_alex

насчет винды не уверен, просто не пробовал, задачи такой не было. Но вроде как должно работать, ну могут конечно при сборке какие-то проблемы возникнуть, куда же без них. Надо гуглить, однозначно.

Blastbit ()
Ответ на: комментарий от Just_alex

RTFM

The backends of Qt use the media systems DirectShow (which requires DirectX) on Windows, QuickTime on Mac, and GStreamer on Linux. The functionality provided on the different platforms are dependent on these underlying systems and may vary somewhat, e.g., in the media formats supported.

EugeneBas ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.