2

In this question, I would like to know the best practice of maintaining the life of an external buffer object associated to QImage object.

Background

I am developing an uncompressed image file viewer with QT. It reads YV12 data from a file, converts it to RGB frame buffer, constructs QImage object, and passes it around the UI layer for rendering.

The YV12 file reader looks like this.

class YV12Frame
{
public:
    YV12Frame(std::string const& fileName)
    {
        // Initialize m_frameBuffer
        // ... (Omitted for brevity)
    }

    QImage GetQImage()
    {
        // Build QImage object
        return QImage(m_frameBuffer, WIDTH, HEIGHT, QImage::Format_RGB32); 
    }

private:
    unsigned char m_frameBuffer[WIDTH * HEIGHT * 4];
};

As QT documentation says, we need to maintain YV12Frame object valid throughout the life of QImage object.

The UI layer may copy the QImage object either through shallow or deep copy. In other words, there may be unknown number of QImage objects which refer to the frame buffer at a time.

Question

How do we know when to delete YV12Frame object safely?

Expected answer

There is a notification (callback or whatever) to tell "Hey, I am the last QImage object referring to the frame buffer and I am about to be deleted. You can safely delete the frame buffer now."

However, I could not find such notifications.

Moto
  • 63
  • 6

1 Answers1

0

The following workaround may fit your need.

Instead of an array, store a real QImage object as the private member of YV12Frame (initialized with the correct width and height). This is the object you need to return from GetQtImage() function. Thanks to QImage implicit sharing, you can safely delete YV12Frame at any time since any other QImage instance will detach its own pixel data when it happens.

In your frame decoding, change the content of QImage via the usual setPixel() function.

If speed is critical, then you can't use setPixel and thus you need to manipulate the pixel data directly. The trick here is to prevent QImage from detaching the pixel data. Therefore, you need to use either constBits() or constScanLine(), cast it to a non-const pointer, and then access it directly (ugly, I know).

Ariya Hidayat
  • 12,523
  • 3
  • 46
  • 39