Gstreamer with multithread app (Qt)

Matias Hernandez Arellano msdark at archlinux.cl
Tue Apr 12 15:14:42 PDT 2011


Well.. i will try!
El 12-04-2011, a las 17:03, Michael Joachimiak escribió:

> Does your StreamThread inherits from QThread? If not you have the answer.
> 
> I think generally you have a problem here because you are using singal/slot
> mechanism which was designed for GUI not for normal (fast) operation. I
> could not find it in the documentation (somebody please correct me if wrong)
> but my guess is that signal/slot mechanism is using qtimer.
> Excerpt from the documentation: "In general, emitting a signal that is
> connected to some slots, is approximately ten times slower than calling the
> receivers directly, with non-virtual function calls." From here
> http://doc.qt.nokia.com/latest/signalsandslots.html.
> 
> So if you want some real-time processing to happen and you have a
> producer-consumer scenario I would suggest to use semaphores (QSemaphore )
> for that.
> 
> Otherways (if qtimer is involved in multithreading) you will get performance
> issues sooner or later.
> Checked on my own skin.
> 
> 
> 
> If not I guess it should
> 
> 2011/4/13 Matias Hernandez Arellano <msdark at archlinux.cl>
> 
>> (me again)...
>> Well i try it a lot of things and finally i get a proof of concept of the
>> final application semi functional using Qt+OpenCV+QGstreamer ...
>> but.. yet.. i have a problem..
>> 
>> Here some snippets of code
>> 
>> main.cpp
>> int main(int argc, char *argv[]){
>>   QCoreApplication a(argc, argv);
>>   QGst::init(&argc,&argv);
>>   FrameBuffer *buffer = new FrameBuffer(3);
>>   FrameBuffer *buffer2 = new FrameBuffer(3);
>>   CaptureThread *capture = new CaptureThread(buffer,0);
>>   ProcessingThread *processing = new
>> ProcessingThread(buffer,buffer2,capture->getSourceWidth(),capture->getSourceHeight());
>>   StreamThread     *stream     = new StreamThread(buffer2);
>> 
>> QCoreApplication::connect(processing,SIGNAL(newframe()),stream,SLOT(update()),Qt::QueuedConnection);
>>   capture->start();
>>   processing->start();
>>   stream->start();
>>   return a.exec();;
>> }
>> 
>> buffer and buffer2 are Circular Buffers that hold cv::Mat (OpenCV Images).
>> buffer hold cv::Mat obtained with CaptureThread. ProcessingThread pull
>> images from here.
>> ProcessingThread push images into buffer2 and StreamThread pull images from
>> here.
>> 
>> The cycle works good...
>> now the StreamThread
>> 
>> StreamThread::StreamThread(FrameBuffer *b, QObject *parent):
>> ImageBuffer(b),QThread(parent){
>>   QString pipe_str = QString("appsrc name=\"appsrc\"
>> caps=\"video/x-raw-rgb,width=320,height=240\" ! queue ! videoparse format=14
>> width=%1 height=%1 ! videorate "
>>                              " ! videoscale !
>> video/x-raw-rgb,width=320,height=240 "
>>                              " ! queue ! ffmpegcolorspace ! jpegenc  !
>> queue  "
>>                              " ! tcpserversink port=5000
>> ").arg(WIDTH,HEIGHT);
>>   this->pipeline =
>> QGst::Parse::launch(pipe_str).dynamicCast<QGst::Pipeline>();
>> 
>> QGlib::connect(this->pipeline->bus(),"message",this,&StreamThread::onBusMessage);
>>   this->pipeline->bus()->addSignalWatch();
>>   this->pipeline->setState(QGst::StatePlaying);
>>   this->m_src.setElement(this->pipeline->getElementByName("appsrc"));
>> }
>> void StreamThread::onBusMessage(const QGst::MessagePtr &message){
>>   switch (message->type()) {
>>   case QGst::MessageEos:
>>       quit();
>>       break;
>>   case QGst::MessageError:
>>       qCritical() << message.staticCast<QGst::ErrorMessage>()->error();
>>       break;
>>   default:
>>       break;
>>   }
>> }
>> void StreamThread::run(){
>>   this->exec();
>> }
>> 
>> //This SLOT fires up when ProcessingThread calls the newImage() SIGNAL ..
>> // this signal ocurrs when a new processing image was push into the buffer
>> void StreamThread::update(){
>>   if(!this->m_src.element().isNull()){
>>       this->pipeline->setState(QGst::StatePlaying);
>>       QGst::BufferPtr buffer =
>> QGst::Buffer::create(WIDTH*HEIGHT*3*sizeof(quint8*));
>>       quint8 *data = buffer->data();
>>       Mat frame = this->ImageBuffer->getFrame();
>>       data      = (quint8*)frame.data;
>>       QGst::FlowReturn ret = this->m_src.pushBuffer(buffer);
>>       if(ret!=QGst::FlowOk){
>>           qDebug()<<"Error pushing data";
>>       }
>>   }
>> }
>> StreamThread::~StreamThread(){
>>   this->pipeline->setState(QGst::StateNull);
>> }
>> 
>> When i run this app i don't get errors, just this warning (this doesn't
>> show if i don't execute StreamThread)
>> QObject::startTimer: QTimer can only be used with threads started with
>> QThread
>> So i suppose that QGstreamer use QTimer in some hidden part.
>> 
>> And... if i try to see the stream using
>> gst-launch tcpclientsrc host=127.0.0.1 port=5000 !  jpegdec ! queue !
>> video/x-raw-rgb,width=320,height=240 ! ffmpegcolorspace ! queue !
>> glimagesink sync=false
>> 
>> I get:
>> Estableciendo el conducto a PAUSA ?
>> El conducto est? PREPAR?NDOSE ?
>> 
>> But the pipeline never goes to PLAYING and nothing happen (i can't see the
>> result)...
>> 
>> Any idea??
>> 
>> Thanks in advance
>> 
>> 
>> El 08-04-2011, a las 4:34, Tim-Philipp Müller escribió:
>> 
>>> On Thu, 2011-04-07 at 18:20 -0400, Matias Hernandez Arellano wrote:
>>> 
>>>> It's possible to use gstreamer in a multithread app?
>>> 
>>> Yes.
>>> 
>>>> I have an Producer/Consumer application where i have two groups 1 with
>>>> 1 Producer and 1 Cosumer (Capture Video with Opencv/Process Image) and
>>>> other group equal ... Take de Process Frame  / Stream the frames...
>>> 
>>> Have you considered writing a simple source element that captures and
>>> processes the frame directly in a GStreamer pipeline?
>>> 
>>>> The communication between threads works good, but know i need to add
>>>> the stream part .. I have another app where i test the functionality of
>>>> AppSrc and works!!! .. So i need to add this (Read from the Buffer
>>>> where i have images, push into AppSrc and Stream over network) in a
>>>> thread.
>>>> 
>>>> is this possible??
>>> 
>>> Why would this not be possible? Have you tried it and run into problems?
>>> 
>>> GStreamer does (almost) all of its processing in dedicated threads of
>>> its own ("streaming threads"). You should be able to push buffers into
>>> appsrc from any application thread (they will get queued internally in
>>> appsrc and then processed in the GStreamer streaming thread).
>>> 
>>> Cheers
>>> -Tim
>>> 
>>> 
>>> _______________________________________________
>>> gstreamer-devel mailing list
>>> gstreamer-devel at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>> 
>> Matías Hernandez Arellano
>> Ingeniero de Software/Proyectos en VisionLabs S.A
>> CDA Archlinux-CL
>> www.msdark.archlinux.cl
>> 
>> 
>> 
>> 
>> _______________________________________________
>> gstreamer-devel mailing list
>> gstreamer-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>> 
> 
> 
> 
> -- 
> Your Sincerely
> Michal Joachimiak
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

Matías Hernandez Arellano
Ingeniero de Software/Proyectos en VisionLabs S.A
CDA Archlinux-CL
www.msdark.archlinux.cl






More information about the gstreamer-devel mailing list