00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "../gtk-lumiera.hpp"
00026
00027 #include <gdk/gdkx.h>
00028
00029 #include "xvdisplayer.hpp"
00030
00031 namespace gui {
00032 namespace output {
00033
00034 XvDisplayer::XvDisplayer( Gtk::Widget *drawing_area, int width, int height ) :
00035 xvImage( NULL ),
00036 drawingArea( drawing_area ),
00037 gotPort( false )
00038 {
00039 INFO(gui, "Trying XVideo at %d x %d", width, height);
00040
00041 imageWidth = width, imageHeight = height;
00042
00043 shmInfo.shmaddr = NULL;
00044
00045 Glib::RefPtr<Gdk::Window> area_window = drawing_area->get_window();
00046
00047 window = gdk_x11_drawable_get_xid( area_window->gobj() );
00048 display = gdk_x11_drawable_get_xdisplay( area_window->gobj() );
00049
00050 unsigned int count;
00051 XvAdaptorInfo *adaptorInfo;
00052
00053 if ( XvQueryAdaptors( display, window, &count, &adaptorInfo ) == Success )
00054 {
00055
00056 INFO(gui, "XvQueryAdaptors count: %d", count);
00057 for ( unsigned int n = 0; gotPort == false && n < count; ++n )
00058 {
00059
00060 INFO(gui, "%s, %d, %d, %d", adaptorInfo[ n ].name,
00061 adaptorInfo[ n ].base_id, adaptorInfo[ n ].num_ports - 1);
00062
00063 for ( port = adaptorInfo[ n ].base_id;
00064 port < adaptorInfo[ n ].base_id + adaptorInfo[ n ].num_ports;
00065 port ++ )
00066 {
00067 if ( XvGrabPort( display, port, CurrentTime ) == Success )
00068 {
00069 int formats;
00070 XvImageFormatValues *list;
00071
00072 list = XvListImageFormats( display, port, &formats );
00073
00074 INFO(gui, "formats supported: %d", formats);
00075
00076 for ( int i = 0; i < formats; i ++ )
00077 {
00078 INFO(gui, "0x%x (%c%c%c%c) %s",
00079 list[ i ].id,
00080 ( list[ i ].id ) & 0xff,
00081 ( list[ i ].id >> 8 ) & 0xff,
00082 ( list[ i ].id >> 16 ) & 0xff,
00083 ( list[ i ].id >> 24 ) & 0xff,
00084 ( list[ i ].format == XvPacked ) ? "packed" : "planar" );
00085 if ( list[ i ].id == 0x32595559 && !gotPort )
00086 gotPort = true;
00087 }
00088
00089 if ( !gotPort )
00090 {
00091 XvUngrabPort( display, port, CurrentTime );
00092 }
00093 else
00094 {
00095 grabbedPort = port;
00096 break;
00097 }
00098 }
00099 }
00100 }
00101
00102 if ( gotPort )
00103 {
00104 int num;
00105 unsigned int unum;
00106 XvEncodingInfo *enc;
00107
00108 XvQueryEncodings( display, grabbedPort, &unum, &enc );
00109 for ( unsigned int index = 0; index < unum; index ++ )
00110 {
00111 INFO(gui, "%d: %s, %ldx%ld rate = %d/%d", index, enc->name,
00112 enc->width, enc->height, enc->rate.numerator,
00113 enc->rate.denominator );
00114 }
00115
00116 XvAttribute *xvattr = XvQueryPortAttributes( display, port, &num );
00117 for ( int k = 0; k < num; k++ )
00118 {
00119 if ( xvattr[k].flags & XvSettable )
00120 {
00121 if ( strcmp( xvattr[k].name, "XV_AUTOPAINT_COLORKEY") == 0 )
00122 {
00123 Atom val_atom = XInternAtom( display, xvattr[k].name, False );
00124 if ( XvSetPortAttribute( display, port, val_atom, 1 ) != Success )
00125 ERROR(gui, "Couldn't set Xv attribute %s\n", xvattr[k].name);
00126 }
00127 else if ( strcmp( xvattr[k].name, "XV_COLORKEY") == 0 )
00128 {
00129 Atom val_atom = XInternAtom( display, xvattr[k].name, False );
00130 if ( XvSetPortAttribute( display, port, val_atom, 0x010102 ) != Success )
00131 ERROR(gui, "Couldn't set Xv attribute %s\n", xvattr[k].name);
00132 }
00133 }
00134 }
00135 }
00136
00137 if ( gotPort )
00138 {
00139 gc = XCreateGC( display, window, 0, &values );
00140
00141 xvImage = ( XvImage * ) XvShmCreateImage( display, port, 0x32595559, 0, width, height, &shmInfo );
00142
00143 shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
00144 if (shmInfo.shmid < 0) {
00145 perror("shmget");
00146 gotPort = false;
00147 }
00148 else
00149 {
00150 shmInfo.shmaddr = ( char * ) shmat( shmInfo.shmid, 0, 0 );
00151 xvImage->data = shmInfo.shmaddr;
00152 shmInfo.readOnly = 0;
00153 if ( !XShmAttach( gdk_display, &shmInfo ) )
00154 {
00155 gotPort = false;
00156 }
00157 XSync( display, false );
00158 shmctl( shmInfo.shmid, IPC_RMID, 0 );
00159 #if 0
00160 xvImage = ( XvImage * ) XvCreateImage( display, port, 0x32595559, pix, width , height );
00161 #endif
00162 }
00163 }
00164 }
00165 else
00166 {
00167 gotPort = false;
00168 }
00169 }
00170
00171 XvDisplayer::~XvDisplayer()
00172 {
00173 ERROR(gui, "Destroying XV Displayer");
00174
00175 if ( gotPort )
00176 {
00177 XvUngrabPort( display, grabbedPort, CurrentTime );
00178 }
00179
00180
00181
00182
00183 if ( shmInfo.shmaddr != NULL )
00184 {
00185 XShmDetach( display, &shmInfo );
00186 shmctl( shmInfo.shmid, IPC_RMID, 0 );
00187 shmdt( shmInfo.shmaddr );
00188 }
00189
00190 if ( xvImage != NULL )
00191 XFree( xvImage );
00192 }
00193
00194 bool
00195 XvDisplayer::usable()
00196 {
00197 return gotPort;
00198 }
00199
00200 void
00201 XvDisplayer::put( void *image )
00202 {
00203 REQUIRE(image != NULL);
00204 REQUIRE(drawingArea != NULL);
00205
00206 if(xvImage != NULL)
00207 {
00208 int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
00209 calculateVideoLayout(
00210 drawingArea->get_width(),
00211 drawingArea->get_height(),
00212 preferredWidth(), preferredHeight(),
00213 video_x, video_y, video_width, video_height );
00214
00215 memcpy( xvImage->data, image, xvImage->data_size );
00216
00217 XvShmPutImage( display, port, window, gc, xvImage,
00218 0, 0, preferredWidth(), preferredHeight(),
00219 video_x, video_y, video_width, video_height, false );
00220 }
00221 }
00222
00223 }
00224 }