Lumiera  0.pre.03
»edit your freedom«
xvdisplayer.cpp
Go to the documentation of this file.
1 /*
2  XvDisplayer - XVideo display
3 
4  Copyright (C)
5  2000, Arne Schirmacher <arne@schirmacher.de>
6  2001-2007, Dan Dennedy <dan@dennedy.org>
7  2008, Joel Holdsworth <joel@airwebreathe.org.uk>
8 
9   **Lumiera** is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2 of the License, or (at your
12   option) any later version. See the file COPYING for further details.
13 
14 * *****************************************************************/
15 
16 
27 #include "stage/gtk-base.hpp"
29 #include "include/logging.h"
30 
31 #include <gdk/gdkx.h>
32 
33 namespace stage {
34 namespace output {
35 
36  XvDisplayer::XvDisplayer(Gtk::Widget *drawing_area,
37  int width, int height)
38  : gotPort(false)
39  , drawingArea(drawing_area)
40  , xvImage(NULL)
41  {
42  REQUIRE(drawing_area != NULL);
43  REQUIRE(width > 0);
44  REQUIRE(height > 0);
45 
46  INFO(stage, "Trying XVideo at %d x %d", width, height);
47 
48  imageWidth = width;
49  imageHeight = height;
50 
51  shmInfo.shmaddr = NULL;
52 
53  Glib::RefPtr<Gdk::Window> area_window = drawing_area->get_window();
54 
55  window = GDK_WINDOW_XID (area_window->gobj());
56  display = GDK_WINDOW_XDISPLAY (area_window->gobj());
57 
58  uint count;
59  XvAdaptorInfo* adaptorInfo;
60 
61  if (XvQueryAdaptors (display, window, &count, &adaptorInfo) == Success)
62  {
63  INFO(stage, "XvQueryAdaptors count: %d", count);
64  for (uint n = 0; gotPort == false && n < count; ++n )
65  {
66  // Diagnostics
67  INFO(stage, "%s, %lu, %lu", adaptorInfo[ n ].name,
68  adaptorInfo[ n ].base_id, adaptorInfo[ n ].num_ports - 1);
69 
70  for (uint port = adaptorInfo[ n ].base_id;
71  port < adaptorInfo[ n ].base_id + adaptorInfo[ n ].num_ports;
72  port ++ )
73  {
74  if ( XvGrabPort( display, port, CurrentTime ) == Success )
75  {
76  int formats;
77  XvImageFormatValues* list;
78 
79  list = XvListImageFormats( display, port, &formats );
80 
81  INFO(stage, "formats supported: %d", formats);
82 
83  for ( int i = 0; i < formats; i ++ )
84  {
85  INFO(stage, "0x%x (%c%c%c%c) %s",
86  list[ i ].id,
87  ( list[ i ].id ) & 0xff,
88  ( list[ i ].id >> 8 ) & 0xff,
89  ( list[ i ].id >> 16 ) & 0xff,
90  ( list[ i ].id >> 24 ) & 0xff,
91  ( list[ i ].format == XvPacked ) ? "packed" : "planar" );
92  if ( list[ i ].id == 0x32595559 && !gotPort )
93  gotPort = true;
94  }
95 
96  if ( !gotPort )
97  {
98  XvUngrabPort( display, port, CurrentTime );
99  }
100  else
101  {
102  grabbedPort = port;
103  break;
104  }
105  }
106  }
107  }
108 
109  if ( gotPort )
110  {
111  int num;
112  uint unum;
113  XvEncodingInfo* enc;
114 
115  XvQueryEncodings( display, grabbedPort, &unum, &enc );
116  for (uint index = 0; index < unum; ++index )
117  {
118  INFO (stage, "%d: %s, %ldx%ld rate = %d/%d"
119  , index, enc->name
120  , enc->width, enc->height
121  , enc->rate.numerator
122  , enc->rate.denominator);
123  }
124 
125  XvAttribute* xvattr = XvQueryPortAttributes (display, grabbedPort, &num);
126  for (int k = 0; k < num; k++ )
127  {
128  if ( xvattr[k].flags & XvSettable )
129  {
130  if (strcmp (xvattr[k].name, "XV_AUTOPAINT_COLORKEY") == 0 )
131  {
132  Atom val_atom = XInternAtom( display, xvattr[k].name, False );
133  if (XvSetPortAttribute(display, grabbedPort, val_atom, 1 ) != Success )
134  NOBUG_ERROR(stage, "Couldn't set Xv attribute %s\n", xvattr[k].name);
135  }
136  else
137  if (strcmp (xvattr[k].name, "XV_COLORKEY") == 0 )
138  {
139  Atom val_atom = XInternAtom( display, xvattr[k].name, False );
140  if ( XvSetPortAttribute( display, grabbedPort, val_atom, 0x010102 ) != Success )
141  NOBUG_ERROR(stage, "Couldn't set Xv attribute %s\n", xvattr[k].name);
142  }
143  }
144  }
145  }
146 
147  if (gotPort)
148  {
149  XGCValues values;
150  memset(&values, 0, sizeof(XGCValues));
151  gc = XCreateGC( display, window, 0, NULL );
152 
153  xvImage = ( XvImage * ) XvShmCreateImage( display, grabbedPort, 0x32595559, 0, width, height, &shmInfo );
154 
155  shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
156  if (shmInfo.shmid < 0) {
157  perror("shmget");
158  gotPort = false;
159  }
160  else
161  {
162  shmInfo.shmaddr = (char*) shmat (shmInfo.shmid, 0, 0);
163  xvImage->data = shmInfo.shmaddr;
164  shmInfo.readOnly = 0;
165 
166  if (!XShmAttach (display, &shmInfo))
167  {
168  gotPort = false;
169  }
170 
171  XSync( display, false );
172  shmctl( shmInfo.shmid, IPC_RMID, 0 );
173  }
174  }
175  }
176  else
177  {
178  gotPort = false;
179  }
180  }
181 
182 
183  XvDisplayer::~XvDisplayer()
184  {
185  NOBUG_ERROR(stage, "Destroying XV Displayer");
186 
187  if ( gotPort )
188  {
189  XvUngrabPort( display, grabbedPort, CurrentTime );
190  }
191 
192  if ( shmInfo.shmaddr != NULL )
193  {
194  XShmDetach( display, &shmInfo );
195  shmctl( shmInfo.shmid, IPC_RMID, 0 );
196  shmdt( shmInfo.shmaddr );
197  }
198 
199  if ( xvImage != NULL )
200  XFree( xvImage );
201  }
202 
203 
204  bool
206  {
207  return gotPort;
208  }
209 
210 
211  void
212  XvDisplayer::put (void* const image)
213  {
214  REQUIRE (image != NULL);
215  REQUIRE (drawingArea != NULL);
216 
217  if (xvImage != NULL)
218  {
219  REQUIRE(display != NULL);
220 
221  int video_x = 0, video_y = 0, video_width = 0, video_height = 0;
223  drawingArea->get_width(),
224  drawingArea->get_height(),
226  video_x, video_y, video_width, video_height );
227 
228  memcpy (xvImage->data, image, xvImage->data_size);
229 
230  XvShmPutImage (display, grabbedPort, window, gc, xvImage,
231  0, 0, preferredWidth(), preferredHeight(),
232  video_x, video_y, video_width, video_height, false);
233  }
234  }
235 
236 
237 }} // namespace stage::output
GC gc
The graphics context which will be used when rendering video.
bool usable()
Indicates if this object can be used to render images on the running system.
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)
Calculates the coordinates for placing a video image inside a widget.
Definition: displayer.cpp:62
virtual int preferredHeight()
Expected height of input to put.
Definition: displayer.cpp:56
virtual DisplayerInput format()
Indicates the format required by the abstract put method.
Definition: displayer.cpp:44
virtual int preferredWidth()
Expected width of input to put.
Definition: displayer.cpp:50
void put(void *const image)
Put an image of a given width and height with the expected input format (as indicated by the format m...
This header is for including and configuring NoBug.
Window window
The X11 window that video will be drawn into.
uint grabbedPort
The current port being used.
Definition: xvdisplayer.hpp:93
bool gotPort
Specifies whether the object is currently attached to an XVideo port.
Definition: xvdisplayer.hpp:87
XShmSegmentInfo shmInfo
Info about the shared memory segment.
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:37
XvDisplayer(Gtk::Widget *drawing_area, int width, int height)
Constructor.
Definition: xvdisplayer.cpp:36
Display * display
The display that video will be drawn into.
Gtk::Widget * drawingArea
The widget that video will be drawn into.
Definition: xvdisplayer.hpp:99
XvImage * xvImage
The shared memory image object which video will be written into.
A set of basic GTK includes for the UI.
Implementation of video output via XVideo.
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption