#include #include #include #include #include #define FOURCC_YUY2 0x32595559 static int xv_port_has_yuy2( XvPortID port ) { XvImageFormatValues *formatValues; int formats; int i; formatValues = XvListImageFormats( qt_xdisplay(), port, &formats ); for( i = 0; i < formats; i++ ) { if((formatValues[ i ].id == FOURCC_YUY2) && (!(strcmp( formatValues[ i ].guid, "YUY2" )))) { XFree (formatValues); return 1; } } XFree( formatValues ); return 0; } static int xv_check_extension( XvPortID &xv_port, Window win ) { unsigned int version; unsigned int release; unsigned int dummy; unsigned int adaptors; unsigned int i; unsigned long j; int has_yuy2 = 0; XvAdaptorInfo *adaptorInfo; if( ( XvQueryExtension( qt_xdisplay(), &version, &release, &dummy, &dummy, &dummy) != Success ) || ( version < 2 ) || ( ( version == 2 ) && ( release < 2 ) ) ) { fprintf( stderr, "xvoutput: XVIDEO extension not found: X too old? didn't load extmod?\n" ); return 0; } XvQueryAdaptors( qt_xdisplay(), win, &adaptors, &adaptorInfo ); for( i = 0; i < adaptors; i++ ) { if( adaptorInfo[ i ].type & XvImageMask ) { for( j = 0; j < adaptorInfo[ i ].num_ports; j++ ) { if( xv_port_has_yuy2( adaptorInfo[ i ].base_id + j ) ) { if( XvGrabPort( qt_xdisplay(), adaptorInfo[ i ].base_id + j, 0 ) == Success ) { xv_port = adaptorInfo[ i ].base_id + j; fprintf( stderr, "xvoutput: Using XVIDEO adaptor %lu: %s.\n", adaptorInfo[ i ].base_id + j, adaptorInfo[ i ].name ); XvFreeAdaptorInfo( adaptorInfo ); return 1; } has_yuy2 = 1; } } } } XvFreeAdaptorInfo( adaptorInfo ); if( has_yuy2 ) fprintf( stderr, "xvoutput: No YUY2 XVIDEO port available.\n" ); else fprintf( stderr, "xvoutput: No XVIDEO port found which supports YUY2 images.\n" ); return 0; } #define W 768 #define H 576 #define Kr 0.2126 #define Kb 0.0722 #define L(r,g,b) (Kr * r + Kb * b + (1 - Kr - Kb) * g) #define YUY2(r,g,b) \ (((int)(219*L(r,g,b)/255 + 16.5)) | \ (((int)(112*(b - L(r,g,b))/((1-Kb)*255) + 128.5)) << 8) | \ (((int)(219*L(r,g,b)/255 + 16.5)) << 16) | \ (((int)(112*(r - L(r,g,b))/((1-Kr)*255) + 128.5)) << 24)) static unsigned long pix[] = { YUY2( 255, 0, 0 ), YUY2( 0, 155, 0 ), YUY2( 0, 0, 255 ), }; class MyWidget : public QWidget { public: MyWidget() : QWidget( 0, 0, WRepaintNoErase ), sz( qApp->desktop()->screen( 0 )->size() ) { if (!xv_check_extension( xv_port, winId() )) exit( 1 ); xv_image = XvCreateImage( qt_xdisplay(), xv_port, FOURCC_YUY2, (char *)buf, W, H ); l = x1 = y1 = 0; x2 = W - 1; y2 = H - 1; showFullScreen(); } protected: void closeEvent( QCloseEvent * ) { qApp->quit(); } void paintEvent( QPaintEvent * ) { for (int i = 0; i < W * H / 2; i++) buf[i] = pix[l]; XvPutImage( qt_xdisplay(), xv_port, winId(), DefaultGC( qt_xdisplay(), 0 ), xv_image, x1, y1, x2 - x1 + 1, y2 - y1 + 1, 0, 0, width(), height() ); } void keyPressEvent( QKeyEvent *e ) { int dx, dy, tlf, brf, nx1, ny1, nx2, ny2; switch (e->key()) { case Key_Escape: case Key_Q: qApp->quit(); break; case Key_Up: dy = -1, dx = 0; goto com; case Key_Down: dy = 1, dx = 0; goto com; case Key_Left: dx = -1, dy = 0; goto com; case Key_Right: dx = 1, dy = 0; com: if (e->state() & ControlButton) tlf = 1, brf = 0; else if (e->state() & AltButton) tlf = 0, brf = 1; else tlf = brf = 1; nx1 = x1 + tlf * dx; ny1 = y1 + tlf * dy; nx2 = x2 + brf * dx; ny2 = y2 + brf * dy; if (nx1 >= 0 && nx2 >= nx1 && nx2 < W && ny1 >= 0 && ny2 >= ny1 && ny2 < H) { x1 = nx1, y1 = ny1, x2 = nx2, y2 = ny2; printf( "%dx%d @ %d,%d\n", x2 - x1 + 1, y2 - y1 + 1, x1, y1 ); case Key_Space: if (++l >= (int)(sizeof(pix)/sizeof(pix[0]))) l = 0; case Key_Return: update(); } } e->ignore(); } private: QSize sz; int l, x1, y1, x2, y2; unsigned long buf[W * H / 2]; XvImage *xv_image; XvPortID xv_port; }; int main(int argc, char **argv) { QApplication app( argc, argv ); MyWidget win; app.exec(); return 0; }