Tidied up the displayer code and added some documentation
This commit is contained in:
parent
8cb48a7298
commit
cdf26d3fe6
5 changed files with 405 additions and 316 deletions
|
|
@ -33,99 +33,97 @@
|
|||
namespace gui {
|
||||
namespace output {
|
||||
|
||||
#define MAX_WIDTH 720
|
||||
#define MAX_HEIGHT 576
|
||||
/**
|
||||
* Supported Displayer formats
|
||||
**/
|
||||
typedef enum {
|
||||
DISPLAY_NONE,
|
||||
DISPLAY_YUV,
|
||||
DISPLAY_RGB,
|
||||
DISPLAY_BGR,
|
||||
DISPLAY_BGR0,
|
||||
DISPLAY_RGB16
|
||||
}
|
||||
DisplayerInput;
|
||||
|
||||
/** Supported Displayer formats
|
||||
/**
|
||||
* A Displayer is a class which is responsible for rendering an image
|
||||
* in some way (ie: Xvideo, GDK, OpenGL etc).
|
||||
*
|
||||
* @remarks All Displayer classes must extend the Displayer class and
|
||||
* minimally rewrite:
|
||||
*
|
||||
* + usable() - to indicate if the object can be used,
|
||||
* + format() - to indicate what type of input the put method expects
|
||||
* + put( void * ) - deal with an image of the expected type and size
|
||||
*
|
||||
* By default, all images will be delivered to the put method in a
|
||||
* resolution of IMG_WIDTH * IMG_HEIGHT. If another size is required,
|
||||
* then the rewrite the methods:
|
||||
*
|
||||
* + preferredWidth
|
||||
* + preferredHeight
|
||||
*
|
||||
* If the widget being written to doesn't need a fixed size, then
|
||||
* rewrite the two other put methods as required.
|
||||
*/
|
||||
class Displayer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Indicates if this object can be used to render images on the
|
||||
* running system.
|
||||
*/
|
||||
typedef enum {
|
||||
DISPLAY_NONE,
|
||||
DISPLAY_YUV,
|
||||
DISPLAY_RGB,
|
||||
DISPLAY_BGR,
|
||||
DISPLAY_BGR0,
|
||||
DISPLAY_RGB16
|
||||
}
|
||||
DisplayerInput;
|
||||
virtual bool usable();
|
||||
|
||||
/**
|
||||
* Indicates the format required by the abstract put method.
|
||||
*/
|
||||
virtual DisplayerInput format();
|
||||
|
||||
/**
|
||||
* Expected width of input to put.
|
||||
*/
|
||||
virtual int preferredWidth();
|
||||
|
||||
/**
|
||||
* Expected height of input to put.
|
||||
*/
|
||||
virtual int preferredHeight();
|
||||
|
||||
/**
|
||||
* A Displayer is a class which is responsible for rendering an image
|
||||
* in some way (ie: Xvideo, GDK, OpenGL etc).
|
||||
*
|
||||
* @remarks All Displayer classes must extend the Displayer class and
|
||||
* minimally rewrite:
|
||||
*
|
||||
* + usable() - to indicate if the object can be used,
|
||||
* + format() - to indicate what type of input the put method expects
|
||||
* + put( void * ) - deal with an image of the expected type and size
|
||||
*
|
||||
* By default, all images will be delivered to the put method in a
|
||||
* resolution of IMG_WIDTH * IMG_HEIGHT. If another size is required,
|
||||
* then the rewrite the methods:
|
||||
*
|
||||
* + preferredWidth
|
||||
* + preferredHeight
|
||||
*
|
||||
* If the widget being written to doesn't need a fixed size, then
|
||||
* rewrite the two other put methods as required.
|
||||
* Put an image of a given width and height with the expected input
|
||||
* format (as indicated by the format method).
|
||||
*/
|
||||
class Displayer
|
||||
{
|
||||
public:
|
||||
virtual void put( const void* ) = 0;
|
||||
|
||||
/**
|
||||
* Indicates if an object can be used to render images on the
|
||||
* running system.
|
||||
*/
|
||||
virtual bool usable();
|
||||
|
||||
/**
|
||||
* Indicates the format required by the abstract put method.
|
||||
*/
|
||||
virtual DisplayerInput format();
|
||||
|
||||
/**
|
||||
* Expected width of input to put.
|
||||
*/
|
||||
virtual int preferredWidth();
|
||||
|
||||
/**
|
||||
* Expected height of input to put.
|
||||
*/
|
||||
virtual int preferredHeight();
|
||||
|
||||
/**
|
||||
* Put an image of a given width and height with the expected input
|
||||
* format (as indicated by the format method).
|
||||
*/
|
||||
virtual void put( void * ) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Calculates the coordinates for placing a video image inside a
|
||||
* widget
|
||||
*
|
||||
* @param[in] widget_width The width of the display widget.
|
||||
* @param[in] widget_height The height of the display widget.
|
||||
* @param[in] image_width The width of the video image.
|
||||
* @param[in] image_height The height of the video image.
|
||||
* @param[out] video_x The x-coordinate of the top left
|
||||
* corner of the scaled video image.
|
||||
* @param[out] video_y The y-coordinate of the top left
|
||||
* corner of the scaled video image.
|
||||
* @param[out] video_width The width of the scale video image.
|
||||
* @param[out] video_height The height of the scale video image.
|
||||
*/
|
||||
static void calculateVideoLayout(
|
||||
int widget_width, int widget_height,
|
||||
int image_width, int image_height,
|
||||
int &video_x, int &video_y, int &video_width, int &video_height );
|
||||
protected:
|
||||
|
||||
protected:
|
||||
int imageWidth;
|
||||
int imageHeight;
|
||||
};
|
||||
/**
|
||||
* Calculates the coordinates for placing a video image inside a
|
||||
* widget
|
||||
*
|
||||
* @param[in] widget_width The width of the display widget.
|
||||
* @param[in] widget_height The height of the display widget.
|
||||
* @param[in] image_width The width of the video image.
|
||||
* @param[in] image_height The height of the video image.
|
||||
* @param[out] video_x The x-coordinate of the top left
|
||||
* corner of the scaled video image.
|
||||
* @param[out] video_y The y-coordinate of the top left
|
||||
* corner of the scaled video image.
|
||||
* @param[out] video_width The width of the scale video image.
|
||||
* @param[out] video_height The height of the scale video image.
|
||||
*/
|
||||
static void calculateVideoLayout(
|
||||
int widget_width, int widget_height,
|
||||
int image_width, int image_height,
|
||||
int &video_x, int &video_y, int &video_width, int &video_height );
|
||||
|
||||
protected:
|
||||
int imageWidth;
|
||||
int imageHeight;
|
||||
};
|
||||
|
||||
} // namespace output
|
||||
} // namespace gui
|
||||
|
|
|
|||
|
|
@ -36,49 +36,49 @@ namespace output {
|
|||
|
||||
GdkDisplayer::GdkDisplayer( Gtk::Widget *drawing_area, int width, int height ) :
|
||||
drawingArea( drawing_area )
|
||||
{
|
||||
REQUIRE(drawing_area != NULL);
|
||||
REQUIRE(width > 0);
|
||||
REQUIRE(height > 0);
|
||||
|
||||
imageWidth = width, imageHeight = height;
|
||||
}
|
||||
{
|
||||
REQUIRE(drawing_area != NULL);
|
||||
REQUIRE(width > 0);
|
||||
REQUIRE(height > 0);
|
||||
|
||||
imageWidth = width, imageHeight = height;
|
||||
}
|
||||
|
||||
bool
|
||||
GdkDisplayer::usable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GdkDisplayer::put( void *image )
|
||||
{
|
||||
int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
|
||||
calculateVideoLayout(
|
||||
drawingArea->get_width(),
|
||||
drawingArea->get_height(),
|
||||
preferredWidth(), preferredHeight(),
|
||||
video_x, video_y, video_width, video_height );
|
||||
GdkDisplayer::put( const void* image )
|
||||
{
|
||||
int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
|
||||
calculateVideoLayout(
|
||||
drawingArea->get_width(),
|
||||
drawingArea->get_height(),
|
||||
preferredWidth(), preferredHeight(),
|
||||
video_x, video_y, video_width, video_height );
|
||||
|
||||
GdkWindow *window = drawingArea->get_window()->gobj();
|
||||
REQUIRE(window != NULL);
|
||||
|
||||
GdkGC *gc = gdk_gc_new( window );
|
||||
REQUIRE(gc != NULL);
|
||||
|
||||
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( (const guchar*)image, GDK_COLORSPACE_RGB, FALSE, 8,
|
||||
preferredWidth(), preferredHeight(), preferredWidth() * 3, NULL, NULL );
|
||||
REQUIRE(pixbuf != NULL);
|
||||
|
||||
GdkPixbuf *scaled_image = gdk_pixbuf_scale_simple( pixbuf, video_width, video_height, GDK_INTERP_NEAREST );
|
||||
REQUIRE(scaled_image != NULL);
|
||||
|
||||
gdk_draw_pixbuf( window, gc, scaled_image, 0, 0, video_x, video_y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 );
|
||||
GdkWindow *window = drawingArea->get_window()->gobj();
|
||||
REQUIRE(window != NULL);
|
||||
|
||||
g_object_unref( scaled_image );
|
||||
g_object_unref( pixbuf );
|
||||
g_object_unref( gc );
|
||||
}
|
||||
GdkGC *gc = gdk_gc_new( window );
|
||||
REQUIRE(gc != NULL);
|
||||
|
||||
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( (const guchar*)image, GDK_COLORSPACE_RGB, FALSE, 8,
|
||||
preferredWidth(), preferredHeight(), preferredWidth() * 3, NULL, NULL );
|
||||
REQUIRE(pixbuf != NULL);
|
||||
|
||||
GdkPixbuf *scaled_image = gdk_pixbuf_scale_simple( pixbuf, video_width, video_height, GDK_INTERP_NEAREST );
|
||||
REQUIRE(scaled_image != NULL);
|
||||
|
||||
gdk_draw_pixbuf( window, gc, scaled_image, 0, 0, video_x, video_y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 );
|
||||
|
||||
g_object_unref( scaled_image );
|
||||
g_object_unref( pixbuf );
|
||||
g_object_unref( gc );
|
||||
}
|
||||
|
||||
} // namespace output
|
||||
} // namespace gui
|
||||
|
|
|
|||
|
|
@ -40,19 +40,48 @@ namespace Gtk {
|
|||
namespace gui {
|
||||
namespace output {
|
||||
|
||||
/**
|
||||
* GdkDisplayer is a class which is responsible for rendering a video
|
||||
* image via GDK.
|
||||
**/
|
||||
class GdkDisplayer : public Displayer
|
||||
{
|
||||
public:
|
||||
GdkDisplayer( Gtk::Widget *drawing_area, int width, int height );
|
||||
{
|
||||
public:
|
||||
|
||||
void put( void *image );
|
||||
|
||||
protected:
|
||||
bool usable();
|
||||
/**
|
||||
* Constructor
|
||||
* @param[in] drawing_area The widget into which the video image will
|
||||
* be drawn. This value must not be NULL.
|
||||
* @param[in] width The width of the video image in pixels. This value
|
||||
* must be greater than zero.
|
||||
* @param[in] height The height of the video image in pixels. This
|
||||
* value must be greater than zero.
|
||||
**/
|
||||
GdkDisplayer( Gtk::Widget *drawing_area, int width, int height );
|
||||
|
||||
private:
|
||||
Gtk::Widget *drawingArea;
|
||||
};
|
||||
/**
|
||||
* Put an image of a given width and height with the expected input
|
||||
* format (as indicated by the format method).
|
||||
* @param[in] image The video image array to draw.
|
||||
*/
|
||||
void put( const void* image );
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Indicates if this object can be used to render images on the
|
||||
* running system.
|
||||
*/
|
||||
bool usable();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The widget that video will be drawn into.
|
||||
* @remarks This value must be a valid pointer.
|
||||
**/
|
||||
Gtk::Widget *drawingArea;
|
||||
};
|
||||
|
||||
} // namespace output
|
||||
} // namespace gui
|
||||
|
|
|
|||
|
|
@ -35,190 +35,192 @@ XvDisplayer::XvDisplayer( Gtk::Widget *drawing_area, int width, int height ) :
|
|||
gotPort( false ),
|
||||
drawingArea( drawing_area ),
|
||||
xvImage( NULL )
|
||||
{
|
||||
INFO(gui, "Trying XVideo at %d x %d", width, height);
|
||||
{
|
||||
REQUIRE(drawing_area != NULL);
|
||||
REQUIRE(width > 0);
|
||||
REQUIRE(height > 0);
|
||||
|
||||
INFO(gui, "Trying XVideo at %d x %d", width, height);
|
||||
|
||||
imageWidth = width, imageHeight = height;
|
||||
imageWidth = width, imageHeight = height;
|
||||
|
||||
shmInfo.shmaddr = NULL;
|
||||
shmInfo.shmaddr = NULL;
|
||||
|
||||
Glib::RefPtr<Gdk::Window> area_window = drawing_area->get_window();
|
||||
Glib::RefPtr<Gdk::Window> area_window = drawing_area->get_window();
|
||||
|
||||
window = gdk_x11_drawable_get_xid( area_window->gobj() );
|
||||
display = gdk_x11_drawable_get_xdisplay( area_window->gobj() );
|
||||
window = gdk_x11_drawable_get_xid( area_window->gobj() );
|
||||
display = gdk_x11_drawable_get_xdisplay( area_window->gobj() );
|
||||
|
||||
unsigned int count;
|
||||
XvAdaptorInfo *adaptorInfo;
|
||||
unsigned int count;
|
||||
XvAdaptorInfo *adaptorInfo;
|
||||
|
||||
if ( XvQueryAdaptors( display, window, &count, &adaptorInfo ) == Success )
|
||||
{
|
||||
if ( XvQueryAdaptors( display, window, &count, &adaptorInfo ) == Success )
|
||||
{
|
||||
|
||||
INFO(gui, "XvQueryAdaptors count: %d", count);
|
||||
for ( unsigned int n = 0; gotPort == false && n < count; ++n )
|
||||
{
|
||||
// Diagnostics
|
||||
INFO(gui, "%s, %d, %d, %d", adaptorInfo[ n ].name,
|
||||
adaptorInfo[ n ].base_id, adaptorInfo[ n ].num_ports - 1);
|
||||
INFO(gui, "XvQueryAdaptors count: %d", count);
|
||||
for ( unsigned int n = 0; gotPort == false && n < count; ++n )
|
||||
{
|
||||
// Diagnostics
|
||||
INFO(gui, "%s, %d, %d, %d", adaptorInfo[ n ].name,
|
||||
adaptorInfo[ n ].base_id, adaptorInfo[ n ].num_ports - 1);
|
||||
|
||||
for ( port = adaptorInfo[ n ].base_id;
|
||||
port < adaptorInfo[ n ].base_id + adaptorInfo[ n ].num_ports;
|
||||
port ++ )
|
||||
for ( unsigned int port = adaptorInfo[ n ].base_id;
|
||||
port < adaptorInfo[ n ].base_id + adaptorInfo[ n ].num_ports;
|
||||
port ++ )
|
||||
{
|
||||
if ( XvGrabPort( display, port, CurrentTime ) == Success )
|
||||
{
|
||||
int formats;
|
||||
XvImageFormatValues *list;
|
||||
|
||||
list = XvListImageFormats( display, port, &formats );
|
||||
|
||||
INFO(gui, "formats supported: %d", formats);
|
||||
|
||||
for ( int i = 0; i < formats; i ++ )
|
||||
{
|
||||
INFO(gui, "0x%x (%c%c%c%c) %s",
|
||||
list[ i ].id,
|
||||
( list[ i ].id ) & 0xff,
|
||||
( list[ i ].id >> 8 ) & 0xff,
|
||||
( list[ i ].id >> 16 ) & 0xff,
|
||||
( list[ i ].id >> 24 ) & 0xff,
|
||||
( list[ i ].format == XvPacked ) ? "packed" : "planar" );
|
||||
if ( list[ i ].id == 0x32595559 && !gotPort )
|
||||
gotPort = true;
|
||||
}
|
||||
|
||||
if ( !gotPort )
|
||||
{
|
||||
XvUngrabPort( display, port, CurrentTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
grabbedPort = port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( gotPort )
|
||||
{
|
||||
int num;
|
||||
unsigned int unum;
|
||||
XvEncodingInfo *enc;
|
||||
|
||||
XvQueryEncodings( display, grabbedPort, &unum, &enc );
|
||||
for ( unsigned int index = 0; index < unum; index ++ )
|
||||
{
|
||||
INFO(gui, "%d: %s, %ldx%ld rate = %d/%d", index, enc->name,
|
||||
enc->width, enc->height, enc->rate.numerator,
|
||||
enc->rate.denominator );
|
||||
}
|
||||
|
||||
XvAttribute *xvattr = XvQueryPortAttributes( display, grabbedPort, &num );
|
||||
for ( int k = 0; k < num; k++ )
|
||||
{
|
||||
if ( xvattr[k].flags & XvSettable )
|
||||
{
|
||||
if ( strcmp( xvattr[k].name, "XV_AUTOPAINT_COLORKEY") == 0 )
|
||||
{
|
||||
Atom val_atom = XInternAtom( display, xvattr[k].name, False );
|
||||
if ( XvSetPortAttribute( display, grabbedPort, val_atom, 1 ) != Success )
|
||||
ERROR(gui, "Couldn't set Xv attribute %s\n", xvattr[k].name);
|
||||
}
|
||||
else if ( strcmp( xvattr[k].name, "XV_COLORKEY") == 0 )
|
||||
{
|
||||
Atom val_atom = XInternAtom( display, xvattr[k].name, False );
|
||||
if ( XvSetPortAttribute( display, grabbedPort, val_atom, 0x010102 ) != Success )
|
||||
ERROR(gui, "Couldn't set Xv attribute %s\n", xvattr[k].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( gotPort )
|
||||
{
|
||||
XGCValues values;
|
||||
memset(&values, 0, sizeof(XGCValues));
|
||||
gc = XCreateGC( display, window, 0, NULL );
|
||||
|
||||
xvImage = ( XvImage * ) XvShmCreateImage( display, grabbedPort, 0x32595559, 0, width, height, &shmInfo );
|
||||
|
||||
shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
|
||||
if (shmInfo.shmid < 0) {
|
||||
perror("shmget");
|
||||
gotPort = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
shmInfo.shmaddr = ( char * ) shmat( shmInfo.shmid, 0, 0 );
|
||||
xvImage->data = shmInfo.shmaddr;
|
||||
shmInfo.readOnly = 0;
|
||||
if ( !XShmAttach( gdk_display, &shmInfo ) )
|
||||
{
|
||||
if ( XvGrabPort( display, port, CurrentTime ) == Success )
|
||||
{
|
||||
int formats;
|
||||
XvImageFormatValues *list;
|
||||
|
||||
list = XvListImageFormats( display, port, &formats );
|
||||
|
||||
INFO(gui, "formats supported: %d", formats);
|
||||
|
||||
for ( int i = 0; i < formats; i ++ )
|
||||
{
|
||||
INFO(gui, "0x%x (%c%c%c%c) %s",
|
||||
list[ i ].id,
|
||||
( list[ i ].id ) & 0xff,
|
||||
( list[ i ].id >> 8 ) & 0xff,
|
||||
( list[ i ].id >> 16 ) & 0xff,
|
||||
( list[ i ].id >> 24 ) & 0xff,
|
||||
( list[ i ].format == XvPacked ) ? "packed" : "planar" );
|
||||
if ( list[ i ].id == 0x32595559 && !gotPort )
|
||||
gotPort = true;
|
||||
}
|
||||
|
||||
if ( !gotPort )
|
||||
{
|
||||
XvUngrabPort( display, port, CurrentTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
grabbedPort = port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( gotPort )
|
||||
{
|
||||
int num;
|
||||
unsigned int unum;
|
||||
XvEncodingInfo *enc;
|
||||
|
||||
XvQueryEncodings( display, grabbedPort, &unum, &enc );
|
||||
for ( unsigned int index = 0; index < unum; index ++ )
|
||||
{
|
||||
INFO(gui, "%d: %s, %ldx%ld rate = %d/%d", index, enc->name,
|
||||
enc->width, enc->height, enc->rate.numerator,
|
||||
enc->rate.denominator );
|
||||
}
|
||||
|
||||
XvAttribute *xvattr = XvQueryPortAttributes( display, port, &num );
|
||||
for ( int k = 0; k < num; k++ )
|
||||
{
|
||||
if ( xvattr[k].flags & XvSettable )
|
||||
{
|
||||
if ( strcmp( xvattr[k].name, "XV_AUTOPAINT_COLORKEY") == 0 )
|
||||
{
|
||||
Atom val_atom = XInternAtom( display, xvattr[k].name, False );
|
||||
if ( XvSetPortAttribute( display, port, val_atom, 1 ) != Success )
|
||||
ERROR(gui, "Couldn't set Xv attribute %s\n", xvattr[k].name);
|
||||
}
|
||||
else if ( strcmp( xvattr[k].name, "XV_COLORKEY") == 0 )
|
||||
{
|
||||
Atom val_atom = XInternAtom( display, xvattr[k].name, False );
|
||||
if ( XvSetPortAttribute( display, port, val_atom, 0x010102 ) != Success )
|
||||
ERROR(gui, "Couldn't set Xv attribute %s\n", xvattr[k].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( gotPort )
|
||||
{
|
||||
gc = XCreateGC( display, window, 0, &values );
|
||||
|
||||
xvImage = ( XvImage * ) XvShmCreateImage( display, port, 0x32595559, 0, width, height, &shmInfo );
|
||||
|
||||
shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
|
||||
if (shmInfo.shmid < 0) {
|
||||
perror("shmget");
|
||||
gotPort = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
shmInfo.shmaddr = ( char * ) shmat( shmInfo.shmid, 0, 0 );
|
||||
xvImage->data = shmInfo.shmaddr;
|
||||
shmInfo.readOnly = 0;
|
||||
if ( !XShmAttach( gdk_display, &shmInfo ) )
|
||||
{
|
||||
gotPort = false;
|
||||
}
|
||||
XSync( display, false );
|
||||
shmctl( shmInfo.shmid, IPC_RMID, 0 );
|
||||
#if 0
|
||||
xvImage = ( XvImage * ) XvCreateImage( display, port, 0x32595559, pix, width , height );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gotPort = false;
|
||||
}
|
||||
}
|
||||
XSync( display, false );
|
||||
shmctl( shmInfo.shmid, IPC_RMID, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gotPort = false;
|
||||
}
|
||||
}
|
||||
|
||||
XvDisplayer::~XvDisplayer()
|
||||
{
|
||||
ERROR(gui, "Destroying XV Displayer");
|
||||
{
|
||||
ERROR(gui, "Destroying XV Displayer");
|
||||
|
||||
if ( gotPort )
|
||||
{
|
||||
XvUngrabPort( display, grabbedPort, CurrentTime );
|
||||
}
|
||||
if ( gotPort )
|
||||
{
|
||||
XvUngrabPort( display, grabbedPort, CurrentTime );
|
||||
}
|
||||
|
||||
//if ( xvImage != NULL )
|
||||
// XvStopVideo( display, port, window );
|
||||
|
||||
if ( shmInfo.shmaddr != NULL )
|
||||
{
|
||||
XShmDetach( display, &shmInfo );
|
||||
shmctl( shmInfo.shmid, IPC_RMID, 0 );
|
||||
shmdt( shmInfo.shmaddr );
|
||||
}
|
||||
|
||||
if ( xvImage != NULL )
|
||||
XFree( xvImage );
|
||||
}
|
||||
if ( shmInfo.shmaddr != NULL )
|
||||
{
|
||||
XShmDetach( display, &shmInfo );
|
||||
shmctl( shmInfo.shmid, IPC_RMID, 0 );
|
||||
shmdt( shmInfo.shmaddr );
|
||||
}
|
||||
|
||||
if ( xvImage != NULL )
|
||||
XFree( xvImage );
|
||||
}
|
||||
|
||||
bool
|
||||
XvDisplayer::usable()
|
||||
{
|
||||
return gotPort;
|
||||
}
|
||||
{
|
||||
return gotPort;
|
||||
}
|
||||
|
||||
void
|
||||
XvDisplayer::put( void *image )
|
||||
{
|
||||
REQUIRE(image != NULL);
|
||||
REQUIRE(drawingArea != NULL);
|
||||
|
||||
if(xvImage != NULL)
|
||||
{
|
||||
int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
|
||||
calculateVideoLayout(
|
||||
drawingArea->get_width(),
|
||||
drawingArea->get_height(),
|
||||
preferredWidth(), preferredHeight(),
|
||||
video_x, video_y, video_width, video_height );
|
||||
XvDisplayer::put( const void* image )
|
||||
{
|
||||
REQUIRE(image != NULL);
|
||||
REQUIRE(drawingArea != NULL);
|
||||
|
||||
if(xvImage != NULL)
|
||||
{
|
||||
REQUIRE(display != NULL);
|
||||
|
||||
int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
|
||||
calculateVideoLayout(
|
||||
drawingArea->get_width(),
|
||||
drawingArea->get_height(),
|
||||
preferredWidth(), preferredHeight(),
|
||||
video_x, video_y, video_width, video_height );
|
||||
|
||||
memcpy( xvImage->data, image, xvImage->data_size );
|
||||
memcpy( xvImage->data, image, xvImage->data_size );
|
||||
|
||||
XvShmPutImage( display, port, window, gc, xvImage,
|
||||
0, 0, preferredWidth(), preferredHeight(),
|
||||
video_x, video_y, video_width, video_height, false );
|
||||
}
|
||||
}
|
||||
XvShmPutImage( display, grabbedPort, window, gc, xvImage,
|
||||
0, 0, preferredWidth(), preferredHeight(),
|
||||
video_x, video_y, video_width, video_height, false );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace output
|
||||
} // namespace gui
|
||||
|
|
|
|||
|
|
@ -46,30 +46,90 @@ namespace Gtk {
|
|||
namespace gui {
|
||||
namespace output {
|
||||
|
||||
class XvDisplayer : public Displayer
|
||||
{
|
||||
public:
|
||||
XvDisplayer( Gtk::Widget *drawing_area, int width, int height );
|
||||
~XvDisplayer();
|
||||
|
||||
void put( void *image );
|
||||
/**
|
||||
* XvDisplayer is a class which is responsible for rendering a video
|
||||
* image via XVideo.
|
||||
**/
|
||||
class XvDisplayer : public Displayer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param drawing_area The widget into which the video image will be
|
||||
* drawn. This value must not be NULL.
|
||||
* @param width The width of the video image in pixels. This value
|
||||
* must be greater than zero.
|
||||
* @param height The height of the video image in pixels. This value
|
||||
* must be greater than zero.
|
||||
**/
|
||||
XvDisplayer( Gtk::Widget *drawing_area, int width, int height );
|
||||
|
||||
protected:
|
||||
bool usable();
|
||||
/**
|
||||
* Destructor
|
||||
**/
|
||||
~XvDisplayer();
|
||||
|
||||
private:
|
||||
bool gotPort;
|
||||
int grabbedPort;
|
||||
Gtk::Widget *drawingArea;
|
||||
Display *display;
|
||||
Window window;
|
||||
GC gc;
|
||||
XGCValues values;
|
||||
XvImage *xvImage;
|
||||
unsigned int port;
|
||||
XShmSegmentInfo shmInfo;
|
||||
char pix[ MAX_WIDTH * MAX_HEIGHT * 4 ];
|
||||
};
|
||||
/**
|
||||
* Put an image of a given width and height with the expected input
|
||||
* format (as indicated by the format method).
|
||||
* @param[in] image The video image array to draw.
|
||||
*/
|
||||
void put( const void* image );
|
||||
|
||||
/**
|
||||
* Indicates if this object can be used to render images on the
|
||||
* running system.
|
||||
*/
|
||||
bool usable();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Specifies whether the object is currently attached to an XVideo
|
||||
* port.
|
||||
* @remarks This value is false until the constructor has finished
|
||||
* successfully.
|
||||
**/
|
||||
bool gotPort;
|
||||
|
||||
/**
|
||||
* The current port being used.
|
||||
* @remarks This value is meaninless unless gotPort is true.
|
||||
**/
|
||||
unsigned int grabbedPort;
|
||||
|
||||
/**
|
||||
* The widget that video will be drawn into.
|
||||
* @remarks This value must be a valid pointer.
|
||||
**/
|
||||
Gtk::Widget *drawingArea;
|
||||
|
||||
/**
|
||||
* The display that video will be drawn into.
|
||||
**/
|
||||
Display *display;
|
||||
|
||||
/**
|
||||
* The X11 window that video will be drawn into.
|
||||
**/
|
||||
Window window;
|
||||
|
||||
/**
|
||||
* The graphics context which will be used when rednering video.
|
||||
**/
|
||||
GC gc;
|
||||
|
||||
/**
|
||||
* The shared memory image object which video will be written into.
|
||||
**/
|
||||
XvImage *xvImage;
|
||||
|
||||
/**
|
||||
* Info about the shared memory segment.
|
||||
* @remarks shmInfo.shmaddr is set to NULL, when the SHM is detached.
|
||||
**/
|
||||
XShmSegmentInfo shmInfo;
|
||||
};
|
||||
|
||||
} // namespace output
|
||||
} // namespace gui
|
||||
|
|
|
|||
Loading…
Reference in a new issue