Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
xv-displayer.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
23#include "stage/gtk-base.hpp"
25#include "include/logging.h"
26//#include "lib/format-cout.hpp"
27
28#include <gdk/gdkx.h>
29#include <sys/ipc.h>
30#include <sys/shm.h>
31
32namespace stage {
33namespace output {
34
35 namespace {
36 const uint32_t FORMAT_ID_YUY2 = 0x32595559;
37 }
38
39 XvDisplayer::XvDisplayer(Gtk::Widget& drawing_area
40 ,uint width, uint height)
41 : Displayer{width,height}
42 , gotPort{false}
43 , drawingArea_{drawing_area}
44 , xvImage{nullptr}
45 {
46 REQUIRE (videoWidth > 0);
47 REQUIRE (videoHeight > 0);
48
49 INFO(stage, "Trying XVideo at %d x %d", videoWidth, videoHeight);
50
51 shmInfo.shmaddr = NULL;
52
53 Glib::RefPtr<Gdk::Window> area_window = drawingArea_.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 and 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 == FORMAT_ID_YUY2 and not 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 /* WARNING: some graphic cards (notably my very old NVidia card) do not properly support the XV-Keying feature.
146 * The above loop is written in a »defensive« way, insofar it is not permitted to set/change X attributes
147 * that are not provided and supported by your hardware and driver stack.
148 * It may thus happen (and it happens on my System) that the X driver somehow applies a default keying
149 * to the complete XWindow. However, if parts of that window are used by other UI elements (as is the case
150 * with our docking-panels), then these other widgets become "garbled" and will not repaint properly.
151 * It does not help to attempt to paint explicitly with low-level X functions into that problematic region,
152 * and I could not figure out why such an attempted fix does not work, when we paint in the on_map()-Event.
153 * We can paint just fine with the same low-level functions from within the put() call.
154 *
155 * Anyhow, as such the XV display works correct even in such cases, but it looks "broken" :-(
156 */
157 }
158
159 if (gotPort)
160 {
161// XGCValues values;
162// memset(&values, 0, sizeof(XGCValues));
164 gc = XCreateGC( display, window, 0, NULL );
165
166 xvImage = ( XvImage * ) XvShmCreateImage( display, grabbedPort, FORMAT_ID_YUY2, 0, videoWidth, videoHeight, &shmInfo );
167
168 shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
169 if (shmInfo.shmid < 0) {
170 perror("shmget");
171 gotPort = false;
172 }
173 else
174 {
175 shmInfo.shmaddr = (char*) shmat (shmInfo.shmid, 0, 0);
176 xvImage->data = shmInfo.shmaddr;
177 shmInfo.readOnly = 0;
178
179 if (!XShmAttach (display, &shmInfo))
180 {
181 gotPort = false;
182 }
183
184 XSync( display, false );
185 shmctl( shmInfo.shmid, IPC_RMID, 0 ); // mark the segment as deleted
186 } // -- it will be retained until the last client calls shmdt()
187 }
188 }
189 else
190 {
191 gotPort = false;
192 }
193 if (not gotPort)
194 ERROR (stage, "unable to use XVideo for display.");
195 }
196
197
199 {
200 NOBUG_ERROR(stage, "Destroying XV Displayer");
201
202 if ( gotPort )
203 {
204 XvUngrabPort( display, grabbedPort, CurrentTime );
205 }
206
207 if ( shmInfo.shmaddr != NULL )
208 {
209 XShmDetach( display, &shmInfo );
210 shmctl( shmInfo.shmid, IPC_RMID, 0 );
211 shmdt( shmInfo.shmaddr );
212 }
213
214 if ( xvImage != NULL )
215 XFree( xvImage );
216 }
217
218
219 bool
221 {
222 return gotPort;
223 }
224
225
226 void
227 XvDisplayer::put (void* const image)
228 {
229 REQUIRE (image != NULL);
230
231 if (xvImage != NULL)
232 {
233 REQUIRE (display != NULL);
234 REQUIRE (drawingArea_.get_mapped());
235
236 int org_x = 0, org_y = 0, destW = 0, destH = 0;
238 drawingArea_.get_width(),
239 drawingArea_.get_height(),
240 org_x, org_y, destW, destH );
241
242 auto spaceAlloc = drawingArea_.get_allocation();
243 org_x += spaceAlloc.get_x();
244 org_y += spaceAlloc.get_y();
245
246 memcpy (xvImage->data, image, xvImage->data_size);
247
248 XvShmPutImage (display, grabbedPort, window, gc, xvImage,
249 0, 0, videoWidth, videoHeight,
250 org_x, org_y, destW, destH, false);
251 XFlush (display);
252 }
253 }
254
255
256}} // namespace stage::output
A Displayer is a class which is responsible for rendering an image in some way (ie: Xvideo,...
Definition displayer.hpp:62
void calculateVideoLayout(int widgetWidth, int widgetHeight, int &imgOrg_x, int &imgOrg_y, int &imgWidth, int &imgHeight)
Calculates the coordinates for placing a video image inside a widget.
Definition displayer.cpp:45
Gtk::Widget & drawingArea_
The widget that video will be drawn into.
void put(void *const image) override
Put an image of a given width and height with the expected input format (as indicated by the format m...
XvDisplayer(Gtk::Widget &drawing_area, uint width, uint height)
Constructor.
bool usable() override
Indicates if this object can be used to render images on the running system.
DisplayerInput format() override
Indicates the format required by the abstract put method.
bool gotPort
Specifies whether the object is currently attached to an XVideo port.
uint grabbedPort
The current port being used.
GC gc
The graphics context which will be used when rendering video.
XShmSegmentInfo shmInfo
Info about the shared memory segment.
Display * display
The display that video will be drawn into.
Window window
The X11 window that video will be drawn into.
XvImage * xvImage
The shared memory image object which video will be written into.
A set of basic GTK includes for the UI.
unsigned int uint
Definition integral.hpp:29
return NULL
Definition llist.h:586
This header is for including and configuring NoBug.
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
Implementation of video output via XVideo.