ToddAtWSU
26th June 2006, 14:08
I figured out how to get my overlay to work on my DirectShow video. I just made a QPixmap of size 5x5 and put this on a QLabel of size 5x5 which I draw on top of the QAxWidget displaying my video. This works great instead of trying to create a transparent pixmap/label but I get a lot of flicker when I click on the video to draw the point. In my GUI building function I set these variables up like this:
mpOverlay = new QPixmap( 5, 5 );
mpOverlay->fill( Qt::red );
mpOverlayLabel = new QLabel( mpVideoPlayer );
mpOverlayLabel->setGeometry( QRect( 0, 0, 5, 5 ) );
mpOverlayLabel->hide( );
mpOverlayLabel->setPixmap( *mpOverlay );
Then whenever I click on the screen I do this:
if( event->type() == QEvent::MouseButtonRelease )
{
AzElPoint point;
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
point.frameNumber = getCurrentFrame( );
point.xPos = mouseEvent->x( );
point.yPos = mouseEvent->y( );
if( mouseEvent->button() == Qt::LeftButton )
{
// If left button, place mark on overlay to indicate position
// and store position in array at the current frame index
for( int i = 0 ; i < azElPoints.size( ) ; i++ )
{
if( azElPoints[i].frameNumber == getCurrentFrame( ) )
{
azElPoints.removeAt( i );
erasePoint = true;
}
}
azElPoints.push_back( point );
printf( "x=%d, y=%d\n", point.xPos, point.yPos );
update( );
return true;
}
}
And my paint event handler just calls repaintWindow( ) which looks like this:
void VideoViewerWindow::repaintWindow( )
{
long lWidth, lHeight;
HRESULT hr = pWindowlessControl->GetNativeVideoSize( &lWidth, &lHeight, NULL, NULL );
RECT rcSrc, rcDest;
// Set the source rectangle.
SetRect( &rcSrc, 0, 0, lWidth, lHeight );
// Get the window client area.
GetClientRect( (HWND) mpVideoPlayer->winId( ), &rcDest );
// Set the destination rectangle.
SetRect(&rcDest, 1, 1, 558, 349);
// Set the video position.
hr = pWindowlessControl->SetVideoPosition( &rcSrc, &rcDest );
PAINTSTRUCT ps;
HDC hdc;
RECT rcClient;
GetClientRect( (HWND) mpVideoPlayer->winId( ), &rcClient );
hdc = BeginPaint( (HWND) mpVideoPlayer->winId( ), &ps );
if( pWindowlessControl != NULL )
{
// Find the region where the application can paint by subtracting
// the video destination rectangle from the client area.
// (Assume that g_rcDest was calculated previously.)
HRGN rgnClient = CreateRectRgnIndirect( &rcClient );
HRGN rgnVideo = CreateRectRgnIndirect( &rcDest );
CombineRgn( rgnClient, rgnClient, rgnVideo, RGN_DIFF );
// Paint on window.
HBRUSH hbr = GetSysColorBrush( COLOR_BTNFACE );
FillRgn( hdc, rgnClient, hbr );
// Clean up.
DeleteObject( hbr );
DeleteObject( rgnClient );
DeleteObject( rgnVideo );
// Request the VMR to paint the video and draw the point chosen by the user.
int i;
for( i = 0 ; i < azElPoints.size( ) ; i++ )
{
if( azElPoints[i].frameNumber == getCurrentFrame( ) )
{
mpOverlayLabel->move( azElPoints[i].xPos - 2, azElPoints[i].yPos - 2 );
mpOverlayLabel->show( );
break;
}
}
if( i == azElPoints.size( ) )
{
mpOverlayLabel->hide( );
}
HRESULT hr = pWindowlessControl->RepaintVideo( (HWND) mpVideoPlayer->winId( ), hdc );
}
}
You can see what I am doing is just showing/hiding the QLabel and then redrawing the video (ie. the QAxWidget) which in turns redraws the QLabel since it is a child of the QAxWidget. But when I click the screen, I want the dot (QPixmap/QLabel) to appear without causing the entire screen to flicker. Sometimes the screen flickers and sometimes it does not. And when it does flicker, sometimes the flicker lasts almost a half of a second - which is very noticeable. So any ideas on how to improve my function(s) to prevent this from flickering would be great! Thanks!
mpOverlay = new QPixmap( 5, 5 );
mpOverlay->fill( Qt::red );
mpOverlayLabel = new QLabel( mpVideoPlayer );
mpOverlayLabel->setGeometry( QRect( 0, 0, 5, 5 ) );
mpOverlayLabel->hide( );
mpOverlayLabel->setPixmap( *mpOverlay );
Then whenever I click on the screen I do this:
if( event->type() == QEvent::MouseButtonRelease )
{
AzElPoint point;
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
point.frameNumber = getCurrentFrame( );
point.xPos = mouseEvent->x( );
point.yPos = mouseEvent->y( );
if( mouseEvent->button() == Qt::LeftButton )
{
// If left button, place mark on overlay to indicate position
// and store position in array at the current frame index
for( int i = 0 ; i < azElPoints.size( ) ; i++ )
{
if( azElPoints[i].frameNumber == getCurrentFrame( ) )
{
azElPoints.removeAt( i );
erasePoint = true;
}
}
azElPoints.push_back( point );
printf( "x=%d, y=%d\n", point.xPos, point.yPos );
update( );
return true;
}
}
And my paint event handler just calls repaintWindow( ) which looks like this:
void VideoViewerWindow::repaintWindow( )
{
long lWidth, lHeight;
HRESULT hr = pWindowlessControl->GetNativeVideoSize( &lWidth, &lHeight, NULL, NULL );
RECT rcSrc, rcDest;
// Set the source rectangle.
SetRect( &rcSrc, 0, 0, lWidth, lHeight );
// Get the window client area.
GetClientRect( (HWND) mpVideoPlayer->winId( ), &rcDest );
// Set the destination rectangle.
SetRect(&rcDest, 1, 1, 558, 349);
// Set the video position.
hr = pWindowlessControl->SetVideoPosition( &rcSrc, &rcDest );
PAINTSTRUCT ps;
HDC hdc;
RECT rcClient;
GetClientRect( (HWND) mpVideoPlayer->winId( ), &rcClient );
hdc = BeginPaint( (HWND) mpVideoPlayer->winId( ), &ps );
if( pWindowlessControl != NULL )
{
// Find the region where the application can paint by subtracting
// the video destination rectangle from the client area.
// (Assume that g_rcDest was calculated previously.)
HRGN rgnClient = CreateRectRgnIndirect( &rcClient );
HRGN rgnVideo = CreateRectRgnIndirect( &rcDest );
CombineRgn( rgnClient, rgnClient, rgnVideo, RGN_DIFF );
// Paint on window.
HBRUSH hbr = GetSysColorBrush( COLOR_BTNFACE );
FillRgn( hdc, rgnClient, hbr );
// Clean up.
DeleteObject( hbr );
DeleteObject( rgnClient );
DeleteObject( rgnVideo );
// Request the VMR to paint the video and draw the point chosen by the user.
int i;
for( i = 0 ; i < azElPoints.size( ) ; i++ )
{
if( azElPoints[i].frameNumber == getCurrentFrame( ) )
{
mpOverlayLabel->move( azElPoints[i].xPos - 2, azElPoints[i].yPos - 2 );
mpOverlayLabel->show( );
break;
}
}
if( i == azElPoints.size( ) )
{
mpOverlayLabel->hide( );
}
HRESULT hr = pWindowlessControl->RepaintVideo( (HWND) mpVideoPlayer->winId( ), hdc );
}
}
You can see what I am doing is just showing/hiding the QLabel and then redrawing the video (ie. the QAxWidget) which in turns redraws the QLabel since it is a child of the QAxWidget. But when I click the screen, I want the dot (QPixmap/QLabel) to appear without causing the entire screen to flicker. Sometimes the screen flickers and sometimes it does not. And when it does flicker, sometimes the flicker lasts almost a half of a second - which is very noticeable. So any ideas on how to improve my function(s) to prevent this from flickering would be great! Thanks!