DirectShow VMR9 Drawing on QWidget Subclass Resulting in Repaint Flicker
I apologize in advance if there's a thread lurking somewhere that contains the information I'm looking for. I searched. Honestly, I did.
I have a QWidget subclass which is meant to be the area where a DirectShow VMR9 draws its video output. The application is working perfectly--all of the DirectShow stuff is wired up happily and the VMR9 is drawing on my QWidget subclass. The problem is that when resizing the window, I'm getting a lot of flicker in the redraw. It looks to me like Qt and DirectShow are having a race during repainting. It looks like Qt is clearing the widget, and then DirectShow is repainting afterward. In my QWidget subclass I have a paintEvent() method something like this:
Code:
RECT pos;
pos.top = 0;
pos.left = 0;
pos.bottom = height() - 1;
pos.right = width() - 1;
_impl->vmrWc->SetVideoPosition(NULL, &pos);
HWND hWnd = (HWND) winId();
HDC hDC = GetDC(hWnd);
_impl->vmrWc->RepaintVideo(hWnd, hDC);
}
"_impl->vmrWc" refers to the IVMRWindowlessControl9 for my VMR9 renderer.
Is there something I should be doing differently with my QWidget subclass to provoke it to not try to redraw the widget's contents?
Thanks in advance...
Michael
Re: DirectShow VMR9 Drawing on QWidget Subclass Resulting in Repaint Flicker
I am not sure if this will help but you could look at the Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent QWidget attribute
See Transparency and Double Buffering and QWidget::setAttribute())
Re: DirectShow VMR9 Drawing on QWidget Subclass Resulting in Repaint Flicker
From reading the docs, that really sounds like it should have done the trick. I'm now setting Qt::WA_OpaquePaintEvent in the constructor of my QWidget subclass. That makes the flicker happen in black, instead of in the default widget background color. It looks a tiny bit better, but it's still not right.
I've also split the work I was doing up into two methods now:
Code:
HWND hWnd = (HWND) winId();
HDC hDC = GetDC(hWnd);
_impl->vmrWc->RepaintVideo(hWnd, hDC);
}
RECT pos;
pos.top = 0;
pos.left = 0;
pos.bottom = height() - 1;
pos.right = width() - 1;
_impl->vmrWc->SetVideoPosition(NULL, &pos);
}
From reading the DirectShow docs, it seems like something is going on with the windows messages, and possibly causing DirectShow to think it needs to repaint more than it should?
This code is being ported from wxWidgets--things worked well there. I have a feeling it's got to be something minor and silly.
Re: DirectShow VMR9 Drawing on QWidget Subclass Resulting in Repaint Flicker
Ok... I managed to get this sorted out.
in my QWidget subclass, I had to override the QWidget::paintEngine method to return NULL. I also had to set the following widget properties:
Code:
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_PaintOnScreen, true);
setAutoFillBackground(false);
I also adjusted my calls to the IVMRWindowlessControl9 like the following:
Code:
HWND hWnd = (HWND) winId();
HDC hDC = GetDC(hWnd);
_impl->vmrWc->RepaintVideo(hWnd, hDC);
}
RECT pos;
pos.top = 0;
pos.left = 0;
pos.bottom = height();
pos.right = width();
_impl->vmrWc->SetVideoPosition(NULL, &pos);
}
Everything seems happy now.
Ok... I managed to get this sorted out.
in my QWidget subclass, I had to override the QWidget::paintEngine method to return NULL. I also had to set the following widget properties:
Code:
setAttribute(Qt::WA_OpaquePaintEvent, true);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_PaintOnScreen, true);
setAutoFillBackground(false);
I also adjusted my calls to the IVMRWindowlessControl9 like the following:
Code:
HWND hWnd = (HWND) winId();
HDC hDC = GetDC(hWnd);
_impl->vmrWc->RepaintVideo(hWnd, hDC);
}
RECT pos;
pos.top = 0;
pos.left = 0;
pos.bottom = height();
pos.right = width();
_impl->vmrWc->SetVideoPosition(NULL, &pos);
}
Everything seems happy now.
Added after 5 minutes:
ChrisW67's tips pointed me in the right direction, but the chunk of code that pushed it over the edge was in the Qt 4.8 source distribution at the location:
Code:
qt-everywhere-opensource-src-4.8.3/src/3rdparty/phonon/ds9
Specifically, the VideoWidget class.