Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

displayer.cc

Go to the documentation of this file.
00001 /*
00002 * Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
00003 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00004 *
00005 * This program is free software; you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License as published by
00007 * the Free Software Foundation; either version 2 of the License, or
00008 * (at your option) any later version.
00009 *
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 *
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program; if not, write to the Free Software Foundation,
00017 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 #include <iostream>
00025 using std::cerr;
00026 using std::endl;
00027 
00028 #include "displayer.h"
00029 #include <gdk/gdkx.h>
00030 
00031 AspectRatioCalculator::AspectRatioCalculator( int widgetWidth, int widgetHeight,
00032         int imageWidth, int imageHeight,
00033         int maxImageWidth, int maxImageHeight )
00034 {
00035     double ratioWidth = ( double ) widgetWidth / ( double ) imageWidth;
00036     double ratioHeight = ( double ) widgetHeight / ( double ) imageHeight;
00037     double ratioConstant = ratioHeight < ratioWidth ?
00038                            ratioHeight : ratioWidth;
00039     width = ( int ) ( imageWidth * ratioConstant + 0.5 );
00040     height = ( int ) ( imageHeight * ratioConstant + 0.5 );
00041     if ( width > maxImageWidth )
00042         width = maxImageWidth;
00043     if ( height > maxImageHeight )
00044         height = maxImageHeight;
00045     x = ( widgetWidth - width ) / 2;
00046     y = ( widgetHeight - height ) / 2;
00047 }
00048 
00049 AspectRatioCalculator::AspectRatioCalculator( int widgetWidth, int widgetHeight,
00050         int imageWidth, int imageHeight, bool isPAL, bool isWidescreen )
00051 {
00052 
00053     static Preferences & prefs = Preferences::getInstance();
00054 
00055     if ( prefs.displayMode == 0 && imageWidth == 360 )
00056     {
00057         imageWidth *= 2;
00058         imageHeight *= 2;
00059     }
00060 
00061     // cerr << "Original: " << imageWidth << "x" << imageHeight << endl;
00062 
00063     if ( isWidescreen )
00064     {
00065         if ( isPAL )
00066         {
00067             // PAL: 720 x 576 at 16:9 aspect ratio: Use an image size of 1024 x 576.
00068             imageWidth = imageWidth * 1024 / 720;
00069             imageHeight = imageHeight * imageHeight / 576;
00070         }
00071         else
00072         {
00073             // NTSC: 720 x 480 at 16:9 aspect ratio: Use an image size of 854 x 480
00074             imageWidth = imageWidth * 854 / 720;
00075             imageHeight = imageHeight * imageHeight / 480;
00076         }
00077     }
00078     else
00079     {
00080         if ( isPAL )
00081         {
00082             // PAL: 720 x 576 at 4:3 aspect ratio: Use an image size of 768 x 576.
00083             imageWidth = imageWidth * 768 / 720;
00084             imageHeight = imageHeight * imageHeight / 576;
00085         }
00086         else
00087         {
00088             // NTSC: 720 x 480 at 4:3 aspect ratio: Use an image size of 720 x 540
00089             imageWidth = imageWidth * imageWidth / 720;
00090             imageHeight = imageHeight * 540 / 480;
00091         }
00092     }
00093 
00094     // cerr << "Changed : " << imageWidth << "x" << imageHeight << endl;
00095 
00096     double ratioWidth = ( double ) widgetWidth / ( double ) imageWidth;
00097     double ratioHeight = ( double ) widgetHeight / ( double ) imageHeight;
00098 
00099     if ( ratioHeight < ratioWidth )
00100     {
00101         width = ( int ) ( imageWidth * ratioHeight + 0.5 );
00102         height = ( int ) ( imageHeight * ratioHeight + 0.5 );
00103     }
00104     else
00105     {
00106         width = ( int ) ( imageWidth * ratioWidth + 0.5 );
00107         height = ( int ) ( imageHeight * ratioWidth + 0.5 );
00108     }
00109 
00110     // cerr << "Final   : " << width << "x" << height << endl;
00111     // cerr << "Ratio   : " << (double)width / (double)height << endl;
00112 
00113     x = ( widgetWidth - width ) / 2;
00114     y = ( widgetHeight - height ) / 2;
00115 }
00116 
00121 bool Displayer::usable()
00122 {
00123     return false;
00124 }
00125 
00129 DisplayerInput Displayer::format()
00130 {
00131     return DISPLAY_NONE;
00132 }
00133 
00137 int Displayer::preferredWidth()
00138 {
00139     return img_width;
00140 }
00141 
00145 int Displayer::preferredHeight()
00146 {
00147     return img_height;
00148 }
00149 
00158 void Displayer::put( void *image, int width, int height )
00159 {
00160     if ( width == preferredWidth() && height == preferredHeight() )
00161     {
00162         put( image );
00163     }
00164     else
00165     {
00166         reformat( format(), format(), image, width, height );
00167         put( pixels );
00168     }
00169 }
00170 
00181 void Displayer::put( DisplayerInput inFormat, void *image,
00182                      int width, int height )
00183 {
00184     if ( format() == inFormat &&
00185             width == preferredWidth() && height == preferredHeight() )
00186     {
00187         put( image );
00188     }
00189     else
00190     {
00191         reformat( inFormat, format(), image, width, height );
00192         put( pixels );
00193     }
00194 }
00195 
00196 void Displayer::Reformat424( unsigned char *image, int inWidth, int inHeight, int outWidth, int outHeight )
00197 {
00198     // Fixed value for rounding to the middle pixel (instead of defaulting to top left)
00199     int rounding = 1 << 15;
00200     // xfactor and yfactor represent the granularity of the output, relative to the input
00201     unsigned int xfactor = ( inWidth << 16 ) / outWidth;
00202     unsigned int yfactor = ( inHeight << 16 ) / outHeight;
00203     // multiplication of x and yfactors to the output height
00204     unsigned int ymax = yfactor * outHeight;
00205     unsigned int xmax = xfactor * outWidth;
00206     // y is used to point to the start of each line in the input
00207     unsigned int y = 0;
00208     // i is a temporary variable used in iterating through each line
00209     unsigned int i = 0;
00210     // o is the position in the output
00211     unsigned int o = 0;
00212 
00213     for ( unsigned int yft = 0; yft < ymax; yft += yfactor )
00214     {
00215         y = ( ( yft + rounding ) >> 16 ) * inWidth * 4;
00216         for ( unsigned int xft = 0; xft < xmax; xft += xfactor )
00217         {
00218             i = y + ( ( xft + rounding ) >> 16 ) * 4;
00219             pixels[ o ++ ] = image[ i ++ ];
00220             pixels[ o ++ ] = image[ i ++ ];
00221             pixels[ o ++ ] = image[ i ++ ];
00222             pixels[ o ++ ] = image[ i ];
00223         }
00224     }
00225 }
00226 
00227 void Displayer::Reformat222( unsigned char *image, int inWidth, int inHeight, int outWidth, int outHeight )
00228 {
00229     // Fixed value for rounding to the middle pixel (instead of defaulting to top left)
00230     int rounding = 1 << 15;
00231     // xfactor and yfactor represent the granularity of the output, relative to the input
00232     unsigned int xfactor = ( inWidth << 16 ) / outWidth;
00233     unsigned int yfactor = ( inHeight << 16 ) / outHeight;
00234     // multiplication of x and yfactors to the output height
00235     unsigned int ymax = yfactor * outHeight;
00236     unsigned int xmax = xfactor * outWidth;
00237     // y is used to point to the start of each line in the input
00238     unsigned int y = 0;
00239     // i is a temporary variable used in iterating through each line
00240     unsigned int i = 0;
00241     // o is the position in the output
00242     unsigned int o = 0;
00243 
00244     for ( unsigned int yft = 0; yft < ymax; yft += yfactor )
00245     {
00246         y = ( ( yft + rounding ) >> 16 ) * inWidth * 2;
00247         for ( unsigned int xft = 0; xft < xmax; xft += xfactor )
00248         {
00249             i = y + ( ( xft + rounding ) >> 16 ) * 2;
00250             pixels[ o ++ ] = image[ i ++ ];
00251             pixels[ o ++ ] = image[ i ];
00252         }
00253     }
00254 }
00255 
00256 void Displayer::Reformat323( unsigned char *image, int inWidth, int inHeight, int outWidth, int outHeight )
00257 {
00258     // Fixed value for rounding to the middle pixel (instead of defaulting to top left)
00259     int rounding = 1 << 15;
00260     // xfactor and yfactor represent the granularity of the output, relative to the input
00261     unsigned int xfactor = ( inWidth << 16 ) / outWidth;
00262     unsigned int yfactor = ( inHeight << 16 ) / outHeight;
00263     // multiplication of x and yfactors to the output height
00264     unsigned int ymax = yfactor * outHeight;
00265     unsigned int xmax = xfactor * outWidth;
00266     // y is used to point to the start of each line in the input
00267     unsigned int y = 0;
00268     // i is a temporary variable used in iterating through each line
00269     unsigned int i = 0;
00270     // o is the position in the output
00271     unsigned int o = 0;
00272 
00273     for ( unsigned int yft = 0; yft < ymax; yft += yfactor )
00274     {
00275         y = ( ( yft + rounding ) >> 16 ) * inWidth * 3;
00276         for ( unsigned int xft = 0; xft < xmax; xft += xfactor )
00277         {
00278             i = y + ( ( xft + rounding ) >> 16 ) * 3;
00279             pixels[ o ++ ] = image[ i ++ ];
00280             pixels[ o ++ ] = image[ i ++ ];
00281             pixels[ o ++ ] = image[ i ];
00282         }
00283     }
00284 }
00285 
00286 void Displayer::Reformat323R( unsigned char *image, int inWidth, int inHeight, int outWidth, int outHeight )
00287 {
00288     // Fixed value for rounding to the middle pixel (instead of defaulting to top left)
00289     int rounding = 1 << 15;
00290     // xfactor and yfactor represent the granularity of the output, relative to the input
00291     unsigned int xfactor = ( inWidth << 16 ) / outWidth;
00292     unsigned int yfactor = ( inHeight << 16 ) / outHeight;
00293     // multiplication of x and yfactors to the output height
00294     unsigned int ymax = yfactor * outHeight;
00295     unsigned int xmax = xfactor * outWidth;
00296     // y is used to point to the start of each line in the input
00297     unsigned int y = 0;
00298     // i is a temporary variable used in iterating through each line
00299     unsigned int i = 0;
00300     // o is the position in the output
00301     unsigned int o = 0;
00302 
00303     for ( unsigned int yft = 0; yft < ymax; yft += yfactor )
00304     {
00305         y = ( ( yft + rounding ) >> 16 ) * inWidth * 3;
00306         for ( unsigned int xft = 0; xft < xmax; xft += xfactor )
00307         {
00308             i = y + ( ( xft + rounding ) >> 16 ) * 3 + 2;
00309             pixels[ o ++ ] = image[ i ];
00310             pixels[ o ++ ] = image[ -- i ];
00311             pixels[ o ++ ] = image[ -- i ];
00312         }
00313     }
00314 }
00315 
00316 void Displayer::Reformat324( unsigned char *image, int inWidth, int inHeight, int outWidth, int outHeight )
00317 {
00318     // Fixed value for rounding to the middle pixel (instead of defaulting to top left)
00319     int rounding = 1 << 15;
00320     // xfactor and yfactor represent the granularity of the output, relative to the input
00321     unsigned int xfactor = ( inWidth << 16 ) / outWidth;
00322     unsigned int yfactor = ( inHeight << 16 ) / outHeight;
00323     // multiplication of x and yfactors to the output height
00324     unsigned int ymax = yfactor * outHeight;
00325     unsigned int xmax = xfactor * outWidth;
00326     // y is used to point to the start of each line in the input
00327     unsigned int y = 0;
00328     // i is a temporary variable used in iterating through each line
00329     unsigned int i = 0;
00330     // o is the position in the output
00331     unsigned int o = 0;
00332 
00333     for ( unsigned int yft = 0; yft < ymax; yft += yfactor )
00334     {
00335         y = ( ( yft + rounding ) >> 16 ) * inWidth * 3;
00336         for ( unsigned int xft = 0; xft < xmax; xft += xfactor )
00337         {
00338             i = y + ( ( xft + rounding ) >> 16 ) * 3;
00339             pixels[ o ++ ] = image[ i ++ ];
00340             pixels[ o ++ ] = image[ i ++ ];
00341             pixels[ o ++ ] = image[ i ];
00342             pixels[ o ++ ] = 0;
00343         }
00344     }
00345 }
00346 
00356 void Displayer::reformat( DisplayerInput inFormat, int outFormat, void *image,
00357                           int width, int height )
00358 {
00359     //struct timeval tv;
00360     //gettimeofday(&tv, NULL);
00361     //long long starttime = tv.tv_sec * 1000000 + tv.tv_usec;
00362 
00363     unsigned char * img = ( unsigned char * ) image;
00364     if ( inFormat == DISPLAY_YUV && outFormat == DISPLAY_YUV )
00365         Reformat424( img, width, height, this->preferredWidth(), this->preferredHeight() );
00366     else if ( inFormat == DISPLAY_RGB16 && outFormat == DISPLAY_RGB16 )
00367         Reformat222( img, width, height, this->preferredWidth(), this->preferredHeight() );
00368     else if ( inFormat == DISPLAY_BGR && outFormat == DISPLAY_RGB )
00369         Reformat323( img, width, height, this->preferredWidth(), this->preferredHeight() );
00370     else if ( inFormat == DISPLAY_BGR && outFormat == DISPLAY_BGR0 )
00371         Reformat324( img, width, height, this->preferredWidth(), this->preferredHeight() );
00372     // Incorrect, but covers the most correctly [take care when introducing new formats]
00373     else if ( inFormat == outFormat )
00374         Reformat323( img, width, height, this->preferredWidth(), this->preferredHeight() );
00375 
00376     //gettimeofday(&tv, NULL);
00377     //long long endtime = tv.tv_sec * 1000000 + tv.tv_usec;
00378     //cerr << "Reformatting took " << endtime - starttime << endl;
00379 }
00380 
00384 XDisplayer::XDisplayer( GtkWidget *drawingarea ) : xImage( NULL )
00385 {
00386     this->drawingarea = drawingarea;
00387     this->canuse = true;
00388 
00389     cerr << ">> Trying X Displayer" << endl;
00390 #if 0
00391 
00392     memset( &shmInfo, 0, sizeof( XShmSegmentInfo ) );
00393     GdkWindowPrivate *priv = ( GdkWindowPrivate* ) drawingarea->window;
00394     window = priv->xwindow;
00395     display = priv->xdisplay;
00396 
00397     gc = XCreateGC( display, window, 0, &values );
00398 
00399     Visual *v = ( ( GdkVisualPrivate * ) gdk_visual_get_system() ) ->xvisual;
00400     depth = DefaultDepth( display, DefaultScreen( display ) );
00401 
00402     xImage = ( XImage * ) XShmCreateImage( display, v, depth, ZPixmap,
00403                                            ( char * ) NULL, &shmInfo,
00404                                            this->preferredWidth(),
00405                                            this->preferredHeight() );
00406 
00407     shmInfo.shmid = shmget( IPC_PRIVATE,
00408                             this->preferredWidth() * this->preferredHeight() * 4,
00409                             IPC_CREAT | 0777 );
00410 
00411     shmInfo.shmaddr = ( char * ) shmat( shmInfo.shmid, 0, 0 );
00412     xImage->data = shmInfo.shmaddr;
00413     shmInfo.readOnly = 0;
00414     if ( !XShmAttach( display, &shmInfo ) )
00415     {
00416         this->canuse = false;
00417         fprintf( stderr, "Cannot attach shared memory\n" );
00418         xImage = NULL;
00419         return ;
00420     }
00421 #endif
00422 }
00423 
00424 XDisplayer::~XDisplayer()
00425 {
00426 #if 0
00427     if ( shmInfo.shmaddr != NULL )
00428     {
00429         XShmDetach( display, &shmInfo );
00430         shmdt( shmInfo.shmaddr );
00431     }
00432     if ( xImage != NULL )
00433     {
00434         XDestroyImage( xImage );
00435     }
00436 #endif
00437 }
00438 
00439 bool XDisplayer::usable()
00440 {
00441     return canuse;
00442 }
00443 
00444 DisplayerInput XDisplayer::format()
00445 {
00446     return DISPLAY_RGB;
00447 }
00448 
00449 void XDisplayer::put( void *data )
00450 {
00451     unsigned char * image = ( unsigned char * ) data;
00452     memcpy( xImage->data, image,
00453             this->preferredWidth() * this->preferredHeight() * 4 );
00454     XShmPutImage( display, window, gc, xImage, 0, 0, 0, 0,
00455                   this->preferredWidth(), this->preferredHeight(), false );
00456 }
00457 
00461 XvDisplayer::XvDisplayer( GtkWidget *drawingarea, int width, int height, bool isPAL, bool isWidescreen ) :
00462         xvImage( NULL )
00463 {
00464 
00465     cerr << ">> Trying XVideo at " << width << "x" << height << endl;
00466 
00467     this->drawingarea = drawingarea;
00468     img_width = width;
00469     img_height = height;
00470     this->isPAL = isPAL;
00471     this->isWidescreen = isWidescreen;
00472 
00473     shmInfo.shmaddr = NULL;
00474     gotPort = false;
00475 
00476     window = GDK_WINDOW_XID( drawingarea->window );
00477     display = GDK_WINDOW_XDISPLAY( drawingarea->window );
00478 
00479     unsigned int    count;
00480     XvAdaptorInfo   *adaptorInfo;
00481 
00482     if ( XvQueryAdaptors( display, window, &count, &adaptorInfo ) == Success )
00483     {
00484 
00485         cerr << ">>> XvQueryAdaptors count: " << count << endl;
00486         for ( unsigned int n = 0; gotPort == false && n < count; ++n )
00487         {
00488             // Diagnostics
00489             cerr << ">>> Xv: " << adaptorInfo[ n ].name
00490             << ": ports " << adaptorInfo[ n ].base_id
00491             << " - " << adaptorInfo[ n ].base_id +
00492             adaptorInfo[ n ].num_ports - 1
00493             << endl;
00494 
00495             for ( port = adaptorInfo[ n ].base_id;
00496                     port < adaptorInfo[ n ].base_id + adaptorInfo[ n ].num_ports;
00497                     port ++ )
00498             {
00499                 if ( XvGrabPort( display, port, CurrentTime ) == 0 )
00500                 {
00501 
00502                     int formats;
00503                     XvImageFormatValues *list;
00504 
00505                     list = XvListImageFormats( display, port, &formats );
00506 
00507                     cerr << ">>> formats supported: " << formats << endl;
00508 
00509                     for ( int i = 0; i < formats; i ++ )
00510                     {
00511                         fprintf( stderr, ">>>     0x%x (%c%c%c%c) %s\n",
00512                                  list[ i ].id,
00513                                  ( list[ i ].id ) & 0xff,
00514                                  ( list[ i ].id >> 8 ) & 0xff,
00515                                  ( list[ i ].id >> 16 ) & 0xff,
00516                                  ( list[ i ].id >> 24 ) & 0xff,
00517                                  ( list[ i ].format == XvPacked ) ? "packed" : "planar" );
00518                         if ( list[ i ].id == 0x32595559 && !gotPort )
00519                             gotPort = true;
00520                     }
00521 
00522                     if ( !gotPort )
00523                     {
00524                         XvUngrabPort( display, port, CurrentTime );
00525                     }
00526                     else
00527                     {
00528                         grabbedPort = port;
00529                         break;
00530                     }
00531                 }
00532             }
00533         }
00534 
00535         if ( gotPort )
00536         {
00537             int num;
00538             unsigned int unum;
00539             XvEncodingInfo *enc;
00540             
00541             XvQueryEncodings( display, grabbedPort, &unum, &enc );
00542             for ( unsigned int index = 0; index < unum; index ++ )
00543             {
00544                 fprintf( stderr, ">>> %d: %s, %ldx%ld rate = %d/%d\n", index, enc->name,
00545                         enc->width, enc->height, enc->rate.numerator,
00546                         enc->rate.denominator );
00547             }
00548             
00549             XvAttribute *xvattr = XvQueryPortAttributes( display, port, &num );
00550             for ( int k = 0; k < num; k++ )
00551             {
00552                 if ( xvattr[k].flags & XvSettable ) 
00553                 {
00554                     if ( strcmp( xvattr[k].name, "XV_AUTOPAINT_COLORKEY") == 0 )
00555                     {
00556                         Atom val_atom = XInternAtom( display, xvattr[k].name, False );
00557                         if ( XvSetPortAttribute( display, port, val_atom, 1 ) != Success )
00558                             fprintf(stderr, "Couldn't set Xv attribute %s\n", xvattr[k].name);
00559                     }
00560                     else if (  strcmp( xvattr[k].name, "XV_COLORKEY") == 0 )
00561                     {
00562                         Atom val_atom = XInternAtom( display, xvattr[k].name, False );
00563                         if ( XvSetPortAttribute( display, port, val_atom, 0x010102 ) != Success )
00564                             fprintf(stderr, "Couldn't set Xv attribute %s\n", xvattr[k].name);
00565                     }
00566                 }
00567             }
00568         }
00569 
00570         if ( gotPort )
00571         {
00572             gc = XCreateGC( display, window, 0, &values );
00573 
00574             xvImage = ( XvImage * ) XvShmCreateImage( display, port, 0x32595559, 0, width, height, &shmInfo );
00575 
00576             shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
00577             if (shmInfo.shmid < 0) {
00578                 perror("shmget");
00579                 gotPort = false;
00580             } else {
00581                 shmInfo.shmaddr = ( char * ) shmat( shmInfo.shmid, 0, 0 );
00582                 xvImage->data = shmInfo.shmaddr;
00583                 shmInfo.readOnly = 0;
00584                 if ( !XShmAttach( gdk_display, &shmInfo ) )
00585                 {
00586                     gotPort = false;
00587                 }
00588                 XSync( display, false );
00589                 shmctl( shmInfo.shmid, IPC_RMID, 0 );
00590 #if 0
00591                 xvImage = ( XvImage * ) XvCreateImage( display, port, 0x32595559, pix, width , height );
00592 #endif
00593             }
00594         }
00595     }
00596     else
00597     {
00598         gotPort = false;
00599     }
00600 }
00601 
00602 XvDisplayer::~XvDisplayer()
00603 {
00604     cerr << ">> Destroying XV Displayer" << endl;
00605 
00606     if ( gotPort )
00607     {
00608         XvUngrabPort( display, grabbedPort, CurrentTime );
00609     }
00610 
00611     if ( xvImage != NULL )
00612         XvStopVideo( display, port, window );
00613 
00614     if ( shmInfo.shmaddr != NULL )
00615     {
00616         XShmDetach( display, &shmInfo );
00617         shmctl( shmInfo.shmid, IPC_RMID, 0 );
00618         shmdt( shmInfo.shmaddr );
00619     }
00620     if ( xvImage != NULL )
00621         XFree( xvImage );
00622 }
00623 
00624 bool XvDisplayer::usable()
00625 {
00626     return gotPort;
00627 }
00628 
00629 DisplayerInput XvDisplayer::format()
00630 {
00631     return DISPLAY_YUV;
00632 }
00633 
00634 void XvDisplayer::put( void *image )
00635 {
00636     AspectRatioCalculator calc( ( ( GtkWidget * ) drawingarea ) ->allocation.width,
00637                                 ( ( GtkWidget * ) drawingarea ) ->allocation.height,
00638                                 this->preferredWidth(), this->preferredHeight(),
00639                                 isPAL, isWidescreen );
00640 
00641     memcpy( xvImage->data, image, xvImage->data_size );
00642 
00643     XvShmPutImage( display, port, window, gc, xvImage,
00644                    0, 0, this->preferredWidth(), this->preferredHeight(),
00645                    calc.x, calc.y, calc.width, calc.height, false );
00646 #if 0
00647 
00648     XvPutImage( display, port, window, gc, xvImage,
00649                 0, 0, this->preferredWidth(), this->preferredHeight(),
00650                 calc.x, calc.y, calc.width, calc.height );
00651 #endif
00652 }
00653 
00654 GdkDisplayer::GdkDisplayer( GtkWidget *drawingarea, int width, int height, bool is_wide )
00655 {
00656     this->drawingarea = drawingarea;
00657     img_width = width;
00658     img_height = height;
00659     m_is_wide = is_wide;
00660 }
00661 
00662 GdkDisplayer::~GdkDisplayer()
00663 {}
00664 
00665 bool GdkDisplayer::usable()
00666 {
00667     return true;
00668 }
00669 
00670 DisplayerInput GdkDisplayer::format()
00671 {
00672     return DISPLAY_RGB;
00673 }
00674 
00675 void GdkDisplayer::put( void *data )
00676 {
00677     unsigned char * image = ( unsigned char * ) data;
00678 
00679     AspectRatioCalculator calc( ( ( GtkWidget * ) drawingarea ) ->allocation.width,
00680                                 ( ( GtkWidget * ) drawingarea ) ->allocation.height,
00681                                 this->preferredWidth(), this->preferredHeight(),
00682                                 img_height == 576, m_is_wide );
00683 
00684     GdkGC *gc = gdk_gc_new( drawingarea->window );
00685     GdkPixbuf *pix = gdk_pixbuf_new_from_data( image, GDK_COLORSPACE_RGB, FALSE, 8, preferredWidth(), preferredHeight(), preferredWidth() * 3, NULL, NULL );
00686     GdkPixbuf *im = gdk_pixbuf_scale_simple( pix, calc.width, calc.height, GDK_INTERP_NEAREST );
00687     gdk_draw_pixbuf( drawingarea->window, gc, im, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 );
00688     g_object_unref( im );
00689     g_object_unref( pix );
00690     g_object_unref( gc );
00691 }
00692 
00693 Displayer *FindDisplayer::getDisplayer( GtkWidget *drawingarea, Frame &frame )
00694 {
00695     Displayer * display = NULL;
00696     Preferences &prefs = Preferences::getInstance();
00697         
00698     switch ( prefs.displayMode )
00699     {
00700     case DISPLAY_XV:
00701         display = new XvDisplayer( drawingarea, frame.GetWidth(), frame.GetHeight(),
00702                                    frame.IsPAL(), frame.IsWide() );
00703         if ( !display->usable() )
00704         {
00705             delete display;
00706             display = NULL;
00707         }
00708 
00709     case DISPLAY_XX:
00710         if ( display == NULL )
00711         {
00712             display = new XvDisplayer( drawingarea, frame.GetWidth() / 2, frame.GetHeight() / 2,
00713                                        frame.IsPAL(), frame.IsWide() );
00714             if ( !display->usable() )
00715             {
00716                 delete display;
00717                 display = NULL;
00718             }
00719         }
00720 
00721     default:
00722         if ( display == NULL )
00723         {
00724             display = new GdkDisplayer( drawingarea, frame.GetWidth(), frame.GetHeight(), frame.IsWide( ) );
00725         }
00726     }
00727 
00728     return display;
00729 }
00730 
00731 Displayer *FindDisplayer::getDisplayer( GtkWidget *drawingarea, int width, int height )
00732 {
00733     Displayer * display = NULL;
00734     Preferences &prefs = Preferences::getInstance();
00735 
00736     switch ( prefs.displayMode )
00737     {
00738     case DISPLAY_XV:
00739         display = new XvDisplayer( drawingarea, width, height, (height > 480), false );
00740         if ( !display->usable() )
00741         {
00742             delete display;
00743             display = NULL;
00744         }
00745 
00746     case DISPLAY_XX:
00747         if ( display == NULL )
00748         {
00749             display = new XvDisplayer( drawingarea, width / 2, height / 2, (height > 480), false );
00750             if ( !display->usable() )
00751             {
00752                 delete display;
00753                 display = NULL;
00754             }
00755         }
00756 
00757     default:
00758         if ( display == NULL )
00759         {
00760             display = new GdkDisplayer( drawingarea, width, height, false );
00761         }
00762     }
00763 
00764     return display;
00765 }

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2