QWidget Flickering for frame by frame streaming of video



  • Hi,

    I am drawing bitmaps(frame) at 30 fps on QWidget, but for higher resolution of data the video starts flickering.

    Please find relevant code below

    BaseWidget::BaseWidget()
    {
      ...
    m_pCanvas = new QWidget;
    m_pQVBoxLayout->addWidget(m_pCanvas);
    this->setLayout(m_pQVBoxLayout); 
        ...
    }
    
    //supposed to be called 30 times a second.
    BaseWidget::getImageData(uchar* buf, size_t size)
    {
        m_pQPixmap->loadFromData(buf,size,"BMP");
        this->update();
    
    } 
    BaseWidget::paintEvent()
    {
    ...
            painter.drawPixmap(rect,*m_pQPixmap,
                          m_pQImage->rect());
    ...
    }
    
    

    Please help me understand why is it flickering and how can I resolve this issue?

    Thanks!
    Note: https://doc.qt.io/archives/qq/qq06-flicker-free.html



  • @SilverSurfer
    hi, my guess would be, loadFromData takes longer than 34 ms, by higher resolutions. or the Drawing itself or the combination of both.

    I would suggest drawing more bitmaps beforehand in some kind of buffer, preferably threaded so you can do more than one drawing at once.

    THan access those premade bitmaps in your main thread, taking the oldest one from the buffer,for example a QList<QPixmaps>, and painting that one in your paintEvent.


  • Qt Champions 2016

    Hi
    How much higher res from when its working ?



  • @mrjj
    Hi,
    Max Non-flickering resolution = 3200 * 1800
    My requirement is 4k(3840 * 2160)



  • @J.Hilk
    Yes, loadFromData does take longer than 34ms(in fact 50ms at 4k resolution).

    This is for live streaming from IP Cameras, so I don't have the bitmaps beforehand.
    I do fetch bitmaps in a background thread and emit an signal (getImageData() is slot to this signal) to the main thread when they are available.

    The Flicker goes away if I reduce the fps, whereas loadFromData time remains the same. So is it really responsible for the flicker?

    I am also observing a lag which I think is because of loadFromData time.

    Is there any other way to draw an Image considering I have bitmap data in an unsigned char array ?



  • @SilverSurfer
    I can think of 2 ways to do it.

    • don't stream directly, but delay the showing by a second or two, save your calculated images to a buffer and take from that to show in your application. Every so often you'll need to skip frames however

    • Split your image into 2, e.g. upper half and lower one, do the Pixmap modifications in 2 different threads and union that to images into one. This could bring you below the needed threshold.



  • Is there any way I can avoid loadFromData() call, which I assume is doing a copy somewhere ?

    To rephrase my question:
    Can't I draw an Image from the existing buffer without a need for the copy? If yes , How?


  • Lifetime Qt Champion

    Hi,

    How are you getting the data in the first place ?



  • @SGaist
    By making a call to a server to fill the passed buffer.

    //time take by this depends size of buffer to be fetched
    //which may be more than 34 ms depending on size
    fetchBitmap(handle, cameraId,(uchar*)buffer , x_width, y_height);
    
    emit bufferAvailable(buffer,size); //calls getImageData(..) slot in the UI thread
    

    Thanks!


  • Lifetime Qt Champion

    What is that server ?

    What does it provide as API to retrieve images ?



  • @SGaist
    It is a Video Management Server(ExacqVision Server to be precise).

    Yes, the API( fetchBitmap(...)) is provided by the server.
    So I don't think the data retrieval time can be reduced.

    What I would Ideally like to do is avoid any copying for this data.
    Which happens when I do pixmap->loadFromData(...) .


  • Lifetime Qt Champion

    Is their API documentation accessible somewhere ?

    If you pass the buffer to the fetchBimap method, then you should be able to pass a QImage buffer pointer and in this case, the data will be copied directly on the QImage that you can then manipulate.



  • @SGaist
    No the Documentation is not available publicly.

    It take a uint8_t* as buffer argument.

    //registered with server
    Callback(event)
    {
        if(event == LIVE_FRAME_AVAILABLE)
    {
        frameSize = fetchBitmap(NULL); 
        // Size fetched everytime as this can change with every frame if image is resized
        vector.resize(framesize)
        fetchBitmap(&vector[0]);
        emit bufferAvailable(&vector[0],frameSize);
    }
    }
    

    I am not sure how can I use QImage pointer here.


  • Lifetime Qt Champion

    QImage::bits.

    Make the QImage the correct format and size.



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.