summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Warren <swarren@wwwdotorg.org>2012-05-01 20:27:24 -0700
committerAaron Plattner <aplattner@nvidia.com>2012-09-04 09:49:17 -0700
commitca9e637c61e80145f0625a590c91429db67d0a40 (patch)
treeb76b00532e7d41e45560eb23425e74b0bd530c21
parent4262513e67c3572ed19bd796ec6180cdde7ccb7e (diff)
Implement workarounds for Adobe Flash bugs
Implement two workarounds: 1) Swap U and V planes to VdpVideoSurfacePutBitsYCbCr to fix blue-tinged videos. 2) Disable VdpPresentationQueueSetBackgroundColor, so that Flash doesn't set the background to pure black or pure white, which would cause the VDPAU image to bleed through to other parts of the desktop with those very common colors. These workarounds are only enabled when running under Flash player, and may be individually controlled via /etc/vdpau_wrapper.cfg, should they ever need to be disabled. Note that this code stores the VDPAU backend function pointers as global variables, which is technically incorrect. However, the likelihood of any known VDPAU implementation ever returning different values for these pointers within a single process is zero. If this becomes a problem, a hash table of VdpDevice to the stored pointers should be implemented. Signed-off-by: Stephen Warren <swarren@wwwdotorg.org> Reviewed-by: Aaron Plattner <aplattner@nvidia.com> Signed-off-by: Aaron Plattner <aplattner@nvidia.com> [aplattner@nvidia.com: fixed distcheck by changing it to dist_libvdpausysconf_DATA]
-rw-r--r--src/Makefile.am4
-rw-r--r--src/vdpau_wrapper.c170
-rw-r--r--src/vdpau_wrapper.cfg2
3 files changed, 174 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 48e69a7..7cb1c20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,7 @@
1AM_CFLAGS = \ 1AM_CFLAGS = \
2 -I$(top_srcdir)/include \ 2 -I$(top_srcdir)/include \
3 -DVDPAU_MODULEDIR="\"$(moduledir)\"" \ 3 -DVDPAU_MODULEDIR="\"$(moduledir)\"" \
4 -DVDPAU_SYSCONFDIR="\"$(sysconfdir)\"" \
4 $(X11_CFLAGS) \ 5 $(X11_CFLAGS) \
5 $(XEXT_CFLAGS) 6 $(XEXT_CFLAGS)
6 7
@@ -26,3 +27,6 @@ libvdpauincludedir = $(includedir)/vdpau
26libvdpauinclude_HEADERS = \ 27libvdpauinclude_HEADERS = \
27 $(top_srcdir)/include/vdpau/vdpau.h \ 28 $(top_srcdir)/include/vdpau/vdpau.h \
28 $(top_srcdir)/include/vdpau/vdpau_x11.h 29 $(top_srcdir)/include/vdpau/vdpau_x11.h
30
31libvdpausysconfdir=$(sysconfdir)
32dist_libvdpausysconf_DATA = vdpau_wrapper.cfg
diff --git a/src/vdpau_wrapper.c b/src/vdpau_wrapper.c
index 23de3d4..a1d5d40 100644
--- a/src/vdpau_wrapper.c
+++ b/src/vdpau_wrapper.c
@@ -210,6 +210,163 @@ static void _vdp_close_driver(void)
210 _vdp_imp_device_create_x11_proc = NULL; 210 _vdp_imp_device_create_x11_proc = NULL;
211} 211}
212 212
213static VdpGetProcAddress * _imp_get_proc_address;
214static VdpVideoSurfacePutBitsYCbCr * _imp_vid_put_bits_y_cb_cr;
215static VdpPresentationQueueSetBackgroundColor * _imp_pq_set_bg_color;
216static int _inited_fixes;
217static int _running_under_flash;
218static int _enable_flash_uv_swap = 1;
219static int _disable_flash_pq_bg_color = 1;
220
221static VdpStatus vid_put_bits_y_cb_cr_swapped(
222 VdpVideoSurface surface,
223 VdpYCbCrFormat source_ycbcr_format,
224 void const * const * source_data,
225 uint32_t const * source_pitches
226)
227{
228 void const * data_reordered[3];
229 void const * const * data;
230
231 if (source_ycbcr_format == VDP_YCBCR_FORMAT_YV12) {
232 data_reordered[0] = source_data[0];
233 data_reordered[1] = source_data[2];
234 data_reordered[2] = source_data[1];
235 /*
236 * source_pitches[1] and source_pitches[2] should be equal,
237 * so no need to re-order.
238 */
239 data = data_reordered;
240 }
241 else {
242 data = source_data;
243 }
244
245 return _imp_vid_put_bits_y_cb_cr(
246 surface,
247 source_ycbcr_format,
248 data,
249 source_pitches
250 );
251}
252
253static VdpStatus pq_set_bg_color_noop(
254 VdpPresentationQueue presentation_queue,
255 VdpColor * const background_color
256)
257{
258 return VDP_STATUS_OK;
259}
260
261static VdpStatus vdp_wrapper_get_proc_address(
262 VdpDevice device,
263 VdpFuncId function_id,
264 /* output parameters follow */
265 void * * function_pointer
266)
267{
268 VdpStatus status;
269
270 status = _imp_get_proc_address(device, function_id, function_pointer);
271 if (status != VDP_STATUS_OK) {
272 return status;
273 }
274
275 if (_running_under_flash) {
276 switch (function_id) {
277 case VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR:
278 if (_enable_flash_uv_swap) {
279 _imp_vid_put_bits_y_cb_cr = *function_pointer;
280 *function_pointer = vid_put_bits_y_cb_cr_swapped;
281 }
282 break;
283 case VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR:
284 if (_disable_flash_pq_bg_color) {
285 _imp_pq_set_bg_color = *function_pointer;
286 *function_pointer = pq_set_bg_color_noop;
287 }
288 break;
289 default:
290 break;
291 }
292 }
293
294 return VDP_STATUS_OK;
295}
296
297static void init_running_under_flash(void)
298{
299 FILE *fp;
300 char buffer[1024];
301 int ret, i;
302
303 fp = fopen("/proc/self/cmdline", "r");
304 if (!fp) {
305 return;
306 }
307 ret = fread(buffer, 1, sizeof(buffer) - 1, fp);
308 fclose(fp);
309 if (ret < 0) {
310 return;
311 }
312 /*
313 * Sometimes the file contains null between arguments. Wipe these out so
314 * strstr doesn't stop early.
315 */
316 for (i = 0; i < ret; i++) {
317 if (buffer[i] == '\0') {
318 buffer[i] = 'x';
319 }
320 }
321 buffer[ret] = '\0';
322
323 if (strstr(buffer, "libflashplayer") != NULL) {
324 _running_under_flash = 1;
325 }
326}
327
328void init_config(void)
329{
330 FILE *fp;
331 char buffer[1024];
332 int ret;
333
334 fp = fopen(VDPAU_SYSCONFDIR "/vdpau_wrapper.cfg", "r");
335 if (!fp) {
336 return;
337 }
338
339 while (fgets(buffer, sizeof(buffer), fp) != NULL) {
340 char * equals = strchr(buffer, '=');
341 char * param;
342
343 if (equals == NULL) {
344 continue;
345 }
346
347 *equals = '\0';
348 param = equals + 1;
349
350 if (!strcmp(buffer, "enable_flash_uv_swap")) {
351 _enable_flash_uv_swap = atoi(param);
352 }
353 else if (!strcmp(buffer, "disable_flash_pq_bg_color")) {
354 _disable_flash_pq_bg_color = atoi(param);
355 }
356 }
357}
358
359void init_fixes(void)
360{
361 if (_inited_fixes) {
362 return;
363 }
364 _inited_fixes = 1;
365
366 init_running_under_flash();
367 init_config();
368}
369
213VdpStatus vdp_device_create_x11( 370VdpStatus vdp_device_create_x11(
214 Display * display, 371 Display * display,
215 int screen, 372 int screen,
@@ -220,6 +377,8 @@ VdpStatus vdp_device_create_x11(
220{ 377{
221 VdpStatus status; 378 VdpStatus status;
222 379
380 init_fixes();
381
223 if (!_vdp_imp_device_create_x11_proc) { 382 if (!_vdp_imp_device_create_x11_proc) {
224 status = _vdp_open_driver(display, screen); 383 status = _vdp_open_driver(display, screen);
225 if (status != VDP_STATUS_OK) { 384 if (status != VDP_STATUS_OK) {
@@ -228,10 +387,17 @@ VdpStatus vdp_device_create_x11(
228 } 387 }
229 } 388 }
230 389
231 return _vdp_imp_device_create_x11_proc( 390 status = _vdp_imp_device_create_x11_proc(
232 display, 391 display,
233 screen, 392 screen,
234 device, 393 device,
235 get_proc_address 394 &_imp_get_proc_address
236 ); 395 );
396 if (status != VDP_STATUS_OK) {
397 return status;
398 }
399
400 *get_proc_address = vdp_wrapper_get_proc_address;
401
402 return VDP_STATUS_OK;
237} 403}
diff --git a/src/vdpau_wrapper.cfg b/src/vdpau_wrapper.cfg
new file mode 100644
index 0000000..21d5b8c
--- /dev/null
+++ b/src/vdpau_wrapper.cfg
@@ -0,0 +1,2 @@
1enable_flash_uv_swap=1
2disable_flash_pq_bg_color=1