Lumiera 0.pre.04~rc.1
»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 }
146
147 if (gotPort)
148 {
149// XGCValues values;
150// memset(&values, 0, sizeof(XGCValues));
152 gc = XCreateGC( display, window, 0, NULL );
153
154 xvImage = ( XvImage * ) XvShmCreateImage( display, grabbedPort, FORMAT_ID_YUY2, 0, videoWidth, videoHeight, &shmInfo );
155
156 shmInfo.shmid = shmget( IPC_PRIVATE, xvImage->data_size, IPC_CREAT | 0777 );
157 if (shmInfo.shmid < 0) {
158 perror("shmget");
159 gotPort = false;
160 }
161 else
162 {
163 shmInfo.shmaddr = (char*) shmat (shmInfo.shmid, 0, 0);
164 xvImage->data = shmInfo.shmaddr;
165 shmInfo.readOnly = 0;
166
167 if (!XShmAttach (display, &shmInfo))
168 {
169 gotPort = false;
170 }
171
172 XSync( display, false );
173 shmctl( shmInfo.shmid, IPC_RMID, 0 ); // mark the segment as deleted
174 } // -- it will be retained until the last client calls shmdt()
175 }
176 }
177 else
178 {
179 gotPort = false;
180 }
181 if (not gotPort)
182 ERROR (stage, "unable to use XVideo for display.");
183 }
184
185
187 {
188 NOBUG_ERROR(stage, "Destroying XV Displayer");
189
190 if ( gotPort )
191 {
192 XvUngrabPort( display, grabbedPort, CurrentTime );
193 }
194
195 if ( shmInfo.shmaddr != NULL )
196 {
197 XShmDetach( display, &shmInfo );
198 shmctl( shmInfo.shmid, IPC_RMID, 0 );
199 shmdt( shmInfo.shmaddr );
200 }
201
202 if ( xvImage != NULL )
203 XFree( xvImage );
204 }
205
206
207 bool
209 {
210 return gotPort;
211 }
212
213
214 void
215 XvDisplayer::put (void* const image)
216 {
217 REQUIRE (image != NULL);
218
219 if (xvImage != NULL)
220 {
221 REQUIRE (display != NULL);
222 REQUIRE (drawingArea_.get_mapped());
223
224 int org_x = 0, org_y = 0, destW = 0, destH = 0;
226 drawingArea_.get_width(),
227 drawingArea_.get_height(),
228 org_x, org_y, destW, destH );
229
230 auto spaceAlloc = drawingArea_.get_allocation();
231 org_x += spaceAlloc.get_x();
232 org_y += spaceAlloc.get_y();
233
234 memcpy (xvImage->data, image, xvImage->data_size);
235
236 XvShmPutImage (display, grabbedPort, window, gc, xvImage,
237 0, 0, videoWidth, videoHeight,
238 org_x, org_y, destW, destH, false);
239 XFlush (display);
240 }
241 }
242
243
244}} // 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.