OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/modules/video_render/linux/video_x11_channel.h" | |
12 | |
13 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
14 #include "webrtc/system_wrappers/include/trace.h" | |
15 | |
16 namespace webrtc { | |
17 | |
18 #define DISP_MAX 128 | |
19 | |
20 static Display *dispArray[DISP_MAX]; | |
21 static int dispCount = 0; | |
22 | |
23 | |
24 VideoX11Channel::VideoX11Channel(int32_t id) : | |
25 _crit(*CriticalSectionWrapper::CreateCriticalSection()), _display(NULL), | |
26 _shminfo(), _image(NULL), _window(0L), _gc(NULL), | |
27 _width(DEFAULT_RENDER_FRAME_WIDTH), | |
28 _height(DEFAULT_RENDER_FRAME_HEIGHT), _outWidth(0), _outHeight(0), | |
29 _xPos(0), _yPos(0), _prepared(false), _dispCount(0), _buffer(NULL), | |
30 _top(0.0), _left(0.0), _right(0.0), _bottom(0.0), | |
31 _Id(id) | |
32 { | |
33 } | |
34 | |
35 VideoX11Channel::~VideoX11Channel() | |
36 { | |
37 if (_prepared) | |
38 { | |
39 _crit.Enter(); | |
40 ReleaseWindow(); | |
41 _crit.Leave(); | |
42 } | |
43 delete &_crit; | |
44 } | |
45 | |
46 int32_t VideoX11Channel::RenderFrame(const uint32_t streamId, | |
47 const VideoFrame& videoFrame) { | |
48 CriticalSectionScoped cs(&_crit); | |
49 if (_width != videoFrame.width() || _height | |
50 != videoFrame.height()) { | |
51 if (FrameSizeChange(videoFrame.width(), videoFrame.height(), 1) == -1) { | |
52 return -1; | |
53 } | |
54 } | |
55 return DeliverFrame(videoFrame); | |
56 } | |
57 | |
58 int32_t VideoX11Channel::FrameSizeChange(int32_t width, | |
59 int32_t height, | |
60 int32_t /*numberOfStreams */) | |
61 { | |
62 CriticalSectionScoped cs(&_crit); | |
63 if (_prepared) | |
64 { | |
65 RemoveRenderer(); | |
66 } | |
67 if (CreateLocalRenderer(width, height) == -1) | |
68 { | |
69 return -1; | |
70 } | |
71 | |
72 return 0; | |
73 } | |
74 | |
75 int32_t VideoX11Channel::DeliverFrame(const VideoFrame& videoFrame) { | |
76 CriticalSectionScoped cs(&_crit); | |
77 if (!_prepared) { | |
78 return 0; | |
79 } | |
80 | |
81 if (!dispArray[_dispCount]) { | |
82 return -1; | |
83 } | |
84 | |
85 ConvertFromI420(videoFrame, kARGB, 0, _buffer); | |
86 | |
87 // Put image in window. | |
88 XShmPutImage(_display, _window, _gc, _image, 0, 0, _xPos, _yPos, _width, | |
89 _height, True); | |
90 | |
91 // Very important for the image to update properly! | |
92 XSync(_display, False); | |
93 return 0; | |
94 } | |
95 | |
96 int32_t VideoX11Channel::GetFrameSize(int32_t& width, int32_t& height) | |
97 { | |
98 width = _width; | |
99 height = _height; | |
100 | |
101 return 0; | |
102 } | |
103 | |
104 int32_t VideoX11Channel::Init(Window window, float left, float top, | |
105 float right, float bottom) | |
106 { | |
107 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s", | |
108 __FUNCTION__); | |
109 CriticalSectionScoped cs(&_crit); | |
110 | |
111 _window = window; | |
112 _left = left; | |
113 _right = right; | |
114 _top = top; | |
115 _bottom = bottom; | |
116 | |
117 _display = XOpenDisplay(NULL); // Use default display | |
118 if (!_window || !_display) | |
119 { | |
120 return -1; | |
121 } | |
122 | |
123 if (dispCount < DISP_MAX) | |
124 { | |
125 dispArray[dispCount] = _display; | |
126 _dispCount = dispCount; | |
127 dispCount++; | |
128 } | |
129 else | |
130 { | |
131 return -1; | |
132 } | |
133 | |
134 if ((1 < left || left < 0) || (1 < top || top < 0) || (1 < right || right | |
135 < 0) || (1 < bottom || bottom < 0)) | |
136 { | |
137 return -1; | |
138 } | |
139 | |
140 // calculate position and size of rendered video | |
141 int x, y; | |
142 unsigned int winWidth, winHeight, borderwidth, depth; | |
143 Window rootret; | |
144 if (XGetGeometry(_display, _window, &rootret, &x, &y, &winWidth, | |
145 &winHeight, &borderwidth, &depth) == 0) | |
146 { | |
147 return -1; | |
148 } | |
149 | |
150 _xPos = (int32_t) (winWidth * left); | |
151 _yPos = (int32_t) (winHeight * top); | |
152 _outWidth = (int32_t) (winWidth * (right - left)); | |
153 _outHeight = (int32_t) (winHeight * (bottom - top)); | |
154 if (_outWidth % 2) | |
155 _outWidth++; // the renderer want's sizes that are multiples of two | |
156 if (_outHeight % 2) | |
157 _outHeight++; | |
158 | |
159 _gc = XCreateGC(_display, _window, 0, 0); | |
160 if (!_gc) { | |
161 // Failed to create the graphics context. | |
162 assert(false); | |
163 return -1; | |
164 } | |
165 | |
166 if (CreateLocalRenderer(winWidth, winHeight) == -1) | |
167 { | |
168 return -1; | |
169 } | |
170 return 0; | |
171 | |
172 } | |
173 | |
174 int32_t VideoX11Channel::ChangeWindow(Window window) | |
175 { | |
176 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s", | |
177 __FUNCTION__); | |
178 CriticalSectionScoped cs(&_crit); | |
179 | |
180 // Stop the rendering, if we are rendering... | |
181 RemoveRenderer(); | |
182 _window = window; | |
183 | |
184 // calculate position and size of rendered video | |
185 int x, y; | |
186 unsigned int winWidth, winHeight, borderwidth, depth; | |
187 Window rootret; | |
188 if (XGetGeometry(_display, _window, &rootret, &x, &y, &winWidth, | |
189 &winHeight, &borderwidth, &depth) == -1) | |
190 { | |
191 return -1; | |
192 } | |
193 _xPos = (int) (winWidth * _left); | |
194 _yPos = (int) (winHeight * _top); | |
195 _outWidth = (int) (winWidth * (_right - _left)); | |
196 _outHeight = (int) (winHeight * (_bottom - _top)); | |
197 if (_outWidth % 2) | |
198 _outWidth++; // the renderer want's sizes that are multiples of two | |
199 if (_outHeight % 2) | |
200 _outHeight++; | |
201 | |
202 // Prepare rendering using the | |
203 if (CreateLocalRenderer(_width, _height) == -1) | |
204 { | |
205 return -1; | |
206 } | |
207 return 0; | |
208 } | |
209 | |
210 int32_t VideoX11Channel::ReleaseWindow() | |
211 { | |
212 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s", | |
213 __FUNCTION__); | |
214 CriticalSectionScoped cs(&_crit); | |
215 | |
216 RemoveRenderer(); | |
217 if (_gc) { | |
218 XFreeGC(_display, _gc); | |
219 _gc = NULL; | |
220 } | |
221 if (_display) | |
222 { | |
223 XCloseDisplay(_display); | |
224 _display = NULL; | |
225 } | |
226 return 0; | |
227 } | |
228 | |
229 int32_t VideoX11Channel::CreateLocalRenderer(int32_t width, int32_t height) | |
230 { | |
231 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s", | |
232 __FUNCTION__); | |
233 CriticalSectionScoped cs(&_crit); | |
234 | |
235 if (!_window || !_display) | |
236 { | |
237 return -1; | |
238 } | |
239 | |
240 if (_prepared) | |
241 { | |
242 WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _Id, | |
243 "Renderer already prepared, exits."); | |
244 return -1; | |
245 } | |
246 | |
247 _width = width; | |
248 _height = height; | |
249 | |
250 // create shared memory image | |
251 _image = XShmCreateImage(_display, CopyFromParent, 24, ZPixmap, NULL, | |
252 &_shminfo, _width, _height); // this parameter need
s to be the same for some reason. | |
253 _shminfo.shmid = shmget(IPC_PRIVATE, (_image->bytes_per_line | |
254 * _image->height), IPC_CREAT | 0777); | |
255 _shminfo.shmaddr = _image->data = (char*) shmat(_shminfo.shmid, 0, 0); | |
256 if (_image->data == reinterpret_cast<char*>(-1)) | |
257 { | |
258 return -1; | |
259 } | |
260 _buffer = (unsigned char*) _image->data; | |
261 _shminfo.readOnly = False; | |
262 | |
263 // attach image to display | |
264 if (!XShmAttach(_display, &_shminfo)) | |
265 { | |
266 //printf("XShmAttach failed !\n"); | |
267 return -1; | |
268 } | |
269 XSync(_display, False); | |
270 | |
271 _prepared = true; | |
272 return 0; | |
273 } | |
274 | |
275 int32_t VideoX11Channel::RemoveRenderer() | |
276 { | |
277 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s", | |
278 __FUNCTION__); | |
279 | |
280 if (!_prepared) | |
281 { | |
282 return 0; | |
283 } | |
284 _prepared = false; | |
285 | |
286 // Free the memory. | |
287 XShmDetach(_display, &_shminfo); | |
288 XDestroyImage( _image ); | |
289 _image = NULL; | |
290 shmdt(_shminfo.shmaddr); | |
291 _shminfo.shmaddr = NULL; | |
292 _buffer = NULL; | |
293 shmctl(_shminfo.shmid, IPC_RMID, 0); | |
294 _shminfo.shmid = 0; | |
295 return 0; | |
296 } | |
297 | |
298 int32_t VideoX11Channel::GetStreamProperties(uint32_t& zOrder, | |
299 float& left, float& top, | |
300 float& right, float& bottom) const | |
301 { | |
302 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s", | |
303 __FUNCTION__); | |
304 | |
305 zOrder = 0; // no z-order support yet | |
306 left = _left; | |
307 top = _top; | |
308 right = _right; | |
309 bottom = _bottom; | |
310 | |
311 return 0; | |
312 } | |
313 | |
314 | |
315 } // namespace webrtc | |
OLD | NEW |