Results 1 to 10 of 10

Thread: QImage data via FFmpeg

  1. #1
    Join Date
    Oct 2007
    Location
    Slovenia
    Posts
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QImage data via FFmpeg

    I'm working on code, that would simply play video frames using ffmpeg in QWidget. All of code is based on this tutorial: http://dranger.com/ffmpeg/tutorial01.c

    I'll show only the part where I paint the image (since the rest is the same as in the tutorial I linked):
    Qt Code:
    1. void MagicCube::PaintFrame(AVFrame *pFrame, int width, int height)
    2. {
    3. QImage image(width, height, QImage::Format_RGB32);
    4. int x, y;
    5. int *src = (int*)pFrame->data[0];
    6.  
    7. for (y = 0; y < height; y++)
    8. {
    9. for (x = 0; x < width; x++)
    10. {
    11. image.setPixel(x, y, src[x] & 0x00ffffff);
    12. }
    13. src += width;
    14. }
    15.  
    16. QPainter painter(this);
    17. painter.drawImage(QRect(10, 37, width, height), image);
    18. }
    To copy to clipboard, switch view to plain text mode 
    The current code is working, but it has its problems - it's using 40+% of CPU. So, is there a way to avoid all the loops and just load the data into image (I tried a lot of combinations but with no success) or any other method?

    Thanks.

  2. #2
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QImage data via FFmpeg

    Perhaps you could copy the data directly to QImage::bits()?
    J-P Nurmi

  3. #3
    Join Date
    Aug 2006
    Posts
    250
    Thanks
    19
    Thanked 49 Times in 36 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QImage data via FFmpeg

    I don't have a good solution for the data copying part, but I'm pretty sure setPixel will be very slow. I had the same problem with our eye tracker, where the opencv image data was RGB, but not aligned to int, so I couldn't do a straight copy. Here is the code I used, which is not ideal, but reasonably fast.

    in the function that updates the image data from the source
    Qt Code:
    1. if(!currImg) {
    2. imgWidth = state->image.width;
    3. imgHeight = state->image.height;
    4. currImg = new unsigned char[4*imgWidth*imgHeight];
    5. for(int i = 0; i < imgWidth*imgHeight; i++) {
    6. currImg[i*4+3] = 0xFF;
    7. }
    8. }
    9.  
    10. for(int i = 0; i < imgWidth*imgHeight; i++) {
    11. memcpy(currImg+i*4, state->bufferImg.data+i*3, 3);
    12. }
    To copy to clipboard, switch view to plain text mode 

    then in the paintevent
    Qt Code:
    1. if(currImg) {
    2. QImage tImg(currImg, imgWidth, imgHeight, QImage::Format_RGB32);
    3.  
    4. QPainter painter(this);
    5. painter.drawImage(0, 0, tImg);
    6. }
    To copy to clipboard, switch view to plain text mode 

    I'd love to hear a better solution though

  4. #4
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QImage data via FFmpeg

    I bumped into this by accident: http://qtnode.net/pastebin/4666
    J-P Nurmi

  5. #5
    Join Date
    Aug 2006
    Posts
    250
    Thanks
    19
    Thanked 49 Times in 36 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QImage data via FFmpeg

    Interesting, thanks. I'll have to test to see if this is any faster than my version. I assume it will be because of the lack of function call overhead.

  6. #6
    Join Date
    Oct 2007
    Location
    Slovenia
    Posts
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QImage data via FFmpeg

    It's working much faster now, thanks for posting.
    Also, the frame coding should be changed from PIX_FMT_RGB32 to PIX_FMT_BGR24.

  7. #7
    Join Date
    Aug 2006
    Posts
    250
    Thanks
    19
    Thanked 49 Times in 36 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Angry Re: QImage data via FFmpeg

    So I'm writing another program that capture video from an opencv camera and needed this again. Well I tried the linked code and it was still seemingly taking quite a long time to copy the frame over. So I benchmarked my original implementation with the for loop compared to that one.

    All results were running on my Athlon 64 3200, scaled down to 1Ghz, and are the time to copy one 640x480 3 channel frame from the camera.
    Results:
    memcpy in a for loop: 14.75ms
    code from the pastebin: 13.42ms
    new implementation: 11.80ms

    So I found a better implementation that's about 12% faster than the one linked above. Here it is:

    Qt Code:
    1. void RenderWidget::updateData(const IplImage* frame) {
    2. if(!imageData) {
    3. imageWidth = frame->width;
    4. imageHeight = frame->height;
    5. imageData = new unsigned char[4*imageWidth*imageHeight];
    6. for(int i = 0; i < imageWidth*imageHeight; i++) {
    7. imageData[i*4+3] = 0xFF;
    8. }
    9. }
    10.  
    11. int pixels = imageWidth * imageHeight;
    12. uchar* src = (uchar*)(frame->imageData);
    13. uchar* srcEnd = src + (3*pixels);
    14. uchar* dest = imageData;
    15.  
    16. do {
    17. memcpy(dest, src, 3);
    18. dest += 4;
    19. src += 3;
    20. } while(src < srcEnd);
    21. }
    To copy to clipboard, switch view to plain text mode 

    So memcpy is faster than a bunch of pointer arithmetic. Hope it's useful to someone.

    I'm still not happy with this solution though. Once I copy the data, I have to construct a QImage with it and then convert it to a QPixmap to render it to the screen. I wish there was a way to construct a QPixmap from raw data. The QImage -> QPixmap conversion takes about as long as the data copying.

  8. #8
    Join Date
    Jan 2008
    Location
    Silicon valley
    Posts
    15
    Thanked 2 Times in 2 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QImage data via FFmpeg

    Quote Originally Posted by pherthyl View Post
    So memcpy is faster than a bunch of pointer arithmetic.
    This is because memcpy copies the data using pointers to 32-bit data (i.e. 4 bytes a time).

    The QImage -> QPixmap conversion takes about as long as the data copying.
    This is true for X11, because the QImage is on the client side (in your code), and the QPixmap is on the X server side (in a separate process). It should take less under Windows.

  9. #9
    Join Date
    Aug 2006
    Posts
    250
    Thanks
    19
    Thanked 49 Times in 36 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QImage data via FFmpeg

    This is because memcpy copies the data using pointers to 32-bit data (i.e. 4 bytes a time).
    But I'm only copying 3 bytes, so that shouldn't make a difference.

    This is true for X11, because the QImage is on the client side (in your code), and the QPixmap is on the X server side (in a separate process). It should take less under Windows.
    Yeah, no way around that on X11 I guess. Thanks.

  10. #10
    Join Date
    Sep 2010
    Posts
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QImage data via FFmpeg

    From the latest documentation for setPixel:

    Warning: This function is expensive due to the call of the internal detach() function called within; if performance is a concern, we recommend the use of scanLine() to access pixel data directly.

    For those still looking here is a routine to convert AVFrame to QImage. QImage must be allocated prior to the call with something like the following:

    Qt Code:
    1. imageQt = new QImage(w,h,QImage::Format_RGB32);
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // Assumes AVFrame is in RGB24 format
    2. void AVFrame2QImage(AVFrame *ffFrame, QImage *imageQt, int w, int h)
    3. {
    4. unsigned char *src = (unsigned char *)ffFrame->data[0];
    5. for (int y = 0; y < h; y++)
    6. {
    7. QRgb *scanLine = (QRgb *)imageQt->scanLine(y);
    8. for (int x = 0; x < w; x++)
    9. {
    10. scanLine[x] = qRgb(src[3*x], src[3*x+1], src[3*x+2]);
    11. }
    12. src += ffFrame->linesize[0];
    13. }
    14.  
    15. return;
    16. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Replies: 4
    Last Post: 19th October 2007, 19:47
  2. QImage loadFromData not run... XPDF data
    By patrik08 in forum Qt Programming
    Replies: 7
    Last Post: 24th April 2007, 11:51
  3. Creating a QImage from uchar* data
    By forrestfsu in forum Qt Programming
    Replies: 6
    Last Post: 8th February 2007, 15:21
  4. speed of setdata - lots of items in treeview
    By Big Duck in forum Qt Programming
    Replies: 4
    Last Post: 6th July 2006, 12:53
  5. Replies: 16
    Last Post: 7th March 2006, 15:57

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.