[Interest] Fastest Way to convert a QVideoFrame to an QImage?

Till Oliver Knoll till.oliver.knoll at gmail.com
Wed Feb 12 09:37:08 CET 2014


Am 11.02.2014 um 23:32 schrieb Jason H <scorp1us at yahoo.com>:

> ...
> 
> 
> constuchar*bits=frame.bits();
> for(inty=0;y<frame.height();y++)
> {
> QRgb*scanLine=(QRgb*)converted.scanLine(y);
> for(intx=0;x<frame.width();x++)
> {
> intc=bits[y*frame.width()+x];
> scanLine[x]=qRgba(c,c,c,255);
> }

That part looks wrong to me at first sight: on one hand you access the pixels via "bits", on the other you access them with "scanLine".

That per se is not wrong, but the problem with "bits" is: you really get the "raw" data block - and the lines might be padded up to the next multiple of N bytes.

In case we talk about RGBA (or any permutation thereof) data, each channel takes 1 Byte and we assume N=4 then it is probably okay to iterate over width and height and access the pixels via (x, y) the way you did.

In all other cases I would use "scanLine" for simplicity, which already takes care of that (possible) "byte padding" at the end of each scan line (the address you get back always points to the proper beginning of each scan line).

That results in at least "height" times more function calls (to scanLine), but is usually worth it to avoid the hassle.

At least the mixture of "bits" (reading pixel) and "scanLine" (writing them back) seems to completely deny the purpose of gaining performance.

Refer again to the QImage docs and look out for "padding".


And yes, writing into a separate 8bit greyscale image instead (with colour lookup - but not sure whether a "colour" lookup is actually needed, since the index [0, 255] already represents the "colour" - am not too familiar with indexed formats) is probably more efficient, because you need to process up to 4 times less data (which might be partly eaten up by the lookup, but check again whether that is actually needed for greyscale indexed images).

But off course it also depends what you need to do later on with that image: if you would need to convert it back to RGBA (in order to "process" it with other RGBA data) it is probably not worth to convert it back and forth.


For even more hardcore performance tuning follow Thiago's advice ;) But do so only once you have a working solution, even if it's the most naive one! ;)


Otherwise, if you are really serious about performance I would suggest to have a look at OpenCL (similar in spirit, but not to be confused with OpenGL ;)).

It provides also "image buffers" and lets you take advantage of all the raw GPU power (or all CPU cores) while still writing your "kernel" (compute) code in a C99 style language.

The bottleneck would probably be the transfer to/from main VRAM/Main RAM, but since that transfer happens asynchronous one could probably use multiple buffers, and while one buffer is uploading and another downloading a kernel could be processing a third image buffer. So the upload/download costs could be amortised, especially if you deal with a stream of images (aka "video") - that's my theory anyway. ;)

OpenCL can also interact with OpenGL buffers, so in case your video is given in an OpenGL buffer you could even save the transfer and calculate everything on the GPU - while still writing your computation in a C99 style "kernel".

Cheers,
  Oliver


More information about the Interest mailing list