diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.00-xdpau_reset_pvr_changes.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.00-xdpau_reset_pvr_changes.patch
new file mode 100644
index 0000000000..e1ff0da442
--- /dev/null
+++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.00-xdpau_reset_pvr_changes.patch
@@ -0,0 +1,91 @@
+diff -Naur xbmc-pvr-11.0.1/language/Dutch/strings.xml xbmc-pvr-11.0.1.patch/language/Dutch/strings.xml
+--- xbmc-pvr-11.0.1/language/Dutch/strings.xml 2012-03-27 17:55:51.000000000 +0200
++++ xbmc-pvr-11.0.1.patch/language/Dutch/strings.xml 2012-05-14 09:40:49.363267601 +0200
+@@ -1542,7 +1542,6 @@
+ Spline36
+ Spline36 geoptimaliseerd
+ Software menging
+- Auto - ION geoptimaliseerd
+
+ Kwaliteitsverbetering video
+
+diff -Naur xbmc-pvr-11.0.1/language/English/strings.xml xbmc-pvr-11.0.1.patch/language/English/strings.xml
+--- xbmc-pvr-11.0.1/language/English/strings.xml 2012-03-27 17:55:51.000000000 +0200
++++ xbmc-pvr-11.0.1.patch/language/English/strings.xml 2012-05-14 09:40:49.366267654 +0200
+@@ -1539,9 +1539,7 @@
+ DXVA Best
+ Spline36
+ Spline36 optimized
+-
+ Software Blend
+- Auto - ION Optimized
+
+ Post-processing
+
+diff -Naur xbmc-pvr-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp xbmc-pvr-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
+--- xbmc-pvr-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp 2012-03-27 17:55:38.000000000 +0200
++++ xbmc-pvr-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp 2012-05-14 09:40:49.371267744 +0200
+@@ -531,8 +531,7 @@
+ bool CVDPAU::Supports(EINTERLACEMETHOD method)
+ {
+ if(method == VS_INTERLACEMETHOD_VDPAU_BOB
+- || method == VS_INTERLACEMETHOD_AUTO
+- || method == VS_INTERLACEMETHOD_AUTO_ION)
++ || method == VS_INTERLACEMETHOD_AUTO)
+ return true;
+
+ for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++)
+@@ -658,21 +657,8 @@
+ }
+ else
+ {
+- if (method == VS_INTERLACEMETHOD_AUTO_ION)
+- {
+- if (vid_height <= 576)
+- {
+- VdpBool enabled[]={1,1,0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- else if (vid_height > 576)
+- {
+- VdpBool enabled[]={1,0,0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- }
+- else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF)
++ if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF)
+ {
+ VdpBool enabled[]={1,0,0};
+ vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+@@ -1401,16 +1387,14 @@
+ if (mode == VS_DEINTERLACEMODE_FORCE
+ || (mode == VS_DEINTERLACEMODE_AUTO && m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED))
+ {
+- if((method == VS_INTERLACEMETHOD_AUTO_ION
+- || method == VS_INTERLACEMETHOD_VDPAU_BOB
++ if((method == VS_INTERLACEMETHOD_VDPAU_BOB
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
+ || method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE ))
+ {
+- if((method == VS_INTERLACEMETHOD_AUTO_ION && vid_height > 576)
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
++ if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
+ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
+ || avctx->skip_frame == AVDISCARD_NONREF)
+ m_mixerstep = 0;
+diff -Naur xbmc-pvr-11.0.1/xbmc/video/dialogs/GUIDialogVideoSettings.cpp xbmc-pvr-11.0.1.patch/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+--- xbmc-pvr-11.0.1/xbmc/video/dialogs/GUIDialogVideoSettings.cpp 2012-03-27 17:55:34.000000000 +0200
++++ xbmc-pvr-11.0.1.patch/xbmc/video/dialogs/GUIDialogVideoSettings.cpp 2012-05-14 09:40:52.908330712 +0200
+@@ -113,7 +113,6 @@
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , 16314));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BOB , 16320));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BEST , 16321));
+- entries.push_back(make_pair(VS_INTERLACEMETHOD_AUTO_ION , 16325));
+
+ /* remove unsupported methods */
+ for(vector >::iterator it = entries.begin(); it != entries.end();)
diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.01-xvba_support-fc969e525002544a65cbf9660c4562cd4e2d45f1.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.01-xvba_support-fc969e525002544a65cbf9660c4562cd4e2d45f1.patch
deleted file mode 100644
index 7738d91487..0000000000
--- a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.01-xvba_support-fc969e525002544a65cbf9660c4562cd4e2d45f1.patch
+++ /dev/null
@@ -1,7176 +0,0 @@
-diff --git a/configure.in b/configure.in
-index e1cc9d2..d0d3beb 100755
---- a/configure.in
-+++ b/configure.in
-@@ -98,6 +98,8 @@ vaapi_not_found="== Could not find libva. VAAPI support disabled. =="
- vaapi_disabled="== VAAPI support manually disabled. =="
- crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. =="
- crystalhd_disabled="== CrystalHD support manually disabled. =="
-+xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. =="
-+xvba_disabled="== XVBA support manually disabled. =="
- vdadecoder_enabled="== VDADecoder support enabled. =="
- vdadecoder_disabled="== VDADecoder support manually disabled. =="
- vtbdecoder_enabled="== VTBDecoder support enabled. =="
-@@ -204,6 +206,12 @@ AC_ARG_ENABLE([crystalhd],
- [enable CrystalHD decoding (default is auto)])],
- [use_crystalhd=$enableval],
- [use_crystalhd=auto])
-+
-+AC_ARG_ENABLE([xvba],
-+ [AS_HELP_STRING([--enable-xvba],
-+ [enable XVBA decoding (default is auto)])],
-+ [use_xvba=$enableval],
-+ [use_xvba=auto])
-
- AC_ARG_ENABLE([vdadecoder],
- [AS_HELP_STRING([--enable-vdadecoder],
-@@ -1382,6 +1390,38 @@ else
- USE_CRYSTALHD=0
- fi
-
-+# XVBA
-+if test "x$use_xvba" != "xno"; then
-+ if test "$host_vendor" = "apple" ; then
-+ if test "x$use_xvba" = "xyes"; then
-+ AC_MSG_ERROR([XVBA not supported on this platform])
-+ else
-+ use_xvba="no"
-+ AC_MSG_NOTICE($xvba_disabled)
-+ fi
-+ USE_XVBA=0
-+ else
-+ initial_val=$use_xvba
-+ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include ])
-+
-+ if test "x$use_xvba" = "xno"; then
-+ if test "x$initial_val" = "xyes"; then
-+ AC_MSG_ERROR($xvba_not_found)
-+ else
-+ AC_MSG_RESULT($xvba_not_found)
-+ fi
-+ USE_XVBA=0
-+ else
-+ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)])
-+ USE_XVBA=1
-+ fi
-+ fi
-+else
-+ AC_MSG_NOTICE($xvba_disabled)
-+ USE_XVBA=0
-+fi
-+
-+
- # VDADecoder
- if test "x$use_vdadecoder" != "xno"; then
- if test "$host_vendor" = "apple" ; then
-@@ -1578,6 +1618,12 @@ else
- final_message="$final_message\n CrystalHD:\tNo"
- fi
-
-+if test "x$use_xvba" != "xno"; then
-+ final_message="$final_message\n XVBA:\t\tYes"
-+else
-+ final_message="$final_message\n XVBA:\t\tNo"
-+fi
-+
- if test "x$use_vdadecoder" != "xno"; then
- final_message="$final_message\n VDADecoder:\tYes"
- else
-@@ -1952,6 +1998,7 @@ AC_SUBST(USE_OPENGLES)
- AC_SUBST(USE_VDPAU)
- AC_SUBST(USE_VAAPI)
- AC_SUBST(USE_CRYSTALHD)
-+AC_SUBST(USE_XVBA)
- AC_SUBST(USE_LIBSMBCLIENT)
- AC_SUBST(USE_LIBNFS)
- AC_SUBST(USE_LIBAFPCLIENT)
-@@ -2094,6 +2141,7 @@ XB_CONFIG_MODULE([lib/ffmpeg], [
- --enable-gpl \
- `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \
- `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \
-+ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \
- --enable-protocol=http \
- --enable-pthreads \
- --enable-runtime-cpudetect \
-diff --git a/language/English/strings.xml b/language/English/strings.xml
-index 0cf25b6..c48c056 100644
---- a/language/English/strings.xml
-+++ b/language/English/strings.xml
-@@ -1234,6 +1234,8 @@
- Allow hardware acceleration (OpenMax)
- Pixel Shaders
- Allow hardware acceleration (VideoToolbox)
-+ Allow hardware acceleration (XVBA)
-+ Use XvBA shared surfaces
-
- A/V sync method
- Audio clock
-diff --git a/lib/UnrarXLib/extract.cpp b/lib/UnrarXLib/extract.cpp
-index b4a8091..da60857 100644
---- a/lib/UnrarXLib/extract.cpp
-+++ b/lib/UnrarXLib/extract.cpp
-@@ -1,9 +1,5 @@
- #include "rar.hpp"
- #include "Util.h"
--#ifdef _LINUX
--#include "XSyncUtils.h"
--#include "XEventUtils.h"
--#endif
-
- // a cautious wrapper around strncpy
- char *strncpy_null_terminated(char *dest, const char *src, size_t n)
-diff --git a/lib/UnrarXLib/unpack.cpp b/lib/UnrarXLib/unpack.cpp
-index 265b54f..bc2f220 100644
---- a/lib/UnrarXLib/unpack.cpp
-+++ b/lib/UnrarXLib/unpack.cpp
-@@ -8,11 +8,6 @@
- #include "unpack20.cpp"
- #endif
-
--#ifdef _LINUX
--#include "XSyncUtils.h"
--#include "XEventUtils.h"
--#endif
--
- Unpack::Unpack(ComprDataIO *DataIO)
- {
- UnpIO=DataIO;
-diff --git a/lib/UnrarXLib/unpack15.cpp b/lib/UnrarXLib/unpack15.cpp
-index e1b5f10..725e2be 100644
---- a/lib/UnrarXLib/unpack15.cpp
-+++ b/lib/UnrarXLib/unpack15.cpp
-@@ -1,7 +1,3 @@
--#ifdef _LINUX
--#include "XSyncUtils.h"
--#endif
--
- #define STARTL1 2
- static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
- 0xee00,0xf000,0xf200,0xf200,0xffff};
-diff --git a/lib/ffmpeg/configure b/lib/ffmpeg/configure
-index fec801c..fc73296 100755
---- a/lib/ffmpeg/configure
-+++ b/lib/ffmpeg/configure
-@@ -111,6 +111,7 @@ Configuration options:
- --disable-vaapi disable VAAPI code
- --disable-vdpau disable VDPAU code
- --disable-dxva2 disable DXVA2 code
-+ --disable-xvba disable XVBA code
- --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
- --enable-hardcoded-tables use hardcoded tables instead of runtime generation
- --enable-memalign-hack emulate memalign, interferes with memory debuggers
-@@ -932,6 +933,7 @@ CONFIG_LIST="
- swscale_alpha
- vaapi
- vdpau
-+ xvba
- version3
- x11grab
- zlib
-@@ -1240,6 +1242,7 @@ h264_decoder_select="golomb h264dsp h264pred"
- h264_dxva2_hwaccel_deps="dxva2api_h"
- h264_dxva2_hwaccel_select="dxva2 h264_decoder"
- h264_vaapi_hwaccel_select="vaapi"
-+h264_xvba_hwaccel_select="xvba"
- h264_vdpau_decoder_select="vdpau h264_decoder"
- imc_decoder_select="fft mdct"
- jpegls_decoder_select="golomb"
-@@ -1263,6 +1266,7 @@ mpeg2_dxva2_hwaccel_deps="dxva2api_h"
- mpeg2_dxva2_hwaccel_select="dxva2 mpeg2video_decoder"
- mpeg2_vaapi_hwaccel_select="vaapi mpeg2video_decoder"
- mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
-+mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder"
- mpeg4_vdpau_decoder_deps="vdpau_vdpau_h vdpau_vdpau_x11_h vdpau_mpeg4_support"
- mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
- mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h"
-@@ -1306,6 +1310,7 @@ vc1_decoder_select="h263_decoder"
- vc1_dxva2_hwaccel_deps="dxva2api_h DXVA_PictureParameters_wDecodedPictureIndex"
- vc1_dxva2_hwaccel_select="dxva2 vc1_decoder"
- vc1_vaapi_hwaccel_select="vaapi vc1_decoder"
-+vc1_xvba_hwaccel_select="xvba vc1_decoder"
- vc1_vdpau_decoder_select="vdpau vc1_decoder"
- vorbis_decoder_select="mdct"
- vorbis_encoder_select="mdct"
-@@ -1327,12 +1332,14 @@ wmv3_decoder_select="vc1_decoder"
- wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
- wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
- wmv3_vdpau_decoder_select="vc1_vdpau_decoder"
-+wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel"
- zlib_decoder_select="zlib"
- zlib_encoder_select="zlib"
- zmbv_decoder_select="zlib"
- zmbv_encoder_select="zlib"
-
- vaapi_deps="va_va_h"
-+xvba_deps="amd_amdxvba_h"
- vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
-
- # parsers
-@@ -2762,6 +2769,7 @@ check_header sys/select.h
- check_header termios.h
- check_header vdpau/vdpau.h
- check_header vdpau/vdpau_x11.h
-+check_header amd/amdxvba.h
- check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support
-
- check_header X11/extensions/XvMClib.h
-diff --git a/lib/ffmpeg/libavcodec/Makefile b/lib/ffmpeg/libavcodec/Makefile
-index 6a0a05b..65cca69 100644
---- a/lib/ffmpeg/libavcodec/Makefile
-+++ b/lib/ffmpeg/libavcodec/Makefile
-@@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak
- NAME = avcodec
- FFLIBS = avcore avutil
-
--HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h
-+HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h xvba.h
-
- OBJS = allcodecs.o \
- audioconvert.o \
-@@ -43,6 +43,7 @@ RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o
- OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes)
- OBJS-$(CONFIG_VAAPI) += vaapi.o
- OBJS-$(CONFIG_VDPAU) += vdpau.o
-+OBJS-$(CONFIG_XVBA) += xvba.o
-
- # decoders/encoders/hardware accelerators
- OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
-@@ -169,6 +170,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \
- mpegvideo.o error_resilience.o
- OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
- OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
-+OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o
- OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o
- OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o
- OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o
-@@ -246,6 +248,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
- mpegvideo.o error_resilience.o
- OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
- OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
-+OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o
- OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \
- mpegvideo.o error_resilience.o
- OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
-@@ -379,6 +382,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \
- intrax8.o intrax8dsp.o
- OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
- OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
-+OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o
- OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
- OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
- OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
-@@ -647,6 +651,7 @@ SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
- SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h
- SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h
- SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h
-+SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h
- SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h
- SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
- SKIPHEADERS += mpegaudio3.h
-diff --git a/lib/ffmpeg/libavcodec/allcodecs.c b/lib/ffmpeg/libavcodec/allcodecs.c
-index 04c5c6a..38b8791 100644
---- a/lib/ffmpeg/libavcodec/allcodecs.c
-+++ b/lib/ffmpeg/libavcodec/allcodecs.c
-@@ -57,13 +57,17 @@ void avcodec_register_all(void)
- REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);
- REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
- REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
-+ REGISTER_HWACCEL (H264_XVBA, h264_xvba);
- REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2);
- REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
- REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);
-+ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba);
- REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2);
- REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi);
-+ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba);
- REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2);
- REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi);
-+ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba);
-
- /* video codecs */
- REGISTER_ENCODER (A64MULTI, a64multi);
-diff --git a/lib/ffmpeg/libavcodec/h264.c b/lib/ffmpeg/libavcodec/h264.c
-index 0e002ce..d054b20 100644
---- a/lib/ffmpeg/libavcodec/h264.c
-+++ b/lib/ffmpeg/libavcodec/h264.c
-@@ -55,6 +55,7 @@ static const uint8_t div6[52]={
- static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = {
- PIX_FMT_DXVA2_VLD,
- PIX_FMT_VAAPI_VLD,
-+ PIX_FMT_XVBA_VLD,
- PIX_FMT_YUVJ420P,
- PIX_FMT_NONE
- };
-diff --git a/lib/ffmpeg/libavcodec/mpegvideo.c b/lib/ffmpeg/libavcodec/mpegvideo.c
-index 31642e6..56113c7 100644
---- a/lib/ffmpeg/libavcodec/mpegvideo.c
-+++ b/lib/ffmpeg/libavcodec/mpegvideo.c
-@@ -117,6 +117,7 @@ const enum PixelFormat ff_pixfmt_list_420[] = {
- const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {
- PIX_FMT_DXVA2_VLD,
- PIX_FMT_VAAPI_VLD,
-+ PIX_FMT_XVBA_VLD,
- PIX_FMT_YUV420P,
- PIX_FMT_NONE
- };
-diff --git a/lib/ffmpeg/libavcodec/xvba.c b/lib/ffmpeg/libavcodec/xvba.c
-new file mode 100644
-index 0000000..48fd905
---- /dev/null
-+++ b/lib/ffmpeg/libavcodec/xvba.c
-@@ -0,0 +1,65 @@
-+/*
-+ * HW decode acceleration for MPEG-2, H.264 and VC-1
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+
-+/**
-+ * \addtogroup XVBA_Decoding
-+ *
-+ * @{
-+ */
-+
-+#include
-+#include "xvba.h"
-+#include "avcodec.h"
-+
-+int ff_xvba_translate_profile(int profile) {
-+
-+ if (profile == 66)
-+ return 1;
-+ else if (profile == 77)
-+ return 2;
-+ else if (profile == 100)
-+ return 3;
-+ else if (profile == 0)
-+ return 4;
-+ else if (profile == 1)
-+ return 5;
-+ else if (profile == 3)
-+ return 6;
-+ else
-+ return -1;
-+}
-+
-+void ff_xvba_add_slice_data(struct xvba_render_state *render, const void *buffer, uint32_t size) {
-+
-+ render->buffers = av_fast_realloc(
-+ render->buffers,
-+ &render->buffers_alllocated,
-+ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1)
-+ );
-+
-+ render->buffers[render->num_slices].buffer = buffer;
-+ render->buffers[render->num_slices].size = size;
-+
-+ render->num_slices++;
-+}
-+
-diff --git a/lib/ffmpeg/libavcodec/xvba.h b/lib/ffmpeg/libavcodec/xvba.h
-new file mode 100644
-index 0000000..a62d649
---- /dev/null
-+++ b/lib/ffmpeg/libavcodec/xvba.h
-@@ -0,0 +1,65 @@
-+/*
-+ * HW decode acceleration for MPEG-2, H.264 and VC-1
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#ifndef AVCODEC_XVBA_H
-+#define AVCODEC_XVBA_H
-+
-+#include
-+#include
-+#include
-+
-+
-+/**
-+ * \defgroup XVBA_Decoding VA API Decoding
-+ * \ingroup Decoder
-+ * @{
-+ */
-+
-+/** \brief The videoSurface is used for rendering. */
-+#define FF_XVBA_STATE_USED_FOR_RENDER 1
-+
-+/**
-+ * \brief The videoSurface is needed for reference/prediction.
-+ * The codec manipulates this.
-+ */
-+#define FF_XVBA_STATE_USED_FOR_REFERENCE 2
-+
-+/* @} */
-+
-+struct xvba_bitstream_buffers
-+{
-+ const void *buffer;
-+ unsigned int size;
-+};
-+
-+struct xvba_render_state {
-+
-+ int state; ///< Holds FF_XVBA_STATE_* values.
-+ void *surface;
-+ XVBAPictureDescriptor *picture_descriptor;
-+ XVBAQuantMatrixAvc *iq_matrix;
-+ unsigned int num_slices;
-+ struct xvba_bitstream_buffers *buffers;
-+ uint32_t buffers_alllocated;
-+};
-+
-+#endif /* AVCODEC_XVBA_H */
-diff --git a/lib/ffmpeg/libavcodec/xvba_h264.c b/lib/ffmpeg/libavcodec/xvba_h264.c
-new file mode 100644
-index 0000000..0d98dea
---- /dev/null
-+++ b/lib/ffmpeg/libavcodec/xvba_h264.c
-@@ -0,0 +1,180 @@
-+/*
-+ * H.264 HW decode acceleration through XVBA
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#include "xvba.h"
-+#include "xvba_internal.h"
-+#include "h264.h"
-+#include
-+
-+/** @file
-+ * This file implements the glue code between FFmpeg's and XvBA API's
-+ * structures for H.264 decoding.
-+ */
-+
-+
-+/** Initialize and start decoding a frame with XVBA. */
-+static int start_frame(AVCodecContext *avctx,
-+ av_unused const uint8_t *buffer,
-+ av_unused uint32_t size)
-+{
-+ H264Context * const h = avctx->priv_data;
-+ MpegEncContext * const s = &h->s;
-+ struct xvba_render_state *render;
-+ XVBAPictureDescriptor *pic_descriptor;
-+ int i;
-+
-+ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
-+ assert(render);
-+
-+ if (render->picture_descriptor == 0)
-+ return -1;
-+
-+ pic_descriptor = render->picture_descriptor;
-+
-+ for (i = 0; i < 2; ++i) {
-+ int foc = s->current_picture_ptr->field_poc[i];
-+ if (foc == INT_MAX)
-+ foc = 0;
-+ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc;
-+ }
-+
-+ pic_descriptor->avc_frame_num = h->frame_num;
-+
-+ render->num_slices = 0;
-+
-+ return 0;
-+}
-+
-+/** End a hardware decoding based frame. */
-+static int end_frame(AVCodecContext *avctx)
-+{
-+ H264Context * const h = avctx->priv_data;
-+ MpegEncContext * const s = &h->s;
-+ struct xvba_render_state *render;
-+ XVBAPictureDescriptor *pic_descriptor;
-+ XVBAQuantMatrixAvc *iq_matrix;
-+
-+ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
-+ assert(render);
-+
-+ if (render->picture_descriptor == 0 || render->iq_matrix == 0)
-+ return -1;
-+
-+ pic_descriptor = render->picture_descriptor;
-+ iq_matrix = render->iq_matrix;
-+
-+ av_dlog(avctx, "end_frame()\n");
-+
-+ /* Fill in Picture Parameters*/
-+ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile);
-+ pic_descriptor->level = avctx->level;
-+ pic_descriptor->width_in_mb = s->mb_width;
-+ pic_descriptor->height_in_mb = s->mb_height;
-+ pic_descriptor->picture_structure = s->picture_structure;
-+ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1;
-+ pic_descriptor->avc_intra_flag = (h->slice_type == FF_I_TYPE) ? 1 : 0;
-+ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0;
-+
-+ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
-+ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8;
-+ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4;
-+ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type;
-+ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
-+ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count;
-+ pic_descriptor->avc_reserved_8bit = 0;
-+
-+ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1;
-+ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
-+ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
-+
-+ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26;
-+ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26;
-+ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
-+ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
-+ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg
-+ pic_descriptor->avc_reserved_16bit = 0; // must be 0
-+ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0
-+ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0
-+
-+ // sps
-+ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
-+ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
-+ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag;
-+ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag;
-+ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff;
-+ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag;
-+ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0;
-+
-+ // pps
-+ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac;
-+ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present;
-+ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred;
-+ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc;
-+ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
-+ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred;
-+ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present;
-+ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode;
-+ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0
-+
-+ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4));
-+ memcpy(iq_matrix->bScalingLists8x8, h->pps.scaling_matrix8, sizeof(iq_matrix->bScalingLists8x8));
-+
-+ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
-+ if (!h->got_first_iframe) {
-+ if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE)
-+ return -1;
-+ h->got_first_iframe = 1;
-+ }
-+
-+ ff_draw_horiz_band(s, 0, s->avctx->height);
-+
-+ return 0;
-+}
-+
-+/** Decode the given H.264 slice with VA API. */
-+static int decode_slice(AVCodecContext *avctx,
-+ const uint8_t *buffer,
-+ uint32_t size)
-+{
-+ H264Context * const h = avctx->priv_data;
-+ MpegEncContext * const s = &h->s;
-+ struct xvba_render_state *render;
-+
-+ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
-+ assert(render);
-+
-+ ff_xvba_add_slice_data(render, buffer, size);
-+
-+ return 0;
-+}
-+
-+AVHWAccel ff_h264_xvba_hwaccel = {
-+ .name = "h264_xvba",
-+ .type = AVMEDIA_TYPE_VIDEO,
-+ .id = CODEC_ID_H264,
-+ .pix_fmt = PIX_FMT_XVBA_VLD,
-+ .capabilities = 0,
-+ .start_frame = start_frame,
-+ .end_frame = end_frame,
-+ .decode_slice = decode_slice,
-+ .priv_data_size = 0,
-+};
-diff --git a/lib/ffmpeg/libavcodec/xvba_internal.h b/lib/ffmpeg/libavcodec/xvba_internal.h
-new file mode 100644
-index 0000000..9653f85
---- /dev/null
-+++ b/lib/ffmpeg/libavcodec/xvba_internal.h
-@@ -0,0 +1,24 @@
-+/*
-+ * HW decode acceleration for MPEG-2, H.264 and VC-1
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+int ff_xvba_translate_profile(int profile);
-+void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size);
-diff --git a/lib/ffmpeg/libavcodec/xvba_mpeg2.c b/lib/ffmpeg/libavcodec/xvba_mpeg2.c
-new file mode 100644
-index 0000000..552ef95
---- /dev/null
-+++ b/lib/ffmpeg/libavcodec/xvba_mpeg2.c
-@@ -0,0 +1,52 @@
-+/*
-+ * MPEG-2 HW decode acceleration through XVBA
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#include "dsputil.h"
-+
-+static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
-+{
-+ struct MpegEncContext * const s = avctx->priv_data;
-+ return 0;
-+}
-+
-+static int end_frame(AVCodecContext *avctx)
-+{
-+ return 0;
-+}
-+
-+static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
-+{
-+ struct MpegEncContext * const s = avctx->priv_data;
-+ return 0;
-+}
-+
-+AVHWAccel ff_mpeg2_xvba_hwaccel = {
-+ .name = "mpeg2_xvba",
-+ .type = AVMEDIA_TYPE_VIDEO,
-+ .id = CODEC_ID_MPEG2VIDEO,
-+ .pix_fmt = PIX_FMT_XVBA_VLD,
-+ .capabilities = 0,
-+ .start_frame = start_frame,
-+ .end_frame = end_frame,
-+ .decode_slice = decode_slice,
-+ .priv_data_size = 0,
-+};
-diff --git a/lib/ffmpeg/libavcodec/xvba_vc1.c b/lib/ffmpeg/libavcodec/xvba_vc1.c
-new file mode 100644
-index 0000000..e7b9211
---- /dev/null
-+++ b/lib/ffmpeg/libavcodec/xvba_vc1.c
-@@ -0,0 +1,194 @@
-+/*
-+ * VC-1 HW decode acceleration through XVBA
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#include "xvba.h"
-+#include "xvba_internal.h"
-+#include "vc1.h"
-+#include "vc1data.h"
-+#include
-+
-+
-+/** @file
-+ * Implement structures of ffmpeg <-> XvBA
-+ */
-+
-+/* Initialize and start decoding a frame with XvBA */
-+static int start_frame(AVCodecContext *avctx,
-+ av_unused const uint8_t *buffer,
-+ av_unused uint32_t size)
-+{
-+ VC1Context * const v = avctx->priv_data;
-+ MpegEncContext * const s = &v->s;
-+ struct xvba_render_state *render;
-+
-+ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
-+ assert(render);
-+
-+ render->num_slices = 0;
-+ return 0;
-+}
-+
-+/* End a hardware decoding based frame */
-+static int end_frame(AVCodecContext *avctx)
-+{
-+ VC1Context* const v = avctx->priv_data;
-+ MpegEncContext* const s = &v->s;
-+ struct xvba_render_state *render, *last, *next;
-+ XVBAPictureDescriptor *pic_descriptor;
-+
-+ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
-+ assert(render);
-+
-+ if (render->picture_descriptor == 0)
-+ return -1;
-+
-+ pic_descriptor = render->picture_descriptor;
-+
-+ av_dlog(avctx, "xvba_vc1_end_frame()\n");
-+
-+ memset(pic_descriptor, 0, sizeof(*pic_descriptor));
-+
-+ /* Fill in Parameters - for reference see AMD sdk documentation */
-+ pic_descriptor->profile = ff_xvba_translate_profile(v->profile);
-+ pic_descriptor->level = v->level;
-+ //done like in va-driver and vaapi
-+ if (v->profile == PROFILE_ADVANCED) {
-+ pic_descriptor->width_in_mb = s->avctx->coded_width;
-+ pic_descriptor->height_in_mb = s->avctx->coded_height;
-+ } else {
-+ pic_descriptor->width_in_mb = s->mb_width;
-+ pic_descriptor->height_in_mb = s->mb_height;
-+ }
-+ pic_descriptor->picture_structure = s->picture_structure;
-+ // xvba-video set this to 1 only 4:2:0 supported
-+ // doc says: if not set, choose 1 - we try this
-+ pic_descriptor->chroma_format = 1;
-+ pic_descriptor->avc_intra_flag = s->pict_type == FF_I_TYPE || v->bi_type == 1;
-+ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0;
-+
-+ // VC-1 explicit parameters see page 30 of sdk
-+ // sps_info
-+ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag;
-+
-+ // done as in vaapi
-+ pic_descriptor->sps_info.vc1.pulldown = v->broadcast;
-+ pic_descriptor->sps_info.vc1.interlace = v->interlace;
-+ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag;
-+ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag;
-+ pic_descriptor->sps_info.vc1.reserved = 1;
-+ // eventually check if this makes sense together with interlace
-+ pic_descriptor->sps_info.vc1.psf = v->psf;
-+ // what about if it is a frame (page 31)
-+ // looked at xvba-driver
-+ pic_descriptor->sps_info.vc1.second_field = !s->first_field;
-+ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0;
-+
-+ // VC-1 explicit parameters see page 30 of sdk
-+ // pps_info
-+ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag;
-+ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag;
-+ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter;
-+ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc;
-+ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv;
-+ pic_descriptor->pps_info.vc1.dquant = v->dquant;
-+ pic_descriptor->pps_info.vc1.vstransform = v->vstransform;
-+ pic_descriptor->pps_info.vc1.overlap = v->overlap;
-+ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode;
-+ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv;
-+ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames;
-+ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered;
-+ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker;
-+ pic_descriptor->pps_info.vc1.multires = v->multires;
-+ pic_descriptor->pps_info.vc1.reserved = 1;
-+ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag;
-+ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy;
-+ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag;
-+ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv;
-+ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0;
-+
-+ pic_descriptor->past_surface = 0;
-+ pic_descriptor->future_surface = 0;
-+ switch (s->pict_type) {
-+ case FF_B_TYPE:
-+ next = (struct xvba_render_state *)s->next_picture.data[0];
-+ assert(next);
-+ if (next)
-+ pic_descriptor->past_surface = next->surface;
-+ // fall-through
-+ case FF_P_TYPE:
-+ last = (struct xvba_render_state *)s->last_picture.data[0];
-+ assert(last);
-+ if (last)
-+ pic_descriptor->future_surface = last->surface;
-+ break;
-+ }
-+
-+ ff_draw_horiz_band(s, 0, s->avctx->height);
-+
-+ return 0;
-+}
-+
-+static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
-+{
-+ VC1Context* const v = avctx->priv_data;
-+ MpegEncContext* const s = &v->s;
-+ struct xvba_render_state *render;
-+
-+ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
-+ assert(render);
-+
-+ if (avctx->codec_id == CODEC_ID_VC1 &&
-+ size >= 4 && IS_MARKER(AV_RB32(buffer))) {
-+ buffer += 4;
-+ size -= 4;
-+ }
-+
-+ ff_xvba_add_slice_data(render, buffer, size);
-+
-+ return 0;
-+}
-+
-+#if CONFIG_WMV3_XVBA_HWACCEL
-+AVHWAccel ff_wmv3_xvba_hwaccel = {
-+ .name = "wmv3_xvba",
-+ .type = AVMEDIA_TYPE_VIDEO,
-+ .id = CODEC_ID_WMV3,
-+ .pix_fmt = PIX_FMT_XVBA_VLD,
-+ .capabilities = 0,
-+ .start_frame = start_frame,
-+ .end_frame = end_frame,
-+ .decode_slice = decode_slice,
-+ .priv_data_size = 0,
-+};
-+#endif
-+
-+AVHWAccel ff_vc1_xvba_hwaccel = {
-+ .name = "vc1_xvba",
-+ .type = AVMEDIA_TYPE_VIDEO,
-+ .id = CODEC_ID_VC1,
-+ .pix_fmt = PIX_FMT_XVBA_VLD,
-+ .capabilities = 0,
-+ .start_frame = start_frame,
-+ .end_frame = end_frame,
-+ .decode_slice = decode_slice,
-+ .priv_data_size = 0,
-+};
-diff --git a/lib/ffmpeg/libavcodec/xvmc_internal.h b/lib/ffmpeg/libavcodec/xvmc_internal.h
-index 9bb8909..a64d6ee 100644
---- a/lib/ffmpeg/libavcodec/xvmc_internal.h
-+++ b/lib/ffmpeg/libavcodec/xvmc_internal.h
-@@ -1,5 +1,7 @@
- /*
-- * XVideo Motion Compensation internal functions
-+ * HW decode acceleration for MPEG-2, H.264 and VC-1
-+ *
-+ * Copyright (C) 2005-2011 Team XBMC
- *
- * This file is part of FFmpeg.
- *
-diff --git a/lib/ffmpeg/libavutil/pixdesc.c b/lib/ffmpeg/libavutil/pixdesc.c
-index 83aa8b0..fcc20d0 100644
---- a/lib/ffmpeg/libavutil/pixdesc.c
-+++ b/lib/ffmpeg/libavutil/pixdesc.c
-@@ -717,6 +717,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = {
- .log2_chroma_h = 1,
- .flags = PIX_FMT_HWACCEL,
- },
-+ [PIX_FMT_XVBA_VLD] = {
-+ .name = "xvba_vld",
-+ .log2_chroma_w = 1,
-+ .log2_chroma_h = 1,
-+ .flags = PIX_FMT_HWACCEL,
-+ },
- [PIX_FMT_YUV420P16LE] = {
- .name = "yuv420p16le",
- .nb_components= 3,
-diff --git a/lib/ffmpeg/libavutil/pixfmt.h b/lib/ffmpeg/libavutil/pixfmt.h
-index 8ec91c8..4803dd7 100644
---- a/lib/ffmpeg/libavutil/pixfmt.h
-+++ b/lib/ffmpeg/libavutil/pixfmt.h
-@@ -127,6 +127,7 @@ enum PixelFormat {
- PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
- PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
- PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
-+ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
-
- PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
- PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
-diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
-index 3dc3d47..7ff943e 100644
-diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp
-index 14c1802..8173e99 100644
---- a/xbmc/ApplicationMessenger.cpp
-+++ b/xbmc/ApplicationMessenger.cpp
-@@ -75,7 +75,7 @@
-
- using namespace std;
-
--CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay)
-+CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("CDelayedMessage")
- {
- m_msg.dwMessage = msg.dwMessage;
- m_msg.dwParam1 = msg.dwParam1;
-diff --git a/xbmc/cdrip/CDDAReader.cpp b/xbmc/cdrip/CDDAReader.cpp
-index 16fa7b6..6c242d8 100644
---- a/xbmc/cdrip/CDDAReader.cpp
-+++ b/xbmc/cdrip/CDDAReader.cpp
-@@ -29,7 +29,7 @@
-
- #define SECTOR_COUNT 52
-
--CCDDAReader::CCDDAReader()
-+CCDDAReader::CCDDAReader() : CThread("CCDDAReader")
- {
- m_sRipBuffer[0].pbtStream = NULL;
- m_sRipBuffer[1].pbtStream = NULL;
-diff --git a/xbmc/cores/DllLoader/exports/emu_kernel32.cpp b/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
-index 13a23e2..493d64d 100644
---- a/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
-+++ b/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
-@@ -240,15 +240,6 @@ extern "C" DWORD WINAPI dllGetCurrentProcessId(void)
- #endif
- }
-
--extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
--{
-- // since the xbox has only one process, we just take the current thread
-- HANDLE h = GetCurrentThread();
-- BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
--
-- return res;
--}
--
- extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
- HANDLE hSourceHandle, // handle to duplicate
- HANDLE hTargetProcessHandle, // handle to target process
-diff --git a/xbmc/cores/DllLoader/exports/emu_kernel32.h b/xbmc/cores/DllLoader/exports/emu_kernel32.h
-index 2e637a7..9cc2f0b 100644
---- a/xbmc/cores/DllLoader/exports/emu_kernel32.h
-+++ b/xbmc/cores/DllLoader/exports/emu_kernel32.h
-@@ -686,7 +686,6 @@ extern "C" BOOL WINAPI dllGetProcessAffinityMask(HANDLE hProcess, LPDWORD lpProc
-
- extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE module, HRSRC res);
- extern "C" HRSRC WINAPI dllFindResourceA(HMODULE module, LPCTSTR name, LPCTSTR type);
--extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
- extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData);
- extern "C" UINT WINAPI dllGetConsoleCP();
- extern "C" UINT WINAPI dllGetConsoleOutputCP();
-diff --git a/xbmc/cores/DummyVideoPlayer.cpp b/xbmc/cores/DummyVideoPlayer.cpp
-index f0b4aeb..47d25e4 100644
---- a/xbmc/cores/DummyVideoPlayer.cpp
-+++ b/xbmc/cores/DummyVideoPlayer.cpp
-@@ -33,7 +33,7 @@
-
- CDummyVideoPlayer::CDummyVideoPlayer(IPlayerCallback& callback)
- : IPlayer(callback),
-- CThread()
-+ CThread("CDummyVideoPlayer")
- {
- m_paused = false;
- m_clock = 0;
-diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
-index 8172750..77e4855 100644
---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
-+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
-@@ -61,6 +61,9 @@
- VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5)))
-
- #endif
-+#ifdef HAVE_LIBXVBA
-+#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h"
-+#endif
-
- #ifdef HAS_GLX
- #include
-@@ -121,6 +124,10 @@ CLinuxRendererGL::YUVBUFFER::YUVBUFFER()
- #ifdef HAVE_LIBVDPAU
- vdpau = NULL;
- #endif
-+#ifdef HAVE_LIBXVBA
-+ xvba = NULL;
-+ xvba_tmp = NULL;
-+#endif
- }
-
- CLinuxRendererGL::YUVBUFFER::~YUVBUFFER()
-@@ -160,6 +167,7 @@ CLinuxRendererGL::CLinuxRendererGL()
- m_rgbPbo = 0;
-
- m_dllSwScale = new DllSwScale;
-+ m_bValidated = false;
- }
-
- CLinuxRendererGL::~CLinuxRendererGL()
-@@ -224,7 +232,7 @@ bool CLinuxRendererGL::ValidateRenderer()
-
- void CLinuxRendererGL::ManageTextures()
- {
-- m_NumYV12Buffers = 2;
-+ m_NumYV12Buffers = 3;
- //m_iYV12RenderBuffer = 0;
- return;
- }
-@@ -241,6 +249,11 @@ bool CLinuxRendererGL::ValidateRenderTarget()
- else
- CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
-
-+ // function pointer for texture might change in
-+ // call to LoadShaders
-+ for (int i = 0 ; i < m_NumYV12Buffers ; i++)
-+ (this->*m_textureDelete)(i);
-+
- // create the yuv textures
- LoadShaders();
-
-@@ -569,6 +582,11 @@ void CLinuxRendererGL::Flush()
- m_bValidated = false;
- }
-
-+unsigned int CLinuxRendererGL::GetProcessorSize()
-+{
-+ return m_NumYV12Buffers;
-+}
-+
- void CLinuxRendererGL::Update(bool bPauseDrawing)
- {
- if (!m_bConfigured) return;
-@@ -730,14 +748,15 @@ unsigned int CLinuxRendererGL::PreInit()
- {
- CSingleLock lock(g_graphicsContext);
- m_bConfigured = false;
-- m_bValidated = false;
-- UnInit();
-+ if (m_bValidated)
-+ UnInit();
-+
- m_resolution = g_guiSettings.m_LookAndFeelResolution;
- if ( m_resolution == RES_WINDOW )
- m_resolution = RES_DESKTOP;
-
- m_iYV12RenderBuffer = 0;
-- m_NumYV12Buffers = 2;
-+ m_NumYV12Buffers = 3;
-
- // setup the background colour
- m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
-@@ -817,7 +836,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
- case VS_SCALINGMETHOD_LINEAR:
- SetTextureFilter(m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR);
- m_renderQuality = RQ_SINGLEPASS;
-- if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) && m_nonLinStretch)
-+ if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch)
- {
- m_pVideoFilterShader = new StretchFilterShader();
- if (!m_pVideoFilterShader->CompileAndLink())
-@@ -898,6 +917,11 @@ void CLinuxRendererGL::LoadShaders(int field)
- CLog::Log(LOGNOTICE, "GL: Using VAAPI render method");
- m_renderMethod = RENDER_VAAPI;
- }
-+ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA)
-+ {
-+ CLog::Log(LOGNOTICE, "GL: Using XVBA render method");
-+ m_renderMethod = RENDER_XVBA;
-+ }
- else
- {
- int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod");
-@@ -1032,6 +1056,18 @@ void CLinuxRendererGL::LoadShaders(int field)
- m_textureCreate = &CLinuxRendererGL::CreateVAAPITexture;
- m_textureDelete = &CLinuxRendererGL::DeleteVAAPITexture;
- }
-+ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA)
-+ {
-+ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture;
-+ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture;
-+ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture;
-+ }
-+ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA_YV12)
-+ {
-+ m_textureUpload = &CLinuxRendererGL::UploadXVBAyv12Texture;
-+ m_textureCreate = &CLinuxRendererGL::CreateXVBAyv12Texture;
-+ m_textureDelete = &CLinuxRendererGL::DeleteXVBAyv12Texture;
-+ }
- else
- {
- // setup default YV12 texture handlers
-@@ -1125,6 +1161,13 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
- RenderVDPAU(renderBuffer, m_currentField);
- }
- #endif
-+#ifdef HAVE_LIBXVBA
-+ else if (m_renderMethod & RENDER_XVBA)
-+ {
-+ UpdateVideoFilter();
-+ RenderXVBA(renderBuffer, m_currentField);
-+ }
-+#endif
- #ifdef HAVE_LIBVA
- else if (m_renderMethod & RENDER_VAAPI)
- {
-@@ -1598,6 +1641,77 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field)
- #endif
- }
-
-+void CLinuxRendererGL::RenderXVBA(int index, int field)
-+{
-+#ifdef HAVE_LIBXVBA
-+ YUVPLANE &plane = m_buffers[index].fields[field][0];
-+
-+ glEnable(m_textureTarget);
-+ glActiveTextureARB(GL_TEXTURE0);
-+ glBindTexture(m_textureTarget, plane.id);
-+
-+ // Try some clamping or wrapping
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-+
-+ if (m_pVideoFilterShader)
-+ {
-+ GLint filter;
-+ if (!m_pVideoFilterShader->GetTextureFilter(filter))
-+ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
-+
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
-+ m_pVideoFilterShader->SetSourceTexture(0);
-+ m_pVideoFilterShader->SetWidth(m_sourceWidth);
-+ m_pVideoFilterShader->SetHeight(m_sourceHeight);
-+
-+ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer
-+ //having non-linear stretch on breaks the alignment
-+ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
-+ m_pVideoFilterShader->SetNonLinStretch(1.0);
-+ else
-+ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio));
-+
-+ m_pVideoFilterShader->Enable();
-+ }
-+ else
-+ {
-+ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
-+ }
-+
-+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-+ VerifyGLState();
-+
-+ glBegin(GL_QUADS);
-+ if (m_textureTarget==GL_TEXTURE_2D)
-+ {
-+ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1);
-+ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1);
-+ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2);
-+ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2);
-+ }
-+ else
-+ {
-+ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f);
-+ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f);
-+ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f);
-+ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f);
-+ }
-+ glEnd();
-+ VerifyGLState();
-+
-+ if (m_pVideoFilterShader)
-+ m_pVideoFilterShader->Disable();
-+
-+ glBindTexture (m_textureTarget, 0);
-+ glDisable(m_textureTarget);
-+#endif
-+}
-+
-+
- void CLinuxRendererGL::RenderSoftware(int index, int field)
- {
- YUVPLANES &planes = m_buffers[index].fields[field];
-@@ -2352,6 +2466,426 @@ void CLinuxRendererGL::UploadVAAPITexture(int index)
- #endif
- }
-
-+void CLinuxRendererGL::DeleteXVBATexture(int index)
-+{
-+#ifdef HAVE_LIBXVBA
-+ YUVPLANE &planeFallback = m_buffers[index].fields[0][1];
-+ YUVFIELDS &fields = m_buffers[index].fields;
-+
-+ if (m_buffers[index].xvba)
-+ m_buffers[index].xvba->FinishGL();
-+
-+ SAFE_RELEASE(m_buffers[index].xvba);
-+ SAFE_RELEASE(m_buffers[index].xvba_tmp);
-+
-+ if(planeFallback.id && glIsTexture(planeFallback.id))
-+ glDeleteTextures(1, &planeFallback.id);
-+ planeFallback.id = 0;
-+ fields[0][0].id = 0;
-+ fields[1][0].id = 0;
-+ fields[2][0].id = 0;
-+#endif
-+}
-+
-+
-+bool CLinuxRendererGL::CreateXVBATexture(int index)
-+{
-+#ifdef HAVE_LIBXVBA
-+ YV12Image &im = m_buffers[index].image;
-+ YUVFIELDS &fields = m_buffers[index].fields;
-+ YUVPLANE &plane = fields[0][0];
-+ YUVPLANE &planeFallback = fields[0][1];
-+
-+ DeleteXVBATexture(index);
-+
-+ memset(&im , 0, sizeof(im));
-+ memset(&fields, 0, sizeof(fields));
-+ im.height = m_sourceHeight;
-+ im.width = m_sourceWidth;
-+
-+ for(int f = 0;fSet();
-+#endif
-+ return true;
-+}
-+
-+void CLinuxRendererGL::UploadXVBATexture(int index)
-+{
-+#ifdef HAVE_LIBXVBA
-+ XVBA::CDecoder *xvba = m_buffers[index].xvba;
-+
-+ if (m_buffers[index].xvba_tmp)
-+ {
-+ SAFE_RELEASE(m_buffers[index].xvba);
-+ xvba = m_buffers[index].xvba = m_buffers[index].xvba_tmp;
-+ m_buffers[index].xvba_tmp = NULL;
-+ }
-+
-+ YUVFIELDS &fields = m_buffers[index].fields;
-+ YUVPLANE &planeFallback = fields[0][1];
-+ YUVPLANE &plane = fields[m_currentField][0];
-+
-+ if (!xvba)
-+ {
-+ fields[0][0].id = planeFallback.id;
-+ fields[1][0].id = planeFallback.id;
-+ fields[2][0].id = planeFallback.id;
-+ m_eventTexturesDone[index]->Set();
-+ return;
-+ }
-+
-+ XVBA_SURFACE_FLAG field;
-+ if (m_currentField == FIELD_TOP)
-+ field = XVBA_TOP_FIELD;
-+ else if (m_currentField == FIELD_BOT)
-+ field = XVBA_BOTTOM_FIELD;
-+ else
-+ field = XVBA_FRAME;
-+
-+ glEnable(m_textureTarget);
-+ if (xvba->UploadTexture(index, field, m_textureTarget) == 1)
-+ plane.id = xvba->GetTexture(index, field);
-+
-+ // crop texture
-+ CRect crop = xvba->GetCropRect();
-+ plane.rect = m_sourceRect;
-+ plane.rect.x1 += crop.x1;
-+ plane.rect.x2 -= m_sourceWidth - crop.x2;
-+ plane.rect.y1 += crop.y1;
-+ plane.rect.y2 -= m_sourceHeight - crop.y2;
-+ plane.rect.y1 /= plane.pixpertex_y;
-+ plane.rect.y2 /= plane.pixpertex_y;
-+ plane.rect.x1 /= plane.pixpertex_x;
-+ plane.rect.x2 /= plane.pixpertex_x;
-+ if (m_textureTarget == GL_TEXTURE_2D)
-+ {
-+ plane.rect.y1 /= plane.texheight;
-+ plane.rect.y2 /= plane.texheight;
-+ plane.rect.x1 /= plane.texwidth;
-+ plane.rect.x2 /= plane.texwidth;
-+ }
-+
-+ glDisable(m_textureTarget);
-+
-+ m_eventTexturesDone[index]->Set();
-+#endif
-+}
-+
-+//********************************************************************************************************
-+// XVBA YV12 Texture creation, deletion, copying + clearing
-+//********************************************************************************************************
-+void CLinuxRendererGL::DeleteXVBAyv12Texture(int index)
-+{
-+#ifdef HAVE_LIBXVBA
-+ YV12Image &im = m_buffers[index].image;
-+ YUVFIELDS &fields = m_buffers[index].fields;
-+ GLuint *pbo = m_buffers[index].pbo;
-+
-+ if (m_buffers[index].xvba)
-+ m_buffers[index].xvba->FinishGL();
-+
-+ SAFE_RELEASE(m_buffers[index].xvba);
-+ SAFE_RELEASE(m_buffers[index].xvba_tmp);
-+
-+ if( fields[FIELD_FULL][0].id == 0 ) return;
-+
-+ /* finish up all textures, and delete them */
-+ g_graphicsContext.BeginPaint(); //FIXME
-+ for(int f = 0;f> im.cshift_x;
-+ im.stride[2] = im.width >> im.cshift_x;
-+
-+ im.planesize[0] = im.stride[0] * im.height;
-+ im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
-+ im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
-+
-+ im.plane[1] = im.plane[2] = 0;
-+ pbo[1] = pbo[2] = 0;
-+
-+ bool pboSetup = false;
-+ if (m_pboUsed)
-+ {
-+ pboSetup = true;
-+
-+ glGenBuffersARB(1, pbo);
-+ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[0]);
-+ glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, im.planesize[0] + im.planesize[0]/2 + PBO_OFFSET, 0, GL_STREAM_DRAW_ARB);
-+ void* pboPtr = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
-+ if (pboPtr)
-+ {
-+ im.plane[0] = (BYTE*) pboPtr + PBO_OFFSET;
-+ memset(im.plane[0], 0, im.planesize[0]);
-+ }
-+ else
-+ {
-+ CLog::Log(LOGWARNING,"GL: failed to set up pixel buffer object");
-+ pboSetup = false;
-+ }
-+
-+ if (!pboSetup)
-+ {
-+ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[0]);
-+ glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
-+ glDeleteBuffersARB(1, pbo);
-+ memset(m_buffers[index].pbo, 0, sizeof(m_buffers[index].pbo));
-+ }
-+
-+ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
-+ }
-+
-+ if (!pboSetup)
-+ {
-+ im.plane[0] = new BYTE[im.planesize[0]+im.planesize[0]/2];
-+ }
-+
-+ glEnable(m_textureTarget);
-+ for(int f = 0;f> fieldshift;
-+
-+ if (m_renderMethod & RENDER_SW)
-+ {
-+ planes[1].texwidth = 0;
-+ planes[1].texheight = 0;
-+ planes[2].texwidth = 0;
-+ planes[2].texheight = 0;
-+ }
-+ else
-+ {
-+ planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
-+ planes[1].texheight = planes[0].texheight >> im.cshift_y;
-+ planes[2].texwidth = planes[0].texwidth >> im.cshift_x;
-+ planes[2].texheight = planes[0].texheight >> im.cshift_y;
-+ }
-+
-+ for (int p = 0; p < 3; p++)
-+ {
-+ planes[p].pixpertex_x = 1;
-+ planes[p].pixpertex_y = 1;
-+ }
-+
-+ if(m_renderMethod & RENDER_POT)
-+ {
-+ for(int p = 0; p < 3; p++)
-+ {
-+ planes[p].texwidth = NP2(planes[p].texwidth);
-+ planes[p].texheight = NP2(planes[p].texheight);
-+ }
-+ }
-+
-+ for(int p = 0; p < 3; p++)
-+ {
-+ YUVPLANE &plane = planes[p];
-+ if (plane.texwidth * plane.texheight == 0)
-+ continue;
-+
-+ glBindTexture(m_textureTarget, plane.id);
-+ if (m_renderMethod & RENDER_SW)
-+ {
-+ glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
-+ }
-+ else
-+ {
-+ GLint format;
-+ if (p == 2) //V plane needs an alpha texture
-+ format = GL_ALPHA;
-+ else
-+ format = GL_LUMINANCE;
-+
-+ glTexImage2D(m_textureTarget, 0, format, plane.texwidth, plane.texheight, 0, format, GL_UNSIGNED_BYTE, NULL);
-+ }
-+
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-+ VerifyGLState();
-+ }
-+ }
-+ glDisable(m_textureTarget);
-+ m_eventTexturesDone[index]->Set();
-+#endif
-+ return true;
-+}
-+
-+void CLinuxRendererGL::UploadXVBAyv12Texture(int source)
-+{
-+#ifdef HAVE_LIBXVBA
-+ YUVBUFFER& buf = m_buffers[source];
-+ YV12Image* im = &buf.image;
-+ YUVFIELDS& fields = buf.fields;
-+ XVBA::CDecoder *xvba = m_buffers[source].xvba;
-+
-+ if (m_buffers[source].xvba_tmp)
-+ {
-+ SAFE_RELEASE(m_buffers[source].xvba);
-+ xvba = m_buffers[source].xvba = m_buffers[source].xvba_tmp;
-+ m_buffers[source].xvba_tmp = NULL;
-+ }
-+
-+ if (!(im->flags&IMAGE_FLAG_READY) || !xvba)
-+ {
-+ m_eventTexturesDone[source]->Set();
-+ return;
-+ }
-+
-+ bool deinterlacing;
-+ if (m_currentField == FIELD_FULL)
-+ deinterlacing = false;
-+ else
-+ deinterlacing = true;
-+
-+ glEnable(m_textureTarget);
-+ VerifyGLState();
-+
-+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
-+
-+ if (deinterlacing)
-+ {
-+ // Load Even Y Field
-+ LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
-+ , im->width, im->height >> 1
-+ , im->stride[0]*2, im->plane[0] );
-+
-+ //load Odd Y Field
-+ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
-+ , im->width, im->height >> 1
-+ , im->stride[0]*2, im->plane[0] + im->stride[0], &buf.pbo[0] ) ;
-+
-+ // Load Even U & V Fields
-+ LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
-+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
-+ , im->stride[1]*2, im->plane[0] + im->planesize[0] + im->planesize[1], &buf.pbo[0] );
-+
-+ LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex
-+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
-+ , im->stride[2]*2, im->plane[0] + im->planesize[0], &buf.pbo[0] );
-+
-+ // Load Odd U & V Fields
-+ LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
-+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
-+ , im->stride[1]*2, im->plane[0] + im->stride[1] + im->planesize[0] + im->planesize[1], &buf.pbo[0] );
-+
-+ LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex
-+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
-+ , im->stride[2]*2, im->plane[0] + im->stride[2] + im->planesize[0], &buf.pbo[0] );
-+ }
-+ else
-+ {
-+ //Load Y plane
-+ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
-+ , im->width, im->height
-+ , im->stride[0], im->plane[0], &buf.pbo[0] );
-+
-+ //load U plane
-+ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
-+ , im->width >> im->cshift_x, im->height >> im->cshift_y
-+ , im->stride[1], im->plane[0] + im->planesize[0] + im->planesize[1] , &buf.pbo[0] );
-+
-+ //load V plane
-+ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex
-+ , im->width >> im->cshift_x, im->height >> im->cshift_y
-+ , im->stride[2], im->plane[0] + im->planesize[0], &buf.pbo[0] );
-+ }
-+
-+ m_eventTexturesDone[source]->Set();
-+
-+ VerifyGLState();
-+
-+ // crop texture
-+ CRect crop = xvba->GetCropRect();
-+ m_sourceRect.x1 += crop.x1;
-+ m_sourceRect.x2 -= m_sourceWidth - crop.x2;
-+ m_sourceRect.y1 += crop.y1;
-+ m_sourceRect.y2 -= m_sourceHeight - crop.y2;
-+ CalculateTextureSourceRects(source, 3);
-+
-+ glDisable(m_textureTarget);
-+#endif
-+}
-+
- void CLinuxRendererGL::UploadYUV422PackedTexture(int source)
- {
- YUVBUFFER& buf = m_buffers[source];
-@@ -2935,6 +3469,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
- if (m_renderMethod & RENDER_VAAPI)
- return false;
-
-+ if (m_renderMethod & RENDER_XVBA)
-+ return false;
-+
- return (m_renderMethod & RENDER_GLSL)
- || (m_renderMethod & RENDER_ARB)
- || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
-@@ -2948,6 +3485,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
- if (m_renderMethod & RENDER_VAAPI)
- return false;
-
-+ if (m_renderMethod & RENDER_XVBA)
-+ return false;
-+
- return (m_renderMethod & RENDER_GLSL)
- || (m_renderMethod & RENDER_ARB)
- || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
-@@ -2971,7 +3511,8 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature)
- if (feature == RENDERFEATURE_NONLINSTRETCH)
- {
- if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) ||
-- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
-+ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) ||
-+ (m_renderMethod & RENDER_XVBA))
- return true;
- }
-
-@@ -3034,10 +3575,22 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method)
- return false;
- #endif
-
-- if(method == VS_INTERLACEMETHOD_DEINTERLACE
-- || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
-- || method == VS_INTERLACEMETHOD_SW_BLEND)
-- return true;
-+ if (CONF_FLAGS_FORMAT_MASK(m_iFlags) != CONF_FLAGS_FORMAT_XVBA)
-+ {
-+ if(method == VS_INTERLACEMETHOD_DEINTERLACE
-+ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
-+ || method == VS_INTERLACEMETHOD_SW_BLEND)
-+ return true;
-+ }
-+
-+ if(m_renderMethod & RENDER_XVBA)
-+ {
-+ if (method == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED
-+ || method == VS_INTERLACEMETHOD_RENDER_BOB)
-+ return true;
-+ else
-+ return false;
-+ }
-
- if((method == VS_INTERLACEMETHOD_RENDER_BLEND
- || method == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED
-@@ -3069,7 +3622,7 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method)
- || method == VS_SCALINGMETHOD_LANCZOS3)
- {
- if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) ||
-- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
-+ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA))
- {
- // spline36 and lanczos3 are only allowed through advancedsettings.xml
- if(method != VS_SCALINGMETHOD_SPLINE36
-@@ -3128,7 +3681,7 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff)
- pbo = true;
-
- glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.pbo[plane]);
-- glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.image.planesize[plane] + PBO_OFFSET, NULL, GL_STREAM_DRAW_ARB);
-+ glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.image.planesize[plane] + buff.image.planesize[plane]/2 + PBO_OFFSET, NULL, GL_STREAM_DRAW_ARB);
- buff.image.plane[plane] = (BYTE*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB) + PBO_OFFSET;
- }
- if(pbo)
-@@ -3152,4 +3705,13 @@ void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder)
- }
- #endif
-
-+#ifdef HAVE_LIBXVBA
-+void CLinuxRendererGL::AddProcessor(XVBA::CDecoder* xvba)
-+{
-+ YUVBUFFER &buf = m_buffers[NextYV12Texture()];
-+ SAFE_RELEASE(buf.xvba_tmp);
-+ buf.xvba_tmp = (XVBA::CDecoder*)xvba->Acquire();
-+}
-+#endif
-+
- #endif
-diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
-index 38c84aa..ae0b81b 100644
---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h
-+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h
-@@ -40,6 +40,7 @@ class CBaseTexture;
- namespace Shaders { class BaseYUV2RGBShader; }
- namespace Shaders { class BaseVideoFilterShader; }
- namespace VAAPI { struct CHolder; }
-+namespace XVBA { class CDecoder; }
-
- #define NUM_BUFFERS 3
-
-@@ -94,6 +95,7 @@ enum RenderMethod
- RENDER_VDPAU=0x08,
- RENDER_POT=0x10,
- RENDER_VAAPI=0x20,
-+ RENDER_XVBA=0x40,
- };
-
- enum RenderQuality
-@@ -141,6 +143,7 @@ public:
- virtual void UnInit();
- virtual void Reset(); /* resets renderer after seek for example */
- virtual void Flush();
-+ virtual unsigned int GetProcessorSize();
-
- #ifdef HAVE_LIBVDPAU
- virtual void AddProcessor(CVDPAU* vdpau);
-@@ -148,6 +151,9 @@ public:
- #ifdef HAVE_LIBVA
- virtual void AddProcessor(VAAPI::CHolder& holder);
- #endif
-+#ifdef HAVE_LIBXVBA
-+ virtual void AddProcessor(XVBA::CDecoder* xvba);
-+#endif
-
- virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255);
-
-@@ -194,6 +200,14 @@ protected:
- void DeleteVAAPITexture(int index);
- bool CreateVAAPITexture(int index);
-
-+ void UploadXVBATexture(int index);
-+ void DeleteXVBATexture(int index);
-+ bool CreateXVBATexture(int index);
-+
-+ void UploadXVBAyv12Texture(int index);
-+ void DeleteXVBAyv12Texture(int index);
-+ bool CreateXVBAyv12Texture(int index);
-+
- void UploadYUV422PackedTexture(int index);
- void DeleteYUV422PackedTexture(int index);
- bool CreateYUV422PackedTexture(int index);
-@@ -211,6 +225,7 @@ protected:
- void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
- void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
- void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
-+ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware
-
- CFrameBufferObject m_fbo;
-
-@@ -270,6 +285,10 @@ protected:
- #ifdef HAVE_LIBVA
- VAAPI::CHolder& vaapi;
- #endif
-+#ifdef HAVE_LIBXVBA
-+ XVBA::CDecoder* xvba;
-+ XVBA::CDecoder* xvba_tmp;
-+#endif
- };
-
- typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS];
-diff --git a/xbmc/cores/VideoRenderers/RenderFlags.h b/xbmc/cores/VideoRenderers/RenderFlags.h
-index f663380..cbe82c5 100644
---- a/xbmc/cores/VideoRenderers/RenderFlags.h
-+++ b/xbmc/cores/VideoRenderers/RenderFlags.h
-@@ -79,5 +79,7 @@
- #define CONF_FLAGS_FORMAT_VAAPI 0x030000
- #define CONF_FLAGS_FORMAT_OMXEGL 0x040000
- #define CONF_FLAGS_FORMAT_CVBREF 0x080000
-+#define CONF_FLAGS_FORMAT_XVBA 0x011000
-+#define CONF_FLAGS_FORMAT_XVBA_YV12 0x012000
- #define CONF_FLAGS_FORMAT_BYPASS 0x100000
- #endif
-diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
-index b917860..10d116d 100644
---- a/xbmc/cores/VideoRenderers/RenderManager.cpp
-+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
-@@ -53,6 +53,10 @@
- #include "../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h"
- #include "../dvdplayer/DVDCodecs/DVDCodecUtils.h"
-
-+#ifdef HAVE_LIBXVBA
-+ #include "../dvdplayer/DVDCodecs/Video/XVBA.h"
-+#endif
-+
- #define MAXPRESENTDELAY 0.500
-
- /* at any point we want an exclusive lock on rendermanager */
-@@ -791,6 +795,25 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
- else if(pic.format == DVDVideoPicture::FMT_VAAPI)
- m_pRenderer->AddProcessor(*pic.vaapi);
- #endif
-+#ifdef HAVE_LIBXVBA
-+ else if(pic.format == DVDVideoPicture::FMT_XVBA)
-+ {
-+ if (pic.xvba)
-+ {
-+ m_pRenderer->AddProcessor(pic.xvba);
-+ pic.xvba->Present(index);
-+ }
-+ }
-+ else if(pic.format == DVDVideoPicture::FMT_XVBA_YV12)
-+ {
-+ if (pic.xvba)
-+ {
-+ m_pRenderer->AddProcessor(pic.xvba);
-+ pic.xvba->Present(index);
-+ pic.xvba->CopyYV12(index, image.plane[0]);
-+ }
-+ }
-+#endif
- m_pRenderer->ReleaseImage(index, false);
-
- return index;
-diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
-index fa9f68a..68f4008 100644
---- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
-+++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
-@@ -186,6 +186,8 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, bool str
- m_defines += "#define XBMC_YUY2\n";
- else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_UYVY)
- m_defines += "#define XBMC_UYVY\n";
-+ if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_XVBA_YV12)
-+ m_defines += "#define XBMC_YV12\n";
-
- VertexShader()->LoadSource("yuv2rgb_vertex.glsl", m_defines);
- #elif HAS_GLES == 2
-diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
-index ae107a6..1b8cd96 100644
---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
-+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
-@@ -323,7 +323,7 @@ CPictureBuffer::~CPictureBuffer()
- #pragma mark -
- #endif
- CMPCOutputThread::CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015) :
-- CThread(),
-+ CThread("CMPCOutputThread"),
- m_dll(dll),
- m_device(device),
- m_has_bcm70015(has_bcm70015),
-diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
-index e4bd9c9..edc2fe1 100644
---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
-+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
-@@ -34,6 +34,7 @@
-
- namespace DXVA { class CSurfaceContext; }
- namespace VAAPI { struct CHolder; }
-+namespace XVBA { class CDecoder; }
- class CVDPAU;
- class COpenMax;
- class COpenMaxVideo;
-@@ -64,6 +65,9 @@ struct DVDVideoPicture
- struct {
- VAAPI::CHolder* vaapi;
- };
-+ struct {
-+ XVBA::CDecoder* xvba;
-+ };
-
- struct {
- COpenMax *openMax;
-@@ -109,6 +113,8 @@ struct DVDVideoPicture
- FMT_VAAPI,
- FMT_OMXEGL,
- FMT_CVBREF,
-+ FMT_XVBA,
-+ FMT_XVBA_YV12,
- } format;
- };
-
-diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
-index b4e1451..374907f 100644
---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
-+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
-@@ -56,6 +56,9 @@
- #ifdef HAVE_LIBVA
- #include "VAAPI.h"
- #endif
-+#ifdef HAVE_LIBXVBA
-+#include "XVBA.h"
-+#endif
-
- using namespace boost;
-
-@@ -100,6 +103,22 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
- dec->Release();
- }
- #endif
-+#ifdef HAVE_LIBXVBA
-+ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba"))
-+ {
-+ if(ctx->GetHardware())
-+ return *cur;
-+
-+ XVBA::CDecoder* dec = new XVBA::CDecoder();
-+ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount))
-+ {
-+ ctx->SetHardware(dec);
-+ return *cur;
-+ }
-+ else
-+ dec->Release();
-+ }
-+#endif
- #ifdef HAVE_LIBVA
- // mpeg4 vaapi decoding is disabled
- if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi")
-diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
-index 1dce256..8b7d5fb 100644
---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
-+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
-@@ -17,6 +17,10 @@ SRCS+= CrystalHD.cpp \
- DVDVideoCodecCrystalHD.cpp \
-
- endif
-+ifeq (@USE_XVBA@,1)
-+SRCS+= XVBA.cpp \
-+
-+endif
- ifeq (@USE_VDA@,1)
- SRCS+= DVDVideoCodecVDA.cpp \
-
-diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
-new file mode 100644
-index 0000000..1f4c4c8
---- /dev/null
-+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
-@@ -0,0 +1,1419 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+#include "system.h"
-+#ifdef HAVE_LIBXVBA
-+#include
-+#include
-+#include "XVBA.h"
-+#include "windowing/WindowingFactory.h"
-+#include "guilib/GraphicContext.h"
-+#include "settings/GUISettings.h"
-+#include "utils/TimeUtils.h"
-+
-+using namespace XVBA;
-+
-+// XVBA interface
-+
-+#define XVBA_LIBRARY "libXvBAW.so.1"
-+
-+typedef Bool (*XVBAQueryExtensionProc) (Display *dpy, int *vers);
-+typedef Status (*XVBACreateContextProc) (void *input, void *output);
-+typedef Status (*XVBADestroyContextProc) (void *context);
-+typedef Bool (*XVBAGetSessionInfoProc) (void *input, void *output);
-+typedef Status (*XVBACreateSurfaceProc) (void *input, void *output);
-+typedef Status (*XVBACreateGLSharedSurfaceProc)(void *input, void *output);
-+typedef Status (*XVBADestroySurfaceProc) (void *surface);
-+typedef Status (*XVBACreateDecodeBuffersProc) (void *input, void *output);
-+typedef Status (*XVBADestroyDecodeBuffersProc) (void *input);
-+typedef Status (*XVBAGetCapDecodeProc) (void *input, void *output);
-+typedef Status (*XVBACreateDecodeProc) (void *input, void *output);
-+typedef Status (*XVBADestroyDecodeProc) (void *session);
-+typedef Status (*XVBAStartDecodePictureProc) (void *input);
-+typedef Status (*XVBADecodePictureProc) (void *input);
-+typedef Status (*XVBAEndDecodePictureProc) (void *input);
-+typedef Status (*XVBASyncSurfaceProc) (void *input, void *output);
-+typedef Status (*XVBAGetSurfaceProc) (void *input);
-+typedef Status (*XVBATransferSurfaceProc) (void *input);
-+
-+static struct
-+{
-+ XVBAQueryExtensionProc QueryExtension;
-+ XVBACreateContextProc CreateContext;
-+ XVBADestroyContextProc DestroyContext;
-+ XVBAGetSessionInfoProc GetSessionInfo;
-+ XVBACreateSurfaceProc CreateSurface;
-+ XVBACreateGLSharedSurfaceProc CreateGLSharedSurface;
-+ XVBADestroySurfaceProc DestroySurface;
-+ XVBACreateDecodeBuffersProc CreateDecodeBuffers;
-+ XVBADestroyDecodeBuffersProc DestroyDecodeBuffers;
-+ XVBAGetCapDecodeProc GetCapDecode;
-+ XVBACreateDecodeProc CreateDecode;
-+ XVBADestroyDecodeProc DestroyDecode;
-+ XVBAStartDecodePictureProc StartDecodePicture;
-+ XVBADecodePictureProc DecodePicture;
-+ XVBAEndDecodePictureProc EndDecodePicture;
-+ XVBASyncSurfaceProc SyncSurface;
-+ XVBAGetSurfaceProc GetSurface;
-+ XVBATransferSurfaceProc TransferSurface;
-+}g_XVBA_vtable;
-+
-+//-----------------------------------------------------------------------------
-+//-----------------------------------------------------------------------------
-+
-+CXVBAContext *CXVBAContext::m_context = 0;
-+CCriticalSection CXVBAContext::m_section;
-+Display *CXVBAContext::m_display = 0;
-+void *CXVBAContext::m_dlHandle = 0;
-+
-+CXVBAContext::CXVBAContext()
-+{
-+ m_context = 0;
-+// m_dlHandle = 0;
-+ m_xvbaContext = 0;
-+ m_refCount = 0;
-+}
-+
-+void CXVBAContext::Release()
-+{
-+ CSingleLock lock(m_section);
-+
-+ m_refCount--;
-+ if (m_refCount <= 0)
-+ {
-+ Close();
-+ delete this;
-+ m_context = 0;
-+ }
-+}
-+
-+void CXVBAContext::Close()
-+{
-+ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder context");
-+
-+ DestroyContext();
-+// if (m_dlHandle)
-+// {
-+// dlclose(m_dlHandle);
-+// m_dlHandle = 0;
-+// }
-+}
-+
-+bool CXVBAContext::EnsureContext(CXVBAContext **ctx)
-+{
-+ CSingleLock lock(m_section);
-+
-+ if (m_context)
-+ {
-+ m_context->m_refCount++;
-+ *ctx = m_context;
-+ return true;
-+ }
-+
-+ m_context = new CXVBAContext();
-+ *ctx = m_context;
-+ {
-+ CSingleLock gLock(g_graphicsContext);
-+ if (!m_context->LoadSymbols() || !m_context->CreateContext())
-+ {
-+ delete m_context;
-+ m_context = 0;
-+ return false;
-+ }
-+ }
-+
-+ m_context->m_refCount++;
-+
-+ *ctx = m_context;
-+ return true;
-+}
-+
-+bool CXVBAContext::LoadSymbols()
-+{
-+ if (!m_dlHandle)
-+ {
-+ m_dlHandle = dlopen(XVBA_LIBRARY, RTLD_LAZY);
-+ if (!m_dlHandle)
-+ {
-+ const char* error = dlerror();
-+ if (!error)
-+ error = "dlerror() returned NULL";
-+
-+ CLog::Log(LOGERROR,"XVBA::LoadSymbols: Unable to get handle to lib: %s", error);
-+ return false;
-+ }
-+ }
-+ else
-+ return true;
-+
-+#define INIT_PROC(PREFIX, PROC) do { \
-+ g_##PREFIX##_vtable.PROC = (PREFIX##PROC##Proc) \
-+ dlsym(m_dlHandle, #PREFIX #PROC); \
-+ } while (0)
-+
-+#define INIT_PROC_CHECK(PREFIX, PROC) do { \
-+ dlerror(); \
-+ INIT_PROC(PREFIX, PROC); \
-+ if (dlerror()) { \
-+ dlclose(m_dlHandle); \
-+ m_dlHandle = NULL; \
-+ return false; \
-+ } \
-+ } while (0)
-+
-+#define XVBA_INIT_PROC(PROC) INIT_PROC_CHECK(XVBA, PROC)
-+
-+ XVBA_INIT_PROC(QueryExtension);
-+ XVBA_INIT_PROC(CreateContext);
-+ XVBA_INIT_PROC(DestroyContext);
-+ XVBA_INIT_PROC(GetSessionInfo);
-+ XVBA_INIT_PROC(CreateSurface);
-+ XVBA_INIT_PROC(CreateGLSharedSurface);
-+ XVBA_INIT_PROC(DestroySurface);
-+ XVBA_INIT_PROC(CreateDecodeBuffers);
-+ XVBA_INIT_PROC(DestroyDecodeBuffers);
-+ XVBA_INIT_PROC(GetCapDecode);
-+ XVBA_INIT_PROC(CreateDecode);
-+ XVBA_INIT_PROC(DestroyDecode);
-+ XVBA_INIT_PROC(StartDecodePicture);
-+ XVBA_INIT_PROC(DecodePicture);
-+ XVBA_INIT_PROC(EndDecodePicture);
-+ XVBA_INIT_PROC(SyncSurface);
-+ XVBA_INIT_PROC(GetSurface);
-+ XVBA_INIT_PROC(TransferSurface);
-+
-+#undef XVBA_INIT_PROC
-+#undef INIT_PROC
-+
-+ return true;
-+}
-+
-+bool CXVBAContext::CreateContext()
-+{
-+ if (m_xvbaContext)
-+ return true;
-+
-+ CLog::Log(LOGNOTICE,"XVBA::CreateContext - creating decoder context");
-+
-+ Drawable window;
-+ { CSingleLock lock(g_graphicsContext);
-+ if (!m_display)
-+ m_display = XOpenDisplay(NULL);
-+ window = 0;
-+ }
-+
-+ int version;
-+ if (!g_XVBA_vtable.QueryExtension(m_display, &version))
-+ return false;
-+ CLog::Log(LOGNOTICE,"XVBA::CreateContext - opening xvba version: %i", version);
-+
-+ // create XVBA Context
-+ XVBA_Create_Context_Input contextInput;
-+ XVBA_Create_Context_Output contextOutput;
-+ contextInput.size = sizeof(contextInput);
-+ contextInput.display = m_display;
-+ contextInput.draw = window;
-+ contextOutput.size = sizeof(contextOutput);
-+ if(Success != g_XVBA_vtable.CreateContext(&contextInput, &contextOutput))
-+ {
-+ CLog::Log(LOGERROR,"XVBA::CreateContext - failed to create context");
-+ return false;
-+ }
-+ m_xvbaContext = contextOutput.context;
-+
-+ return true;
-+}
-+
-+void CXVBAContext::DestroyContext()
-+{
-+ if (!m_xvbaContext)
-+ return;
-+
-+ g_XVBA_vtable.DestroyContext(m_xvbaContext);
-+ m_xvbaContext = 0;
-+// XCloseDisplay(m_display);
-+}
-+
-+void *CXVBAContext::GetContext()
-+{
-+ return m_xvbaContext;
-+}
-+
-+//-----------------------------------------------------------------------------
-+//-----------------------------------------------------------------------------
-+
-+static unsigned int decoderId = 0;
-+
-+CDecoder::CDecoder()
-+{
-+ m_context = 0;
-+ m_xvbaSession = 0;
-+ m_flipBuffer = 0;
-+}
-+
-+CDecoder::~CDecoder()
-+{
-+ Close();
-+}
-+
-+typedef struct {
-+ unsigned int size;
-+ unsigned int num_of_decodecaps;
-+ XVBADecodeCap decode_caps_list[];
-+} XVBA_GetCapDecode_Output_Base;
-+
-+void CDecoder::OnLostDevice()
-+{
-+ CLog::Log(LOGNOTICE,"XVBA::OnLostDevice event");
-+
-+ CExclusiveLock lock(m_decoderSection);
-+ DestroySession();
-+ if (m_context)
-+ m_context->Release();
-+ m_context = 0;
-+
-+ m_displayState = XVBA_LOST;
-+ m_displayEvent.Reset();
-+}
-+
-+void CDecoder::OnResetDevice()
-+{
-+ CLog::Log(LOGNOTICE,"XVBA::OnResetDevice event");
-+
-+ CExclusiveLock lock(m_displaySection);
-+ if (m_displayState == XVBA_LOST)
-+ {
-+ m_displayState = XVBA_RESET;
-+ m_displayEvent.Set();
-+ }
-+}
-+
-+bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces)
-+{
-+ std::string Vendor = g_Windowing.GetRenderVendor();
-+ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
-+ if (Vendor.compare(0, 3, "ati") != 0)
-+ {
-+ return false;
-+ }
-+
-+ m_decoderId = decoderId++;
-+
-+ CLog::Log(LOGNOTICE,"(XVBA::Open) opening xvba decoder, id: %d", m_decoderId);
-+
-+ if(avctx->coded_width == 0
-+ || avctx->coded_height == 0)
-+ {
-+ CLog::Log(LOGWARNING,"(XVBA) no width/height available, can't init");
-+ return false;
-+ }
-+
-+ if (!m_dllAvUtil.Load())
-+ return false;
-+
-+ if (!CXVBAContext::EnsureContext(&m_context))
-+ return false;
-+
-+ // xvba get session info
-+ XVBA_GetSessionInfo_Input sessionInput;
-+ XVBA_GetSessionInfo_Output sessionOutput;
-+ sessionInput.size = sizeof(sessionInput);
-+ sessionInput.context = m_context->GetContext();
-+ sessionOutput.size = sizeof(sessionOutput);
-+ if (Success != g_XVBA_vtable.GetSessionInfo(&sessionInput, &sessionOutput))
-+ {
-+ CLog::Log(LOGERROR,"(XVBA) can't get session info");
-+ return false;
-+ }
-+ if (sessionOutput.getcapdecode_output_size == 0)
-+ {
-+ CLog::Log(LOGERROR,"(XVBA) session decode not supported");
-+ return false;
-+ }
-+
-+ // get decoder capabilities
-+ XVBA_GetCapDecode_Input capInput;
-+ XVBA_GetCapDecode_Output *capOutput;
-+ capInput.size = sizeof(capInput);
-+ capInput.context = m_context->GetContext();
-+ capOutput = (XVBA_GetCapDecode_Output *)calloc(sessionOutput.getcapdecode_output_size, 1);
-+ capOutput->size = sessionOutput.getcapdecode_output_size;
-+ if (Success != g_XVBA_vtable.GetCapDecode(&capInput, capOutput))
-+ {
-+ CLog::Log(LOGERROR,"(XVBA) can't get decode capabilities");
-+ return false;
-+ }
-+
-+ int match = -1;
-+ if (avctx->codec_id == CODEC_ID_H264)
-+ {
-+ // search for profile high
-+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
-+ {
-+ if (capOutput->decode_caps_list[i].capability_id == XVBA_H264 &&
-+ capOutput->decode_caps_list[i].flags == XVBA_H264_HIGH)
-+ {
-+ match = (int) i;
-+ break;
-+ }
-+ }
-+ if (match < 0)
-+ {
-+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_H264_HIGH not found");
-+ }
-+ }
-+ else if (avctx->codec_id == CODEC_ID_VC1)
-+ {
-+ // search for profile advanced
-+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
-+ {
-+ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
-+ capOutput->decode_caps_list[i].flags == XVBA_VC1_ADVANCED)
-+ {
-+ match = (int) i;
-+ break;
-+ }
-+ }
-+ if (match < 0)
-+ {
-+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_ADVANCED not found");
-+ }
-+ }
-+ else if (avctx->codec_id == CODEC_ID_MPEG2VIDEO)
-+ {
-+ // search for profile high
-+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
-+ {
-+ if (capOutput->decode_caps_list[i].capability_id == XVBA_MPEG2_VLD)
-+ {
-+ // XXX: uncomment when implemented
-+ // match = (int) i;
-+ // break;
-+ }
-+ }
-+ if (match < 0)
-+ {
-+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_MPEG2_VLD not found");
-+ }
-+ }
-+ else if (avctx->codec_id == CODEC_ID_WMV3)
-+ {
-+ // search for profile high
-+ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
-+ {
-+ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
-+ capOutput->decode_caps_list[i].flags == XVBA_VC1_MAIN)
-+ {
-+ match = (int) i;
-+ break;
-+ }
-+ }
-+ if (match < 0)
-+ {
-+ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_MAIN not found");
-+ }
-+ }
-+
-+ if (match < 0)
-+ {
-+ free(capOutput);
-+ return false;
-+ }
-+
-+ CLog::Log(LOGNOTICE,"(XVBA) using decoder capability id: %i flags: %i",
-+ capOutput->decode_caps_list[match].capability_id,
-+ capOutput->decode_caps_list[match].flags);
-+ CLog::Log(LOGNOTICE,"(XVBA) using surface type: %x",
-+ capOutput->decode_caps_list[match].surface_type);
-+
-+ m_decoderCap = capOutput->decode_caps_list[match];
-+
-+ free(capOutput);
-+
-+ // set some varables
-+ m_xvbaSession = 0;
-+ m_xvbaBufferPool.data_buffer = 0;
-+ m_xvbaBufferPool.iq_matrix_buffer = 0;
-+ m_xvbaBufferPool.picture_descriptor_buffer = 0;
-+ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
-+ m_surfaceWidth = 0;
-+ m_surfaceHeight = 0;
-+ m_presentPicture = 0;
-+ m_numRenderBuffers = surfaces;
-+ m_flipBuffer = new RenderPicture[m_numRenderBuffers];
-+ for (unsigned int i = 0; i < m_numRenderBuffers; ++i)
-+ {
-+ m_flipBuffer[i].outPic = 0;
-+ m_flipBuffer[i].glSurface[0] =
-+ m_flipBuffer[i].glSurface[1] =
-+ m_flipBuffer[i].glSurface[2] = 0;
-+ m_flipBuffer[i].glTexture[0] =
-+ m_flipBuffer[i].glTexture[1] =
-+ m_flipBuffer[i].glTexture[2] = 0;
-+ }
-+ for (unsigned int j = 0; j < NUM_OUTPUT_PICS; ++j)
-+ m_freeOutPic.push_back(&m_allOutPic[j]);
-+ m_displayState = XVBA_OPEN;
-+
-+ // setup ffmpeg
-+ avctx->thread_count = 1;
-+ avctx->get_buffer = CDecoder::FFGetBuffer;
-+ avctx->release_buffer = CDecoder::FFReleaseBuffer;
-+ avctx->draw_horiz_band = CDecoder::FFDrawSlice;
-+ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
-+
-+ g_Windowing.Register(this);
-+ return true;
-+}
-+
-+void CDecoder::Close()
-+{
-+ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder, id: %d", m_decoderId);
-+
-+ if (!m_context)
-+ return;
-+
-+ FinishGL();
-+
-+ DestroySession();
-+ if (m_context)
-+ m_context->Release();
-+ m_context = 0;
-+
-+ while (!m_videoSurfaces.empty())
-+ {
-+ xvba_render_state *render = m_videoSurfaces.back();
-+ if(render->buffers_alllocated > 0)
-+ m_dllAvUtil.av_free(render->buffers);
-+ m_videoSurfaces.pop_back();
-+ free(render);
-+ }
-+
-+ if (m_flipBuffer)
-+ delete [] m_flipBuffer;
-+
-+ g_Windowing.Unregister(this);
-+ m_dllAvUtil.Unload();
-+}
-+
-+void CDecoder::ResetState()
-+{
-+ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
-+ m_presentPicture = 0;
-+ m_freeOutPic.clear();
-+ m_usedOutPic.clear();
-+ for (int j = 0; j < NUM_OUTPUT_PICS; ++j)
-+ m_freeOutPic.push_back(&m_allOutPic[j]);
-+ m_displayState = XVBA_OPEN;
-+}
-+
-+int CDecoder::Check(AVCodecContext* avctx)
-+{
-+ EDisplayState state;
-+
-+ { CSharedLock lock(m_displaySection);
-+ state = m_displayState;
-+ }
-+
-+ if (state == XVBA_LOST)
-+ {
-+ CLog::Log(LOGNOTICE,"XVBA::Check waiting for display reset event");
-+ if (!m_displayEvent.WaitMSec(2000))
-+ {
-+ CLog::Log(LOGERROR, "XVBA::Check - device didn't reset in reasonable time");
-+ return VC_ERROR;
-+ }
-+ { CSharedLock lock(m_displaySection);
-+ state = m_displayState;
-+ }
-+ }
-+ if (state == XVBA_RESET || state == XVBA_ERROR)
-+ {
-+ CLog::Log(LOGNOTICE,"XVBA::Check - Attempting recovery");
-+
-+ CSingleLock gLock(g_graphicsContext);
-+ CExclusiveLock lock(m_decoderSection);
-+
-+ DestroySession();
-+ ResetState();
-+ CXVBAContext::EnsureContext(&m_context);
-+
-+ if (state == XVBA_RESET)
-+ return VC_FLUSHED;
-+ else
-+ return VC_ERROR;
-+ }
-+ return 0;
-+}
-+
-+void CDecoder::SetError(const char* function, const char* msg, int line)
-+{
-+ CLog::Log(LOGERROR, "XVBA::%s - %s, line %d", function, msg, line);
-+ CExclusiveLock lock(m_displaySection);
-+ m_displayState = XVBA_ERROR;
-+}
-+
-+bool CDecoder::CreateSession(AVCodecContext* avctx)
-+{
-+ m_surfaceWidth = (avctx->coded_width+15) & ~15;
-+ m_surfaceHeight = (avctx->coded_height+15) & ~15;
-+
-+ m_vidWidth = avctx->width;
-+ m_vidHeight = avctx->height;
-+
-+ XVBA_Create_Decode_Session_Input sessionInput;
-+ XVBA_Create_Decode_Session_Output sessionOutput;
-+
-+ sessionInput.size = sizeof(sessionInput);
-+ sessionInput.width = m_surfaceWidth;
-+ sessionInput.height = m_surfaceHeight;
-+ sessionInput.context = m_context->GetContext();
-+ sessionInput.decode_cap = &m_decoderCap;
-+ sessionOutput.size = sizeof(sessionOutput);
-+
-+ if (Success != g_XVBA_vtable.CreateDecode(&sessionInput, &sessionOutput))
-+ {
-+ SetError(__FUNCTION__, "failed to create decoder session", __LINE__);
-+ CLog::Log(LOGERROR, "Decoder failed with following stats: m_surfaceWidth %u, m_surfaceHeight %u,"
-+ " m_vidWidth %u, m_vidHeight %u, coded_width %d, coded_height %d",
-+ m_surfaceWidth,
-+ m_surfaceHeight,
-+ m_vidWidth,
-+ m_vidHeight,
-+ avctx->coded_width,
-+ avctx->coded_height);
-+ return false;
-+ }
-+ m_xvbaSession = sessionOutput.session;
-+
-+
-+ // create decode buffers
-+ XVBA_Create_DecodeBuff_Input bufferInput;
-+ XVBA_Create_DecodeBuff_Output bufferOutput;
-+
-+ bufferInput.size = sizeof(bufferInput);
-+ bufferInput.session = m_xvbaSession;
-+ bufferInput.buffer_type = XVBA_PICTURE_DESCRIPTION_BUFFER;
-+ bufferInput.num_of_buffers = 1;
-+ bufferOutput.size = sizeof(bufferOutput);
-+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
-+ || bufferOutput.num_of_buffers_in_list != 1)
-+ {
-+ SetError(__FUNCTION__, "failed to create picture buffer", __LINE__);
-+ return false;
-+ }
-+ m_xvbaBufferPool.picture_descriptor_buffer = bufferOutput.buffer_list;
-+
-+ // data buffer
-+ bufferInput.buffer_type = XVBA_DATA_BUFFER;
-+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
-+ || bufferOutput.num_of_buffers_in_list != 1)
-+ {
-+ SetError(__FUNCTION__, "failed to create data buffer", __LINE__);
-+ return false;
-+ }
-+ m_xvbaBufferPool.data_buffer = bufferOutput.buffer_list;
-+
-+ // QO Buffer
-+ bufferInput.buffer_type = XVBA_QM_BUFFER;
-+ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
-+ || bufferOutput.num_of_buffers_in_list != 1)
-+ {
-+ SetError(__FUNCTION__, "failed to create qm buffer", __LINE__);
-+ return false;
-+ }
-+ m_xvbaBufferPool.iq_matrix_buffer = bufferOutput.buffer_list;
-+
-+ return true;
-+}
-+
-+void CDecoder::DestroySession()
-+{
-+ XVBA_Destroy_Decode_Buffers_Input bufInput;
-+ bufInput.size = sizeof(bufInput);
-+ bufInput.num_of_buffers_in_list = 1;
-+
-+ for (unsigned int i=0; isurface)
-+ {
-+ g_XVBA_vtable.DestroySurface(render->surface);
-+ render->surface = 0;
-+ render->picture_descriptor = 0;
-+ render->iq_matrix = 0;
-+ }
-+ }
-+
-+ if (m_xvbaSession)
-+ g_XVBA_vtable.DestroyDecode(m_xvbaSession);
-+ m_xvbaSession = 0;
-+}
-+
-+bool CDecoder::IsSurfaceValid(xvba_render_state *render)
-+{
-+ // find render state in queue
-+ bool found(false);
-+ unsigned int i;
-+ for(i = 0; i < m_videoSurfaces.size(); ++i)
-+ {
-+ if(m_videoSurfaces[i] == render)
-+ {
-+ found = true;
-+ break;
-+ }
-+ }
-+ if (!found)
-+ {
-+ CLog::Log(LOGERROR,"%s - video surface not found", __FUNCTION__);
-+ return false;
-+ }
-+ if (m_videoSurfaces[i]->surface == 0)
-+ {
-+ m_videoSurfaces[i]->state = 0;
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+bool CDecoder::EnsureDataControlBuffers(unsigned int num)
-+{
-+ if (m_xvbaBufferPool.data_control_buffers.size() >= num)
-+ return true;
-+
-+ unsigned int missing = num - m_xvbaBufferPool.data_control_buffers.size();
-+
-+ XVBA_Create_DecodeBuff_Input bufferInput;
-+ XVBA_Create_DecodeBuff_Output bufferOutput;
-+ bufferInput.size = sizeof(bufferInput);
-+ bufferInput.session = m_xvbaSession;
-+ bufferInput.buffer_type = XVBA_DATA_CTRL_BUFFER;
-+ bufferInput.num_of_buffers = 1;
-+ bufferOutput.size = sizeof(bufferOutput);
-+
-+ for (unsigned int i=0; iopaque;
-+ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
-+ unsigned int i;
-+
-+ CSharedLock lock(xvba->m_decoderSection);
-+
-+ xvba_render_state * render = NULL;
-+ render = (xvba_render_state*)pic->data[0];
-+ if(!render)
-+ {
-+ CLog::Log(LOGERROR, "XVBA::FFReleaseBuffer - invalid context handle provided");
-+ return;
-+ }
-+
-+ for(i=0; i<4; i++)
-+ pic->data[i]= NULL;
-+
-+ // find render state in queue
-+ if (!xvba->IsSurfaceValid(render))
-+ {
-+ CLog::Log(LOGDEBUG, "XVBA::FFReleaseBuffer - ignoring invalid buffer");
-+ return;
-+ }
-+
-+ render->state &= ~FF_XVBA_STATE_USED_FOR_REFERENCE;
-+}
-+
-+void CDecoder::FFDrawSlice(struct AVCodecContext *avctx,
-+ const AVFrame *src, int offset[4],
-+ int y, int type, int height)
-+{
-+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
-+ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
-+
-+ CSharedLock lock(xvba->m_decoderSection);
-+
-+ { CSharedLock dLock(xvba->m_displaySection);
-+ if(xvba->m_displayState != XVBA_OPEN)
-+ return;
-+ }
-+
-+ if(src->linesize[0] || src->linesize[1] || src->linesize[2]
-+ || offset[0] || offset[1] || offset[2])
-+ {
-+ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid linesizes or offsets provided");
-+ return;
-+ }
-+
-+ xvba_render_state * render;
-+
-+ render = (xvba_render_state*)src->data[0];
-+ if(!render)
-+ {
-+ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid context handle provided");
-+ return;
-+ }
-+
-+ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
-+ if (!xvba->IsSurfaceValid(render))
-+ {
-+ CLog::Log(LOGWARNING, "XVBA::FFDrawSlice - ignoring invalid buffer");
-+ return;
-+ }
-+
-+ // decoding
-+ XVBA_Decode_Picture_Start_Input startInput;
-+ startInput.size = sizeof(startInput);
-+ startInput.session = xvba->m_xvbaSession;
-+ startInput.target_surface = render->surface;
-+ { CSingleLock lock(xvba->m_apiSec);
-+ if (Success != g_XVBA_vtable.StartDecodePicture(&startInput))
-+ {
-+ xvba->SetError(__FUNCTION__, "failed to start decoding", __LINE__);
-+ return;
-+ }
-+ }
-+ XVBA_Decode_Picture_Input picInput;
-+ picInput.size = sizeof(picInput);
-+ picInput.session = xvba->m_xvbaSession;
-+ XVBABufferDescriptor *list[2];
-+ picInput.buffer_list = list;
-+ list[0] = xvba->m_xvbaBufferPool.picture_descriptor_buffer;
-+ picInput.num_of_buffers_in_list = 1;
-+ if (avctx->codec_id == CODEC_ID_H264)
-+ {
-+ list[1] = xvba->m_xvbaBufferPool.iq_matrix_buffer;
-+ picInput.num_of_buffers_in_list = 2;
-+ }
-+
-+ { CSingleLock lock(xvba->m_apiSec);
-+ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
-+ {
-+ xvba->SetError(__FUNCTION__, "failed to decode picture 1", __LINE__);
-+ return;
-+ }
-+ }
-+
-+ if (!xvba->EnsureDataControlBuffers(render->num_slices))
-+ return;
-+
-+ XVBADataCtrl *dataControl;
-+ int location = 0;
-+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer = 0;
-+ for (unsigned int j = 0; j < render->num_slices; ++j)
-+ {
-+ int startCodeSize = 0;
-+ uint8_t startCode[] = {0x00,0x00,0x01};
-+ if (avctx->codec_id == CODEC_ID_H264)
-+ {
-+ startCodeSize = 3;
-+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
-+ startCode, 3);
-+ }
-+ else if (avctx->codec_id == CODEC_ID_VC1 &&
-+ (memcmp(render->buffers[j].buffer, startCode, 3) != 0))
-+ {
-+ startCodeSize = 4;
-+ uint8_t sdf = 0x0d;
-+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
-+ startCode, 3);
-+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+3,
-+ &sdf, 1);
-+ }
-+ // check for potential buffer overwrite
-+ unsigned int bytesToCopy = render->buffers[j].size;
-+ unsigned int freeBufferSize = xvba->m_xvbaBufferPool.data_buffer->buffer_size -
-+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
-+ if (bytesToCopy >= freeBufferSize)
-+ {
-+ xvba->SetError(__FUNCTION__, "bitstream buffer too large, maybe corrupted packet", __LINE__);
-+ return;
-+ }
-+ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+startCodeSize,
-+ render->buffers[j].buffer,
-+ render->buffers[j].size);
-+ dataControl = (XVBADataCtrl*)xvba->m_xvbaBufferPool.data_control_buffers[j]->bufferXVBA;
-+ dataControl->SliceDataLocation = location;
-+ dataControl->SliceBytesInBuffer = render->buffers[j].size+startCodeSize;
-+ dataControl->SliceBitsInBuffer = dataControl->SliceBytesInBuffer * 8;
-+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += dataControl->SliceBytesInBuffer;
-+ location += dataControl->SliceBytesInBuffer;
-+ }
-+
-+ int bufSize = xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
-+ int padding = bufSize % 128;
-+ if (padding)
-+ {
-+ padding = 128 - padding;
-+ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += padding;
-+ memset((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+bufSize,0,padding);
-+ }
-+
-+ picInput.num_of_buffers_in_list = 2;
-+ for (unsigned int i = 0; i < render->num_slices; ++i)
-+ {
-+ list[0] = xvba->m_xvbaBufferPool.data_buffer;
-+ list[0]->data_offset = 0;
-+ list[1] = xvba->m_xvbaBufferPool.data_control_buffers[i];
-+ list[1]->data_size_in_buffer = sizeof(*dataControl);
-+ { CSingleLock lock(xvba->m_apiSec);
-+ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
-+ {
-+ xvba->SetError(__FUNCTION__, "failed to decode picture 2", __LINE__);
-+ return;
-+ }
-+ }
-+ }
-+ XVBA_Decode_Picture_End_Input endInput;
-+ endInput.size = sizeof(endInput);
-+ endInput.session = xvba->m_xvbaSession;
-+ { CSingleLock lock(xvba->m_apiSec);
-+ if (Success != g_XVBA_vtable.EndDecodePicture(&endInput))
-+ {
-+ xvba->SetError(__FUNCTION__, "failed to decode picture 3", __LINE__);
-+ return;
-+ }
-+ }
-+
-+ // decode sync and error
-+ XVBA_Surface_Sync_Input syncInput;
-+ XVBA_Surface_Sync_Output syncOutput;
-+ syncInput.size = sizeof(syncInput);
-+ syncInput.session = xvba->m_xvbaSession;
-+ syncInput.surface = render->surface;
-+ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
-+ syncOutput.size = sizeof(syncOutput);
-+ int64_t start = CurrentHostCounter();
-+ while (1)
-+ {
-+ { CSingleLock lock(xvba->m_apiSec);
-+ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
-+ {
-+ xvba->SetError(__FUNCTION__, "failed sync surface 1", __LINE__);
-+ return;
-+ }
-+ }
-+ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
-+ break;
-+ if (CurrentHostCounter() - start > CurrentHostFrequency())
-+ {
-+ xvba->SetError(__FUNCTION__, "timed out waiting for surface", __LINE__);
-+ break;
-+ }
-+ usleep(100);
-+ }
-+ render->state |= 4;
-+}
-+
-+int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
-+{
-+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
-+ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
-+ struct pictureAge* pA = &xvba->picAge;
-+
-+ pic->data[0] =
-+ pic->data[1] =
-+ pic->data[2] =
-+ pic->data[3] = 0;
-+
-+ pic->linesize[0] =
-+ pic->linesize[1] =
-+ pic->linesize[2] =
-+ pic->linesize[3] = 0;
-+
-+ CSharedLock lock(xvba->m_decoderSection);
-+
-+ { CSharedLock dLock(xvba->m_displaySection);
-+ if(xvba->m_displayState != XVBA_OPEN)
-+ return -1;
-+ }
-+
-+ if (xvba->m_xvbaSession == 0)
-+ {
-+ if (!xvba->CreateSession(avctx))
-+ return -1;
-+ }
-+
-+ xvba_render_state * render = NULL;
-+ // find unused surface
-+ { CSingleLock lock(xvba->m_videoSurfaceSec);
-+ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i)
-+ {
-+ if(!(xvba->m_videoSurfaces[i]->state & (FF_XVBA_STATE_USED_FOR_REFERENCE | FF_XVBA_STATE_USED_FOR_RENDER)))
-+ {
-+ render = xvba->m_videoSurfaces[i];
-+ render->state = 0;
-+ break;
-+ }
-+ }
-+ }
-+
-+ // create a new render state
-+ if (render == NULL)
-+ {
-+ render = (xvba_render_state*)calloc(sizeof(xvba_render_state), 1);
-+ if (render == NULL)
-+ {
-+ CLog::Log(LOGERROR, "XVBA::FFGetBuffer - calloc failed");
-+ return -1;
-+ }
-+ render->surface = 0;
-+ render->buffers_alllocated = 0;
-+ CSingleLock lock(xvba->m_videoSurfaceSec);
-+ xvba->m_videoSurfaces.push_back(render);
-+ }
-+
-+ // create a new surface
-+ if (render->surface == 0)
-+ {
-+ XVBA_Create_Surface_Input surfaceInput;
-+ XVBA_Create_Surface_Output surfaceOutput;
-+ surfaceInput.size = sizeof(surfaceInput);
-+ surfaceInput.surface_type = xvba->m_decoderCap.surface_type;
-+ surfaceInput.width = xvba->m_surfaceWidth;
-+ surfaceInput.height = xvba->m_surfaceHeight;
-+ surfaceInput.session = xvba->m_xvbaSession;
-+ surfaceOutput.size = sizeof(surfaceOutput);
-+ { CSingleLock lock(xvba->m_apiSec);
-+ if (Success != g_XVBA_vtable.CreateSurface(&surfaceInput, &surfaceOutput))
-+ {
-+ xvba->SetError(__FUNCTION__, "failed to create video surface", __LINE__);
-+ return -1;
-+ }
-+ }
-+ render->surface = surfaceOutput.surface;
-+ render->picture_descriptor = (XVBAPictureDescriptor *)xvba->m_xvbaBufferPool.picture_descriptor_buffer->bufferXVBA;
-+ render->iq_matrix = (XVBAQuantMatrixAvc *)xvba->m_xvbaBufferPool.iq_matrix_buffer->bufferXVBA;
-+ CLog::Log(LOGDEBUG, "XVBA::FFGetBuffer - created video surface");
-+ }
-+
-+ if (render == NULL)
-+ return -1;
-+
-+ pic->data[0] = (uint8_t*)render;
-+
-+ if(pic->reference)
-+ {
-+ pic->age = pA->ip_age[0];
-+ pA->ip_age[0]= pA->ip_age[1]+1;
-+ pA->ip_age[1]= 1;
-+ pA->b_age++;
-+ }
-+ else
-+ {
-+ pic->age = pA->b_age;
-+ pA->ip_age[0]++;
-+ pA->ip_age[1]++;
-+ pA->b_age = 1;
-+ }
-+ pic->type= FF_BUFFER_TYPE_USER;
-+
-+ render->state |= FF_XVBA_STATE_USED_FOR_REFERENCE;
-+ render->state &= ~4;
-+ pic->reordered_opaque= avctx->reordered_opaque;
-+
-+ return 0;
-+}
-+
-+int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
-+{
-+ int result = Check(avctx);
-+ if (result)
-+ return result;
-+
-+ CSharedLock lock(m_decoderSection);
-+
-+ int iReturn(0);
-+ if(frame)
-+ { // we have a new frame from decoder
-+
-+ xvba_render_state * render = (xvba_render_state*)frame->data[0];
-+ if(!render)
-+ return VC_ERROR;
-+
-+ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
-+ if (!IsSurfaceValid(render))
-+ {
-+ CLog::Log(LOGWARNING, "XVBA::Decode - ignoring invalid buffer");
-+ return VC_BUFFER;
-+ }
-+ if (!(render->state & 4))
-+ {
-+ CLog::Log(LOGDEBUG, "XVBA::Decode - ffmpeg failed");
-+ return VC_BUFFER;
-+ }
-+
-+ render->state |= FF_XVBA_STATE_USED_FOR_RENDER;
-+
-+ CSingleLock lock(m_outPicSec);
-+ if (m_freeOutPic.empty())
-+ {
-+ return VC_ERROR;
-+ }
-+ OutputPicture *outPic = m_freeOutPic.front();
-+ m_freeOutPic.pop_front();
-+ memset(&outPic->dvdPic, 0, sizeof(DVDVideoPicture));
-+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&outPic->dvdPic);
-+ outPic->render = render;
-+
-+ if (g_guiSettings.GetBool("videoplayer.usexvbasharedsurface"))
-+ outPic->dvdPic.format = DVDVideoPicture::FMT_XVBA;
-+ else
-+ outPic->dvdPic.format = DVDVideoPicture::FMT_XVBA_YV12;
-+ outPic->dvdPic.iWidth = m_surfaceWidth;
-+ outPic->dvdPic.iHeight = m_surfaceHeight;
-+ outPic->dvdPic.xvba = this;
-+
-+ m_usedOutPic.push_back(outPic);
-+ lock.Leave();
-+
-+ iReturn |= VC_PICTURE;
-+ }
-+
-+ { CSingleLock lock(m_outPicSec);
-+ if (!m_freeOutPic.empty())
-+ iReturn |= VC_BUFFER;
-+ }
-+
-+ return iReturn;
-+}
-+
-+bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
-+{
-+ CSharedLock lock(m_decoderSection);
-+
-+ { CSharedLock dLock(m_displaySection);
-+ if(m_displayState != XVBA_OPEN)
-+ return false;
-+ }
-+
-+ { CSingleLock lock(m_outPicSec);
-+
-+ if (DiscardPresentPicture())
-+ CLog::Log(LOGWARNING,"XVBA::GetPicture: old presentPicture was still valid - now discarded");
-+ if (m_usedOutPic.size() > 0)
-+ {
-+ m_presentPicture = m_usedOutPic.front();
-+ m_usedOutPic.pop_front();
-+ *picture = m_presentPicture->dvdPic;
-+ }
-+ else
-+ {
-+ CLog::Log(LOGERROR,"XVBA::GetPicture: no picture");
-+ return false;
-+ }
-+ }
-+ return true;
-+}
-+
-+bool CDecoder::DiscardPresentPicture()
-+{
-+ CSingleLock lock(m_outPicSec);
-+ if (m_presentPicture)
-+ {
-+ if (m_presentPicture->render)
-+ m_presentPicture->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
-+ m_presentPicture->render = NULL;
-+ m_freeOutPic.push_back(m_presentPicture);
-+ m_presentPicture = NULL;
-+ return true;
-+ }
-+ return false;
-+}
-+
-+void CDecoder::Present(int index)
-+{
-+ CSharedLock lock(m_decoderSection);
-+
-+ { CSharedLock dLock(m_displaySection);
-+ if(m_displayState != XVBA_OPEN)
-+ return;
-+ }
-+
-+ if (!m_presentPicture)
-+ {
-+ // use last picture, we might processing a still frame here
-+ int lastIndex = (index + m_numRenderBuffers -1) % m_numRenderBuffers;
-+ m_presentPicture = m_flipBuffer[lastIndex].outPic;
-+ m_flipBuffer[lastIndex].isDuplicate = true;
-+ if (!m_presentPicture)
-+ {
-+ CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL");
-+ return;
-+ }
-+ }
-+
-+ if (m_flipBuffer[index].outPic && !m_flipBuffer[index].isDuplicate)
-+ {
-+ if (m_flipBuffer[index].outPic->render)
-+ {
-+ CSingleLock lock(m_videoSurfaceSec);
-+ m_flipBuffer[index].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
-+ m_flipBuffer[index].outPic->render = NULL;
-+ }
-+ CSingleLock lock(m_outPicSec);
-+ m_freeOutPic.push_back(m_flipBuffer[index].outPic);
-+ m_flipBuffer[index].outPic = NULL;
-+ }
-+
-+ m_flipBuffer[index].outPic = m_presentPicture;
-+ m_flipBuffer[index].isDuplicate = false;
-+ m_presentPicture = NULL;
-+}
-+
-+void CDecoder::CopyYV12(int index, uint8_t *dest)
-+{
-+ CSharedLock lock(m_decoderSection);
-+
-+ { CSharedLock dLock(m_displaySection);
-+ if(m_displayState != XVBA_OPEN)
-+ return;
-+ }
-+
-+ if (!m_flipBuffer[index].outPic)
-+ {
-+ CLog::Log(LOGWARNING, "XVBA::CopyYV12: current picture is NULL");
-+ return;
-+ }
-+ if (!m_flipBuffer[index].outPic->render)
-+ {
-+ CLog::Log(LOGWARNING, "XVBA::CopyYV12: current render is NULL");
-+ return;
-+ }
-+ if (!m_flipBuffer[index].outPic->render->surface)
-+ {
-+ CLog::Log(LOGWARNING, "XVBA::CopyYV12: current surface is NULL");
-+ return;
-+ }
-+
-+ XVBA_GetSurface_Target target;
-+ target.size = sizeof(target);
-+ target.surfaceType = XVBA_YV12;
-+ target.flag = XVBA_FRAME;
-+
-+ XVBA_Get_Surface_Input input;
-+ input.size = sizeof(input);
-+ input.session = m_xvbaSession;
-+ input.src_surface = m_flipBuffer[index].outPic->render->surface;
-+ input.target_buffer = dest;
-+ input.target_pitch = m_surfaceWidth;
-+ input.target_width = m_surfaceWidth;
-+ input.target_height = m_surfaceHeight;
-+ input.target_parameter = target;
-+ { CSingleLock lock(m_apiSec);
-+ if (Success != g_XVBA_vtable.GetSurface(&input))
-+ {
-+ CLog::Log(LOGERROR,"XVBA::CopyYV12: failed to get surface");
-+ }
-+ }
-+}
-+
-+void CDecoder::Reset()
-+{
-+
-+}
-+
-+int CDecoder::UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget)
-+{
-+ CSharedLock lock(m_decoderSection);
-+
-+ { CSharedLock dLock(m_displaySection);
-+ if(m_displayState != XVBA_OPEN)
-+ return -1;
-+ }
-+
-+ if (!m_flipBuffer[index].outPic ||
-+ !m_flipBuffer[index].outPic->render ||
-+ !m_flipBuffer[index].outPic->render->surface)
-+ return -1;
-+
-+ int i = field;
-+// unsigned int first, last;
-+// first = last = 0;
-+// if (field != XVBA_FRAME)
-+// {
-+// first = 1;
-+// last = 2;
-+// }
-+// for (unsigned int i = first; i <= last; ++i)
-+ {
-+ XVBA_SURFACE_FLAG field;
-+ if (i==0) field = XVBA_FRAME;
-+ else if (i==1) field = XVBA_TOP_FIELD;
-+ else field = XVBA_BOTTOM_FIELD;
-+
-+ if (!glIsTexture(m_flipBuffer[index].glTexture[i]))
-+ {
-+ glEnable(textureTarget);
-+ glGenTextures(1, &m_flipBuffer[index].glTexture[i]);
-+ glBindTexture(textureTarget, m_flipBuffer[index].glTexture[i]);
-+ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-+ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-+ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-+ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_surfaceWidth, m_surfaceHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-+
-+ XVBA_Create_GLShared_Surface_Input surfInput;
-+ XVBA_Create_GLShared_Surface_Output surfOutput;
-+ surfInput.size = sizeof(surfInput);
-+ surfInput.session = m_xvbaSession;
-+ surfInput.gltexture = m_flipBuffer[index].glTexture[i];
-+ surfInput.glcontext = glXGetCurrentContext();
-+ surfOutput.size = sizeof(surfOutput);
-+ surfOutput.surface = 0;
-+ if (Success != g_XVBA_vtable.CreateGLSharedSurface(&surfInput, &surfOutput))
-+ {
-+ CLog::Log(LOGERROR,"(XVBA) failed to create shared surface");
-+ return -1;
-+ }
-+ m_flipBuffer[index].glSurface[i] = surfOutput.surface;
-+ CLog::Log(LOGDEBUG, "XVBA::GetTexture - created shared surface");
-+ }
-+
-+ XVBA_Transfer_Surface_Input transInput;
-+ transInput.size = sizeof(transInput);
-+ transInput.session = m_xvbaSession;
-+ transInput.src_surface = m_flipBuffer[index].outPic->render->surface;
-+ transInput.target_surface = m_flipBuffer[index].glSurface[i];
-+ transInput.flag = field;
-+ { CSingleLock lock(m_apiSec);
-+ if (Success != g_XVBA_vtable.TransferSurface(&transInput))
-+ {
-+ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
-+ return -1;
-+ }
-+ }
-+ }
-+
-+// { CSingleLock lock(m_videoSurfaceSec);
-+// m_flipBuffer[index].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
-+// m_flipBuffer[index].outPic->render = NULL;
-+// }
-+// {
-+// CSingleLock lock(m_outPicSec);
-+// m_freeOutPic.push_back(m_flipBuffer[index].outPic);
-+// m_flipBuffer[index].outPic = NULL;
-+// }
-+
-+ return 1;
-+}
-+
-+GLuint CDecoder::GetTexture(int index, XVBA_SURFACE_FLAG field)
-+{
-+ return m_flipBuffer[index].glTexture[field];
-+}
-+
-+CRect CDecoder::GetCropRect()
-+{
-+ CRect crop;
-+ crop.x1 = 0;
-+ crop.y1 = 0;
-+ crop.x2 = m_vidWidth;
-+ crop.y2 = m_vidHeight;
-+ return crop;
-+}
-+
-+void CDecoder::FinishGL()
-+{
-+ CLog::Log(LOGNOTICE, "XVBA::FinishGL - clearing down gl resources");
-+
-+ CExclusiveLock lock(m_decoderSection);
-+ // if decoder was created with non supported codec, we would not have a flipBuffer and segfault
-+ if(!m_flipBuffer)
-+ return;
-+
-+ for (unsigned int i=0; irender)
-+ {
-+ { CSingleLock lock(m_videoSurfaceSec);
-+ m_flipBuffer[i].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
-+ m_flipBuffer[i].outPic->render = NULL;
-+ }
-+ { CSingleLock lock(m_outPicSec);
-+ m_freeOutPic.push_back(m_flipBuffer[i].outPic);
-+ m_flipBuffer[i].outPic = 0;
-+ }
-+ }
-+
-+ for (unsigned int j=0; j<3; ++j)
-+ {
-+ if (m_flipBuffer[i].glSurface[j] && m_xvbaSession)
-+ {
-+ { CSingleLock lock(m_apiSec);
-+ g_XVBA_vtable.DestroySurface(m_flipBuffer[i].glSurface[j]);
-+ }
-+ m_flipBuffer[i].glSurface[j] = 0;
-+ CLog::Log(LOGDEBUG, "XVBA::FinishGL - destroyed shared surface");
-+ }
-+ if (glIsTexture(m_flipBuffer[i].glTexture[j]))
-+ {
-+ glDeleteTextures(1, &m_flipBuffer[i].glTexture[j]);
-+ m_flipBuffer[i].glTexture[j] = 0;
-+ CLog::Log(LOGDEBUG, "XVBA::FinishGL - destroyed texture, index: %d, field %d", i, j);
-+ }
-+ }
-+ }
-+}
-+
-+#endif
-diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
-new file mode 100644
-index 0000000..07ef811
---- /dev/null
-+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
-@@ -0,0 +1,161 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+#pragma once
-+
-+#include "X11/Xlib.h"
-+#include "amd/amdxvba.h"
-+#include "DllAvCodec.h"
-+#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h"
-+#include "threads/CriticalSection.h"
-+#include "threads/SharedSection.h"
-+#include "threads/Event.h"
-+#include "guilib/DispResource.h"
-+#include "guilib/Geometry.h"
-+#include "libavcodec/xvba.h"
-+#include
-+#include
-+
-+#define NUM_OUTPUT_PICS 7
-+
-+namespace XVBA
-+{
-+
-+struct pictureAge
-+{
-+ int b_age;
-+ int ip_age[2];
-+};
-+
-+enum EDisplayState
-+{ XVBA_OPEN
-+, XVBA_RESET
-+, XVBA_LOST
-+, XVBA_ERROR
-+};
-+
-+class CXVBAContext
-+{
-+public:
-+ static bool EnsureContext(CXVBAContext **ctx);
-+ void *GetContext();
-+ void Release();
-+private:
-+ CXVBAContext();
-+ void Close();
-+ bool LoadSymbols();
-+ bool CreateContext();
-+ void DestroyContext();
-+ static CXVBAContext *m_context;
-+ static CCriticalSection m_section;
-+ static Display *m_display;
-+ int m_refCount;
-+ static void *m_dlHandle;
-+ void *m_xvbaContext;
-+};
-+
-+class CDecoder : public CDVDVideoCodecFFmpeg::IHardwareDecoder,
-+ public IDispResource
-+{
-+public:
-+ CDecoder();
-+ virtual ~CDecoder();
-+ virtual void OnLostDevice();
-+ virtual void OnResetDevice();
-+
-+ virtual bool Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces = 0);
-+ virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
-+ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
-+ virtual void Reset();
-+ virtual void Close();
-+ virtual int Check(AVCodecContext* avctx);
-+ virtual const std::string Name() { return "xvba"; }
-+
-+ void Present(int index);
-+ void CopyYV12(int index, uint8_t *dest);
-+ int UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget);
-+ GLuint GetTexture(int index, XVBA_SURFACE_FLAG field);
-+ CRect GetCropRect();
-+ void FinishGL();
-+
-+protected:
-+ bool CreateSession(AVCodecContext* avctx);
-+ void DestroySession();
-+ bool EnsureDataControlBuffers(unsigned int num);
-+ bool DiscardPresentPicture();
-+ void ResetState();
-+ void SetError(const char* function, const char* msg, int line);
-+ bool IsSurfaceValid(xvba_render_state *render);
-+
-+ // callbacks for ffmpeg
-+ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
-+ static void FFDrawSlice(struct AVCodecContext *avctx,
-+ const AVFrame *src, int offset[4],
-+ int y, int type, int height);
-+ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
-+
-+ DllAvUtil m_dllAvUtil;
-+ CXVBAContext *m_context;
-+ CSharedSection m_displaySection, m_decoderSection;
-+ CEvent m_displayEvent;
-+ EDisplayState m_displayState;
-+
-+ unsigned int m_surfaceWidth, m_surfaceHeight;
-+ unsigned int m_vidWidth, m_vidHeight;
-+ unsigned int m_numRenderBuffers;
-+
-+ XVBADecodeCap m_decoderCap;
-+ void *m_xvbaSession;
-+ unsigned int m_decoderId;
-+ struct XVBABufferPool
-+ {
-+ XVBABufferDescriptor *picture_descriptor_buffer;
-+ XVBABufferDescriptor *iq_matrix_buffer;
-+ XVBABufferDescriptor *data_buffer;
-+ std::vector data_control_buffers;
-+ };
-+ XVBABufferPool m_xvbaBufferPool;
-+
-+ std::vector m_videoSurfaces;
-+ pictureAge picAge;
-+
-+ struct OutputPicture
-+ {
-+ DVDVideoPicture dvdPic;
-+ xvba_render_state *render;
-+ void *glSurface;
-+ };
-+ struct RenderPicture
-+ {
-+ OutputPicture *outPic;
-+ bool isDuplicate;
-+ void *glSurface[3];
-+ GLuint glTexture[3];
-+ };
-+ CCriticalSection m_outPicSec, m_videoSurfaceSec;
-+ CCriticalSection m_apiSec;
-+ OutputPicture m_allOutPic[NUM_OUTPUT_PICS];
-+ std::deque m_freeOutPic;
-+ std::deque m_usedOutPic;
-+ OutputPicture *m_presentPicture;
-+ RenderPicture *m_flipBuffer;
-+};
-+
-+}
-diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
-index 55138fa..423d9f8 100644
---- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
-+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
-@@ -19,7 +19,6 @@
- *
- */
-
--#include "threads/SystemClock.h"
- #include "system.h"
- #ifndef __STDC_CONSTANT_MACROS
- #define __STDC_CONSTANT_MACROS
-@@ -44,6 +43,7 @@
- #include "filesystem/Directory.h"
- #include "utils/log.h"
- #include "threads/Thread.h"
-+#include "threads/SystemClock.h"
- #include "utils/TimeUtils.h"
-
- void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo)
-@@ -154,16 +154,12 @@ static void ff_flush_avutil_log_buffers(void)
- ++it;
- }
-
--#ifdef _MSC_VER
--static __declspec(thread) CDVDDemuxFFmpeg* g_demuxer = 0;
--#else
--static TLS g_tls;
--#define g_demuxer (*((CDVDDemuxFFmpeg**)g_tls.Get()))
--#endif
-+static XbmcThreads::ThreadLocal g_demuxer;
-
- static int interrupt_cb(void)
- {
-- if(g_demuxer && g_demuxer->Aborted())
-+ CDVDDemuxFFmpeg* demuxer = g_demuxer.get();
-+ if(demuxer && demuxer->Aborted())
- return 1;
- return 0;
- }
-@@ -235,7 +231,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
- std::string strFile;
- m_iCurrentPts = DVD_NOPTS_VALUE;
- m_speed = DVD_PLAYSPEED_NORMAL;
-- g_demuxer = this;
-+ g_demuxer.set(this);
- m_program = UINT_MAX;
-
- if (!pInput) return false;
-@@ -507,7 +503,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
-
- void CDVDDemuxFFmpeg::Dispose()
- {
-- g_demuxer = this;
-+ g_demuxer.set(this);
-
- if (m_pFormatContext)
- {
-@@ -556,7 +552,7 @@ void CDVDDemuxFFmpeg::Reset()
-
- void CDVDDemuxFFmpeg::Flush()
- {
-- g_demuxer = this;
-+ g_demuxer.set(this);
-
- // naughty usage of an internal ffmpeg function
- if (m_pFormatContext)
-@@ -572,7 +568,7 @@ void CDVDDemuxFFmpeg::Abort()
-
- void CDVDDemuxFFmpeg::SetSpeed(int iSpeed)
- {
-- g_demuxer = this;
-+ g_demuxer.set(this);
-
- if(!m_pFormatContext)
- return;
-@@ -634,7 +630,7 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num)
-
- DemuxPacket* CDVDDemuxFFmpeg::Read()
- {
-- g_demuxer = this;
-+ g_demuxer.set(this);
-
- AVPacket pkt;
- DemuxPacket* pPacket = NULL;
-@@ -833,7 +829,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
-
- bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
- {
-- g_demuxer = this;
-+ g_demuxer.set(this);
-
- if(time < 0)
- time = 0;
-@@ -893,7 +889,7 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
-
- bool CDVDDemuxFFmpeg::SeekByte(__int64 pos)
- {
-- g_demuxer = this;
-+ g_demuxer.set(this);
-
- CSingleLock lock(m_critSection);
- int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE);
-diff --git a/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp b/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
-index 23c5e3e..129674a 100644
---- a/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
-+++ b/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
-@@ -21,6 +21,7 @@
-
- #include "DVDPerformanceCounter.h"
- #include "DVDMessageQueue.h"
-+#include "utils/TimeUtils.h"
-
- #include "dvd_config.h"
-
-@@ -68,22 +69,16 @@ HRESULT __stdcall DVDPerformanceCounterVideoQueue(PLARGE_INTEGER numerator, PLAR
-
- inline __int64 get_thread_cpu_usage(ProcessPerformance* p)
- {
-- if (p->hThread)
-+ if (p->thread)
- {
-- FILETIME dummy;
-- FILETIME current_time_thread;
-- FILETIME current_time_system;
- ULARGE_INTEGER old_time_thread;
- ULARGE_INTEGER old_time_system;
-
- old_time_thread.QuadPart = p->timer_thread.QuadPart;
- old_time_system.QuadPart = p->timer_system.QuadPart;
-
-- GetThreadTimes(p->hThread, &dummy, &dummy, ¤t_time_thread, &dummy);
-- GetSystemTimeAsFileTime(¤t_time_system);
--
-- FILETIME_TO_ULARGE_INTEGER(p->timer_thread, current_time_thread);
-- FILETIME_TO_ULARGE_INTEGER(p->timer_system, current_time_system);
-+ p->timer_thread.QuadPart = p->thread->GetAbsoluteUsage();
-+ p->timer_system.QuadPart = CurrentHostCounter();
-
- __int64 threadTime = (p->timer_thread.QuadPart - old_time_thread.QuadPart);
- __int64 systemTime = (p->timer_system.QuadPart - old_time_system.QuadPart);
-diff --git a/xbmc/cores/dvdplayer/DVDPerformanceCounter.h b/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
-index 2f0b5ac..e97a14c 100644
---- a/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
-+++ b/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
-@@ -24,7 +24,7 @@
- #define FILETIME_TO_ULARGE_INTEGER(ularge, filetime) { ularge.u.HighPart = filetime.dwHighDateTime; ularge.u.LowPart = filetime.dwLowDateTime; }
-
- #include "system.h"
--
-+#include "threads/Thread.h"
- #include "threads/SingleLock.h"
-
- class CDVDMessageQueue;
-@@ -33,7 +33,7 @@ typedef struct stProcessPerformance
- {
- ULARGE_INTEGER timer_thread;
- ULARGE_INTEGER timer_system;
-- HANDLE hThread;
-+ CThread* thread;
- } ProcessPerformance;
-
- class CDVDPerformanceCounter
-@@ -45,20 +45,20 @@ public:
- bool Initialize();
- void DeInitialize();
-
-- void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; }
-- void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; }
-+ void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; }
-+ void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; }
-
-- void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; }
-- void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; }
-+ void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; }
-+ void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; }
-
-- void EnableVideoDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = hThread; }
-- void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = NULL; }
-+ void EnableVideoDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = thread; }
-+ void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = NULL; }
-
-- void EnableAudioDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = hThread; }
-- void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = NULL; }
-+ void EnableAudioDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = thread; }
-+ void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = NULL; }
-
-- void EnableMainPerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_mainPerformance.hThread = hThread; }
-- void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.hThread = NULL; }
-+ void EnableMainPerformance(CThread *thread) { CSingleLock lock(m_critSection); m_mainPerformance.thread = thread; }
-+ void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.thread = NULL; }
-
- CDVDMessageQueue* m_pAudioQueue;
- CDVDMessageQueue* m_pVideoQueue;
-diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
-index 6c9a3ea..2d1338e 100644
---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
-+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
-@@ -348,7 +348,7 @@ bool CDVDPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
-
- // if playing a file close it first
- // this has to be changed so we won't have to close it.
-- if(ThreadHandle())
-+ if(IsRunning())
- CloseFile();
-
- m_bAbortRequest = false;
-@@ -440,9 +440,8 @@ void CDVDPlayer::OnStartup()
-
- m_messenger.Init();
-
-- g_dvdPerformanceCounter.EnableMainPerformance(ThreadHandle());
--
- CUtil::ClearTempFonts();
-+ g_dvdPerformanceCounter.EnableMainPerformance(this);
- }
-
- bool CDVDPlayer::OpenInputStream()
-@@ -2897,7 +2896,7 @@ bool CDVDPlayer::OpenAudioStream(int iStream, int source)
- m_dvdPlayerAudio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1);
-
- /* audio normally won't consume full cpu, so let it have prio */
-- m_dvdPlayerAudio.SetPriority(GetThreadPriority(*this)+1);
-+ m_dvdPlayerAudio.SetPriority(GetPriority()+1);
-
- return true;
- }
-@@ -2962,11 +2961,11 @@ bool CDVDPlayer::OpenVideoStream(int iStream, int source)
- // the CoreAudio audio device handler thread. We do the same for
- // the DVDPlayerVideo thread so it can run to sleep without getting
- // swapped out by a busy OS.
-- m_dvdPlayerVideo.SetPrioritySched_RR();
-+ m_dvdPlayerVideo.SetPriority(GetSchedRRPriority());
- #else
- /* use same priority for video thread as demuxing thread, as */
- /* otherwise demuxer will starve if video consumes the full cpu */
-- m_dvdPlayerVideo.SetPriority(GetThreadPriority(*this));
-+ m_dvdPlayerVideo.SetPriority(GetPriority());
- #endif
- return true;
-
-diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
-index 41fbaaf..9f2128c 100644
---- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
-+++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
-@@ -518,7 +518,7 @@ void CDVDPlayerAudio::OnStartup()
- m_decode.msg = NULL;
- m_decode.Release();
-
-- g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle());
-+ g_dvdPerformanceCounter.EnableAudioDecodePerformance(this);
-
- #ifdef _WIN32
- CoInitializeEx(NULL, COINIT_MULTITHREADED);
-diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
-index e28faaf..0b02b49 100644
---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
-+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
-@@ -189,7 +189,7 @@ bool CDVDPlayerVideo::OpenStream( CDVDStreamInfo &hint )
- return false;
- }
-
-- if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && g_VideoReferenceClock.ThreadHandle() == NULL)
-+ if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && !g_VideoReferenceClock.IsRunning())
- {
- g_VideoReferenceClock.Create();
- //we have to wait for the clock to start otherwise alsa can cause trouble
-@@ -291,7 +291,7 @@ void CDVDPlayerVideo::OnStartup()
- m_iCurrentPts = DVD_NOPTS_VALUE;
- m_FlipTimeStamp = m_pClock->GetAbsoluteClock();
-
-- g_dvdPerformanceCounter.EnableVideoDecodePerformance(ThreadHandle());
-+ g_dvdPerformanceCounter.EnableVideoDecodePerformance(this);
- }
-
- void CDVDPlayerVideo::Process()
-@@ -1052,6 +1052,14 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
- flags |= CONF_FLAGS_FORMAT_CVBREF;
- formatstr = "BGRA";
- break;
-+ case DVDVideoPicture::FMT_XVBA:
-+ flags |= CONF_FLAGS_FORMAT_XVBA;
-+ formatstr = "XVBA";
-+ break;
-+ case DVDVideoPicture::FMT_XVBA_YV12:
-+ flags |= CONF_FLAGS_FORMAT_XVBA_YV12;
-+ formatstr = "XVBA";
-+ break;
- }
-
- if(m_bAllowFullscreen)
-diff --git a/xbmc/cores/paplayer/PAPlayer.cpp b/xbmc/cores/paplayer/PAPlayer.cpp
-index 43b57d3..13f5238 100644
---- a/xbmc/cores/paplayer/PAPlayer.cpp
-+++ b/xbmc/cores/paplayer/PAPlayer.cpp
-@@ -52,7 +52,7 @@
- // Supporting all open audio codec standards.
- // First one being nullsoft's nsv audio decoder format
-
--PAPlayer::PAPlayer(IPlayerCallback& callback) : IPlayer(callback)
-+PAPlayer::PAPlayer(IPlayerCallback& callback) : CThread("PAPlayer"), IPlayer(callback)
- {
- m_bIsPlaying = false;
- m_bPaused = false;
-@@ -168,7 +168,7 @@ bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
-
- *m_currentFile = file;
-
-- if (ThreadHandle() == NULL)
-+ if (!IsRunning())
- Create();
-
- m_startEvent.Set();
-diff --git a/xbmc/dialogs/GUIDialogCache.cpp b/xbmc/dialogs/GUIDialogCache.cpp
-index 1114cc6..85548e4 100644
---- a/xbmc/dialogs/GUIDialogCache.cpp
-+++ b/xbmc/dialogs/GUIDialogCache.cpp
-@@ -29,7 +29,7 @@
- #include "threads/SingleLock.h"
- #include "utils/TimeUtils.h"
-
--CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg)
-+CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg) : CThread("CGUIDialogCache")
- {
- m_pDlg = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
-
-diff --git a/xbmc/filesystem/FileCache.cpp b/xbmc/filesystem/FileCache.cpp
-index c6af9d0..63937ef 100644
---- a/xbmc/filesystem/FileCache.cpp
-+++ b/xbmc/filesystem/FileCache.cpp
-@@ -79,7 +79,7 @@ private:
- };
-
-
--CFileCache::CFileCache()
-+CFileCache::CFileCache() : CThread("CFileCache")
- {
- m_bDeleteCache = true;
- m_nSeekResult = 0;
-@@ -95,7 +95,7 @@ CFileCache::CFileCache()
- m_cacheFull = false;
- }
-
--CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache)
-+CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache) : CThread("CFileCache")
- {
- m_pCache = pCache;
- m_bDeleteCache = bDeleteCache;
-diff --git a/xbmc/filesystem/FilePipe.cpp b/xbmc/filesystem/FilePipe.cpp
-index 1a55336..c61175e 100644
---- a/xbmc/filesystem/FilePipe.cpp
-+++ b/xbmc/filesystem/FilePipe.cpp
-@@ -24,6 +24,8 @@
- #include "PipesManager.h"
- #include "utils/StringUtils.h"
-
-+#define INFINITE 0xFFFFFFFF
-+
- using namespace XFILE;
-
- CFilePipe::CFilePipe() : m_pos(0), m_length(-1), m_pipe(NULL)
-diff --git a/xbmc/filesystem/FileRar.cpp b/xbmc/filesystem/FileRar.cpp
-index 9c87a35..202b3ee 100644
---- a/xbmc/filesystem/FileRar.cpp
-+++ b/xbmc/filesystem/FileRar.cpp
-@@ -43,7 +43,7 @@ using namespace std;
- #define SEEKTIMOUT 30000
-
- #ifdef HAS_FILESYSTEM_RAR
--CFileRarExtractThread::CFileRarExtractThread() : hRunning(true), hQuit(true)
-+CFileRarExtractThread::CFileRarExtractThread() : CThread("CFileRarExtractThread"), hRunning(true), hQuit(true)
- {
- m_pArc = NULL;
- m_pCmd = NULL;
-diff --git a/xbmc/filesystem/HTSPDirectory.cpp b/xbmc/filesystem/HTSPDirectory.cpp
-index 83a1fca..152754d 100644
---- a/xbmc/filesystem/HTSPDirectory.cpp
-+++ b/xbmc/filesystem/HTSPDirectory.cpp
-@@ -76,7 +76,7 @@ static SSessions g_sessions;
- static CCriticalSection g_section;
-
-
--CHTSPDirectorySession::CHTSPDirectorySession()
-+CHTSPDirectorySession::CHTSPDirectorySession() : CThread("CHTSPDirectorySession")
- {
- }
-
-diff --git a/xbmc/filesystem/LastFMDirectory.cpp b/xbmc/filesystem/LastFMDirectory.cpp
-index af5621c..a4b23fc 100644
---- a/xbmc/filesystem/LastFMDirectory.cpp
-+++ b/xbmc/filesystem/LastFMDirectory.cpp
-@@ -69,7 +69,7 @@ bool CLastFMDirectory::RetrieveList(CStdString url)
- m_dlgProgress->Progress();
- }
-
-- CThread thread(this);
-+ CThread thread(this, "CLastFMDirectory");
- m_strSource = url;
- m_strDestination = "special://temp/lastfm.xml";
- thread.Create();
-diff --git a/xbmc/filesystem/MythSession.cpp b/xbmc/filesystem/MythSession.cpp
-index 45de2cc..304ecdd 100644
---- a/xbmc/filesystem/MythSession.cpp
-+++ b/xbmc/filesystem/MythSession.cpp
-@@ -359,7 +359,7 @@ void CMythSession::SetSeasonAndEpisode(const cmyth_proginfo_t &program, int *sea
- return;
- }
-
--CMythSession::CMythSession(const CURL& url)
-+CMythSession::CMythSession(const CURL& url) : CThread("CMythSession")
- {
- m_control = NULL;
- m_event = NULL;
-diff --git a/xbmc/filesystem/PipesManager.cpp b/xbmc/filesystem/PipesManager.cpp
-index 73f4aa2..80a1044 100644
---- a/xbmc/filesystem/PipesManager.cpp
-+++ b/xbmc/filesystem/PipesManager.cpp
-@@ -23,6 +23,8 @@
- #include "threads/SingleLock.h"
- #include "Application.h"
-
-+#define INFINITE 0xFFFFFFFF
-+
- #ifndef min
- #define min(a,b) ((a) < (b) ? (a) : (b))
- #endif
-diff --git a/xbmc/filesystem/RarManager.h b/xbmc/filesystem/RarManager.h
-index dd4b2f0..6f93f79 100644
---- a/xbmc/filesystem/RarManager.h
-+++ b/xbmc/filesystem/RarManager.h
-@@ -71,7 +71,7 @@ public:
- CRarManager();
- ~CRarManager();
- bool CacheRarredFile(CStdString& strPathInCache, const CStdString& strRarPath,
-- const CStdString& strPathInRar, BYTE bOptions = EXFILE_AUTODELETE,
-+ const CStdString& strPathInRar, uint8_t bOptions = EXFILE_AUTODELETE,
- const CStdString& strDir =RAR_DEFAULT_CACHE, const int64_t iSize=-1);
- bool GetPathInCache(CStdString& strPathInCache, const CStdString& strRarPath,
- const CStdString& strPathInRar = "");
-diff --git a/xbmc/filesystem/SAPDirectory.cpp b/xbmc/filesystem/SAPDirectory.cpp
-index d8931b8..b997c12 100644
---- a/xbmc/filesystem/SAPDirectory.cpp
-+++ b/xbmc/filesystem/SAPDirectory.cpp
-@@ -272,7 +272,7 @@ namespace SDP
- using namespace SDP;
-
-
--CSAPSessions::CSAPSessions()
-+CSAPSessions::CSAPSessions() : CThread("CSAPSessions")
- {
- m_socket = INVALID_SOCKET;
- }
-@@ -486,7 +486,7 @@ namespace XFILE
-
- CSingleLock lock(g_sapsessions.m_section);
-
-- if(g_sapsessions.ThreadHandle() == NULL)
-+ if(!g_sapsessions.IsRunning())
- g_sapsessions.Create();
-
- // check if we can find this session in our cache
-diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp
-index 9f43894..8cb3e61 100644
---- a/xbmc/interfaces/python/XBPython.cpp
-+++ b/xbmc/interfaces/python/XBPython.cpp
-@@ -676,11 +676,11 @@ void XBPython::PulseGlobalEvent()
- m_globalEvent.Set();
- }
-
--void XBPython::WaitForEvent(CEvent& hEvent, unsigned int timeout)
-+void XBPython::WaitForEvent(CEvent& hEvent)
- {
- // wait for either this event our our global event
- XbmcThreads::CEventGroup eventGroup(&hEvent, &m_globalEvent, NULL);
-- eventGroup.wait(timeout);
-+ eventGroup.wait();
- m_globalEvent.Reset();
- }
-
-diff --git a/xbmc/interfaces/python/XBPython.h b/xbmc/interfaces/python/XBPython.h
-index 7737744..8877b54 100644
---- a/xbmc/interfaces/python/XBPython.h
-+++ b/xbmc/interfaces/python/XBPython.h
-@@ -61,7 +61,7 @@ public:
- void Process();
-
- void PulseGlobalEvent();
-- void WaitForEvent(CEvent& hEvent, unsigned int timeout);
-+ void WaitForEvent(CEvent& hEvent);
-
- int ScriptsSize();
- int GetPythonScriptId(int scriptPosition);
-diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
-index 4ec7e23..d44fc23 100644
---- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
-+++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
-@@ -181,9 +181,9 @@ void CGUIPythonWindow::SetCallbackWindow(void *state, void *object)
- m_threadState = state;
- }
-
--void CGUIPythonWindow::WaitForActionEvent(unsigned int timeout)
-+void CGUIPythonWindow::WaitForActionEvent()
- {
-- g_pythonParser.WaitForEvent(m_actionEvent, timeout);
-+ g_pythonParser.WaitForEvent(m_actionEvent);
- m_actionEvent.Reset();
- }
-
-diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
-index c776187..09c0d42 100644
---- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
-+++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
-@@ -51,7 +51,7 @@ public:
- virtual bool OnAction(const CAction &action);
- virtual bool OnBack(int actionID);
- void SetCallbackWindow(void* state, void *object);
-- void WaitForActionEvent(unsigned int timeout);
-+ void WaitForActionEvent();
- void PulseActionEvent();
- void SetDestroyAfterDeinit(bool destroy = true);
- protected:
-diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
-index 2db79f1..9644351 100644
---- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
-+++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
-@@ -279,9 +279,9 @@ void CGUIPythonWindowXML::ClearList()
- UpdateButtons();
- }
-
--void CGUIPythonWindowXML::WaitForActionEvent(unsigned int timeout)
-+void CGUIPythonWindowXML::WaitForActionEvent()
- {
-- g_pythonParser.WaitForEvent(m_actionEvent, timeout);
-+ g_pythonParser.WaitForEvent(m_actionEvent);
- m_actionEvent.Reset();
- }
-
-diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
-index 27bc3a2..340be8b 100644
---- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
-+++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
-@@ -40,7 +40,7 @@ public:
- virtual void AllocResources(bool forceLoad = false);
- virtual void FreeResources(bool forceUnLoad = false);
- void Process(unsigned int currentTime, CDirtyRegionList ®ions);
-- void WaitForActionEvent(unsigned int timeout);
-+ void WaitForActionEvent();
- void PulseActionEvent();
- void AddItem(CFileItemPtr fileItem,int itemPosition);
- void RemoveItem(int itemPosition);
-diff --git a/xbmc/interfaces/python/xbmcmodule/window.cpp b/xbmc/interfaces/python/xbmcmodule/window.cpp
-index 9b9184a..1b72644 100644
---- a/xbmc/interfaces/python/xbmcmodule/window.cpp
-+++ b/xbmc/interfaces/python/xbmcmodule/window.cpp
-@@ -540,11 +540,11 @@ namespace PYXBMC
-
- CPyThreadState pyState;
- if (WindowXML_Check(self))
-- ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent(INFINITE);
-+ ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent();
- else if (WindowXMLDialog_Check(self))
-- ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent(INFINITE);
-+ ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent();
- else
-- ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent(INFINITE);
-+ ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent();
- }
- }
- Py_INCREF(Py_None);
-diff --git a/xbmc/linux/Makefile.in b/xbmc/linux/Makefile.in
-index c3a5877..43f552b 100644
---- a/xbmc/linux/Makefile.in
-+++ b/xbmc/linux/Makefile.in
-@@ -10,14 +10,11 @@ SRCS=ConvUtils.cpp \
- LinuxResourceCounter.cpp \
- LinuxTimezone.cpp \
- PosixMountProvider.cpp \
-- XEventUtils.cpp \
- XFileUtils.cpp \
- XHandle.cpp \
- XLCDproc.cpp \
- XMemUtils.cpp \
-- XSyncUtils.cpp \
- XTimeUtils.cpp \
-- XThreadUtils.cpp \
-
- LIB=linux.a
-
-diff --git a/xbmc/linux/PlatformDefs.h b/xbmc/linux/PlatformDefs.h
-index 33d1c96..55d20c5 100644
---- a/xbmc/linux/PlatformDefs.h
-+++ b/xbmc/linux/PlatformDefs.h
-@@ -182,8 +182,6 @@
- #define EXCEPTION_EXECUTE_HANDLER ...
- //NOTE: dont try to define __except because it breaks g++ (already uses it).
-
--typedef pthread_t ThreadIdentifier;
--
- struct CXHandle; // forward declaration
- typedef CXHandle* HANDLE;
-
-diff --git a/xbmc/linux/PlatformInclude.h b/xbmc/linux/PlatformInclude.h
-index 1f7e7e9..4e44ed8 100644
---- a/xbmc/linux/PlatformInclude.h
-+++ b/xbmc/linux/PlatformInclude.h
-@@ -25,10 +25,7 @@
- #include "PlatformDefs.h"
- #include "XHandlePublic.h"
- #include "XFileUtils.h"
--#include "XSyncUtils.h"
--#include "XEventUtils.h"
- #include "XTimeUtils.h"
--#include "XThreadUtils.h"
- #include "XMemUtils.h"
- #include "ConvUtils.h"
-
-diff --git a/xbmc/linux/XEventUtils.cpp b/xbmc/linux/XEventUtils.cpp
-deleted file mode 100644
-index 639b7b9..0000000
---- a/xbmc/linux/XEventUtils.cpp
-+++ /dev/null
-@@ -1,144 +0,0 @@
--/*
-- * Copyright (C) 2005-2008 Team XBMC
-- * http://www.xbmc.org
-- *
-- * This Program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This Program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with XBMC; see the file COPYING. If not, write to
-- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-- * http://www.gnu.org/copyleft/gpl.html
-- *
-- */
--
--#include "system.h"
--#include "PlatformDefs.h"
--#include "XEventUtils.h"
--#include "XHandle.h"
--#include "utils/log.h"
--#include "threads/SingleLock.h"
--
--using namespace std;
--
--HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName)
--{
-- CXHandle *pHandle = new CXHandle(CXHandle::HND_EVENT);
-- pHandle->m_bManualEvent = bManualReset;
-- pHandle->m_hCond = new XbmcThreads::ConditionVariable();
-- pHandle->m_hMutex = new CCriticalSection();
-- pHandle->m_bEventSet = false;
--
-- if (bInitialState)
-- SetEvent(pHandle);
--
-- return pHandle;
--}
--
--//
--// The state of a manual-reset event object remains signaled until it is set explicitly to the nonsignaled
--// state by the ResetEvent function. Any number of waiting threads, or threads that subsequently begin wait
--// operations for the specified event object by calling one of the wait functions, can be released while the
--// object's state is signaled.
--//
--// The state of an auto-reset event object remains signaled until a single waiting thread is released, at
--// which time the system automatically sets the state to nonsignaled. If no threads are waiting, the event
--// object's state remains signaled.
--//
--bool WINAPI SetEvent(HANDLE hEvent)
--{
-- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
-- return false;
--
-- CSingleLock lock(*(hEvent->m_hMutex));
-- hEvent->m_bEventSet = true;
--
-- // we must guarantee that these handle's won't be deleted, until we are done
-- list events = hEvent->m_hParents;
-- for(list::iterator it = events.begin();it != events.end();it++)
-- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
--
-- lock.Leave();
--
-- for(list::iterator it = events.begin();it != events.end();it++)
-- {
-- SetEvent(*it);
-- CloseHandle(*it);
-- }
--
-- DuplicateHandle(GetCurrentProcess(), hEvent, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
--
-- if (hEvent->m_bManualEvent == true)
-- hEvent->m_hCond->notifyAll();
-- else
-- hEvent->m_hCond->notify();
--
-- CloseHandle(hEvent);
--
-- return true;
--}
--
--bool WINAPI ResetEvent(HANDLE hEvent)
--{
-- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
-- return false;
--
-- CSingleLock lock(*(hEvent->m_hMutex));
-- hEvent->m_bEventSet = false;
--
-- return true;
--}
--
--bool WINAPI PulseEvent(HANDLE hEvent)
--{
-- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
-- return false;
--
-- CSingleLock lock(*(hEvent->m_hMutex));
-- // we must guarantee that these handle's won't be deleted, until we are done
-- list events = hEvent->m_hParents;
-- for(list::iterator it = events.begin();it != events.end();it++)
-- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
--
-- if(events.size())
-- {
-- CLog::Log(LOGWARNING,"PulseEvent - ineffecient multiwait detected");
-- hEvent->m_bEventSet = true;
-- }
--
-- lock.Leave();
--
-- for(list::iterator it = events.begin();it != events.end();it++)
-- {
-- SetEvent(*it);
-- CloseHandle(*it);
--
-- if (hEvent->m_bManualEvent == false)
-- break;
-- }
--
-- // for multiwaits, we must yield some time to get the multiwaits to notice it was signaled
-- if(events.size())
-- Sleep(10);
--
-- // we should always unset the event on pulse
-- {
-- CSingleLock lock2(*(hEvent->m_hMutex));
-- hEvent->m_bEventSet = false;
-- }
--
-- if (hEvent->m_bManualEvent == true)
-- hEvent->m_hCond->notifyAll();
-- else
-- hEvent->m_hCond->notify();
--
-- return true;
--}
--
-diff --git a/xbmc/linux/XEventUtils.h b/xbmc/linux/XEventUtils.h
-deleted file mode 100644
-index a77f843..0000000
---- a/xbmc/linux/XEventUtils.h
-+++ /dev/null
-@@ -1,38 +0,0 @@
--#ifndef __X_EVENT_UTIL_H__
--#define __X_EVENT_UTIL_H__
--
--/*
-- * Copyright (C) 2005-2008 Team XBMC
-- * http://www.xbmc.org
-- *
-- * This Program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This Program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with XBMC; see the file COPYING. If not, write to
-- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-- * http://www.gnu.org/copyleft/gpl.html
-- *
-- */
--
--#include "XHandlePublic.h"
--
--#ifdef _LINUX
--
--HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName);
--bool WINAPI SetEvent(HANDLE hEvent);
--bool WINAPI ResetEvent(HANDLE hEvent);
--bool WINAPI PulseEvent(HANDLE hEvent);
--
--#endif
--
--
--#endif
--
-diff --git a/xbmc/linux/XHandle.cpp b/xbmc/linux/XHandle.cpp
-index 61520b2..52f540a 100644
---- a/xbmc/linux/XHandle.cpp
-+++ b/xbmc/linux/XHandle.cpp
-@@ -20,12 +20,15 @@
- */
-
- #include "XHandle.h"
--#include "XThreadUtils.h"
- #include "utils/log.h"
- #include "threads/SingleLock.h"
-
- int CXHandle::m_objectTracker[10] = {0};
-
-+HANDLE WINAPI GetCurrentProcess(void) {
-+ return (HANDLE)-1; // -1 a special value - pseudo handle
-+}
-+
- CXHandle::CXHandle()
- {
- Init();
-@@ -47,11 +50,6 @@ CXHandle::CXHandle(const CXHandle &src)
-
- Init();
-
-- if (m_threadValid)
-- {
-- CLog::Log(LOGERROR, "%s - thread handle copied instead of passed!", __FUNCTION__);
-- }
--
- if (src.m_hMutex)
- m_hMutex = new CCriticalSection();
-
-@@ -80,7 +78,7 @@ CXHandle::~CXHandle()
- CLog::Log(LOGERROR,"%s, destroying handle with ref count %d", __FUNCTION__, m_nRefCount);
- assert(false);
- }
--
-+
- if (m_hMutex) {
- delete m_hMutex;
- }
-@@ -93,10 +91,6 @@ CXHandle::~CXHandle()
- delete m_hCond;
- }
-
-- if (m_threadValid) {
-- pthread_join(m_hThread, NULL);
-- }
--
- if ( fd != 0 ) {
- close(fd);
- }
-@@ -107,11 +101,9 @@ void CXHandle::Init()
- {
- fd=0;
- m_hMutex=NULL;
-- m_threadValid=false;
- m_hCond=NULL;
- m_type = HND_NULL;
- RecursionCount=0;
-- OwningThread=0;
- m_bManualEvent=FALSE;
- m_bEventSet=FALSE;
- m_nFindFileIterator=0 ;
-diff --git a/xbmc/linux/XHandle.h b/xbmc/linux/XHandle.h
-index 0e119bc..dd7f37d 100644
---- a/xbmc/linux/XHandle.h
-+++ b/xbmc/linux/XHandle.h
-@@ -25,7 +25,6 @@
- #ifndef _WIN32
-
- #include
--#include
-
- #include "PlatformDefs.h"
- #include "XHandlePublic.h"
-@@ -36,7 +35,7 @@
- struct CXHandle {
-
- public:
-- typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_THREAD, HND_FIND_FILE } HandleType;
-+ typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_FIND_FILE } HandleType;
-
- CXHandle();
- CXHandle(HandleType nType);
-@@ -47,8 +46,6 @@ public:
- inline HandleType GetType() { return m_type; }
- void ChangeType(HandleType newType);
-
-- ThreadIdentifier m_hThread;
-- bool m_threadValid;
- XbmcThreads::ConditionVariable *m_hCond;
- std::list m_hParents;
-
-@@ -62,7 +59,6 @@ public:
- // simulate mutex and critical section
- CCriticalSection *m_hMutex;
- int RecursionCount; // for mutex - for compatibility with WIN32 critical section
-- pthread_t OwningThread;
- int fd;
- bool m_bManualEvent;
- time_t m_tmCreation;
-diff --git a/xbmc/linux/XMemUtils.cpp b/xbmc/linux/XMemUtils.cpp
-index 906fe4e..c0006fe 100644
---- a/xbmc/linux/XMemUtils.cpp
-+++ b/xbmc/linux/XMemUtils.cpp
-@@ -25,6 +25,10 @@
-
- #include "XMemUtils.h"
-
-+#ifdef __APPLE__
-+#include
-+#endif
-+
- #undef ALIGN
- #define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
-
-@@ -49,4 +53,130 @@ void _aligned_free(void *p) {
- free(pFull);
- }
-
-+#ifndef _WIN32
-+
-+#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__)
-+static FILE* procMeminfoFP = NULL;
-+#endif
-+
-+void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
-+{
-+ if (!lpBuffer)
-+ return;
-+
-+ memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
-+
-+#ifdef __APPLE__
-+ uint64_t physmem;
-+ size_t len = sizeof physmem;
-+ int mib[2] = { CTL_HW, HW_MEMSIZE };
-+ size_t miblen = sizeof(mib) / sizeof(mib[0]);
-+
-+ // Total physical memory.
-+ if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
-+ lpBuffer->ullTotalPhys = physmem;
-+
-+ // Virtual memory.
-+ mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
-+ struct xsw_usage swap;
-+ len = sizeof(struct xsw_usage);
-+ if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
-+ {
-+ lpBuffer->ullAvailPageFile = swap.xsu_avail;
-+ lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
-+ }
-+
-+ // In use.
-+ mach_port_t stat_port = mach_host_self();
-+ vm_statistics_data_t vm_stat;
-+ mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
-+ if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
-+ {
-+ // Find page size.
-+ int pageSize;
-+ mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
-+ len = sizeof(int);
-+ if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
-+ {
-+ uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
-+
-+ lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
-+ lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
-+ }
-+ }
-+#elif defined(__FreeBSD__)
-+ /* sysctl hw.physmem */
-+ size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
-+ size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
-+
-+ /* physmem */
-+ len = sizeof(physmem);
-+ if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
-+ lpBuffer->ullTotalPhys = physmem;
-+ lpBuffer->ullTotalVirtual = physmem;
-+ }
-+ /* pagesize */
-+ len = sizeof(pagesize);
-+ if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
-+ pagesize = 4096;
-+ /* mem_inactive */
-+ len = sizeof(mem_inactive);
-+ if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
-+ mem_inactive *= pagesize;
-+ /* mem_cache */
-+ len = sizeof(mem_cache);
-+ if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
-+ mem_cache *= pagesize;
-+ /* mem_free */
-+ len = sizeof(mem_free);
-+ if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
-+ mem_free *= pagesize;
-+
-+ /* mem_avail = mem_inactive + mem_cache + mem_free */
-+ lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
-+ lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
-+
-+ if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
-+ lpBuffer->ullAvailPageFile = swap_free * pagesize;
-+#else
-+ struct sysinfo info;
-+ char name[32];
-+ unsigned val;
-+ if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
-+ sysinfo(&info);
-+ else
-+ {
-+ memset(&info, 0, sizeof(struct sysinfo));
-+ info.mem_unit = 4096;
-+ while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
-+ {
-+ if (strncmp("MemTotal:", name, 9) == 0)
-+ info.totalram = val/4;
-+ else if (strncmp("MemFree:", name, 8) == 0)
-+ info.freeram = val/4;
-+ else if (strncmp("Buffers:", name, 8) == 0)
-+ info.bufferram += val/4;
-+ else if (strncmp("Cached:", name, 7) == 0)
-+ info.bufferram += val/4;
-+ else if (strncmp("SwapTotal:", name, 10) == 0)
-+ info.totalswap = val/4;
-+ else if (strncmp("SwapFree:", name, 9) == 0)
-+ info.freeswap = val/4;
-+ else if (strncmp("HighTotal:", name, 10) == 0)
-+ info.totalhigh = val/4;
-+ else if (strncmp("HighFree:", name, 9) == 0)
-+ info.freehigh = val/4;
-+ }
-+ rewind(procMeminfoFP);
-+ fflush(procMeminfoFP);
-+ }
-+ lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
-+ lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
-+ lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
-+ lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
-+ lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);
-+#endif
-+}
-+
-+#endif
-
-diff --git a/xbmc/linux/XMemUtils.h b/xbmc/linux/XMemUtils.h
-index d6d314a..83fc95d 100644
---- a/xbmc/linux/XMemUtils.h
-+++ b/xbmc/linux/XMemUtils.h
-@@ -22,10 +22,14 @@
- *
- */
-
-+#include "linux/PlatformDefs.h"
-+
- // aligned memory allocation and free. memory returned will be aligned to "alignTo" bytes.
- // this is a linux (actually platfom free) implementation of the win32 CRT methods _aligned_malloc and _aligned_free.
- void *_aligned_malloc(size_t s, size_t alignTo);
- void _aligned_free(void *p) ;
-
-+void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer);
-+
- #endif
-
-diff --git a/xbmc/linux/XSyncUtils.cpp b/xbmc/linux/XSyncUtils.cpp
-deleted file mode 100644
-index 19c4b5a..0000000
---- a/xbmc/linux/XSyncUtils.cpp
-+++ /dev/null
-@@ -1,169 +0,0 @@
--/*
-- * Copyright (C) 2005-2008 Team XBMC
-- * http://www.xbmc.org
-- *
-- * This Program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This Program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with XBMC; see the file COPYING. If not, write to
-- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-- * http://www.gnu.org/copyleft/gpl.html
-- *
-- */
--
--#ifndef _WIN32
--
--
--#include
--#include
--#include
--#include
--#include
--#ifdef __APPLE__
--#include
--#endif
--
--#include "XSyncUtils.h"
--#include "XTimeUtils.h"
--#include "PlatformDefs.h"
--#include "XHandle.h"
--#include "XEventUtils.h"
--
--using namespace std;
--using namespace XbmcThreads;
--
--#include "../utils/log.h"
--#include "../utils/TimeUtils.h"
--
--#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__)
--static FILE* procMeminfoFP = NULL;
--#endif
--
--void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
--{
-- if (!lpBuffer)
-- return;
--
-- memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
--
--#ifdef __APPLE__
-- uint64_t physmem;
-- size_t len = sizeof physmem;
-- int mib[2] = { CTL_HW, HW_MEMSIZE };
-- size_t miblen = sizeof(mib) / sizeof(mib[0]);
--
-- // Total physical memory.
-- if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
-- lpBuffer->ullTotalPhys = physmem;
--
-- // Virtual memory.
-- mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
-- struct xsw_usage swap;
-- len = sizeof(struct xsw_usage);
-- if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
-- {
-- lpBuffer->ullAvailPageFile = swap.xsu_avail;
-- lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
-- }
--
-- // In use.
-- mach_port_t stat_port = mach_host_self();
-- vm_statistics_data_t vm_stat;
-- mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
-- if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
-- {
-- // Find page size.
-- int pageSize;
-- mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
-- len = sizeof(int);
-- if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
-- {
-- uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
--
-- lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
-- lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
-- }
-- }
--#elif defined(__FreeBSD__)
-- /* sysctl hw.physmem */
-- size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
-- size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
--
-- /* physmem */
-- len = sizeof(physmem);
-- if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
-- lpBuffer->ullTotalPhys = physmem;
-- lpBuffer->ullTotalVirtual = physmem;
-- }
-- /* pagesize */
-- len = sizeof(pagesize);
-- if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
-- pagesize = 4096;
-- /* mem_inactive */
-- len = sizeof(mem_inactive);
-- if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
-- mem_inactive *= pagesize;
-- /* mem_cache */
-- len = sizeof(mem_cache);
-- if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
-- mem_cache *= pagesize;
-- /* mem_free */
-- len = sizeof(mem_free);
-- if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
-- mem_free *= pagesize;
--
-- /* mem_avail = mem_inactive + mem_cache + mem_free */
-- lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
-- lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
--
-- if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
-- lpBuffer->ullAvailPageFile = swap_free * pagesize;
--#else
-- struct sysinfo info;
-- char name[32];
-- unsigned val;
-- if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
-- sysinfo(&info);
-- else
-- {
-- memset(&info, 0, sizeof(struct sysinfo));
-- info.mem_unit = 4096;
-- while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
-- {
-- if (strncmp("MemTotal:", name, 9) == 0)
-- info.totalram = val/4;
-- else if (strncmp("MemFree:", name, 8) == 0)
-- info.freeram = val/4;
-- else if (strncmp("Buffers:", name, 8) == 0)
-- info.bufferram += val/4;
-- else if (strncmp("Cached:", name, 7) == 0)
-- info.bufferram += val/4;
-- else if (strncmp("SwapTotal:", name, 10) == 0)
-- info.totalswap = val/4;
-- else if (strncmp("SwapFree:", name, 9) == 0)
-- info.freeswap = val/4;
-- else if (strncmp("HighTotal:", name, 10) == 0)
-- info.totalhigh = val/4;
-- else if (strncmp("HighFree:", name, 9) == 0)
-- info.freehigh = val/4;
-- }
-- rewind(procMeminfoFP);
-- fflush(procMeminfoFP);
-- }
-- lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
-- lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
-- lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
-- lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
-- lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);
--#endif
--}
--
--#endif
-diff --git a/xbmc/linux/XSyncUtils.h b/xbmc/linux/XSyncUtils.h
-deleted file mode 100644
-index f3ad36f..0000000
---- a/xbmc/linux/XSyncUtils.h
-+++ /dev/null
-@@ -1,44 +0,0 @@
--#ifndef __X_SYNC_UTILS_
--#define __X_SYNC_UTILS_
--
--/*
-- * Copyright (C) 2005-2008 Team XBMC
-- * http://www.xbmc.org
-- *
-- * This Program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This Program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with XBMC; see the file COPYING. If not, write to
-- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-- * http://www.gnu.org/copyleft/gpl.html
-- *
-- */
--
--#include "PlatformDefs.h"
--#include "XHandlePublic.h"
--
--#ifdef _LINUX
--
--#define STATUS_WAIT_0 ((DWORD )0x00000000L)
--#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
--#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
--#define WAIT_TIMEOUT 258L
--#define INFINITE 0xFFFFFFFF
--#define STATUS_ABANDONED_WAIT_0 0x00000080
--#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
--#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
--
--void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer);
--
--#endif
--
--#endif
--
-diff --git a/xbmc/linux/XThreadUtils.cpp b/xbmc/linux/XThreadUtils.cpp
-deleted file mode 100644
-index 9d68481..0000000
---- a/xbmc/linux/XThreadUtils.cpp
-+++ /dev/null
-@@ -1,210 +0,0 @@
--/*
-- * Copyright (C) 2005-2009 Team XBMC
-- * http://www.xbmc.org
-- *
-- * This Program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This Program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with XBMC; see the file COPYING. If not, write to
-- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-- * http://www.gnu.org/copyleft/gpl.html
-- *
-- */
--
--#include "PlatformDefs.h"
--#include "XHandle.h"
--#include "XThreadUtils.h"
--#include "XTimeUtils.h"
--#include "XEventUtils.h"
--#include "system.h"
--#include "utils/log.h"
--
--#ifdef _LINUX
--#include
--#include
--#include
--
--HANDLE WINAPI CreateThread(
-- LPSECURITY_ATTRIBUTES lpThreadAttributes,
-- SIZE_T dwStackSize,
-- LPTHREAD_START_ROUTINE lpStartAddress,
-- LPVOID lpParameter,
-- DWORD dwCreationFlags,
-- LPDWORD lpThreadId
-- ) {
--
-- // a thread handle would actually contain an event
-- // the event would mark if the thread is running or not. it will be used in the Wait functions.
-- HANDLE h = CreateEvent(NULL, TRUE, FALSE, NULL);
-- h->ChangeType(CXHandle::HND_THREAD);
--#ifdef __APPLE__
-- h->m_machThreadPort = MACH_PORT_NULL;
--#endif
-- pthread_attr_t attr;
-- pthread_attr_init(&attr);
-- if (dwStackSize > PTHREAD_STACK_MIN)
-- pthread_attr_setstacksize(&attr, dwStackSize);
-- if (pthread_create(&(h->m_hThread), &attr, (void*(*)(void*))lpStartAddress, lpParameter) == 0)
-- h->m_threadValid = true;
-- else
-- {
-- CloseHandle(h);
-- h = NULL;
-- }
-- pthread_attr_destroy(&attr);
--
-- if (h && lpThreadId)
-- // WARNING: This can truncate thread IDs on x86_64.
-- *lpThreadId = (DWORD)h->m_hThread;
-- return h;
--}
--
--
--#if 0 // Deprecated, use CThread::GetCurrentThreadId() instead
--DWORD WINAPI GetCurrentThreadId(void) {
-- // WARNING: This can truncate thread IDs on x86_64.
-- return (DWORD)pthread_self();
--}
--#endif
--
--HANDLE WINAPI GetCurrentThread(void) {
-- return (HANDLE)-1; // -1 a special value - pseudo handle
--}
--
--HANDLE WINAPI GetCurrentProcess(void) {
-- return (HANDLE)-1; // -1 a special value - pseudo handle
--}
--
--HANDLE _beginthreadex(
-- void *security,
-- unsigned stack_size,
-- int ( *start_address )( void * ),
-- void *arglist,
-- unsigned initflag,
-- unsigned *thrdaddr
--) {
--
-- HANDLE h = CreateThread(NULL, stack_size, start_address, arglist, initflag, (LPDWORD)thrdaddr);
-- return h;
--
--}
--
--uintptr_t _beginthread(
-- void( *start_address )( void * ),
-- unsigned stack_size,
-- void *arglist
--) {
-- HANDLE h = CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)start_address, arglist, 0, NULL);
-- return (uintptr_t)h;
--}
--
--BOOL WINAPI GetThreadTimes (
-- HANDLE hThread,
-- LPFILETIME lpCreationTime,
-- LPFILETIME lpExitTime,
-- LPFILETIME lpKernelTime,
-- LPFILETIME lpUserTime
--) {
-- if (!hThread)
-- return false;
-- if (!hThread->m_threadValid)
-- return false;
--
-- if (hThread == (HANDLE)-1) {
-- if (lpCreationTime)
-- TimeTToFileTime(0,lpCreationTime);
-- if (lpExitTime)
-- TimeTToFileTime(time(NULL),lpExitTime);
-- if (lpKernelTime)
-- TimeTToFileTime(0,lpKernelTime);
-- if (lpUserTime)
-- TimeTToFileTime(0,lpUserTime);
--
-- return true;
-- }
--
-- if (lpCreationTime)
-- TimeTToFileTime(hThread->m_tmCreation,lpCreationTime);
-- if (lpExitTime)
-- TimeTToFileTime(time(NULL),lpExitTime);
-- if (lpKernelTime)
-- TimeTToFileTime(0,lpKernelTime);
--
--#ifdef __APPLE__
-- thread_info_data_t threadInfo;
-- mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX;
--
-- if (hThread->m_machThreadPort == MACH_PORT_NULL)
-- hThread->m_machThreadPort = pthread_mach_thread_np(hThread->m_hThread);
--
-- kern_return_t ret = thread_info(hThread->m_machThreadPort, THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount);
-- if (ret == KERN_SUCCESS)
-- {
-- thread_basic_info_t threadBasicInfo = (thread_basic_info_t)threadInfo;
--
-- if (lpUserTime)
-- {
-- // User time.
-- unsigned long long time = ((__int64)threadBasicInfo->user_time.seconds * 10000000L) + threadBasicInfo->user_time.microseconds*10L;
-- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF);
-- lpUserTime->dwHighDateTime = (time >> 32);
-- }
--
-- if (lpKernelTime)
-- {
-- // System time.
-- unsigned long long time = ((__int64)threadBasicInfo->system_time.seconds * 10000000L) + threadBasicInfo->system_time.microseconds*10L;
-- lpKernelTime->dwLowDateTime = (time & 0xFFFFFFFF);
-- lpKernelTime->dwHighDateTime = (time >> 32);
-- }
-- }
-- else
-- {
-- if (lpUserTime)
-- lpUserTime->dwLowDateTime = lpUserTime->dwHighDateTime = 0;
--
-- if (lpKernelTime)
-- lpKernelTime->dwLowDateTime = lpKernelTime->dwHighDateTime = 0;
-- }
--#elif _POSIX_THREAD_CPUTIME != -1
-- if(lpUserTime)
-- {
-- lpUserTime->dwLowDateTime = 0;
-- lpUserTime->dwHighDateTime = 0;
-- clockid_t clock;
-- if (pthread_getcpuclockid(hThread->m_hThread, &clock) == 0)
-- {
-- struct timespec tp = {};
-- clock_gettime(clock, &tp);
-- unsigned long long time = (unsigned long long)tp.tv_sec * 10000000 + (unsigned long long)tp.tv_nsec/100;
-- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF);
-- lpUserTime->dwHighDateTime = (time >> 32);
-- }
-- }
--#else
-- if (lpUserTime)
-- TimeTToFileTime(0,lpUserTime);
--#endif
-- return true;
--}
--
--BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority)
--{
-- return true;
--}
--
--int GetThreadPriority(HANDLE hThread)
--{
-- return 0;
--}
--
--#endif
--
-diff --git a/xbmc/music/LastFmManager.cpp b/xbmc/music/LastFmManager.cpp
-index 700f28a..b97fdf2 100644
---- a/xbmc/music/LastFmManager.cpp
-+++ b/xbmc/music/LastFmManager.cpp
-@@ -70,7 +70,7 @@ using namespace XFILE;
-
- CLastFmManager* CLastFmManager::m_pInstance=NULL;
-
--CLastFmManager::CLastFmManager()
-+CLastFmManager::CLastFmManager() : CThread("CLastFmManager")
- {
- m_RadioTrackQueue = new CPlayList;
- }
-@@ -534,7 +534,7 @@ void CLastFmManager::Update()
- if (iNrCachedTracks == 0)
- {
- //get more tracks
-- if (ThreadHandle() != NULL)
-+ if (IsRunning())
- {
- m_hWorkerEvent.Set();
- }
-@@ -633,7 +633,7 @@ void CLastFmManager::StopRadio(bool bKillSession /*= true*/)
- {
- m_RadioSession = "";
- }
-- if (m_ThreadHandle)
-+ if (IsRunning())
- {
- m_bStop = true;
- m_hWorkerEvent.Set();
-diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp
-index 3400f27..445edaf 100644
---- a/xbmc/music/infoscanner/MusicInfoScanner.cpp
-+++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp
-@@ -57,7 +57,7 @@ using namespace MUSIC_INFO;
- using namespace XFILE;
- using namespace MUSIC_GRABBER;
-
--CMusicInfoScanner::CMusicInfoScanner()
-+CMusicInfoScanner::CMusicInfoScanner() : CThread("CMusicInfoScanner")
- {
- m_bRunning = false;
- m_pObserver = NULL;
-@@ -99,7 +99,7 @@ void CMusicInfoScanner::Process()
-
- // Create the thread to count all files to be scanned
- SetPriority( GetMinPriority() );
-- CThread fileCountReader(this);
-+ CThread fileCountReader(this, "CMusicInfoScanner");
- if (m_pObserver)
- fileCountReader.Create();
-
-diff --git a/xbmc/music/infoscanner/MusicInfoScraper.cpp b/xbmc/music/infoscanner/MusicInfoScraper.cpp
-index 09aeb14..aad726c 100644
---- a/xbmc/music/infoscanner/MusicInfoScraper.cpp
-+++ b/xbmc/music/infoscanner/MusicInfoScraper.cpp
-@@ -28,7 +28,7 @@ using namespace MUSIC_GRABBER;
- using namespace ADDON;
- using namespace std;
-
--CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper)
-+CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper) : CThread("CMusicInfoScraper")
- {
- m_bSucceeded=false;
- m_bCanceled=false;
-diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp
-index 7388997..1ba7871 100644
---- a/xbmc/network/AirPlayServer.cpp
-+++ b/xbmc/network/AirPlayServer.cpp
-@@ -184,7 +184,7 @@ void CAirPlayServer::StopServer(bool bWait)
- }
- }
-
--CAirPlayServer::CAirPlayServer(int port, bool nonlocal)
-+CAirPlayServer::CAirPlayServer(int port, bool nonlocal) : CThread("AirPlayServer")
- {
- m_port = port;
- m_nonlocal = nonlocal;
-diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp
-index f092bb4..8cafa8e 100644
---- a/xbmc/network/AirTunesServer.cpp
-+++ b/xbmc/network/AirTunesServer.cpp
-@@ -292,7 +292,7 @@ void CAirTunesServer::StopServer(bool bWait)
- }
- }
-
--CAirTunesServer::CAirTunesServer(int port, bool nonlocal)
-+CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("CAirTunesServer")
- {
- m_port = port;
- m_pLibShairport = new DllLibShairport();
-diff --git a/xbmc/network/Network.h b/xbmc/network/Network.h
-index cb0ea52..e514e05 100644
---- a/xbmc/network/Network.h
-+++ b/xbmc/network/Network.h
-@@ -24,6 +24,7 @@
-
- #include
- #include "utils/StdString.h"
-+#include "system.h"
-
- enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 };
- enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 };
-diff --git a/xbmc/network/TCPServer.cpp b/xbmc/network/TCPServer.cpp
-index 4b0d9ad..fd46236 100644
---- a/xbmc/network/TCPServer.cpp
-+++ b/xbmc/network/TCPServer.cpp
-@@ -85,7 +85,7 @@ void CTCPServer::StopServer(bool bWait)
- }
- }
-
--CTCPServer::CTCPServer(int port, bool nonlocal)
-+CTCPServer::CTCPServer(int port, bool nonlocal) : CThread("CTCPServer")
- {
- m_port = port;
- m_nonlocal = nonlocal;
-diff --git a/xbmc/network/UdpClient.cpp b/xbmc/network/UdpClient.cpp
-index 8e1ef2e..8f49ce8 100644
---- a/xbmc/network/UdpClient.cpp
-+++ b/xbmc/network/UdpClient.cpp
-@@ -35,7 +35,7 @@
-
- #define UDPCLIENT_DEBUG_LEVEL LOGDEBUG
-
--CUdpClient::CUdpClient(void) : CThread()
-+CUdpClient::CUdpClient(void) : CThread("CUdpClient")
- {}
-
- CUdpClient::~CUdpClient(void)
-diff --git a/xbmc/network/UdpClient.h b/xbmc/network/UdpClient.h
-index 97acb28..a1aa597 100644
---- a/xbmc/network/UdpClient.h
-+++ b/xbmc/network/UdpClient.h
-@@ -25,6 +25,7 @@
- #include "threads/CriticalSection.h"
- #include
- #include
-+#include "system.h"
-
- class CUdpClient : CThread
- {
-diff --git a/xbmc/network/libscrobbler/scrobbler.cpp b/xbmc/network/libscrobbler/scrobbler.cpp
-index cb08d1b..cf5f927 100644
---- a/xbmc/network/libscrobbler/scrobbler.cpp
-+++ b/xbmc/network/libscrobbler/scrobbler.cpp
-@@ -46,7 +46,7 @@
- #define SCROBBLER_ACTION_NOWPLAYING 2
-
- CScrobbler::CScrobbler(const CStdString &strHandshakeURL, const CStdString &strLogPrefix)
-- : CThread()
-+ : CThread("CScrobbler")
- {
- m_bBanned = false;
- m_bBadAuth = false;
-@@ -67,7 +67,7 @@ void CScrobbler::Init()
- ResetState();
- LoadCredentials();
- LoadJournal();
-- if (!ThreadHandle())
-+ if (!IsRunning())
- Create();
- }
-
-diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp
-index 3868cc7..ffd78d2 100644
---- a/xbmc/peripherals/Peripherals.cpp
-+++ b/xbmc/peripherals/Peripherals.cpp
-@@ -19,6 +19,7 @@
- *
- */
-
-+#include "system.h"
- #include "Peripherals.h"
- #include "bus/PeripheralBus.h"
- #include "devices/PeripheralBluetooth.h"
-diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp
-index a762031..beb7d28 100644
---- a/xbmc/pictures/GUIWindowSlideShow.cpp
-+++ b/xbmc/pictures/GUIWindowSlideShow.cpp
-@@ -67,7 +67,7 @@ using namespace XFILE;
-
- static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f };
-
--CBackgroundPicLoader::CBackgroundPicLoader()
-+CBackgroundPicLoader::CBackgroundPicLoader() : CThread("CBackgroundPicLoader")
- {
- m_pCallback = NULL;
- m_isLoading = false;
-diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp
-index 938cb36..ed92a41 100644
---- a/xbmc/rendering/dx/RenderSystemDX.cpp
-+++ b/xbmc/rendering/dx/RenderSystemDX.cpp
-@@ -569,7 +569,7 @@ bool CRenderSystemDX::PresentRenderImpl(const CDirtyRegionList &dirty)
-
- //CVideoReferenceClock polls GetRasterStatus too,
- //polling it from two threads at the same time is bad
-- if (g_advancedSettings.m_sleepBeforeFlip > 0 && g_VideoReferenceClock.ThreadHandle() == NULL)
-+ if (g_advancedSettings.m_sleepBeforeFlip > 0 && !g_VideoReferenceClock.IsRunning())
- {
- //save current thread priority and set thread priority to THREAD_PRIORITY_TIME_CRITICAL
- int priority = GetThreadPriority(GetCurrentThread());
-diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp
-index 231c715..083947d 100644
---- a/xbmc/settings/GUISettings.cpp
-+++ b/xbmc/settings/GUISettings.cpp
-@@ -592,6 +592,10 @@ void CGUISettings::Initialize()
- #ifdef HAVE_LIBVA
- AddBool(vp, "videoplayer.usevaapi", 13426, true);
- #endif
-+#ifdef HAVE_LIBXVBA
-+ AddBool(vp, "videoplayer.usexvba", 13433, true);
-+ AddBool(vp, "videoplayer.usexvbasharedsurface", 13434, true);
-+#endif
- #ifdef HAS_DX
- AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false);
- #endif
-diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp
-index dc26188..1a259a6 100644
---- a/xbmc/settings/GUIWindowSettingsCategory.cpp
-+++ b/xbmc/settings/GUIWindowSettingsCategory.cpp
-@@ -936,6 +936,15 @@ void CGUIWindowSettingsCategory::UpdateSettings()
- pControl->SetEnabled(enabled);
- }
- }
-+ else if (strSetting.Equals("videoplayer.usexvbasharedsurface"))
-+ {
-+ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
-+ if (pControl)
-+ {
-+ bool enabled = (g_guiSettings.GetBool("videoplayer.usexvba"));
-+ pControl->SetEnabled(enabled);
-+ }
-+ }
- else if (strSetting.Equals("weather.addonsettings"))
- {
- AddonPtr addon;
-diff --git a/xbmc/threads/Thread.cpp b/xbmc/threads/Thread.cpp
-index bd213e2..3e228df 100644
---- a/xbmc/threads/Thread.cpp
-+++ b/xbmc/threads/Thread.cpp
-@@ -20,41 +20,27 @@
-
- #include "threads/SystemClock.h"
- #include "Thread.h"
--#ifndef _LINUX
--#include
--#include "utils/win32exception.h"
--#ifndef _MT
--#pragma message( "Please compile using multithreaded run-time libraries" )
--#endif
--typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter);
--#else
--#include "PlatformInclude.h"
--#include "XHandle.h"
--#include
--typedef int (*PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter);
--#endif
--
--#if defined(__GNUC__) && !defined(__clang__)
--#include
--using namespace __cxxabiv1;
--#endif
--
- #include "utils/log.h"
- #include "utils/TimeUtils.h"
- #include "threads/ThreadLocal.h"
-
-+#define __STDC_FORMAT_MACROS
-+#include
-+
- static XbmcThreads::ThreadLocal currentThread;
-
-+#include "threads/platform/ThreadImpl.cpp"
-+
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
--CThread::CThread(const char* ThreadName) : m_StopEvent(true,true)
-+CThread::CThread(const char* ThreadName)
-+: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true)
- {
- m_bStop = false;
-
- m_bAutoDelete = false;
-- m_ThreadHandle = NULL;
- m_ThreadId = 0;
- m_iLastTime = 0;
- m_iLastUsage = 0;
-@@ -66,12 +52,12 @@ CThread::CThread(const char* ThreadName) : m_StopEvent(true,true)
- m_ThreadName = ThreadName;
- }
-
--CThread::CThread(IRunnable* pRunnable, const char* ThreadName) : m_StopEvent(true,true)
-+CThread::CThread(IRunnable* pRunnable, const char* ThreadName)
-+: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true)
- {
- m_bStop = false;
-
- m_bAutoDelete = false;
-- m_ThreadHandle = NULL;
- m_ThreadId = 0;
- m_iLastTime = 0;
- m_iLastUsage = 0;
-@@ -85,171 +71,62 @@ CThread::CThread(IRunnable* pRunnable, const char* ThreadName) : m_StopEvent(tru
-
- CThread::~CThread()
- {
-- if (m_ThreadHandle != NULL)
-- {
-- CloseHandle(m_ThreadHandle);
-- }
-- m_ThreadHandle = NULL;
--
-+ StopThread();
- }
-
--#ifndef _WIN32
--void CThread::term_handler (int signum)
-+bool CThread::IsRunning()
- {
-- CLog::Log(LOGERROR,"thread 0x%lx (%lu) got signal %d. calling OnException and terminating thread abnormally.", (long unsigned int)pthread_self(), (long unsigned int)pthread_self(), signum);
--
-- CThread* curThread = currentThread.get();
-- if (curThread)
-- {
-- curThread->m_bStop = TRUE;
-- curThread->m_StopEvent.Set();
--
-- curThread->OnException();
-- if( curThread->IsAutoDelete() )
-- delete curThread;
-- }
--
-- pthread_exit(NULL);
-+ return m_ThreadId ? true : false;
- }
-
--int CThread::staticThread(void* data)
--#else
--DWORD WINAPI CThread::staticThread(LPVOID* data)
--#endif
-+THREADFUNC CThread::staticThread(void* data)
- {
- CThread* pThread = (CThread*)(data);
-+ std::string name;
-+ ThreadIdentifier id;
-+ bool autodelete;
-+
- if (!pThread) {
- CLog::Log(LOGERROR,"%s, sanity failed. thread is NULL.",__FUNCTION__);
- return 1;
- }
-
-- if (pThread->m_ThreadName.empty())
-- pThread->m_ThreadName = pThread->GetTypeName();
-- pThread->SetDebugCallStackName(pThread->m_ThreadName.c_str());
-+ name = pThread->m_ThreadName;
-+ id = pThread->m_ThreadId;
-+ autodelete = pThread->m_bAutoDelete;
-
-- CLog::Log(LOGDEBUG,"Thread %s start, auto delete: %d", pThread->m_ThreadName.c_str(), pThread->IsAutoDelete());
-+ pThread->SetThreadInfo();
-+
-+ CLog::Log(LOGNOTICE,"Thread %s start, auto delete: %s", name.c_str(), (autodelete ? "true" : "false"));
-
- currentThread.set(pThread);
--#ifndef _LINUX
-- /* install win32 exception translator */
-- win32_exception::install_handler();
--#else
-- struct sigaction action;
-- action.sa_handler = term_handler;
-- sigemptyset (&action.sa_mask);
-- action.sa_flags = 0;
-- //sigaction (SIGABRT, &action, NULL);
-- //sigaction (SIGSEGV, &action, NULL);
--#endif
--
--
-- try
-- {
-- pThread->OnStartup();
-- }
--#ifndef _LINUX
-- catch (const win32_exception &e)
-- {
-- e.writelog(__FUNCTION__);
-- if( pThread->IsAutoDelete() )
-- {
-- delete pThread;
-- _endthreadex(123);
-- return 0;
-- }
-- }
--#endif
-- catch(...)
-- {
-- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread startup, aborting. auto delete: %d", __FUNCTION__, pThread->m_ThreadName.c_str(), pThread->IsAutoDelete());
-- if( pThread->IsAutoDelete() )
-- {
-- delete pThread;
--#ifndef _LINUX
-- _endthreadex(123);
--#endif
-- return 0;
-- }
-- }
-+ pThread->m_StartEvent.Set();
-
-- try
-- {
-- pThread->Process();
-- }
--#ifndef _LINUX
-- catch (const access_violation &e)
-- {
-- e.writelog(__FUNCTION__);
-- }
-- catch (const win32_exception &e)
-- {
-- e.writelog(__FUNCTION__);
-- }
--#endif
-- catch(...)
-- {
-- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread process, attemping cleanup in OnExit", __FUNCTION__, pThread->m_ThreadName.c_str());
-- }
-+ pThread->OnStartup();
-+ pThread->Process();
-+ pThread->OnExit();
-
-- try
-- {
-- pThread->OnExit();
-- }
--#ifndef _LINUX
-- catch (const access_violation &e)
-- {
-- e.writelog(__FUNCTION__);
-- }
-- catch (const win32_exception &e)
-- {
-- e.writelog(__FUNCTION__);
-- }
--#endif
-- catch(...)
-- {
-- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread exit", __FUNCTION__, pThread->m_ThreadName.c_str());
-- }
-+ // lock during termination
-+ CSingleLock lock(pThread->m_CriticalSection);
-+
-+ pThread->m_ThreadId = 0;
-+ pThread->m_TermEvent.Set();
-+ pThread->TermHandler();
-
-- if ( pThread->IsAutoDelete() )
-+ lock.Leave();
-+
-+ if (autodelete)
- {
-- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId());
-+ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", name.c_str(), (uint64_t)id);
- delete pThread;
- pThread = NULL;
- }
- else
-- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId());
--
--// DXMERGE - this looks like it might have used to have been useful for something...
--// g_graphicsContext.DeleteThreadContext();
-+ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", name.c_str(), (uint64_t)id);
-
--#ifndef _LINUX
-- _endthreadex(123);
--#endif
- return 0;
- }
-
--void CThread::Create(bool bAutoDelete, unsigned stacksize)
--{
-- if (m_ThreadHandle != NULL)
-- {
-- throw 1; //ERROR should not b possible!!!
-- }
-- m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
-- m_iLastUsage = 0;
-- m_fLastUsage = 0.0f;
-- m_bAutoDelete = bAutoDelete;
-- m_bStop = false;
-- m_StopEvent.Reset();
--
-- m_ThreadHandle = (HANDLE)_beginthreadex(NULL, stacksize, (PBEGINTHREADEX_THREADFUNC)staticThread, (void*)this, 0, &m_ThreadId);
--
--#ifdef _LINUX
-- if (m_ThreadHandle && m_ThreadHandle->m_threadValid && m_bAutoDelete)
-- // FIXME: WinAPI can truncate 64bit pthread ids
-- pthread_detach(m_ThreadHandle->m_hThread);
--#endif
--}
--
- bool CThread::IsAutoDelete() const
- {
- return m_bAutoDelete;
-@@ -259,213 +136,17 @@ void CThread::StopThread(bool bWait /*= true*/)
- {
- m_bStop = true;
- m_StopEvent.Set();
-- if (m_ThreadHandle && bWait)
-+ CSingleLock lock(m_CriticalSection);
-+ if (m_ThreadId && bWait)
- {
-- WaitForThreadExit(INFINITE);
-- CloseHandle(m_ThreadHandle);
-- m_ThreadHandle = NULL;
-+ lock.Leave();
-+ WaitForThreadExit(0xFFFFFFFF);
- }
- }
-
- ThreadIdentifier CThread::ThreadId() const
- {
--#ifdef _LINUX
-- if (m_ThreadHandle && m_ThreadHandle->m_threadValid)
-- return m_ThreadHandle->m_hThread;
-- else
-- return 0;
--#else
- return m_ThreadId;
--#endif
--}
--
--
--CThread::operator HANDLE()
--{
-- return m_ThreadHandle;
--}
--
--CThread::operator HANDLE() const
--{
-- return m_ThreadHandle;
--}
--
--bool CThread::SetPriority(const int iPriority)
--// Set thread priority
--// Return true for success
--{
-- bool rtn = false;
--
-- if (m_ThreadHandle)
-- {
-- rtn = SetThreadPriority( m_ThreadHandle, iPriority ) == TRUE;
-- }
--
-- return(rtn);
--}
--
--void CThread::SetPrioritySched_RR(void)
--{
--#ifdef __APPLE__
-- // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the
-- // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects
-- // the thread running away. OSX automatically does this with the CoreAudio audio
-- // device handler thread.
-- int32_t result;
-- thread_extended_policy_data_t theFixedPolicy;
--
-- // make thread fixed, set to 'true' for a non-fixed thread
-- theFixedPolicy.timeshare = false;
-- result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY,
-- (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
--
-- int policy;
-- struct sched_param param;
-- result = pthread_getschedparam(ThreadId(), &policy, ¶m );
-- // change from default SCHED_OTHER to SCHED_RR
-- policy = SCHED_RR;
-- result = pthread_setschedparam(ThreadId(), policy, ¶m );
--#endif
--}
--
--int CThread::GetMinPriority(void)
--{
--#if 0
--//#if defined(__APPLE__)
-- struct sched_param sched;
-- int rtn, policy;
--
-- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
-- int min = sched_get_priority_min(policy);
--
-- return(min);
--#else
-- return(THREAD_PRIORITY_IDLE);
--#endif
--}
--
--int CThread::GetMaxPriority(void)
--{
--#if 0
--//#if defined(__APPLE__)
-- struct sched_param sched;
-- int rtn, policy;
--
-- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
-- int max = sched_get_priority_max(policy);
--
-- return(max);
--#else
-- return(THREAD_PRIORITY_HIGHEST);
--#endif
--}
--
--int CThread::GetNormalPriority(void)
--{
--#if 0
--//#if defined(__APPLE__)
-- struct sched_param sched;
-- int rtn, policy;
--
-- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
-- int min = sched_get_priority_min(policy);
-- int max = sched_get_priority_max(policy);
--
-- return( min + ((max-min) / 2) );
--#else
-- return(THREAD_PRIORITY_NORMAL);
--#endif
--}
--
--
--void CThread::SetDebugCallStackName( const char *name )
--{
--#ifdef _WIN32
-- const unsigned int MS_VC_EXCEPTION = 0x406d1388;
-- struct THREADNAME_INFO
-- {
-- DWORD dwType; // must be 0x1000
-- LPCSTR szName; // pointer to name (in same addr space)
-- DWORD dwThreadID; // thread ID (-1 caller thread)
-- DWORD dwFlags; // reserved for future use, most be zero
-- } info;
--
-- info.dwType = 0x1000;
-- info.szName = name;
-- info.dwThreadID = m_ThreadId;
-- info.dwFlags = 0;
--
-- try
-- {
-- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
-- }
-- catch(...)
-- {
-- }
--#endif
--}
--
--// Get the thread name using the implementation dependant typeid() class
--// and attempt to clean it.
--std::string CThread::GetTypeName(void)
--{
-- std::string name = typeid(*this).name();
--
--#if defined(_MSC_VER)
-- // Visual Studio 2010 returns the name as "class CThread" etc
-- if (name.substr(0, 6) == "class ")
-- name = name.substr(6, name.length() - 6);
--#elif defined(__GNUC__) && !defined(__clang__)
-- // gcc provides __cxa_demangle to demangle the name
-- char* demangled = NULL;
-- int status;
--
-- demangled = __cxa_demangle(name.c_str(), NULL, 0, &status);
-- if (status == 0)
-- name = demangled;
-- else
-- CLog::Log(LOGDEBUG,"%s, __cxa_demangle(%s) failed with status %d", __FUNCTION__, name.c_str(), status);
--
-- if (demangled)
-- free(demangled);
--#endif
--
-- return name;
--}
--
--bool CThread::WaitForThreadExit(unsigned int milliseconds)
--// Waits for thread to exit, timeout in given number of msec.
--// Returns true when thread ended
--{
-- if (!m_ThreadHandle) return true;
--
--#ifndef _LINUX
-- // boost priority of thread we are waiting on to same as caller
-- int callee = GetThreadPriority(m_ThreadHandle);
-- int caller = GetThreadPriority(GetCurrentThread());
-- if(caller > callee)
-- SetThreadPriority(m_ThreadHandle, caller);
--
-- if (::WaitForSingleObject(m_ThreadHandle, milliseconds) != WAIT_TIMEOUT)
-- return true;
--
-- // restore thread priority if thread hasn't exited
-- if(caller > callee)
-- SetThreadPriority(m_ThreadHandle, callee);
--#else
-- if (!(m_ThreadHandle->m_threadValid) || pthread_join(m_ThreadHandle->m_hThread, NULL) == 0)
-- {
-- m_ThreadHandle->m_threadValid = false;
-- return true;
-- }
--#endif
--
-- return false;
--}
--
--HANDLE CThread::ThreadHandle()
--{
-- return m_ThreadHandle;
- }
-
- void CThread::Process()
-@@ -474,54 +155,14 @@ void CThread::Process()
- m_pRunnable->Run();
- }
-
--float CThread::GetRelativeUsage()
--{
-- unsigned __int64 iTime = XbmcThreads::SystemClockMillis();
-- iTime *= 10000; // convert into 100ns tics
--
-- // only update every 1 second
-- if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
--
-- FILETIME CreationTime, ExitTime, UserTime, KernelTime;
-- if( GetThreadTimes( m_ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
-- {
-- unsigned __int64 iUsage = 0;
-- iUsage += (((unsigned __int64)UserTime.dwHighDateTime) << 32) + ((unsigned __int64)UserTime.dwLowDateTime);
-- iUsage += (((unsigned __int64)KernelTime.dwHighDateTime) << 32) + ((unsigned __int64)KernelTime.dwLowDateTime);
--
-- if(m_iLastUsage > 0 && m_iLastTime > 0)
-- m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
--
-- m_iLastUsage = iUsage;
-- m_iLastTime = iTime;
--
-- return m_fLastUsage;
-- }
-- return 0.0f;
--}
--
- bool CThread::IsCurrentThread() const
- {
- return IsCurrentThread(ThreadId());
- }
-
--
--ThreadIdentifier CThread::GetCurrentThreadId()
--{
--#ifdef _LINUX
-- return pthread_self();
--#else
-- return ::GetCurrentThreadId();
--#endif
--}
--
--bool CThread::IsCurrentThread(const ThreadIdentifier tid)
-+CThread* CThread::GetCurrentThread()
- {
--#ifdef _LINUX
-- return pthread_equal(pthread_self(), tid);
--#else
-- return (::GetCurrentThreadId() == tid);
--#endif
-+ return currentThread.get();
- }
-
- void CThread::Sleep(unsigned int milliseconds)
-@@ -529,7 +170,7 @@ void CThread::Sleep(unsigned int milliseconds)
- if(milliseconds > 10 && IsCurrentThread())
- m_StopEvent.WaitMSec(milliseconds);
- else
-- ::Sleep(milliseconds);
-+ XbmcThreads::ThreadSleep(milliseconds);
- }
-
-
-diff --git a/xbmc/threads/Thread.h b/xbmc/threads/Thread.h
-index 768d6f8..bebd9ee 100644
---- a/xbmc/threads/Thread.h
-+++ b/xbmc/threads/Thread.h
-@@ -23,19 +23,13 @@
- //
- //////////////////////////////////////////////////////////////////////
-
--#if !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_) && !defined(AFX_THREAD_H__67621B15_8724_4B5D_9343_7667075C89F2__INCLUDED_)
--#define AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_
--
--#if _MSC_VER > 1000
- #pragma once
--#endif // _MSC_VER > 1000
-
- #include
--#include "system.h" // for HANDLE
--#ifdef _LINUX
--#include "PlatformInclude.h"
--#endif
-+#include
- #include "Event.h"
-+#include "threads/ThreadImpl.h"
-+#include "threads/ThreadLocal.h"
-
- class IRunnable
- {
-@@ -44,37 +38,36 @@ public:
- virtual ~IRunnable() {}
- };
-
--#ifdef CTHREAD
--#undef CTHREAD
--#endif
--
- // minimum as mandated by XTL
- #define THREAD_MINSTACKSIZE 0x10000
-
- class CThread
- {
- public:
-- CThread(const char* ThreadName = NULL);
-- CThread(IRunnable* pRunnable, const char* ThreadName = NULL);
-+ CThread(const char* ThreadName);
-+ CThread(IRunnable* pRunnable, const char* ThreadName);
- virtual ~CThread();
- void Create(bool bAutoDelete = false, unsigned stacksize = 0);
- bool WaitForThreadExit(unsigned int milliseconds);
- void Sleep(unsigned int milliseconds);
- bool SetPriority(const int iPriority);
-- void SetPrioritySched_RR(void);
-+ int GetPriority(void);
- int GetMinPriority(void);
- int GetMaxPriority(void);
- int GetNormalPriority(void);
-- HANDLE ThreadHandle();
-- operator HANDLE();
-- operator HANDLE() const;
-+ int GetSchedRRPriority(void);
-+ bool SetPrioritySched_RR(int iPriority);
- bool IsAutoDelete() const;
- virtual void StopThread(bool bWait = true);
- float GetRelativeUsage(); // returns the relative cpu usage of this thread since last call
-+ int64_t GetAbsoluteUsage();
- bool IsCurrentThread() const;
-+ bool IsRunning();
-
- static bool IsCurrentThread(const ThreadIdentifier tid);
- static ThreadIdentifier GetCurrentThreadId();
-+ static CThread* GetCurrentThread();
-+ static int64_t GetCurrentThreadUsage();
- protected:
- virtual void OnStartup(){};
- virtual void OnExit(){};
-@@ -82,7 +75,6 @@ protected:
- virtual void Process();
-
- volatile bool m_bStop;
-- HANDLE m_ThreadHandle;
-
- enum WaitResponse { WAIT_INTERRUPTED = -1, WAIT_SIGNALED = 0, WAIT_TIMEDOUT = 1 };
-
-@@ -108,36 +100,22 @@ protected:
- }
-
- private:
-- /*! \brief set the threadname for the debugger/callstack, implementation dependent.
-- */
-- void SetDebugCallStackName( const char *threadName );
-- std::string GetTypeName(void);
--
--private:
-+ static THREADFUNC staticThread(void *data);
- ThreadIdentifier ThreadId() const;
-+ void SetThreadInfo();
-+ void TermHandler();
-+
-+ ThreadIdentifier m_ThreadId;
-+ ThreadOpaque m_ThreadOpaque;
- bool m_bAutoDelete;
- CEvent m_StopEvent;
-- unsigned m_ThreadId; // This value is unreliable on platforms using pthreads
-- // Use m_ThreadHandle->m_hThread instead
-+ CEvent m_TermEvent;
-+ CEvent m_StartEvent;
-+ CCriticalSection m_CriticalSection;
- IRunnable* m_pRunnable;
--
-- unsigned __int64 m_iLastUsage;
-- unsigned __int64 m_iLastTime;
-+ uint64_t m_iLastUsage;
-+ uint64_t m_iLastTime;
- float m_fLastUsage;
-
- std::string m_ThreadName;
--
--#ifdef _LINUX
-- static void term_handler (int signum);
--#endif
--
--#ifndef _WIN32
-- static int staticThread(void* data);
--#else
-- static DWORD WINAPI staticThread(LPVOID* data);
--#endif
--
--private:
- };
--
--#endif // !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_)
-diff --git a/xbmc/threads/ThreadImpl.h b/xbmc/threads/ThreadImpl.h
-new file mode 100644
-index 0000000..ad10e3b
---- /dev/null
-+++ b/xbmc/threads/ThreadImpl.h
-@@ -0,0 +1,25 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+#pragma once
-+
-+#include "threads/platform/ThreadImpl.h"
-+
-diff --git a/xbmc/threads/platform/ThreadImpl.cpp b/xbmc/threads/platform/ThreadImpl.cpp
-new file mode 100644
-index 0000000..7f0213b
---- /dev/null
-+++ b/xbmc/threads/platform/ThreadImpl.cpp
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+#pragma once
-+
-+#if (defined TARGET_POSIX)
-+#include "threads/platform/pthreads/ThreadImpl.cpp"
-+#if defined(TARGET_DARWIN_IOS)
-+#include "threads/platform/darwin/ThreadSchedImpl.cpp"
-+#else
-+#include "threads/platform/linux/ThreadSchedImpl.cpp"
-+#endif
-+#elif (defined TARGET_WINDOWS)
-+#include "threads/platform/win/ThreadImpl.cpp"
-+#endif
-+
-diff --git a/xbmc/threads/platform/ThreadImpl.h b/xbmc/threads/platform/ThreadImpl.h
-new file mode 100644
-index 0000000..f37709e
---- /dev/null
-+++ b/xbmc/threads/platform/ThreadImpl.h
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+#pragma once
-+
-+#if (defined TARGET_POSIX)
-+#include "threads/platform/pthreads/ThreadImpl.h"
-+#elif (defined TARGET_WINDOWS)
-+#include "threads/platform/win/ThreadImpl.h"
-+#endif
-diff --git a/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp b/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp
-new file mode 100644
-index 0000000..7612fe7
---- /dev/null
-+++ b/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp
-@@ -0,0 +1,47 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+int CThread::GetSchedRRPriority(void)
-+{
-+ return 96;
-+}
-+
-+bool CThread::SetPrioritySched_RR(int iPriority)
-+{
-+ // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the
-+ // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects
-+ // the thread running away. OSX automatically does this with the CoreAudio audio
-+ // device handler thread.
-+ int32_t result;
-+ thread_extended_policy_data_t theFixedPolicy;
-+
-+ // make thread fixed, set to 'true' for a non-fixed thread
-+ theFixedPolicy.timeshare = false;
-+ result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY,
-+ (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
-+
-+ int policy;
-+ struct sched_param param;
-+ result = pthread_getschedparam(ThreadId(), &policy, ¶m );
-+ // change from default SCHED_OTHER to SCHED_RR
-+ policy = SCHED_RR;
-+ result = pthread_setschedparam(ThreadId(), policy, ¶m );
-+}
-diff --git a/xbmc/threads/platform/linux/ThreadSchedImpl.cpp b/xbmc/threads/platform/linux/ThreadSchedImpl.cpp
-new file mode 100644
-index 0000000..034a100
---- /dev/null
-+++ b/xbmc/threads/platform/linux/ThreadSchedImpl.cpp
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+int CThread::GetSchedRRPriority(void)
-+{
-+ return GetNormalPriority();
-+}
-+
-+bool CThread::SetPrioritySched_RR(int iPriority)
-+{
-+ return false;
-+}
-diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.cpp b/xbmc/threads/platform/pthreads/ThreadImpl.cpp
-new file mode 100644
-index 0000000..58b602c
---- /dev/null
-+++ b/xbmc/threads/platform/pthreads/ThreadImpl.cpp
-@@ -0,0 +1,220 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+
-+void CThread::Create(bool bAutoDelete, unsigned stacksize)
-+{
-+ if (m_ThreadId != 0)
-+ {
-+ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
-+ exit(1);
-+ }
-+ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
-+ m_iLastUsage = 0;
-+ m_fLastUsage = 0.0f;
-+ m_bAutoDelete = bAutoDelete;
-+ m_bStop = false;
-+ m_StopEvent.Reset();
-+ m_TermEvent.Reset();
-+ m_StartEvent.Reset();
-+
-+ pthread_attr_t attr;
-+ pthread_attr_init(&attr);
-+ if (stacksize > PTHREAD_STACK_MIN)
-+ pthread_attr_setstacksize(&attr, stacksize);
-+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+ if (pthread_create(&m_ThreadId, &attr, (void*(*)(void*))staticThread, this) != 0)
-+ {
-+ CLog::Log(LOGNOTICE, "%s - fatal error creating thread",__FUNCTION__);
-+ }
-+ pthread_attr_destroy(&attr);
-+}
-+
-+void CThread::TermHandler()
-+{
-+
-+}
-+
-+void CThread::SetThreadInfo()
-+{
-+ m_ThreadOpaque.LwpId = syscall(SYS_gettid);
-+
-+ // start thread with nice level of appication
-+ int appNice = getpriority(PRIO_PROCESS, getpid());
-+ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0)
-+ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno));
-+}
-+
-+ThreadIdentifier CThread::GetCurrentThreadId()
-+{
-+ return pthread_self();
-+}
-+
-+bool CThread::IsCurrentThread(const ThreadIdentifier tid)
-+{
-+ return pthread_equal(pthread_self(), tid);
-+}
-+
-+int CThread::GetMinPriority(void)
-+{
-+ // one level lower than application
-+ return -1;
-+}
-+
-+int CThread::GetMaxPriority(void)
-+{
-+ // one level higher than application
-+ return 1;
-+}
-+
-+int CThread::GetNormalPriority(void)
-+{
-+ // same level as application
-+ return 0;
-+}
-+
-+bool CThread::SetPriority(const int iPriority)
-+{
-+ bool bReturn = false;
-+
-+ // wait until thread is running, it needs to get its lwp id
-+ m_StartEvent.Wait();
-+
-+ CSingleLock lock(m_CriticalSection);
-+
-+ // get min prio for SCHED_RR
-+ int minRR = GetMaxPriority() + 1;
-+
-+ if (!m_ThreadId)
-+ bReturn = false;
-+ else if (iPriority >= minRR)
-+ bReturn = SetPrioritySched_RR(iPriority);
-+ else
-+ {
-+ // get user max prio
-+ struct rlimit limit;
-+ int userMaxPrio;
-+ if (getrlimit(RLIMIT_NICE, &limit) == 0)
-+ {
-+ userMaxPrio = limit.rlim_cur - 20;
-+ }
-+ else
-+ userMaxPrio = 0;
-+
-+ // keep priority in bounds
-+ int prio = iPriority;
-+ if (prio >= GetMaxPriority())
-+ prio = std::min(GetMaxPriority(), userMaxPrio);
-+ if (prio < GetMinPriority())
-+ prio = GetMinPriority();
-+
-+ // nice level of application
-+ int appNice = getpriority(PRIO_PROCESS, getpid());
-+ if (prio)
-+ prio = prio > 0 ? appNice-1 : appNice+1;
-+
-+ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, prio) == 0)
-+ bReturn = true;
-+ else
-+ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno));
-+ }
-+
-+ return bReturn;
-+}
-+
-+int CThread::GetPriority()
-+{
-+ int iReturn;
-+
-+ // lwp id is valid after start signel has fired
-+ m_StartEvent.Wait();
-+
-+ CSingleLock lock(m_CriticalSection);
-+
-+ int appNice = getpriority(PRIO_PROCESS, getpid());
-+ int prio = getpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId);
-+ iReturn = appNice - prio;
-+
-+ return iReturn;
-+}
-+
-+bool CThread::WaitForThreadExit(unsigned int milliseconds)
-+{
-+ bool bReturn = m_TermEvent.WaitMSec(milliseconds);
-+
-+ return bReturn;
-+}
-+
-+int64_t CThread::GetAbsoluteUsage()
-+{
-+ CSingleLock lock(m_CriticalSection);
-+
-+ if (!m_ThreadId)
-+ return 0;
-+
-+ clockid_t clock;
-+ int64_t time = 0;
-+ if (pthread_getcpuclockid(m_ThreadId, &clock) == 0)
-+ {
-+ struct timespec tp;
-+ clock_gettime(clock, &tp);
-+ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100;
-+ }
-+ return time;
-+}
-+
-+float CThread::GetRelativeUsage()
-+{
-+ unsigned int iTime = XbmcThreads::SystemClockMillis();
-+ iTime *= 10000; // convert into 100ns tics
-+
-+ // only update every 1 second
-+ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
-+
-+ int64_t iUsage = GetAbsoluteUsage();
-+
-+ if (m_iLastUsage > 0 && m_iLastTime > 0)
-+ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
-+
-+ m_iLastUsage = iUsage;
-+ m_iLastTime = iTime;
-+
-+ return m_fLastUsage;
-+}
-+
-+int64_t CThread::GetCurrentThreadUsage()
-+{
-+ pthread_t tid = pthread_self();
-+ clockid_t clock;
-+ int64_t time = 0;
-+ if (pthread_getcpuclockid(tid, &clock) == 0)
-+ {
-+ struct timespec tp;
-+ clock_gettime(clock, &tp);
-+ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100;
-+ }
-+ return time;
-+}
-+
-diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.h b/xbmc/threads/platform/pthreads/ThreadImpl.h
-new file mode 100644
-index 0000000..3f4dd39
---- /dev/null
-+++ b/xbmc/threads/platform/pthreads/ThreadImpl.h
-@@ -0,0 +1,39 @@
-+/*
-+* Copyright (C) 2005-2011 Team XBMC
-+* http://www.xbmc.org
-+*
-+* This Program is free software; you can redistribute it and/or modify
-+* it under the terms of the GNU General Public License as published by
-+* the Free Software Foundation; either version 2, or (at your option)
-+* any later version.
-+*
-+* This Program is distributed in the hope that it will be useful,
-+* but WITHOUT ANY WARRANTY; without even the implied warranty of
-+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+* GNU General Public License for more details.
-+*
-+* You should have received a copy of the GNU General Public License
-+* along with XBMC; see the file COPYING. If not, write to
-+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+* http://www.gnu.org/copyleft/gpl.html
-+*
-+*/
-+
-+#pragma once
-+
-+#include
-+
-+struct threadOpaque
-+{
-+ pid_t LwpId;
-+};
-+
-+typedef pthread_t ThreadIdentifier;
-+typedef threadOpaque ThreadOpaque;
-+typedef int THREADFUNC;
-+
-+namespace XbmcThreads
-+{
-+ inline static void ThreadSleep(unsigned int millis) { usleep(millis*1000); }
-+}
-+
-diff --git a/xbmc/threads/platform/win/ThreadImpl.cpp b/xbmc/threads/platform/win/ThreadImpl.cpp
-new file mode 100644
-index 0000000..6650ee6
---- /dev/null
-+++ b/xbmc/threads/platform/win/ThreadImpl.cpp
-@@ -0,0 +1,207 @@
-+/*
-+ * Copyright (C) 2005-2011 Team XBMC
-+ * http://www.xbmc.org
-+ *
-+ * This Program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ *
-+ * This Program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with XBMC; see the file COPYING. If not, write to
-+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * http://www.gnu.org/copyleft/gpl.html
-+ *
-+ */
-+
-+#include
-+
-+
-+void CThread::Create(bool bAutoDelete, unsigned stacksize)
-+{
-+ if (m_ThreadId != 0)
-+ {
-+ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
-+ exit(1);
-+ }
-+ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
-+ m_iLastUsage = 0;
-+ m_fLastUsage = 0.0f;
-+ m_bAutoDelete = bAutoDelete;
-+ m_bStop = false;
-+ m_StopEvent.Reset();
-+ m_TermEvent.Reset();
-+ m_StartEvent.Reset();
-+
-+ m_ThreadOpaque.handle = CreateThread(NULL,stacksize, (LPTHREAD_START_ROUTINE)&staticThread, this, 0, &m_ThreadId);
-+ if (m_ThreadOpaque.handle == NULL)
-+ {
-+ CLog::Log(LOGERROR, "%s - fatal error creating thread", __FUNCTION__);
-+ }
-+}
-+
-+void CThread::TermHandler()
-+{
-+ CloseHandle(m_ThreadOpaque.handle);
-+ m_ThreadOpaque.handle = NULL;
-+}
-+
-+void CThread::SetThreadInfo()
-+{
-+ const unsigned int MS_VC_EXCEPTION = 0x406d1388;
-+ struct THREADNAME_INFO
-+ {
-+ DWORD dwType; // must be 0x1000
-+ LPCSTR szName; // pointer to name (in same addr space)
-+ DWORD dwThreadID; // thread ID (-1 caller thread)
-+ DWORD dwFlags; // reserved for future use, most be zero
-+ } info;
-+
-+ info.dwType = 0x1000;
-+ info.szName = m_ThreadName.c_str();
-+ info.dwThreadID = m_ThreadId;
-+ info.dwFlags = 0;
-+
-+ try
-+ {
-+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
-+ }
-+ catch(...)
-+ {
-+ }
-+}
-+
-+ThreadIdentifier CThread::GetCurrentThreadId()
-+{
-+ return ::GetCurrentThreadId();
-+}
-+
-+bool CThread::IsCurrentThread(const ThreadIdentifier tid)
-+{
-+ return (::GetCurrentThreadId() == tid);
-+}
-+
-+int CThread::GetMinPriority(void)
-+{
-+ return(THREAD_PRIORITY_IDLE);
-+}
-+
-+int CThread::GetMaxPriority(void)
-+{
-+ return(THREAD_PRIORITY_HIGHEST);
-+}
-+
-+int CThread::GetNormalPriority(void)
-+{
-+ return(THREAD_PRIORITY_NORMAL);
-+}
-+
-+int CThread::GetSchedRRPriority(void)
-+{
-+ return GetNormalPriority();
-+}
-+
-+bool CThread::SetPriority(const int iPriority)
-+{
-+ bool bReturn = false;
-+
-+ CSingleLock lock(m_CriticalSection);
-+ if (m_ThreadOpaque.handle)
-+ {
-+ bReturn = SetThreadPriority(m_ThreadOpaque.handle, iPriority) == TRUE;
-+ }
-+
-+ return bReturn;
-+}
-+
-+int CThread::GetPriority()
-+{
-+ CSingleLock lock(m_CriticalSection);
-+
-+ int iReturn = THREAD_PRIORITY_NORMAL;
-+ if (m_ThreadOpaque.handle)
-+ {
-+ iReturn = GetThreadPriority(m_ThreadOpaque.handle);
-+ }
-+ return iReturn;
-+}
-+
-+bool CThread::WaitForThreadExit(unsigned int milliseconds)
-+{
-+ bool bReturn = true;
-+
-+ CSingleLock lock(m_CriticalSection);
-+ if (m_ThreadId && m_ThreadOpaque.handle != NULL)
-+ {
-+ // boost priority of thread we are waiting on to same as caller
-+ int callee = GetThreadPriority(m_ThreadOpaque.handle);
-+ int caller = GetThreadPriority(GetCurrentThread());
-+ if(caller > callee)
-+ SetThreadPriority(m_ThreadOpaque.handle, caller);
-+
-+ lock.Leave();
-+ bReturn = m_TermEvent.WaitMSec(milliseconds);
-+ lock.Enter();
-+
-+ // restore thread priority if thread hasn't exited
-+ if(caller > callee && m_ThreadOpaque.handle)
-+ SetThreadPriority(m_ThreadOpaque.handle, callee);
-+ }
-+ return bReturn;
-+}
-+
-+int64_t CThread::GetAbsoluteUsage()
-+{
-+ CSingleLock lock(m_CriticalSection);
-+
-+ if (!m_ThreadOpaque.handle)
-+ return 0;
-+
-+ uint64_t time = 0;
-+ FILETIME CreationTime, ExitTime, UserTime, KernelTime;
-+ if( GetThreadTimes(m_ThreadOpaque.handle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
-+ {
-+ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
-+ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
-+ }
-+ return time;
-+}
-+
-+float CThread::GetRelativeUsage()
-+{
-+ unsigned int iTime = XbmcThreads::SystemClockMillis();
-+ iTime *= 10000; // convert into 100ns tics
-+
-+ // only update every 1 second
-+ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
-+
-+ int64_t iUsage = GetAbsoluteUsage();
-+
-+ if (m_iLastUsage > 0 && m_iLastTime > 0)
-+ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
-+
-+ m_iLastUsage = iUsage;
-+ m_iLastTime = iTime;
-+
-+ return m_fLastUsage;
-+}
-+
-+int64_t CThread::GetCurrentThreadUsage()
-+{
-+ HANDLE h = GetCurrentThread();
-+
-+ uint64_t time = 0;
-+ FILETIME CreationTime, ExitTime, UserTime, KernelTime;
-+ if( GetThreadTimes(h, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
-+ {
-+ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
-+ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
-+ }
-+ return time;
-+}
-+
-diff --git a/xbmc/threads/platform/win/ThreadImpl.h b/xbmc/threads/platform/win/ThreadImpl.h
-new file mode 100644
-index 0000000..ea9a0db
---- /dev/null
-+++ b/xbmc/threads/platform/win/ThreadImpl.h
-@@ -0,0 +1,40 @@
-+/*
-+* Copyright (C) 2005-2011 Team XBMC
-+* http://www.xbmc.org
-+*
-+* This Program is free software; you can redistribute it and/or modify
-+* it under the terms of the GNU General Public License as published by
-+* the Free Software Foundation; either version 2, or (at your option)
-+* any later version.
-+*
-+* This Program is distributed in the hope that it will be useful,
-+* but WITHOUT ANY WARRANTY; without even the implied warranty of
-+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+* GNU General Public License for more details.
-+*
-+* You should have received a copy of the GNU General Public License
-+* along with XBMC; see the file COPYING. If not, write to
-+* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-+* http://www.gnu.org/copyleft/gpl.html
-+*
-+*/
-+
-+#pragma once
-+
-+#include
-+
-+
-+struct threadOpaque
-+{
-+ HANDLE handle;
-+};
-+
-+typedef DWORD ThreadIdentifier;
-+typedef threadOpaque ThreadOpaque;
-+typedef DWORD THREADFUNC;
-+
-+namespace XbmcThreads
-+{
-+ inline static void ThreadSleep(unsigned int millis) { Sleep(millis); }
-+}
-+
-diff --git a/xbmc/utils/AlarmClock.cpp b/xbmc/utils/AlarmClock.cpp
-index 09c9619..6ca327f 100644
---- a/xbmc/utils/AlarmClock.cpp
-+++ b/xbmc/utils/AlarmClock.cpp
-@@ -28,7 +28,7 @@
-
- using namespace std;
-
--CAlarmClock::CAlarmClock() : m_bIsRunning(false)
-+CAlarmClock::CAlarmClock() : CThread("CAlarmClock"), m_bIsRunning(false)
- {
- }
-
-diff --git a/xbmc/utils/AsyncFileCopy.cpp b/xbmc/utils/AsyncFileCopy.cpp
-index e9b7bc0..44e7043 100644
---- a/xbmc/utils/AsyncFileCopy.cpp
-+++ b/xbmc/utils/AsyncFileCopy.cpp
-@@ -26,7 +26,7 @@
- #include "log.h"
- #include "utils/TimeUtils.h"
-
--CAsyncFileCopy::CAsyncFileCopy()
-+CAsyncFileCopy::CAsyncFileCopy() : CThread("CAsyncFileCopy")
- {
- m_cancelled = false;
- m_succeeded = false;
-diff --git a/xbmc/utils/DownloadQueue.cpp b/xbmc/utils/DownloadQueue.cpp
-index 4101090..0210241 100644
---- a/xbmc/utils/DownloadQueue.cpp
-+++ b/xbmc/utils/DownloadQueue.cpp
-@@ -32,7 +32,7 @@ using namespace XFILE;
-
- WORD CDownloadQueue::m_wNextQueueId = 0;
-
--CDownloadQueue::CDownloadQueue(void) : CThread()
-+CDownloadQueue::CDownloadQueue(void) : CThread("CDownloadQueue")
- {
- m_bStop = false;
- m_wQueueId = m_wNextQueueId++;
-diff --git a/xbmc/utils/DownloadQueue.h b/xbmc/utils/DownloadQueue.h
-index c314792..543a825 100644
---- a/xbmc/utils/DownloadQueue.h
-+++ b/xbmc/utils/DownloadQueue.h
-@@ -26,6 +26,8 @@
- #include "threads/CriticalSection.h"
- #include "StdString.h"
-
-+#include "system.h"
-+
- struct TICKET
- {
- TICKET(WORD aQueueId, DWORD aItemId)
-diff --git a/xbmc/utils/DownloadQueueManager.h b/xbmc/utils/DownloadQueueManager.h
-index 3fb0d9f..9bda3ea 100644
---- a/xbmc/utils/DownloadQueueManager.h
-+++ b/xbmc/utils/DownloadQueueManager.h
-@@ -22,6 +22,7 @@
- */
-
- #include "DownloadQueue.h"
-+#include "system.h"
-
- #define MAX_DOWNLOAD_QUEUES 3
-
-diff --git a/xbmc/utils/JobManager.cpp b/xbmc/utils/JobManager.cpp
-index dd7b28d..07c9502 100644
---- a/xbmc/utils/JobManager.cpp
-+++ b/xbmc/utils/JobManager.cpp
-@@ -23,6 +23,9 @@
- #include
- #include "threads/SingleLock.h"
-
-+#include "system.h"
-+
-+
- using namespace std;
-
- bool CJob::ShouldCancel(unsigned int progress, unsigned int total) const
-diff --git a/xbmc/utils/LCD.h b/xbmc/utils/LCD.h
-index b60bcf2..888e5ac 100644
---- a/xbmc/utils/LCD.h
-+++ b/xbmc/utils/LCD.h
-@@ -68,8 +68,9 @@ public:
- void LoadSkin(const CStdString &xmlFile);
- void Reset();
- void Render(LCD_MODE mode);
-- ILCD() : m_disableOnPlay(DISABLE_ON_PLAY_NONE),
-- m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {}
-+ ILCD() : CThread("ILCD"),
-+ m_disableOnPlay(DISABLE_ON_PLAY_NONE),
-+ m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {}
- protected:
- virtual void Process() = 0;
- void StringToLCDCharSet(CStdString& strText);
-diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp
-index 18fcdb4..fff6f5e 100644
---- a/xbmc/utils/RssReader.cpp
-+++ b/xbmc/utils/RssReader.cpp
-@@ -44,7 +44,7 @@ using namespace XFILE;
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
--CRssReader::CRssReader() : CThread()
-+CRssReader::CRssReader() : CThread("CRssReader")
- {
- m_pObserver = NULL;
- m_spacesBetweenFeeds = 0;
-diff --git a/xbmc/utils/RssReader.h b/xbmc/utils/RssReader.h
-index f94e2be..d202b37 100644
---- a/xbmc/utils/RssReader.h
-+++ b/xbmc/utils/RssReader.h
-@@ -39,6 +39,9 @@
-
- #include "tinyXML/tinyxml.h"
-
-+#include "system.h"
-+
-+
- #define RSS_COLOR_BODY 0
- #define RSS_COLOR_HEADLINE 1
- #define RSS_COLOR_CHANNEL 2
-diff --git a/xbmc/utils/Splash.cpp b/xbmc/utils/Splash.cpp
-index 58093b0..a53c90e 100644
---- a/xbmc/utils/Splash.cpp
-+++ b/xbmc/utils/Splash.cpp
-@@ -31,7 +31,7 @@
-
- using namespace XFILE;
-
--CSplash::CSplash(const CStdString& imageName)
-+CSplash::CSplash(const CStdString& imageName) : CThread("CSplash")
- {
- m_ImageName = imageName;
- fade = 0.5;
-@@ -139,5 +139,5 @@ void CSplash::Stop()
-
- bool CSplash::IsRunning()
- {
-- return (m_ThreadHandle != NULL);
-+ return (IsRunning());
- }
-diff --git a/xbmc/utils/TuxBoxUtil.cpp b/xbmc/utils/TuxBoxUtil.cpp
-index c15b634..ab5a5ce 100644
---- a/xbmc/utils/TuxBoxUtil.cpp
-+++ b/xbmc/utils/TuxBoxUtil.cpp
-@@ -48,7 +48,7 @@ using namespace std;
- CTuxBoxUtil g_tuxbox;
- CTuxBoxService g_tuxboxService;
-
--CTuxBoxService::CTuxBoxService()
-+CTuxBoxService::CTuxBoxService() : CThread("CTuxBoxService")
- {
- }
- CTuxBoxService::~CTuxBoxService()
-diff --git a/xbmc/video/VideoInfoDownloader.cpp b/xbmc/video/VideoInfoDownloader.cpp
-index 3185d2b..5a46034 100644
---- a/xbmc/video/VideoInfoDownloader.cpp
-+++ b/xbmc/video/VideoInfoDownloader.cpp
-@@ -116,7 +116,7 @@ int CVideoInfoDownloader::FindMovie(const CStdString &strMovie,
- m_state = FIND_MOVIE;
- m_strMovie = strMovie;
- m_found = 0;
-- if (ThreadHandle())
-+ if (IsRunning())
- StopThread();
- Create();
- while (m_state != DO_NOTHING)
-@@ -160,7 +160,7 @@ bool CVideoInfoDownloader::GetDetails(const CScraperUrl &url,
- { // threaded version
- m_state = GET_DETAILS;
- m_found = 0;
-- if (ThreadHandle())
-+ if (IsRunning())
- StopThread();
- Create();
- while (!m_found)
-@@ -195,7 +195,7 @@ bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url,
- { // threaded version
- m_state = GET_EPISODE_DETAILS;
- m_found = 0;
-- if (ThreadHandle())
-+ if (IsRunning())
- StopThread();
- Create();
- while (!m_found)
-@@ -230,7 +230,7 @@ bool CVideoInfoDownloader::GetEpisodeList(const CScraperUrl& url,
- { // threaded version
- m_state = GET_EPISODE_LIST;
- m_found = 0;
-- if (ThreadHandle())
-+ if (IsRunning())
- StopThread();
- Create();
- while (!m_found)
-diff --git a/xbmc/video/VideoInfoDownloader.h b/xbmc/video/VideoInfoDownloader.h
-index b91477d..8a05568 100644
---- a/xbmc/video/VideoInfoDownloader.h
-+++ b/xbmc/video/VideoInfoDownloader.h
-@@ -42,7 +42,7 @@ typedef std::vector MOVIELIST;
- class CVideoInfoDownloader : public CThread
- {
- public:
-- CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : m_info(scraper) {}
-+ CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : CThread("CVideoInfoDownloader"), m_info(scraper) {}
- virtual ~CVideoInfoDownloader() {}
-
- // threaded lookup functions
-diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp
-index 1b680f3..f2f50e8 100644
---- a/xbmc/video/VideoInfoScanner.cpp
-+++ b/xbmc/video/VideoInfoScanner.cpp
-@@ -54,7 +54,7 @@ using namespace ADDON;
- namespace VIDEO
- {
-
-- CVideoInfoScanner::CVideoInfoScanner()
-+ CVideoInfoScanner::CVideoInfoScanner() : CThread("CVideoInfoScanner")
- {
- m_bRunning = false;
- m_pObserver = NULL;
-diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp
-index ea72ee8..1c00b6b 100644
---- a/xbmc/video/VideoReferenceClock.cpp
-+++ b/xbmc/video/VideoReferenceClock.cpp
-@@ -107,7 +107,7 @@ using namespace std;
-
- #endif
-
--CVideoReferenceClock::CVideoReferenceClock()
-+CVideoReferenceClock::CVideoReferenceClock() : CThread("CVideoReferenceClock")
- {
- m_SystemFrequency = CurrentHostFrequency();
- m_ClockSpeed = 1.0;
-@@ -161,6 +161,8 @@ void CVideoReferenceClock::Process()
- m_RefreshChanged = 0;
- m_Started.Set();
-
-+ SetPriority(1);
-+
- if (SetupSuccess)
- {
- m_UseVblank = true; //tell other threads we're using vblank as clock
-diff --git a/xbmc/win32/PlatformDefs.h b/xbmc/win32/PlatformDefs.h
-index 57cab8f..74e3d53 100644
---- a/xbmc/win32/PlatformDefs.h
-+++ b/xbmc/win32/PlatformDefs.h
-@@ -33,7 +33,6 @@ typedef __int64 off64_t;
- typedef __int64 fpos64_t;
- typedef __int64 __off64_t;
- typedef long __off_t;
--typedef unsigned long ThreadIdentifier;
-
- #define ssize_t int
-
-diff --git a/xbmc/win32/WindowHelper.cpp b/xbmc/win32/WindowHelper.cpp
-index 56856ac..8aa7da9 100644
---- a/xbmc/win32/WindowHelper.cpp
-+++ b/xbmc/win32/WindowHelper.cpp
-@@ -28,7 +28,7 @@ using namespace std;
-
- CWHelper g_windowHelper;
-
--CWHelper::CWHelper(void)
-+CWHelper::CWHelper(void) : CThread("CWHelper")
- {
- m_hwnd = NULL;
- m_hProcess = NULL;
-diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp
-index 201b0ad..c686e6e 100644
---- a/xbmc/windowing/X11/WinSystemX11.cpp
-+++ b/xbmc/windowing/X11/WinSystemX11.cpp
-@@ -35,6 +35,8 @@
- #include
- #include "cores/VideoRenderers/RenderManager.h"
- #include "utils/TimeUtils.h"
-+#include "settings/AdvancedSettings.h"
-+#include "settings/GUISettings.h"
-
- #if defined(HAS_XRANDR)
- #include
-@@ -52,6 +54,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase()
- m_wmWindow = 0;
- m_bWasFullScreenBeforeMinimize = false;
- m_dpyLostTime = 0;
-+ m_internalModeSwitch = false;
-
- XSetErrorHandler(XErrorHandler);
- }
-@@ -178,6 +181,45 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
- return false;
- }
-
-+void CWinSystemX11::RefreshWindow()
-+{
-+ // save current mode if this is not an internal request
-+ if (!m_internalModeSwitch)
-+ {
-+ CLog::Log(LOGNOTICE, "CWinSystemX11::RefreshWindow - external or initial xrandr event");
-+ m_xrandrOut = g_xrandr.GetCurrentOutput();
-+ m_xrandrMode = g_xrandr.GetCurrentMode(m_xrandrOut.name);
-+ }
-+ m_internalModeSwitch = false;
-+
-+ g_xrandr.Query(true);
-+ XOutput out = g_xrandr.GetCurrentOutput();
-+ XMode mode = g_xrandr.GetCurrentMode(out.name);
-+
-+ RESOLUTION_INFO res;
-+ unsigned int i;
-+ bool found(false);
-+ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i)
-+ {
-+ if (g_settings.m_ResInfo[i].strId == mode.id)
-+ {
-+ found = true;
-+ break;
-+ }
-+ }
-+
-+ if (!found)
-+ {
-+ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution");
-+ return;
-+ }
-+
-+ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true);
-+ g_guiSettings.SetInt("window.width", mode.w);
-+ g_guiSettings.SetInt("window.height", mode.h);
-+ g_settings.Save();
-+}
-+
- bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
- {
- m_nWidth = res.iWidth;
-@@ -193,13 +235,32 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
- mode.hz = res.fRefreshRate;
- mode.id = res.strId;
-
-- if(m_bFullScreen)
-+ XOutput currout = g_xrandr.GetCurrentOutput();
-+ XMode currmode = g_xrandr.GetCurrentMode(currout.name);
-+
-+ if (m_xrandrOut.name.empty())
-+ {
-+ m_xrandrOut = currout;
-+ m_xrandrMode = currmode;
-+ }
-+
-+ if(!m_bFullScreen)
- {
-+ // reset to mode we had before internal mode switch
-+ out = m_xrandrOut;
-+ mode = m_xrandrMode;
-+ }
-+
-+ // only call xrandr if mode changes
-+ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h ||
-+ currmode.hz != mode.hz || currmode.id != mode.id)
-+ {
-+ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr");
- OnLostDevice();
-+ m_internalModeSwitch = true;
- g_xrandr.SetMode(out, mode);
- }
-- else
-- g_xrandr.RestoreState();
-+
- #endif
-
- int options = SDL_OPENGL;
-@@ -493,6 +554,7 @@ void CWinSystemX11::CheckDisplayEvents()
- if (bGotEvent || bTimeout)
- {
- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
-+ RefreshWindow();
-
- CSingleLock lock(m_resourceSection);
-
-diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h
-index a77c4d5..dcc63ff 100644
---- a/xbmc/windowing/X11/WinSystemX11.h
-+++ b/xbmc/windowing/X11/WinSystemX11.h
-@@ -27,6 +27,7 @@
- #include "utils/Stopwatch.h"
- #include
- #include "threads/CriticalSection.h"
-+#include "XRandR.h"
-
- class IDispResource;
-
-@@ -60,6 +61,7 @@ public:
- // Local to WinSystemX11 only
- Display* GetDisplay() { return m_dpy; }
- GLXWindow GetWindow() { return m_glWindow; }
-+ void RefreshWindow();
-
- protected:
- bool RefreshGlxContext();
-@@ -76,6 +78,9 @@ protected:
- CCriticalSection m_resourceSection;
- std::vector m_resources;
- uint64_t m_dpyLostTime;
-+ XOutput m_xrandrOut;
-+ XMode m_xrandrMode;
-+ bool m_internalModeSwitch;
-
- private:
- bool IsSuitableVisual(XVisualInfo *vInfo);
diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.01-xvba_support_vdpau_rework-c633159.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.01-xvba_support_vdpau_rework-c633159.patch
new file mode 100644
index 0000000000..807ade8595
--- /dev/null
+++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-902.01-xvba_support_vdpau_rework-c633159.patch
@@ -0,0 +1,15378 @@
+diff -Naur xbmc-11.0.1/configure.in xbmc-11.0.1.patch/configure.in
+--- xbmc-11.0.1/configure.in 2012-03-21 23:57:58.000000000 +0100
++++ xbmc-11.0.1.patch/configure.in 2012-05-13 22:08:46.942192804 +0200
+@@ -98,6 +98,8 @@
+ vaapi_disabled="== VAAPI support manually disabled. =="
+ crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. =="
+ crystalhd_disabled="== CrystalHD support manually disabled. =="
++xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. =="
++xvba_disabled="== XVBA support manually disabled. =="
+ vdadecoder_enabled="== VDADecoder support enabled. =="
+ vdadecoder_disabled="== VDADecoder support manually disabled. =="
+ vtbdecoder_enabled="== VTBDecoder support enabled. =="
+@@ -204,6 +206,12 @@
+ [enable CrystalHD decoding (default is auto)])],
+ [use_crystalhd=$enableval],
+ [use_crystalhd=auto])
++
++AC_ARG_ENABLE([xvba],
++ [AS_HELP_STRING([--enable-xvba],
++ [enable XVBA decoding (default is auto)])],
++ [use_xvba=$enableval],
++ [use_xvba=auto])
+
+ AC_ARG_ENABLE([vdadecoder],
+ [AS_HELP_STRING([--enable-vdadecoder],
+@@ -1382,6 +1390,38 @@
+ USE_CRYSTALHD=0
+ fi
+
++# XVBA
++if test "x$use_xvba" != "xno"; then
++ if test "$host_vendor" = "apple" ; then
++ if test "x$use_xvba" = "xyes"; then
++ AC_MSG_ERROR([XVBA not supported on this platform])
++ else
++ use_xvba="no"
++ AC_MSG_NOTICE($xvba_disabled)
++ fi
++ USE_XVBA=0
++ else
++ initial_val=$use_xvba
++ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include ])
++
++ if test "x$use_xvba" = "xno"; then
++ if test "x$initial_val" = "xyes"; then
++ AC_MSG_ERROR($xvba_not_found)
++ else
++ AC_MSG_RESULT($xvba_not_found)
++ fi
++ USE_XVBA=0
++ else
++ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)])
++ USE_XVBA=1
++ fi
++ fi
++else
++ AC_MSG_NOTICE($xvba_disabled)
++ USE_XVBA=0
++fi
++
++
+ # VDADecoder
+ if test "x$use_vdadecoder" != "xno"; then
+ if test "$host_vendor" = "apple" ; then
+@@ -1578,6 +1618,12 @@
+ final_message="$final_message\n CrystalHD:\tNo"
+ fi
+
++if test "x$use_xvba" != "xno"; then
++ final_message="$final_message\n XVBA:\t\tYes"
++else
++ final_message="$final_message\n XVBA:\t\tNo"
++fi
++
+ if test "x$use_vdadecoder" != "xno"; then
+ final_message="$final_message\n VDADecoder:\tYes"
+ else
+@@ -1943,6 +1989,7 @@
+ AC_SUBST(USE_VDPAU)
+ AC_SUBST(USE_VAAPI)
+ AC_SUBST(USE_CRYSTALHD)
++AC_SUBST(USE_XVBA)
+ AC_SUBST(USE_LIBSMBCLIENT)
+ AC_SUBST(USE_LIBNFS)
+ AC_SUBST(USE_LIBAFPCLIENT)
+@@ -2085,6 +2132,7 @@
+ --enable-gpl \
+ `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \
+ `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \
++ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \
+ --enable-protocol=http \
+ --enable-pthreads \
+ --enable-runtime-cpudetect \
+diff -Naur xbmc-11.0.1/language/Dutch/strings.xml xbmc-11.0.1.patch/language/Dutch/strings.xml
+--- xbmc-11.0.1/language/Dutch/strings.xml 2012-03-21 23:57:54.000000000 +0100
++++ xbmc-11.0.1.patch/language/Dutch/strings.xml 2012-05-13 22:16:42.908637517 +0200
+@@ -1233,7 +1233,8 @@
+ Hardwareversnelling inschakelen (OpenMax)
+ Pixelshaders
+ Hardware acceleratie toestaan (VideoToolbox)
+-
++ Vdpau OpenGL interop RGB inschakelen
++ Vdpau OpenGL interop YUV inschakelen
+ A/V-synchronisatiemethode
+ Audiosignaal
+ Videosignaal (Drop/Dupe audio)
+@@ -1539,6 +1540,7 @@
+ Spline36
+ Spline36 geoptimaliseerd
+ Software menging
++ VDPAU Bob
+
+ Kwaliteitsverbetering video
+
+diff -Naur xbmc-11.0.1/language/English/strings.xml xbmc-11.0.1.patch/language/English/strings.xml
+--- xbmc-11.0.1/language/English/strings.xml 2012-03-21 23:57:54.000000000 +0100
++++ xbmc-11.0.1.patch/language/English/strings.xml 2012-05-13 22:16:30.975400722 +0200
+@@ -1232,6 +1232,9 @@
+ Allow hardware acceleration (OpenMax)
+ Pixel Shaders
+ Allow hardware acceleration (VideoToolbox)
++ Allow Vdpau OpenGL interop RGB
++ Allow Vdpau OpenGL interop YUV
++ Allow hardware acceleration (XVBA)
+
+ A/V sync method
+ Audio clock
+@@ -1538,6 +1541,8 @@
+ Spline36
+ Spline36 optimized
+ Software Blend
++ VDPAU Bob
++ XVBA
+
+ Post-processing
+
+diff -Naur xbmc-11.0.1/language/German/strings.xml xbmc-11.0.1.patch/language/German/strings.xml
+--- xbmc-11.0.1/language/German/strings.xml 2012-03-21 23:57:54.000000000 +0100
++++ xbmc-11.0.1.patch/language/German/strings.xml 2012-05-13 22:08:46.676187527 +0200
+@@ -1266,6 +1266,8 @@
+ Hardwarebeschleunigung erlauben (OpenMax)
+ Pixel Shaders
+ Hardwarebeschleunigung erlauben (VideoToolbox)
++ Vdpau OpenGL interop RGB erlauben
++ Vdpau OpenGL interop YUV erlauben
+
+ A/V Sync Methode
+ Audio Takt
+@@ -1565,6 +1567,7 @@
+ Zeitlich (Hälfte)
+ Zeitlich/Räumlich (Hälfte)
+ DXVA
++ VDPAU Bob
+
+ Video Nachbearbeitung
+ Deaktiviert
+diff -Naur xbmc-11.0.1/language/Swedish/strings.xml xbmc-11.0.1.patch/language/Swedish/strings.xml
+--- xbmc-11.0.1/language/Swedish/strings.xml 2012-03-21 23:57:54.000000000 +0100
++++ xbmc-11.0.1.patch/language/Swedish/strings.xml 2012-05-13 22:08:46.663187269 +0200
+@@ -1412,6 +1412,7 @@
+ Spline36
+ Spline36-optimerad
+ Mjukvarublandning
++ VDPAU Bob
+ Efterbearbetning
+ Visa insommningstimeout
+ Byt till kanal
+diff -Naur xbmc-11.0.1/lib/ffmpeg/configure xbmc-11.0.1.patch/lib/ffmpeg/configure
+--- xbmc-11.0.1/lib/ffmpeg/configure 2012-03-21 23:57:44.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/configure 2012-05-13 22:08:46.926192488 +0200
+@@ -111,6 +111,7 @@
+ --disable-vaapi disable VAAPI code
+ --disable-vdpau disable VDPAU code
+ --disable-dxva2 disable DXVA2 code
++ --disable-xvba disable XVBA code
+ --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
+ --enable-hardcoded-tables use hardcoded tables instead of runtime generation
+ --enable-memalign-hack emulate memalign, interferes with memory debuggers
+@@ -932,6 +933,7 @@
+ swscale_alpha
+ vaapi
+ vdpau
++ xvba
+ version3
+ x11grab
+ zlib
+@@ -1240,6 +1242,7 @@
+ h264_dxva2_hwaccel_deps="dxva2api_h"
+ h264_dxva2_hwaccel_select="dxva2 h264_decoder"
+ h264_vaapi_hwaccel_select="vaapi"
++h264_xvba_hwaccel_select="xvba"
+ h264_vdpau_decoder_select="vdpau h264_decoder"
+ imc_decoder_select="fft mdct"
+ jpegls_decoder_select="golomb"
+@@ -1263,6 +1266,7 @@
+ mpeg2_dxva2_hwaccel_select="dxva2 mpeg2video_decoder"
+ mpeg2_vaapi_hwaccel_select="vaapi mpeg2video_decoder"
+ mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
++mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder"
+ mpeg4_vdpau_decoder_deps="vdpau_vdpau_h vdpau_vdpau_x11_h vdpau_mpeg4_support"
+ mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
+ mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h"
+@@ -1306,6 +1310,7 @@
+ vc1_dxva2_hwaccel_deps="dxva2api_h DXVA_PictureParameters_wDecodedPictureIndex"
+ vc1_dxva2_hwaccel_select="dxva2 vc1_decoder"
+ vc1_vaapi_hwaccel_select="vaapi vc1_decoder"
++vc1_xvba_hwaccel_select="xvba vc1_decoder"
+ vc1_vdpau_decoder_select="vdpau vc1_decoder"
+ vorbis_decoder_select="mdct"
+ vorbis_encoder_select="mdct"
+@@ -1327,12 +1332,14 @@
+ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
+ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
+ wmv3_vdpau_decoder_select="vc1_vdpau_decoder"
++wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel"
+ zlib_decoder_select="zlib"
+ zlib_encoder_select="zlib"
+ zmbv_decoder_select="zlib"
+ zmbv_encoder_select="zlib"
+
+ vaapi_deps="va_va_h"
++xvba_deps="amd_amdxvba_h"
+ vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
+
+ # parsers
+@@ -2762,6 +2769,7 @@
+ check_header termios.h
+ check_header vdpau/vdpau.h
+ check_header vdpau/vdpau_x11.h
++check_header amd/amdxvba.h
+ check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support
+
+ check_header X11/extensions/XvMClib.h
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/allcodecs.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/allcodecs.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/allcodecs.c 2012-03-21 23:57:47.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/allcodecs.c 2012-05-13 22:08:46.928192528 +0200
+@@ -57,13 +57,17 @@
+ REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);
+ REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
+ REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
++ REGISTER_HWACCEL (H264_XVBA, h264_xvba);
+ REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2);
+ REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
+ REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);
++ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba);
+ REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2);
+ REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi);
++ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba);
+ REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2);
+ REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi);
++ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba);
+
+ /* video codecs */
+ REGISTER_ENCODER (A64MULTI, a64multi);
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/h264.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/h264.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/h264.c 2012-03-21 23:57:45.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/h264.c 2012-05-13 22:08:46.930192568 +0200
+@@ -55,6 +55,7 @@
+ static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = {
+ PIX_FMT_DXVA2_VLD,
+ PIX_FMT_VAAPI_VLD,
++ PIX_FMT_XVBA_VLD,
+ PIX_FMT_YUVJ420P,
+ PIX_FMT_NONE
+ };
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/Makefile xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/Makefile
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/Makefile 2012-03-21 23:57:45.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/Makefile 2012-05-13 22:08:46.927192508 +0200
+@@ -3,7 +3,7 @@
+ NAME = avcodec
+ FFLIBS = avcore avutil
+
+-HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h
++HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h xvba.h
+
+ OBJS = allcodecs.o \
+ audioconvert.o \
+@@ -43,6 +43,7 @@
+ OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes)
+ OBJS-$(CONFIG_VAAPI) += vaapi.o
+ OBJS-$(CONFIG_VDPAU) += vdpau.o
++OBJS-$(CONFIG_XVBA) += xvba.o
+
+ # decoders/encoders/hardware accelerators
+ OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
+@@ -169,6 +170,7 @@
+ mpegvideo.o error_resilience.o
+ OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
+ OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
++OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o
+ OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o
+ OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o
+ OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o
+@@ -246,6 +248,7 @@
+ mpegvideo.o error_resilience.o
+ OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
+ OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
++OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o
+ OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \
+ mpegvideo.o error_resilience.o
+ OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \
+@@ -379,6 +382,7 @@
+ intrax8.o intrax8dsp.o
+ OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
+ OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
++OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o
+ OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
+ OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
+ OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
+@@ -647,6 +651,7 @@
+ SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h
+ SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h
+ SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h
++SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h
+ SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h
+ SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
+ SKIPHEADERS += mpegaudio3.h
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/mpegvideo.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/mpegvideo.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/mpegvideo.c 2012-03-21 23:57:45.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/mpegvideo.c 2012-05-13 22:08:46.933192627 +0200
+@@ -117,6 +117,7 @@
+ const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {
+ PIX_FMT_DXVA2_VLD,
+ PIX_FMT_VAAPI_VLD,
++ PIX_FMT_XVBA_VLD,
+ PIX_FMT_YUV420P,
+ PIX_FMT_NONE
+ };
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba.c 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba.c 2012-05-13 22:08:46.934192647 +0200
+@@ -0,0 +1,65 @@
++/*
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++
++/**
++ * \addtogroup XVBA_Decoding
++ *
++ * @{
++ */
++
++#include
++#include "xvba.h"
++#include "avcodec.h"
++
++int ff_xvba_translate_profile(int profile) {
++
++ if (profile == 66)
++ return 1;
++ else if (profile == 77)
++ return 2;
++ else if (profile == 100)
++ return 3;
++ else if (profile == 0)
++ return 4;
++ else if (profile == 1)
++ return 5;
++ else if (profile == 3)
++ return 6;
++ else
++ return -1;
++}
++
++void ff_xvba_add_slice_data(struct xvba_render_state *render, const void *buffer, uint32_t size) {
++
++ render->buffers = av_fast_realloc(
++ render->buffers,
++ &render->buffers_alllocated,
++ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1)
++ );
++
++ render->buffers[render->num_slices].buffer = buffer;
++ render->buffers[render->num_slices].size = size;
++
++ render->num_slices++;
++}
++
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba.h xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba.h
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba.h 2012-05-13 22:08:46.935192667 +0200
+@@ -0,0 +1,71 @@
++/*
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef AVCODEC_XVBA_H
++#define AVCODEC_XVBA_H
++
++#include
++#include
++#include
++
++
++/**
++ * \defgroup XVBA_Decoding VA API Decoding
++ * \ingroup Decoder
++ * @{
++ */
++
++/** \brief The videoSurface is used for rendering. */
++#define FF_XVBA_STATE_USED_FOR_RENDER 1
++
++/**
++ * \brief The videoSurface is needed for reference/prediction.
++ * The codec manipulates this.
++ */
++#define FF_XVBA_STATE_USED_FOR_REFERENCE 2
++
++/**
++ * \brief The videoSurface holds a decoded frame.
++ * The codec manipulates this.
++ */
++#define FF_XVBA_STATE_DECODED 4
++
++/* @} */
++
++struct xvba_bitstream_buffers
++{
++ const void *buffer;
++ unsigned int size;
++};
++
++struct xvba_render_state {
++
++ int state; ///< Holds FF_XVBA_STATE_* values.
++ void *surface;
++ XVBAPictureDescriptor *picture_descriptor;
++ XVBAQuantMatrixAvc *iq_matrix;
++ int num_slices;
++ struct xvba_bitstream_buffers *buffers;
++ uint32_t buffers_alllocated;
++};
++
++#endif /* AVCODEC_XVBA_H */
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_h264.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_h264.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_h264.c 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_h264.c 2012-05-13 22:08:46.936192687 +0200
+@@ -0,0 +1,180 @@
++/*
++ * H.264 HW decode acceleration through XVBA
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "xvba.h"
++#include "xvba_internal.h"
++#include "h264.h"
++#include
++
++/** @file
++ * This file implements the glue code between FFmpeg's and XvBA API's
++ * structures for H.264 decoding.
++ */
++
++
++/** Initialize and start decoding a frame with XVBA. */
++static int start_frame(AVCodecContext *avctx,
++ av_unused const uint8_t *buffer,
++ av_unused uint32_t size)
++{
++ H264Context * const h = avctx->priv_data;
++ MpegEncContext * const s = &h->s;
++ struct xvba_render_state *render;
++ XVBAPictureDescriptor *pic_descriptor;
++ int i;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (render->picture_descriptor == 0)
++ return -1;
++
++ pic_descriptor = render->picture_descriptor;
++
++ for (i = 0; i < 2; ++i) {
++ int foc = s->current_picture_ptr->field_poc[i];
++ if (foc == INT_MAX)
++ foc = 0;
++ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc;
++ }
++
++ pic_descriptor->avc_frame_num = h->frame_num;
++
++ render->num_slices = 0;
++
++ return 0;
++}
++
++/** End a hardware decoding based frame. */
++static int end_frame(AVCodecContext *avctx)
++{
++ H264Context * const h = avctx->priv_data;
++ MpegEncContext * const s = &h->s;
++ struct xvba_render_state *render;
++ XVBAPictureDescriptor *pic_descriptor;
++ XVBAQuantMatrixAvc *iq_matrix;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (render->picture_descriptor == 0 || render->iq_matrix == 0)
++ return -1;
++
++ pic_descriptor = render->picture_descriptor;
++ iq_matrix = render->iq_matrix;
++
++ av_dlog(avctx, "end_frame()\n");
++
++ /* Fill in Picture Parameters*/
++ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile);
++ pic_descriptor->level = avctx->level;
++ pic_descriptor->width_in_mb = s->mb_width;
++ pic_descriptor->height_in_mb = s->mb_height;
++ pic_descriptor->picture_structure = s->picture_structure;
++ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1;
++ pic_descriptor->avc_intra_flag = (h->slice_type == FF_I_TYPE) ? 1 : 0;
++ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0;
++
++ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
++ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8;
++ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4;
++ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type;
++ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
++ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count;
++ pic_descriptor->avc_reserved_8bit = 0;
++
++ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1;
++ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
++ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
++
++ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26;
++ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26;
++ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
++ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
++ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg
++ pic_descriptor->avc_reserved_16bit = 0; // must be 0
++ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0
++ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0
++
++ // sps
++ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
++ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
++ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag;
++ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag;
++ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff;
++ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag;
++ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0;
++
++ // pps
++ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac;
++ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present;
++ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred;
++ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc;
++ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
++ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred;
++ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present;
++ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode;
++ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0
++
++ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4));
++ memcpy(iq_matrix->bScalingLists8x8, h->pps.scaling_matrix8, sizeof(iq_matrix->bScalingLists8x8));
++
++ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
++ if (!h->got_first_iframe) {
++ if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE)
++ return -1;
++ h->got_first_iframe = 1;
++ }
++
++ ff_draw_horiz_band(s, 0, s->avctx->height);
++
++ return 0;
++}
++
++/** Decode the given H.264 slice with VA API. */
++static int decode_slice(AVCodecContext *avctx,
++ const uint8_t *buffer,
++ uint32_t size)
++{
++ H264Context * const h = avctx->priv_data;
++ MpegEncContext * const s = &h->s;
++ struct xvba_render_state *render;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ ff_xvba_add_slice_data(render, buffer, size);
++
++ return 0;
++}
++
++AVHWAccel ff_h264_xvba_hwaccel = {
++ .name = "h264_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_H264,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_internal.h xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_internal.h
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_internal.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_internal.h 2012-05-13 22:08:46.936192687 +0200
+@@ -0,0 +1,24 @@
++/*
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++int ff_xvba_translate_profile(int profile);
++void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size);
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_mpeg2.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_mpeg2.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_mpeg2.c 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_mpeg2.c 2012-05-13 22:08:46.937192706 +0200
+@@ -0,0 +1,52 @@
++/*
++ * MPEG-2 HW decode acceleration through XVBA
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "dsputil.h"
++
++static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
++{
++ struct MpegEncContext * const s = avctx->priv_data;
++ return 0;
++}
++
++static int end_frame(AVCodecContext *avctx)
++{
++ return 0;
++}
++
++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
++{
++ struct MpegEncContext * const s = avctx->priv_data;
++ return 0;
++}
++
++AVHWAccel ff_mpeg2_xvba_hwaccel = {
++ .name = "mpeg2_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_MPEG2VIDEO,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_vc1.c xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_vc1.c
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvba_vc1.c 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvba_vc1.c 2012-05-13 22:08:46.937192706 +0200
+@@ -0,0 +1,194 @@
++/*
++ * VC-1 HW decode acceleration through XVBA
++ *
++ * Copyright (C) 2005-2011 Team XBMC
++ *
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * FFmpeg is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "xvba.h"
++#include "xvba_internal.h"
++#include "vc1.h"
++#include "vc1data.h"
++#include
++
++
++/** @file
++ * Implement structures of ffmpeg <-> XvBA
++ */
++
++/* Initialize and start decoding a frame with XvBA */
++static int start_frame(AVCodecContext *avctx,
++ av_unused const uint8_t *buffer,
++ av_unused uint32_t size)
++{
++ VC1Context * const v = avctx->priv_data;
++ MpegEncContext * const s = &v->s;
++ struct xvba_render_state *render;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ render->num_slices = 0;
++ return 0;
++}
++
++/* End a hardware decoding based frame */
++static int end_frame(AVCodecContext *avctx)
++{
++ VC1Context* const v = avctx->priv_data;
++ MpegEncContext* const s = &v->s;
++ struct xvba_render_state *render, *last, *next;
++ XVBAPictureDescriptor *pic_descriptor;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (render->picture_descriptor == 0)
++ return -1;
++
++ pic_descriptor = render->picture_descriptor;
++
++ av_dlog(avctx, "xvba_vc1_end_frame()\n");
++
++ memset(pic_descriptor, 0, sizeof(*pic_descriptor));
++
++ /* Fill in Parameters - for reference see AMD sdk documentation */
++ pic_descriptor->profile = ff_xvba_translate_profile(v->profile);
++ pic_descriptor->level = v->level;
++ //done like in va-driver and vaapi
++ if (v->profile == PROFILE_ADVANCED) {
++ pic_descriptor->width_in_mb = s->avctx->coded_width;
++ pic_descriptor->height_in_mb = s->avctx->coded_height;
++ } else {
++ pic_descriptor->width_in_mb = s->mb_width;
++ pic_descriptor->height_in_mb = s->mb_height;
++ }
++ pic_descriptor->picture_structure = s->picture_structure;
++ // xvba-video set this to 1 only 4:2:0 supported
++ // doc says: if not set, choose 1 - we try this
++ pic_descriptor->chroma_format = 1;
++ pic_descriptor->avc_intra_flag = s->pict_type == FF_I_TYPE || v->bi_type == 1;
++ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0;
++
++ // VC-1 explicit parameters see page 30 of sdk
++ // sps_info
++ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag;
++
++ // done as in vaapi
++ pic_descriptor->sps_info.vc1.pulldown = v->broadcast;
++ pic_descriptor->sps_info.vc1.interlace = v->interlace;
++ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag;
++ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag;
++ pic_descriptor->sps_info.vc1.reserved = 1;
++ // eventually check if this makes sense together with interlace
++ pic_descriptor->sps_info.vc1.psf = v->psf;
++ // what about if it is a frame (page 31)
++ // looked at xvba-driver
++ pic_descriptor->sps_info.vc1.second_field = !s->first_field;
++ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0;
++
++ // VC-1 explicit parameters see page 30 of sdk
++ // pps_info
++ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag;
++ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag;
++ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter;
++ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc;
++ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv;
++ pic_descriptor->pps_info.vc1.dquant = v->dquant;
++ pic_descriptor->pps_info.vc1.vstransform = v->vstransform;
++ pic_descriptor->pps_info.vc1.overlap = v->overlap;
++ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode;
++ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv;
++ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames;
++ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered;
++ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker;
++ pic_descriptor->pps_info.vc1.multires = v->multires;
++ pic_descriptor->pps_info.vc1.reserved = 1;
++ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag;
++ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy;
++ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag;
++ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv;
++ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0;
++
++ pic_descriptor->past_surface = 0;
++ pic_descriptor->future_surface = 0;
++ switch (s->pict_type) {
++ case FF_B_TYPE:
++ next = (struct xvba_render_state *)s->next_picture.data[0];
++ assert(next);
++ if (next)
++ pic_descriptor->past_surface = next->surface;
++ // fall-through
++ case FF_P_TYPE:
++ last = (struct xvba_render_state *)s->last_picture.data[0];
++ assert(last);
++ if (last)
++ pic_descriptor->future_surface = last->surface;
++ break;
++ }
++
++ ff_draw_horiz_band(s, 0, s->avctx->height);
++
++ return 0;
++}
++
++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
++{
++ VC1Context* const v = avctx->priv_data;
++ MpegEncContext* const s = &v->s;
++ struct xvba_render_state *render;
++
++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
++ assert(render);
++
++ if (avctx->codec_id == CODEC_ID_VC1 &&
++ size >= 4 && IS_MARKER(AV_RB32(buffer))) {
++ buffer += 4;
++ size -= 4;
++ }
++
++ ff_xvba_add_slice_data(render, buffer, size);
++
++ return 0;
++}
++
++#if CONFIG_WMV3_XVBA_HWACCEL
++AVHWAccel ff_wmv3_xvba_hwaccel = {
++ .name = "wmv3_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_WMV3,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
++#endif
++
++AVHWAccel ff_vc1_xvba_hwaccel = {
++ .name = "vc1_xvba",
++ .type = AVMEDIA_TYPE_VIDEO,
++ .id = CODEC_ID_VC1,
++ .pix_fmt = PIX_FMT_XVBA_VLD,
++ .capabilities = 0,
++ .start_frame = start_frame,
++ .end_frame = end_frame,
++ .decode_slice = decode_slice,
++ .priv_data_size = 0,
++};
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavcodec/xvmc_internal.h xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvmc_internal.h
+--- xbmc-11.0.1/lib/ffmpeg/libavcodec/xvmc_internal.h 2012-03-21 23:57:47.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavcodec/xvmc_internal.h 2012-05-13 22:08:46.938192726 +0200
+@@ -1,5 +1,7 @@
+ /*
+- * XVideo Motion Compensation internal functions
++ * HW decode acceleration for MPEG-2, H.264 and VC-1
++ *
++ * Copyright (C) 2005-2011 Team XBMC
+ *
+ * This file is part of FFmpeg.
+ *
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavutil/pixdesc.c xbmc-11.0.1.patch/lib/ffmpeg/libavutil/pixdesc.c
+--- xbmc-11.0.1/lib/ffmpeg/libavutil/pixdesc.c 2012-03-21 23:57:44.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavutil/pixdesc.c 2012-05-13 22:08:46.939192746 +0200
+@@ -717,6 +717,12 @@
+ .log2_chroma_h = 1,
+ .flags = PIX_FMT_HWACCEL,
+ },
++ [PIX_FMT_XVBA_VLD] = {
++ .name = "xvba_vld",
++ .log2_chroma_w = 1,
++ .log2_chroma_h = 1,
++ .flags = PIX_FMT_HWACCEL,
++ },
+ [PIX_FMT_YUV420P16LE] = {
+ .name = "yuv420p16le",
+ .nb_components= 3,
+diff -Naur xbmc-11.0.1/lib/ffmpeg/libavutil/pixfmt.h xbmc-11.0.1.patch/lib/ffmpeg/libavutil/pixfmt.h
+--- xbmc-11.0.1/lib/ffmpeg/libavutil/pixfmt.h 2012-03-21 23:57:44.000000000 +0100
++++ xbmc-11.0.1.patch/lib/ffmpeg/libavutil/pixfmt.h 2012-05-13 22:08:46.939192746 +0200
+@@ -127,6 +127,7 @@
+ PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+ PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
++ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+
+ PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0
+ PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0
+diff -Naur xbmc-11.0.1/lib/UnrarXLib/extract.cpp xbmc-11.0.1.patch/lib/UnrarXLib/extract.cpp
+--- xbmc-11.0.1/lib/UnrarXLib/extract.cpp 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/lib/UnrarXLib/extract.cpp 2012-05-13 22:08:46.773189450 +0200
+@@ -1,9 +1,5 @@
+ #include "rar.hpp"
+ #include "Util.h"
+-#ifdef _LINUX
+-#include "XSyncUtils.h"
+-#include "XEventUtils.h"
+-#endif
+
+ // a cautious wrapper around strncpy
+ char *strncpy_null_terminated(char *dest, const char *src, size_t n)
+diff -Naur xbmc-11.0.1/lib/UnrarXLib/unpack15.cpp xbmc-11.0.1.patch/lib/UnrarXLib/unpack15.cpp
+--- xbmc-11.0.1/lib/UnrarXLib/unpack15.cpp 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/lib/UnrarXLib/unpack15.cpp 2012-05-13 22:08:46.774189470 +0200
+@@ -1,7 +1,3 @@
+-#ifdef _LINUX
+-#include "XSyncUtils.h"
+-#endif
+-
+ #define STARTL1 2
+ static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
+ 0xee00,0xf000,0xf200,0xf200,0xffff};
+diff -Naur xbmc-11.0.1/lib/UnrarXLib/unpack.cpp xbmc-11.0.1.patch/lib/UnrarXLib/unpack.cpp
+--- xbmc-11.0.1/lib/UnrarXLib/unpack.cpp 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/lib/UnrarXLib/unpack.cpp 2012-05-13 22:08:46.774189470 +0200
+@@ -8,11 +8,6 @@
+ #include "unpack20.cpp"
+ #endif
+
+-#ifdef _LINUX
+-#include "XSyncUtils.h"
+-#include "XEventUtils.h"
+-#endif
+-
+ Unpack::Unpack(ComprDataIO *DataIO)
+ {
+ UnpIO=DataIO;
+diff -Naur xbmc-11.0.1/system/shaders/yuv2rgb_basic.glsl xbmc-11.0.1.patch/system/shaders/yuv2rgb_basic.glsl
+--- xbmc-11.0.1/system/shaders/yuv2rgb_basic.glsl 2012-03-21 23:57:58.000000000 +0100
++++ xbmc-11.0.1.patch/system/shaders/yuv2rgb_basic.glsl 2012-05-13 22:01:28.506492824 +0200
+@@ -70,6 +70,18 @@
+ rgb.a = gl_Color.a;
+ gl_FragColor = rgb;
+
++#elif defined(XBMC_VDPAU_NV12)
++
++ vec4 yuv, rgb;
++ yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r
++ , texture2D(m_sampU, stretch(m_cordU)).r
++ , texture2D(m_sampV, stretch(m_cordV)).g
++ , 1.0 );
++
++ rgb = m_yuvmat * yuv;
++ rgb.a = gl_Color.a;
++ gl_FragColor = rgb;
++
+ #elif defined(XBMC_YUY2) || defined(XBMC_UYVY)
+
+ #if(XBMC_texture_rectangle)
+diff -Naur xbmc-11.0.1/xbmc/Application.cpp xbmc-11.0.1.patch/xbmc/Application.cpp
+--- xbmc-11.0.1/xbmc/Application.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/Application.cpp 2012-05-13 22:08:46.751189015 +0200
+@@ -369,8 +369,6 @@
+ #endif
+ m_currentStack = new CFileItemList;
+
+- m_frameCount = 0;
+-
+ m_bPresentFrame = false;
+ m_bPlatformDirectories = true;
+
+@@ -1965,28 +1963,18 @@
+
+ bool CApplication::WaitFrame(unsigned int timeout)
+ {
+- bool done = false;
+-
+ // Wait for all other frames to be presented
+- CSingleLock lock(m_frameMutex);
+- //wait until event is set, but modify remaining time
++ m_frameEvent.Reset();
+
+- TightConditionVariable > cv(m_frameCond, InversePredicate(m_frameCount));
+- cv.wait(lock,timeout);
+- done = m_frameCount == 0;
++ if (!g_renderManager.HasFrame() && !m_frameEvent.WaitMSec(timeout))
++ return false;
+
+- return done;
++ return g_renderManager.HasFrame();
+ }
+
+ void CApplication::NewFrame()
+ {
+- // We just posted another frame. Keep track and notify.
+- {
+- CSingleLock lock(m_frameMutex);
+- m_frameCount++;
+- }
+-
+- m_frameCond.notifyAll();
++ m_frameEvent.Set();
+ }
+
+ void CApplication::Render()
+@@ -2020,12 +2008,13 @@
+ m_bPresentFrame = false;
+ if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
+ {
+- CSingleLock lock(m_frameMutex);
+-
+- TightConditionVariable cv(m_frameCond,m_frameCount);
+- cv.wait(lock,100);
++ uint64_t timeout = CurrentHostCounter() + CurrentHostFrequency()/10;
++ while (!g_renderManager.HasFrame() && CurrentHostCounter() < timeout)
++ {
++ m_frameEvent.WaitMSec(100);
++ }
++ m_bPresentFrame = g_renderManager.HasFrame();
+
+- m_bPresentFrame = m_frameCount > 0;
+ decrement = m_bPresentFrame;
+ hasRendered = true;
+ }
+@@ -2108,18 +2097,14 @@
+ m_lastFrameTime = XbmcThreads::SystemClockMillis();
+
+ if (flip)
++ {
+ g_graphicsContext.Flip(dirtyRegions);
++ g_renderManager.NotifyDisplayFlip();
++ }
+ CTimeUtils::UpdateFrameTime(flip);
+
+ g_renderManager.UpdateResolution();
+ g_renderManager.ManageCaptures();
+-
+- {
+- CSingleLock lock(m_frameMutex);
+- if(m_frameCount > 0 && decrement)
+- m_frameCount--;
+- }
+- m_frameCond.notifyAll();
+ }
+
+ void CApplication::SetStandAlone(bool value)
+@@ -5303,12 +5288,6 @@
+ // See if we're playing a video, and are in GUI mode
+ if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
+ {
+- // Reset frame count so that timing is FPS will be correct.
+- {
+- CSingleLock lock(m_frameMutex);
+- m_frameCount = 0;
+- }
+-
+ // then switch to fullscreen mode
+ g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
+ return true;
+@@ -5479,7 +5458,6 @@
+
+ bool CApplication::IsPresentFrame()
+ {
+- CSingleLock lock(m_frameMutex);
+ bool ret = m_bPresentFrame;
+
+ return ret;
+diff -Naur xbmc-11.0.1/xbmc/Application.h xbmc-11.0.1.patch/xbmc/Application.h
+--- xbmc-11.0.1/xbmc/Application.h 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/Application.h 2012-05-13 22:08:46.752189035 +0200
+@@ -343,9 +343,7 @@
+ bool m_bTestMode;
+ bool m_bSystemScreenSaverEnable;
+
+- int m_frameCount;
+- CCriticalSection m_frameMutex;
+- XbmcThreads::ConditionVariable m_frameCond;
++ CEvent m_frameEvent;
+
+ void Mute();
+ void UnMute();
+diff -Naur xbmc-11.0.1/xbmc/ApplicationMessenger.cpp xbmc-11.0.1.patch/xbmc/ApplicationMessenger.cpp
+--- xbmc-11.0.1/xbmc/ApplicationMessenger.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/ApplicationMessenger.cpp 2012-05-13 22:08:46.776189511 +0200
+@@ -73,7 +73,7 @@
+
+ using namespace std;
+
+-CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay)
++CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("CDelayedMessage")
+ {
+ m_msg.dwMessage = msg.dwMessage;
+ m_msg.dwParam1 = msg.dwParam1;
+diff -Naur xbmc-11.0.1/xbmc/cdrip/CDDAReader.cpp xbmc-11.0.1.patch/xbmc/cdrip/CDDAReader.cpp
+--- xbmc-11.0.1/xbmc/cdrip/CDDAReader.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cdrip/CDDAReader.cpp 2012-05-13 22:08:46.776189511 +0200
+@@ -29,7 +29,7 @@
+
+ #define SECTOR_COUNT 52
+
+-CCDDAReader::CCDDAReader()
++CCDDAReader::CCDDAReader() : CThread("CCDDAReader")
+ {
+ m_sRipBuffer[0].pbtStream = NULL;
+ m_sRipBuffer[1].pbtStream = NULL;
+diff -Naur xbmc-11.0.1/xbmc/cores/DllLoader/exports/emu_kernel32.cpp xbmc-11.0.1.patch/xbmc/cores/DllLoader/exports/emu_kernel32.cpp
+--- xbmc-11.0.1/xbmc/cores/DllLoader/exports/emu_kernel32.cpp 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/DllLoader/exports/emu_kernel32.cpp 2012-05-13 22:08:46.777189531 +0200
+@@ -240,15 +240,6 @@
+ #endif
+ }
+
+-extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
+-{
+- // since the xbox has only one process, we just take the current thread
+- HANDLE h = GetCurrentThread();
+- BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime);
+-
+- return res;
+-}
+-
+ extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
+ HANDLE hSourceHandle, // handle to duplicate
+ HANDLE hTargetProcessHandle, // handle to target process
+diff -Naur xbmc-11.0.1/xbmc/cores/DllLoader/exports/emu_kernel32.h xbmc-11.0.1.patch/xbmc/cores/DllLoader/exports/emu_kernel32.h
+--- xbmc-11.0.1/xbmc/cores/DllLoader/exports/emu_kernel32.h 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/DllLoader/exports/emu_kernel32.h 2012-05-13 22:08:46.778189551 +0200
+@@ -686,7 +686,6 @@
+
+ extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE module, HRSRC res);
+ extern "C" HRSRC WINAPI dllFindResourceA(HMODULE module, LPCTSTR name, LPCTSTR type);
+-extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
+ extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData);
+ extern "C" UINT WINAPI dllGetConsoleCP();
+ extern "C" UINT WINAPI dllGetConsoleOutputCP();
+diff -Naur xbmc-11.0.1/xbmc/cores/DummyVideoPlayer.cpp xbmc-11.0.1.patch/xbmc/cores/DummyVideoPlayer.cpp
+--- xbmc-11.0.1/xbmc/cores/DummyVideoPlayer.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/DummyVideoPlayer.cpp 2012-05-13 22:08:46.778189551 +0200
+@@ -33,7 +33,7 @@
+
+ CDummyVideoPlayer::CDummyVideoPlayer(IPlayerCallback& callback)
+ : IPlayer(callback),
+- CThread()
++ CThread("CDummyVideoPlayer")
+ {
+ m_paused = false;
+ m_clock = 0;
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp 2012-05-13 22:08:46.780189591 +0200
+@@ -325,7 +325,7 @@
+ #pragma mark -
+ #endif
+ CMPCOutputThread::CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015) :
+- CThread(),
++ CThread("CMPCOutputThread"),
+ m_dll(dll),
+ m_device(device),
+ m_has_bcm70015(has_bcm70015),
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp 2012-05-13 22:08:46.978193519 +0200
+@@ -56,6 +56,9 @@
+ #ifdef HAVE_LIBVA
+ #include "VAAPI.h"
+ #endif
++#ifdef HAVE_LIBXVBA
++#include "XVBA.h"
++#endif
+
+ using namespace boost;
+
+@@ -71,14 +74,14 @@
+ while(*cur != PIX_FMT_NONE)
+ {
+ #ifdef HAVE_LIBVDPAU
+- if(CVDPAU::IsVDPAUFormat(*cur) && g_guiSettings.GetBool("videoplayer.usevdpau"))
++ if(VDPAU::CDecoder::IsVDPAUFormat(*cur) && g_guiSettings.GetBool("videoplayer.usevdpau"))
+ {
+ if(ctx->GetHardware())
+ return *cur;
+
+ CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::GetFormat - Creating VDPAU(%ix%i)", avctx->width, avctx->height);
+- CVDPAU* vdp = new CVDPAU();
+- if(vdp->Open(avctx, *cur))
++ VDPAU::CDecoder* vdp = new VDPAU::CDecoder();
++ if(vdp->Open(avctx, *cur, ctx->m_uSurfacesCount))
+ {
+ ctx->SetHardware(vdp);
+ return *cur;
+@@ -100,6 +103,19 @@
+ dec->Release();
+ }
+ #endif
++#ifdef HAVE_LIBXVBA
++ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba"))
++ {
++ XVBA::CDecoder* dec = new XVBA::CDecoder();
++ if(dec->Open(avctx, *cur))
++ {
++ ctx->SetHardware(dec);
++ return *cur;
++ }
++ else
++ dec->Release();
++ }
++#endif
+ #ifdef HAVE_LIBVA
+ // mpeg4 vaapi decoding is disabled
+ if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi")
+@@ -142,6 +158,7 @@
+ m_iLastKeyframe = 0;
+ m_dts = DVD_NOPTS_VALUE;
+ m_started = false;
++ m_decoderPts = DVD_NOPTS_VALUE;
+ }
+
+ CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
+@@ -195,13 +212,25 @@
+ continue;
+
+ CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::Open() Creating VDPAU(%ix%i, %d)",hints.width, hints.height, hints.codec);
+- CVDPAU* vdp = new CVDPAU();
++ VDPAU::CDecoder* vdp = new VDPAU::CDecoder();
+ m_pCodecContext->codec_id = hints.codec;
+ m_pCodecContext->width = hints.width;
+ m_pCodecContext->height = hints.height;
+ m_pCodecContext->coded_width = hints.width;
+ m_pCodecContext->coded_height = hints.height;
+- if(vdp->Open(m_pCodecContext, pCodec->pix_fmts ? pCodec->pix_fmts[0] : PIX_FMT_NONE))
++
++ // check number of surfaces used in renderer
++ unsigned int surfaces = 0;
++ for(CDVDCodecOptions::iterator it = options.begin(); it != options.end(); it++)
++ {
++ if (it->m_name == "surfaces")
++ {
++ surfaces = std::atoi(it->m_value.c_str());
++ break;
++ }
++ }
++
++ if(vdp->Open(m_pCodecContext, pCodec->pix_fmts ? pCodec->pix_fmts[0] : PIX_FMT_NONE, surfaces))
+ {
+ m_pHardware = vdp;
+ m_pCodecContext->codec_id = CODEC_ID_NONE; // ffmpeg will complain if this has been set
+@@ -338,6 +367,14 @@
+ {
+ if( m_pCodecContext )
+ {
++ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint())
++ {
++ m_requestSkipDeint = true;
++ bDrop = false;
++ }
++ else
++ m_requestSkipDeint = false;
++
+ // i don't know exactly how high this should be set
+ // couldn't find any good docs on it. think it varies
+ // from codec to codec on what it does
+@@ -558,6 +595,7 @@
+ void CDVDVideoCodecFFmpeg::Reset()
+ {
+ m_started = false;
++ m_decoderPts = DVD_NOPTS_VALUE;
+ m_iLastKeyframe = m_pCodecContext->has_b_frames;
+ m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
+
+@@ -663,6 +701,22 @@
+ else
+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
+
++ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE)
++ m_decoderPts = pDvdVideoPicture->pts;
++ else
++ m_decoderPts = m_dts;
++
++ if (m_requestSkipDeint)
++ {
++ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT;
++ m_skippedDeint = 1;
++ }
++ else
++ m_skippedDeint = 0;
++
++ m_requestSkipDeint = false;
++ pDvdVideoPicture->iFlags |= m_codecControlState;
++
+ if(!m_started)
+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
+
+@@ -883,3 +937,14 @@
+ else
+ return 0;
+ }
++
++void CDVDVideoCodecFFmpeg::SetSpeed(int speed)
++{
++ if (m_pHardware)
++ m_pHardware->SetSpeed(speed);
++}
++
++void CDVDVideoCodecFFmpeg::SetCodecControl(int state)
++{
++ m_codecControlState = state;
++}
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h 2012-05-13 22:08:46.989193738 +0200
+@@ -29,7 +29,6 @@
+ #include "DllSwScale.h"
+ #include "DllAvFilter.h"
+
+-class CVDPAU;
+ class CCriticalSection;
+
+ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
+@@ -45,6 +44,8 @@
+ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) = 0;
+ virtual int Check (AVCodecContext* avctx) = 0;
+ virtual void Reset () {}
++ virtual bool CanSkipDeint() {return false; }
++ virtual void SetSpeed(int speed) {}
+ virtual const std::string Name() = 0;
+ virtual CCriticalSection* Section() { return NULL; }
+ };
+@@ -61,6 +62,9 @@
+ virtual unsigned int SetFilters(unsigned int filters);
+ virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
+ virtual unsigned GetConvergeCount();
++ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;}
++ virtual void SetSpeed(int speed);
++ virtual void SetCodecControl(int state);
+
+ bool IsHardwareAllowed() { return !m_bSoftware; }
+ IHardwareDecoder * GetHardware() { return m_pHardware; };
+@@ -109,4 +113,8 @@
+ int m_iLastKeyframe;
+ double m_dts;
+ bool m_started;
++ double m_decoderPts, m_decoderInterval;
++ int m_skippedDeint;
++ bool m_requestSkipDeint;
++ int m_codecControlState;
+ };
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2012-05-13 22:08:46.989193738 +0200
+@@ -34,7 +34,8 @@
+
+ namespace DXVA { class CSurfaceContext; }
+ namespace VAAPI { struct CHolder; }
+-class CVDPAU;
++namespace VDPAU { class CVdpauRenderPicture; }
++namespace XVBA { class CXvbaRenderPicture; }
+ class COpenMax;
+ class COpenMaxVideo;
+ struct OpenMaxVideoBuffer;
+@@ -59,11 +60,14 @@
+ DXVA::CSurfaceContext* context;
+ };
+ struct {
+- CVDPAU* vdpau;
++ VDPAU::CVdpauRenderPicture* vdpau;
+ };
+ struct {
+ VAAPI::CHolder* vaapi;
+ };
++ struct {
++ XVBA::CXvbaRenderPicture* xvba;
++ };
+
+ struct {
+ COpenMax *openMax;
+@@ -102,6 +106,7 @@
+ enum EFormat {
+ FMT_YUV420P = 0,
+ FMT_VDPAU,
++ FMT_VDPAU_420,
+ FMT_NV12,
+ FMT_UYVY,
+ FMT_YUY2,
+@@ -109,6 +114,7 @@
+ FMT_VAAPI,
+ FMT_OMXEGL,
+ FMT_CVBREF,
++ FMT_XVBA,
+ } format;
+ };
+
+@@ -125,6 +131,10 @@
+
+ #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped
+ #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data
++#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage
++
++#define DVP_FLAG_SKIP_PROC 0x00000100
++#define DVP_FLAG_DRAIN 0x00000200
+
+ // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2!
+
+@@ -143,6 +153,10 @@
+ #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data
+ #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data
+ #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again
++#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped
++#define VC_HURRY 0x00000040
++#define VC_SKIPPROC 0x00000080
++
+ class CDVDVideoCodec
+ {
+ public:
+@@ -207,7 +221,6 @@
+ */
+ virtual void SetDropState(bool bDrop) = 0;
+
+-
+ enum EFilterFlags {
+ FILTER_NONE = 0x0,
+ FILTER_DEINTERLACE_YADIF = 0x1, /* use first deinterlace mode */
+@@ -237,4 +250,16 @@
+ {
+ return 0;
+ }
++
++ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced)
++ {
++ return false;
++ }
++
++ virtual void SetSpeed(int speed)
++ {
++ return;
++ }
++
++ virtual void SetCodecControl(int state) {}
+ };
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2012-05-13 22:08:46.950192964 +0200
+@@ -17,6 +17,10 @@
+ DVDVideoCodecCrystalHD.cpp \
+
+ endif
++ifeq (@USE_XVBA@,1)
++SRCS+= XVBA.cpp \
++
++endif
+ ifeq (@USE_VDA@,1)
+ SRCS+= DVDVideoCodecVDA.cpp \
+
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp 2012-05-13 22:08:47.058195107 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2005-2009 Team XBMC
++ * Copyright (C) 2005-2011 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+@@ -33,11 +33,16 @@
+ #include "settings/AdvancedSettings.h"
+ #include "Application.h"
+ #include "utils/MathUtils.h"
++#include "utils/TimeUtils.h"
+ #include "DVDCodecs/DVDCodecUtils.h"
++#include "cores/VideoRenderers/RenderFlags.h"
++
++using namespace VDPAU;
++#define NUM_RENDER_PICS 9
+
+ #define ARSIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+-CVDPAU::Desc decoder_profiles[] = {
++CDecoder::Desc decoder_profiles[] = {
+ {"MPEG1", VDP_DECODER_PROFILE_MPEG1},
+ {"MPEG2_SIMPLE", VDP_DECODER_PROFILE_MPEG2_SIMPLE},
+ {"MPEG2_MAIN", VDP_DECODER_PROFILE_MPEG2_MAIN},
+@@ -51,14 +56,16 @@
+ {"MPEG4_PART2_ASP", VDP_DECODER_PROFILE_MPEG4_PART2_ASP},
+ #endif
+ };
+-const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CVDPAU::Desc);
++const size_t decoder_profile_count = sizeof(decoder_profiles)/sizeof(CDecoder::Desc);
+
+-static float studioCSC[3][4] =
+-{
+- { 1.0f, 0.0f, 1.57480000f,-0.78740000f},
+- { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f},
+- { 1.0f, 1.85556000f, 0.0f,-0.92780000f}
+-};
++//static float studioCSC[3][4] =
++//{
++// { 1.0f, 0.0f, 1.57480000f,-0.78740000f},
++// { 1.0f,-0.18737736f,-0.46813736f, 0.32775736f},
++// { 1.0f, 1.85556000f, 0.0f,-0.92780000f}
++//};
++static float studioCSCKCoeffs601[3] = {0.299, 0.587, 0.114}; //BT601 {Kr, Kg, Kb}
++static float studioCSCKCoeffs709[3] = {0.2126, 0.7152, 0.0722}; //BT709 {Kr, Kg, Kb}
+
+ static struct SInterlaceMapping
+ {
+@@ -69,59 +76,32 @@
+ , {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL}
+ , {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL}
+ , {VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL}
+-, {VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE}
++, {VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE}
+ , {VS_INTERLACEMETHOD_NONE , (VdpVideoMixerFeature)-1}
+ };
+
+ //since libvdpau 0.4, vdp_device_create_x11() installs a callback on the Display*,
+ //if we unload libvdpau with dlclose(), we segfault on XCloseDisplay,
+ //so we just keep a static handle to libvdpau around
+-void* CVDPAU::dl_handle;
+-
+-CVDPAU::CVDPAU()
+-{
+- glXBindTexImageEXT = NULL;
+- glXReleaseTexImageEXT = NULL;
+- vdp_device = VDP_INVALID_HANDLE;
+- surfaceNum = presentSurfaceNum = 0;
+- picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
+- vdpauConfigured = false;
+- m_DisplayState = VDPAU_OPEN;
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
+- m_mixerstep = 0;
++void* CDecoder::dl_handle;
+
+- m_glPixmap = 0;
+- m_Pixmap = 0;
+- if (!glXBindTexImageEXT)
+- glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
+- if (!glXReleaseTexImageEXT)
+- glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXReleaseTexImageEXT");
+-
+- totalAvailableOutputSurfaces = 0;
+- outputSurface = presentSurface = VDP_INVALID_HANDLE;
+- vdp_flip_target = VDP_INVALID_HANDLE;
+- vdp_flip_queue = VDP_INVALID_HANDLE;
+- vid_width = vid_height = OutWidth = OutHeight = 0;
+- memset(&outRect, 0, sizeof(VdpRect));
+- memset(&outRectVid, 0, sizeof(VdpRect));
+-
+- tmpBrightness = 0;
+- tmpContrast = 0;
+- tmpDeintMode = 0;
+- tmpDeintGUI = 0;
+- tmpDeint = 0;
+- max_references = 0;
+-
+- for (int i = 0; i < NUM_OUTPUT_SURFACES; i++)
+- outputSurfaces[i] = VDP_INVALID_HANDLE;
++//-----------------------------------------------------------------------------
++// CVDPAU
++//-----------------------------------------------------------------------------
+
+- videoMixer = VDP_INVALID_HANDLE;
+- m_BlackBar = NULL;
++CDecoder::CDecoder() : m_vdpauOutput(&m_inMsgEvent)
++{
++ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
++ m_vdpauConfig.videoSurfaces = &m_videoSurfaces;
++ m_vdpauConfig.videoSurfaceSec = &m_videoSurfaceSec;
+
+- upScale = g_advancedSettings.m_videoVDPAUScaling;
++ m_picAge.b_age = m_picAge.ip_age[0] = m_picAge.ip_age[1] = 256*256*256*64;
++ m_vdpauConfigured = false;
++ m_DisplayState = VDPAU_OPEN;
++ m_speed = DVD_PLAYSPEED_NORMAL;
+ }
+
+-bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces)
++bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces)
+ {
+ if(avctx->coded_width == 0
+ || avctx->coded_height == 0)
+@@ -129,6 +109,8 @@
+ CLog::Log(LOGWARNING,"(VDPAU) no width/height available, can't init");
+ return false;
+ }
++ m_vdpauConfig.numRenderBuffers = surfaces;
++ m_decoderThread = CThread::GetCurrentThreadId();
+
+ if (!dl_handle)
+ {
+@@ -140,8 +122,6 @@
+ error = "dlerror() returned NULL";
+
+ CLog::Log(LOGNOTICE,"(VDPAU) Unable to get handle to libvdpau: %s", error);
+- //g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "VDPAU", error, 10000);
+-
+ return false;
+ }
+ }
+@@ -150,8 +130,9 @@
+ return false;
+
+ InitVDPAUProcs();
++ m_presentPicture = 0;
+
+- if (vdp_device != VDP_INVALID_HANDLE)
++ if (m_vdpauConfig.vdpDevice != VDP_INVALID_HANDLE)
+ {
+ SpewHardwareAvailable();
+
+@@ -169,25 +150,23 @@
+
+ /* attempt to create a decoder with this width/height, some sizes are not supported by hw */
+ VdpStatus vdp_st;
+- vdp_st = vdp_decoder_create(vdp_device, profile, avctx->coded_width, avctx->coded_height, 5, &decoder);
++ vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_create(m_vdpauConfig.vdpDevice, profile, avctx->coded_width, avctx->coded_height, 5, &m_vdpauConfig.vdpDecoder);
+
+ if(vdp_st != VDP_STATUS_OK)
+ {
+- CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) checking for decoder support\n", vdp_get_error_string(vdp_st), vdp_st);
++ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) checking for decoder support\n", m_vdpauConfig.vdpProcs.vdp_get_error_string(vdp_st), vdp_st);
+ FiniVDPAUProcs();
+ return false;
+ }
+
+- vdp_decoder_destroy(decoder);
++ m_vdpauConfig.vdpProcs.vdp_decoder_destroy(m_vdpauConfig.vdpDecoder);
+ CheckStatus(vdp_st, __LINE__);
+ }
+
+- InitCSCMatrix(avctx->coded_height);
+-
+ /* finally setup ffmpeg */
+- avctx->get_buffer = CVDPAU::FFGetBuffer;
+- avctx->release_buffer = CVDPAU::FFReleaseBuffer;
+- avctx->draw_horiz_band = CVDPAU::FFDrawSlice;
++ avctx->get_buffer = CDecoder::FFGetBuffer;
++ avctx->release_buffer = CDecoder::FFReleaseBuffer;
++ avctx->draw_horiz_band = CDecoder::FFDrawSlice;
+ avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
+
+ g_Windowing.Register(this);
+@@ -196,17 +175,20 @@
+ return false;
+ }
+
+-CVDPAU::~CVDPAU()
++CDecoder::~CDecoder()
+ {
+ Close();
+ }
+
+-void CVDPAU::Close()
++void CDecoder::Close()
+ {
+ CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__);
+
++ CSingleLock lock(m_DecoderSection);
++
+ FiniVDPAUOutput();
+ FiniVDPAUProcs();
++ m_vdpauOutput.Dispose();
+
+ while (!m_videoSurfaces.empty())
+ {
+@@ -222,188 +204,118 @@
+ m_dllAvUtil.Unload();
+ }
+
+-bool CVDPAU::MakePixmapGL()
++long CDecoder::Release()
+ {
+- int num=0;
+- int fbConfigIndex = 0;
+-
+- int doubleVisAttributes[] = {
+- GLX_RENDER_TYPE, GLX_RGBA_BIT,
+- GLX_RED_SIZE, 8,
+- GLX_GREEN_SIZE, 8,
+- GLX_BLUE_SIZE, 8,
+- GLX_ALPHA_SIZE, 8,
+- GLX_DEPTH_SIZE, 8,
+- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+- GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
+- GLX_DOUBLEBUFFER, True,
+- GLX_Y_INVERTED_EXT, True,
+- GLX_X_RENDERABLE, True,
+- None
+- };
+-
+- int pixmapAttribs[] = {
+- GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+- GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+- None
+- };
++ // check if we should do some pre-cleanup here
++ // a second decoder might need resources
++ if (m_vdpauConfigured == true)
++ {
++ CSingleLock lock(m_DecoderSection);
++ CLog::Log(LOGNOTICE,"CVDPAU::Release pre-cleanup");
++
++ Message *reply;
++ if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP,
++ &reply,
++ 2000))
++ {
++ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
++ reply->Release();
++ if (!success)
++ {
++ CLog::Log(LOGERROR, "VDPAU::%s - pre-cleanup returned error", __FUNCTION__);
++ m_DisplayState = VDPAU_ERROR;
++ }
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "VDPAU::%s - pre-cleanup timed out", __FUNCTION__);
++ m_DisplayState = VDPAU_ERROR;
++ }
+
+- GLXFBConfig *fbConfigs;
+- fbConfigs = glXChooseFBConfig(m_Display, DefaultScreen(m_Display), doubleVisAttributes, &num);
+- if (fbConfigs==NULL)
+- {
+- CLog::Log(LOGERROR, "GLX Error: MakePixmap: No compatible framebuffers found");
+- return false;
++ for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
++ {
++ vdpau_render_state *render = m_videoSurfaces[i];
++ if (render->surface != VDP_INVALID_HANDLE && !(render->state & FF_VDPAU_STATE_USED_FOR_RENDER))
++ {
++ m_vdpauConfig.vdpProcs.vdp_video_surface_destroy(render->surface);
++ render->surface = VDP_INVALID_HANDLE;
++ }
++ }
+ }
+- CLog::Log(LOGDEBUG, "Found %d fbconfigs.", num);
+- fbConfigIndex = 0;
+- CLog::Log(LOGDEBUG, "Using fbconfig index %d.", fbConfigIndex);
++ IHardwareDecoder::Release();
++}
+
+- m_glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], m_Pixmap, pixmapAttribs);
++long CDecoder::ReleasePicReference()
++{
++ return IHardwareDecoder::Release();
++}
+
+- if (!m_glPixmap)
++void CDecoder::SetWidthHeight(int width, int height)
++{
++ int vdpauMaxHeight = g_advancedSettings.m_videoVDPAUmaxHeight;
++ if (vdpauMaxHeight > 0 && height > vdpauMaxHeight)
+ {
+- CLog::Log(LOGINFO, "GLX Error: Could not create Pixmap");
+- XFree(fbConfigs);
+- return false;
++ width = MathUtils::round_int((double)width * vdpauMaxHeight / height);
++ height = vdpauMaxHeight;
+ }
+- XFree(fbConfigs);
+
+- return true;
+-}
++ m_vdpauConfig.upscale = g_advancedSettings.m_videoVDPAUScaling;
+
+-bool CVDPAU::MakePixmap(int width, int height)
+-{
+ //pick the smallest dimensions, so we downscale with vdpau and upscale with opengl when appropriate
+ //this requires the least amount of gpu memory bandwidth
+- if (g_graphicsContext.GetWidth() < width || g_graphicsContext.GetHeight() < height || upScale)
++ if (g_graphicsContext.GetWidth() < width || g_graphicsContext.GetHeight() < height || m_vdpauConfig.upscale >= 0)
+ {
+ //scale width to desktop size if the aspect ratio is the same or bigger than the desktop
+ if ((double)height * g_graphicsContext.GetWidth() / width <= (double)g_graphicsContext.GetHeight())
+ {
+- OutWidth = g_graphicsContext.GetWidth();
+- OutHeight = MathUtils::round_int((double)height * g_graphicsContext.GetWidth() / width);
++ m_vdpauConfig.outWidth = g_graphicsContext.GetWidth();
++ m_vdpauConfig.outHeight = MathUtils::round_int((double)height * g_graphicsContext.GetWidth() / width);
+ }
+ else //scale height to the desktop size if the aspect ratio is smaller than the desktop
+ {
+- OutHeight = g_graphicsContext.GetHeight();
+- OutWidth = MathUtils::round_int((double)width * g_graphicsContext.GetHeight() / height);
++ m_vdpauConfig.outHeight = g_graphicsContext.GetHeight();
++ m_vdpauConfig.outWidth = MathUtils::round_int((double)width * g_graphicsContext.GetHeight() / height);
+ }
+ }
+ else
+ { //let opengl scale
+- OutWidth = width;
+- OutHeight = height;
+- }
+-
+- CLog::Log(LOGNOTICE,"Creating %ix%i pixmap", OutWidth, OutHeight);
+-
+- // Get our window attribs.
+- XWindowAttributes wndattribs;
+- XGetWindowAttributes(m_Display, DefaultRootWindow(m_Display), &wndattribs); // returns a status but I don't know what success is
+-
+- m_Pixmap = XCreatePixmap(m_Display,
+- DefaultRootWindow(m_Display),
+- OutWidth,
+- OutHeight,
+- wndattribs.depth);
+- if (!m_Pixmap)
+- {
+- CLog::Log(LOGERROR, "GLX Error: MakePixmap: Unable to create XPixmap");
+- return false;
+- }
+-
+- XGCValues values = {};
+- GC xgc;
+- values.foreground = BlackPixel (m_Display, DefaultScreen (m_Display));
+- xgc = XCreateGC(m_Display, m_Pixmap, GCForeground, &values);
+- XFillRectangle(m_Display, m_Pixmap, xgc, 0, 0, OutWidth, OutHeight);
+- XFreeGC(m_Display, xgc);
+-
+- if(!MakePixmapGL())
+- return false;
+-
+- return true;
+-}
+-
+-void CVDPAU::BindPixmap()
+-{
+- CSharedLock lock(m_DecoderSection);
+-
+- { CSharedLock dLock(m_DisplaySection);
+- if (m_DisplayState != VDPAU_OPEN)
+- return;
+- }
+-
+- if (m_glPixmap)
+- {
+- if(presentSurface != VDP_INVALID_HANDLE)
+- {
+- VdpPresentationQueueStatus status;
+- VdpTime time;
+- VdpStatus vdp_st;
+- vdp_st = vdp_presentation_queue_query_surface_status(
+- vdp_flip_queue, presentSurface, &status, &time);
+- CheckStatus(vdp_st, __LINE__);
+- while(status != VDP_PRESENTATION_QUEUE_STATUS_VISIBLE && vdp_st == VDP_STATUS_OK)
+- {
+- Sleep(1);
+- vdp_st = vdp_presentation_queue_query_surface_status(
+- vdp_flip_queue, presentSurface, &status, &time);
+- CheckStatus(vdp_st, __LINE__);
+- }
+- }
+-
+- glXBindTexImageEXT(m_Display, m_glPixmap, GLX_FRONT_LEFT_EXT, NULL);
+- }
+- else CLog::Log(LOGERROR,"(VDPAU) BindPixmap called without valid pixmap");
+-}
+-
+-void CVDPAU::ReleasePixmap()
+-{
+- CSharedLock lock(m_DecoderSection);
+-
+- { CSharedLock dLock(m_DisplaySection);
+- if (m_DisplayState != VDPAU_OPEN)
+- return;
+- }
+-
+- if (m_glPixmap)
+- {
+- glXReleaseTexImageEXT(m_Display, m_glPixmap, GLX_FRONT_LEFT_EXT);
++ m_vdpauConfig.outWidth = width;
++ m_vdpauConfig.outHeight = height;
+ }
+- else CLog::Log(LOGERROR,"(VDPAU) ReleasePixmap called without valid pixmap");
++ CLog::Log(LOGDEBUG, "CVDPAU::SetWidthHeight Setting OutWidth: %i OutHeight: %i vdpauMaxHeight: %i", m_vdpauConfig.outWidth, m_vdpauConfig.outHeight, vdpauMaxHeight);
+ }
+
+-void CVDPAU::OnLostDevice()
++void CDecoder::OnLostDevice()
+ {
+ CLog::Log(LOGNOTICE,"CVDPAU::OnLostDevice event");
+
+- CExclusiveLock lock(m_DecoderSection);
++ CSingleLock lock(m_DecoderSection);
+ FiniVDPAUOutput();
+ FiniVDPAUProcs();
+
+ m_DisplayState = VDPAU_LOST;
++ lock.Leave();
+ m_DisplayEvent.Reset();
+ }
+
+-void CVDPAU::OnResetDevice()
++void CDecoder::OnResetDevice()
+ {
+ CLog::Log(LOGNOTICE,"CVDPAU::OnResetDevice event");
+
+- CExclusiveLock lock(m_DisplaySection);
++ CSingleLock lock(m_DecoderSection);
+ if (m_DisplayState == VDPAU_LOST)
+ {
+ m_DisplayState = VDPAU_RESET;
++ lock.Leave();
+ m_DisplayEvent.Set();
+ }
+ }
+
+-int CVDPAU::Check(AVCodecContext* avctx)
++int CDecoder::Check(AVCodecContext* avctx)
+ {
+ EDisplayState state;
+
+- { CSharedLock lock(m_DisplaySection);
++ { CSingleLock lock(m_DecoderSection);
+ state = m_DisplayState;
+ }
+
+@@ -417,16 +329,13 @@
+ }
+ else
+ {
+- CSharedLock lock(m_DisplaySection);
++ CSingleLock lock(m_DecoderSection);
+ state = m_DisplayState;
+ }
+ }
+ if (state == VDPAU_RESET || state == VDPAU_ERROR)
+ {
+- CLog::Log(LOGNOTICE,"Attempting recovery");
+-
+- CSingleLock gLock(g_graphicsContext);
+- CExclusiveLock lock(m_DecoderSection);
++ CSingleLock lock(m_DecoderSection);
+
+ FiniVDPAUOutput();
+ FiniVDPAUProcs();
+@@ -441,7 +350,7 @@
+ return 0;
+ }
+
+-bool CVDPAU::IsVDPAUFormat(PixelFormat format)
++bool CDecoder::IsVDPAUFormat(PixelFormat format)
+ {
+ if ((format >= PIX_FMT_VDPAU_H264) && (format <= PIX_FMT_VDPAU_VC1)) return true;
+ #if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL)
+@@ -450,90 +359,28 @@
+ else return false;
+ }
+
+-void CVDPAU::CheckFeatures()
+-{
+- if (videoMixer == VDP_INVALID_HANDLE)
+- {
+- CLog::Log(LOGNOTICE, " (VDPAU) Creating the video mixer");
+- // Creation of VideoMixer.
+- VdpVideoMixerParameter parameters[] = {
+- VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
+- VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
+- VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
+- };
+-
+- void const * parameter_values[] = {
+- &surface_width,
+- &surface_height,
+- &vdp_chroma_type
+- };
+-
+- tmpBrightness = 0;
+- tmpContrast = 0;
+- tmpNoiseReduction = 0;
+- tmpSharpness = 0;
+-
+- VdpStatus vdp_st = VDP_STATUS_ERROR;
+- vdp_st = vdp_video_mixer_create(vdp_device,
+- m_feature_count,
+- m_features,
+- ARSIZE(parameters),
+- parameters,
+- parameter_values,
+- &videoMixer);
+- CheckStatus(vdp_st, __LINE__);
+-
+- SetHWUpscaling();
+- }
+-
+- if (tmpBrightness != g_settings.m_currentVideoSettings.m_Brightness ||
+- tmpContrast != g_settings.m_currentVideoSettings.m_Contrast)
+- {
+- SetColor();
+- tmpBrightness = g_settings.m_currentVideoSettings.m_Brightness;
+- tmpContrast = g_settings.m_currentVideoSettings.m_Contrast;
+- }
+- if (tmpNoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction)
+- {
+- tmpNoiseReduction = g_settings.m_currentVideoSettings.m_NoiseReduction;
+- SetNoiseReduction();
+- }
+- if (tmpSharpness != g_settings.m_currentVideoSettings.m_Sharpness)
+- {
+- tmpSharpness = g_settings.m_currentVideoSettings.m_Sharpness;
+- SetSharpness();
+- }
+- if ( tmpDeintMode != g_settings.m_currentVideoSettings.m_DeinterlaceMode ||
+- tmpDeintGUI != g_settings.m_currentVideoSettings.m_InterlaceMethod ||
+- (tmpDeintGUI == VS_INTERLACEMETHOD_AUTO && tmpDeint != AutoInterlaceMethod()))
+- {
+- tmpDeintMode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
+- tmpDeintGUI = g_settings.m_currentVideoSettings.m_InterlaceMethod;
+- if (tmpDeintGUI == VS_INTERLACEMETHOD_AUTO)
+- tmpDeint = AutoInterlaceMethod();
+- else
+- tmpDeint = tmpDeintGUI;
+-
+- SetDeinterlacing();
+- }
+-}
+-
+-bool CVDPAU::Supports(VdpVideoMixerFeature feature)
++bool CDecoder::Supports(VdpVideoMixerFeature feature)
+ {
+- for(int i = 0; i < m_feature_count; i++)
++ for(int i = 0; i < m_vdpauConfig.featureCount; i++)
+ {
+- if(m_features[i] == feature)
++ if(m_vdpauConfig.vdpFeatures[i] == feature)
+ return true;
+ }
+ return false;
+ }
+
+-bool CVDPAU::Supports(EINTERLACEMETHOD method)
++bool CDecoder::Supports(EINTERLACEMETHOD method)
+ {
+ if(method == VS_INTERLACEMETHOD_VDPAU_BOB
+ || method == VS_INTERLACEMETHOD_AUTO)
+ return true;
+
++ if (g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv"))
++ {
++ if (method == VS_INTERLACEMETHOD_RENDER_BOB)
++ return true;
++ }
++
+ for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++)
+ {
+ if(p->method == method)
+@@ -542,149 +389,12 @@
+ return false;
+ }
+
+-EINTERLACEMETHOD CVDPAU::AutoInterlaceMethod()
+-{
+- return VS_INTERLACEMETHOD_VDPAU_TEMPORAL;
+-}
+-
+-void CVDPAU::SetColor()
+-{
+- VdpStatus vdp_st;
+-
+- if (tmpBrightness != g_settings.m_currentVideoSettings.m_Brightness)
+- m_Procamp.brightness = (float)((g_settings.m_currentVideoSettings.m_Brightness)-50) / 100;
+- if (tmpContrast != g_settings.m_currentVideoSettings.m_Contrast)
+- m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100;
+-
+- if(vid_height >= 600 || vid_width > 1024)
+- vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix);
+- else
+- vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix);
+-
+- VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
+- if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
+- {
+- void const * pm_CSCMatix[] = { &studioCSC };
+- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
+- }
+- else
+- {
+- void const * pm_CSCMatix[] = { &m_CSCMatrix };
+- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
+- }
+- CheckStatus(vdp_st, __LINE__);
+-}
+-
+-void CVDPAU::SetNoiseReduction()
+-{
+- if(!Supports(VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION))
+- return;
+-
+- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION };
+- VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL };
+- VdpStatus vdp_st;
+-
+- if (!g_settings.m_currentVideoSettings.m_NoiseReduction)
+- {
+- VdpBool enabled[]= {0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- CheckStatus(vdp_st, __LINE__);
+- return;
+- }
+- VdpBool enabled[]={1};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- CheckStatus(vdp_st, __LINE__);
+- void* nr[] = { &g_settings.m_currentVideoSettings.m_NoiseReduction };
+- CLog::Log(LOGNOTICE,"Setting Noise Reduction to %f",g_settings.m_currentVideoSettings.m_NoiseReduction);
+- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, nr);
+- CheckStatus(vdp_st, __LINE__);
+-}
+-
+-void CVDPAU::SetSharpness()
+-{
+- if(!Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS))
+- return;
+-
+- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS };
+- VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL };
+- VdpStatus vdp_st;
+-
+- if (!g_settings.m_currentVideoSettings.m_Sharpness)
+- {
+- VdpBool enabled[]={0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- CheckStatus(vdp_st, __LINE__);
+- return;
+- }
+- VdpBool enabled[]={1};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- CheckStatus(vdp_st, __LINE__);
+- void* sh[] = { &g_settings.m_currentVideoSettings.m_Sharpness };
+- CLog::Log(LOGNOTICE,"Setting Sharpness to %f",g_settings.m_currentVideoSettings.m_Sharpness);
+- vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, sh);
+- CheckStatus(vdp_st, __LINE__);
+-}
+-
+-void CVDPAU::SetHWUpscaling()
+-{
+-#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
+- if(!Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1) || !upScale)
+- return;
+-
+- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 };
+- VdpStatus vdp_st;
+- VdpBool enabled[]={1};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- CheckStatus(vdp_st, __LINE__);
+-#endif
+-}
+-
+-void CVDPAU::SetDeinterlacing()
++EINTERLACEMETHOD CDecoder::AutoInterlaceMethod()
+ {
+- VdpStatus vdp_st;
+- EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
+- EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
+- if (method == VS_INTERLACEMETHOD_AUTO)
+- method = AutoInterlaceMethod();
+-
+- VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
+- VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
+- VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE };
+- if (mode == VS_DEINTERLACEMODE_OFF)
+- {
+- VdpBool enabled[]={0,0,0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- else
+- {
+- if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF)
+- {
+- VdpBool enabled[]={1,0,0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF)
+- {
+- VdpBool enabled[]={1,1,0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- else if (method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE)
+- {
+- VdpBool enabled[]={1,0,1};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- else
+- {
+- VdpBool enabled[]={0,0,0};
+- vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled);
+- }
+- }
+-
+- CheckStatus(vdp_st, __LINE__);
++ return VS_INTERLACEMETHOD_RENDER_BOB;
+ }
+
+-void CVDPAU::InitVDPAUProcs()
++void CDecoder::InitVDPAUProcs()
+ {
+ char* error;
+
+@@ -694,151 +404,115 @@
+ if (error)
+ {
+ CLog::Log(LOGERROR,"(VDPAU) - %s in %s",error,__FUNCTION__);
+- vdp_device = VDP_INVALID_HANDLE;
+-
+- //g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "VDPAU", error, 10000);
+-
++ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
+ return;
+ }
+
+ if (dl_vdp_device_create_x11)
+ {
+- CSingleLock lock(g_graphicsContext);
+- m_Display = g_Windowing.GetDisplay();
++ m_Display = XOpenDisplay(NULL);
+ }
+
+ int mScreen = DefaultScreen(m_Display);
+ VdpStatus vdp_st;
+
+ // Create Device
+- // tested on 64bit Ubuntu 11.10 and it deadlocked without this
+- XLockDisplay(m_Display);
+ vdp_st = dl_vdp_device_create_x11(m_Display, //x_display,
+ mScreen, //x_screen,
+- &vdp_device,
+- &vdp_get_proc_address);
+- XUnlockDisplay(m_Display);
++ &m_vdpauConfig.vdpDevice,
++ &m_vdpauConfig.vdpProcs.vdp_get_proc_address);
+
+- CLog::Log(LOGNOTICE,"vdp_device = 0x%08x vdp_st = 0x%08x",vdp_device,vdp_st);
++ CLog::Log(LOGNOTICE,"vdp_device = 0x%08x vdp_st = 0x%08x",m_vdpauConfig.vdpDevice,vdp_st);
+ if (vdp_st != VDP_STATUS_OK)
+ {
+ CLog::Log(LOGERROR,"(VDPAU) unable to init VDPAU - vdp_st = 0x%x. Falling back.",vdp_st);
+- vdp_device = VDP_INVALID_HANDLE;
++ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
+ return;
+ }
+
+- if (vdp_st != VDP_STATUS_OK)
+- {
+- CLog::Log(LOGERROR,"(VDPAU) - Unable to create X11 device in %s",__FUNCTION__);
+- vdp_device = VDP_INVALID_HANDLE;
+- return;
+- }
+ #define VDP_PROC(id, proc) \
+ do { \
+- vdp_st = vdp_get_proc_address(vdp_device, id, (void**)&proc); \
++ vdp_st = m_vdpauConfig.vdpProcs.vdp_get_proc_address(m_vdpauConfig.vdpDevice, id, (void**)&proc); \
+ CheckStatus(vdp_st, __LINE__); \
+ } while(0);
+
+- VDP_PROC(VDP_FUNC_ID_GET_ERROR_STRING , vdp_get_error_string);
+- VDP_PROC(VDP_FUNC_ID_DEVICE_DESTROY , vdp_device_destroy);
+- VDP_PROC(VDP_FUNC_ID_GENERATE_CSC_MATRIX , vdp_generate_csc_matrix);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_CREATE , vdp_video_surface_create);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , vdp_video_surface_destroy);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , vdp_video_surface_put_bits_y_cb_cr);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , vdp_video_surface_get_bits_y_cb_cr);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , vdp_output_surface_put_bits_y_cb_cr);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , vdp_output_surface_put_bits_native);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , vdp_output_surface_create);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , vdp_output_surface_destroy);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE , vdp_output_surface_get_bits_native);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, vdp_output_surface_render_output_surface);
+- VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED , vdp_output_surface_put_bits_indexed);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_CREATE , vdp_video_mixer_create);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , vdp_video_mixer_set_feature_enables);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_DESTROY , vdp_video_mixer_destroy);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_RENDER , vdp_video_mixer_render);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , vdp_video_mixer_set_attribute_values);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , vdp_video_mixer_query_parameter_support);
+- VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , vdp_video_mixer_query_feature_support);
+- VDP_PROC(VDP_FUNC_ID_DECODER_CREATE , vdp_decoder_create);
+- VDP_PROC(VDP_FUNC_ID_DECODER_DESTROY , vdp_decoder_destroy);
+- VDP_PROC(VDP_FUNC_ID_DECODER_RENDER , vdp_decoder_render);
+- VDP_PROC(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , vdp_decoder_query_caps);
+- VDP_PROC(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER , vdp_preemption_callback_register);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , vdp_presentation_queue_target_destroy);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , vdp_presentation_queue_create);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , vdp_presentation_queue_destroy);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , vdp_presentation_queue_display);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, vdp_presentation_queue_block_until_surface_idle);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , vdp_presentation_queue_target_create_x11);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , vdp_presentation_queue_query_surface_status);
+- VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , vdp_presentation_queue_get_time);
+-
++ VDP_PROC(VDP_FUNC_ID_GET_ERROR_STRING , m_vdpauConfig.vdpProcs.vdp_get_error_string);
++ VDP_PROC(VDP_FUNC_ID_DEVICE_DESTROY , m_vdpauConfig.vdpProcs.vdp_device_destroy);
++ VDP_PROC(VDP_FUNC_ID_GENERATE_CSC_MATRIX , m_vdpauConfig.vdpProcs.vdp_generate_csc_matrix);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_CREATE , m_vdpauConfig.vdpProcs.vdp_video_surface_create);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , m_vdpauConfig.vdpProcs.vdp_video_surface_destroy);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , m_vdpauConfig.vdpProcs.vdp_video_surface_put_bits_y_cb_cr);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , m_vdpauConfig.vdpProcs.vdp_video_surface_get_bits_y_cb_cr);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , m_vdpauConfig.vdpProcs.vdp_output_surface_put_bits_y_cb_cr);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , m_vdpauConfig.vdpProcs.vdp_output_surface_put_bits_native);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , m_vdpauConfig.vdpProcs.vdp_output_surface_create);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , m_vdpauConfig.vdpProcs.vdp_output_surface_destroy);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE , m_vdpauConfig.vdpProcs.vdp_output_surface_get_bits_native);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, m_vdpauConfig.vdpProcs.vdp_output_surface_render_output_surface);
++ VDP_PROC(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED , m_vdpauConfig.vdpProcs.vdp_output_surface_put_bits_indexed);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_CREATE , m_vdpauConfig.vdpProcs.vdp_video_mixer_create);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , m_vdpauConfig.vdpProcs.vdp_video_mixer_set_feature_enables);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_DESTROY , m_vdpauConfig.vdpProcs.vdp_video_mixer_destroy);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_RENDER , m_vdpauConfig.vdpProcs.vdp_video_mixer_render);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , m_vdpauConfig.vdpProcs.vdp_video_mixer_set_attribute_values);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , m_vdpauConfig.vdpProcs.vdp_video_mixer_query_parameter_support);
++ VDP_PROC(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , m_vdpauConfig.vdpProcs.vdp_video_mixer_query_feature_support);
++ VDP_PROC(VDP_FUNC_ID_DECODER_CREATE , m_vdpauConfig.vdpProcs.vdp_decoder_create);
++ VDP_PROC(VDP_FUNC_ID_DECODER_DESTROY , m_vdpauConfig.vdpProcs.vdp_decoder_destroy);
++ VDP_PROC(VDP_FUNC_ID_DECODER_RENDER , m_vdpauConfig.vdpProcs.vdp_decoder_render);
++ VDP_PROC(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , m_vdpauConfig.vdpProcs.vdp_decoder_query_caps);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , m_vdpauConfig.vdpProcs.vdp_presentation_queue_target_destroy);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , m_vdpauConfig.vdpProcs.vdp_presentation_queue_create);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , m_vdpauConfig.vdpProcs.vdp_presentation_queue_destroy);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , m_vdpauConfig.vdpProcs.vdp_presentation_queue_display);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, m_vdpauConfig.vdpProcs.vdp_presentation_queue_block_until_surface_idle);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , m_vdpauConfig.vdpProcs.vdp_presentation_queue_target_create_x11);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , m_vdpauConfig.vdpProcs.vdp_presentation_queue_query_surface_status);
++ VDP_PROC(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , m_vdpauConfig.vdpProcs.vdp_presentation_queue_get_time);
++
+ #undef VDP_PROC
+
+ // set all vdpau resources to invalid
+- vdp_flip_target = VDP_INVALID_HANDLE;
+- vdp_flip_queue = VDP_INVALID_HANDLE;
+- videoMixer = VDP_INVALID_HANDLE;
+- totalAvailableOutputSurfaces = 0;
+- presentSurface = VDP_INVALID_HANDLE;
+- outputSurface = VDP_INVALID_HANDLE;
+- for (int i = 0; i < NUM_OUTPUT_SURFACES; i++)
+- outputSurfaces[i] = VDP_INVALID_HANDLE;
+-
+- m_vdpauOutputMethod = OUTPUT_NONE;
+-
+- CExclusiveLock lock(m_DisplaySection);
+ m_DisplayState = VDPAU_OPEN;
+- vdpauConfigured = false;
++ m_vdpauConfigured = false;
+ }
+
+-void CVDPAU::FiniVDPAUProcs()
++void CDecoder::FiniVDPAUProcs()
+ {
+- if (vdp_device == VDP_INVALID_HANDLE) return;
++ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE) return;
+
+ VdpStatus vdp_st;
+- vdp_st = vdp_device_destroy(vdp_device);
++ vdp_st = m_vdpauConfig.vdpProcs.vdp_device_destroy(m_vdpauConfig.vdpDevice);
+ CheckStatus(vdp_st, __LINE__);
+- vdp_device = VDP_INVALID_HANDLE;
+- vdpauConfigured = false;
++ m_vdpauConfig.vdpDevice = VDP_INVALID_HANDLE;
+ }
+
+-void CVDPAU::InitCSCMatrix(int Height)
++void CDecoder::FiniVDPAUOutput()
+ {
++ if (m_vdpauConfig.vdpDevice == VDP_INVALID_HANDLE || !m_vdpauConfigured) return;
++
++ CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__);
++
++ // uninit output
++ m_vdpauOutput.Dispose();
++ m_vdpauConfigured = false;
++
+ VdpStatus vdp_st;
+- m_Procamp.struct_version = VDP_PROCAMP_VERSION;
+- m_Procamp.brightness = 0.0;
+- m_Procamp.contrast = 1.0;
+- m_Procamp.saturation = 1.0;
+- m_Procamp.hue = 0;
+- vdp_st = vdp_generate_csc_matrix(&m_Procamp,
+- (Height < 720)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709,
+- &m_CSCMatrix);
+- CheckStatus(vdp_st, __LINE__);
+-}
+-
+-void CVDPAU::FiniVDPAUOutput()
+-{
+- FiniOutputMethod();
+-
+- if (vdp_device == VDP_INVALID_HANDLE || !vdpauConfigured) return;
+
+- CLog::Log(LOGNOTICE, " (VDPAU) %s", __FUNCTION__);
+-
+- VdpStatus vdp_st;
+-
+- vdp_st = vdp_decoder_destroy(decoder);
++ vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_destroy(m_vdpauConfig.vdpDecoder);
+ if (CheckStatus(vdp_st, __LINE__))
+ return;
+- decoder = VDP_INVALID_HANDLE;
++ m_vdpauConfig.vdpDecoder = VDP_INVALID_HANDLE;
+
+- for (unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
++ CSingleLock lock(m_videoSurfaceSec);
++ CLog::Log(LOGDEBUG, "CVDPAU::FiniVDPAUOutput destroying %d video surfaces", (int)m_videoSurfaces.size());
++
++ for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
+ {
+ vdpau_render_state *render = m_videoSurfaces[i];
+ if (render->surface != VDP_INVALID_HANDLE)
+ {
+- vdp_st = vdp_video_surface_destroy(render->surface);
++ vdp_st = m_vdpauConfig.vdpProcs.vdp_video_surface_destroy(render->surface);
+ render->surface = VDP_INVALID_HANDLE;
+ }
+ if (CheckStatus(vdp_st, __LINE__))
+@@ -846,8 +520,7 @@
+ }
+ }
+
+-
+-void CVDPAU::ReadFormatOf( PixelFormat fmt
++void CDecoder::ReadFormatOf( PixelFormat fmt
+ , VdpDecoderProfile &vdp_decoder_profile
+ , VdpChromaType &vdp_chroma_type)
+ {
+@@ -885,170 +558,78 @@
+ }
+ }
+
+-
+-bool CVDPAU::ConfigVDPAU(AVCodecContext* avctx, int ref_frames)
++bool CDecoder::ConfigVDPAU(AVCodecContext* avctx, int ref_frames)
+ {
+ FiniVDPAUOutput();
+
+ VdpStatus vdp_st;
+ VdpDecoderProfile vdp_decoder_profile;
+- vid_width = avctx->width;
+- vid_height = avctx->height;
+- surface_width = avctx->coded_width;
+- surface_height = avctx->coded_height;
+-
+- past[1] = past[0] = current = future = NULL;
+- CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i surfaceWidth:%i",OutWidth,vid_width,surface_width);
+- CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i surfaceHeight:%i",OutHeight,vid_height,surface_height);
+- ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, vdp_chroma_type);
++
++ m_vdpauConfig.vidWidth = avctx->width;
++ m_vdpauConfig.vidHeight = avctx->height;
++ m_vdpauConfig.surfaceWidth = avctx->coded_width;
++ m_vdpauConfig.surfaceHeight = avctx->coded_height;
++
++ SetWidthHeight(avctx->width,avctx->height);
++
++ CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i surfaceWidth:%i",m_vdpauConfig.outWidth,m_vdpauConfig.vidWidth,m_vdpauConfig.surfaceWidth);
++ CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i surfaceHeight:%i",m_vdpauConfig.outHeight,m_vdpauConfig.vidHeight,m_vdpauConfig.surfaceHeight);
++
++ ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, m_vdpauConfig.vdpChromaType);
+
+ if(avctx->pix_fmt == PIX_FMT_VDPAU_H264)
+ {
+- max_references = ref_frames;
+- if (max_references > 16) max_references = 16;
+- if (max_references < 5) max_references = 5;
++ m_vdpauConfig.maxReferences = ref_frames;
++ if (m_vdpauConfig.maxReferences > 16) m_vdpauConfig.maxReferences = 16;
++ if (m_vdpauConfig.maxReferences < 5) m_vdpauConfig.maxReferences = 5;
+ }
+ else
+- max_references = 2;
++ m_vdpauConfig.maxReferences = 2;
+
+- vdp_st = vdp_decoder_create(vdp_device,
++ vdp_st = m_vdpauConfig.vdpProcs.vdp_decoder_create(m_vdpauConfig.vdpDevice,
+ vdp_decoder_profile,
+- surface_width,
+- surface_height,
+- max_references,
+- &decoder);
+- if (CheckStatus(vdp_st, __LINE__))
+- return false;
+-
+- m_vdpauOutputMethod = OUTPUT_NONE;
+-
+- vdpauConfigured = true;
+- return true;
+-}
+-
+-bool CVDPAU::ConfigOutputMethod(AVCodecContext *avctx, AVFrame *pFrame)
+-{
+- VdpStatus vdp_st;
+-
+- if (m_vdpauOutputMethod == OUTPUT_PIXMAP)
+- return true;
+-
+- FiniOutputMethod();
+-
+- MakePixmap(avctx->width,avctx->height);
+-
+- vdp_st = vdp_presentation_queue_target_create_x11(vdp_device,
+- m_Pixmap, //x_window,
+- &vdp_flip_target);
+- if (CheckStatus(vdp_st, __LINE__))
+- return false;
+-
+- vdp_st = vdp_presentation_queue_create(vdp_device,
+- vdp_flip_target,
+- &vdp_flip_queue);
++ m_vdpauConfig.surfaceWidth,
++ m_vdpauConfig.surfaceHeight,
++ m_vdpauConfig.maxReferences,
++ &m_vdpauConfig.vdpDecoder);
+ if (CheckStatus(vdp_st, __LINE__))
+ return false;
+
+- totalAvailableOutputSurfaces = 0;
+-
+- int tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES;
+- if (vid_width == FULLHD_WIDTH)
+- tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES_FOR_FULLHD;
+-
+- // Creation of outputSurfaces
+- for (int i = 0; i < NUM_OUTPUT_SURFACES && i < tmpMaxOutputSurfaces; i++)
+- {
+- vdp_st = vdp_output_surface_create(vdp_device,
+- VDP_RGBA_FORMAT_B8G8R8A8,
+- OutWidth,
+- OutHeight,
+- &outputSurfaces[i]);
+- if (CheckStatus(vdp_st, __LINE__))
++ // initialize output
++ CSingleLock lock(g_graphicsContext);
++ m_vdpauConfig.stats = &m_bufferStats;
++ m_vdpauConfig.vdpau = this;
++ m_bufferStats.Reset();
++ m_vdpauOutput.Start();
++ Message *reply;
++ if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::INIT,
++ &reply,
++ 2000,
++ &m_vdpauConfig,
++ sizeof(m_vdpauConfig)))
++ {
++ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
++ reply->Release();
++ if (!success)
++ {
++ CLog::Log(LOGERROR, "VDPAU::%s - vdpau output returned error", __FUNCTION__);
++ m_vdpauOutput.Dispose();
+ return false;
+- totalAvailableOutputSurfaces++;
+- }
+- CLog::Log(LOGNOTICE, " (VDPAU) Total Output Surfaces Available: %i of a max (tmp: %i const: %i)",
+- totalAvailableOutputSurfaces,
+- tmpMaxOutputSurfaces,
+- NUM_OUTPUT_SURFACES);
+-
+- // create 3 pitches of black lines needed for clipping top
+- // and bottom lines when de-interlacing
+- m_BlackBar = new uint32_t[3*OutWidth];
+- memset(m_BlackBar, 0, 3*OutWidth*sizeof(uint32_t));
+-
+- surfaceNum = presentSurfaceNum = 0;
+- outputSurface = presentSurface = VDP_INVALID_HANDLE;
+- videoMixer = VDP_INVALID_HANDLE;
+-
+- m_vdpauOutputMethod = OUTPUT_PIXMAP;
+-
+- return true;
+-}
+-
+-bool CVDPAU::FiniOutputMethod()
+-{
+- VdpStatus vdp_st;
+-
+- if (vdp_flip_queue != VDP_INVALID_HANDLE)
+- {
+- vdp_st = vdp_presentation_queue_destroy(vdp_flip_queue);
+- vdp_flip_queue = VDP_INVALID_HANDLE;
+- CheckStatus(vdp_st, __LINE__);
+- }
+-
+- if (vdp_flip_target != VDP_INVALID_HANDLE)
+- {
+- vdp_st = vdp_presentation_queue_target_destroy(vdp_flip_target);
+- vdp_flip_target = VDP_INVALID_HANDLE;
+- CheckStatus(vdp_st, __LINE__);
+- }
+-
+- if (m_glPixmap)
+- {
+- CLog::Log(LOGDEBUG, "GLX: Destroying glPixmap");
+- glXDestroyPixmap(m_Display, m_glPixmap);
+- m_glPixmap = None;
+- }
+-
+- if (m_Pixmap)
+- {
+- CLog::Log(LOGDEBUG, "GLX: Destroying XPixmap");
+- XFreePixmap(m_Display, m_Pixmap);
+- m_Pixmap = None;
+- }
+-
+- outputSurface = presentSurface = VDP_INVALID_HANDLE;
+-
+- for (int i = 0; i < totalAvailableOutputSurfaces; i++)
+- {
+- if (outputSurfaces[i] == VDP_INVALID_HANDLE)
+- continue;
+- vdp_st = vdp_output_surface_destroy(outputSurfaces[i]);
+- outputSurfaces[i] = VDP_INVALID_HANDLE;
+- CheckStatus(vdp_st, __LINE__);
+- }
+-
+- if (videoMixer != VDP_INVALID_HANDLE)
+- {
+- vdp_st = vdp_video_mixer_destroy(videoMixer);
+- videoMixer = VDP_INVALID_HANDLE;
+- if (CheckStatus(vdp_st, __LINE__));
++ }
+ }
+-
+- if (m_BlackBar)
++ else
+ {
+- delete [] m_BlackBar;
+- m_BlackBar = NULL;
++ CLog::Log(LOGERROR, "VDPAU::%s - failed to init output", __FUNCTION__);
++ m_vdpauOutput.Dispose();
++ return false;
+ }
+
+- while (!m_DVDVideoPics.empty())
+- m_DVDVideoPics.pop();
+-
++ m_inMsgEvent.Reset();
++ m_vdpauConfigured = true;
+ return true;
+ }
+
+-void CVDPAU::SpewHardwareAvailable() //Copyright (c) 2008 Wladimir J. van der Laan -- VDPInfo
++void CDecoder::SpewHardwareAvailable() //CopyrighVDPAUt (c) 2008 Wladimir J. van der Laan -- VDPInfo
+ {
+ VdpStatus rv;
+ CLog::Log(LOGNOTICE,"VDPAU Decoder capabilities:");
+@@ -1058,7 +639,7 @@
+ {
+ VdpBool is_supported = false;
+ uint32_t max_level, max_macroblocks, max_width, max_height;
+- rv = vdp_decoder_query_caps(vdp_device, decoder_profiles[x].id,
++ rv = m_vdpauConfig.vdpProcs.vdp_decoder_query_caps(m_vdpauConfig.vdpDevice, decoder_profiles[x].id,
+ &is_supported, &max_level, &max_macroblocks, &max_width, &max_height);
+ if(rv == VDP_STATUS_OK && is_supported)
+ {
+@@ -1067,13 +648,13 @@
+ }
+ }
+ CLog::Log(LOGNOTICE,"------------------------------------");
+- m_feature_count = 0;
++ m_vdpauConfig.featureCount = 0;
+ #define CHECK_SUPPORT(feature) \
+ do { \
+ VdpBool supported; \
+- if(vdp_video_mixer_query_feature_support(vdp_device, feature, &supported) == VDP_STATUS_OK && supported) { \
++ if(m_vdpauConfig.vdpProcs.vdp_video_mixer_query_feature_support(m_vdpauConfig.vdpDevice, feature, &supported) == VDP_STATUS_OK && supported) { \
+ CLog::Log(LOGNOTICE, "Mixer feature: "#feature); \
+- m_features[m_feature_count++] = feature; \
++ m_vdpauConfig.vdpFeatures[m_vdpauConfig.featureCount++] = feature; \
+ } \
+ } while(false)
+
+@@ -1097,7 +678,7 @@
+
+ }
+
+-bool CVDPAU::IsSurfaceValid(vdpau_render_state *render)
++bool CDecoder::IsSurfaceValid(vdpau_render_state *render)
+ {
+ // find render state in queue
+ bool found(false);
+@@ -1124,34 +705,34 @@
+ return true;
+ }
+
+-int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
++int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
+ {
+ //CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
+- CVDPAU* vdp = (CVDPAU*)ctx->GetHardware();
+- struct pictureAge* pA = &vdp->picAge;
++ CDecoder* vdp = (CDecoder*)ctx->GetHardware();
++ struct PictureAge* pA = &vdp->m_picAge;
+
+ // while we are waiting to recover we can't do anything
+- CSharedLock lock(vdp->m_DecoderSection);
++ CSingleLock lock(vdp->m_DecoderSection);
+
+- { CSharedLock dLock(vdp->m_DisplaySection);
+- if(vdp->m_DisplayState != VDPAU_OPEN)
+- {
+- CLog::Log(LOGWARNING, "CVDPAU::FFGetBuffer - returning due to awaiting recovery");
+- return -1;
+- }
++ if(vdp->m_DisplayState != VDPAU_OPEN)
++ {
++ CLog::Log(LOGWARNING, "CVDPAU::FFGetBuffer - returning due to awaiting recovery");
++ return -1;
+ }
+
+ vdpau_render_state * render = NULL;
+
+ // find unused surface
+- for(unsigned int i = 0; i < vdp->m_videoSurfaces.size(); i++)
+- {
+- if(!(vdp->m_videoSurfaces[i]->state & (FF_VDPAU_STATE_USED_FOR_REFERENCE | FF_VDPAU_STATE_USED_FOR_RENDER)))
++ { CSingleLock lock(vdp->m_videoSurfaceSec);
++ for(unsigned int i = 0; i < vdp->m_videoSurfaces.size(); i++)
+ {
+- render = vdp->m_videoSurfaces[i];
+- render->state = 0;
+- break;
++ if(!(vdp->m_videoSurfaces[i]->state & (FF_VDPAU_STATE_USED_FOR_REFERENCE | FF_VDPAU_STATE_USED_FOR_RENDER)))
++ {
++ render = vdp->m_videoSurfaces[i];
++ render->state = 0;
++ break;
++ }
+ }
+ }
+
+@@ -1160,21 +741,22 @@
+ {
+ // create a new surface
+ VdpDecoderProfile profile;
+- ReadFormatOf(avctx->pix_fmt, profile, vdp->vdp_chroma_type);
++ ReadFormatOf(avctx->pix_fmt, profile, vdp->m_vdpauConfig.vdpChromaType);
+ render = (vdpau_render_state*)calloc(sizeof(vdpau_render_state), 1);
+ if (render == NULL)
+ {
+ CLog::Log(LOGWARNING, "CVDPAU::FFGetBuffer - calloc failed");
+ return -1;
+ }
++ CSingleLock lock(vdp->m_videoSurfaceSec);
+ render->surface = VDP_INVALID_HANDLE;
+ vdp->m_videoSurfaces.push_back(render);
+ }
+
+ if (render->surface == VDP_INVALID_HANDLE)
+ {
+- vdp_st = vdp->vdp_video_surface_create(vdp->vdp_device,
+- vdp->vdp_chroma_type,
++ vdp_st = vdp->m_vdpauConfig.vdpProcs.vdp_video_surface_create(vdp->m_vdpauConfig.vdpDevice,
++ vdp->m_vdpauConfig.vdpChromaType,
+ avctx->coded_width,
+ avctx->coded_height,
+ &render->surface);
+@@ -1216,15 +798,16 @@
+ return 0;
+ }
+
+-void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
++void CDecoder::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic)
+ {
+ //CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
+- CVDPAU* vdp = (CVDPAU*)ctx->GetHardware();
++ CDecoder* vdp = (CDecoder*)ctx->GetHardware();
++
+ vdpau_render_state * render;
+ unsigned int i;
+
+- CSharedLock lock(vdp->m_DecoderSection);
++ CSingleLock lock(vdp->m_DecoderSection);
+
+ render=(vdpau_render_state*)pic->data[0];
+ if(!render)
+@@ -1233,6 +816,8 @@
+ return;
+ }
+
++ CSingleLock vLock(vdp->m_videoSurfaceSec);
++ render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
+ for(i=0; i<4; i++)
+ pic->data[i]= NULL;
+
+@@ -1247,21 +832,18 @@
+ }
+
+
+-void CVDPAU::FFDrawSlice(struct AVCodecContext *s,
++void CDecoder::FFDrawSlice(struct AVCodecContext *s,
+ const AVFrame *src, int offset[4],
+ int y, int type, int height)
+ {
+ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)s->opaque;
+- CVDPAU* vdp = (CVDPAU*)ctx->GetHardware();
++ CDecoder* vdp = (CDecoder*)ctx->GetHardware();
+
+ // while we are waiting to recover we can't do anything
+- CSharedLock lock(vdp->m_DecoderSection);
+-
+- { CSharedLock dLock(vdp->m_DisplaySection);
+- if(vdp->m_DisplayState != VDPAU_OPEN)
+- return;
+- }
++ CSingleLock lock(vdp->m_DecoderSection);
+
++ if(vdp->m_DisplayState != VDPAU_OPEN)
++ return;
+
+ if(src->linesize[0] || src->linesize[1] || src->linesize[2]
+ || offset[0] || offset[1] || offset[2])
+@@ -1291,59 +873,41 @@
+ if(s->pix_fmt == PIX_FMT_VDPAU_H264)
+ max_refs = render->info.h264.num_ref_frames;
+
+- if(vdp->decoder == VDP_INVALID_HANDLE
+- || vdp->vdpauConfigured == false
+- || vdp->max_references < max_refs)
++ if(vdp->m_vdpauConfig.vdpDecoder == VDP_INVALID_HANDLE
++ || vdp->m_vdpauConfigured == false
++ || vdp->m_vdpauConfig.maxReferences < max_refs)
+ {
+ if(!vdp->ConfigVDPAU(s, max_refs))
+ return;
+ }
+
+- vdp_st = vdp->vdp_decoder_render(vdp->decoder,
++ uint64_t startTime = CurrentHostCounter();
++ uint16_t decoded, processed, rend;
++ vdp->m_bufferStats.Get(decoded, processed, rend);
++ vdp_st = vdp->m_vdpauConfig.vdpProcs.vdp_decoder_render(vdp->m_vdpauConfig.vdpDecoder,
+ render->surface,
+ (VdpPictureInfo const *)&(render->info),
+ render->bitstream_buffers_used,
+ render->bitstream_buffers);
+ vdp->CheckStatus(vdp_st, __LINE__);
++ uint64_t diff = CurrentHostCounter() - startTime;
++ if (diff*1000/CurrentHostFrequency() > 30)
++ CLog::Log(LOGWARNING,"CVDPAU::DrawSlice - VdpDecoderRender long decoding: %d ms, dec: %d, proc: %d, rend: %d", (int)((diff*1000)/CurrentHostFrequency()), decoded, processed, rend);
++
+ }
+
+-int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
+-{
+- //CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
+- VdpStatus vdp_st;
+- VdpTime time;
+
++int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame, bool bSoftDrain, bool bHardDrain)
++{
+ int result = Check(avctx);
+ if (result)
+ return result;
+
+- CSharedLock lock(m_DecoderSection);
++ CSingleLock lock(m_DecoderSection);
+
+- if (!vdpauConfigured)
++ if (!m_vdpauConfigured)
+ return VC_ERROR;
+
+- // configure vdpau output
+- if (!ConfigOutputMethod(avctx, pFrame))
+- return VC_FLUSHED;
+-
+- outputSurface = outputSurfaces[surfaceNum];
+-
+- CheckFeatures();
+-
+- if (( (int)outRectVid.x1 != OutWidth ) ||
+- ( (int)outRectVid.y1 != OutHeight ))
+- {
+- outRectVid.x0 = 0;
+- outRectVid.y0 = 0;
+- outRectVid.x1 = OutWidth;
+- outRectVid.y1 = OutHeight;
+- }
+-
+- EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
+- EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
+- if (method == VS_INTERLACEMETHOD_AUTO)
+- method = AutoInterlaceMethod();
+-
+ if(pFrame)
+ { // we have a new frame from decoder
+
+@@ -1351,7 +915,10 @@
+ if(!render) // old style ffmpeg gave data on plane 0
+ render = (vdpau_render_state*)pFrame->data[0];
+ if(!render)
++ {
++ CLog::Log(LOGERROR, "CVDPAU::Decode: no valid frame");
+ return VC_ERROR;
++ }
+
+ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
+ if (!IsSurfaceValid(render))
+@@ -1360,256 +927,175 @@
+ return VC_BUFFER;
+ }
+
++ CSingleLock lock(m_videoSurfaceSec);
+ render->state |= FF_VDPAU_STATE_USED_FOR_RENDER;
++ lock.Leave();
++
++ // send frame to output for processing
++ CVdpauDecodedPicture pic;
++ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic));
++ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic);
++ pic.render = render;
++ m_bufferStats.IncDecoded();
++ m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic));
+
+- ClearUsedForRender(&past[0]);
+- past[0] = past[1];
+- past[1] = current;
+- current = future;
+- future = render;
+-
+- DVDVideoPicture DVDPic;
+- memset(&DVDPic, 0, sizeof(DVDVideoPicture));
+- ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&DVDPic);
+- m_DVDVideoPics.push(DVDPic);
+-
+- int pics = m_DVDVideoPics.size();
+- if (pics < 2)
+- return VC_BUFFER;
+- else if (pics > 2)
+- {
+- // this should not normally happen
+- CLog::Log(LOGERROR, "CVDPAU::Decode - invalid number of pictures in queue");
+- while (pics-- != 2)
+- m_DVDVideoPics.pop();
++ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_SKIP_PROC);
++ if (m_codecControl & DVP_FLAG_SKIP_PROC)
++ {
++ m_bufferStats.SetCmd(DVP_FLAG_SKIP_PROC);
+ }
++ }
+
+- if (mode == VS_DEINTERLACEMODE_FORCE
+- || (mode == VS_DEINTERLACEMODE_AUTO && m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED))
++ int retval = 0;
++ uint16_t decoded, processed, render;
++ Message *msg;
++ while (m_vdpauOutput.m_controlPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputControlProtocol::ERROR)
+ {
+- if((method == VS_INTERLACEMETHOD_VDPAU_BOB
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
+- || method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE ))
++ m_DisplayState = VDPAU_ERROR;
++ retval |= VC_ERROR;
++ }
++ msg->Release();
++ }
++
++ m_bufferStats.Get(decoded, processed, render);
++
++ uint64_t startTime = CurrentHostCounter();
++ while (!retval)
++ {
++ if (m_vdpauOutput.m_dataPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputDataProtocol::PICTURE)
+ {
+- if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
+- || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
+- || avctx->skip_frame == AVDISCARD_NONREF)
+- m_mixerstep = 0;
+- else
+- m_mixerstep = 1;
+-
+- if(m_DVDVideoPics.front().iFlags & DVP_FLAG_TOP_FIELD_FIRST)
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+- else
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
++ if (m_presentPicture)
++ {
++ m_presentPicture->ReturnUnused();
++ m_presentPicture = 0;
++ }
++
++ m_presentPicture = *(CVdpauRenderPicture**)msg->data;
++ m_presentPicture->vdpau = this;
++ m_bufferStats.DecRender();
++ m_bufferStats.Get(decoded, processed, render);
++ retval |= VC_PICTURE;
++ msg->Release();
++ break;
++ }
++ msg->Release();
++ }
++ else if (m_vdpauOutput.m_controlPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputControlProtocol::STATS)
++ {
++ m_bufferStats.Get(decoded, processed, render);
+ }
+ else
+ {
+- m_mixerstep = 0;
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
++ m_DisplayState = VDPAU_ERROR;
++ retval |= VC_ERROR;
+ }
++ msg->Release();
+ }
+- else
++
++ if ((m_codecControl & DVP_FLAG_DRAIN))
+ {
+- m_mixerstep = 0;
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
++ if (decoded + processed + render < 4)
++ {
++ retval |= VC_BUFFER;
++ }
+ }
+-
+- }
+- else if(m_mixerstep == 1)
+- { // no new frame given, output second field of old frame
+-
+- if(avctx->skip_frame == AVDISCARD_NONREF)
++ else
+ {
+- ClearUsedForRender(&past[1]);
+- m_DVDVideoPics.pop();
+- return VC_BUFFER;
++ if (decoded < 4 && (processed + render) < 3)
++ {
++ retval |= VC_BUFFER;
++ }
+ }
+
+- m_mixerstep = 2;
+- if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD)
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
+- else
+- m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
++ if (!retval && !m_inMsgEvent.WaitMSec(2000))
++ break;
+ }
+- else
++ uint64_t diff = CurrentHostCounter() - startTime;
++ if (retval & VC_PICTURE)
+ {
+- CLog::Log(LOGERROR, "CVDPAU::Decode - invalid mixer state reached");
+- return VC_BUFFER;
++ m_bufferStats.SetParams(diff, m_speed);
+ }
++ if (diff*1000/CurrentHostFrequency() > 50)
++ CLog::Log(LOGDEBUG,"CVDPAU::Decode long wait: %d", (int)((diff*1000)/CurrentHostFrequency()));
+
+- VdpVideoSurface past_surfaces[2] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
+- VdpVideoSurface futu_surfaces[1] = { VDP_INVALID_HANDLE };
+-
+- if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
+- {
+- if (past[0])
+- past_surfaces[1] = past[0]->surface;
+- if (past[1])
+- past_surfaces[0] = past[1]->surface;
+- futu_surfaces[0] = future->surface;
+- }
+- else
++ if (!retval)
+ {
+- if(m_mixerstep == 1)
+- { // first field
+- if (past[1])
+- {
+- past_surfaces[1] = past[1]->surface;
+- past_surfaces[0] = past[1]->surface;
+- }
+- futu_surfaces[0] = current->surface;
+- }
+- else
+- { // second field
+- if (past[1])
+- past_surfaces[1] = past[1]->surface;
+- past_surfaces[0] = current->surface;
+- futu_surfaces[0] = future->surface;
+- }
++ CLog::Log(LOGERROR, "VDPAU::%s - timed out waiting for output message", __FUNCTION__);
++ m_DisplayState = VDPAU_ERROR;
++ retval |= VC_ERROR;
+ }
+
+- vdp_st = vdp_presentation_queue_block_until_surface_idle(vdp_flip_queue,outputSurface,&time);
+-
+- VdpRect sourceRect = {0,0,vid_width, vid_height};
+-
+- vdp_st = vdp_video_mixer_render(videoMixer,
+- VDP_INVALID_HANDLE,
+- 0,
+- m_mixerfield,
+- 2,
+- past_surfaces,
+- current->surface,
+- 1,
+- futu_surfaces,
+- &sourceRect,
+- outputSurface,
+- &(outRectVid),
+- &(outRectVid),
+- 0,
+- NULL);
+- CheckStatus(vdp_st, __LINE__);
+-
+- surfaceNum++;
+- if (surfaceNum >= totalAvailableOutputSurfaces) surfaceNum = 0;
++ return retval;
++}
+
+- if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
+- {
+- ClearUsedForRender(&past[0]);
+- return VC_BUFFER | VC_PICTURE;
+- }
+- else
+- {
+- // in order to clip top and bottom lines when de-interlacing
+- // we black those lines as a work around for not working
+- // background colour using the mixer
+- // pixel perfect is preferred over overscanning or zooming
++bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
++{
++ CSingleLock lock(m_DecoderSection);
+
+- VdpRect clipRect = outRectVid;
+- clipRect.y1 = clipRect.y0 + 2;
+- uint32_t *data[] = {m_BlackBar};
+- uint32_t pitches[] = {outRectVid.x1};
+- vdp_st = vdp_output_surface_put_bits_native(outputSurface,
+- (void**)data,
+- pitches,
+- &clipRect);
+- CheckStatus(vdp_st, __LINE__);
++ if (m_DisplayState != VDPAU_OPEN)
++ return false;
+
+- clipRect = outRectVid;
+- clipRect.y0 = clipRect.y1 - 2;
+- vdp_st = vdp_output_surface_put_bits_native(outputSurface,
+- (void**)data,
+- pitches,
+- &clipRect);
+- CheckStatus(vdp_st, __LINE__);
++ *picture = m_presentPicture->DVDPic;
++ picture->vdpau = m_presentPicture;
+
+- if(m_mixerstep == 1)
+- return VC_PICTURE;
+- else
+- {
+- ClearUsedForRender(&past[1]);
+- return VC_BUFFER | VC_PICTURE;
+- }
+- }
++ return true;
+ }
+
+-bool CVDPAU::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
++void CDecoder::Reset()
+ {
+- CSharedLock lock(m_DecoderSection);
+-
+- { CSharedLock dLock(m_DisplaySection);
+- if (m_DisplayState != VDPAU_OPEN)
+- return false;
+- }
++ CSingleLock lock(m_DecoderSection);
+
+- *picture = m_DVDVideoPics.front();
+- // if this is the first field of an interlaced frame, we'll need
+- // this same picture for the second field later
+- if (m_mixerstep != 1)
+- m_DVDVideoPics.pop();
+-
+- picture->format = DVDVideoPicture::FMT_VDPAU;
+- picture->iFlags &= DVP_FLAG_DROPPED;
+- picture->iWidth = OutWidth;
+- picture->iHeight = OutHeight;
+- picture->vdpau = this;
++ if (!m_vdpauConfigured)
++ return;
+
+- if(m_mixerstep)
+- {
+- picture->iRepeatPicture = -0.5;
+- if(m_mixerstep > 1)
++ Message *reply;
++ if (m_vdpauOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::FLUSH,
++ &reply,
++ 2000))
++ {
++ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
++ reply->Release();
++ if (!success)
+ {
+- picture->dts = DVD_NOPTS_VALUE;
+- picture->pts = DVD_NOPTS_VALUE;
++ CLog::Log(LOGERROR, "VDPAU::%s - flush returned error", __FUNCTION__);
++ m_DisplayState = VDPAU_ERROR;
+ }
++ else
++ m_bufferStats.Reset();
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "VDPAU::%s - flush timed out", __FUNCTION__);
++ m_DisplayState = VDPAU_ERROR;
+ }
+- return true;
+ }
+
+-void CVDPAU::Reset()
++bool CDecoder::CanSkipDeint()
+ {
+- // invalidate surfaces and picture queue when seeking
+- ClearUsedForRender(&past[0]);
+- ClearUsedForRender(&past[1]);
+- ClearUsedForRender(¤t);
+- ClearUsedForRender(&future);
+-
+- while (!m_DVDVideoPics.empty())
+- m_DVDVideoPics.pop();
++ return m_bufferStats.CanSkipDeint();
+ }
+
+-void CVDPAU::Present()
++void CDecoder::SetSpeed(int speed)
+ {
+- //CLog::Log(LOGNOTICE,"%s",__FUNCTION__);
+- VdpStatus vdp_st;
+-
+- CSharedLock lock(m_DecoderSection);
+-
+- { CSharedLock dLock(m_DisplaySection);
+- if (m_DisplayState != VDPAU_OPEN)
+- return;
+- }
+-
+- presentSurface = outputSurface;
++ m_speed = speed;
++}
+
+- vdp_st = vdp_presentation_queue_display(vdp_flip_queue,
+- presentSurface,
+- 0,
+- 0,
+- 0);
+- CheckStatus(vdp_st, __LINE__);
++void CDecoder::ReturnRenderPicture(CVdpauRenderPicture *renderPic)
++{
++ m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::RETURNPIC, &renderPic, sizeof(renderPic));
+ }
+
+-bool CVDPAU::CheckStatus(VdpStatus vdp_st, int line)
++bool CDecoder::CheckStatus(VdpStatus vdp_st, int line)
+ {
+ if (vdp_st != VDP_STATUS_OK)
+ {
+- CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
+-
+- CExclusiveLock lock(m_DisplaySection);
++ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", m_vdpauConfig.vdpProcs.vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
+
+ if(m_DisplayState == VDPAU_OPEN)
+ {
+@@ -1627,4 +1113,2432 @@
+ return false;
+ }
+
++//-----------------------------------------------------------------------------
++// RenderPicture
++//-----------------------------------------------------------------------------
++
++CVdpauRenderPicture* CVdpauRenderPicture::Acquire()
++{
++ CSingleLock lock(*renderPicSection);
++
++ if (refCount == 0)
++ vdpau->Acquire();
++
++ refCount++;
++ return this;
++}
++
++long CVdpauRenderPicture::Release()
++{
++ CSingleLock lock(*renderPicSection);
++
++ refCount--;
++ if (refCount > 0)
++ return refCount;
++
++ lock.Leave();
++ vdpau->ReturnRenderPicture(this);
++ vdpau->ReleasePicReference();
++
++ return refCount;
++}
++
++void CVdpauRenderPicture::ReturnUnused()
++{
++ { CSingleLock lock(*renderPicSection);
++ if (refCount > 0)
++ return;
++ }
++ if (vdpau)
++ vdpau->ReturnRenderPicture(this);
++}
++
++//-----------------------------------------------------------------------------
++// Mixer
++//-----------------------------------------------------------------------------
++CMixer::CMixer(CEvent *inMsgEvent) :
++ CThread("Vdpau Mixer Thread"),
++ m_controlPort("ControlPort", inMsgEvent, &m_outMsgEvent),
++ m_dataPort("DataPort", inMsgEvent, &m_outMsgEvent)
++{
++ m_inMsgEvent = inMsgEvent;
++}
++
++CMixer::~CMixer()
++{
++ Dispose();
++}
++
++void CMixer::Start()
++{
++ Create();
++}
++
++void CMixer::Dispose()
++{
++ m_bStop = true;
++ m_outMsgEvent.Set();
++ StopThread();
++
++ m_controlPort.Purge();
++ m_dataPort.Purge();
++}
++
++void CMixer::OnStartup()
++{
++ CLog::Log(LOGNOTICE, "CMixer::OnStartup: Output Thread created");
++}
++
++void CMixer::OnExit()
++{
++ CLog::Log(LOGNOTICE, "CMixer::OnExit: Output Thread terminated");
++}
++
++enum MIXER_STATES
++{
++ M_TOP = 0, // 0
++ M_TOP_ERROR, // 1
++ M_TOP_UNCONFIGURED, // 2
++ M_TOP_CONFIGURED, // 3
++ M_TOP_CONFIGURED_WAIT1, // 4
++ M_TOP_CONFIGURED_STEP1, // 5
++ M_TOP_CONFIGURED_WAIT2, // 6
++ M_TOP_CONFIGURED_STEP2, // 7
++};
++
++int MIXER_parentStates[] = {
++ -1,
++ 0, //TOP_ERROR
++ 0, //TOP_UNCONFIGURED
++ 0, //TOP_CONFIGURED
++ 3, //TOP_CONFIGURED_WAIT1
++ 3, //TOP_CONFIGURED_STEP1
++ 3, //TOP_CONFIGURED_WAIT2
++ 3, //TOP_CONFIGURED_STEP2
++};
++
++void CMixer::StateMachine(int signal, Protocol *port, Message *msg)
++{
++ for (int state = m_state; ; state = MIXER_parentStates[state])
++ {
++ switch (state)
++ {
++ case M_TOP: // TOP
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case CMixerControlProtocol::FLUSH:
++ Flush();
++ msg->Reply(CMixerControlProtocol::ACC);
++ return;
++ default:
++ break;
++ }
++ }
++ {
++ std::string portName = port == NULL ? "timer" : port->portName;
++ CLog::Log(LOGWARNING, "CMixer::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
++ }
++ return;
++
++ case M_TOP_ERROR: // TOP
++ break;
++
++ case M_TOP_UNCONFIGURED:
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case CMixerControlProtocol::INIT:
++ CVdpauConfig *data;
++ data = (CVdpauConfig*)msg->data;
++ if (data)
++ {
++ m_config = *data;
++ }
++ Init();
++ if (!m_vdpError)
++ {
++ m_state = M_TOP_CONFIGURED_WAIT1;
++ msg->Reply(CMixerControlProtocol::ACC);
++ }
++ else
++ {
++ msg->Reply(CMixerControlProtocol::ERROR);
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case M_TOP_CONFIGURED:
++ if (port == &m_dataPort)
++ {
++ switch (signal)
++ {
++ case CMixerDataProtocol::FRAME:
++ CVdpauDecodedPicture *frame;
++ frame = (CVdpauDecodedPicture*)msg->data;
++ if (frame)
++ {
++ m_decodedPics.push(*frame);
++ }
++ m_extTimeout = 0;
++ return;
++ case CMixerDataProtocol::BUFFER:
++ VdpOutputSurface *surf;
++ surf = (VdpOutputSurface*)msg->data;
++ if (surf)
++ {
++ m_outputSurfaces.push(*surf);
++ }
++ m_extTimeout = 0;
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case M_TOP_CONFIGURED_WAIT1:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case CMixerControlProtocol::TIMEOUT:
++ if (!m_decodedPics.empty() && !m_outputSurfaces.empty())
++ {
++ m_state = M_TOP_CONFIGURED_STEP1;
++ m_bStateMachineSelfTrigger = true;
++ }
++ else
++ {
++// if (m_extTimeout != 0)
++// {
++// SetPostProcFeatures(false);
++// CLog::Log(LOGWARNING,"CVDPAU::Mixer timeout - decoded: %d, outputSurf: %d", (int)m_decodedPics.size(), (int)m_outputSurfaces.size());
++// }
++ m_extTimeout = 100;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case M_TOP_CONFIGURED_STEP1:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case CMixerControlProtocol::TIMEOUT:
++ m_mixerInput.push_front(m_decodedPics.front());
++ m_decodedPics.pop();
++ if (m_mixerInput.size() < 2)
++ {
++ m_state = M_TOP_CONFIGURED_WAIT1;
++ m_extTimeout = 0;
++ return;
++ }
++ InitCycle();
++ ProcessPicture();
++ if (m_vdpError)
++ {
++ m_state = M_TOP_CONFIGURED_WAIT1;
++ m_extTimeout = 1000;
++ return;
++ }
++ if (m_processPicture.DVDPic.format != DVDVideoPicture::FMT_VDPAU_420)
++ m_outputSurfaces.pop();
++ m_config.stats->IncProcessed();
++ m_config.stats->DecDecoded();
++ m_dataPort.SendInMessage(CMixerDataProtocol::PICTURE,&m_processPicture,sizeof(m_processPicture));
++ if (m_mixersteps > 1)
++ {
++ m_state = M_TOP_CONFIGURED_WAIT2;
++ m_extTimeout = 0;
++ }
++ else
++ {
++ FiniCycle();
++ m_state = M_TOP_CONFIGURED_WAIT1;
++ m_extTimeout = 0;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case M_TOP_CONFIGURED_WAIT2:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case CMixerControlProtocol::TIMEOUT:
++ if (!m_outputSurfaces.empty())
++ {
++ m_state = M_TOP_CONFIGURED_STEP2;
++ m_bStateMachineSelfTrigger = true;
++ }
++ else
++ {
++// if (m_extTimeout != 0)
++// {
++// SetPostProcFeatures(false);
++// CLog::Log(LOGNOTICE,"---mixer wait2 decoded: %d, outputSurf: %d", (int)m_decodedPics.size(), (int)m_outputSurfaces.size());
++// }
++ m_extTimeout = 100;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case M_TOP_CONFIGURED_STEP2:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case CMixerControlProtocol::TIMEOUT:
++ m_processPicture.outputSurface = m_outputSurfaces.front();
++ m_mixerstep = 1;
++ ProcessPicture();
++ if (m_vdpError)
++ {
++ m_state = M_TOP_CONFIGURED_WAIT1;
++ m_extTimeout = 1000;
++ return;
++ }
++ if (m_processPicture.DVDPic.format != DVDVideoPicture::FMT_VDPAU_420)
++ m_outputSurfaces.pop();
++ m_config.stats->IncProcessed();
++ m_dataPort.SendInMessage(CMixerDataProtocol::PICTURE,&m_processPicture,sizeof(m_processPicture));
++ FiniCycle();
++ m_state = M_TOP_CONFIGURED_WAIT1;
++ m_extTimeout = 0;
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ default: // we are in no state, should not happen
++ CLog::Log(LOGERROR, "CMixer::%s - no valid state: %d", __FUNCTION__, m_state);
++ return;
++ }
++ } // for
++}
++
++void CMixer::Process()
++{
++ Message *msg;
++ Protocol *port;
++ bool gotMsg;
++
++ m_state = M_TOP_UNCONFIGURED;
++ m_extTimeout = 1000;
++ m_bStateMachineSelfTrigger = false;
++
++ while (!m_bStop)
++ {
++ gotMsg = false;
++
++ if (m_bStateMachineSelfTrigger)
++ {
++ m_bStateMachineSelfTrigger = false;
++ // self trigger state machine
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ continue;
++ }
++ // check control port
++ else if (m_controlPort.ReceiveOutMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_controlPort;
++ }
++ // check data port
++ else if (m_dataPort.ReceiveOutMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_dataPort;
++ }
++
++ if (gotMsg)
++ {
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ continue;
++ }
++
++ // wait for message
++ else if (m_outMsgEvent.WaitMSec(m_extTimeout))
++ {
++ continue;
++ }
++ // time out
++ else
++ {
++ msg = m_controlPort.GetMessage();
++ msg->signal = CMixerControlProtocol::TIMEOUT;
++ port = 0;
++ // signal timeout to state machine
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ }
++ }
++ Uninit();
++}
++
++void CMixer::CreateVdpauMixer()
++{
++ CLog::Log(LOGNOTICE, " (VDPAU) Creating the video mixer");
++
++ InitCSCMatrix(m_config.vidWidth);
++
++ VdpVideoMixerParameter parameters[] = {
++ VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
++ VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
++ VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE};
++
++ void const * parameter_values[] = {
++ &m_config.surfaceWidth,
++ &m_config.surfaceHeight,
++ &m_config.vdpChromaType};
++
++ VdpStatus vdp_st = VDP_STATUS_ERROR;
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_create(m_config.vdpDevice,
++ m_config.featureCount,
++ m_config.vdpFeatures,
++ ARSIZE(parameters),
++ parameters,
++ parameter_values,
++ &m_videoMixer);
++ CheckStatus(vdp_st, __LINE__);
++
++ // create 3 pitches of black lines needed for clipping top
++ // and bottom lines when de-interlacing
++ m_BlackBar = new uint32_t[3*m_config.outWidth];
++ memset(m_BlackBar, 0, 3*m_config.outWidth*sizeof(uint32_t));
++
++}
++
++void CMixer::InitCSCMatrix(int Width)
++{
++ VdpStatus vdp_st;
++ m_Procamp.struct_version = VDP_PROCAMP_VERSION;
++ m_Procamp.brightness = 0.0;
++ m_Procamp.contrast = 1.0;
++ m_Procamp.saturation = 1.0;
++ m_Procamp.hue = 0;
++ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp,
++ (Width < 1000)? VDP_COLOR_STANDARD_ITUR_BT_601 : VDP_COLOR_STANDARD_ITUR_BT_709,
++ &m_CSCMatrix);
++ CheckStatus(vdp_st, __LINE__);
++}
++
++void CMixer::CheckFeatures()
++{
++ if (m_Upscale != m_config.upscale)
++ {
++ SetHWUpscaling();
++ m_Upscale = m_config.upscale;
++ }
++ if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness ||
++ m_Contrast != g_settings.m_currentVideoSettings.m_Contrast)
++ {
++ SetColor();
++ m_Brightness = g_settings.m_currentVideoSettings.m_Brightness;
++ m_Contrast = g_settings.m_currentVideoSettings.m_Contrast;
++ }
++ if (m_NoiseReduction != g_settings.m_currentVideoSettings.m_NoiseReduction)
++ {
++ m_NoiseReduction = g_settings.m_currentVideoSettings.m_NoiseReduction;
++ SetNoiseReduction();
++ }
++ if (m_Sharpness != g_settings.m_currentVideoSettings.m_Sharpness)
++ {
++ m_Sharpness = g_settings.m_currentVideoSettings.m_Sharpness;
++ SetSharpness();
++ }
++ if (m_DeintMode != g_settings.m_currentVideoSettings.m_DeinterlaceMode ||
++ m_Deint != g_settings.m_currentVideoSettings.m_InterlaceMethod)
++ {
++ m_DeintMode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
++ m_Deint = g_settings.m_currentVideoSettings.m_InterlaceMethod;
++ SetDeinterlacing();
++ }
++}
++
++void CMixer::SetPostProcFeatures(bool postProcEnabled)
++{
++ if (m_PostProc != postProcEnabled)
++ {
++ if (postProcEnabled)
++ {
++ SetNoiseReduction();
++ SetSharpness();
++ SetDeinterlacing();
++ SetHWUpscaling();
++ }
++ else
++ PostProcOff();
++ m_PostProc = postProcEnabled;
++ }
++}
++
++void CMixer::PostProcOff()
++{
++ VdpStatus vdp_st;
++
++ if (m_videoMixer == VDP_INVALID_HANDLE)
++ return;
++
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
++ VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
++ VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE};
++
++ VdpBool enabled[]={0,0,0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION};
++
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS};
++
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ DisableHQScaling();
++}
++
++
++bool CMixer::GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix)
++{
++ // instead use studioCSCKCoeffs601[3], studioCSCKCoeffs709[3] to generate float[3][4] matrix (float studioCSC[3][4])
++ // m00 = mRY = red: luma factor (contrast factor) (1.0)
++ // m10 = mGY = green: luma factor (contrast factor) (1.0)
++ // m20 = mBY = blue: luma factor (contrast factor) (1.0)
++ //
++ // m01 = mRB = red: blue color diff coeff (0.0)
++ // m11 = mGB = green: blue color diff coeff (-2Kb(1-Kb)/(Kg))
++ // m21 = mBB = blue: blue color diff coeff ((1-Kb)/0.5)
++ //
++ // m02 = mRR = red: red color diff coeff ((1-Kr)/0.5)
++ // m12 = mGR = green: red color diff coeff (-2Kr(1-Kr)/(Kg))
++ // m22 = mBR = blue: red color diff coeff (0.0)
++ //
++ // m03 = mRC = red: colour zero offset (brightness factor) (-(1-Kr)/0.5 * (128/255))
++ // m13 = mGC = green: colour zero offset (brightness factor) ((256/255) * (Kb(1-Kb) + Kr(1-Kr)) / Kg)
++ // m23 = mBC = blue: colour zero offset (brightness factor) (-(1-Kb)/0.5 * (128/255))
++
++ // columns
++ int Y = 0;
++ int Cb = 1;
++ int Cr = 2;
++ int C = 3;
++ // rows
++ int R = 0;
++ int G = 1;
++ int B = 2;
++ // colour standard coefficients for red, geen, blue
++ double Kr, Kg, Kb;
++ // colour diff zero position (use standard 8-bit coding precision)
++ double CDZ = 128; //256*0.5
++ // range excursion (use standard 8-bit coding precision)
++ double EXC = 255; //256-1
++
++ if (colorStandard == VDP_COLOR_STANDARD_ITUR_BT_601)
++ {
++ Kr = studioCSCKCoeffs601[0];
++ Kg = studioCSCKCoeffs601[1];
++ Kb = studioCSCKCoeffs601[2];
++ }
++ else // assume VDP_COLOR_STANDARD_ITUR_BT_709
++ {
++ Kr = studioCSCKCoeffs709[0];
++ Kg = studioCSCKCoeffs709[1];
++ Kb = studioCSCKCoeffs709[2];
++ }
++ // we keep luma unscaled to retain the levels present in source so that 16-235 luma is converted to RGB 16-235
++ studioCSCMatrix[R][Y] = 1.0;
++ studioCSCMatrix[G][Y] = 1.0;
++ studioCSCMatrix[B][Y] = 1.0;
++
++ studioCSCMatrix[R][Cb] = 0.0;
++ studioCSCMatrix[G][Cb] = (double)-2 * Kb * (1 - Kb) / Kg;
++ studioCSCMatrix[B][Cb] = (double)(1 - Kb) / 0.5;
++
++ studioCSCMatrix[R][Cr] = (double)(1 - Kr) / 0.5;
++ studioCSCMatrix[G][Cr] = (double)-2 * Kr * (1 - Kr) / Kg;
++ studioCSCMatrix[B][Cr] = 0.0;
++
++ studioCSCMatrix[R][C] = (double)-1 * studioCSCMatrix[R][Cr] * CDZ/EXC;
++ studioCSCMatrix[G][C] = (double)-1 * (studioCSCMatrix[G][Cb] + studioCSCMatrix[G][Cr]) * CDZ/EXC;
++ studioCSCMatrix[B][C] = (double)-1 * studioCSCMatrix[B][Cb] * CDZ/EXC;
++
++ return true;
++}
++
++void CMixer::SetColor()
++{
++ VdpStatus vdp_st;
++
++ if (m_Brightness != g_settings.m_currentVideoSettings.m_Brightness)
++ m_Procamp.brightness = (float)((g_settings.m_currentVideoSettings.m_Brightness)-50) / 100;
++ if (m_Contrast != g_settings.m_currentVideoSettings.m_Contrast)
++ m_Procamp.contrast = (float)((g_settings.m_currentVideoSettings.m_Contrast)+50) / 100;
++
++ VdpColorStandard colorStandard;
++// if(vid_height >= 600 || vid_width > 1024)
++ if(m_config.surfaceWidth > 1000)
++ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_709;
++ //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_709, &m_CSCMatrix);
++ else
++ colorStandard = VDP_COLOR_STANDARD_ITUR_BT_601;
++ //vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix);
++
++ VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX };
++ if (g_guiSettings.GetBool("videoplayer.vdpaustudiolevel"))
++ {
++ float studioCSC[3][4];
++ GenerateStudioCSCMatrix(colorStandard, studioCSC);
++ void const * pm_CSCMatix[] = { &studioCSC };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
++ }
++ else
++ {
++ vdp_st = m_config.vdpProcs.vdp_generate_csc_matrix(&m_Procamp, colorStandard, &m_CSCMatrix);
++ void const * pm_CSCMatix[] = { &m_CSCMatrix };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix);
++ }
++ CheckStatus(vdp_st, __LINE__);
++}
++
++void CMixer::SetNoiseReduction()
++{
++ if(!m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION))
++ return;
++
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION };
++ VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL };
++ VdpStatus vdp_st;
++
++ if (!g_settings.m_currentVideoSettings.m_NoiseReduction)
++ {
++ VdpBool enabled[]= {0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ return;
++ }
++ VdpBool enabled[]={1};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ void* nr[] = { &g_settings.m_currentVideoSettings.m_NoiseReduction };
++ CLog::Log(LOGNOTICE,"Setting Noise Reduction to %f",g_settings.m_currentVideoSettings.m_NoiseReduction);
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, nr);
++ CheckStatus(vdp_st, __LINE__);
++}
++
++void CMixer::SetSharpness()
++{
++ if(!m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_SHARPNESS))
++ return;
++
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS };
++ VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL };
++ VdpStatus vdp_st;
++
++ if (!g_settings.m_currentVideoSettings.m_Sharpness)
++ {
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ return;
++ }
++ VdpBool enabled[]={1};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ void* sh[] = { &g_settings.m_currentVideoSettings.m_Sharpness };
++ CLog::Log(LOGNOTICE,"Setting Sharpness to %f",g_settings.m_currentVideoSettings.m_Sharpness);
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attributes), attributes, sh);
++ CheckStatus(vdp_st, __LINE__);
++}
++
++EINTERLACEMETHOD CMixer::GetDeinterlacingMethod(bool log /* = false */)
++{
++ EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
++ if (method == VS_INTERLACEMETHOD_AUTO)
++ {
++ int deint = -1;
++ if (m_config.outHeight >= 720)
++ deint = g_advancedSettings.m_videoVDPAUdeintHD;
++ else
++ deint = g_advancedSettings.m_videoVDPAUdeintSD;
++
++ if (deint != -1)
++ {
++ if (m_config.vdpau->Supports(EINTERLACEMETHOD(deint)))
++ {
++ method = EINTERLACEMETHOD(deint);
++ if (log)
++ CLog::Log(LOGNOTICE, "CVDPAU::GetDeinterlacingMethod: set de-interlacing to %d", deint);
++ }
++ else
++ {
++ if (log)
++ CLog::Log(LOGWARNING, "CVDPAU::GetDeinterlacingMethod: method for de-interlacing (advanced settings) not supported");
++ }
++ }
++ }
++ return method;
++}
++
++void CMixer::SetDeinterlacing()
++{
++ VdpStatus vdp_st;
++
++ if (m_videoMixer == VDP_INVALID_HANDLE)
++ return;
++
++ EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
++ EINTERLACEMETHOD method = GetDeinterlacingMethod(true);
++
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
++ VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
++ VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE };
++
++ if (mode == VS_DEINTERLACEMODE_OFF)
++ {
++ VdpBool enabled[] = {0,0,0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ }
++ else
++ {
++ if (method == VS_INTERLACEMETHOD_AUTO)
++ {
++ VdpBool enabled[] = {1,1,0};
++ if (g_advancedSettings.m_videoVDPAUtelecine)
++ enabled[2] = 1;
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ }
++ else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF)
++ {
++ VdpBool enabled[] = {1,0,0};
++ if (g_advancedSettings.m_videoVDPAUtelecine)
++ enabled[2] = 1;
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ }
++ else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF)
++ {
++ VdpBool enabled[] = {1,1,0};
++ if (g_advancedSettings.m_videoVDPAUtelecine)
++ enabled[2] = 1;
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ }
++ else
++ {
++ VdpBool enabled[]={0,0,0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ }
++ }
++ CheckStatus(vdp_st, __LINE__);
++
++ SetDeintSkipChroma();
++
++ m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv");
++}
++
++void CMixer::SetDeintSkipChroma()
++{
++ VdpVideoMixerAttribute attribute[] = { VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE};
++ VdpStatus vdp_st;
++
++ uint8_t val;
++ if (g_advancedSettings.m_videoVDPAUdeintSkipChromaHD && m_config.outHeight >= 720)
++ val = 1;
++ else
++ val = 0;
++
++ void const *values[]={&val};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_attribute_values(m_videoMixer, ARSIZE(attribute), attribute, values);
++
++ CheckStatus(vdp_st, __LINE__);
++}
++
++void CMixer::SetHWUpscaling()
++{
++#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1
++
++ VdpStatus vdp_st;
++ VdpBool enabled[]={1};
++ switch (m_config.upscale)
++ {
++ case 9:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 8:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 7:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 6:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 5:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 4:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 3:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 2:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ case 1:
++ if (m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 };
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ break;
++ }
++ default:
++ DisableHQScaling();
++ return;
++ }
++ CheckStatus(vdp_st, __LINE__);
++#endif
++}
++
++void CMixer::DisableHQScaling()
++{
++ VdpStatus vdp_st;
++
++ if (m_videoMixer == VDP_INVALID_HANDLE)
++ return;
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++
++ if(m_config.vdpau->Supports(VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9))
++ {
++ VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9 };
++ VdpBool enabled[]={0};
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
++ CheckStatus(vdp_st, __LINE__);
++ }
++}
++
++
++void CMixer::Init()
++{
++ m_Brightness = 0.0;
++ m_Contrast = 0.0;
++ m_NoiseReduction = 0.0;
++ m_Sharpness = 0.0;
++ m_DeintMode = 0;
++ m_Deint = 0;
++ m_PostProc = false;
++ m_vdpError = false;
++
++ m_config.upscale = g_advancedSettings.m_videoVDPAUScaling;
++ m_config.useInteropYuv = g_guiSettings.GetBool("videoplayer.usevdpauinteropyuv");
++
++ CreateVdpauMixer();
++}
++
++void CMixer::Uninit()
++{
++ Flush();
++ while (!m_outputSurfaces.empty())
++ {
++ m_outputSurfaces.pop();
++ }
++ m_config.vdpProcs.vdp_video_mixer_destroy(m_videoMixer);
++}
++
++void CMixer::Flush()
++{
++ while (!m_mixerInput.empty())
++ {
++ CVdpauDecodedPicture pic = m_mixerInput.back();
++ m_mixerInput.pop_back();
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ while (!m_decodedPics.empty())
++ {
++ CVdpauDecodedPicture pic = m_decodedPics.front();
++ m_decodedPics.pop();
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ Message *msg;
++ while (m_dataPort.ReceiveOutMessage(&msg))
++ {
++ if (msg->signal == CMixerDataProtocol::FRAME)
++ {
++ CVdpauDecodedPicture pic = *(CVdpauDecodedPicture*)msg->data;
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ else if (msg->signal == CMixerDataProtocol::BUFFER)
++ {
++ VdpOutputSurface *surf;
++ surf = (VdpOutputSurface*)msg->data;
++ m_outputSurfaces.push(*surf);
++ }
++ msg->Release();
++ }
++}
++
++void CMixer::InitCycle()
++{
++ CheckFeatures();
++ uint64_t latency;
++ int speed;
++ m_config.stats->GetParams(latency, speed);
++ latency = (latency*1000)/CurrentHostFrequency();
++ if (speed != DVD_PLAYSPEED_NORMAL)
++ SetPostProcFeatures(false);
++ else
++ SetPostProcFeatures(true);
++
++ m_config.stats->SetCanSkipDeint(false);
++
++ EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
++ EINTERLACEMETHOD method = GetDeinterlacingMethod();
++ bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED;
++
++ if (mode == VS_DEINTERLACEMODE_FORCE ||
++ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))
++ {
++ if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
++ || method == VS_INTERLACEMETHOD_VDPAU_BOB
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
++ || method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE )
++ {
++ if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
++ || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
++ || !g_graphicsContext.IsFullScreenVideo())
++ m_mixersteps = 1;
++ else
++ {
++ m_mixersteps = 2;
++ m_config.stats->SetCanSkipDeint(true);
++ }
++
++ if (m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT)
++ {
++ m_mixersteps = 1;
++ }
++
++ if(m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST)
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
++ else
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
++
++ m_mixerInput[1].DVDPic.format = DVDVideoPicture::FMT_VDPAU;
++ m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
++ DVP_FLAG_REPEAT_TOP_FIELD |
++ DVP_FLAG_INTERLACED);
++ m_config.useInteropYuv = false;
++ }
++ else if (method == VS_INTERLACEMETHOD_RENDER_BOB && m_config.useInteropYuv)
++ {
++ m_mixersteps = 1;
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
++ m_mixerInput[1].DVDPic.format = DVDVideoPicture::FMT_VDPAU_420;
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "CMixer::%s - interlace method not supported", __FUNCTION__);
++ m_mixersteps = 1;
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
++ m_mixerInput[1].DVDPic.format = DVDVideoPicture::FMT_VDPAU;
++ m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
++ DVP_FLAG_REPEAT_TOP_FIELD |
++ DVP_FLAG_INTERLACED);
++ }
++ }
++ else
++ {
++ m_mixersteps = 1;
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
++
++ if (m_config.useInteropYuv)
++ m_mixerInput[1].DVDPic.format = DVDVideoPicture::FMT_VDPAU_420;
++ else
++ {
++ m_mixerInput[1].DVDPic.format = DVDVideoPicture::FMT_VDPAU;
++ m_mixerInput[1].DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
++ DVP_FLAG_REPEAT_TOP_FIELD |
++ DVP_FLAG_INTERLACED);
++ }
++ }
++ m_mixerstep = 0;
++
++ if (m_mixerInput[1].DVDPic.format == DVDVideoPicture::FMT_VDPAU)
++ {
++ m_processPicture.outputSurface = m_outputSurfaces.front();
++ m_mixerInput[1].DVDPic.iWidth = m_config.outWidth;
++ m_mixerInput[1].DVDPic.iHeight = m_config.outHeight;
++ }
++ else
++ {
++ m_mixerInput[1].DVDPic.iWidth = m_config.vidWidth;
++ m_mixerInput[1].DVDPic.iHeight = m_config.vidHeight;
++ }
++
++ m_processPicture.DVDPic = m_mixerInput[1].DVDPic;
++ m_processPicture.render = m_mixerInput[1].render;
++}
++
++void CMixer::FiniCycle()
++{
++ while (m_mixerInput.size() > 3)
++ {
++ CVdpauDecodedPicture &tmp = m_mixerInput.back();
++ if (tmp.render && m_processPicture.DVDPic.format != DVDVideoPicture::FMT_VDPAU_420)
++ {
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ tmp.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ m_mixerInput.pop_back();
++// m_config.stats->DecDecoded();
++ }
++}
++
++void CMixer::ProcessPicture()
++{
++ if (m_processPicture.DVDPic.format == DVDVideoPicture::FMT_VDPAU_420)
++ return;
++
++ int cmd = 0;
++ m_config.stats->GetCmd(cmd);
++ if (cmd & DVP_FLAG_SKIP_PROC)
++ {
++ m_processPicture.DVDPic.iFlags |= DVP_FLAG_DROPPED;
++ return;
++ }
++
++ VdpStatus vdp_st;
++
++ if (m_mixerstep == 1)
++ {
++ if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD)
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
++ else
++ m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
++ }
++
++ VdpVideoSurface past_surfaces[4] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE, VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
++ VdpVideoSurface futu_surfaces[2] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
++ uint32_t pastCount = 4;
++ uint32_t futuCount = 2;
++
++ if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
++ {
++ // use only 2 past 1 future for progressive/weave
++ // (only used for postproc anyway eg noise reduction)
++ if (m_mixerInput.size() > 3)
++ past_surfaces[1] = m_mixerInput[3].render->surface;
++ if (m_mixerInput.size() > 2)
++ past_surfaces[0] = m_mixerInput[2].render->surface;
++ futu_surfaces[0] = m_mixerInput[0].render->surface;
++ pastCount = 2;
++ futuCount = 1;
++ }
++ else
++ {
++ if(m_mixerstep == 0)
++ { // first field
++ if (m_mixerInput.size() > 3)
++ {
++ past_surfaces[3] = m_mixerInput[3].render->surface;
++ past_surfaces[2] = m_mixerInput[3].render->surface;
++ }
++ if (m_mixerInput.size() > 2)
++ {
++ past_surfaces[1] = m_mixerInput[2].render->surface;
++ past_surfaces[0] = m_mixerInput[2].render->surface;
++ }
++ futu_surfaces[0] = m_mixerInput[1].render->surface;
++ futu_surfaces[1] = m_mixerInput[0].render->surface;;
++ }
++ else
++ { // second field
++ if (m_mixerInput.size() > 3)
++ {
++ past_surfaces[3] = m_mixerInput[3].render->surface;
++ }
++ if (m_mixerInput.size() > 2)
++ {
++ past_surfaces[2] = m_mixerInput[2].render->surface;
++ past_surfaces[1] = m_mixerInput[2].render->surface;
++ }
++ past_surfaces[0] = m_mixerInput[1].render->surface;
++ futu_surfaces[0] = m_mixerInput[1].render->surface;
++ futu_surfaces[1] = m_mixerInput[1].render->surface;
++
++ m_processPicture.DVDPic.pts = DVD_NOPTS_VALUE;
++ m_processPicture.DVDPic.dts = DVD_NOPTS_VALUE;
++ }
++ m_processPicture.DVDPic.iRepeatPicture = 0.0;
++ } // interlaced
++
++ VdpRect sourceRect;
++ sourceRect.x0 = 0;
++ sourceRect.y0 = 0;
++ sourceRect.x1 = m_config.vidWidth;
++ sourceRect.y1 = m_config.vidHeight;
++
++ VdpRect destRect;
++ destRect.x0 = 0;
++ destRect.y0 = 0;
++ destRect.x1 = m_config.outWidth;
++ destRect.y1 = m_config.outHeight;
++
++ // start vdpau video mixer
++ vdp_st = m_config.vdpProcs.vdp_video_mixer_render(m_videoMixer,
++ VDP_INVALID_HANDLE,
++ 0,
++ m_mixerfield,
++ pastCount,
++ past_surfaces,
++ m_mixerInput[1].render->surface,
++ futuCount,
++ futu_surfaces,
++ &sourceRect,
++ m_processPicture.outputSurface,
++ &destRect,
++ &destRect,
++ 0,
++ NULL);
++ CheckStatus(vdp_st, __LINE__);
++
++ if (m_mixerfield != VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
++ {
++ // in order to clip top and bottom lines when de-interlacing
++ // we black those lines as a work around for not working
++ // background colour using the mixer
++ // pixel perfect is preferred over overscanning or zooming
++
++ VdpRect clipRect = destRect;
++ clipRect.y1 = clipRect.y0 + 2;
++ uint32_t *data[] = {m_BlackBar};
++ uint32_t pitches[] = {destRect.x1};
++ vdp_st = m_config.vdpProcs.vdp_output_surface_put_bits_native(m_processPicture.outputSurface,
++ (void**)data,
++ pitches,
++ &clipRect);
++ CheckStatus(vdp_st, __LINE__);
++
++ clipRect = destRect;
++ clipRect.y0 = clipRect.y1 - 2;
++ vdp_st = m_config.vdpProcs.vdp_output_surface_put_bits_native(m_processPicture.outputSurface,
++ (void**)data,
++ pitches,
++ &clipRect);
++ CheckStatus(vdp_st, __LINE__);
++ }
++}
++
++
++bool CMixer::CheckStatus(VdpStatus vdp_st, int line)
++{
++ if (vdp_st != VDP_STATUS_OK)
++ {
++ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", m_config.vdpProcs.vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
++ m_vdpError = true;
++ return true;
++ }
++ return false;
++}
++
++//-----------------------------------------------------------------------------
++// Output
++//-----------------------------------------------------------------------------
++COutput::COutput(CEvent *inMsgEvent) :
++ CThread("Vdpau Output Thread"),
++ m_controlPort("OutputControlPort", inMsgEvent, &m_outMsgEvent),
++ m_dataPort("OutputDataPort", inMsgEvent, &m_outMsgEvent),
++ m_mixer(&m_outMsgEvent)
++{
++ m_inMsgEvent = inMsgEvent;
++
++ CVdpauRenderPicture pic;
++ pic.renderPicSection = &m_bufferPool.renderPicSec;
++ pic.refCount = 0;
++ for (unsigned int i = 0; i < NUM_RENDER_PICS; i++)
++ {
++ m_bufferPool.allRenderPics.push_back(pic);
++ }
++ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); ++i)
++ {
++ m_bufferPool.freeRenderPics.push_back(&m_bufferPool.allRenderPics[i]);
++ }
++}
++
++void COutput::Start()
++{
++ Create();
++}
++
++COutput::~COutput()
++{
++ Dispose();
++
++ m_bufferPool.freeRenderPics.clear();
++ m_bufferPool.usedRenderPics.clear();
++ m_bufferPool.allRenderPics.clear();
++}
++
++void COutput::Dispose()
++{
++ CSingleLock lock(g_graphicsContext);
++ m_bStop = true;
++ m_outMsgEvent.Set();
++ StopThread();
++ m_controlPort.Purge();
++ m_dataPort.Purge();
++}
++
++void COutput::OnStartup()
++{
++ CLog::Log(LOGNOTICE, "COutput::OnStartup: Output Thread created");
++}
++
++void COutput::OnExit()
++{
++ CLog::Log(LOGNOTICE, "COutput::OnExit: Output Thread terminated");
++}
++
++enum OUTPUT_STATES
++{
++ O_TOP = 0, // 0
++ O_TOP_ERROR, // 1
++ O_TOP_UNCONFIGURED, // 2
++ O_TOP_CONFIGURED, // 3
++ O_TOP_CONFIGURED_IDLE, // 4
++ O_TOP_CONFIGURED_WORK, // 5
++};
++
++int VDPAU_OUTPUT_parentStates[] = {
++ -1,
++ 0, //TOP_ERROR
++ 0, //TOP_UNCONFIGURED
++ 0, //TOP_CONFIGURED
++ 3, //TOP_CONFIGURED_IDLE
++ 3, //TOP_CONFIGURED_WORK
++};
++
++void COutput::StateMachine(int signal, Protocol *port, Message *msg)
++{
++ for (int state = m_state; ; state = VDPAU_OUTPUT_parentStates[state])
++ {
++ switch (state)
++ {
++ case O_TOP: // TOP
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::FLUSH:
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ case COutputControlProtocol::PRECLEANUP:
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ default:
++ break;
++ }
++ }
++ else if (port == &m_dataPort)
++ {
++ switch (signal)
++ {
++ case COutputDataProtocol::RETURNPIC:
++ CVdpauRenderPicture *pic;
++ pic = *((CVdpauRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ return;
++ default:
++ break;
++ }
++ }
++ {
++ std::string portName = port == NULL ? "timer" : port->portName;
++ CLog::Log(LOGWARNING, "COutput::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
++ }
++ return;
++
++ case O_TOP_ERROR:
++ break;
++
++ case O_TOP_UNCONFIGURED:
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::INIT:
++ CVdpauConfig *data;
++ data = (CVdpauConfig*)msg->data;
++ if (data)
++ {
++ m_config = *data;
++ }
++ Init();
++ Message *reply;
++ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::INIT,
++ &reply, 1000, &m_config, sizeof(m_config)))
++ {
++ if (reply->signal != CMixerControlProtocol::ACC)
++ m_vdpError = true;
++ reply->Release();
++ }
++
++ // set initial number of
++ m_bufferPool.numOutputSurfaces = 4;
++ EnsureBufferPool();
++ if (!m_vdpError)
++ {
++ m_state = O_TOP_CONFIGURED_IDLE;
++ msg->Reply(COutputControlProtocol::ACC);
++ }
++ else
++ {
++ m_state = O_TOP_ERROR;
++ msg->Reply(COutputControlProtocol::ERROR);
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED:
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::FLUSH:
++ Flush();
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ case COutputControlProtocol::PRECLEANUP:
++ Flush();
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ default:
++ break;
++ }
++ }
++ else if (port == &m_dataPort)
++ {
++ switch (signal)
++ {
++ case COutputDataProtocol::NEWFRAME:
++ CVdpauDecodedPicture *frame;
++ frame = (CVdpauDecodedPicture*)msg->data;
++ if (frame)
++ {
++ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::FRAME,
++ frame,sizeof(CVdpauDecodedPicture));
++ }
++ return;
++ case COutputDataProtocol::RETURNPIC:
++ CVdpauRenderPicture *pic;
++ pic = *((CVdpauRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ m_controlPort.SendInMessage(COutputControlProtocol::STATS);
++ m_state = O_TOP_CONFIGURED_WORK;
++ m_extTimeout = 0;
++ return;
++ default:
++ break;
++ }
++ }
++ else if (port == &m_mixer.m_dataPort)
++ {
++ switch (signal)
++ {
++ case CMixerDataProtocol::PICTURE:
++ CVdpauProcessedPicture *pic;
++ pic = (CVdpauProcessedPicture*)msg->data;
++ m_bufferPool.processedPics.push(*pic);
++ m_state = O_TOP_CONFIGURED_WORK;
++ m_extTimeout = 0;
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_IDLE:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++// uint16_t decoded, processed, render;
++// m_config.stats->Get(decoded, processed, render);
++// CLog::Log(LOGDEBUG, "CVDPAU::COutput - timeout idle: decoded: %d, proc: %d, render: %d", decoded, processed, render);
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_WORK:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++ if (HasWork())
++ {
++ CVdpauRenderPicture *pic;
++ pic = ProcessMixerPicture();
++ if (pic)
++ {
++ m_config.stats->DecProcessed();
++ m_config.stats->IncRender();
++ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &pic, sizeof(pic));
++ }
++ m_extTimeout = 1;
++ }
++ else
++ {
++ m_state = O_TOP_CONFIGURED_IDLE;
++ m_extTimeout = 100;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ default: // we are in no state, should not happen
++ CLog::Log(LOGERROR, "COutput::%s - no valid state: %d", __FUNCTION__, m_state);
++ return;
++ }
++ } // for
++}
++
++void COutput::Process()
++{
++ Message *msg;
++ Protocol *port;
++ bool gotMsg;
++
++ m_state = O_TOP_UNCONFIGURED;
++ m_extTimeout = 1000;
++ m_bStateMachineSelfTrigger = false;
++
++ while (!m_bStop)
++ {
++ gotMsg = false;
++
++ if (m_bStateMachineSelfTrigger)
++ {
++ m_bStateMachineSelfTrigger = false;
++ // self trigger state machine
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ continue;
++ }
++ // check control port
++ else if (m_controlPort.ReceiveOutMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_controlPort;
++ }
++ // check data port
++ else if (m_dataPort.ReceiveOutMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_dataPort;
++ }
++ // check mixer data port
++ else if (m_mixer.m_dataPort.ReceiveInMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_mixer.m_dataPort;
++ }
++ if (gotMsg)
++ {
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ continue;
++ }
++
++ // wait for message
++ else if (m_outMsgEvent.WaitMSec(m_extTimeout))
++ {
++ continue;
++ }
++ // time out
++ else
++ {
++ msg = m_controlPort.GetMessage();
++ msg->signal = COutputControlProtocol::TIMEOUT;
++ port = 0;
++ // signal timeout to state machine
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ }
++ }
++ Flush();
++ Uninit();
++}
++
++bool COutput::Init()
++{
++ if (!CreateGlxContext())
++ return false;
++
++ if (!GLInit())
++ return false;
++
++ m_mixer.Start();
++ m_vdpError = false;
++
++ return true;
++}
++
++bool COutput::Uninit()
++{
++ m_mixer.Dispose();
++ GLUnmapSurfaces();
++ GLUnbindPixmaps();
++ ReleaseBufferPool();
++ DestroyGlxContext();
++ return true;
++}
++
++void COutput::Flush()
++{
++ Message *reply;
++ if (m_mixer.m_controlPort.SendOutMessageSync(CMixerControlProtocol::FLUSH,
++ &reply,
++ 2000))
++ {
++ reply->Release();
++ }
++ else
++ CLog::Log(LOGERROR, "Coutput::%s - failed to flush mixer", __FUNCTION__);
++
++ Message *msg;
++ while (m_mixer.m_dataPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == CMixerDataProtocol::PICTURE)
++ {
++ CVdpauProcessedPicture pic = *(CVdpauProcessedPicture*)msg->data;
++ if (pic.DVDPic.format == DVDVideoPicture::FMT_VDPAU_420)
++ {
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ }
++ msg->Release();
++ }
++
++ while (m_dataPort.ReceiveOutMessage(&msg))
++ {
++ if (msg->signal == COutputDataProtocol::NEWFRAME)
++ {
++ CVdpauDecodedPicture pic = *(CVdpauDecodedPicture*)msg->data;
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ else if (msg->signal == COutputDataProtocol::RETURNPIC)
++ {
++ CVdpauRenderPicture *pic;
++ pic = *((CVdpauRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ }
++ msg->Release();
++ }
++
++ while (m_dataPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputDataProtocol::PICTURE)
++ {
++ CVdpauRenderPicture *pic;
++ pic = *((CVdpauRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ }
++ }
++
++ // reset used render flag which was cleared on mixer flush
++ std::deque::iterator it;
++ for (it = m_bufferPool.usedRenderPics.begin(); it != m_bufferPool.usedRenderPics.end(); ++it)
++ {
++ if ((*it)->DVDPic.format == DVDVideoPicture::FMT_VDPAU_420)
++ {
++ std::map::iterator it2;
++ it2 = m_bufferPool.glVideoSurfaceMap.find((*it)->sourceIdx);
++ if (it2 == m_bufferPool.glVideoSurfaceMap.end())
++ {
++ CLog::Log(LOGDEBUG, "COutput::Flush - gl surface not found");
++ continue;
++ }
++ vdpau_render_state *render = it2->second.sourceVuv;
++ if (render)
++ render->state |= FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ }
++}
++
++bool COutput::HasWork()
++{
++ if (m_config.usePixmaps)
++ {
++ if (!m_bufferPool.processedPics.empty() && FindFreePixmap() >= 0)
++ return true;
++ if (!m_bufferPool.notVisiblePixmaps.empty() && !m_bufferPool.freeRenderPics.empty())
++ return true;
++ return false;
++ }
++ else
++ {
++ if (!m_bufferPool.processedPics.empty() && !m_bufferPool.freeRenderPics.empty())
++ return true;
++ return false;
++ }
++}
++
++CVdpauRenderPicture* COutput::ProcessMixerPicture()
++{
++ CVdpauRenderPicture *retPic = 0;
++
++ if (m_config.usePixmaps)
++ {
++ if (!m_bufferPool.processedPics.empty() && FindFreePixmap() >= 0)
++ {
++ unsigned int i = FindFreePixmap();
++ VdpauBufferPool::Pixmaps *pixmap = &m_bufferPool.pixmaps[i];
++ pixmap->used = true;
++ CVdpauProcessedPicture pic = m_bufferPool.processedPics.front();
++ m_bufferPool.processedPics.pop();
++ pixmap->surface = pic.outputSurface;
++ pixmap->DVDPic = pic.DVDPic;
++ pixmap->id = i;
++ m_bufferPool.notVisiblePixmaps.push_back(pixmap);
++ VdpStatus vdp_st;
++ m_config.vdpProcs.vdp_presentation_queue_display(pixmap->vdp_flip_queue,
++ pixmap->surface,0,0,0);
++ }
++ if (!m_bufferPool.notVisiblePixmaps.empty() && !m_bufferPool.freeRenderPics.empty())
++ {
++ VdpStatus vdp_st;
++ VdpTime time;
++ VdpPresentationQueueStatus status;
++ VdpauBufferPool::Pixmaps *pixmap = m_bufferPool.notVisiblePixmaps.front();
++ vdp_st = m_config.vdpProcs.vdp_presentation_queue_query_surface_status(
++ pixmap->vdp_flip_queue, pixmap->surface, &status, &time);
++
++ if (vdp_st == VDP_STATUS_OK && status == VDP_PRESENTATION_QUEUE_STATUS_VISIBLE)
++ {
++ retPic = m_bufferPool.freeRenderPics.front();
++ m_bufferPool.freeRenderPics.pop_front();
++ m_bufferPool.usedRenderPics.push_back(retPic);
++ retPic->sourceIdx = pixmap->id;
++ retPic->DVDPic = pixmap->DVDPic;
++ retPic->valid = true;
++ retPic->texture[0] = pixmap->texture;
++ retPic->crop = CRect(0,0,0,0);
++ m_bufferPool.notVisiblePixmaps.pop_front();
++ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER, &pixmap->surface, sizeof(pixmap->surface));
++ }
++ }
++ } // pixmap
++ else if (!m_bufferPool.processedPics.empty() && !m_bufferPool.freeRenderPics.empty())
++ {
++ retPic = m_bufferPool.freeRenderPics.front();
++ m_bufferPool.freeRenderPics.pop_front();
++ m_bufferPool.usedRenderPics.push_back(retPic);
++ CVdpauProcessedPicture procPic = m_bufferPool.processedPics.front();
++ m_bufferPool.processedPics.pop();
++
++ retPic->DVDPic = procPic.DVDPic;
++ retPic->valid = true;
++ if (retPic->DVDPic.format == DVDVideoPicture::FMT_VDPAU)
++ {
++ m_config.useInteropYuv = false;
++ m_bufferPool.numOutputSurfaces = NUM_RENDER_PICS;
++ EnsureBufferPool();
++ GLMapSurfaces();
++ retPic->sourceIdx = procPic.outputSurface;
++ retPic->texture[0] = m_bufferPool.glOutputSurfaceMap[procPic.outputSurface].texture[0];
++ retPic->crop = CRect(0,0,0,0);
++ }
++ else
++ {
++ m_config.useInteropYuv = true;
++ GLMapSurfaces();
++ retPic->sourceIdx = procPic.render->surface;
++ for (unsigned int i=0; i<4; ++i)
++ retPic->texture[i] = m_bufferPool.glVideoSurfaceMap[procPic.render->surface].texture[i];
++ retPic->texWidth = m_config.surfaceWidth;
++ retPic->texHeight = m_config.surfaceHeight;
++ retPic->crop.x1 = 0;
++ retPic->crop.y1 = 0;
++ retPic->crop.x2 = m_config.surfaceWidth - m_config.vidWidth;
++ retPic->crop.y2 = m_config.surfaceHeight - m_config.vidHeight;
++ }
++ }
++ return retPic;
++}
++
++void COutput::ProcessReturnPicture(CVdpauRenderPicture *pic)
++{
++ std::deque::iterator it;
++ it = std::find(m_bufferPool.usedRenderPics.begin(), m_bufferPool.usedRenderPics.end(), pic);
++ if (it == m_bufferPool.usedRenderPics.end())
++ {
++ CLog::Log(LOGWARNING, "COutput::ProcessReturnPicture - pic not found");
++ return;
++ }
++ m_bufferPool.usedRenderPics.erase(it);
++ m_bufferPool.freeRenderPics.push_back(pic);
++ if (!pic->valid)
++ {
++ CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__);
++ return;
++ }
++
++ if (m_config.usePixmaps)
++ {
++ m_bufferPool.pixmaps[pic->sourceIdx].used = false;
++ return;
++ }
++ else if (pic->DVDPic.format == DVDVideoPicture::FMT_VDPAU_420)
++ {
++ std::map::iterator it;
++ it = m_bufferPool.glVideoSurfaceMap.find(pic->sourceIdx);
++ if (it == m_bufferPool.glVideoSurfaceMap.end())
++ {
++ CLog::Log(LOGDEBUG, "COutput::ProcessReturnPicture - gl surface not found");
++ return;
++ }
++ vdpau_render_state *render = it->second.sourceVuv;
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ render->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
++ }
++ else if (pic->DVDPic.format == DVDVideoPicture::FMT_VDPAU)
++ {
++ std::map::iterator it;
++ it = m_bufferPool.glOutputSurfaceMap.find(pic->sourceIdx);
++ if (it == m_bufferPool.glOutputSurfaceMap.end())
++ {
++ CLog::Log(LOGDEBUG, "COutput::ProcessReturnPicture - gl surface not found");
++ return;
++ }
++ VdpOutputSurface outSurf = it->second.sourceRgb;
++ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER, &outSurf, sizeof(outSurf));
++ }
++}
++
++int COutput::FindFreePixmap()
++{
++ // find free pixmap
++ unsigned int i;
++ for (i = 0; i < m_bufferPool.pixmaps.size(); ++i)
++ {
++ if (!m_bufferPool.pixmaps[i].used)
++ break;
++ }
++ if (i == m_bufferPool.pixmaps.size())
++ return -1;
++ else
++ return i;
++}
++
++bool COutput::EnsureBufferPool()
++{
++ VdpStatus vdp_st;
++
++ // Creation of outputSurfaces
++ VdpOutputSurface outputSurface;
++ for (int i = m_bufferPool.outputSurfaces.size(); i < m_bufferPool.numOutputSurfaces; i++)
++ {
++ vdp_st = m_config.vdpProcs.vdp_output_surface_create(m_config.vdpDevice,
++ VDP_RGBA_FORMAT_B8G8R8A8,
++ m_config.outWidth,
++ m_config.outHeight,
++ &outputSurface);
++ if (CheckStatus(vdp_st, __LINE__))
++ return false;
++ m_bufferPool.outputSurfaces.push_back(outputSurface);
++
++ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER,
++ &outputSurface,
++ sizeof(VdpOutputSurface));
++ CLog::Log(LOGNOTICE, "VDPAU::COutput::InitBufferPool - Output Surface created");
++ }
++
++
++ if (m_config.usePixmaps && m_bufferPool.pixmaps.empty())
++ {
++ // create pixmpas
++ VdpauBufferPool::Pixmaps pixmap;
++ int numPixmaps = NUM_RENDER_PICS;
++ for (unsigned int i = 0; i < numPixmaps; i++)
++ {
++ pixmap.pixmap = None;
++ pixmap.glPixmap = None;
++ pixmap.vdp_flip_queue = VDP_INVALID_HANDLE;
++ pixmap.vdp_flip_target = VDP_INVALID_HANDLE;
++ MakePixmap(pixmap);
++ glXMakeCurrent(m_Display, None, NULL);
++ vdp_st = m_config.vdpProcs.vdp_presentation_queue_target_create_x11(m_config.vdpDevice,
++ pixmap.pixmap, //x_window,
++ &pixmap.vdp_flip_target);
++
++ CheckStatus(vdp_st, __LINE__);
++
++ vdp_st = m_config.vdpProcs.vdp_presentation_queue_create(m_config.vdpDevice,
++ pixmap.vdp_flip_target,
++ &pixmap.vdp_flip_queue);
++ CheckStatus(vdp_st, __LINE__);
++ glXMakeCurrent(m_Display, m_glPixmap, m_glContext);
++
++ pixmap.id = i;
++ pixmap.used = false;
++ m_bufferPool.pixmaps.push_back(pixmap);
++ }
++ GLBindPixmaps();
++ }
++
++ return true;
++}
++
++void COutput::ReleaseBufferPool()
++{
++ VdpStatus vdp_st;
++
++ CSingleLock lock(m_bufferPool.renderPicSec);
++
++ if (m_config.usePixmaps)
++ {
++ for (unsigned int i = 0; i < m_bufferPool.pixmaps.size(); ++i)
++ {
++ if (m_bufferPool.pixmaps[i].vdp_flip_queue != VDP_INVALID_HANDLE)
++ {
++ vdp_st = m_config.vdpProcs.vdp_presentation_queue_destroy(m_bufferPool.pixmaps[i].vdp_flip_queue);
++ CheckStatus(vdp_st, __LINE__);
++ }
++ if (m_bufferPool.pixmaps[i].vdp_flip_target != VDP_INVALID_HANDLE)
++ {
++ vdp_st = m_config.vdpProcs.vdp_presentation_queue_target_destroy(m_bufferPool.pixmaps[i].vdp_flip_target);
++ CheckStatus(vdp_st, __LINE__);
++ }
++ if (m_bufferPool.pixmaps[i].glPixmap)
++ {
++ glXDestroyPixmap(m_Display, m_bufferPool.pixmaps[i].glPixmap);
++ }
++ if (m_bufferPool.pixmaps[i].pixmap)
++ {
++ XFreePixmap(m_Display, m_bufferPool.pixmaps[i].pixmap);
++ }
++ }
++ m_bufferPool.pixmaps.clear();
++ }
++
++ // release all output surfaces
++ for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i)
++ {
++ if (m_bufferPool.outputSurfaces[i] == VDP_INVALID_HANDLE)
++ continue;
++ vdp_st = m_config.vdpProcs.vdp_output_surface_destroy(m_bufferPool.outputSurfaces[i]);
++ CheckStatus(vdp_st, __LINE__);
++ }
++ m_bufferPool.outputSurfaces.clear();
++
++ // invalidate all used render pictures
++ for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
++ {
++ m_bufferPool.usedRenderPics[i]->valid = false;
++ }
++}
++
++void COutput::InitMixer()
++{
++ for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i)
++ {
++ m_mixer.m_dataPort.SendOutMessage(CMixerDataProtocol::BUFFER,
++ &m_bufferPool.outputSurfaces[i],
++ sizeof(VdpOutputSurface));
++ }
++}
++
++bool COutput::MakePixmap(VdpauBufferPool::Pixmaps &pixmap)
++{
++ CLog::Log(LOGNOTICE,"Creating %ix%i pixmap", m_config.outWidth, m_config.outHeight);
++
++ // Get our window attribs.
++ XWindowAttributes wndattribs;
++ XGetWindowAttributes(m_Display, DefaultRootWindow(m_Display), &wndattribs);
++
++ pixmap.pixmap = XCreatePixmap(m_Display,
++ DefaultRootWindow(m_Display),
++ m_config.outWidth,
++ m_config.outHeight,
++ wndattribs.depth);
++ if (!pixmap.pixmap)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COUtput::MakePixmap - GLX Error: MakePixmap: Unable to create XPixmap");
++ return false;
++ }
++
++// XGCValues values = {};
++// GC xgc;
++// values.foreground = BlackPixel (m_Display, DefaultScreen (m_Display));
++// xgc = XCreateGC(m_Display, pixmap.pixmap, GCForeground, &values);
++// XFillRectangle(m_Display, pixmap.pixmap, xgc, 0, 0, m_config.outWidth, m_config.outHeight);
++// XFreeGC(m_Display, xgc);
++
++ if(!MakePixmapGL(pixmap))
++ return false;
++
++ return true;
++}
++
++bool COutput::MakePixmapGL(VdpauBufferPool::Pixmaps &pixmap)
++{
++ int num=0;
++ int fbConfigIndex = 0;
++
++ int doubleVisAttributes[] = {
++ GLX_RENDER_TYPE, GLX_RGBA_BIT,
++ GLX_RED_SIZE, 8,
++ GLX_GREEN_SIZE, 8,
++ GLX_BLUE_SIZE, 8,
++ GLX_ALPHA_SIZE, 8,
++ GLX_DEPTH_SIZE, 8,
++ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
++ GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
++ GLX_DOUBLEBUFFER, False,
++ GLX_Y_INVERTED_EXT, True,
++ GLX_X_RENDERABLE, True,
++ None
++ };
++
++ int pixmapAttribs[] = {
++ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
++ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
++ None
++ };
++
++ GLXFBConfig *fbConfigs;
++ fbConfigs = glXChooseFBConfig(m_Display, DefaultScreen(m_Display), doubleVisAttributes, &num);
++ if (fbConfigs==NULL)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput::MakPixmapGL - No compatible framebuffers found");
++ return false;
++ }
++ fbConfigIndex = 0;
++
++ pixmap.glPixmap = glXCreatePixmap(m_Display, fbConfigs[fbConfigIndex], pixmap.pixmap, pixmapAttribs);
++
++ if (!pixmap.glPixmap)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput::MakPixmapGL - Could not create Pixmap");
++ XFree(fbConfigs);
++ return false;
++ }
++ XFree(fbConfigs);
++ return true;
++}
++
++bool COutput::GLInit()
++{
++ glXBindTexImageEXT = NULL;
++ glXReleaseTexImageEXT = NULL;
++#ifdef GL_NV_vdpau_interop
++ glVDPAUInitNV = NULL;
++ glVDPAUFiniNV = NULL;
++ glVDPAURegisterOutputSurfaceNV = NULL;
++ glVDPAURegisterVideoSurfaceNV = NULL;
++ glVDPAUIsSurfaceNV = NULL;
++ glVDPAUUnregisterSurfaceNV = NULL;
++ glVDPAUSurfaceAccessNV = NULL;
++ glVDPAUMapSurfacesNV = NULL;
++ glVDPAUUnmapSurfacesNV = NULL;
++ glVDPAUGetSurfaceivNV = NULL;
++#endif
++
++ m_config.usePixmaps = !g_guiSettings.GetBool("videoplayer.usevdpauinteroprgb");
++
++#ifdef GL_NV_vdpau_interop
++ if (glewIsSupported("GL_NV_vdpau_interop"))
++ {
++ if (!glVDPAUInitNV)
++ glVDPAUInitNV = (PFNGLVDPAUINITNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUInitNV");
++ if (!glVDPAUFiniNV)
++ glVDPAUFiniNV = (PFNGLVDPAUFININVPROC)glXGetProcAddress((GLubyte *) "glVDPAUFiniNV");
++ if (!glVDPAURegisterOutputSurfaceNV)
++ glVDPAURegisterOutputSurfaceNV = (PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAURegisterOutputSurfaceNV");
++ if (!glVDPAURegisterVideoSurfaceNV)
++ glVDPAURegisterVideoSurfaceNV = (PFNGLVDPAUREGISTERVIDEOSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAURegisterVideoSurfaceNV");
++ if (!glVDPAUIsSurfaceNV)
++ glVDPAUIsSurfaceNV = (PFNGLVDPAUISSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAUIsSurfaceNV");
++ if (!glVDPAUUnregisterSurfaceNV)
++ glVDPAUUnregisterSurfaceNV = (PFNGLVDPAUUNREGISTERSURFACENVPROC)glXGetProcAddress((GLubyte *) "glVDPAUUnregisterSurfaceNV");
++ if (!glVDPAUSurfaceAccessNV)
++ glVDPAUSurfaceAccessNV = (PFNGLVDPAUSURFACEACCESSNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUSurfaceAccessNV");
++ if (!glVDPAUMapSurfacesNV)
++ glVDPAUMapSurfacesNV = (PFNGLVDPAUMAPSURFACESNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUMapSurfacesNV");
++ if (!glVDPAUUnmapSurfacesNV)
++ glVDPAUUnmapSurfacesNV = (PFNGLVDPAUUNMAPSURFACESNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUUnmapSurfacesNV");
++ if (!glVDPAUGetSurfaceivNV)
++ glVDPAUGetSurfaceivNV = (PFNGLVDPAUGETSURFACEIVNVPROC)glXGetProcAddress((GLubyte *) "glVDPAUGetSurfaceivNV");
++
++ CLog::Log(LOGNOTICE, "VDPAU::COutput GL interop supported");
++ }
++ else
++#endif
++ {
++ m_config.usePixmaps = true;
++ g_guiSettings.SetBool("videoplayer.usevdpauinteroprgb",false);
++ g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false);
++ }
++ if (!glXBindTexImageEXT)
++ glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
++ if (!glXReleaseTexImageEXT)
++ glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((GLubyte *) "glXReleaseTexImageEXT");
++
++#ifdef GL_NV_vdpau_interop
++ if (!m_config.usePixmaps)
++ {
++ while (glGetError() != GL_NO_ERROR);
++ glVDPAUInitNV(reinterpret_cast(m_config.vdpDevice), reinterpret_cast(m_config.vdpProcs.vdp_get_proc_address));
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput - GLInitInterop glVDPAUInitNV failed");
++ m_vdpError = true;
++ return false;
++ }
++ CLog::Log(LOGNOTICE, "VDPAU::COutput: vdpau gl interop initialized");
++ }
++#endif
++ return true;
++}
++
++void COutput::GLMapSurfaces()
++{
++#ifdef GL_NV_vdpau_interop
++ if (m_config.usePixmaps)
++ return;
++
++ if (m_config.useInteropYuv)
++ {
++ VdpauBufferPool::GLVideoSurface glSurface;
++ if (m_config.videoSurfaces->size() != m_bufferPool.glVideoSurfaceMap.size())
++ {
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ for (int i = 0; i < m_config.videoSurfaces->size(); i++)
++ {
++ if ((*m_config.videoSurfaces)[i]->surface == VDP_INVALID_HANDLE)
++ continue;
++
++ if (m_bufferPool.glVideoSurfaceMap.find((*m_config.videoSurfaces)[i]->surface) == m_bufferPool.glVideoSurfaceMap.end())
++ {
++ glSurface.sourceVuv = (*m_config.videoSurfaces)[i];
++ while (glGetError() != GL_NO_ERROR) ;
++ glGenTextures(4, glSurface.texture);
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error creating texture");
++ m_vdpError = true;
++ }
++ glSurface.glVdpauSurface = glVDPAURegisterVideoSurfaceNV(reinterpret_cast((*m_config.videoSurfaces)[i]->surface),
++ GL_TEXTURE_2D, 4, glSurface.texture);
++
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error register video surface");
++ m_vdpError = true;
++ }
++ glVDPAUSurfaceAccessNV(glSurface.glVdpauSurface, GL_READ_ONLY);
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error setting access");
++ m_vdpError = true;
++ }
++ glVDPAUMapSurfacesNV(1, &glSurface.glVdpauSurface);
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error mapping surface");
++ m_vdpError = true;
++ }
++ m_bufferPool.glVideoSurfaceMap[(*m_config.videoSurfaces)[i]->surface] = glSurface;
++ if (m_vdpError)
++ return;
++ CLog::Log(LOGNOTICE, "VDPAU::COutput registered surface");
++ }
++ }
++ }
++ }
++ else
++ {
++ if (m_bufferPool.glOutputSurfaceMap.size() != m_bufferPool.numOutputSurfaces)
++ {
++ VdpauBufferPool::GLVideoSurface glSurface;
++ for (int i=m_bufferPool.glOutputSurfaceMap.size(); i(m_bufferPool.outputSurfaces[i]),
++ GL_TEXTURE_2D, 1, glSurface.texture);
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error register output surface");
++ m_vdpError = true;
++ }
++ glVDPAUSurfaceAccessNV(glSurface.glVdpauSurface, GL_READ_ONLY);
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error setting access");
++ m_vdpError = true;
++ }
++ glVDPAUMapSurfacesNV(1, &glSurface.glVdpauSurface);
++ if (glGetError() != GL_NO_ERROR)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput error mapping surface");
++ m_vdpError = true;
++ }
++ m_bufferPool.glOutputSurfaceMap[m_bufferPool.outputSurfaces[i]] = glSurface;
++ if (m_vdpError)
++ return;
++ }
++ CLog::Log(LOGNOTICE, "VDPAU::COutput registered output surfaces");
++ }
++ }
++#endif
++}
++
++void COutput::GLUnmapSurfaces()
++{
++#ifdef GL_NV_vdpau_interop
++ if (m_config.usePixmaps)
++ return;
++
++ { CSingleLock lock(*m_config.videoSurfaceSec);
++ std::map::iterator it;
++ for (it = m_bufferPool.glVideoSurfaceMap.begin(); it != m_bufferPool.glVideoSurfaceMap.end(); ++it)
++ {
++ glVDPAUUnregisterSurfaceNV(it->second.glVdpauSurface);
++ glDeleteTextures(4, it->second.texture);
++ }
++ m_bufferPool.glVideoSurfaceMap.clear();
++ }
++
++ std::map::iterator it;
++ for (it = m_bufferPool.glOutputSurfaceMap.begin(); it != m_bufferPool.glOutputSurfaceMap.end(); ++it)
++ {
++ glVDPAUUnregisterSurfaceNV(it->second.glVdpauSurface);
++ glDeleteTextures(1, it->second.texture);
++ }
++ m_bufferPool.glOutputSurfaceMap.clear();
++
++ glVDPAUFiniNV();
++
++ CLog::Log(LOGNOTICE, "VDPAU::COutput: vdpau gl interop finished");
++
++#endif
++}
++
++void COutput::GLBindPixmaps()
++{
++ if (!m_config.usePixmaps)
++ return;
++
++ for (unsigned int i = 0; i < m_bufferPool.pixmaps.size(); i++)
++ {
++ // create texture
++ glGenTextures(1, &m_bufferPool.pixmaps[i].texture);
++
++ //bind texture
++ glBindTexture(GL_TEXTURE_2D, m_bufferPool.pixmaps[i].texture);
++
++ // bind pixmap
++ glXBindTexImageEXT(m_Display, m_bufferPool.pixmaps[i].glPixmap, GLX_FRONT_LEFT_EXT, NULL);
++
++ glBindTexture(GL_TEXTURE_2D, 0);
++ }
++
++ CLog::Log(LOGNOTICE, "VDPAU::COutput: bound pixmaps");
++}
++
++void COutput::GLUnbindPixmaps()
++{
++ if (!m_config.usePixmaps)
++ return;
++
++ for (unsigned int i = 0; i < m_bufferPool.pixmaps.size(); i++)
++ {
++ // create texture
++ if (!glIsTexture(m_bufferPool.pixmaps[i].texture))
++ continue;
++
++ //bind texture
++ glBindTexture(GL_TEXTURE_2D, m_bufferPool.pixmaps[i].texture);
++
++ // release pixmap
++ glXReleaseTexImageEXT(m_Display, m_bufferPool.pixmaps[i].glPixmap, GLX_FRONT_LEFT_EXT);
++
++ glBindTexture(GL_TEXTURE_2D, 0);
++
++ glDeleteTextures(1, &m_bufferPool.pixmaps[i].texture);
++ }
++ CLog::Log(LOGNOTICE, "VDPAU::COutput: unbound pixmaps");
++}
++
++bool COutput::CheckStatus(VdpStatus vdp_st, int line)
++{
++ if (vdp_st != VDP_STATUS_OK)
++ {
++ CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", m_config.vdpProcs.vdp_get_error_string(vdp_st), vdp_st, __FILE__, line);
++ m_vdpError = true;
++ return true;
++ }
++ return false;
++}
++
++bool COutput::CreateGlxContext()
++{
++ GLXContext glContext;
++ Window window;
++
++ m_Display = g_Windowing.GetDisplay();
++ glContext = g_Windowing.GetGlxContext();
++ m_Window = g_Windowing.GetWmWindow();
++
++ // Get our window attribs.
++ XWindowAttributes wndattribs;
++ XGetWindowAttributes(m_Display, m_Window, &wndattribs);
++
++ // Get visual Info
++ XVisualInfo visInfo;
++ visInfo.visualid = wndattribs.visual->visualid;
++ int nvisuals = 0;
++ XVisualInfo* visuals = XGetVisualInfo(m_Display, VisualIDMask, &visInfo, &nvisuals);
++ if (nvisuals != 1)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput::CreateGlxContext - could not find visual");
++ return false;
++ }
++ visInfo = visuals[0];
++ XFree(visuals);
++
++ m_pixmap = XCreatePixmap(m_Display,
++ DefaultRootWindow(m_Display),
++ 192,
++ 108,
++ visInfo.depth);
++ if (!m_pixmap)
++ {
++ CLog::Log(LOGERROR, "VDPAU::COutput::CreateGlxContext - Unable to create XPixmap");
++ return false;
++ }
++
++ // create gl pixmap
++ m_glPixmap = glXCreateGLXPixmap(m_Display, &visInfo, m_pixmap);
++
++ if (!m_glPixmap)
++ {
++ CLog::Log(LOGINFO, "VDPAU::COutput::CreateGlxContext - Could not create glPixmap");
++ return false;
++ }
++
++ m_glContext = glXCreateContext(m_Display, &visInfo, glContext, True);
++
++ if (!glXMakeCurrent(m_Display, m_glPixmap, m_glContext))
++ {
++ CLog::Log(LOGINFO, "VDPAU::COutput::CreateGlxContext - Could not make Pixmap current");
++ return false;
++ }
++
++ CLog::Log(LOGNOTICE, "VDPAU::COutput::CreateGlxContext - created context");
++ return true;
++}
++
++bool COutput::DestroyGlxContext()
++{
++ if (m_glContext)
++ {
++ glXMakeCurrent(m_Display, None, NULL);
++ glXDestroyContext(m_Display, m_glContext);
++ }
++ m_glContext = 0;
++
++ if (m_glPixmap)
++ glXDestroyPixmap(m_Display, m_glPixmap);
++ m_glPixmap = 0;
++
++ if (m_pixmap)
++ XFreePixmap(m_Display, m_pixmap);
++ m_pixmap = 0;
++
++ return true;
++}
++
++
+ #endif
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h 2012-05-13 22:08:47.038194709 +0200
+@@ -1,4 +1,3 @@
+-
+ #pragma once
+ /*
+ * Copyright (C) 2005-2009 Team XBMC
+@@ -21,6 +20,24 @@
+ *
+ */
+
++/**
++ * design goals:
++ * - improve performance
++ * max out hw resources: e.g. make 1080p60 play on ION2
++ * allow advanced de-interlacing on ION
++ *
++ * - add vdpau/opengl interop
++ *
++ * - remove tight dependency to render thread
++ * prior design needed to hijack render thread in order to do
++ * gl interop functions. In particular this was a problem for
++ * init and clear down. Introduction of GL_NV_vdpau_interop
++ * increased the need to be independent from render thread
++ *
++ * - move to an actor based design in order to reduce the number
++ * of locks needed.
++ */
++
+ #include "DllAvUtil.h"
+ #include "DVDVideoCodec.h"
+ #include "DVDVideoCodecFFmpeg.h"
+@@ -37,118 +54,31 @@
+ #include "settings/VideoSettings.h"
+ #include "guilib/DispResource.h"
+ #include "threads/Event.h"
+-namespace Surface { class CSurface; }
+-
+-#define NUM_OUTPUT_SURFACES 4
+-#define NUM_VIDEO_SURFACES_MPEG2 10 // (1 frame being decoded, 2 reference)
+-#define NUM_VIDEO_SURFACES_H264 32 // (1 frame being decoded, up to 16 references)
+-#define NUM_VIDEO_SURFACES_VC1 10 // (same as MPEG-2)
+-#define NUM_OUTPUT_SURFACES_FOR_FULLHD 2
+-#define FULLHD_WIDTH 1920
+-
+-class CVDPAU
+- : public CDVDVideoCodecFFmpeg::IHardwareDecoder
+- , public IDispResource
+-{
+-public:
+-
+- struct pictureAge
+- {
+- int b_age;
+- int ip_age[2];
+- };
+-
+- struct Desc
+- {
+- const char *name;
+- uint32_t id;
+- uint32_t aux; /* optional extra parameter... */
+- };
++#include "threads/Thread.h"
++#include "utils/ActorProtocol.h"
+
+- CVDPAU();
+- virtual ~CVDPAU();
+-
+- virtual bool Open (AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces = 0);
+- virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
+- virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
+- virtual void Reset();
+- virtual void Close();
+-
+- virtual int Check(AVCodecContext* avctx);
+-
+- virtual const std::string Name() { return "vdpau"; }
+-
+- bool MakePixmap(int width, int height);
+- bool MakePixmapGL();
+-
+- void ReleasePixmap();
+- void BindPixmap();
+-
+- PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
+- PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
+- GLXPixmap m_glPixmap;
+- Pixmap m_Pixmap;
++using namespace Actor;
+
+- static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
+- static void FFDrawSlice(struct AVCodecContext *s,
+- const AVFrame *src, int offset[4],
+- int y, int type, int height);
+- static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
+
+- void Present();
+- bool ConfigVDPAU(AVCodecContext *avctx, int ref_frames);
+- void SpewHardwareAvailable();
+- void InitCSCMatrix(int Height);
+- bool CheckStatus(VdpStatus vdp_st, int line);
+- bool IsSurfaceValid(vdpau_render_state *render);
+-
+- void CheckFeatures();
+- void SetColor();
+- void SetNoiseReduction();
+- void SetSharpness();
+- void SetDeinterlacing();
+- void SetHWUpscaling();
++#define FULLHD_WIDTH 1920
++#define MAX_PIC_Q_LENGTH 20 //for non-interop_yuv this controls the max length of the decoded pic to render completion Q
+
+- pictureAge picAge;
+- vdpau_render_state *past[2], *current, *future;
+- int tmpDeintMode, tmpDeintGUI, tmpDeint;
+- float tmpNoiseReduction, tmpSharpness;
+- float tmpBrightness, tmpContrast;
+- int OutWidth, OutHeight;
+- bool upScale;
+- std::queue m_DVDVideoPics;
+-
+- static inline void ClearUsedForRender(vdpau_render_state **st)
+- {
+- if (*st) {
+- (*st)->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER;
+- *st = NULL;
+- }
+- }
++namespace VDPAU
++{
+
+- VdpProcamp m_Procamp;
+- VdpCSCMatrix m_CSCMatrix;
+- VdpDevice HasDevice() { return vdp_device != VDP_INVALID_HANDLE; };
+- VdpChromaType vdp_chroma_type;
++/**
++ * VDPAU interface to driver
++ */
+
++struct VDPAU_procs
++{
++ VdpGetProcAddress * vdp_get_proc_address;
++ VdpDeviceDestroy * vdp_device_destroy;
+
+- // protected:
+- void InitVDPAUProcs();
+- void FiniVDPAUProcs();
+- void FiniVDPAUOutput();
+- bool ConfigOutputMethod(AVCodecContext *avctx, AVFrame *pFrame);
+- bool FiniOutputMethod();
+-
+- VdpDevice vdp_device;
+- VdpGetProcAddress * vdp_get_proc_address;
+- VdpPresentationQueueTarget vdp_flip_target;
+- VdpPresentationQueue vdp_flip_queue;
+- VdpDeviceDestroy * vdp_device_destroy;
+-
+- VdpVideoSurfaceCreate * vdp_video_surface_create;
+- VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
+- VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
+- VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
++ VdpVideoSurfaceCreate * vdp_video_surface_create;
++ VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
++ VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
++ VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
+
+ VdpOutputSurfacePutBitsYCbCr * vdp_output_surface_put_bits_y_cb_cr;
+ VdpOutputSurfacePutBitsNative * vdp_output_surface_put_bits_native;
+@@ -158,15 +88,15 @@
+ VdpOutputSurfaceRenderOutputSurface * vdp_output_surface_render_output_surface;
+ VdpOutputSurfacePutBitsIndexed * vdp_output_surface_put_bits_indexed;
+
+- VdpVideoMixerCreate * vdp_video_mixer_create;
+- VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
+- VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
+- VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
+- VdpVideoMixerDestroy * vdp_video_mixer_destroy;
+- VdpVideoMixerRender * vdp_video_mixer_render;
+- VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
++ VdpVideoMixerCreate * vdp_video_mixer_create;
++ VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
++ VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
++ VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
++ VdpVideoMixerDestroy * vdp_video_mixer_destroy;
++ VdpVideoMixerRender * vdp_video_mixer_render;
++ VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
+
+- VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
++ VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
+
+ VdpPresentationQueueTargetDestroy * vdp_presentation_queue_target_destroy;
+ VdpPresentationQueueCreate * vdp_presentation_queue_create;
+@@ -179,64 +109,467 @@
+
+ VdpGetErrorString * vdp_get_error_string;
+
+- VdpDecoderCreate * vdp_decoder_create;
+- VdpDecoderDestroy * vdp_decoder_destroy;
+- VdpDecoderRender * vdp_decoder_render;
+- VdpDecoderQueryCapabilities * vdp_decoder_query_caps;
++ VdpDecoderCreate * vdp_decoder_create;
++ VdpDecoderDestroy * vdp_decoder_destroy;
++ VdpDecoderRender * vdp_decoder_render;
++ VdpDecoderQueryCapabilities * vdp_decoder_query_caps;
+
+ VdpPreemptionCallbackRegister * vdp_preemption_callback_register;
+
+- VdpOutputSurface outputSurfaces[NUM_OUTPUT_SURFACES];
+- VdpOutputSurface outputSurface;
+- VdpOutputSurface presentSurface;
+-
+- VdpDecoder decoder;
+- VdpVideoMixer videoMixer;
+- VdpRect outRect;
+- VdpRect outRectVid;
++};
+
+- static void* dl_handle;
+- VdpStatus (*dl_vdp_device_create_x11)(Display* display, int screen, VdpDevice* device, VdpGetProcAddress **get_proc_address);
+- VdpStatus (*dl_vdp_get_proc_address)(VdpDevice device, VdpFuncId function_id, void** function_pointer);
+- VdpStatus (*dl_vdp_preemption_callback_register)(VdpDevice device, VdpPreemptionCallback callback, void* context);
++//-----------------------------------------------------------------------------
++// VDPAU data structs
++//-----------------------------------------------------------------------------
+
+- int surfaceNum;
+- int presentSurfaceNum;
+- int totalAvailableOutputSurfaces;
+- uint32_t vid_width, vid_height;
+- int surface_width, surface_height;
+- uint32_t max_references;
+- Display* m_Display;
+- bool vdpauConfigured;
+- uint32_t *m_BlackBar;
++class CDecoder;
++
++/**
++ * Buffer statistics used to control number of frames in queue
++ */
++
++class CVdpauBufferStats
++{
++public:
++ uint16_t decodedPics;
++ uint16_t processedPics;
++ uint16_t renderPics;
++ uint64_t latency; // time decoder has waited for a frame, ideally there is no latency
++ int playSpeed;
++ bool canSkipDeint;
++ int processCmd;
++
++ void IncDecoded() { CSingleLock l(m_sec); decodedPics++;}
++ void DecDecoded() { CSingleLock l(m_sec); decodedPics--;}
++ void IncProcessed() { CSingleLock l(m_sec); processedPics++;}
++ void DecProcessed() { CSingleLock l(m_sec); processedPics--;}
++ void IncRender() { CSingleLock l(m_sec); renderPics++;}
++ void DecRender() { CSingleLock l(m_sec); renderPics--;}
++ void Reset() { CSingleLock l(m_sec); decodedPics=0; processedPics=0;renderPics=0;latency=0;}
++ void Get(uint16_t &decoded, uint16_t &processed, uint16_t &render) {CSingleLock l(m_sec); decoded = decodedPics, processed=processedPics, render=renderPics;}
++ void SetParams(uint64_t time, int speed) { CSingleLock l(m_sec); latency = time; playSpeed = speed; }
++ void GetParams(uint64_t &lat, int &speed) { CSingleLock l(m_sec); lat = latency; speed = playSpeed; }
++ void SetCmd(int cmd) { CSingleLock l(m_sec); processCmd = cmd; }
++ void GetCmd(int &cmd) { CSingleLock l(m_sec); cmd = processCmd; processCmd = 0; }
++ void SetCanSkipDeint(bool canSkip) { CSingleLock l(m_sec); canSkipDeint = canSkip; }
++ bool CanSkipDeint() { CSingleLock l(m_sec); if (canSkipDeint) return true; else return false;}
++private:
++ CCriticalSection m_sec;
++};
++
++/**
++ * CVdpauConfig holds all configuration parameters needed by vdpau
++ * The structure is sent to the internal classes CMixer and COutput
++ * for init.
++ */
++
++struct CVdpauConfig
++{
++ int surfaceWidth;
++ int surfaceHeight;
++ int vidWidth;
++ int vidHeight;
++ int outWidth;
++ int outHeight;
++ VDPAU_procs vdpProcs;
++ VdpDevice vdpDevice;
++ VdpDecoder vdpDecoder;
++ VdpChromaType vdpChromaType;
++ CVdpauBufferStats *stats;
++ CDecoder *vdpau;
++ int featureCount;
++ int upscale;
++ VdpVideoMixerFeature vdpFeatures[10];
++ std::vector *videoSurfaces;
++ CCriticalSection *videoSurfaceSec;
++ bool usePixmaps;
++ int numRenderBuffers;
++ uint32_t maxReferences;
++ bool useInteropYuv;
++};
++
++/**
++ * Holds a decoded frame
++ * Input to COutput for further processing
++ */
++struct CVdpauDecodedPicture
++{
++ DVDVideoPicture DVDPic;
++ vdpau_render_state *render;
++};
++
++/**
++ * Frame after having been processed by vdpau mixer
++ */
++struct CVdpauProcessedPicture
++{
++ DVDVideoPicture DVDPic;
++ vdpau_render_state *render;
++ VdpOutputSurface outputSurface;
++};
+
++/**
++ * Ready to render textures
++ * Sent from COutput back to CDecoder
++ * Objects are referenced by DVDVideoPicture and are sent
++ * to renderer
++ */
++class CVdpauRenderPicture
++{
++ friend class CDecoder;
++ friend class COutput;
++public:
++ DVDVideoPicture DVDPic;
++ int texWidth, texHeight;
++ CRect crop;
++ GLuint texture[4];
++ uint32_t sourceIdx;
++ bool valid;
++ CDecoder *vdpau;
++ CVdpauRenderPicture* Acquire();
++ long Release();
++private:
++ void ReturnUnused();
++ int refCount;
++ CCriticalSection *renderPicSection;
++};
+
++//-----------------------------------------------------------------------------
++// Mixer
++//-----------------------------------------------------------------------------
++
++class CMixerControlProtocol : public Protocol
++{
++public:
++ CMixerControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
++ enum OutSignal
++ {
++ INIT = 0,
++ FLUSH,
++ TIMEOUT,
++ };
++ enum InSignal
++ {
++ ACC,
++ ERROR,
++ };
++};
++
++class CMixerDataProtocol : public Protocol
++{
++public:
++ CMixerDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
++ enum OutSignal
++ {
++ FRAME,
++ BUFFER,
++ };
++ enum InSignal
++ {
++ PICTURE,
++ };
++};
++
++/**
++ * Embeds the vdpau video mixer
++ * Embedded by COutput class, gets decoded frames from COutput, processes
++ * them in mixer ands sends processed frames back to COutput
++ */
++class CMixer : private CThread
++{
++public:
++ CMixer(CEvent *inMsgEvent);
++ virtual ~CMixer();
++ void Start();
++ void Dispose();
++ CMixerControlProtocol m_controlPort;
++ CMixerDataProtocol m_dataPort;
++protected:
++ void OnStartup();
++ void OnExit();
++ void Process();
++ void StateMachine(int signal, Protocol *port, Message *msg);
++ void Init();
++ void Uninit();
++ void Flush();
++ void CreateVdpauMixer();
++ void ProcessPicture();
++ void InitCycle();
++ void FiniCycle();
++ void CheckFeatures();
++ void SetPostProcFeatures(bool postProcEnabled);
++ void PostProcOff();
++ void InitCSCMatrix(int Width);
++ bool GenerateStudioCSCMatrix(VdpColorStandard colorStandard, VdpCSCMatrix &studioCSCMatrix);
++ void SetColor();
++ void SetNoiseReduction();
++ void SetSharpness();
++ void SetDeintSkipChroma();
++ void SetDeinterlacing();
++ void SetHWUpscaling();
++ void DisableHQScaling();
++ EINTERLACEMETHOD GetDeinterlacingMethod(bool log = false);
++ bool CheckStatus(VdpStatus vdp_st, int line);
++ CEvent m_outMsgEvent;
++ CEvent *m_inMsgEvent;
++ int m_state;
++ bool m_bStateMachineSelfTrigger;
++
++ // extended state variables for state machine
++ int m_extTimeout;
++ bool m_vdpError;
++ CVdpauConfig m_config;
++ VdpVideoMixer m_videoMixer;
++ VdpProcamp m_Procamp;
++ VdpCSCMatrix m_CSCMatrix;
++ bool m_PostProc;
++ float m_Brightness;
++ float m_Contrast;
++ float m_NoiseReduction;
++ float m_Sharpness;
++ int m_DeintMode;
++ int m_Deint;
++ int m_Upscale;
++ uint32_t *m_BlackBar;
+ VdpVideoMixerPictureStructure m_mixerfield;
+- int m_mixerstep;
++ int m_mixerstep;
++ int m_mixersteps;
++ CVdpauProcessedPicture m_processPicture;
++ std::queue m_outputSurfaces;
++ std::queue m_decodedPics;
++ std::deque m_mixerInput;
++};
++
++//-----------------------------------------------------------------------------
++// Output
++//-----------------------------------------------------------------------------
++
++/**
++ * Buffer pool holds allocated vdpau and gl resources
++ * Embedded in COutput
++ */
++struct VdpauBufferPool
++{
++ struct Pixmaps
++ {
++ unsigned short id;
++ bool used;
++ DVDVideoPicture DVDPic;
++ GLuint texture;
++ Pixmap pixmap;
++ GLXPixmap glPixmap;
++ VdpPresentationQueueTarget vdp_flip_target;
++ VdpPresentationQueue vdp_flip_queue;
++ VdpOutputSurface surface;
++ };
++ struct GLVideoSurface
++ {
++ GLuint texture[4];
++#ifdef GL_NV_vdpau_interop
++ GLvdpauSurfaceNV glVdpauSurface;
++#endif
++ vdpau_render_state *sourceVuv;
++ VdpOutputSurface sourceRgb;
++ };
++ unsigned short numOutputSurfaces;
++ std::vector pixmaps;
++ std::vector outputSurfaces;
++ std::deque notVisiblePixmaps;
++ std::vector allRenderPics;
++ std::map glVideoSurfaceMap;
++ std::map glOutputSurfaceMap;
++ std::queue processedPics;
++ std::deque usedRenderPics;
++ std::deque freeRenderPics;
++ CCriticalSection renderPicSec;
++};
++
++class COutputControlProtocol : public Protocol
++{
++public:
++ COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
++ enum OutSignal
++ {
++ INIT,
++ FLUSH,
++ PRECLEANUP,
++ TIMEOUT,
++ };
++ enum InSignal
++ {
++ ACC,
++ ERROR,
++ STATS,
++ };
++};
++
++class COutputDataProtocol : public Protocol
++{
++public:
++ COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
++ enum OutSignal
++ {
++ NEWFRAME = 0,
++ RETURNPIC,
++ };
++ enum InSignal
++ {
++ PICTURE,
++ };
++};
++
++/**
++ * COutput is embedded in CDecoder and embeds CMixer
++ * The class has its own OpenGl context which is shared with render thread
++ * COuput generated ready to render textures and passes them back to
++ * CDecoder
++ */
++class COutput : private CThread
++{
++public:
++ COutput(CEvent *inMsgEvent);
++ virtual ~COutput();
++ void Start();
++ void Dispose();
++ COutputControlProtocol m_controlPort;
++ COutputDataProtocol m_dataPort;
++protected:
++ void OnStartup();
++ void OnExit();
++ void Process();
++ void StateMachine(int signal, Protocol *port, Message *msg);
++ bool HasWork();
++ CVdpauRenderPicture *ProcessMixerPicture();
++ void ProcessReturnPicture(CVdpauRenderPicture *pic);
++ int FindFreePixmap();
++ bool Init();
++ bool Uninit();
++ void Flush();
++ bool CreateGlxContext();
++ bool DestroyGlxContext();
++ bool EnsureBufferPool();
++ void ReleaseBufferPool();
++ void InitMixer();
++ bool GLInit();
++ void GLMapSurfaces();
++ void GLUnmapSurfaces();
++ void GLBindPixmaps();
++ void GLUnbindPixmaps();
++ bool MakePixmap(VdpauBufferPool::Pixmaps &pixmap);
++ bool MakePixmapGL(VdpauBufferPool::Pixmaps &pixmap);
++ bool CheckStatus(VdpStatus vdp_st, int line);
++ CEvent m_outMsgEvent;
++ CEvent *m_inMsgEvent;
++ int m_state;
++ bool m_bStateMachineSelfTrigger;
++
++ // extended state variables for state machine
++ int m_extTimeout;
++ bool m_vdpError;
++ CVdpauConfig m_config;
++ VdpauBufferPool m_bufferPool;
++ CMixer m_mixer;
++ Display *m_Display;
++ Window m_Window;
++ GLXContext m_glContext;
++ GLXWindow m_glWindow;
++ Pixmap m_pixmap;
++ GLXPixmap m_glPixmap;
++
++ // gl functions
++ PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
++ PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
++#ifdef GL_NV_vdpau_interop
++ PFNGLVDPAUINITNVPROC glVDPAUInitNV;
++ PFNGLVDPAUFININVPROC glVDPAUFiniNV;
++ PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC glVDPAURegisterOutputSurfaceNV;
++ PFNGLVDPAUREGISTERVIDEOSURFACENVPROC glVDPAURegisterVideoSurfaceNV;
++ PFNGLVDPAUISSURFACENVPROC glVDPAUIsSurfaceNV;
++ PFNGLVDPAUUNREGISTERSURFACENVPROC glVDPAUUnregisterSurfaceNV;
++ PFNGLVDPAUSURFACEACCESSNVPROC glVDPAUSurfaceAccessNV;
++ PFNGLVDPAUMAPSURFACESNVPROC glVDPAUMapSurfacesNV;
++ PFNGLVDPAUUNMAPSURFACESNVPROC glVDPAUUnmapSurfacesNV;
++ PFNGLVDPAUGETSURFACEIVNVPROC glVDPAUGetSurfaceivNV;
++#endif
++};
++
++//-----------------------------------------------------------------------------
++// VDPAU decoder
++//-----------------------------------------------------------------------------
++
++/**
++ * VDPAU main class
++ */
++class CDecoder
++ : public CDVDVideoCodecFFmpeg::IHardwareDecoder
++ , public IDispResource
++{
++ friend class CVdpauRenderPicture;
++
++public:
++
++ struct PictureAge
++ {
++ int b_age;
++ int ip_age[2];
++ };
++
++ struct Desc
++ {
++ const char *name;
++ uint32_t id;
++ uint32_t aux; /* optional extra parameter... */
++ };
++
++ CDecoder();
++ virtual ~CDecoder();
++
++ virtual bool Open (AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces = 0);
++ virtual int Decode (AVCodecContext* avctx, AVFrame* frame) {return Decode(avctx, frame, false, false);};
++ virtual int Decode (AVCodecContext* avctx, AVFrame* frame, bool bSoftDrain = false, bool bHardDrain = false);
++ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
++ virtual void Reset();
++ virtual void Close();
++ virtual long Release();
++ virtual bool CanSkipDeint();
++ virtual void SetSpeed(int speed);
++
++ virtual int Check(AVCodecContext* avctx);
++ virtual const std::string Name() { return "vdpau"; }
+
+ bool Supports(VdpVideoMixerFeature feature);
+ bool Supports(EINTERLACEMETHOD method);
+ EINTERLACEMETHOD AutoInterlaceMethod();
++ static bool IsVDPAUFormat(PixelFormat fmt);
+
+- VdpVideoMixerFeature m_features[10];
+- int m_feature_count;
++ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
++ static void FFDrawSlice(struct AVCodecContext *s,
++ const AVFrame *src, int offset[4],
++ int y, int type, int height);
++ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
++
++ virtual void OnLostDevice();
++ virtual void OnResetDevice();
++
++protected:
++ void SetWidthHeight(int width, int height);
++ bool ConfigVDPAU(AVCodecContext *avctx, int ref_frames);
++ void SpewHardwareAvailable();
++ bool CheckStatus(VdpStatus vdp_st, int line);
++ bool IsSurfaceValid(vdpau_render_state *render);
++ void InitVDPAUProcs();
++ void FiniVDPAUProcs();
++ void FiniVDPAUOutput();
++ void ReturnRenderPicture(CVdpauRenderPicture *renderPic);
++ long ReleasePicReference();
+
+- static bool IsVDPAUFormat(PixelFormat fmt);
+ static void ReadFormatOf( PixelFormat fmt
+ , VdpDecoderProfile &decoder_profile
+ , VdpChromaType &chroma_type);
+
+- std::vector m_videoSurfaces;
+- DllAvUtil m_dllAvUtil;
+-
+- enum VDPAUOutputMethod
+- {
+- OUTPUT_NONE,
+- OUTPUT_PIXMAP,
+- OUTPUT_GL_INTEROP_RGB,
+- OUTPUT_GL_INTEROP_YUV
+- };
+- VDPAUOutputMethod m_vdpauOutputMethod;
++ VdpStatus (*dl_vdp_device_create_x11)(Display* display, int screen, VdpDevice* device, VdpGetProcAddress **get_proc_address);
++ VdpStatus (*dl_vdp_get_proc_address)(VdpDevice device, VdpFuncId function_id, void** function_pointer);
++ VdpStatus (*dl_vdp_preemption_callback_register)(VdpDevice device, VdpPreemptionCallback callback, void* context);
+
+ // OnLostDevice triggers transition from all states to LOST
+ // internal errors trigger transition from OPEN to RESET
+@@ -247,9 +580,27 @@
+ , VDPAU_LOST
+ , VDPAU_ERROR
+ } m_DisplayState;
+- CSharedSection m_DecoderSection;
+- CSharedSection m_DisplaySection;
++ CCriticalSection m_DecoderSection;
+ CEvent m_DisplayEvent;
+- virtual void OnLostDevice();
+- virtual void OnResetDevice();
++
++ static void* dl_handle;
++ DllAvUtil m_dllAvUtil;
++ Display* m_Display;
++ ThreadIdentifier m_decoderThread;
++ bool m_vdpauConfigured;
++ CVdpauConfig m_vdpauConfig;
++ std::vector m_videoSurfaces;
++ CCriticalSection m_videoSurfaceSec;
++ PictureAge m_picAge;
++
++ COutput m_vdpauOutput;
++ CVdpauBufferStats m_bufferStats;
++ CEvent m_inMsgEvent;
++ CVdpauRenderPicture *m_presentPicture;
++
++ int m_speed;
++ int m_codecControl;
+ };
++
++}
++
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp 2012-05-13 22:08:47.063195207 +0200
+@@ -0,0 +1,2382 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include "system.h"
++#ifdef HAVE_LIBXVBA
++#include
++#include
++#include "XVBA.h"
++#include "windowing/WindowingFactory.h"
++#include "guilib/GraphicContext.h"
++#include "settings/GUISettings.h"
++#include "settings/Settings.h"
++#include "utils/TimeUtils.h"
++#include "cores/dvdplayer/DVDClock.h"
++
++using namespace XVBA;
++
++// XVBA interface
++
++#define XVBA_LIBRARY "libXvBAW.so.1"
++
++typedef Bool (*XVBAQueryExtensionProc) (Display *dpy, int *vers);
++typedef Status (*XVBACreateContextProc) (void *input, void *output);
++typedef Status (*XVBADestroyContextProc) (void *context);
++typedef Bool (*XVBAGetSessionInfoProc) (void *input, void *output);
++typedef Status (*XVBACreateSurfaceProc) (void *input, void *output);
++typedef Status (*XVBACreateGLSharedSurfaceProc)(void *input, void *output);
++typedef Status (*XVBADestroySurfaceProc) (void *surface);
++typedef Status (*XVBACreateDecodeBuffersProc) (void *input, void *output);
++typedef Status (*XVBADestroyDecodeBuffersProc) (void *input);
++typedef Status (*XVBAGetCapDecodeProc) (void *input, void *output);
++typedef Status (*XVBACreateDecodeProc) (void *input, void *output);
++typedef Status (*XVBADestroyDecodeProc) (void *session);
++typedef Status (*XVBAStartDecodePictureProc) (void *input);
++typedef Status (*XVBADecodePictureProc) (void *input);
++typedef Status (*XVBAEndDecodePictureProc) (void *input);
++typedef Status (*XVBASyncSurfaceProc) (void *input, void *output);
++typedef Status (*XVBAGetSurfaceProc) (void *input);
++typedef Status (*XVBATransferSurfaceProc) (void *input);
++
++static struct
++{
++ XVBAQueryExtensionProc QueryExtension;
++ XVBACreateContextProc CreateContext;
++ XVBADestroyContextProc DestroyContext;
++ XVBAGetSessionInfoProc GetSessionInfo;
++ XVBACreateSurfaceProc CreateSurface;
++ XVBACreateGLSharedSurfaceProc CreateGLSharedSurface;
++ XVBADestroySurfaceProc DestroySurface;
++ XVBACreateDecodeBuffersProc CreateDecodeBuffers;
++ XVBADestroyDecodeBuffersProc DestroyDecodeBuffers;
++ XVBAGetCapDecodeProc GetCapDecode;
++ XVBACreateDecodeProc CreateDecode;
++ XVBADestroyDecodeProc DestroyDecode;
++ XVBAStartDecodePictureProc StartDecodePicture;
++ XVBADecodePictureProc DecodePicture;
++ XVBAEndDecodePictureProc EndDecodePicture;
++ XVBASyncSurfaceProc SyncSurface;
++ XVBAGetSurfaceProc GetSurface;
++ XVBATransferSurfaceProc TransferSurface;
++}g_XVBA_vtable;
++
++//-----------------------------------------------------------------------------
++//-----------------------------------------------------------------------------
++
++CXVBAContext *CXVBAContext::m_context = 0;
++CCriticalSection CXVBAContext::m_section;
++Display *CXVBAContext::m_display = 0;
++void *CXVBAContext::m_dlHandle = 0;
++
++CXVBAContext::CXVBAContext()
++{
++ m_context = 0;
++// m_dlHandle = 0;
++ m_xvbaContext = 0;
++ m_refCount = 0;
++}
++
++void CXVBAContext::Release()
++{
++ CSingleLock lock(m_section);
++
++ m_refCount--;
++ if (m_refCount <= 0)
++ {
++ Close();
++ delete this;
++ m_context = 0;
++ }
++}
++
++void CXVBAContext::Close()
++{
++ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder context");
++
++ DestroyContext();
++// if (m_dlHandle)
++// {
++// dlclose(m_dlHandle);
++// m_dlHandle = 0;
++// }
++}
++
++bool CXVBAContext::EnsureContext(CXVBAContext **ctx)
++{
++ CSingleLock lock(m_section);
++
++ if (m_context)
++ {
++ m_context->m_refCount++;
++ *ctx = m_context;
++ return true;
++ }
++
++ m_context = new CXVBAContext();
++ *ctx = m_context;
++ {
++ CSingleLock gLock(g_graphicsContext);
++ if (!m_context->LoadSymbols() || !m_context->CreateContext())
++ {
++ delete m_context;
++ m_context = 0;
++ return false;
++ }
++ }
++
++ m_context->m_refCount++;
++
++ *ctx = m_context;
++ return true;
++}
++
++bool CXVBAContext::LoadSymbols()
++{
++ if (!m_dlHandle)
++ {
++ m_dlHandle = dlopen(XVBA_LIBRARY, RTLD_LAZY);
++ if (!m_dlHandle)
++ {
++ const char* error = dlerror();
++ if (!error)
++ error = "dlerror() returned NULL";
++
++ CLog::Log(LOGERROR,"XVBA::LoadSymbols: Unable to get handle to lib: %s", error);
++ return false;
++ }
++ }
++ else
++ return true;
++
++#define INIT_PROC(PREFIX, PROC) do { \
++ g_##PREFIX##_vtable.PROC = (PREFIX##PROC##Proc) \
++ dlsym(m_dlHandle, #PREFIX #PROC); \
++ } while (0)
++
++#define INIT_PROC_CHECK(PREFIX, PROC) do { \
++ dlerror(); \
++ INIT_PROC(PREFIX, PROC); \
++ if (dlerror()) { \
++ dlclose(m_dlHandle); \
++ m_dlHandle = NULL; \
++ return false; \
++ } \
++ } while (0)
++
++#define XVBA_INIT_PROC(PROC) INIT_PROC_CHECK(XVBA, PROC)
++
++ XVBA_INIT_PROC(QueryExtension);
++ XVBA_INIT_PROC(CreateContext);
++ XVBA_INIT_PROC(DestroyContext);
++ XVBA_INIT_PROC(GetSessionInfo);
++ XVBA_INIT_PROC(CreateSurface);
++ XVBA_INIT_PROC(CreateGLSharedSurface);
++ XVBA_INIT_PROC(DestroySurface);
++ XVBA_INIT_PROC(CreateDecodeBuffers);
++ XVBA_INIT_PROC(DestroyDecodeBuffers);
++ XVBA_INIT_PROC(GetCapDecode);
++ XVBA_INIT_PROC(CreateDecode);
++ XVBA_INIT_PROC(DestroyDecode);
++ XVBA_INIT_PROC(StartDecodePicture);
++ XVBA_INIT_PROC(DecodePicture);
++ XVBA_INIT_PROC(EndDecodePicture);
++ XVBA_INIT_PROC(SyncSurface);
++ XVBA_INIT_PROC(GetSurface);
++ XVBA_INIT_PROC(TransferSurface);
++
++#undef XVBA_INIT_PROC
++#undef INIT_PROC
++
++ return true;
++}
++
++bool CXVBAContext::CreateContext()
++{
++ if (m_xvbaContext)
++ return true;
++
++ CLog::Log(LOGNOTICE,"XVBA::CreateContext - creating decoder context");
++
++ Drawable window;
++ { CSingleLock lock(g_graphicsContext);
++ if (!m_display)
++ m_display = XOpenDisplay(NULL);
++ window = 0;
++ }
++
++ int version;
++ if (!g_XVBA_vtable.QueryExtension(m_display, &version))
++ return false;
++ CLog::Log(LOGNOTICE,"XVBA::CreateContext - opening xvba version: %i", version);
++
++ // create XVBA Context
++ XVBA_Create_Context_Input contextInput;
++ XVBA_Create_Context_Output contextOutput;
++ contextInput.size = sizeof(contextInput);
++ contextInput.display = m_display;
++ contextInput.draw = window;
++ contextOutput.size = sizeof(contextOutput);
++ if(Success != g_XVBA_vtable.CreateContext(&contextInput, &contextOutput))
++ {
++ CLog::Log(LOGERROR,"XVBA::CreateContext - failed to create context");
++ return false;
++ }
++ m_xvbaContext = contextOutput.context;
++
++ return true;
++}
++
++void CXVBAContext::DestroyContext()
++{
++ if (!m_xvbaContext)
++ return;
++
++ g_XVBA_vtable.DestroyContext(m_xvbaContext);
++ m_xvbaContext = 0;
++// XCloseDisplay(m_display);
++}
++
++void *CXVBAContext::GetContext()
++{
++ return m_xvbaContext;
++}
++
++//-----------------------------------------------------------------------------
++//-----------------------------------------------------------------------------
++
++static unsigned int decoderId = 0;
++
++CDecoder::CDecoder() : m_xvbaOutput(&m_inMsgEvent)
++{
++ m_xvbaConfig.context = 0;
++ m_xvbaConfig.xvbaSession = 0;
++ m_xvbaConfig.videoSurfaces = &m_videoSurfaces;
++ m_xvbaConfig.videoSurfaceSec = &m_videoSurfaceSec;
++ m_xvbaConfig.apiSec = &m_apiSec;
++
++ m_displayState = XVBA_OPEN;
++}
++
++CDecoder::~CDecoder()
++{
++ Close();
++}
++
++typedef struct {
++ unsigned int size;
++ unsigned int num_of_decodecaps;
++ XVBADecodeCap decode_caps_list[];
++} XVBA_GetCapDecode_Output_Base;
++
++void CDecoder::OnLostDevice()
++{
++ CLog::Log(LOGNOTICE,"XVBA::OnLostDevice event");
++
++ CSingleLock lock(m_decoderSection);
++ DestroySession();
++ if (m_xvbaConfig.context)
++ m_xvbaConfig.context->Release();
++ m_xvbaConfig.context = 0;
++
++ m_displayState = XVBA_LOST;
++ m_displayEvent.Reset();
++}
++
++void CDecoder::OnResetDevice()
++{
++ CLog::Log(LOGNOTICE,"XVBA::OnResetDevice event");
++
++ CSingleLock lock(m_decoderSection);
++ if (m_displayState == XVBA_LOST)
++ {
++ m_displayState = XVBA_RESET;
++ lock.Leave();
++ m_displayEvent.Set();
++ }
++}
++
++bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces)
++{
++ std::string Vendor = g_Windowing.GetRenderVendor();
++ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
++ if (Vendor.compare(0, 3, "ati") != 0)
++ {
++ return false;
++ }
++
++ m_decoderId = decoderId++;
++
++ CLog::Log(LOGNOTICE,"(XVBA::Open) opening xvba decoder, id: %d", m_decoderId);
++
++ if(avctx->coded_width == 0
++ || avctx->coded_height == 0)
++ {
++ CLog::Log(LOGWARNING,"(XVBA) no width/height available, can't init");
++ return false;
++ }
++
++ if (!m_dllAvUtil.Load())
++ return false;
++
++ if (!CXVBAContext::EnsureContext(&m_xvbaConfig.context))
++ return false;
++
++ // xvba get session info
++ XVBA_GetSessionInfo_Input sessionInput;
++ XVBA_GetSessionInfo_Output sessionOutput;
++ sessionInput.size = sizeof(sessionInput);
++ sessionInput.context = m_xvbaConfig.context->GetContext();
++ sessionOutput.size = sizeof(sessionOutput);
++ if (Success != g_XVBA_vtable.GetSessionInfo(&sessionInput, &sessionOutput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) can't get session info");
++ return false;
++ }
++ if (sessionOutput.getcapdecode_output_size == 0)
++ {
++ CLog::Log(LOGERROR,"(XVBA) session decode not supported");
++ return false;
++ }
++
++ // get decoder capabilities
++ XVBA_GetCapDecode_Input capInput;
++ XVBA_GetCapDecode_Output *capOutput;
++ capInput.size = sizeof(capInput);
++ capInput.context = m_xvbaConfig.context->GetContext();
++ capOutput = (XVBA_GetCapDecode_Output *)calloc(sessionOutput.getcapdecode_output_size, 1);
++ capOutput->size = sessionOutput.getcapdecode_output_size;
++ if (Success != g_XVBA_vtable.GetCapDecode(&capInput, capOutput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) can't get decode capabilities");
++ return false;
++ }
++
++ int match = -1;
++ if (avctx->codec_id == CODEC_ID_H264)
++ {
++ // search for profile high
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_H264 &&
++ capOutput->decode_caps_list[i].flags == XVBA_H264_HIGH)
++ {
++ match = (int) i;
++ break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_H264_HIGH not found");
++ }
++ }
++ else if (avctx->codec_id == CODEC_ID_VC1)
++ {
++ // search for profile advanced
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
++ capOutput->decode_caps_list[i].flags == XVBA_VC1_ADVANCED)
++ {
++ match = (int) i;
++ break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_ADVANCED not found");
++ }
++ }
++ else if (avctx->codec_id == CODEC_ID_MPEG2VIDEO)
++ {
++ // search for profile high
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_MPEG2_VLD)
++ {
++ // XXX: uncomment when implemented
++ // match = (int) i;
++ // break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_MPEG2_VLD not found");
++ }
++ }
++ else if (avctx->codec_id == CODEC_ID_WMV3)
++ {
++ // search for profile high
++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i)
++ {
++ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 &&
++ capOutput->decode_caps_list[i].flags == XVBA_VC1_MAIN)
++ {
++ match = (int) i;
++ break;
++ }
++ }
++ if (match < 0)
++ {
++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_MAIN not found");
++ }
++ }
++
++ if (match < 0)
++ {
++ free(capOutput);
++ return false;
++ }
++
++ CLog::Log(LOGNOTICE,"(XVBA) using decoder capability id: %i flags: %i",
++ capOutput->decode_caps_list[match].capability_id,
++ capOutput->decode_caps_list[match].flags);
++ CLog::Log(LOGNOTICE,"(XVBA) using surface type: %x",
++ capOutput->decode_caps_list[match].surface_type);
++
++ m_xvbaConfig.decoderCap = capOutput->decode_caps_list[match];
++
++ free(capOutput);
++
++ // set some varables
++ m_xvbaConfig.xvbaSession = 0;
++ m_xvbaBufferPool.data_buffer = 0;
++ m_xvbaBufferPool.iq_matrix_buffer = 0;
++ m_xvbaBufferPool.picture_descriptor_buffer = 0;
++ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
++ m_presentPicture = 0;
++ m_xvbaConfig.numRenderBuffers = surfaces;
++ m_decoderThread = CThread::GetCurrentThreadId();
++ m_speed = DVD_PLAYSPEED_NORMAL;
++
++ if (1) //g_guiSettings.GetBool("videoplayer.usexvbasharedsurface"))
++ m_xvbaConfig.useSharedSurfaces = true;
++ else
++ m_xvbaConfig.useSharedSurfaces = false;
++
++ m_displayState = XVBA_OPEN;
++
++ // setup ffmpeg
++ avctx->thread_count = 1;
++ avctx->get_buffer = CDecoder::FFGetBuffer;
++ avctx->release_buffer = CDecoder::FFReleaseBuffer;
++ avctx->draw_horiz_band = CDecoder::FFDrawSlice;
++ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
++
++ g_Windowing.Register(this);
++ return true;
++}
++
++void CDecoder::Close()
++{
++ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder, id: %d", m_decoderId);
++
++ if (!m_xvbaConfig.context)
++ return;
++
++ DestroySession();
++ if (m_xvbaConfig.context)
++ m_xvbaConfig.context->Release();
++ m_xvbaConfig.context = 0;
++
++ while (!m_videoSurfaces.empty())
++ {
++ xvba_render_state *render = m_videoSurfaces.back();
++ if(render->buffers_alllocated > 0)
++ m_dllAvUtil.av_free(render->buffers);
++ m_videoSurfaces.pop_back();
++ free(render);
++ }
++
++ g_Windowing.Unregister(this);
++ m_dllAvUtil.Unload();
++}
++
++long CDecoder::Release()
++{
++ // check if we should do some pre-cleanup here
++ // a second decoder might need resources
++ if (m_xvbaConfig.xvbaSession)
++ {
++ CSingleLock lock(m_decoderSection);
++ CLog::Log(LOGNOTICE,"XVBA::Release pre-cleanup");
++
++ Message *reply;
++ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::PRECLEANUP,
++ &reply,
++ 2000))
++ {
++ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
++ reply->Release();
++ if (!success)
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup returned error", __FUNCTION__);
++ m_displayState = XVBA_ERROR;
++ }
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - pre-cleanup timed out", __FUNCTION__);
++ m_displayState = XVBA_ERROR;
++ }
++
++ for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i)
++ {
++ xvba_render_state *render = m_videoSurfaces[i];
++ if (render->surface && !(render->state & FF_XVBA_STATE_USED_FOR_RENDER))
++ {
++ g_XVBA_vtable.DestroySurface(render->surface);
++ render->surface = 0;
++ render->picture_descriptor = 0;
++ render->iq_matrix = 0;
++ }
++ }
++ }
++ IHardwareDecoder::Release();
++}
++
++long CDecoder::ReleasePicReference()
++{
++ return IHardwareDecoder::Release();
++}
++
++bool CDecoder::Supports(EINTERLACEMETHOD method)
++{
++ if(method == VS_INTERLACEMETHOD_AUTO)
++ return true;
++
++ if (1) //g_guiSettings.GetBool("videoplayer.usexvbasharedsurface"))
++ {
++ if (method == VS_INTERLACEMETHOD_XVBA)
++ return true;
++ }
++
++ return false;
++}
++
++void CDecoder::ResetState()
++{
++ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64;
++
++ m_displayState = XVBA_OPEN;
++}
++
++int CDecoder::Check(AVCodecContext* avctx)
++{
++ EDisplayState state;
++
++ { CSingleLock lock(m_decoderSection);
++ state = m_displayState;
++ }
++
++ if (state == XVBA_LOST)
++ {
++ CLog::Log(LOGNOTICE,"XVBA::Check waiting for display reset event");
++ if (!m_displayEvent.WaitMSec(2000))
++ {
++ CLog::Log(LOGERROR, "XVBA::Check - device didn't reset in reasonable time");
++ state = XVBA_RESET;;
++ }
++ else
++ { CSingleLock lock(m_decoderSection);
++ state = m_displayState;
++ }
++ }
++ if (state == XVBA_RESET || state == XVBA_ERROR)
++ {
++ CLog::Log(LOGNOTICE,"XVBA::Check - Attempting recovery");
++
++ CSingleLock gLock(g_graphicsContext);
++ CSingleLock lock(m_decoderSection);
++
++ DestroySession();
++ ResetState();
++ CXVBAContext::EnsureContext(&m_xvbaConfig.context);
++
++ if (state == XVBA_RESET)
++ return VC_FLUSHED;
++ else
++ return VC_ERROR;
++ }
++ return 0;
++}
++
++void CDecoder::SetError(const char* function, const char* msg, int line)
++{
++ CLog::Log(LOGERROR, "XVBA::%s - %s, line %d", function, msg, line);
++ CSingleLock lock(m_decoderSection);
++ m_displayState = XVBA_ERROR;
++}
++
++bool CDecoder::CreateSession(AVCodecContext* avctx)
++{
++ m_xvbaConfig.surfaceWidth = (avctx->coded_width+15) & ~15;
++ m_xvbaConfig.surfaceHeight = (avctx->coded_height+15) & ~15;
++
++ m_xvbaConfig.vidWidth = avctx->width;
++ m_xvbaConfig.vidHeight = avctx->height;
++
++ XVBA_Create_Decode_Session_Input sessionInput;
++ XVBA_Create_Decode_Session_Output sessionOutput;
++
++ sessionInput.size = sizeof(sessionInput);
++ sessionInput.width = m_xvbaConfig.surfaceWidth;
++ sessionInput.height = m_xvbaConfig.surfaceHeight;
++ sessionInput.context = m_xvbaConfig.context->GetContext();
++ sessionInput.decode_cap = &m_xvbaConfig.decoderCap;
++ sessionOutput.size = sizeof(sessionOutput);
++
++ if (Success != g_XVBA_vtable.CreateDecode(&sessionInput, &sessionOutput))
++ {
++ SetError(__FUNCTION__, "failed to create decoder session", __LINE__);
++ CLog::Log(LOGERROR, "Decoder failed with following stats: m_surfaceWidth %u, m_surfaceHeight %u,"
++ " m_vidWidth %u, m_vidHeight %u, coded_width %d, coded_height %d",
++ m_xvbaConfig.surfaceWidth,
++ m_xvbaConfig.surfaceHeight,
++ m_xvbaConfig.vidWidth,
++ m_xvbaConfig.vidHeight,
++ avctx->coded_width,
++ avctx->coded_height);
++ return false;
++ }
++ m_xvbaConfig.xvbaSession = sessionOutput.session;
++
++ // create decode buffers
++ XVBA_Create_DecodeBuff_Input bufferInput;
++ XVBA_Create_DecodeBuff_Output bufferOutput;
++
++ bufferInput.size = sizeof(bufferInput);
++ bufferInput.session = m_xvbaConfig.xvbaSession;
++ bufferInput.buffer_type = XVBA_PICTURE_DESCRIPTION_BUFFER;
++ bufferInput.num_of_buffers = 1;
++ bufferOutput.size = sizeof(bufferOutput);
++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
++ || bufferOutput.num_of_buffers_in_list != 1)
++ {
++ SetError(__FUNCTION__, "failed to create picture buffer", __LINE__);
++ return false;
++ }
++ m_xvbaBufferPool.picture_descriptor_buffer = bufferOutput.buffer_list;
++
++ // data buffer
++ bufferInput.buffer_type = XVBA_DATA_BUFFER;
++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
++ || bufferOutput.num_of_buffers_in_list != 1)
++ {
++ SetError(__FUNCTION__, "failed to create data buffer", __LINE__);
++ return false;
++ }
++ m_xvbaBufferPool.data_buffer = bufferOutput.buffer_list;
++
++ // QO Buffer
++ bufferInput.buffer_type = XVBA_QM_BUFFER;
++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput)
++ || bufferOutput.num_of_buffers_in_list != 1)
++ {
++ SetError(__FUNCTION__, "failed to create qm buffer", __LINE__);
++ return false;
++ }
++ m_xvbaBufferPool.iq_matrix_buffer = bufferOutput.buffer_list;
++
++
++ // initialize output
++ CSingleLock lock(g_graphicsContext);
++ m_xvbaConfig.stats = &m_bufferStats;
++ m_bufferStats.Reset();
++ m_xvbaOutput.Start();
++ Message *reply;
++ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::INIT,
++ &reply,
++ 2000,
++ &m_xvbaConfig,
++ sizeof(m_xvbaConfig)))
++ {
++ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
++ reply->Release();
++ if (!success)
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - vdpau output returned error", __FUNCTION__);
++ m_xvbaOutput.Dispose();
++ return false;
++ }
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - failed to init output", __FUNCTION__);
++ m_xvbaOutput.Dispose();
++ return false;
++ }
++ m_inMsgEvent.Reset();
++
++ return true;
++}
++
++void CDecoder::DestroySession()
++{
++ m_xvbaOutput.Dispose();
++
++ XVBA_Destroy_Decode_Buffers_Input bufInput;
++ bufInput.size = sizeof(bufInput);
++ bufInput.num_of_buffers_in_list = 1;
++
++ for (unsigned int i=0; isurface)
++ {
++ g_XVBA_vtable.DestroySurface(render->surface);
++ render->surface = 0;
++ render->picture_descriptor = 0;
++ render->iq_matrix = 0;
++ }
++ }
++
++ if (m_xvbaConfig.xvbaSession)
++ g_XVBA_vtable.DestroyDecode(m_xvbaConfig.xvbaSession);
++ m_xvbaConfig.xvbaSession = 0;
++}
++
++bool CDecoder::IsSurfaceValid(xvba_render_state *render)
++{
++ // find render state in queue
++ bool found(false);
++ unsigned int i;
++ for(i = 0; i < m_videoSurfaces.size(); ++i)
++ {
++ if(m_videoSurfaces[i] == render)
++ {
++ found = true;
++ break;
++ }
++ }
++ if (!found)
++ {
++ CLog::Log(LOGERROR,"%s - video surface not found", __FUNCTION__);
++ return false;
++ }
++ if (m_videoSurfaces[i]->surface == 0)
++ {
++ m_videoSurfaces[i]->state = 0;
++ return false;
++ }
++
++ return true;
++}
++
++bool CDecoder::EnsureDataControlBuffers(unsigned int num)
++{
++ if (m_xvbaBufferPool.data_control_buffers.size() >= num)
++ return true;
++
++ unsigned int missing = num - m_xvbaBufferPool.data_control_buffers.size();
++
++ XVBA_Create_DecodeBuff_Input bufferInput;
++ XVBA_Create_DecodeBuff_Output bufferOutput;
++ bufferInput.size = sizeof(bufferInput);
++ bufferInput.session = m_xvbaConfig.xvbaSession;
++ bufferInput.buffer_type = XVBA_DATA_CTRL_BUFFER;
++ bufferInput.num_of_buffers = 1;
++ bufferOutput.size = sizeof(bufferOutput);
++
++ for (unsigned int i=0; iopaque;
++ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
++ unsigned int i;
++
++ CSingleLock lock(xvba->m_decoderSection);
++
++ xvba_render_state * render = NULL;
++ render = (xvba_render_state*)pic->data[0];
++ if(!render)
++ {
++ CLog::Log(LOGERROR, "XVBA::FFReleaseBuffer - invalid context handle provided");
++ return;
++ }
++
++ for(i=0; i<4; i++)
++ pic->data[i]= NULL;
++
++ // find render state in queue
++ if (!xvba->IsSurfaceValid(render))
++ {
++ CLog::Log(LOGDEBUG, "XVBA::FFReleaseBuffer - ignoring invalid buffer");
++ return;
++ }
++
++ render->state &= ~FF_XVBA_STATE_USED_FOR_REFERENCE;
++}
++
++void CDecoder::FFDrawSlice(struct AVCodecContext *avctx,
++ const AVFrame *src, int offset[4],
++ int y, int type, int height)
++{
++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
++ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
++
++ CSingleLock lock(xvba->m_decoderSection);
++
++ if(xvba->m_displayState != XVBA_OPEN)
++ return;
++
++ if(src->linesize[0] || src->linesize[1] || src->linesize[2]
++ || offset[0] || offset[1] || offset[2])
++ {
++ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid linesizes or offsets provided");
++ return;
++ }
++
++ xvba_render_state * render;
++
++ render = (xvba_render_state*)src->data[0];
++ if(!render)
++ {
++ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid context handle provided");
++ return;
++ }
++
++ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
++ if (!xvba->IsSurfaceValid(render))
++ {
++ CLog::Log(LOGWARNING, "XVBA::FFDrawSlice - ignoring invalid buffer");
++ return;
++ }
++
++ // decoding
++ XVBA_Decode_Picture_Start_Input startInput;
++ startInput.size = sizeof(startInput);
++ startInput.session = xvba->m_xvbaConfig.xvbaSession;
++ startInput.target_surface = render->surface;
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.StartDecodePicture(&startInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to start decoding", __LINE__);
++ return;
++ }
++ }
++
++ XVBA_Decode_Picture_Input picInput;
++ picInput.size = sizeof(picInput);
++ picInput.session = xvba->m_xvbaConfig.xvbaSession;
++ XVBABufferDescriptor *list[2];
++ picInput.buffer_list = list;
++ list[0] = xvba->m_xvbaBufferPool.picture_descriptor_buffer;
++ picInput.num_of_buffers_in_list = 1;
++ if (avctx->codec_id == CODEC_ID_H264)
++ {
++ list[1] = xvba->m_xvbaBufferPool.iq_matrix_buffer;
++ picInput.num_of_buffers_in_list = 2;
++ }
++
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to decode picture 1", __LINE__);
++ return;
++ }
++ }
++
++ if (!xvba->EnsureDataControlBuffers(render->num_slices))
++ return;
++
++ XVBADataCtrl *dataControl;
++ int location = 0;
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer = 0;
++ for (unsigned int j = 0; j < render->num_slices; ++j)
++ {
++ int startCodeSize = 0;
++ uint8_t startCode[] = {0x00,0x00,0x01};
++ if (avctx->codec_id == CODEC_ID_H264)
++ {
++ startCodeSize = 3;
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
++ startCode, 3);
++ }
++ else if (avctx->codec_id == CODEC_ID_VC1 &&
++ (memcmp(render->buffers[j].buffer, startCode, 3) != 0))
++ {
++ startCodeSize = 4;
++ uint8_t sdf = 0x0d;
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location,
++ startCode, 3);
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+3,
++ &sdf, 1);
++ }
++ // check for potential buffer overwrite
++ unsigned int bytesToCopy = render->buffers[j].size;
++ unsigned int freeBufferSize = xvba->m_xvbaBufferPool.data_buffer->buffer_size -
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
++ if (bytesToCopy >= freeBufferSize)
++ {
++ xvba->SetError(__FUNCTION__, "bitstream buffer too large, maybe corrupted packet", __LINE__);
++ return;
++ }
++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+startCodeSize,
++ render->buffers[j].buffer,
++ render->buffers[j].size);
++ dataControl = (XVBADataCtrl*)xvba->m_xvbaBufferPool.data_control_buffers[j]->bufferXVBA;
++ dataControl->SliceDataLocation = location;
++ dataControl->SliceBytesInBuffer = render->buffers[j].size+startCodeSize;
++ dataControl->SliceBitsInBuffer = dataControl->SliceBytesInBuffer * 8;
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += dataControl->SliceBytesInBuffer;
++ location += dataControl->SliceBytesInBuffer;
++ }
++
++ int bufSize = xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer;
++ int padding = bufSize % 128;
++ if (padding)
++ {
++ padding = 128 - padding;
++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += padding;
++ memset((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+bufSize,0,padding);
++ }
++
++ picInput.num_of_buffers_in_list = 2;
++ for (unsigned int i = 0; i < render->num_slices; ++i)
++ {
++ list[0] = xvba->m_xvbaBufferPool.data_buffer;
++ list[0]->data_offset = 0;
++ list[1] = xvba->m_xvbaBufferPool.data_control_buffers[i];
++ list[1]->data_size_in_buffer = sizeof(*dataControl);
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.DecodePicture(&picInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to decode picture 2", __LINE__);
++ return;
++ }
++ }
++ }
++ XVBA_Decode_Picture_End_Input endInput;
++ endInput.size = sizeof(endInput);
++ endInput.session = xvba->m_xvbaConfig.xvbaSession;
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.EndDecodePicture(&endInput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to decode picture 3", __LINE__);
++ return;
++ }
++ }
++
++ // decode sync and error
++ XVBA_Surface_Sync_Input syncInput;
++ XVBA_Surface_Sync_Output syncOutput;
++ syncInput.size = sizeof(syncInput);
++ syncInput.session = xvba->m_xvbaConfig.xvbaSession;
++ syncInput.surface = render->surface;
++ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
++ syncOutput.size = sizeof(syncOutput);
++ int64_t start = CurrentHostCounter();
++ while (1)
++ {
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
++ {
++ xvba->SetError(__FUNCTION__, "failed sync surface 1", __LINE__);
++ return;
++ }
++ }
++ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
++ break;
++ if (CurrentHostCounter() - start > CurrentHostFrequency())
++ {
++ xvba->SetError(__FUNCTION__, "timed out waiting for surface", __LINE__);
++ break;
++ }
++ usleep(100);
++ }
++ render->state |= FF_XVBA_STATE_DECODED;
++}
++
++int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic)
++{
++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
++ CDecoder* xvba = (CDecoder*)ctx->GetHardware();
++ struct pictureAge* pA = &xvba->picAge;
++
++ pic->data[0] =
++ pic->data[1] =
++ pic->data[2] =
++ pic->data[3] = 0;
++
++ pic->linesize[0] =
++ pic->linesize[1] =
++ pic->linesize[2] =
++ pic->linesize[3] = 0;
++
++ CSingleLock lock(xvba->m_decoderSection);
++
++ if(xvba->m_displayState != XVBA_OPEN)
++ return -1;
++
++ if (xvba->m_xvbaConfig.xvbaSession == 0)
++ {
++ if (!xvba->CreateSession(avctx))
++ return -1;
++ }
++
++ xvba_render_state * render = NULL;
++ // find unused surface
++ { CSingleLock lock(xvba->m_videoSurfaceSec);
++ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i)
++ {
++ if(!(xvba->m_videoSurfaces[i]->state & (FF_XVBA_STATE_USED_FOR_REFERENCE | FF_XVBA_STATE_USED_FOR_RENDER)))
++ {
++ render = xvba->m_videoSurfaces[i];
++ render->state = 0;
++ break;
++ }
++ }
++ }
++
++ // create a new render state
++ if (render == NULL)
++ {
++ render = (xvba_render_state*)calloc(sizeof(xvba_render_state), 1);
++ if (render == NULL)
++ {
++ CLog::Log(LOGERROR, "XVBA::FFGetBuffer - calloc failed");
++ return -1;
++ }
++ render->surface = 0;
++ render->buffers_alllocated = 0;
++ CSingleLock lock(xvba->m_videoSurfaceSec);
++ xvba->m_videoSurfaces.push_back(render);
++ }
++
++ // create a new surface
++ if (render->surface == 0)
++ {
++ XVBA_Create_Surface_Input surfaceInput;
++ XVBA_Create_Surface_Output surfaceOutput;
++ surfaceInput.size = sizeof(surfaceInput);
++ surfaceInput.surface_type = xvba->m_xvbaConfig.decoderCap.surface_type;
++ surfaceInput.width = xvba->m_xvbaConfig.surfaceWidth;
++ surfaceInput.height = xvba->m_xvbaConfig.surfaceHeight;
++ surfaceInput.session = xvba->m_xvbaConfig.xvbaSession;
++ surfaceOutput.size = sizeof(surfaceOutput);
++ { CSingleLock lock(xvba->m_apiSec);
++ if (Success != g_XVBA_vtable.CreateSurface(&surfaceInput, &surfaceOutput))
++ {
++ xvba->SetError(__FUNCTION__, "failed to create video surface", __LINE__);
++ return -1;
++ }
++ }
++ render->surface = surfaceOutput.surface;
++ render->picture_descriptor = (XVBAPictureDescriptor *)xvba->m_xvbaBufferPool.picture_descriptor_buffer->bufferXVBA;
++ render->iq_matrix = (XVBAQuantMatrixAvc *)xvba->m_xvbaBufferPool.iq_matrix_buffer->bufferXVBA;
++ CLog::Log(LOGDEBUG, "XVBA::FFGetBuffer - created video surface");
++ }
++
++ if (render == NULL)
++ return -1;
++
++ pic->data[0] = (uint8_t*)render;
++
++ if(pic->reference)
++ {
++ pic->age = pA->ip_age[0];
++ pA->ip_age[0]= pA->ip_age[1]+1;
++ pA->ip_age[1]= 1;
++ pA->b_age++;
++ }
++ else
++ {
++ pic->age = pA->b_age;
++ pA->ip_age[0]++;
++ pA->ip_age[1]++;
++ pA->b_age = 1;
++ }
++ pic->type= FF_BUFFER_TYPE_USER;
++
++ render->state |= FF_XVBA_STATE_USED_FOR_REFERENCE;
++ render->state &= ~FF_XVBA_STATE_DECODED;
++ pic->reordered_opaque= avctx->reordered_opaque;
++
++ return 0;
++}
++
++int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
++{
++ int result = Check(avctx);
++ if (result)
++ return result;
++
++ CSingleLock lock(m_decoderSection);
++
++ if(frame)
++ { // we have a new frame from decoder
++
++ xvba_render_state * render = (xvba_render_state*)frame->data[0];
++ if(!render)
++ {
++ CLog::Log(LOGERROR, "XVBA::Decode - no render buffer");
++ return VC_ERROR;
++ }
++
++ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid
++ if (!IsSurfaceValid(render))
++ {
++ CLog::Log(LOGWARNING, "XVBA::Decode - ignoring invalid buffer");
++ return VC_BUFFER;
++ }
++ if (!(render->state & FF_XVBA_STATE_DECODED))
++ {
++ CLog::Log(LOGDEBUG, "XVBA::Decode - ffmpeg failed");
++ return VC_BUFFER;
++ }
++
++ CSingleLock lock(m_videoSurfaceSec);
++ render->state |= FF_XVBA_STATE_USED_FOR_RENDER;
++ lock.Leave();
++
++ // send frame to output for processing
++ CXvbaDecodedPicture pic;
++ memset(&pic.DVDPic, 0, sizeof(pic.DVDPic));
++ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&pic.DVDPic);
++ pic.render = render;
++ m_bufferStats.IncDecoded();
++ m_xvbaOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic));
++
++ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_SKIP_PROC);
++ if (m_codecControl & DVP_FLAG_SKIP_PROC)
++ {
++ m_bufferStats.SetCmd(DVP_FLAG_SKIP_PROC);
++ }
++ }
++
++ int retval = 0;
++ uint16_t decoded, processed, render;
++ Message *msg;
++ while (m_xvbaOutput.m_controlPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputControlProtocol::ERROR)
++ {
++ m_displayState = XVBA_ERROR;
++ retval |= VC_ERROR;
++ }
++ msg->Release();
++ }
++
++ m_bufferStats.Get(decoded, processed, render);
++
++ uint64_t startTime = CurrentHostCounter();
++ while (!retval)
++ {
++ if (m_xvbaOutput.m_dataPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputDataProtocol::PICTURE)
++ {
++ if (m_presentPicture)
++ {
++ m_presentPicture->ReturnUnused();
++ m_presentPicture = 0;
++ }
++
++ m_presentPicture = *(CXvbaRenderPicture**)msg->data;
++ m_presentPicture->xvba = this;
++ m_bufferStats.DecRender();
++ m_bufferStats.Get(decoded, processed, render);
++ retval |= VC_PICTURE;
++ }
++ msg->Release();
++ }
++ else if (m_xvbaOutput.m_controlPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputControlProtocol::STATS)
++ {
++ m_bufferStats.Get(decoded, processed, render);
++ }
++ else
++ {
++ m_displayState = XVBA_ERROR;
++ retval |= VC_ERROR;
++ }
++ msg->Release();
++ }
++
++ if ((m_codecControl & DVP_FLAG_DRAIN))
++ {
++ if (decoded + processed + render < 2)
++ {
++ retval |= VC_BUFFER;
++ }
++ }
++ else
++ {
++ if (decoded + processed + render < 4)
++ {
++ retval |= VC_BUFFER;
++ }
++ }
++
++ if (!retval && !m_inMsgEvent.WaitMSec(2000))
++ break;
++ }
++ uint64_t diff = CurrentHostCounter() - startTime;
++ if (retval & VC_PICTURE)
++ {
++ m_bufferStats.SetParams(diff, m_speed);
++ if (diff*1000/CurrentHostFrequency() > 50)
++ CLog::Log(LOGDEBUG,"XVBA::Decode long wait: %d", (int)((diff*1000)/CurrentHostFrequency()));
++ }
++
++ if (!retval)
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - timed out waiting for output message", __FUNCTION__);
++ m_displayState = XVBA_ERROR;
++ retval |= VC_ERROR;
++ }
++
++ return retval;
++
++}
++
++bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
++{
++ CSingleLock lock(m_decoderSection);
++
++ if (m_displayState != XVBA_OPEN)
++ return false;
++
++ *picture = m_presentPicture->DVDPic;
++ picture->xvba = m_presentPicture;
++
++ return true;
++}
++
++void CDecoder::ReturnRenderPicture(CXvbaRenderPicture *renderPic)
++{
++ m_xvbaOutput.m_dataPort.SendOutMessage(COutputDataProtocol::RETURNPIC, &renderPic, sizeof(renderPic));
++}
++
++
++//void CDecoder::CopyYV12(int index, uint8_t *dest)
++//{
++// CSharedLock lock(m_decoderSection);
++//
++// { CSharedLock dLock(m_displaySection);
++// if(m_displayState != XVBA_OPEN)
++// return;
++// }
++//
++// if (!m_flipBuffer[index].outPic)
++// {
++// CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL");
++// return;
++// }
++//
++// XVBA_GetSurface_Target target;
++// target.size = sizeof(target);
++// target.surfaceType = XVBA_YV12;
++// target.flag = XVBA_FRAME;
++//
++// XVBA_Get_Surface_Input input;
++// input.size = sizeof(input);
++// input.session = m_xvbaSession;
++// input.src_surface = m_flipBuffer[index].outPic->render->surface;
++// input.target_buffer = dest;
++// input.target_pitch = m_surfaceWidth;
++// input.target_width = m_surfaceWidth;
++// input.target_height = m_surfaceHeight;
++// input.target_parameter = target;
++// { CSingleLock lock(m_apiSec);
++// if (Success != g_XVBA_vtable.GetSurface(&input))
++// {
++// CLog::Log(LOGERROR,"(XVBA::CopyYV12) failed to get surface");
++// }
++// }
++//}
++
++void CDecoder::Reset()
++{
++ CSingleLock lock(m_decoderSection);
++
++ if (!m_xvbaConfig.xvbaSession)
++ return;
++
++ Message *reply;
++ if (m_xvbaOutput.m_controlPort.SendOutMessageSync(COutputControlProtocol::FLUSH,
++ &reply,
++ 2000))
++ {
++ bool success = reply->signal == COutputControlProtocol::ACC ? true : false;
++ reply->Release();
++ if (!success)
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - flush returned error", __FUNCTION__);
++ m_displayState = XVBA_ERROR;
++ }
++ else
++ m_bufferStats.Reset();
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "XVBA::%s - flush timed out", __FUNCTION__);
++ m_displayState = XVBA_ERROR;
++ }
++}
++
++bool CDecoder::CanSkipDeint()
++{
++ return m_bufferStats.CanSkipDeint();
++}
++
++void CDecoder::SetSpeed(int speed)
++{
++ m_speed = speed;
++}
++
++//-----------------------------------------------------------------------------
++// RenderPicture
++//-----------------------------------------------------------------------------
++
++CXvbaRenderPicture* CXvbaRenderPicture::Acquire()
++{
++ CSingleLock lock(*renderPicSection);
++
++ if (refCount == 0)
++ xvba->Acquire();
++
++ refCount++;
++ return this;
++}
++
++long CXvbaRenderPicture::Release()
++{
++ CSingleLock lock(*renderPicSection);
++
++ refCount--;
++ if (refCount > 0)
++ return refCount;
++
++ lock.Leave();
++ xvba->ReturnRenderPicture(this);
++ xvba->ReleasePicReference();
++
++ return refCount;
++}
++
++void CXvbaRenderPicture::Transfer()
++{
++ CSingleLock lock(*renderPicSection);
++
++ if (valid)
++ xvbaOutput->TransferSurface(sourceIdx);
++}
++
++void CXvbaRenderPicture::ReturnUnused()
++{
++ { CSingleLock lock(*renderPicSection);
++ if (refCount > 0)
++ return;
++ }
++ if (xvba)
++ xvba->ReturnRenderPicture(this);
++}
++
++//-----------------------------------------------------------------------------
++// Output
++//-----------------------------------------------------------------------------
++COutput::COutput(CEvent *inMsgEvent) :
++ CThread("XVBA Output Thread"),
++ m_controlPort("OutputControlPort", inMsgEvent, &m_outMsgEvent),
++ m_dataPort("OutputDataPort", inMsgEvent, &m_outMsgEvent)
++{
++ m_inMsgEvent = inMsgEvent;
++
++ CXvbaRenderPicture pic;
++ pic.renderPicSection = &m_bufferPool.renderPicSec;
++ pic.refCount = 0;
++ for (unsigned int i = 0; i < NUM_RENDER_PICS; i++)
++ {
++ m_bufferPool.allRenderPics.push_back(pic);
++ }
++ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); ++i)
++ {
++ m_bufferPool.freeRenderPics.push_back(&m_bufferPool.allRenderPics[i]);
++ }
++}
++
++void COutput::Start()
++{
++ Create();
++}
++
++COutput::~COutput()
++{
++ Dispose();
++
++ m_bufferPool.freeRenderPics.clear();
++ m_bufferPool.usedRenderPics.clear();
++ m_bufferPool.allRenderPics.clear();
++}
++
++void COutput::Dispose()
++{
++ CSingleLock lock(g_graphicsContext);
++ m_bStop = true;
++ m_outMsgEvent.Set();
++ StopThread();
++ m_controlPort.Purge();
++ m_dataPort.Purge();
++}
++
++void COutput::OnStartup()
++{
++ CLog::Log(LOGNOTICE, "COutput::OnStartup: Output Thread created");
++}
++
++void COutput::OnExit()
++{
++ CLog::Log(LOGNOTICE, "COutput::OnExit: Output Thread terminated");
++}
++
++enum OUTPUT_STATES
++{
++ O_TOP = 0, // 0
++ O_TOP_ERROR, // 1
++ O_TOP_UNCONFIGURED, // 2
++ O_TOP_CONFIGURED, // 3
++ O_TOP_CONFIGURED_WAIT_RES1, // 4
++ O_TOP_CONFIGURED_WAIT_DEC, // 5
++ O_TOP_CONFIGURED_STEP1, // 6
++ O_TOP_CONFIGURED_WAIT_RES2, // 7
++ O_TOP_CONFIGURED_STEP2, // 8
++};
++
++int OUTPUT_parentStates[] = {
++ -1,
++ 0, //TOP_ERROR
++ 0, //TOP_UNCONFIGURED
++ 0, //TOP_CONFIGURED
++ 3, //TOP_CONFIGURED_WAIT_RES1
++ 3, //TOP_CONFIGURED_WAIT_DEC
++ 3, //TOP_CONFIGURED_STEP1
++ 3, //TOP_CONFIGURED_WAIT_RES2
++ 3, //TOP_CONFIGURED_STEP2
++};
++
++void COutput::StateMachine(int signal, Protocol *port, Message *msg)
++{
++ for (int state = m_state; ; state = OUTPUT_parentStates[state])
++ {
++ switch (state)
++ {
++ case O_TOP: // TOP
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::FLUSH:
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ case COutputControlProtocol::PRECLEANUP:
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ default:
++ break;
++ }
++ }
++ else if (port == &m_dataPort)
++ {
++ switch (signal)
++ {
++ case COutputDataProtocol::RETURNPIC:
++ CXvbaRenderPicture *pic;
++ pic = *((CXvbaRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ return;
++ default:
++ break;
++ }
++ }
++ {
++ std::string portName = port == NULL ? "timer" : port->portName;
++ CLog::Log(LOGWARNING, "COutput::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
++ }
++ return;
++
++ case O_TOP_ERROR:
++ m_extTimeout = 1000;
++ break;
++
++ case O_TOP_UNCONFIGURED:
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::INIT:
++ CXvbaConfig *data;
++ data = (CXvbaConfig*)msg->data;
++ if (data)
++ {
++ m_config = *data;
++ }
++ Init();
++ EnsureBufferPool();
++ if (!m_xvbaError)
++ {
++ m_state = O_TOP_CONFIGURED_WAIT_RES1;
++ msg->Reply(COutputControlProtocol::ACC);
++ }
++ else
++ {
++ m_state = O_TOP_ERROR;
++ msg->Reply(COutputControlProtocol::ERROR);
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED:
++ if (port == &m_controlPort)
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::FLUSH:
++ m_state = O_TOP_CONFIGURED_WAIT_RES1;
++ Flush();
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ case COutputControlProtocol::PRECLEANUP:
++ m_state = O_TOP_CONFIGURED_WAIT_RES1;
++ Flush();
++ PreReleaseBufferPool();
++ msg->Reply(COutputControlProtocol::ACC);
++ return;
++ default:
++ break;
++ }
++ }
++ else if (port == &m_dataPort)
++ {
++ switch (signal)
++ {
++ case COutputDataProtocol::NEWFRAME:
++ CXvbaDecodedPicture *frame;
++ frame = (CXvbaDecodedPicture*)msg->data;
++ if (frame)
++ {
++ m_decodedPics.push(*frame);
++ m_extTimeout = 0;
++ }
++ return;
++ case COutputDataProtocol::RETURNPIC:
++ CXvbaRenderPicture *pic;
++ pic = *((CXvbaRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ m_controlPort.SendInMessage(COutputControlProtocol::STATS);
++ m_extTimeout = 0;
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_WAIT_RES1:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++ if (!m_decodedPics.empty() && FindFreeSurface() >= 0 && !m_bufferPool.freeRenderPics.empty())
++ {
++ m_state = O_TOP_CONFIGURED_WAIT_DEC;
++ m_bStateMachineSelfTrigger = true;
++ }
++ else
++ {
++ if (m_extTimeout != 0)
++ {
++ uint16_t decoded, processed, render;
++ m_config.stats->Get(decoded, processed, render);
++// CLog::Log(LOGDEBUG, "CVDPAU::COutput - timeout idle: decoded: %d, proc: %d, render: %d", decoded, processed, render);
++ }
++ m_extTimeout = 100;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_WAIT_DEC:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++ if (IsDecodingFinished())
++ {
++ m_state = O_TOP_CONFIGURED_STEP1;
++ m_bStateMachineSelfTrigger = true;
++ }
++ else
++ {
++ m_extTimeout = 1;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_STEP1:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++ m_processPicture = m_decodedPics.front();
++ m_decodedPics.pop();
++ InitCycle();
++ CXvbaRenderPicture *pic;
++ pic = ProcessPicture();
++ if (pic)
++ {
++ m_config.stats->IncRender();
++ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &pic, sizeof(pic));
++ }
++ if (m_xvbaError)
++ {
++ m_state = O_TOP_ERROR;
++ return;
++ }
++ if (m_deinterlacing && !m_deintSkip)
++ {
++ m_state = O_TOP_CONFIGURED_WAIT_RES2;
++ m_extTimeout = 0;
++ }
++ else
++ {
++ FiniCycle();
++ m_state = O_TOP_CONFIGURED_WAIT_RES1;
++ m_extTimeout = 0;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_WAIT_RES2:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++ if (FindFreeSurface() >= 0 && !m_bufferPool.freeRenderPics.empty())
++ {
++ m_state = O_TOP_CONFIGURED_STEP2;
++ m_bStateMachineSelfTrigger = true;
++ }
++ else
++ {
++ if (m_extTimeout != 0)
++ {
++ uint16_t decoded, processed, render;
++ m_config.stats->Get(decoded, processed, render);
++ CLog::Log(LOGDEBUG, "CVDPAU::COutput - timeout idle: decoded: %d, proc: %d, render: %d", decoded, processed, render);
++ }
++ m_extTimeout = 100;
++ }
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ case O_TOP_CONFIGURED_STEP2:
++ if (port == NULL) // timeout
++ {
++ switch (signal)
++ {
++ case COutputControlProtocol::TIMEOUT:
++ CXvbaRenderPicture *pic;
++ m_deintStep = 1;
++ pic = ProcessPicture();
++ if (pic)
++ {
++ m_config.stats->IncRender();
++ m_dataPort.SendInMessage(COutputDataProtocol::PICTURE, &pic, sizeof(pic));
++ }
++ if (m_xvbaError)
++ {
++ m_state = O_TOP_ERROR;
++ return;
++ }
++ FiniCycle();
++ m_state = O_TOP_CONFIGURED_WAIT_RES1;
++ m_extTimeout = 0;
++ return;
++ default:
++ break;
++ }
++ }
++ break;
++
++ default: // we are in no state, should not happen
++ CLog::Log(LOGERROR, "COutput::%s - no valid state: %d", __FUNCTION__, m_state);
++ return;
++ }
++ } // for
++}
++
++void COutput::Process()
++{
++ Message *msg;
++ Protocol *port;
++ bool gotMsg;
++
++ m_state = O_TOP_UNCONFIGURED;
++ m_extTimeout = 1000;
++ m_bStateMachineSelfTrigger = false;
++
++ while (!m_bStop)
++ {
++ gotMsg = false;
++
++ if (m_bStateMachineSelfTrigger)
++ {
++ m_bStateMachineSelfTrigger = false;
++ // self trigger state machine
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ continue;
++ }
++ // check control port
++ else if (m_controlPort.ReceiveOutMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_controlPort;
++ }
++ // check data port
++ else if (m_dataPort.ReceiveOutMessage(&msg))
++ {
++ gotMsg = true;
++ port = &m_dataPort;
++ }
++ if (gotMsg)
++ {
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ continue;
++ }
++
++ // wait for message
++ else if (m_outMsgEvent.WaitMSec(m_extTimeout))
++ {
++ continue;
++ }
++ // time out
++ else
++ {
++ msg = m_controlPort.GetMessage();
++ msg->signal = COutputControlProtocol::TIMEOUT;
++ port = 0;
++ // signal timeout to state machine
++ StateMachine(msg->signal, port, msg);
++ if (!m_bStateMachineSelfTrigger)
++ {
++ msg->Release();
++ msg = NULL;
++ }
++ }
++ }
++ Flush();
++ Uninit();
++}
++
++bool COutput::Init()
++{
++ if (!CreateGlxContext())
++ return false;
++
++ m_xvbaError = false;
++ m_processPicture.render = 0;
++
++ return true;
++}
++
++bool COutput::Uninit()
++{
++ ReleaseBufferPool();
++ DestroyGlxContext();
++ return true;
++}
++
++void COutput::Flush()
++{
++ while (!m_decodedPics.empty())
++ {
++ CXvbaDecodedPicture pic = m_decodedPics.front();
++ m_decodedPics.pop();
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
++ }
++
++ if (m_processPicture.render)
++ {
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ m_processPicture.render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
++ m_processPicture.render = 0;
++ }
++
++ Message *msg;
++ while (m_dataPort.ReceiveOutMessage(&msg))
++ {
++ if (msg->signal == COutputDataProtocol::NEWFRAME)
++ {
++ CXvbaDecodedPicture pic = *(CXvbaDecodedPicture*)msg->data;
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ if (pic.render)
++ pic.render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
++ }
++ else if (msg->signal == COutputDataProtocol::RETURNPIC)
++ {
++ CXvbaRenderPicture *pic;
++ pic = *((CXvbaRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ }
++ msg->Release();
++ }
++
++ while (m_dataPort.ReceiveInMessage(&msg))
++ {
++ if (msg->signal == COutputDataProtocol::PICTURE)
++ {
++ CXvbaRenderPicture *pic;
++ pic = *((CXvbaRenderPicture**)msg->data);
++ ProcessReturnPicture(pic);
++ }
++ }
++}
++
++bool COutput::IsDecodingFinished()
++{
++ return true;
++
++ // check for decoding to be finished
++ CXvbaDecodedPicture decodedPic = m_decodedPics.front();
++
++ XVBA_Surface_Sync_Input syncInput;
++ XVBA_Surface_Sync_Output syncOutput;
++ syncInput.size = sizeof(syncInput);
++ syncInput.session = m_config.xvbaSession;
++ syncInput.surface = decodedPic.render->surface;
++ syncInput.query_status = XVBA_GET_SURFACE_STATUS;
++ syncOutput.size = sizeof(syncOutput);
++ { CSingleLock lock(*(m_config.apiSec));
++ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput))
++ {
++ CLog::Log(LOGERROR,"XVBA - failed sync surface");
++ m_xvbaError = true;
++ return false;
++ }
++ }
++ if (!(syncOutput.status_flags & XVBA_STILL_PENDING))
++ return true;
++
++ return false;
++}
++
++void COutput::TransferSurface(uint32_t source)
++{
++ XvbaBufferPool::GLVideoSurface *glSurface = &m_bufferPool.glSurfaces[source];
++
++ if (glSurface->transferred)
++ return;
++
++ glSurface->transferred = true;
++
++ // transfer surface
++ XVBA_Transfer_Surface_Input transInput;
++ transInput.size = sizeof(transInput);
++ transInput.session = m_config.xvbaSession;
++ transInput.src_surface = glSurface->render->surface;
++ transInput.target_surface = glSurface->glSurface;
++ transInput.flag = glSurface->field;
++ { CSingleLock lock(*(m_config.apiSec));
++ if (Success != g_XVBA_vtable.TransferSurface(&transInput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
++ m_xvbaError = true;
++ return;
++ }
++ }
++}
++
++CXvbaRenderPicture* COutput::ProcessPicture()
++{
++ CXvbaRenderPicture *retPic = 0;
++
++ if (m_deintStep == 1)
++ {
++ if(m_field == XVBA_TOP_FIELD)
++ m_field = XVBA_BOTTOM_FIELD;
++ else
++ m_field = XVBA_TOP_FIELD;
++ }
++
++ // find unused shared surface
++ unsigned int idx = FindFreeSurface();
++ XvbaBufferPool::GLVideoSurface *glSurface = &m_bufferPool.glSurfaces[idx];
++ glSurface->used = true;
++ glSurface->field = m_field;
++ glSurface->render = m_processPicture.render;
++ glSurface->transferred = false;
++
++ int cmd = 0;
++ m_config.stats->GetCmd(cmd);
++
++// if (!(cmd & DVP_FLAG_SKIP_PROC))
++// {
++ // transfer surface
++ XVBA_Transfer_Surface_Input transInput;
++ transInput.size = sizeof(transInput);
++ transInput.session = m_config.xvbaSession;
++ transInput.src_surface = m_processPicture.render->surface;
++ transInput.target_surface = glSurface->glSurface;
++ transInput.flag = m_field;
++ { CSingleLock lock(*(m_config.apiSec));
++ if (Success != g_XVBA_vtable.TransferSurface(&transInput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface");
++ m_xvbaError = true;
++ return retPic;
++ }
++ }
++
++ // make sure that transfer is completed
++// uint64_t maxTimeout = 1000000000LL;
++// GLsync ReadyFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
++// glClientWaitSync(ReadyFence, GL_SYNC_FLUSH_COMMANDS_BIT, maxTimeout);
++// glDeleteSync(ReadyFence);
++// glFinish();GL_SYNC_FLUSH_COMMANDS_BIT
++// }
++// else
++// {
++// CLog::Log(LOGDEBUG,"XVBA::ProcessPicture - skipped transfer surface");
++// m_processPicture.DVDPic.iFlags |= DVP_FLAG_DROPPED;
++// }
++
++ // prepare render pic
++ retPic = m_bufferPool.freeRenderPics.front();
++ m_bufferPool.freeRenderPics.pop_front();
++ m_bufferPool.usedRenderPics.push_back(retPic);
++ retPic->sourceIdx = glSurface->id;
++ retPic->DVDPic = m_processPicture.DVDPic;
++ retPic->valid = true;
++ retPic->texture = glSurface->texture;
++ retPic->crop = CRect(0,0,0,0);
++ retPic->texWidth = m_config.surfaceWidth;
++ retPic->texHeight = m_config.surfaceHeight;
++ retPic->xvbaOutput = this;
++
++ // set repeat pic for de-interlacing
++ if (m_deinterlacing)
++ {
++ if (m_deintStep == 1)
++ {
++ retPic->DVDPic.pts = DVD_NOPTS_VALUE;
++ retPic->DVDPic.dts = DVD_NOPTS_VALUE;
++ }
++ retPic->DVDPic.iRepeatPicture = 0.0;
++ }
++
++ return retPic;
++}
++
++void COutput::ProcessReturnPicture(CXvbaRenderPicture *pic)
++{
++ std::deque::iterator it;
++ it = std::find(m_bufferPool.usedRenderPics.begin(), m_bufferPool.usedRenderPics.end(), pic);
++ if (it == m_bufferPool.usedRenderPics.end())
++ {
++ CLog::Log(LOGWARNING, "COutput::ProcessReturnPicture - pic not found");
++ return;
++ }
++ m_bufferPool.usedRenderPics.erase(it);
++ m_bufferPool.freeRenderPics.push_back(pic);
++ if (!pic->valid)
++ {
++ CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__);
++ return;
++ }
++
++ if (m_config.useSharedSurfaces)
++ {
++ xvba_render_state *render = m_bufferPool.glSurfaces[pic->sourceIdx].render;
++ if (render)
++ {
++ // check if video surface if referenced by other glSurfaces
++ bool referenced(false);
++ for (unsigned int i=0; isourceIdx)
++ continue;
++ if (m_bufferPool.glSurfaces[i].render == render)
++ {
++ referenced = true;
++ break;
++ }
++ }
++ if (m_processPicture.render == render)
++ referenced = true;
++
++ // release video surface
++ if (!referenced)
++ {
++ CSingleLock lock(*m_config.videoSurfaceSec);
++ render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
++ }
++
++ // unreference video surface
++ m_bufferPool.glSurfaces[pic->sourceIdx].render = 0;
++ }
++ m_bufferPool.glSurfaces[pic->sourceIdx].used = false;
++ return;
++ }
++}
++
++int COutput::FindFreeSurface()
++{
++ // find free shared surface
++ unsigned int i;
++ for (i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
++ {
++ if (!m_bufferPool.glSurfaces[i].used)
++ break;
++ }
++ if (i == m_bufferPool.glSurfaces.size())
++ return -1;
++ else
++ return i;
++}
++
++void COutput::InitCycle()
++{
++ uint64_t latency;
++ int speed;
++ m_config.stats->GetParams(latency, speed);
++ latency = (latency*1000)/CurrentHostFrequency();
++
++ m_config.stats->SetCanSkipDeint(false);
++
++ EDEINTERLACEMODE mode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
++ EINTERLACEMETHOD method = g_settings.m_currentVideoSettings.m_InterlaceMethod;
++ bool interlaced = m_processPicture.DVDPic.iFlags & DVP_FLAG_INTERLACED;
++
++ if (mode == VS_DEINTERLACEMODE_FORCE ||
++ (mode == VS_DEINTERLACEMODE_AUTO && interlaced))
++ {
++ if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
++ || method == VS_INTERLACEMETHOD_XVBA)
++ {
++ m_deinterlacing = true;
++ m_deintSkip = false;
++ m_config.stats->SetCanSkipDeint(true);
++
++ if (m_processPicture.DVDPic.iFlags & DVP_FLAG_DROPDEINT)
++ {
++ m_deintSkip = true;
++ }
++
++ // do only half deinterlacing
++ if (speed != DVD_PLAYSPEED_NORMAL || !g_graphicsContext.IsFullScreenVideo())
++ {
++ m_config.stats->SetCanSkipDeint(false);
++ m_deintSkip = true;
++ }
++
++ if(m_processPicture.DVDPic.iFlags & DVP_FLAG_TOP_FIELD_FIRST)
++ m_field = XVBA_TOP_FIELD;
++ else
++ m_field = XVBA_BOTTOM_FIELD;
++ }
++ }
++ else
++ {
++ m_deinterlacing = false;
++ m_field = XVBA_FRAME;
++ }
++
++ m_processPicture.DVDPic.format = DVDVideoPicture::FMT_XVBA;
++ m_processPicture.DVDPic.iFlags &= ~(DVP_FLAG_TOP_FIELD_FIRST |
++ DVP_FLAG_REPEAT_TOP_FIELD |
++ DVP_FLAG_INTERLACED);
++ m_processPicture.DVDPic.iWidth = m_config.vidWidth;
++ m_processPicture.DVDPic.iHeight = m_config.vidHeight;
++
++ m_deintStep = 0;
++}
++
++void COutput::FiniCycle()
++{
++// { CSingleLock lock(*m_config.videoSurfaceSec);
++// m_processPicture.render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER;
++// }
++ m_processPicture.render = 0;
++ m_config.stats->DecDecoded();
++}
++
++bool COutput::EnsureBufferPool()
++{
++ if (m_config.useSharedSurfaces && m_bufferPool.glSurfaces.empty())
++ {
++ GLenum textureTarget;
++ if (!glewIsSupported("GL_ARB_texture_non_power_of_two") && glewIsSupported("GL_ARB_texture_rectangle"))
++ {
++ textureTarget = GL_TEXTURE_RECTANGLE_ARB;
++ }
++ else
++ textureTarget = GL_TEXTURE_2D;
++
++ // create shared surfaces
++ XvbaBufferPool::GLVideoSurface surface;
++ for (unsigned int i = 0; i < NUM_RENDER_PICS; ++i)
++ {
++ glEnable(textureTarget);
++ glGenTextures(1, &surface.texture);
++ glBindTexture(textureTarget, surface.texture);
++ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
++ glTexImage2D(textureTarget, 0, GL_RGBA, m_config.surfaceWidth, m_config.surfaceHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
++
++ XVBA_Create_GLShared_Surface_Input surfInput;
++ XVBA_Create_GLShared_Surface_Output surfOutput;
++ surfInput.size = sizeof(surfInput);
++ surfInput.session = m_config.xvbaSession;
++ surfInput.gltexture = surface.texture;
++ surfInput.glcontext = m_glContext;
++ surfOutput.size = sizeof(surfOutput);
++ surfOutput.surface = 0;
++ if (Success != g_XVBA_vtable.CreateGLSharedSurface(&surfInput, &surfOutput))
++ {
++ CLog::Log(LOGERROR,"(XVBA) failed to create shared surface");
++ m_xvbaError = true;
++ break;
++ }
++ CLog::Log(LOGDEBUG, "XVBA::GetTexture - created shared surface");
++
++ surface.glSurface = surfOutput.surface;
++ surface.id = i;
++ surface.used = false;
++ surface.render = 0;
++ m_bufferPool.glSurfaces.push_back(surface);
++ }
++ glDisable(textureTarget);
++ }
++
++ return true;
++}
++
++void COutput::ReleaseBufferPool()
++{
++ CSingleLock lock(m_bufferPool.renderPicSec);
++
++ if (m_config.useSharedSurfaces)
++ {
++ for (unsigned int i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
++ {
++ if (!m_bufferPool.glSurfaces[i].glSurface)
++ continue;
++ g_XVBA_vtable.DestroySurface(m_bufferPool.glSurfaces[i].glSurface);
++ glDeleteTextures(1, &m_bufferPool.glSurfaces[i].texture);
++ }
++ m_bufferPool.glSurfaces.clear();
++ }
++ // invalidate all used render pictures
++ for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
++ {
++ m_bufferPool.usedRenderPics[i]->valid = false;
++ unsigned int idx = m_bufferPool.usedRenderPics[i]->sourceIdx;
++ if (m_bufferPool.glSurfaces[idx].render)
++ {
++ { CSingleLock lock(*m_config.videoSurfaceSec);
++ m_bufferPool.glSurfaces[idx].render->state &= ~(FF_XVBA_STATE_USED_FOR_RENDER | FF_XVBA_STATE_DECODED);
++ m_bufferPool.glSurfaces[idx].render = 0;
++ }
++ }
++ }
++}
++
++void COutput::PreReleaseBufferPool()
++{
++ CSingleLock lock(m_bufferPool.renderPicSec);
++
++ if (m_config.useSharedSurfaces)
++ {
++ for (unsigned int i = 0; i < m_bufferPool.glSurfaces.size(); ++i)
++ {
++ if (!m_bufferPool.glSurfaces[i].used)
++ {
++ g_XVBA_vtable.DestroySurface(m_bufferPool.glSurfaces[i].glSurface);
++ glDeleteTextures(1, &m_bufferPool.glSurfaces[i].texture);
++ m_bufferPool.glSurfaces[i].glSurface = 0;
++ m_bufferPool.glSurfaces[i].used = true;
++ }
++ }
++ }
++}
++
++bool COutput::CreateGlxContext()
++{
++ GLXContext glContext;
++ Window window;
++
++ m_Display = g_Windowing.GetDisplay();
++ glContext = g_Windowing.GetGlxContext();
++ m_Window = g_Windowing.GetWmWindow();
++
++ // Get our window attribs.
++ XWindowAttributes wndattribs;
++ XGetWindowAttributes(m_Display, m_Window, &wndattribs);
++
++ // Get visual Info
++ XVisualInfo visInfo;
++ visInfo.visualid = wndattribs.visual->visualid;
++ int nvisuals = 0;
++ XVisualInfo* visuals = XGetVisualInfo(m_Display, VisualIDMask, &visInfo, &nvisuals);
++ if (nvisuals != 1)
++ {
++ CLog::Log(LOGERROR, "XVBA::COutput::CreateGlxContext - could not find visual");
++ return false;
++ }
++ visInfo = visuals[0];
++ XFree(visuals);
++
++ m_pixmap = XCreatePixmap(m_Display,
++ DefaultRootWindow(m_Display),
++ 192,
++ 108,
++ visInfo.depth);
++ if (!m_pixmap)
++ {
++ CLog::Log(LOGERROR, "XVBA::COutput::CreateGlxContext - Unable to create XPixmap");
++ return false;
++ }
++
++ // create gl pixmap
++ m_glPixmap = glXCreateGLXPixmap(m_Display, &visInfo, m_pixmap);
++
++ if (!m_glPixmap)
++ {
++ CLog::Log(LOGINFO, "XVBA::COutput::CreateGlxContext - Could not create glPixmap");
++ return false;
++ }
++
++ m_glContext = glXCreateContext(m_Display, &visInfo, glContext, True);
++
++ if (!glXMakeCurrent(m_Display, m_glPixmap, m_glContext))
++ {
++ CLog::Log(LOGINFO, "XVBA::COutput::CreateGlxContext - Could not make Pixmap current");
++ return false;
++ }
++
++ CLog::Log(LOGNOTICE, "XVBA::COutput::CreateGlxContext - created context");
++ return true;
++}
++
++bool COutput::DestroyGlxContext()
++{
++ if (m_glContext)
++ {
++ glXMakeCurrent(m_Display, None, NULL);
++ glXDestroyContext(m_Display, m_glContext);
++ }
++ m_glContext = 0;
++
++ if (m_glPixmap)
++ glXDestroyPixmap(m_Display, m_glPixmap);
++ m_glPixmap = 0;
++
++ if (m_pixmap)
++ XFreePixmap(m_Display, m_pixmap);
++ m_pixmap = 0;
++
++ return true;
++}
++
++#endif
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h 2012-05-13 22:08:47.053195007 +0200
+@@ -0,0 +1,386 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++#pragma once
++
++#include "X11/Xlib.h"
++#include "amd/amdxvba.h"
++#include "DllAvCodec.h"
++#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h"
++#include "threads/Thread.h"
++#include "threads/CriticalSection.h"
++#include "threads/SharedSection.h"
++#include "threads/Event.h"
++#include "guilib/DispResource.h"
++#include "guilib/Geometry.h"
++#include "libavcodec/xvba.h"
++#include "utils/ActorProtocol.h"
++#include "settings/VideoSettings.h"
++#include
++#include
++#include
++#include
++
++using namespace Actor;
++
++
++namespace XVBA
++{
++
++//-----------------------------------------------------------------------------
++// XVBA data structs
++//-----------------------------------------------------------------------------
++
++class CDecoder;
++class CXVBAContext;
++class COutput;
++
++#define NUM_RENDER_PICS 9
++
++/**
++ * Buffer statistics used to control number of frames in queue
++ */
++
++class CXvbaBufferStats
++{
++public:
++ uint16_t decodedPics;
++ uint16_t processedPics;
++ uint16_t renderPics;
++ uint64_t latency; // time decoder has waited for a frame, ideally there is no latency
++ int playSpeed;
++ bool canSkipDeint;
++ int processCmd;
++
++ void IncDecoded() { CSingleLock l(m_sec); decodedPics++;}
++ void DecDecoded() { CSingleLock l(m_sec); decodedPics--;}
++ void IncProcessed() { CSingleLock l(m_sec); processedPics++;}
++ void DecProcessed() { CSingleLock l(m_sec); processedPics--;}
++ void IncRender() { CSingleLock l(m_sec); renderPics++;}
++ void DecRender() { CSingleLock l(m_sec); renderPics--;}
++ void Reset() { CSingleLock l(m_sec); decodedPics=0; processedPics=0;renderPics=0;latency=0;}
++ void Get(uint16_t &decoded, uint16_t &processed, uint16_t &render) {CSingleLock l(m_sec); decoded = decodedPics, processed=processedPics, render=renderPics;}
++ void SetParams(uint64_t time, int speed) { CSingleLock l(m_sec); latency = time; playSpeed = speed; }
++ void GetParams(uint64_t &lat, int &speed) { CSingleLock l(m_sec); lat = latency; speed = playSpeed; }
++ void SetCmd(int cmd) { CSingleLock l(m_sec); processCmd = cmd; }
++ void GetCmd(int &cmd) { CSingleLock l(m_sec); cmd = processCmd; processCmd = 0; }
++ void SetCanSkipDeint(bool canSkip) { CSingleLock l(m_sec); canSkipDeint = canSkip; }
++ bool CanSkipDeint() { CSingleLock l(m_sec); if (canSkipDeint) return true; else return false;}
++private:
++ CCriticalSection m_sec;
++};
++
++/**
++ * CXvbaConfig holds all configuration parameters needed by vdpau
++ * The structure is sent to the internal classes CMixer and COutput
++ * for init.
++ */
++
++struct CXvbaConfig
++{
++ int surfaceWidth;
++ int surfaceHeight;
++ int vidWidth;
++ int vidHeight;
++ int outWidth;
++ int outHeight;
++ bool useSharedSurfaces;
++
++ CXVBAContext *context;
++ XVBADecodeCap decoderCap;
++ void *xvbaSession;
++ std::vector *videoSurfaces;
++ CCriticalSection *videoSurfaceSec;
++ CCriticalSection *apiSec;
++
++ CXvbaBufferStats *stats;
++ int numRenderBuffers;
++ uint32_t maxReferences;
++};
++
++/**
++ * Holds a decoded frame
++ * Input to COutput for further processing
++ */
++struct CXvbaDecodedPicture
++{
++ DVDVideoPicture DVDPic;
++ xvba_render_state *render;
++};
++
++/**
++ * Ready to render textures
++ * Sent from COutput back to CDecoder
++ * Objects are referenced by DVDVideoPicture and are sent
++ * to renderer
++ */
++class CXvbaRenderPicture
++{
++ friend class CDecoder;
++ friend class COutput;
++public:
++ DVDVideoPicture DVDPic;
++ int texWidth, texHeight;
++ CRect crop;
++ GLuint texture;
++ uint32_t sourceIdx;
++ bool valid;
++ CDecoder *xvba;
++ CXvbaRenderPicture* Acquire();
++ long Release();
++ void Transfer();
++private:
++ void ReturnUnused();
++ int refCount;
++ CCriticalSection *renderPicSection;
++ COutput *xvbaOutput;
++};
++
++//-----------------------------------------------------------------------------
++// Output
++//-----------------------------------------------------------------------------
++
++/**
++ * Buffer pool holds allocated xvba and gl resources
++ * Embedded in COutput
++ */
++struct XvbaBufferPool
++{
++ struct GLVideoSurface
++ {
++ unsigned int id;
++ bool used;
++ bool transferred;
++ GLuint texture;
++ void *glSurface;
++ xvba_render_state *render;
++ XVBA_SURFACE_FLAG field;
++ };
++ std::vector glSurfaces;
++ std::vector allRenderPics;
++ std::deque usedRenderPics;
++ std::deque freeRenderPics;
++ CCriticalSection renderPicSec;
++};
++
++class COutputControlProtocol : public Protocol
++{
++public:
++ COutputControlProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
++ enum OutSignal
++ {
++ INIT,
++ FLUSH,
++ PRECLEANUP,
++ TIMEOUT,
++ };
++ enum InSignal
++ {
++ ACC,
++ ERROR,
++ STATS,
++ };
++};
++
++class COutputDataProtocol : public Protocol
++{
++public:
++ COutputDataProtocol(std::string name, CEvent* inEvent, CEvent *outEvent) : Protocol(name, inEvent, outEvent) {};
++ enum OutSignal
++ {
++ NEWFRAME = 0,
++ RETURNPIC,
++ };
++ enum InSignal
++ {
++ PICTURE,
++ };
++};
++
++/**
++ * COutput is embedded in CDecoder and embeds CMixer
++ * The class has its own OpenGl context which is shared with render thread
++ * COuput generated ready to render textures and passes them back to
++ * CDecoder
++ */
++class COutput : private CThread
++{
++public:
++ COutput(CEvent *inMsgEvent);
++ virtual ~COutput();
++ void Start();
++ void Dispose();
++ void TransferSurface(uint32_t source);
++ COutputControlProtocol m_controlPort;
++ COutputDataProtocol m_dataPort;
++protected:
++ void OnStartup();
++ void OnExit();
++ void Process();
++ void StateMachine(int signal, Protocol *port, Message *msg);
++ bool HasWork();
++ bool IsDecodingFinished();
++ CXvbaRenderPicture* ProcessPicture();
++ void ProcessReturnPicture(CXvbaRenderPicture *pic);
++ int FindFreeSurface();
++ void InitCycle();
++ void FiniCycle();
++ bool Init();
++ bool Uninit();
++ void Flush();
++ bool CreateGlxContext();
++ bool DestroyGlxContext();
++ bool EnsureBufferPool();
++ void ReleaseBufferPool();
++ void PreReleaseBufferPool();
++ CEvent m_outMsgEvent;
++ CEvent *m_inMsgEvent;
++ int m_state;
++ bool m_bStateMachineSelfTrigger;
++
++ // extended state variables for state machine
++ int m_extTimeout;
++ bool m_xvbaError;
++ CXvbaConfig m_config;
++ XvbaBufferPool m_bufferPool;
++ Display *m_Display;
++ Window m_Window;
++ GLXContext m_glContext;
++ GLXWindow m_glWindow;
++ Pixmap m_pixmap;
++ GLXPixmap m_glPixmap;
++ std::queue m_decodedPics;
++ CXvbaDecodedPicture m_processPicture;
++ XVBA_SURFACE_FLAG m_field;
++ bool m_deinterlacing;
++ int m_deintStep;
++ bool m_deintSkip;
++};
++
++//-----------------------------------------------------------------------------
++// XVBA decoder
++//-----------------------------------------------------------------------------
++
++class CXVBAContext
++{
++public:
++ static bool EnsureContext(CXVBAContext **ctx);
++ void *GetContext();
++ void Release();
++private:
++ CXVBAContext();
++ void Close();
++ bool LoadSymbols();
++ bool CreateContext();
++ void DestroyContext();
++ static CXVBAContext *m_context;
++ static CCriticalSection m_section;
++ static Display *m_display;
++ int m_refCount;
++ static void *m_dlHandle;
++ void *m_xvbaContext;
++};
++
++class CDecoder : public CDVDVideoCodecFFmpeg::IHardwareDecoder,
++ public IDispResource
++{
++ friend class CXvbaRenderPicture;
++
++public:
++
++ struct pictureAge
++ {
++ int b_age;
++ int ip_age[2];
++ };
++
++ enum EDisplayState
++ { XVBA_OPEN
++ , XVBA_RESET
++ , XVBA_LOST
++ , XVBA_ERROR
++ };
++
++ CDecoder();
++ virtual ~CDecoder();
++ virtual void OnLostDevice();
++ virtual void OnResetDevice();
++
++ virtual bool Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces = 0);
++ virtual int Decode (AVCodecContext* avctx, AVFrame* frame);
++ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture);
++ virtual void Reset();
++ virtual void Close();
++ virtual int Check(AVCodecContext* avctx);
++ virtual long Release();
++ virtual const std::string Name() { return "xvba"; }
++ virtual bool CanSkipDeint();
++ virtual void SetSpeed(int speed);
++
++ bool Supports(EINTERLACEMETHOD method);
++ long ReleasePicReference();
++
++protected:
++ bool CreateSession(AVCodecContext* avctx);
++ void DestroySession();
++ bool EnsureDataControlBuffers(unsigned int num);
++ void ResetState();
++ void SetError(const char* function, const char* msg, int line);
++ bool IsSurfaceValid(xvba_render_state *render);
++ void ReturnRenderPicture(CXvbaRenderPicture *renderPic);
++
++ // callbacks for ffmpeg
++ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic);
++ static void FFDrawSlice(struct AVCodecContext *avctx,
++ const AVFrame *src, int offset[4],
++ int y, int type, int height);
++ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic);
++
++ DllAvUtil m_dllAvUtil;
++ CCriticalSection m_decoderSection;
++ CEvent m_displayEvent;
++ EDisplayState m_displayState;
++ CXvbaConfig m_xvbaConfig;
++ std::vector m_videoSurfaces;
++ CCriticalSection m_apiSec, m_videoSurfaceSec;
++ ThreadIdentifier m_decoderThread;
++
++ unsigned int m_decoderId;
++ struct XVBABufferPool
++ {
++ XVBABufferDescriptor *picture_descriptor_buffer;
++ XVBABufferDescriptor *iq_matrix_buffer;
++ XVBABufferDescriptor *data_buffer;
++ std::vector data_control_buffers;
++ };
++ XVBABufferPool m_xvbaBufferPool;
++
++ pictureAge picAge;
++
++ COutput m_xvbaOutput;
++ CXvbaBufferStats m_bufferStats;
++ CEvent m_inMsgEvent;
++ CXvbaRenderPicture *m_presentPicture;
++
++ int m_speed;
++ int m_codecControl;
++};
++
++}
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2012-05-13 22:08:46.782189631 +0200
+@@ -19,7 +19,6 @@
+ *
+ */
+
+-#include "threads/SystemClock.h"
+ #include "system.h"
+ #ifndef __STDC_CONSTANT_MACROS
+ #define __STDC_CONSTANT_MACROS
+@@ -43,6 +42,7 @@
+ #include "filesystem/Directory.h"
+ #include "utils/log.h"
+ #include "threads/Thread.h"
++#include "threads/SystemClock.h"
+ #include "utils/TimeUtils.h"
+
+ void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo)
+@@ -153,16 +153,12 @@
+ ++it;
+ }
+
+-#ifdef _MSC_VER
+-static __declspec(thread) CDVDDemuxFFmpeg* g_demuxer = 0;
+-#else
+-static TLS g_tls;
+-#define g_demuxer (*((CDVDDemuxFFmpeg**)g_tls.Get()))
+-#endif
++static XbmcThreads::ThreadLocal g_demuxer;
+
+ static int interrupt_cb(void)
+ {
+- if(g_demuxer && g_demuxer->Aborted())
++ CDVDDemuxFFmpeg* demuxer = g_demuxer.get();
++ if(demuxer && demuxer->Aborted())
+ return 1;
+ return 0;
+ }
+@@ -234,7 +230,7 @@
+ std::string strFile;
+ m_iCurrentPts = DVD_NOPTS_VALUE;
+ m_speed = DVD_PLAYSPEED_NORMAL;
+- g_demuxer = this;
++ g_demuxer.set(this);
+ m_program = UINT_MAX;
+
+ if (!pInput) return false;
+@@ -506,7 +502,7 @@
+
+ void CDVDDemuxFFmpeg::Dispose()
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ if (m_pFormatContext)
+ {
+@@ -555,7 +551,7 @@
+
+ void CDVDDemuxFFmpeg::Flush()
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ // naughty usage of an internal ffmpeg function
+ if (m_pFormatContext)
+@@ -571,7 +567,7 @@
+
+ void CDVDDemuxFFmpeg::SetSpeed(int iSpeed)
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ if(!m_pFormatContext)
+ return;
+@@ -633,7 +629,7 @@
+
+ DemuxPacket* CDVDDemuxFFmpeg::Read()
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ AVPacket pkt;
+ DemuxPacket* pPacket = NULL;
+@@ -832,7 +828,7 @@
+
+ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ if(time < 0)
+ time = 0;
+@@ -892,7 +888,7 @@
+
+ bool CDVDDemuxFFmpeg::SeekByte(__int64 pos)
+ {
+- g_demuxer = this;
++ g_demuxer.set(this);
+
+ CSingleLock lock(m_critSection);
+ int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE);
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp 2012-05-13 22:08:46.782189631 +0200
+@@ -21,6 +21,7 @@
+
+ #include "DVDPerformanceCounter.h"
+ #include "DVDMessageQueue.h"
++#include "utils/TimeUtils.h"
+
+ #include "dvd_config.h"
+
+@@ -68,22 +69,16 @@
+
+ inline __int64 get_thread_cpu_usage(ProcessPerformance* p)
+ {
+- if (p->hThread)
++ if (p->thread)
+ {
+- FILETIME dummy;
+- FILETIME current_time_thread;
+- FILETIME current_time_system;
+ ULARGE_INTEGER old_time_thread;
+ ULARGE_INTEGER old_time_system;
+
+ old_time_thread.QuadPart = p->timer_thread.QuadPart;
+ old_time_system.QuadPart = p->timer_system.QuadPart;
+
+- GetThreadTimes(p->hThread, &dummy, &dummy, ¤t_time_thread, &dummy);
+- GetSystemTimeAsFileTime(¤t_time_system);
+-
+- FILETIME_TO_ULARGE_INTEGER(p->timer_thread, current_time_thread);
+- FILETIME_TO_ULARGE_INTEGER(p->timer_system, current_time_system);
++ p->timer_thread.QuadPart = p->thread->GetAbsoluteUsage();
++ p->timer_system.QuadPart = CurrentHostCounter();
+
+ __int64 threadTime = (p->timer_thread.QuadPart - old_time_thread.QuadPart);
+ __int64 systemTime = (p->timer_system.QuadPart - old_time_system.QuadPart);
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPerformanceCounter.h xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.h
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPerformanceCounter.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.h 2012-05-13 22:08:46.783189651 +0200
+@@ -24,7 +24,7 @@
+ #define FILETIME_TO_ULARGE_INTEGER(ularge, filetime) { ularge.u.HighPart = filetime.dwHighDateTime; ularge.u.LowPart = filetime.dwLowDateTime; }
+
+ #include "system.h"
+-
++#include "threads/Thread.h"
+ #include "threads/SingleLock.h"
+
+ class CDVDMessageQueue;
+@@ -33,7 +33,7 @@
+ {
+ ULARGE_INTEGER timer_thread;
+ ULARGE_INTEGER timer_system;
+- HANDLE hThread;
++ CThread* thread;
+ } ProcessPerformance;
+
+ class CDVDPerformanceCounter
+@@ -45,20 +45,20 @@
+ bool Initialize();
+ void DeInitialize();
+
+- void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; }
+- void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; }
++ void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; }
++ void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; }
+
+- void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; }
+- void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; }
++ void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; }
++ void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; }
+
+- void EnableVideoDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = hThread; }
+- void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = NULL; }
++ void EnableVideoDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = thread; }
++ void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = NULL; }
+
+- void EnableAudioDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = hThread; }
+- void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = NULL; }
++ void EnableAudioDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = thread; }
++ void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = NULL; }
+
+- void EnableMainPerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_mainPerformance.hThread = hThread; }
+- void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.hThread = NULL; }
++ void EnableMainPerformance(CThread *thread) { CSingleLock lock(m_critSection); m_mainPerformance.thread = thread; }
++ void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.thread = NULL; }
+
+ CDVDMessageQueue* m_pAudioQueue;
+ CDVDMessageQueue* m_pVideoQueue;
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp 2012-05-13 22:08:46.786189710 +0200
+@@ -518,7 +518,7 @@
+ m_decode.msg = NULL;
+ m_decode.Release();
+
+- g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle());
++ g_dvdPerformanceCounter.EnableAudioDecodePerformance(this);
+
+ #ifdef _WIN32
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayer.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayer.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayer.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayer.cpp 2012-05-13 22:08:46.897191913 +0200
+@@ -341,7 +341,7 @@
+
+ // if playing a file close it first
+ // this has to be changed so we won't have to close it.
+- if(ThreadHandle())
++ if(IsRunning())
+ CloseFile();
+
+ m_bAbortRequest = false;
+@@ -358,7 +358,7 @@
+ m_ready.Reset();
+
+ #if defined(HAS_VIDEO_PLAYBACK)
+- g_renderManager.PreInit();
++ g_renderManager.PreInit(&m_clock);
+ #endif
+
+ Create();
+@@ -432,9 +432,8 @@
+
+ m_messenger.Init();
+
+- g_dvdPerformanceCounter.EnableMainPerformance(ThreadHandle());
+-
+ CUtil::ClearTempFonts();
++ g_dvdPerformanceCounter.EnableMainPerformance(this);
+ }
+
+ bool CDVDPlayer::OpenInputStream()
+@@ -1457,7 +1456,7 @@
+
+ }
+ else if (m_CurrentVideo.id >= 0
+- && m_CurrentVideo.inited == true
++ && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0)
+ && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts()
+ && m_SpeedState.lasttime != GetTime())
+ {
+@@ -2127,6 +2126,11 @@
+ if (speed != DVD_PLAYSPEED_PAUSE && m_playSpeed != DVD_PLAYSPEED_PAUSE && speed != m_playSpeed)
+ m_callback.OnPlayBackSpeedChanged(speed / DVD_PLAYSPEED_NORMAL);
+
++ if (m_playSpeed < 0 && speed >= 0)
++ {
++ m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true));
++ }
++
+ // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE
+ // audioplayer, stops outputing audio to audiorendere, but still tries to
+ // sleep an correct amount for each packet
+@@ -2143,6 +2147,7 @@
+ // until our buffers are somewhat filled
+ if(m_pDemuxer)
+ m_pDemuxer->SetSpeed(speed);
++
+ }
+ else if (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_NEXT) ||
+ pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_PREV) ||
+@@ -2716,7 +2721,7 @@
+ m_dvdPlayerAudio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1);
+
+ /* audio normally won't consume full cpu, so let it have prio */
+- m_dvdPlayerAudio.SetPriority(GetThreadPriority(*this)+1);
++ m_dvdPlayerAudio.SetPriority(GetPriority()+1);
+
+ return true;
+ }
+@@ -2781,11 +2786,11 @@
+ // the CoreAudio audio device handler thread. We do the same for
+ // the DVDPlayerVideo thread so it can run to sleep without getting
+ // swapped out by a busy OS.
+- m_dvdPlayerVideo.SetPrioritySched_RR();
++ m_dvdPlayerVideo.SetPriority(GetSchedRRPriority());
+ #else
+ /* use same priority for video thread as demuxing thread, as */
+ /* otherwise demuxer will starve if video consumes the full cpu */
+- m_dvdPlayerVideo.SetPriority(GetThreadPriority(*this));
++ m_dvdPlayerVideo.SetPriority(GetPriority());
+ #endif
+ return true;
+
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2012-05-13 22:08:47.040194749 +0200
+@@ -189,7 +189,7 @@
+ return false;
+ }
+
+- if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && g_VideoReferenceClock.ThreadHandle() == NULL)
++ if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && !g_VideoReferenceClock.IsRunning())
+ {
+ g_VideoReferenceClock.Create();
+ //we have to wait for the clock to start otherwise alsa can cause trouble
+@@ -247,6 +247,7 @@
+ m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0;
+ m_started = false;
+ m_codecname = m_pVideoCodec->GetName();
++ g_renderManager.EnableBuffering(false);
+ }
+
+ void CDVDPlayerVideo::CloseStream(bool bWaitForBuffers)
+@@ -291,7 +292,7 @@
+ m_iCurrentPts = DVD_NOPTS_VALUE;
+ m_FlipTimeStamp = m_pClock->GetAbsoluteClock();
+
+- g_dvdPerformanceCounter.EnableVideoDecodePerformance(ThreadHandle());
++ g_dvdPerformanceCounter.EnableVideoDecodePerformance(this);
+ }
+
+ void CDVDPlayerVideo::Process()
+@@ -311,8 +312,10 @@
+
+ int iDropped = 0; //frames dropped in a row
+ bool bRequestDrop = false;
++ int iDropDirective;
+
+ m_videoStats.Start();
++ m_droppingStats.Reset();
+
+ while (!m_bStop)
+ {
+@@ -414,18 +417,24 @@
+ if(m_pVideoCodec)
+ m_pVideoCodec->Reset();
+ m_packets.clear();
++ picture.iFlags &= ~DVP_FLAG_ALLOCATED;
+ m_started = false;
++ m_droppingStats.Reset();
++ g_renderManager.EnableBuffering(false);
+ }
+ else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush())
+ {
+ if(m_pVideoCodec)
+ m_pVideoCodec->Reset();
+ m_packets.clear();
++ picture.iFlags &= ~DVP_FLAG_ALLOCATED;
+
+ m_pullupCorrection.Flush();
+ //we need to recalculate the framerate
+ //TODO: this needs to be set on a streamchange instead
+ ResetFrameRateCalc();
++ m_droppingStats.Reset();
++ g_renderManager.EnableBuffering(false);
+
+ m_stalled = true;
+ m_started = false;
+@@ -443,6 +452,10 @@
+ m_speed = static_cast(pMsg)->m_value;
+ if(m_speed == DVD_PLAYSPEED_PAUSE)
+ m_iNrOfPicturesNotToSkip = 0;
++ m_droppingStats.Reset();
++// g_renderManager.EnableBuffering(m_speed == DVD_PLAYSPEED_NORMAL);
++ if (m_pVideoCodec)
++ m_pVideoCodec->SetSpeed(m_speed);
+ }
+ else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
+ {
+@@ -477,6 +490,29 @@
+ m_iNrOfPicturesNotToSkip = 1;
+ }
+
++ bRequestDrop = false;
++ iDropDirective = CalcDropRequirement(pts);
++ if (iDropDirective & EOS_VERYLATE)
++ {
++ if (m_bAllowDrop)
++ {
++ m_pullupCorrection.Flush();
++ bRequestDrop = true;
++ }
++ }
++ int codecControl = 0;
++ if (iDropDirective & EOS_BUFFER_LEVEL)
++ {
++ if (iDropDirective & EOS_BUFFER_LEVEL)
++ codecControl |= DVP_FLAG_DRAIN;
++ }
++ m_pVideoCodec->SetCodecControl(codecControl);
++ if (iDropDirective & EOS_DROPPED)
++ {
++ m_iDroppedFrames++;
++ iDropped++;
++ }
++
+ #ifdef PROFILE
+ bRequestDrop = false;
+ #else
+@@ -486,6 +522,7 @@
+ bRequestDrop = false;
+ m_iDroppedRequest = 0;
+ m_iLateFrames = 0;
++ m_droppingStats.m_requestOutputDrop = false;
+ }
+ #endif
+
+@@ -524,7 +561,7 @@
+ if(m_pVideoCodec->GetConvergeCount() > 0)
+ {
+ m_packets.push_back(DVDMessageListItem(pMsg, 0));
+- if(m_packets.size() > m_pVideoCodec->GetConvergeCount()
++ if(m_packets.size() > m_pVideoCodec->GetConvergeCount()
+ || m_packets.size() * frametime > DVD_SEC_TO_TIME(10))
+ m_packets.pop_front();
+ }
+@@ -534,11 +571,13 @@
+ // picture from a demux packet, this should be reasonable
+ // for libavformat as a demuxer as it normally packetizes
+ // pictures when they come from demuxer
+- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE))
+- {
+- m_iDroppedFrames++;
+- iDropped++;
+- }
++// if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE))
++// {
++// m_iDroppedFrames++;
++// iDropped++;
++// }
++
++ bRequestDrop = false;
+
+ // loop while no error
+ while (!m_bStop)
+@@ -561,6 +600,8 @@
+
+ m_pVideoCodec->Reset();
+ m_packets.clear();
++ picture.iFlags &= ~DVP_FLAG_ALLOCATED;
++ g_renderManager.DiscardBuffer();
+ break;
+ }
+
+@@ -670,11 +711,15 @@
+ CDVDCodecUtils::FreePicture(pTempYUVPackedPicture);
+ #endif
+
++ if (!m_bFpsInvalid)
++ frametime = (double)DVD_TIME_BASE/m_fFrameRate;
++
+ if(m_started == false)
+ {
+ m_codecname = m_pVideoCodec->GetName();
+ m_started = true;
+ m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO));
++ g_renderManager.EnableBuffering(true);
+ }
+
+ // guess next frame pts. iDuration is always valid
+@@ -1037,6 +1082,10 @@
+ flags |= CONF_FLAGS_FORMAT_VDPAU;
+ formatstr = "VDPAU";
+ break;
++ case DVDVideoPicture::FMT_VDPAU_420:
++ flags |= CONF_FLAGS_FORMAT_VDPAU_420;
++ formatstr = "VDPAU_420";
++ break;
+ case DVDVideoPicture::FMT_DXVA:
+ flags |= CONF_FLAGS_FORMAT_DXVA;
+ formatstr = "DXVA";
+@@ -1052,6 +1101,10 @@
+ flags |= CONF_FLAGS_FORMAT_CVBREF;
+ formatstr = "BGRA";
+ break;
++ case DVDVideoPicture::FMT_XVBA:
++ flags |= CONF_FLAGS_FORMAT_XVBA;
++ formatstr = "XVBA";
++ break;
+ }
+
+ if(m_bAllowFullscreen)
+@@ -1160,50 +1213,63 @@
+ m_FlipTimeStamp += max(0.0, iSleepTime);
+ m_FlipTimeStamp += iFrameDuration;
+
+- if (iSleepTime <= 0 && m_speed)
+- m_iLateFrames++;
+- else
+- m_iLateFrames = 0;
++// if (iSleepTime <= 0 && m_speed)
++// m_iLateFrames++;
++// else
++// m_iLateFrames = 0;
++//
++// // ask decoder to drop frames next round, as we are very late
++// if(m_iLateFrames > 10)
++// {
++// if (!(pPicture->iFlags & DVP_FLAG_NOSKIP))
++// {
++// //if we're calculating the framerate,
++// //don't drop frames until we've calculated a stable framerate
++// if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL)
++// {
++// result |= EOS_VERYLATE;
++// m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it
++// }
++//
++// //if we requested 5 drops in a row and we're still late, drop on output
++// //this keeps a/v sync if the decoder can't drop, or we're still calculating the framerate
++// if (m_iDroppedRequest > 5)
++// {
++// m_iDroppedRequest--; //decrease so we only drop half the frames
++// return result | EOS_DROPPED;
++// }
++// m_iDroppedRequest++;
++// }
++// }
++// else
++// {
++// m_iDroppedRequest = 0;
++// }
++
++ if ((m_droppingStats.m_requestOutputDrop && !(pPicture->iFlags & DVP_FLAG_NOSKIP))
++ || (pPicture->iFlags & DVP_FLAG_DROPPED))
++ {
++ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate);
++ m_droppingStats.m_requestOutputDrop = false;
++ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__);
++ return result | EOS_DROPPED;
++ }
+
+- // ask decoder to drop frames next round, as we are very late
+- if(m_iLateFrames > 10)
++ if( m_speed < 0 )
+ {
+- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP))
++ double decoderPts = m_droppingStats.m_lastDecoderPts;
++ double renderPts = m_droppingStats.m_lastRenderPts;
++ if (pts > renderPts)
+ {
+- //if we're calculating the framerate,
+- //don't drop frames until we've calculated a stable framerate
+- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL)
++ if (decoderPts >= renderPts)
+ {
+- result |= EOS_VERYLATE;
+- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it
++ Sleep(200);
+ }
+-
+- //if we requested 5 drops in a row and we're still late, drop on output
+- //this keeps a/v sync if the decoder can't drop, or we're still calculating the framerate
+- if (m_iDroppedRequest > 5)
+- {
+- m_iDroppedRequest--; //decrease so we only drop half the frames
+- return result | EOS_DROPPED;
+- }
+- m_iDroppedRequest++;
+- }
+- }
+- else
+- {
+- m_iDroppedRequest = 0;
+- }
+-
+- if( m_speed < 0 )
+- {
+- if( iClockSleep < -DVD_MSEC_TO_TIME(200)
+- && !(pPicture->iFlags & DVP_FLAG_NOSKIP) )
+ return result | EOS_DROPPED;
++ }
+ }
+
+- if( (pPicture->iFlags & DVP_FLAG_DROPPED) )
+- return result | EOS_DROPPED;
+-
+- if( m_speed != DVD_PLAYSPEED_NORMAL && limited )
++ if( m_speed != DVD_PLAYSPEED_NORMAL && m_speed >= 0 && limited )
+ {
+ // calculate frame dropping pattern to render at this speed
+ // we do that by deciding if this or next frame is closest
+@@ -1239,6 +1305,16 @@
+ mDisplayField = FS_BOT;
+ }
+
++ int buffer = g_renderManager.WaitForBuffer(m_bStop);
++ while (buffer < 0 && !CThread::m_bStop &&
++ CDVDClock::GetAbsoluteClock(false) < iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500) )
++ {
++ Sleep(1);
++ buffer = g_renderManager.WaitForBuffer(m_bStop);
++ }
++ if (buffer < 0)
++ return EOS_DROPPED;
++
+ ProcessOverlays(pPicture, pts);
+ AutoCrop(pPicture);
+
+@@ -1255,7 +1331,7 @@
+ if (index < 0)
+ return EOS_DROPPED;
+
+- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField);
++ g_renderManager.FlipPage(CThread::m_bStop, pts, -1, mDisplayField, m_speed);
+
+ return result;
+ #else
+@@ -1269,7 +1345,8 @@
+ if ((pPicture->format == DVDVideoPicture::FMT_YUV420P) ||
+ (pPicture->format == DVDVideoPicture::FMT_NV12) ||
+ (pPicture->format == DVDVideoPicture::FMT_YUY2) ||
+- (pPicture->format == DVDVideoPicture::FMT_UYVY))
++ (pPicture->format == DVDVideoPicture::FMT_UYVY) ||
++ (pPicture->format == DVDVideoPicture::FMT_VDPAU_420))
+ {
+ RECT crop;
+
+@@ -1498,7 +1575,7 @@
+ double frameduration = m_pullupCorrection.GetFrameDuration();
+
+ if (frameduration == DVD_NOPTS_VALUE ||
+- (g_advancedSettings.m_videoFpsDetect == 1 && m_pullupCorrection.GetPatternLength() > 1))
++ (g_advancedSettings.m_videoFpsDetect == 1 && (m_pullupCorrection.GetPatternLength() > 1 && !m_bFpsInvalid)))
+ {
+ //reset the stored framerates if no good framerate was detected
+ m_fStableFrameRate = 0.0;
+@@ -1554,3 +1631,142 @@
+ m_iFrameRateCount = 0;
+ }
+ }
++
++int CDVDPlayerVideo::CalcDropRequirement(double pts)
++{
++ int result = 0;
++ double iSleepTime;
++ double iDecoderPts, iRenderPts;
++ double iInterval;
++ int interlaced;
++ double iGain;
++ double iLateness;
++ bool bNewFrame;
++ int iSkippedDeint = 0;
++ int iBufferLevel;
++
++ // get decoder stats
++ if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced))
++ iDecoderPts = pts;
++
++ // get render stats
++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel);
++
++ if (iBufferLevel < 2)
++ {
++ result |= EOS_BUFFER_LEVEL;
++ if (iBufferLevel < 1)
++ CLog::Log(LOGDEBUG,"--------------------- hurry: %d", iBufferLevel);
++ }
++
++ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts;
++
++ if (interlaced)
++ iInterval = 2/m_fFrameRate*(double)DVD_TIME_BASE;
++ else
++ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE;
++
++ // add any gains regardless of being late
++ if (m_droppingStats.m_lastDecoderPts > 0
++ && bNewFrame
++ && m_bAllowDrop
++ && m_droppingStats.m_dropRequests > 0)
++ {
++ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE;
++ if (iSkippedDeint)
++ {
++ CDroppingStats::CGain gain;
++ gain.gain = 1/m_fFrameRate;
++ gain.pts = iDecoderPts;
++ m_droppingStats.m_gain.push_back(gain);
++ m_droppingStats.m_totalGain += gain.gain;
++ result |= EOS_DROPPED;
++ m_droppingStats.m_dropRequests = 0;
++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped de-interlacing cycle, Sleeptime: %f, Bufferlevel: %d", iSleepTime, iBufferLevel);
++ }
++ else if (iGain > 1/m_fFrameRate)
++ {
++ CDroppingStats::CGain gain;
++ gain.gain = iGain;
++ gain.pts = iDecoderPts;
++ m_droppingStats.m_gain.push_back(gain);
++ m_droppingStats.m_totalGain += iGain;
++ result |= EOS_DROPPED;
++ m_droppingStats.m_dropRequests = 0;
++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain);
++ }
++
++ }
++ m_droppingStats.m_lastDecoderPts = iDecoderPts;
++
++ // subtract gains
++ while (!m_droppingStats.m_gain.empty() &&
++ iRenderPts >= m_droppingStats.m_gain.front().pts)
++ {
++ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain;
++ m_droppingStats.m_gain.pop_front();
++ }
++
++// if (iSleepTime < 0)
++// {
++// CLog::Log(LOGNOTICE,"----- sleep: %f, gain :%f",
++// iSleepTime, m_droppingStats.m_totalGain);
++// }
++
++ // calculate lateness
++ iLateness = iSleepTime + m_droppingStats.m_totalGain;
++ if (iLateness < 0 && m_speed)
++ {
++ if (bNewFrame)
++ m_droppingStats.m_lateFrames++;
++
++ // if lateness is smaller than frametime, we observe this state
++ // for 10 cycles
++ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate)
++ {
++ // is frame allowed to skip
++ if (m_iNrOfPicturesNotToSkip <= 0)
++ {
++ result |= EOS_VERYLATE;
++
++ // drop in output
++ if (m_droppingStats.m_dropRequests > 7 && g_graphicsContext.IsFullScreenVideo())
++ {
++ m_droppingStats.m_dropRequests--; //decrease so we only drop half the frames
++ m_droppingStats.m_requestOutputDrop = true;
++ CLog::Log(LOGNOTICE,"-------- drop output");
++ }
++ else if (bNewFrame)
++ m_droppingStats.m_dropRequests++;
++ }
++ }
++ }
++ else
++ {
++ m_droppingStats.m_dropRequests = 0;
++ m_droppingStats.m_lateFrames = 0;
++ m_droppingStats.m_requestOutputDrop = false;
++ }
++ m_droppingStats.m_lastRenderPts = iRenderPts;
++ return result;
++}
++
++void CDroppingStats::Reset()
++{
++ m_gain.clear();
++ m_totalGain = 0;
++ m_lastDecoderPts = 0;
++ m_lastRenderPts = 0;
++ m_lateFrames = 0;
++ m_dropRequests = 0;
++ m_requestOutputDrop = false;
++}
++
++void CDroppingStats::AddOutputDropGain(double pts, double frametime)
++{
++ CDroppingStats::CGain gain;
++ gain.gain = frametime;
++ gain.pts = pts;
++ m_gain.push_back(gain);
++ m_totalGain += frametime;
++}
+diff -Naur xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayerVideo.h xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.h
+--- xbmc-11.0.1/xbmc/cores/dvdplayer/DVDPlayerVideo.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.h 2012-05-13 22:08:47.047194890 +0200
+@@ -38,6 +38,26 @@
+
+ #define VIDEO_PICTURE_QUEUE_SIZE 1
+
++class CDroppingStats
++{
++public:
++ void Reset();
++ void AddOutputDropGain(double pts, double frametime);
++ struct CGain
++ {
++ double gain;
++ double pts;
++ };
++ std::deque m_gain;
++ double m_totalGain;
++ double m_lastDecoderPts;
++ double m_lastRenderPts;
++ unsigned int m_lateFrames;
++ unsigned int m_dropRequests;
++ bool m_requestOutputDrop;
++};
++
++
+ class CDVDPlayerVideo : public CThread
+ {
+ public:
+@@ -111,6 +131,7 @@
+ #define EOS_ABORT 1
+ #define EOS_DROPPED 2
+ #define EOS_VERYLATE 4
++#define EOS_BUFFER_LEVEL 8
+
+ void AutoCrop(DVDVideoPicture* pPicture);
+ void AutoCrop(DVDVideoPicture *pPicture, RECT &crop);
+@@ -130,9 +151,11 @@
+ int m_iLateFrames;
+ int m_iDroppedFrames;
+ int m_iDroppedRequest;
++ double m_iLastSleepTime;
+
+ void ResetFrameRateCalc();
+ void CalcFrameRate();
++ int CalcDropRequirement(double pts);
+
+ double m_fFrameRate; //framerate of the video currently playing
+ bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps
+@@ -193,5 +216,7 @@
+ CPullupCorrection m_pullupCorrection;
+
+ std::list m_packets;
++
++ CDroppingStats m_droppingStats;
+ };
+
+diff -Naur xbmc-11.0.1/xbmc/cores/paplayer/PAPlayer.cpp xbmc-11.0.1.patch/xbmc/cores/paplayer/PAPlayer.cpp
+--- xbmc-11.0.1/xbmc/cores/paplayer/PAPlayer.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/paplayer/PAPlayer.cpp 2012-05-13 22:08:46.787189730 +0200
+@@ -52,7 +52,7 @@
+ // Supporting all open audio codec standards.
+ // First one being nullsoft's nsv audio decoder format
+
+-PAPlayer::PAPlayer(IPlayerCallback& callback) : IPlayer(callback)
++PAPlayer::PAPlayer(IPlayerCallback& callback) : CThread("PAPlayer"), IPlayer(callback)
+ {
+ m_bIsPlaying = false;
+ m_bPaused = false;
+@@ -168,7 +168,7 @@
+
+ *m_currentFile = file;
+
+- if (ThreadHandle() == NULL)
++ if (!IsRunning())
+ Create();
+
+ m_startEvent.Set();
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp 2012-05-13 22:08:47.060195147 +0200
+@@ -61,6 +61,9 @@
+ VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5)))
+
+ #endif
++#ifdef HAVE_LIBXVBA
++#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h"
++#endif
+
+ #ifdef HAS_GLX
+ #include
+@@ -121,6 +124,9 @@
+ #ifdef HAVE_LIBVDPAU
+ vdpau = NULL;
+ #endif
++#ifdef HAVE_LIBXVBA
++ xvba = NULL;
++#endif
+ }
+
+ CLinuxRendererGL::YUVBUFFER::~YUVBUFFER()
+@@ -224,7 +230,7 @@
+
+ void CLinuxRendererGL::ManageTextures()
+ {
+- m_NumYV12Buffers = 2;
++// m_NumYV12Buffers = NUM_BUFFERS;
+ //m_iYV12RenderBuffer = 0;
+ return;
+ }
+@@ -241,6 +247,11 @@
+ else
+ CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
+
++ // function pointer for texture might change in
++ // call to LoadShaders
++ for (int i = 0 ; i < m_NumYV12Buffers ; i++)
++ (this->*m_textureDelete)(i);
++
+ // create the yuv textures
+ LoadShaders();
+
+@@ -567,6 +578,18 @@
+
+ glFinish();
+ m_bValidated = false;
++ m_iYV12RenderBuffer = 0;
++}
++
++void CLinuxRendererGL::ReleaseBuffer(int idx)
++{
++ YUVBUFFER &buf = m_buffers[idx];
++#ifdef HAVE_LIBVDPAU
++ SAFE_RELEASE(buf.vdpau);
++#endif
++#ifdef HAVE_LIBXVBA
++ SAFE_RELEASE(buf.xvba);
++#endif
+ }
+
+ void CLinuxRendererGL::Update(bool bPauseDrawing)
+@@ -640,6 +663,18 @@
+
+ glDisable(GL_POLYGON_STIPPLE);
+ }
++ else if( CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_VDPAU_420
++ && !(flags & (RENDER_FLAG_TOP | RENDER_FLAG_BOT)))
++ {
++ glDisable(GL_BLEND);
++ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
++ Render(flags | RENDER_FLAG_TOP, index);
++
++ glEnable(GL_BLEND);
++ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
++ glColor4f(1.0f, 1.0f, 1.0f, 128 / 255.0f);
++ Render(flags | RENDER_FLAG_BOT , index);
++ }
+ else
+ Render(flags, index);
+
+@@ -718,11 +753,6 @@
+
+ m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
+
+-#ifdef HAVE_LIBVDPAU
+- if((m_renderMethod & RENDER_VDPAU) && m_buffers[m_iYV12RenderBuffer].vdpau)
+- m_buffers[m_iYV12RenderBuffer].vdpau->Present();
+-#endif
+-
+ return;
+ }
+
+@@ -737,7 +767,6 @@
+ m_resolution = RES_DESKTOP;
+
+ m_iYV12RenderBuffer = 0;
+- m_NumYV12Buffers = 2;
+
+ // setup the background colour
+ m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
+@@ -817,7 +846,7 @@
+ case VS_SCALINGMETHOD_LINEAR:
+ SetTextureFilter(m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR);
+ m_renderQuality = RQ_SINGLEPASS;
+- if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) && m_nonLinStretch)
++ if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch)
+ {
+ m_pVideoFilterShader = new StretchFilterShader();
+ if (!m_pVideoFilterShader->CompileAndLink())
+@@ -898,6 +927,11 @@
+ CLog::Log(LOGNOTICE, "GL: Using VAAPI render method");
+ m_renderMethod = RENDER_VAAPI;
+ }
++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA)
++ {
++ CLog::Log(LOGNOTICE, "GL: Using XVBA render method");
++ m_renderMethod = RENDER_XVBA;
++ }
+ else
+ {
+ int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod");
+@@ -1026,12 +1060,24 @@
+ m_textureCreate = &CLinuxRendererGL::CreateVDPAUTexture;
+ m_textureDelete = &CLinuxRendererGL::DeleteVDPAUTexture;
+ }
++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_VDPAU_420)
++ {
++ m_textureUpload = &CLinuxRendererGL::UploadVDPAUTexture420;
++ m_textureCreate = &CLinuxRendererGL::CreateVDPAUTexture420;
++ m_textureDelete = &CLinuxRendererGL::DeleteVDPAUTexture420;
++ }
+ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_VAAPI)
+ {
+ m_textureUpload = &CLinuxRendererGL::UploadVAAPITexture;
+ m_textureCreate = &CLinuxRendererGL::CreateVAAPITexture;
+ m_textureDelete = &CLinuxRendererGL::DeleteVAAPITexture;
+ }
++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA)
++ {
++ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture;
++ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture;
++ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture;
++ }
+ else
+ {
+ // setup default YV12 texture handlers
+@@ -1132,6 +1178,13 @@
+ RenderVAAPI(renderBuffer, m_currentField);
+ }
+ #endif
++#ifdef HAVE_LIBXVBA
++ else if (m_renderMethod & RENDER_XVBA)
++ {
++ UpdateVideoFilter();
++ RenderXVBA(renderBuffer, m_currentField);
++ }
++#endif
+ else
+ {
+ RenderSoftware(renderBuffer, m_currentField);
+@@ -1434,17 +1487,12 @@
+ void CLinuxRendererGL::RenderVDPAU(int index, int field)
+ {
+ #ifdef HAVE_LIBVDPAU
+- YUVPLANE &plane = m_buffers[index].fields[field][0];
+- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau;
+-
+- if (!vdpau)
+- return;
++ YUVPLANE &plane = m_buffers[index].fields[0][1];
+
+ glEnable(m_textureTarget);
+ glActiveTextureARB(GL_TEXTURE0);
+- glBindTexture(m_textureTarget, plane.id);
+
+- vdpau->BindPixmap();
++ glBindTexture(m_textureTarget, plane.id);
+
+ // Try some clamping or wrapping
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+@@ -1502,8 +1550,6 @@
+ if (m_pVideoFilterShader)
+ m_pVideoFilterShader->Disable();
+
+- vdpau->ReleasePixmap();
+-
+ glBindTexture (m_textureTarget, 0);
+ glDisable(m_textureTarget);
+ #endif
+@@ -1598,6 +1644,77 @@
+ #endif
+ }
+
++void CLinuxRendererGL::RenderXVBA(int index, int field)
++{
++#ifdef HAVE_LIBXVBA
++ YUVPLANE &plane = m_buffers[index].fields[0][1];
++
++ glEnable(m_textureTarget);
++ glActiveTextureARB(GL_TEXTURE0);
++
++ glBindTexture(m_textureTarget, plane.id);
++
++ // Try some clamping or wrapping
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++
++ if (m_pVideoFilterShader)
++ {
++ GLint filter;
++ if (!m_pVideoFilterShader->GetTextureFilter(filter))
++ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
++
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
++ m_pVideoFilterShader->SetSourceTexture(0);
++ m_pVideoFilterShader->SetWidth(m_sourceWidth);
++ m_pVideoFilterShader->SetHeight(m_sourceHeight);
++
++ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer
++ //having non-linear stretch on breaks the alignment
++ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
++ m_pVideoFilterShader->SetNonLinStretch(1.0);
++ else
++ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio));
++
++ m_pVideoFilterShader->Enable();
++ }
++ else
++ {
++ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
++ }
++
++ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
++ VerifyGLState();
++
++ glBegin(GL_QUADS);
++ if (m_textureTarget==GL_TEXTURE_2D)
++ {
++ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1);
++ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1);
++ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2);
++ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2);
++ }
++ else
++ {
++ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f);
++ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f);
++ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f);
++ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f);
++ }
++ glEnd();
++ VerifyGLState();
++
++ if (m_pVideoFilterShader)
++ m_pVideoFilterShader->Disable();
++
++ glBindTexture (m_textureTarget, 0);
++ glDisable(m_textureTarget);
++#endif
++}
++
+ void CLinuxRendererGL::RenderSoftware(int index, int field)
+ {
+ YUVPLANES &planes = m_buffers[index].fields[field];
+@@ -2162,12 +2279,14 @@
+ {
+ #ifdef HAVE_LIBVDPAU
+ YUVPLANE &plane = m_buffers[index].fields[0][0];
++ YUVFIELDS &fields = m_buffers[index].fields;
+
+ SAFE_RELEASE(m_buffers[index].vdpau);
+
+ if(plane.id && glIsTexture(plane.id))
+ glDeleteTextures(1, &plane.id);
+ plane.id = 0;
++ fields[0][1].id = 0;
+ #endif
+ }
+
+@@ -2201,8 +2320,156 @@
+ void CLinuxRendererGL::UploadVDPAUTexture(int index)
+ {
+ #ifdef HAVE_LIBVDPAU
++ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau;
++
++ unsigned int flipindex = m_buffers[index].flipindex;
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &plane = fields[0][0];
++
++ if (!vdpau)
++ {
++ fields[0][1].id = plane.id;
++ m_eventTexturesDone[index]->Set();
++ CLog::Log(LOGWARNING,"--------- no vdpau texture, index: %d", index);
++ return;
++ }
++
++// CLog::Log(LOGNOTICE,"-------- rendered output surf: %d", vdpau->sourceIdx);
++// CLog::Log(LOGNOTICE,"-------- pts: %f", vdpau->DVDPic.pts);
++ fields[0][1].id = vdpau->texture[0];
++
++ m_eventTexturesDone[index]->Set();
++#endif
++}
++
++void CLinuxRendererGL::DeleteVDPAUTexture420(int index)
++{
++#ifdef HAVE_LIBVDPAU
++ YUVPLANE &plane = m_buffers[index].fields[0][0];
++ YUVFIELDS &fields = m_buffers[index].fields;
++
++ SAFE_RELEASE(m_buffers[index].vdpau);
++
++ if(plane.id && glIsTexture(plane.id))
++ glDeleteTextures(1, &plane.id);
++ plane.id = 0;
++ fields[1][0].id = 0;
++ fields[1][1].id = 0;
++ fields[2][0].id = 0;
++ fields[2][1].id = 0;
++
++#endif
++}
++
++bool CLinuxRendererGL::CreateVDPAUTexture420(int index)
++{
++#ifdef HAVE_LIBVDPAU
++ YV12Image &im = m_buffers[index].image;
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &plane = fields[0][0];
++ GLuint *pbo = m_buffers[index].pbo;
++
++ DeleteVDPAUTexture420(index);
++
++ memset(&im , 0, sizeof(im));
++ memset(&fields, 0, sizeof(fields));
++
++ im.cshift_x = 1;
++ im.cshift_y = 1;
++
++ im.plane[0] = NULL;
++ im.plane[1] = NULL;
++ im.plane[2] = NULL;
++
++ for(int p = 0;p<3;p++)
++ {
++ pbo[p] = None;
++ }
++
++ glEnable(m_textureTarget);
++ glGenTextures(1, &plane.id);
++ glDisable(m_textureTarget);
++
++ m_eventTexturesDone[index]->Set();
++#endif
++ return true;
++}
++
++void CLinuxRendererGL::UploadVDPAUTexture420(int index)
++{
++#ifdef HAVE_LIBVDPAU
++ VDPAU::CVdpauRenderPicture *vdpau = m_buffers[index].vdpau;
++ YV12Image &im = m_buffers[index].image;
++
++ unsigned int flipindex = m_buffers[index].flipindex;
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &plane = fields[0][0];
++
++ if (!vdpau)
++ {
++ fields[1][0].id = plane.id;
++ fields[1][1].id = plane.id;
++ fields[2][0].id = plane.id;
++ fields[2][1].id = plane.id;
++ m_eventTexturesDone[index]->Set();
++ return;
++ }
++
++ im.height = vdpau->texHeight;
++ im.width = vdpau->texWidth;
++
++ // YUV
++ for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
++ {
++ int fieldshift = (f==FIELD_FULL) ? 0 : 1;
++ YUVPLANES &planes = fields[f];
++
++ planes[0].texwidth = im.width;
++ planes[0].texheight = im.height >> fieldshift;
++
++ planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
++ planes[1].texheight = planes[0].texheight >> im.cshift_y;
++ planes[2].texwidth = planes[1].texwidth;
++ planes[2].texheight = planes[1].texheight;
++
++ for (int p = 0; p < 3; p++)
++ {
++ planes[p].pixpertex_x = 1;
++ planes[p].pixpertex_y = 1;
++ }
++ }
++ // crop
++// m_sourceRect.x1 += vdpau->crop.x1;
++// m_sourceRect.x2 -= vdpau->crop.x2;
++// m_sourceRect.y1 += vdpau->crop.y1;
++// m_sourceRect.y2 -= vdpau->crop.y2;
++
++ // set textures
++ fields[1][0].id = vdpau->texture[0];
++ fields[1][1].id = vdpau->texture[2];
++ fields[2][0].id = vdpau->texture[1];
++ fields[2][1].id = vdpau->texture[3];
++
++ glEnable(m_textureTarget);
++ for (int f = 1; f < 3; f++)
++ {
++ for (int p=0;p<2;p++)
++ {
++ glBindTexture(m_textureTarget,fields[f][p].id);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++
++ glBindTexture(m_textureTarget,0);
++ VerifyGLState();
++ }
++ fields[f][2].id = fields[f][1].id;
++ }
++ CalculateTextureSourceRects(index, 3);
++ glDisable(m_textureTarget);
++
+ m_eventTexturesDone[index]->Set();
+- glPixelStorei(GL_UNPACK_ALIGNMENT,1); //what's this for?
+ #endif
+ }
+
+@@ -2352,6 +2619,93 @@
+ #endif
+ }
+
++void CLinuxRendererGL::DeleteXVBATexture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ YUVPLANE &plane = m_buffers[index].fields[0][0];
++ YUVFIELDS &fields = m_buffers[index].fields;
++
++ SAFE_RELEASE(m_buffers[index].xvba);
++
++ if(plane.id && glIsTexture(plane.id))
++ glDeleteTextures(1, &plane.id);
++ plane.id = 0;
++ fields[0][1].id = 0;
++#endif
++}
++
++bool CLinuxRendererGL::CreateXVBATexture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ YV12Image &im = m_buffers[index].image;
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &plane = fields[0][0];
++
++ DeleteXVBATexture(index);
++
++ memset(&im , 0, sizeof(im));
++ memset(&fields, 0, sizeof(fields));
++
++ glGenTextures(1, &plane.id);
++
++ m_eventTexturesDone[index]->Set();
++#endif
++ return true;
++}
++
++void CLinuxRendererGL::UploadXVBATexture(int index)
++{
++#ifdef HAVE_LIBXVBA
++ XVBA::CXvbaRenderPicture *xvba = m_buffers[index].xvba;
++ YV12Image &im = m_buffers[index].image;
++
++ YUVFIELDS &fields = m_buffers[index].fields;
++ YUVPLANE &plane = fields[0][1];
++
++ if (!xvba)
++ {
++ fields[0][1].id = fields[0][0].id;
++ m_eventTexturesDone[index]->Set();
++ CLog::Log(LOGWARNING,"CLinuxRendererGL::UploadXVBATexture no xvba texture, index: %d", index);
++ return;
++ }
++// xvba->Transfer();
++
++ fields[0][1].id = xvba->texture;
++
++ im.height = xvba->texHeight;
++ im.width = xvba->texWidth;
++
++ plane.texwidth = xvba->texWidth;
++ plane.texheight = xvba->texHeight;
++ plane.pixpertex_x = 1;
++ plane.pixpertex_y = 1;
++
++ plane.rect = m_sourceRect;
++ plane.width = im.width;
++ plane.height = im.height;
++
++ plane.height /= plane.pixpertex_y;
++ plane.rect.y1 /= plane.pixpertex_y;
++ plane.rect.y2 /= plane.pixpertex_y;
++ plane.width /= plane.pixpertex_x;
++ plane.rect.x1 /= plane.pixpertex_x;
++ plane.rect.x2 /= plane.pixpertex_x;
++
++ if (m_textureTarget == GL_TEXTURE_2D)
++ {
++ plane.height /= plane.texheight;
++ plane.rect.y1 /= plane.texheight;
++ plane.rect.y2 /= plane.texheight;
++ plane.width /= plane.texwidth;
++ plane.rect.x1 /= plane.texwidth;
++ plane.rect.x2 /= plane.texwidth;
++ }
++
++ m_eventTexturesDone[index]->Set();
++#endif
++}
++
+ void CLinuxRendererGL::UploadYUV422PackedTexture(int source)
+ {
+ YUVBUFFER& buf = m_buffers[source];
+@@ -2935,6 +3289,9 @@
+ if (m_renderMethod & RENDER_VAAPI)
+ return false;
+
++ if (m_renderMethod & RENDER_XVBA)
++ return false;
++
+ return (m_renderMethod & RENDER_GLSL)
+ || (m_renderMethod & RENDER_ARB)
+ || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
+@@ -2948,6 +3305,9 @@
+ if (m_renderMethod & RENDER_VAAPI)
+ return false;
+
++ if (m_renderMethod & RENDER_XVBA)
++ return false;
++
+ return (m_renderMethod & RENDER_GLSL)
+ || (m_renderMethod & RENDER_ARB)
+ || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE);
+@@ -2971,7 +3331,8 @@
+ if (feature == RENDERFEATURE_NONLINSTRETCH)
+ {
+ if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) ||
+- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) ||
++ (m_renderMethod & RENDER_XVBA))
+ return true;
+ }
+
+@@ -2998,12 +3359,13 @@
+ if(method == VS_INTERLACEMETHOD_AUTO)
+ return true;
+
+- if(m_renderMethod & RENDER_VDPAU)
++ if(m_renderMethod & RENDER_VDPAU ||
++ CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_VDPAU_420)
+ {
+ #ifdef HAVE_LIBVDPAU
+- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau;
+- if(vdpau)
+- return vdpau->Supports(method);
++ VDPAU::CVdpauRenderPicture *vdpauPic = m_buffers[m_iYV12RenderBuffer].vdpau;
++ if(vdpauPic && vdpauPic->vdpau)
++ return vdpauPic->vdpau->Supports(method);
+ #endif
+ return false;
+ }
+@@ -3027,6 +3389,16 @@
+ return false;
+ }
+
++ if(m_renderMethod & RENDER_XVBA)
++ {
++#ifdef HAVE_LIBXVBA
++ XVBA::CXvbaRenderPicture *xvba = m_buffers[m_iYV12RenderBuffer].xvba;
++ if(xvba)
++ return xvba->xvba->Supports(method);
++#endif
++ return false;
++ }
++
+ #ifdef TARGET_DARWIN
+ // YADIF too slow for HD but we have no methods to fall back
+ // to something that works so just turn it off.
+@@ -3069,7 +3441,7 @@
+ || method == VS_SCALINGMETHOD_LANCZOS3)
+ {
+ if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) ||
+- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI))
++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA))
+ {
+ // spline36 and lanczos3 are only allowed through advancedsettings.xml
+ if(method != VS_SCALINGMETHOD_SPLINE36
+@@ -3088,9 +3460,9 @@
+ if(m_renderMethod & RENDER_VDPAU)
+ {
+ #ifdef HAVE_LIBVDPAU
+- CVDPAU *vdpau = m_buffers[m_iYV12RenderBuffer].vdpau;
+- if(vdpau)
+- return vdpau->AutoInterlaceMethod();
++ VDPAU::CVdpauRenderPicture *vdpauPic = m_buffers[m_iYV12RenderBuffer].vdpau;
++ if(vdpauPic && vdpauPic->vdpau)
++ return vdpauPic->vdpau->AutoInterlaceMethod();
+ #endif
+ return VS_INTERLACEMETHOD_NONE;
+ }
+@@ -3136,20 +3508,31 @@
+ }
+
+ #ifdef HAVE_LIBVDPAU
+-void CLinuxRendererGL::AddProcessor(CVDPAU* vdpau)
++void CLinuxRendererGL::AddProcessor(VDPAU::CVdpauRenderPicture *vdpau, int index)
+ {
+- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
++ YUVBUFFER &buf = m_buffers[index];
++ VDPAU::CVdpauRenderPicture *pic = vdpau->Acquire();
+ SAFE_RELEASE(buf.vdpau);
+- buf.vdpau = (CVDPAU*)vdpau->Acquire();
++ buf.vdpau = pic;
+ }
+ #endif
+
+ #ifdef HAVE_LIBVA
+-void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder)
++void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder, int index)
+ {
+- YUVBUFFER &buf = m_buffers[NextYV12Texture()];
++ YUVBUFFER &buf = m_buffers[index];
+ buf.vaapi.surface = holder.surface;
+ }
+ #endif
+
++#ifdef HAVE_LIBXVBA
++void CLinuxRendererGL::AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index)
++{
++ YUVBUFFER &buf = m_buffers[index];
++ XVBA::CXvbaRenderPicture *pic = xvba->Acquire();
++ SAFE_RELEASE(buf.xvba);
++ buf.xvba = pic;
++}
++#endif
++
+ #endif
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/LinuxRendererGL.h xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.h
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/LinuxRendererGL.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.h 2012-05-13 22:08:46.947192904 +0200
+@@ -35,13 +35,14 @@
+
+ class CRenderCapture;
+
+-class CVDPAU;
+ class CBaseTexture;
+ namespace Shaders { class BaseYUV2RGBShader; }
+ namespace Shaders { class BaseVideoFilterShader; }
+ namespace VAAPI { struct CHolder; }
++namespace VDPAU { class CVdpauRenderPicture; }
++namespace XVBA { class CXvbaRenderPicture; }
+
+-#define NUM_BUFFERS 3
++#define NUM_BUFFERS 10
+
+
+ #undef ALIGN
+@@ -94,6 +95,7 @@
+ RENDER_VDPAU=0x08,
+ RENDER_POT=0x10,
+ RENDER_VAAPI=0x20,
++ RENDER_XVBA=0x40,
+ };
+
+ enum RenderQuality
+@@ -141,14 +143,19 @@
+ virtual void UnInit();
+ virtual void Reset(); /* resets renderer after seek for example */
+ virtual void Flush();
++ virtual void ReleaseBuffer(int idx);
++ virtual void SetProcessorSize(int numBuffers) { m_NumYV12Buffers = numBuffers; }
++ virtual unsigned int GetProcessorSize() { return m_NumYV12Buffers; }
+
+ #ifdef HAVE_LIBVDPAU
+- virtual void AddProcessor(CVDPAU* vdpau);
++ virtual void AddProcessor(VDPAU::CVdpauRenderPicture* vdpau, int index);
+ #endif
+ #ifdef HAVE_LIBVA
+- virtual void AddProcessor(VAAPI::CHolder& holder);
++ virtual void AddProcessor(VAAPI::CHolder& holder, int index);
++#endif
++#ifdef HAVE_LIBXVBA
++ virtual void AddProcessor(XVBA::CXvbaRenderPicture* xvba, int index);
+ #endif
+-
+ virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255);
+
+ // Feature support
+@@ -190,6 +197,10 @@
+ void DeleteVDPAUTexture(int index);
+ bool CreateVDPAUTexture(int index);
+
++ void UploadVDPAUTexture420(int index);
++ void DeleteVDPAUTexture420(int index);
++ bool CreateVDPAUTexture420(int index);
++
+ void UploadVAAPITexture(int index);
+ void DeleteVAAPITexture(int index);
+ bool CreateVAAPITexture(int index);
+@@ -198,6 +209,10 @@
+ void DeleteYUV422PackedTexture(int index);
+ bool CreateYUV422PackedTexture(int index);
+
++ void UploadXVBATexture(int index);
++ void DeleteXVBATexture(int index);
++ bool CreateXVBATexture(int index);
++
+ void UploadRGBTexture(int index);
+ void ToRGBFrame(YV12Image* im, unsigned flipIndexPlane, unsigned flipIndexBuf);
+ void ToRGBFields(YV12Image* im, unsigned flipIndexPlaneTop, unsigned flipIndexPlaneBot, unsigned flipIndexBuf);
+@@ -210,7 +225,9 @@
+ void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer
+ void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
+ void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
++ void RenderVDPAUYV12(int renderBuffer, int field); // render using vdpau hardware
+ void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
++ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware
+
+ CFrameBufferObject m_fbo;
+
+@@ -265,11 +282,14 @@
+ GLuint pbo[MAX_PLANES];
+
+ #ifdef HAVE_LIBVDPAU
+- CVDPAU* vdpau;
++ VDPAU::CVdpauRenderPicture *vdpau;
+ #endif
+ #ifdef HAVE_LIBVA
+ VAAPI::CHolder& vaapi;
+ #endif
++#ifdef HAVE_LIBXVBA
++ XVBA::CXvbaRenderPicture *xvba;
++#endif
+ };
+
+ typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS];
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/OverlayRenderer.cpp xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/OverlayRenderer.cpp 2012-03-21 23:57:35.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/OverlayRenderer.cpp 2012-05-13 22:08:46.744188878 +0200
+@@ -89,7 +89,7 @@
+ CRenderer::CRenderer()
+ {
+ m_render = 0;
+- m_decode = (m_render + 1) % 2;
++// m_decode = (m_render + 1) % 2;
+ }
+
+ CRenderer::~CRenderer()
+@@ -154,9 +154,10 @@
+ {
+ CSingleLock lock(m_section);
+
+- for(int i = 0; i < 2; i++)
++ for(int i = 0; i < m_iNumBuffers; i++)
+ Release(m_buffers[i]);
+
++ m_render = 0;
+ Release(m_cleanup);
+ }
+
+@@ -164,10 +165,23 @@
+ {
+ CSingleLock lock(m_section);
+
+- m_render = m_decode;
+- m_decode =(m_decode + 1) % 2;
++// m_render = m_decode;
++ m_render = (m_render + 1) % m_iNumBuffers;
++
++// Release(m_buffers[m_decode]);
++}
++
++void CRenderer::SetBuffer(int idx)
++{
++ CSingleLock lock(m_section);
++ Release(m_buffers[idx]);
++ m_decode = idx;
++}
+
+- Release(m_buffers[m_decode]);
++void CRenderer::ReleaseBuffer(int idx)
++{
++ CSingleLock lock(m_section);
++ Release(m_buffers[idx]);
+ }
+
+ void CRenderer::Render()
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/OverlayRenderer.h xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/OverlayRenderer.h
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/OverlayRenderer.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/OverlayRenderer.h 2012-05-13 22:08:46.745188897 +0200
+@@ -99,6 +99,9 @@
+ void Flip();
+ void Render();
+ void Flush();
++ void SetNumBuffers(int numBuffers) { m_iNumBuffers = numBuffers; }
++ void SetBuffer(int idx);
++ void ReleaseBuffer(int idx);
+
+ protected:
+
+@@ -124,7 +127,8 @@
+ void Release(SElementV& list);
+
+ CCriticalSection m_section;
+- SElementV m_buffers[2];
++ SElementV m_buffers[10];
++ int m_iNumBuffers;
+ int m_decode;
+ int m_render;
+
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/RenderFlags.h xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/RenderFlags.h
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/RenderFlags.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/RenderFlags.h 2012-05-13 22:08:46.948192924 +0200
+@@ -76,8 +76,10 @@
+ #define CONF_FLAGS_FORMAT_YUY2 0x008000
+ #define CONF_FLAGS_FORMAT_DXVA 0x010000
+ #define CONF_FLAGS_FORMAT_VDPAU 0x020000
++#define CONF_FLAGS_FORMAT_VDPAU_420 0x22000
+ #define CONF_FLAGS_FORMAT_VAAPI 0x030000
+ #define CONF_FLAGS_FORMAT_OMXEGL 0x040000
+ #define CONF_FLAGS_FORMAT_CVBREF 0x080000
+ #define CONF_FLAGS_FORMAT_BYPASS 0x100000
++#define CONF_FLAGS_FORMAT_XVBA 0x200000
+ #endif
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/RenderManager.cpp
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/RenderManager.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/RenderManager.cpp 2012-05-13 22:08:47.061195167 +0200
+@@ -26,6 +26,7 @@
+ #include "utils/MathUtils.h"
+ #include "threads/SingleLock.h"
+ #include "utils/log.h"
++#include "utils/TimeUtils.h"
+
+ #include "Application.h"
+ #include "settings/Settings.h"
+@@ -53,6 +54,8 @@
+ #include "../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h"
+ #include "../dvdplayer/DVDCodecs/DVDCodecUtils.h"
+
++#include "windowing/WindowingFactory.h"
++
+ #define MAXPRESENTDELAY 0.500
+
+ /* at any point we want an exclusive lock on rendermanager */
+@@ -246,6 +249,7 @@
+ m_bReconfigured = true;
+ m_presentstep = PRESENT_IDLE;
+ m_presentevent.Set();
++// ResetRenderBuffer();
+ }
+
+ return result;
+@@ -277,8 +281,12 @@
+ if (!m_pRenderer)
+ return;
+
++ if (m_presentstep == PRESENT_IDLE)
++ PrepareNextRender();
++
+ if(m_presentstep == PRESENT_FLIP)
+ {
++ FlipRenderBuffer();
+ m_overlays.Flip();
+ m_pRenderer->FlipPage(m_presentsource);
+ m_presentstep = PRESENT_FRAME;
+@@ -286,6 +294,8 @@
+ }
+ }
+
++// CLog::Log(LOGNOTICE,"------ current: %d", m_iCurrentRenderBuffer);
++
+ if (g_advancedSettings.m_videoDisableBackgroundDeinterlace)
+ {
+ CSharedLock lock(m_sharedSection);
+@@ -297,7 +307,7 @@
+ m_presentevent.Set();
+ }
+
+-unsigned int CXBMCRenderManager::PreInit()
++unsigned int CXBMCRenderManager::PreInit(CDVDClock *pClock)
+ {
+ CRetakeLock lock(m_sharedSection);
+
+@@ -305,6 +315,7 @@
+ m_presenterr = 0.0;
+ m_errorindex = 0;
+ memset(m_errorbuff, 0, sizeof(m_errorbuff));
++ m_pClock = pClock;
+
+ m_bIsStarted = false;
+ m_bPauseDrawing = false;
+@@ -323,6 +334,17 @@
+
+ UpdateDisplayLatency();
+
++ m_swapCount = 1;
++// std::string Vendor = g_Windowing.GetRenderVendor();
++// std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower);
++// if (Vendor.compare(0, 3, "ati") == 0)
++// {
++// m_swapCount = 2;
++// }
++ ResetRenderBuffer();
++ m_bUseBuffering = false;
++ m_overlays.SetNumBuffers(m_iNumRenderBuffers);
++ m_pRenderer->SetProcessorSize(m_iNumRenderBuffers);
+ return m_pRenderer->PreInit();
+ }
+
+@@ -351,7 +373,9 @@
+
+ CRetakeLock lock(m_sharedSection);
+ m_pRenderer->Flush();
++ m_overlays.Flush();
+ m_flushEvent.Set();
++ ResetRenderBuffer();
+ }
+ else
+ {
+@@ -512,25 +536,21 @@
+ m_captures.erase(it);
+ }
+
+-void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
++void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/, int speed /*= 0*/)
+ {
+- if(timestamp - GetPresentTime() > MAXPRESENTDELAY)
+- timestamp = GetPresentTime() + MAXPRESENTDELAY;
+-
+- /* can't flip, untill timestamp */
+- if(!g_graphicsContext.IsFullScreenVideo())
+- WaitPresentTime(timestamp);
+-
+- /* make sure any queued frame was fully presented */
+- double timeout = m_presenttime + 1.0;
+- while(m_presentstep != PRESENT_IDLE && !bStop)
++ if (!m_bUseBuffering)
+ {
+- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
++ /* make sure any queued frame was fully presented */
++ double timeout = m_presenttime + 1.0;
++ while(m_presentstep != PRESENT_IDLE && !bStop)
+ {
+- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame");
+- return;
++ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
++ {
++ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for previous frame");
++ return;
++ }
+ }
+- };
++ }
+
+ if(bStop)
+ return;
+@@ -538,58 +558,67 @@
+ { CRetakeLock lock(m_sharedSection);
+ if(!m_pRenderer) return;
+
+- m_presenttime = timestamp;
+- m_presentfield = sync;
+- m_presentstep = PRESENT_FLIP;
+- m_presentsource = source;
++ double presenttime = timestamp;
++ EFIELDSYNC presentfield = sync;
++ EPRESENTMETHOD presentmethod;
++
+ EDEINTERLACEMODE deinterlacemode = g_settings.m_currentVideoSettings.m_DeinterlaceMode;
+ EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(g_settings.m_currentVideoSettings.m_InterlaceMethod);
+
+ bool invert = false;
+
+ if (deinterlacemode == VS_DEINTERLACEMODE_OFF)
+- m_presentmethod = PRESENT_METHOD_SINGLE;
++ presentmethod = PRESENT_METHOD_SINGLE;
+ else
+ {
+- if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && m_presentfield == FS_NONE)
+- m_presentmethod = PRESENT_METHOD_SINGLE;
++ if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && presentfield == FS_NONE)
++ presentmethod = PRESENT_METHOD_SINGLE;
+ else
+ {
+- if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) m_presentmethod = PRESENT_METHOD_BLEND;
+- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) m_presentmethod = PRESENT_METHOD_WEAVE;
+- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { m_presentmethod = PRESENT_METHOD_WEAVE ; invert = true; }
+- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) m_presentmethod = PRESENT_METHOD_BOB;
+- else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { m_presentmethod = PRESENT_METHOD_BOB; invert = true; }
+- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) m_presentmethod = PRESENT_METHOD_BOB;
+- else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) m_presentmethod = PRESENT_METHOD_BOB;
+- else m_presentmethod = PRESENT_METHOD_SINGLE;
++ if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND) presentmethod = PRESENT_METHOD_BLEND;
++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE) presentmethod = PRESENT_METHOD_WEAVE;
++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED) { presentmethod = PRESENT_METHOD_WEAVE ; invert = true; }
++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB) presentmethod = PRESENT_METHOD_BOB;
++ else if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED) { presentmethod = PRESENT_METHOD_BOB; invert = true; }
++ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BOB) presentmethod = PRESENT_METHOD_BOB;
++ else if (interlacemethod == VS_INTERLACEMETHOD_DXVA_BEST) presentmethod = PRESENT_METHOD_BOB;
++ else presentmethod = PRESENT_METHOD_SINGLE;
+
+ /* default to odd field if we want to deinterlace and don't know better */
+- if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && m_presentfield == FS_NONE)
+- m_presentfield = FS_TOP;
++ if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && presentfield == FS_NONE)
++ presentfield = FS_TOP;
+
+ /* invert present field */
+ if(invert)
+ {
+- if( m_presentfield == FS_BOT )
+- m_presentfield = FS_TOP;
++ if( presentfield == FS_BOT )
++ presentfield = FS_TOP;
+ else
+- m_presentfield = FS_BOT;
++ presentfield = FS_BOT;
+ }
+ }
+ }
+
++ FlipFreeBuffer();
++ m_renderBuffers[m_iOutputRenderBuffer].pts = timestamp;
++ m_renderBuffers[m_iOutputRenderBuffer].presentfield = presentfield;
++ m_renderBuffers[m_iOutputRenderBuffer].presentmethod = presentmethod;
++ m_speed = speed;
+ }
+
+ g_application.NewFrame();
+- /* wait untill render thread have flipped buffers */
+- timeout = m_presenttime + 1.0;
+- while(m_presentstep == PRESENT_FLIP && !bStop)
++
++ if (!m_bUseBuffering)
+ {
+- if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
++ /* wait untill render thread have flipped buffers */
++ double timeout = m_presenttime + 1.0;
++ while(m_presentstep == PRESENT_FLIP && !bStop)
+ {
+- CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete");
+- return;
++ if(!m_presentevent.WaitMSec(100) && GetPresentTime() > timeout && !bStop)
++ {
++ CLog::Log(LOGWARNING, "CRenderManager::FlipPage - timeout waiting for flip to complete");
++ return;
++ }
+ }
+ }
+ }
+@@ -631,8 +660,12 @@
+ if (!m_pRenderer)
+ return;
+
++ if (m_presentstep == PRESENT_IDLE)
++ PrepareNextRender();
++
+ if(m_presentstep == PRESENT_FLIP)
+ {
++ FlipRenderBuffer();
+ m_overlays.Flip();
+ m_pRenderer->FlipPage(m_presentsource);
+ m_presentstep = PRESENT_FRAME;
+@@ -647,6 +680,8 @@
+ WaitPresentTime(m_presenttime);
+
+ m_presentevent.Set();
++
++ m_rendertime = CurrentHostCounter();
+ }
+
+ /* simple present method */
+@@ -753,7 +788,7 @@
+ return 1;
+
+ YV12Image image;
+- int index = m_pRenderer->GetImage(&image);
++ int index = m_pRenderer->GetImage(&image, (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers);
+
+ if(index < 0)
+ return index;
+@@ -776,8 +811,9 @@
+ CDVDCodecUtils::CopyDXVA2Picture(&image, &pic);
+ }
+ #ifdef HAVE_LIBVDPAU
+- else if(pic.format == DVDVideoPicture::FMT_VDPAU)
+- m_pRenderer->AddProcessor(pic.vdpau);
++ else if(pic.format == DVDVideoPicture::FMT_VDPAU
++ || pic.format == DVDVideoPicture::FMT_VDPAU_420)
++ m_pRenderer->AddProcessor(pic.vdpau, index);
+ #endif
+ #ifdef HAVE_LIBOPENMAX
+ else if(pic.format == DVDVideoPicture::FMT_OMXEGL)
+@@ -789,7 +825,11 @@
+ #endif
+ #ifdef HAVE_LIBVA
+ else if(pic.format == DVDVideoPicture::FMT_VAAPI)
+- m_pRenderer->AddProcessor(*pic.vaapi);
++ m_pRenderer->AddProcessor(*pic.vaapi, index);
++#endif
++#ifdef HAVE_LIBXVBA
++ else if(pic.format == DVDVideoPicture::FMT_XVBA)
++ m_pRenderer->AddProcessor(pic.xvba, index);
+ #endif
+ m_pRenderer->ReleaseImage(index, false);
+
+@@ -809,3 +849,212 @@
+
+ return mInt;
+ }
++
++int CXBMCRenderManager::WaitForBuffer(volatile bool& bStop)
++{
++ CSharedLock lock(m_sharedSection);
++ if (!m_pRenderer)
++ return -1;
++
++ //wait up to a second as this is our slowest allowed output rate
++ double timeout = GetPresentTime() + 0.1;
++ while(!HasFreeBuffer() && !bStop)
++ {
++ lock.Leave();
++ m_flipEvent.WaitMSec(50);
++ if(GetPresentTime() > timeout && !bStop)
++ {
++ CLog::Log(LOGWARNING, "CRenderManager::WaitForBuffer - timeout waiting for buffer");
++ return -1;
++ }
++ lock.Enter();
++ }
++ lock.Leave();
++
++ { CRetakeLock lock(m_sharedSection);
++ m_overlays.SetBuffer((m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers);
++ }
++
++ if (bStop)
++ return -1;
++
++ return 1;
++}
++
++int CXBMCRenderManager::GetNextRenderBufferIndex()
++{
++ if (m_iOutputRenderBuffer == m_iCurrentRenderBuffer)
++ return -1;
++ return (m_iCurrentRenderBuffer + 1) % m_iNumRenderBuffers;
++}
++
++void CXBMCRenderManager::FlipRenderBuffer()
++{
++ m_iCurrentRenderBuffer = GetNextRenderBufferIndex();
++// CLog::Log(LOGNOTICE,"-------- flip render: %d", m_iCurrentRenderBuffer);
++}
++
++int CXBMCRenderManager::FlipFreeBuffer()
++{
++ // See "Render Buffer State Description" in header for information.
++ if (HasFreeBuffer())
++ {
++ m_bAllRenderBuffersDisplayed = false;
++ m_iOutputRenderBuffer = (m_iOutputRenderBuffer + 1) % m_iNumRenderBuffers;
++ return m_iOutputRenderBuffer;
++ }
++}
++
++bool CXBMCRenderManager::HasFreeBuffer()
++{
++ if (!m_bUseBuffering)
++ {
++ if (m_iOutputRenderBuffer != m_iCurrentRenderBuffer)
++ return false;
++ else
++ return true;
++ }
++
++ int outputPlusSwap = (m_iOutputRenderBuffer + m_swapCount) % m_iNumRenderBuffers;
++ if ((m_iOutputRenderBuffer == m_iDisplayedRenderBuffer && !m_bAllRenderBuffersDisplayed)
++ || outputPlusSwap == m_iCurrentRenderBuffer)
++ return false;
++ else
++ return true;
++}
++
++void CXBMCRenderManager::ResetRenderBuffer()
++{
++ m_iNumRenderBuffers = 5;
++ m_iCurrentRenderBuffer = 0;
++ m_iFlipRequestRenderBuffer = 0;
++ m_iOutputRenderBuffer = 0;
++ m_iDisplayedRenderBuffer = 0;
++ m_bAllRenderBuffersDisplayed = true;
++ m_sleeptime = 1.0;
++ m_presentPts = DVD_NOPTS_VALUE;
++// m_bUseBuffering = true;
++ m_speed = 0;
++}
++
++void CXBMCRenderManager::PrepareNextRender()
++{
++ int idx = GetNextRenderBufferIndex();
++ if (idx < 0)
++ {
++ if (m_speed >= DVD_PLAYSPEED_NORMAL && g_graphicsContext.IsFullScreenVideo())
++ CLog::Log(LOGNOTICE,"----------- no buffer, out: %d, current: %d, display: %d",
++ m_iOutputRenderBuffer, m_iCurrentRenderBuffer, m_iDisplayedRenderBuffer);
++ return;
++ }
++
++ double iClockSleep, iPlayingClock, iCurrentClock;
++ iPlayingClock = m_pClock->GetClock(iCurrentClock, false);
++ iClockSleep = m_renderBuffers[idx].pts - iPlayingClock;
++
++ if (m_speed)
++ iClockSleep = iClockSleep * DVD_PLAYSPEED_NORMAL / m_speed;
++
++ double presenttime = (iCurrentClock + iClockSleep) / DVD_TIME_BASE;
++ double clocktime = iCurrentClock / DVD_TIME_BASE;
++ if(presenttime - clocktime > MAXPRESENTDELAY)
++ presenttime = clocktime + MAXPRESENTDELAY;
++
++ m_sleeptime = presenttime - clocktime;
++
++// double interval;
++// if (g_VideoReferenceClock.GetRefreshRate(&interval) > 0)
++// {
++// if (m_swaptime > interval * 0.7)
++// {
++// presenttime += interval;
++// CLog::Log(LOGDEBUG,"------------ very long swaptime");
++// }
++// }
++
++ if (g_graphicsContext.IsFullScreenVideo() || presenttime <= clocktime+0.01)
++ {
++ m_presentPts = m_renderBuffers[idx].pts;
++ m_presenttime = presenttime;
++ m_presentmethod = m_renderBuffers[idx].presentmethod;
++ m_presentfield = m_renderBuffers[idx].presentfield;
++ m_presentstep = PRESENT_FLIP;
++ m_presentsource = idx;
++ }
++}
++
++void CXBMCRenderManager::EnableBuffering(bool enable)
++{
++ CRetakeLock lock(m_sharedSection);
++ m_bUseBuffering = enable;
++ if (!m_bUseBuffering)
++ m_iOutputRenderBuffer = m_iCurrentRenderBuffer;
++
++ CLog::Log(LOGDEBUG, "CXBMCRenderManager::EnableBuffering - %d", m_bUseBuffering);
++}
++
++void CXBMCRenderManager::DiscardBuffer()
++{
++ CRetakeLock lock(m_sharedSection);
++ m_iOutputRenderBuffer = m_iCurrentRenderBuffer;
++}
++
++void CXBMCRenderManager::NotifyDisplayFlip()
++{
++ CRetakeLock lock(m_sharedSection);
++ if (!m_pRenderer)
++ return;
++
++// if (g_graphicsContext.IsFullScreenVideo())
++// {
++// uint64_t diff = CurrentHostCounter() - m_rendertime;
++// m_swaptime = ((double)(diff))/CurrentHostFrequency();
++// int waittime = (int)((diff*1000LL)/CurrentHostFrequency());
++// if (waittime > 15)
++// {
++// CLog::Log(LOGNOTICE,"------------------ wait swap buffers: %f, sleep: %f", m_swaptime, m_sleeptime);
++// }
++// }
++
++ int last = m_iDisplayedRenderBuffer;
++ m_iDisplayedRenderBuffer = (m_iCurrentRenderBuffer + m_iNumRenderBuffers - m_swapCount) % m_iNumRenderBuffers;
++ m_iFlipRequestRenderBuffer = m_iCurrentRenderBuffer;
++
++// // we have caught up with output so all buffers are re-usable
++// if (last != m_iDisplayedRenderBuffer
++// && m_iDisplayedRenderBuffer == m_iOutputRenderBuffer)
++// {
++// CLog::Log(LOGNOTICE,"-------------- all displayed");
++// m_bAllRenderBuffersDisplayed = true;
++// }
++
++ if (last != m_iDisplayedRenderBuffer
++ && m_iDisplayedRenderBuffer != m_iCurrentRenderBuffer)
++ {
++ m_pRenderer->ReleaseBuffer(m_iDisplayedRenderBuffer);
++ m_overlays.ReleaseBuffer(m_iDisplayedRenderBuffer);
++ }
++
++ lock.Leave();
++ m_flipEvent.Set();
++}
++
++bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel)
++{
++ CSharedLock lock(m_sharedSection);
++ sleeptime = m_sleeptime;
++ pts = m_presentPts;
++ bufferLevel = (m_iOutputRenderBuffer - m_iCurrentRenderBuffer + m_iNumRenderBuffers) % m_iNumRenderBuffers;
++ return true;
++}
++
++bool CXBMCRenderManager::HasFrame()
++{
++ CSharedLock lock(m_sharedSection);
++ if (m_presentstep == PRESENT_IDLE &&
++ GetNextRenderBufferIndex() < 0 &&
++ m_speed > 0)
++ return false;
++ else
++ return true;
++}
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/RenderManager.h xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/RenderManager.h
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/RenderManager.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/RenderManager.h 2012-05-13 22:08:47.016194272 +0200
+@@ -39,10 +39,11 @@
+ #include "OverlayRenderer.h"
+
+ class CRenderCapture;
++class CDVDClock;
+
+ namespace DXVA { class CProcessor; }
+ namespace VAAPI { class CSurfaceHolder; }
+-class CVDPAU;
++namespace VDPAU { struct CVdpauRenderPicture; }
+ struct DVDVideoPicture;
+
+ #define ERRORBUFFSIZE 30
+@@ -73,8 +74,8 @@
+
+ int AddVideoPicture(DVDVideoPicture& picture);
+
+- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
+- unsigned int PreInit();
++ void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE, int speed = 0);
++ unsigned int PreInit(CDVDClock *pClock);
+ void UnInit();
+ bool Flush();
+
+@@ -182,6 +183,13 @@
+
+ CSharedSection& GetSection() { return m_sharedSection; };
+
++ int WaitForBuffer(volatile bool& bStop);
++ void NotifyDisplayFlip();
++ bool GetStats(double &sleeptime, double &pts, int &bufferLevel);
++ bool HasFrame();
++ void EnableBuffering(bool enable);
++ void DiscardBuffer();
++
+ protected:
+ void Render(bool clear, DWORD flags, DWORD alpha);
+
+@@ -190,6 +198,13 @@
+ void PresentBob(bool clear, DWORD flags, DWORD alpha);
+ void PresentBlend(bool clear, DWORD flags, DWORD alpha);
+
++ int GetNextRenderBufferIndex();
++ void FlipRenderBuffer();
++ int FlipFreeBuffer();
++ bool HasFreeBuffer();
++ void ResetRenderBuffer();
++ void PrepareNextRender();
++
+ EINTERLACEMETHOD AutoInterlaceMethodInternal(EINTERLACEMETHOD mInt);
+
+ bool m_bPauseDrawing; // true if we should pause rendering
+@@ -220,6 +235,43 @@
+ double m_displayLatency;
+ void UpdateDisplayLatency();
+
++ // Render Buffer State Description:
++ //
++ // Output: is the buffer about to or having its texture prepared for render (ie from output thread).
++ // Cannot go past the "Displayed" buffer (otherwise we will probably overwrite buffers not yet
++ // displayed or even rendered).
++ // Current: is the current buffer being or having been submitted for render to back buffer.
++ // Cannot go past "Output" buffer (else it would be rendering old output).
++ // FlipRequest: is the render buffer that has last been submitted for render AND importantly has had
++ // swap-buffer flip subsequently invoked (thus flip to front buffer is requested for vblank
++ // subsequent to render completion).
++ // Displayed: is the buffer that is now considered to be safely copied from back buffer to front buffer
++ // (we assume that after two swap-buffer flips for the same "Current" render buffer that that
++ // buffer will be safe, but otherwise we consider that only the previous-to-"Current" is guaranteed).
++ // Last: is the last buffer successfully submitted for render to back buffer (purpose: to rollback to in
++ // unexpected case where a texture render fails).
++
++ int m_iCurrentRenderBuffer;
++ int m_iNumRenderBuffers;
++// int m_iLastRenderBuffer;
++ int m_iFlipRequestRenderBuffer;
++ int m_iOutputRenderBuffer;
++ int m_iDisplayedRenderBuffer;
++ bool m_bAllRenderBuffersDisplayed;
++ bool m_bUseBuffering;
++ int m_speed;
++ CEvent m_flipEvent;
++
++ struct
++ {
++ double pts;
++ EFIELDSYNC presentfield;
++ EPRESENTMETHOD presentmethod;
++ }m_renderBuffers[5];
++
++ double m_sleeptime;
++ double m_presentPts;
++
+ double m_presenttime;
+ double m_presentcorr;
+ double m_presenterr;
+@@ -231,7 +283,10 @@
+ int m_presentsource;
+ CEvent m_presentevent;
+ CEvent m_flushEvent;
+-
++ CDVDClock *m_pClock;
++ uint64_t m_rendertime;
++ double m_swaptime;
++ unsigned int m_swapCount;
+
+ OVERLAY::CRenderer m_overlays;
+
+diff -Naur xbmc-11.0.1/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
+--- xbmc-11.0.1/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2012-05-13 22:01:28.569494075 +0200
+@@ -186,6 +186,8 @@
+ m_defines += "#define XBMC_YUY2\n";
+ else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_UYVY)
+ m_defines += "#define XBMC_UYVY\n";
++ else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_VDPAU_420)
++ m_defines += "#define XBMC_VDPAU_NV12\n";
+
+ VertexShader()->LoadSource("yuv2rgb_vertex.glsl", m_defines);
+ #elif HAS_GLES == 2
+diff -Naur xbmc-11.0.1/xbmc/dialogs/GUIDialogCache.cpp xbmc-11.0.1.patch/xbmc/dialogs/GUIDialogCache.cpp
+--- xbmc-11.0.1/xbmc/dialogs/GUIDialogCache.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/dialogs/GUIDialogCache.cpp 2012-05-13 22:08:46.789189770 +0200
+@@ -29,7 +29,7 @@
+ #include "threads/SingleLock.h"
+ #include "utils/TimeUtils.h"
+
+-CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg)
++CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg) : CThread("CGUIDialogCache")
+ {
+ m_pDlg = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
+
+diff -Naur xbmc-11.0.1/xbmc/filesystem/FileCache.cpp xbmc-11.0.1.patch/xbmc/filesystem/FileCache.cpp
+--- xbmc-11.0.1/xbmc/filesystem/FileCache.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/FileCache.cpp 2012-05-13 22:08:46.789189770 +0200
+@@ -79,7 +79,7 @@
+ };
+
+
+-CFileCache::CFileCache()
++CFileCache::CFileCache() : CThread("CFileCache")
+ {
+ m_bDeleteCache = true;
+ m_nSeekResult = 0;
+@@ -95,7 +95,7 @@
+ m_cacheFull = false;
+ }
+
+-CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache)
++CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache) : CThread("CFileCache")
+ {
+ m_pCache = pCache;
+ m_bDeleteCache = bDeleteCache;
+diff -Naur xbmc-11.0.1/xbmc/filesystem/FilePipe.cpp xbmc-11.0.1.patch/xbmc/filesystem/FilePipe.cpp
+--- xbmc-11.0.1/xbmc/filesystem/FilePipe.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/FilePipe.cpp 2012-05-13 22:08:46.790189789 +0200
+@@ -24,6 +24,8 @@
+ #include "PipesManager.h"
+ #include "utils/StringUtils.h"
+
++#define INFINITE 0xFFFFFFFF
++
+ using namespace XFILE;
+
+ CFilePipe::CFilePipe() : m_pos(0), m_length(-1), m_pipe(NULL)
+diff -Naur xbmc-11.0.1/xbmc/filesystem/FileRar.cpp xbmc-11.0.1.patch/xbmc/filesystem/FileRar.cpp
+--- xbmc-11.0.1/xbmc/filesystem/FileRar.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/FileRar.cpp 2012-05-13 22:08:46.790189789 +0200
+@@ -43,7 +43,7 @@
+ #define SEEKTIMOUT 30000
+
+ #ifdef HAS_FILESYSTEM_RAR
+-CFileRarExtractThread::CFileRarExtractThread() : hRunning(true), hQuit(true)
++CFileRarExtractThread::CFileRarExtractThread() : CThread("CFileRarExtractThread"), hRunning(true), hQuit(true)
+ {
+ m_pArc = NULL;
+ m_pCmd = NULL;
+diff -Naur xbmc-11.0.1/xbmc/filesystem/HTSPDirectory.cpp xbmc-11.0.1.patch/xbmc/filesystem/HTSPDirectory.cpp
+--- xbmc-11.0.1/xbmc/filesystem/HTSPDirectory.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/HTSPDirectory.cpp 2012-05-13 22:08:46.791189809 +0200
+@@ -76,7 +76,7 @@
+ static CCriticalSection g_section;
+
+
+-CHTSPDirectorySession::CHTSPDirectorySession()
++CHTSPDirectorySession::CHTSPDirectorySession() : CThread("CHTSPDirectorySession")
+ {
+ }
+
+diff -Naur xbmc-11.0.1/xbmc/filesystem/LastFMDirectory.cpp xbmc-11.0.1.patch/xbmc/filesystem/LastFMDirectory.cpp
+--- xbmc-11.0.1/xbmc/filesystem/LastFMDirectory.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/LastFMDirectory.cpp 2012-05-13 22:08:46.792189829 +0200
+@@ -69,7 +69,7 @@
+ m_dlgProgress->Progress();
+ }
+
+- CThread thread(this);
++ CThread thread(this, "CLastFMDirectory");
+ m_strSource = url;
+ m_strDestination = "special://temp/lastfm.xml";
+ thread.Create();
+diff -Naur xbmc-11.0.1/xbmc/filesystem/MythSession.cpp xbmc-11.0.1.patch/xbmc/filesystem/MythSession.cpp
+--- xbmc-11.0.1/xbmc/filesystem/MythSession.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/MythSession.cpp 2012-05-13 22:08:46.792189829 +0200
+@@ -359,7 +359,7 @@
+ return;
+ }
+
+-CMythSession::CMythSession(const CURL& url)
++CMythSession::CMythSession(const CURL& url) : CThread("CMythSession")
+ {
+ m_control = NULL;
+ m_event = NULL;
+diff -Naur xbmc-11.0.1/xbmc/filesystem/PipesManager.cpp xbmc-11.0.1.patch/xbmc/filesystem/PipesManager.cpp
+--- xbmc-11.0.1/xbmc/filesystem/PipesManager.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/PipesManager.cpp 2012-05-13 22:08:46.793189848 +0200
+@@ -23,6 +23,8 @@
+ #include "threads/SingleLock.h"
+ #include "Application.h"
+
++#define INFINITE 0xFFFFFFFF
++
+ #ifndef min
+ #define min(a,b) ((a) < (b) ? (a) : (b))
+ #endif
+diff -Naur xbmc-11.0.1/xbmc/filesystem/RarManager.h xbmc-11.0.1.patch/xbmc/filesystem/RarManager.h
+--- xbmc-11.0.1/xbmc/filesystem/RarManager.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/RarManager.h 2012-05-13 22:08:46.793189848 +0200
+@@ -71,7 +71,7 @@
+ CRarManager();
+ ~CRarManager();
+ bool CacheRarredFile(CStdString& strPathInCache, const CStdString& strRarPath,
+- const CStdString& strPathInRar, BYTE bOptions = EXFILE_AUTODELETE,
++ const CStdString& strPathInRar, uint8_t bOptions = EXFILE_AUTODELETE,
+ const CStdString& strDir =RAR_DEFAULT_CACHE, const int64_t iSize=-1);
+ bool GetPathInCache(CStdString& strPathInCache, const CStdString& strRarPath,
+ const CStdString& strPathInRar = "");
+diff -Naur xbmc-11.0.1/xbmc/filesystem/SAPDirectory.cpp xbmc-11.0.1.patch/xbmc/filesystem/SAPDirectory.cpp
+--- xbmc-11.0.1/xbmc/filesystem/SAPDirectory.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/filesystem/SAPDirectory.cpp 2012-05-13 22:08:46.794189867 +0200
+@@ -272,7 +272,7 @@
+ using namespace SDP;
+
+
+-CSAPSessions::CSAPSessions()
++CSAPSessions::CSAPSessions() : CThread("CSAPSessions")
+ {
+ m_socket = INVALID_SOCKET;
+ }
+@@ -486,7 +486,7 @@
+
+ CSingleLock lock(g_sapsessions.m_section);
+
+- if(g_sapsessions.ThreadHandle() == NULL)
++ if(!g_sapsessions.IsRunning())
+ g_sapsessions.Create();
+
+ // check if we can find this session in our cache
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp
+--- xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp 2012-05-13 22:08:46.796189907 +0200
+@@ -181,9 +181,9 @@
+ m_threadState = state;
+ }
+
+-void CGUIPythonWindow::WaitForActionEvent(unsigned int timeout)
++void CGUIPythonWindow::WaitForActionEvent()
+ {
+- g_pythonParser.WaitForEvent(m_actionEvent, timeout);
++ g_pythonParser.WaitForEvent(m_actionEvent);
+ m_actionEvent.Reset();
+ }
+
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h
+--- xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h 2012-05-13 22:08:46.796189907 +0200
+@@ -51,7 +51,7 @@
+ virtual bool OnAction(const CAction &action);
+ virtual bool OnBack(int actionID);
+ void SetCallbackWindow(void* state, void *object);
+- void WaitForActionEvent(unsigned int timeout);
++ void WaitForActionEvent();
+ void PulseActionEvent();
+ void SetDestroyAfterDeinit(bool destroy = true);
+ protected:
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp
+--- xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp 2012-05-13 22:08:46.797189927 +0200
+@@ -279,9 +279,9 @@
+ UpdateButtons();
+ }
+
+-void CGUIPythonWindowXML::WaitForActionEvent(unsigned int timeout)
++void CGUIPythonWindowXML::WaitForActionEvent()
+ {
+- g_pythonParser.WaitForEvent(m_actionEvent, timeout);
++ g_pythonParser.WaitForEvent(m_actionEvent);
+ m_actionEvent.Reset();
+ }
+
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h
+--- xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h 2012-05-13 22:08:46.798189947 +0200
+@@ -40,7 +40,7 @@
+ virtual void AllocResources(bool forceLoad = false);
+ virtual void FreeResources(bool forceUnLoad = false);
+ void Process(unsigned int currentTime, CDirtyRegionList ®ions);
+- void WaitForActionEvent(unsigned int timeout);
++ void WaitForActionEvent();
+ void PulseActionEvent();
+ void AddItem(CFileItemPtr fileItem,int itemPosition);
+ void RemoveItem(int itemPosition);
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/window.cpp xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/window.cpp
+--- xbmc-11.0.1/xbmc/interfaces/python/xbmcmodule/window.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/xbmcmodule/window.cpp 2012-05-13 22:08:46.798189947 +0200
+@@ -540,11 +540,11 @@
+
+ CPyThreadState pyState;
+ if (WindowXML_Check(self))
+- ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent(INFINITE);
++ ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent();
+ else if (WindowXMLDialog_Check(self))
+- ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent(INFINITE);
++ ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent();
+ else
+- ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent(INFINITE);
++ ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent();
+ }
+ }
+ Py_INCREF(Py_None);
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/XBPython.cpp xbmc-11.0.1.patch/xbmc/interfaces/python/XBPython.cpp
+--- xbmc-11.0.1/xbmc/interfaces/python/XBPython.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/XBPython.cpp 2012-05-13 22:08:46.795189887 +0200
+@@ -676,11 +676,11 @@
+ m_globalEvent.Set();
+ }
+
+-void XBPython::WaitForEvent(CEvent& hEvent, unsigned int timeout)
++void XBPython::WaitForEvent(CEvent& hEvent)
+ {
+ // wait for either this event our our global event
+ XbmcThreads::CEventGroup eventGroup(&hEvent, &m_globalEvent, NULL);
+- eventGroup.wait(timeout);
++ eventGroup.wait();
+ m_globalEvent.Reset();
+ }
+
+diff -Naur xbmc-11.0.1/xbmc/interfaces/python/XBPython.h xbmc-11.0.1.patch/xbmc/interfaces/python/XBPython.h
+--- xbmc-11.0.1/xbmc/interfaces/python/XBPython.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/interfaces/python/XBPython.h 2012-05-13 22:08:46.795189887 +0200
+@@ -61,7 +61,7 @@
+ void Process();
+
+ void PulseGlobalEvent();
+- void WaitForEvent(CEvent& hEvent, unsigned int timeout);
++ void WaitForEvent(CEvent& hEvent);
+
+ int ScriptsSize();
+ int GetPythonScriptId(int scriptPosition);
+diff -Naur xbmc-11.0.1/xbmc/linux/Makefile.in xbmc-11.0.1.patch/xbmc/linux/Makefile.in
+--- xbmc-11.0.1/xbmc/linux/Makefile.in 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/Makefile.in 2012-05-13 22:08:46.799189967 +0200
+@@ -10,14 +10,11 @@
+ LinuxResourceCounter.cpp \
+ LinuxTimezone.cpp \
+ PosixMountProvider.cpp \
+- XEventUtils.cpp \
+ XFileUtils.cpp \
+ XHandle.cpp \
+ XLCDproc.cpp \
+ XMemUtils.cpp \
+- XSyncUtils.cpp \
+ XTimeUtils.cpp \
+- XThreadUtils.cpp \
+
+ LIB=linux.a
+
+diff -Naur xbmc-11.0.1/xbmc/linux/PlatformDefs.h xbmc-11.0.1.patch/xbmc/linux/PlatformDefs.h
+--- xbmc-11.0.1/xbmc/linux/PlatformDefs.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/PlatformDefs.h 2012-05-13 22:08:46.800189987 +0200
+@@ -182,8 +182,6 @@
+ #define EXCEPTION_EXECUTE_HANDLER ...
+ //NOTE: dont try to define __except because it breaks g++ (already uses it).
+
+-typedef pthread_t ThreadIdentifier;
+-
+ struct CXHandle; // forward declaration
+ typedef CXHandle* HANDLE;
+
+diff -Naur xbmc-11.0.1/xbmc/linux/PlatformInclude.h xbmc-11.0.1.patch/xbmc/linux/PlatformInclude.h
+--- xbmc-11.0.1/xbmc/linux/PlatformInclude.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/PlatformInclude.h 2012-05-13 22:08:46.800189987 +0200
+@@ -25,10 +25,7 @@
+ #include "PlatformDefs.h"
+ #include "XHandlePublic.h"
+ #include "XFileUtils.h"
+-#include "XSyncUtils.h"
+-#include "XEventUtils.h"
+ #include "XTimeUtils.h"
+-#include "XThreadUtils.h"
+ #include "XMemUtils.h"
+ #include "ConvUtils.h"
+
+diff -Naur xbmc-11.0.1/xbmc/linux/XEventUtils.cpp xbmc-11.0.1.patch/xbmc/linux/XEventUtils.cpp
+--- xbmc-11.0.1/xbmc/linux/XEventUtils.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XEventUtils.cpp 1970-01-01 01:00:00.000000000 +0100
+@@ -1,144 +0,0 @@
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "system.h"
+-#include "PlatformDefs.h"
+-#include "XEventUtils.h"
+-#include "XHandle.h"
+-#include "utils/log.h"
+-#include "threads/SingleLock.h"
+-
+-using namespace std;
+-
+-HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName)
+-{
+- CXHandle *pHandle = new CXHandle(CXHandle::HND_EVENT);
+- pHandle->m_bManualEvent = bManualReset;
+- pHandle->m_hCond = new XbmcThreads::ConditionVariable();
+- pHandle->m_hMutex = new CCriticalSection();
+- pHandle->m_bEventSet = false;
+-
+- if (bInitialState)
+- SetEvent(pHandle);
+-
+- return pHandle;
+-}
+-
+-//
+-// The state of a manual-reset event object remains signaled until it is set explicitly to the nonsignaled
+-// state by the ResetEvent function. Any number of waiting threads, or threads that subsequently begin wait
+-// operations for the specified event object by calling one of the wait functions, can be released while the
+-// object's state is signaled.
+-//
+-// The state of an auto-reset event object remains signaled until a single waiting thread is released, at
+-// which time the system automatically sets the state to nonsignaled. If no threads are waiting, the event
+-// object's state remains signaled.
+-//
+-bool WINAPI SetEvent(HANDLE hEvent)
+-{
+- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
+- return false;
+-
+- CSingleLock lock(*(hEvent->m_hMutex));
+- hEvent->m_bEventSet = true;
+-
+- // we must guarantee that these handle's won't be deleted, until we are done
+- list events = hEvent->m_hParents;
+- for(list::iterator it = events.begin();it != events.end();it++)
+- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
+-
+- lock.Leave();
+-
+- for(list::iterator it = events.begin();it != events.end();it++)
+- {
+- SetEvent(*it);
+- CloseHandle(*it);
+- }
+-
+- DuplicateHandle(GetCurrentProcess(), hEvent, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
+-
+- if (hEvent->m_bManualEvent == true)
+- hEvent->m_hCond->notifyAll();
+- else
+- hEvent->m_hCond->notify();
+-
+- CloseHandle(hEvent);
+-
+- return true;
+-}
+-
+-bool WINAPI ResetEvent(HANDLE hEvent)
+-{
+- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
+- return false;
+-
+- CSingleLock lock(*(hEvent->m_hMutex));
+- hEvent->m_bEventSet = false;
+-
+- return true;
+-}
+-
+-bool WINAPI PulseEvent(HANDLE hEvent)
+-{
+- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL)
+- return false;
+-
+- CSingleLock lock(*(hEvent->m_hMutex));
+- // we must guarantee that these handle's won't be deleted, until we are done
+- list events = hEvent->m_hParents;
+- for(list::iterator it = events.begin();it != events.end();it++)
+- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS);
+-
+- if(events.size())
+- {
+- CLog::Log(LOGWARNING,"PulseEvent - ineffecient multiwait detected");
+- hEvent->m_bEventSet = true;
+- }
+-
+- lock.Leave();
+-
+- for(list::iterator it = events.begin();it != events.end();it++)
+- {
+- SetEvent(*it);
+- CloseHandle(*it);
+-
+- if (hEvent->m_bManualEvent == false)
+- break;
+- }
+-
+- // for multiwaits, we must yield some time to get the multiwaits to notice it was signaled
+- if(events.size())
+- Sleep(10);
+-
+- // we should always unset the event on pulse
+- {
+- CSingleLock lock2(*(hEvent->m_hMutex));
+- hEvent->m_bEventSet = false;
+- }
+-
+- if (hEvent->m_bManualEvent == true)
+- hEvent->m_hCond->notifyAll();
+- else
+- hEvent->m_hCond->notify();
+-
+- return true;
+-}
+-
+diff -Naur xbmc-11.0.1/xbmc/linux/XEventUtils.h xbmc-11.0.1.patch/xbmc/linux/XEventUtils.h
+--- xbmc-11.0.1/xbmc/linux/XEventUtils.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XEventUtils.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,38 +0,0 @@
+-#ifndef __X_EVENT_UTIL_H__
+-#define __X_EVENT_UTIL_H__
+-
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "XHandlePublic.h"
+-
+-#ifdef _LINUX
+-
+-HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName);
+-bool WINAPI SetEvent(HANDLE hEvent);
+-bool WINAPI ResetEvent(HANDLE hEvent);
+-bool WINAPI PulseEvent(HANDLE hEvent);
+-
+-#endif
+-
+-
+-#endif
+-
+diff -Naur xbmc-11.0.1/xbmc/linux/XHandle.cpp xbmc-11.0.1.patch/xbmc/linux/XHandle.cpp
+--- xbmc-11.0.1/xbmc/linux/XHandle.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XHandle.cpp 2012-05-13 22:08:46.805190085 +0200
+@@ -20,12 +20,15 @@
+ */
+
+ #include "XHandle.h"
+-#include "XThreadUtils.h"
+ #include "utils/log.h"
+ #include "threads/SingleLock.h"
+
+ int CXHandle::m_objectTracker[10] = {0};
+
++HANDLE WINAPI GetCurrentProcess(void) {
++ return (HANDLE)-1; // -1 a special value - pseudo handle
++}
++
+ CXHandle::CXHandle()
+ {
+ Init();
+@@ -47,11 +50,6 @@
+
+ Init();
+
+- if (m_threadValid)
+- {
+- CLog::Log(LOGERROR, "%s - thread handle copied instead of passed!", __FUNCTION__);
+- }
+-
+ if (src.m_hMutex)
+ m_hMutex = new CCriticalSection();
+
+@@ -80,7 +78,7 @@
+ CLog::Log(LOGERROR,"%s, destroying handle with ref count %d", __FUNCTION__, m_nRefCount);
+ assert(false);
+ }
+-
++
+ if (m_hMutex) {
+ delete m_hMutex;
+ }
+@@ -93,10 +91,6 @@
+ delete m_hCond;
+ }
+
+- if (m_threadValid) {
+- pthread_join(m_hThread, NULL);
+- }
+-
+ if ( fd != 0 ) {
+ close(fd);
+ }
+@@ -107,11 +101,9 @@
+ {
+ fd=0;
+ m_hMutex=NULL;
+- m_threadValid=false;
+ m_hCond=NULL;
+ m_type = HND_NULL;
+ RecursionCount=0;
+- OwningThread=0;
+ m_bManualEvent=FALSE;
+ m_bEventSet=FALSE;
+ m_nFindFileIterator=0 ;
+diff -Naur xbmc-11.0.1/xbmc/linux/XHandle.h xbmc-11.0.1.patch/xbmc/linux/XHandle.h
+--- xbmc-11.0.1/xbmc/linux/XHandle.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XHandle.h 2012-05-13 22:08:46.805190085 +0200
+@@ -25,7 +25,6 @@
+ #ifndef _WIN32
+
+ #include
+-#include
+
+ #include "PlatformDefs.h"
+ #include "XHandlePublic.h"
+@@ -36,7 +35,7 @@
+ struct CXHandle {
+
+ public:
+- typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_THREAD, HND_FIND_FILE } HandleType;
++ typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_FIND_FILE } HandleType;
+
+ CXHandle();
+ CXHandle(HandleType nType);
+@@ -47,8 +46,6 @@
+ inline HandleType GetType() { return m_type; }
+ void ChangeType(HandleType newType);
+
+- ThreadIdentifier m_hThread;
+- bool m_threadValid;
+ XbmcThreads::ConditionVariable *m_hCond;
+ std::list m_hParents;
+
+@@ -62,7 +59,6 @@
+ // simulate mutex and critical section
+ CCriticalSection *m_hMutex;
+ int RecursionCount; // for mutex - for compatibility with WIN32 critical section
+- pthread_t OwningThread;
+ int fd;
+ bool m_bManualEvent;
+ time_t m_tmCreation;
+diff -Naur xbmc-11.0.1/xbmc/linux/XMemUtils.cpp xbmc-11.0.1.patch/xbmc/linux/XMemUtils.cpp
+--- xbmc-11.0.1/xbmc/linux/XMemUtils.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XMemUtils.cpp 2012-05-13 22:08:46.806190105 +0200
+@@ -25,6 +25,10 @@
+
+ #include "XMemUtils.h"
+
++#ifdef __APPLE__
++#include
++#endif
++
+ #undef ALIGN
+ #define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
+
+@@ -49,4 +53,130 @@
+ free(pFull);
+ }
+
++#ifndef _WIN32
++
++#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__)
++static FILE* procMeminfoFP = NULL;
++#endif
++
++void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
++{
++ if (!lpBuffer)
++ return;
++
++ memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
++
++#ifdef __APPLE__
++ uint64_t physmem;
++ size_t len = sizeof physmem;
++ int mib[2] = { CTL_HW, HW_MEMSIZE };
++ size_t miblen = sizeof(mib) / sizeof(mib[0]);
++
++ // Total physical memory.
++ if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
++ lpBuffer->ullTotalPhys = physmem;
++
++ // Virtual memory.
++ mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
++ struct xsw_usage swap;
++ len = sizeof(struct xsw_usage);
++ if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
++ {
++ lpBuffer->ullAvailPageFile = swap.xsu_avail;
++ lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
++ }
++
++ // In use.
++ mach_port_t stat_port = mach_host_self();
++ vm_statistics_data_t vm_stat;
++ mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
++ if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
++ {
++ // Find page size.
++ int pageSize;
++ mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
++ len = sizeof(int);
++ if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
++ {
++ uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
++
++ lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
++ lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
++ }
++ }
++#elif defined(__FreeBSD__)
++ /* sysctl hw.physmem */
++ size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
++ size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
++
++ /* physmem */
++ len = sizeof(physmem);
++ if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
++ lpBuffer->ullTotalPhys = physmem;
++ lpBuffer->ullTotalVirtual = physmem;
++ }
++ /* pagesize */
++ len = sizeof(pagesize);
++ if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
++ pagesize = 4096;
++ /* mem_inactive */
++ len = sizeof(mem_inactive);
++ if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
++ mem_inactive *= pagesize;
++ /* mem_cache */
++ len = sizeof(mem_cache);
++ if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
++ mem_cache *= pagesize;
++ /* mem_free */
++ len = sizeof(mem_free);
++ if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
++ mem_free *= pagesize;
++
++ /* mem_avail = mem_inactive + mem_cache + mem_free */
++ lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
++ lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
++
++ if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
++ lpBuffer->ullAvailPageFile = swap_free * pagesize;
++#else
++ struct sysinfo info;
++ char name[32];
++ unsigned val;
++ if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
++ sysinfo(&info);
++ else
++ {
++ memset(&info, 0, sizeof(struct sysinfo));
++ info.mem_unit = 4096;
++ while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
++ {
++ if (strncmp("MemTotal:", name, 9) == 0)
++ info.totalram = val/4;
++ else if (strncmp("MemFree:", name, 8) == 0)
++ info.freeram = val/4;
++ else if (strncmp("Buffers:", name, 8) == 0)
++ info.bufferram += val/4;
++ else if (strncmp("Cached:", name, 7) == 0)
++ info.bufferram += val/4;
++ else if (strncmp("SwapTotal:", name, 10) == 0)
++ info.totalswap = val/4;
++ else if (strncmp("SwapFree:", name, 9) == 0)
++ info.freeswap = val/4;
++ else if (strncmp("HighTotal:", name, 10) == 0)
++ info.totalhigh = val/4;
++ else if (strncmp("HighFree:", name, 9) == 0)
++ info.freehigh = val/4;
++ }
++ rewind(procMeminfoFP);
++ fflush(procMeminfoFP);
++ }
++ lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
++ lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
++ lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
++ lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
++ lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);
++#endif
++}
++
++#endif
+
+diff -Naur xbmc-11.0.1/xbmc/linux/XMemUtils.h xbmc-11.0.1.patch/xbmc/linux/XMemUtils.h
+--- xbmc-11.0.1/xbmc/linux/XMemUtils.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XMemUtils.h 2012-05-13 22:08:46.806190105 +0200
+@@ -22,10 +22,14 @@
+ *
+ */
+
++#include "linux/PlatformDefs.h"
++
+ // aligned memory allocation and free. memory returned will be aligned to "alignTo" bytes.
+ // this is a linux (actually platfom free) implementation of the win32 CRT methods _aligned_malloc and _aligned_free.
+ void *_aligned_malloc(size_t s, size_t alignTo);
+ void _aligned_free(void *p) ;
+
++void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer);
++
+ #endif
+
+diff -Naur xbmc-11.0.1/xbmc/linux/XSyncUtils.cpp xbmc-11.0.1.patch/xbmc/linux/XSyncUtils.cpp
+--- xbmc-11.0.1/xbmc/linux/XSyncUtils.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XSyncUtils.cpp 1970-01-01 01:00:00.000000000 +0100
+@@ -1,169 +0,0 @@
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#ifndef _WIN32
+-
+-
+-#include
+-#include
+-#include
+-#include
+-#include
+-#ifdef __APPLE__
+-#include
+-#endif
+-
+-#include "XSyncUtils.h"
+-#include "XTimeUtils.h"
+-#include "PlatformDefs.h"
+-#include "XHandle.h"
+-#include "XEventUtils.h"
+-
+-using namespace std;
+-using namespace XbmcThreads;
+-
+-#include "../utils/log.h"
+-#include "../utils/TimeUtils.h"
+-
+-#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__)
+-static FILE* procMeminfoFP = NULL;
+-#endif
+-
+-void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
+-{
+- if (!lpBuffer)
+- return;
+-
+- memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
+-
+-#ifdef __APPLE__
+- uint64_t physmem;
+- size_t len = sizeof physmem;
+- int mib[2] = { CTL_HW, HW_MEMSIZE };
+- size_t miblen = sizeof(mib) / sizeof(mib[0]);
+-
+- // Total physical memory.
+- if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
+- lpBuffer->ullTotalPhys = physmem;
+-
+- // Virtual memory.
+- mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
+- struct xsw_usage swap;
+- len = sizeof(struct xsw_usage);
+- if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
+- {
+- lpBuffer->ullAvailPageFile = swap.xsu_avail;
+- lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
+- }
+-
+- // In use.
+- mach_port_t stat_port = mach_host_self();
+- vm_statistics_data_t vm_stat;
+- mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
+- if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
+- {
+- // Find page size.
+- int pageSize;
+- mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
+- len = sizeof(int);
+- if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
+- {
+- uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
+-
+- lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
+- lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
+- }
+- }
+-#elif defined(__FreeBSD__)
+- /* sysctl hw.physmem */
+- size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
+- size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
+-
+- /* physmem */
+- len = sizeof(physmem);
+- if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
+- lpBuffer->ullTotalPhys = physmem;
+- lpBuffer->ullTotalVirtual = physmem;
+- }
+- /* pagesize */
+- len = sizeof(pagesize);
+- if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
+- pagesize = 4096;
+- /* mem_inactive */
+- len = sizeof(mem_inactive);
+- if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
+- mem_inactive *= pagesize;
+- /* mem_cache */
+- len = sizeof(mem_cache);
+- if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
+- mem_cache *= pagesize;
+- /* mem_free */
+- len = sizeof(mem_free);
+- if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
+- mem_free *= pagesize;
+-
+- /* mem_avail = mem_inactive + mem_cache + mem_free */
+- lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
+- lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
+-
+- if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
+- lpBuffer->ullAvailPageFile = swap_free * pagesize;
+-#else
+- struct sysinfo info;
+- char name[32];
+- unsigned val;
+- if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
+- sysinfo(&info);
+- else
+- {
+- memset(&info, 0, sizeof(struct sysinfo));
+- info.mem_unit = 4096;
+- while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
+- {
+- if (strncmp("MemTotal:", name, 9) == 0)
+- info.totalram = val/4;
+- else if (strncmp("MemFree:", name, 8) == 0)
+- info.freeram = val/4;
+- else if (strncmp("Buffers:", name, 8) == 0)
+- info.bufferram += val/4;
+- else if (strncmp("Cached:", name, 7) == 0)
+- info.bufferram += val/4;
+- else if (strncmp("SwapTotal:", name, 10) == 0)
+- info.totalswap = val/4;
+- else if (strncmp("SwapFree:", name, 9) == 0)
+- info.freeswap = val/4;
+- else if (strncmp("HighTotal:", name, 10) == 0)
+- info.totalhigh = val/4;
+- else if (strncmp("HighFree:", name, 9) == 0)
+- info.freehigh = val/4;
+- }
+- rewind(procMeminfoFP);
+- fflush(procMeminfoFP);
+- }
+- lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
+- lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
+- lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
+- lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
+- lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);
+-#endif
+-}
+-
+-#endif
+diff -Naur xbmc-11.0.1/xbmc/linux/XSyncUtils.h xbmc-11.0.1.patch/xbmc/linux/XSyncUtils.h
+--- xbmc-11.0.1/xbmc/linux/XSyncUtils.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XSyncUtils.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,44 +0,0 @@
+-#ifndef __X_SYNC_UTILS_
+-#define __X_SYNC_UTILS_
+-
+-/*
+- * Copyright (C) 2005-2008 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "PlatformDefs.h"
+-#include "XHandlePublic.h"
+-
+-#ifdef _LINUX
+-
+-#define STATUS_WAIT_0 ((DWORD )0x00000000L)
+-#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
+-#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
+-#define WAIT_TIMEOUT 258L
+-#define INFINITE 0xFFFFFFFF
+-#define STATUS_ABANDONED_WAIT_0 0x00000080
+-#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
+-#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
+-
+-void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer);
+-
+-#endif
+-
+-#endif
+-
+diff -Naur xbmc-11.0.1/xbmc/linux/XThreadUtils.cpp xbmc-11.0.1.patch/xbmc/linux/XThreadUtils.cpp
+--- xbmc-11.0.1/xbmc/linux/XThreadUtils.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/linux/XThreadUtils.cpp 1970-01-01 01:00:00.000000000 +0100
+@@ -1,210 +0,0 @@
+-/*
+- * Copyright (C) 2005-2009 Team XBMC
+- * http://www.xbmc.org
+- *
+- * This Program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This Program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with XBMC; see the file COPYING. If not, write to
+- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+- * http://www.gnu.org/copyleft/gpl.html
+- *
+- */
+-
+-#include "PlatformDefs.h"
+-#include "XHandle.h"
+-#include "XThreadUtils.h"
+-#include "XTimeUtils.h"
+-#include "XEventUtils.h"
+-#include "system.h"
+-#include "utils/log.h"
+-
+-#ifdef _LINUX
+-#include
+-#include
+-#include
+-
+-HANDLE WINAPI CreateThread(
+- LPSECURITY_ATTRIBUTES lpThreadAttributes,
+- SIZE_T dwStackSize,
+- LPTHREAD_START_ROUTINE lpStartAddress,
+- LPVOID lpParameter,
+- DWORD dwCreationFlags,
+- LPDWORD lpThreadId
+- ) {
+-
+- // a thread handle would actually contain an event
+- // the event would mark if the thread is running or not. it will be used in the Wait functions.
+- HANDLE h = CreateEvent(NULL, TRUE, FALSE, NULL);
+- h->ChangeType(CXHandle::HND_THREAD);
+-#ifdef __APPLE__
+- h->m_machThreadPort = MACH_PORT_NULL;
+-#endif
+- pthread_attr_t attr;
+- pthread_attr_init(&attr);
+- if (dwStackSize > PTHREAD_STACK_MIN)
+- pthread_attr_setstacksize(&attr, dwStackSize);
+- if (pthread_create(&(h->m_hThread), &attr, (void*(*)(void*))lpStartAddress, lpParameter) == 0)
+- h->m_threadValid = true;
+- else
+- {
+- CloseHandle(h);
+- h = NULL;
+- }
+- pthread_attr_destroy(&attr);
+-
+- if (h && lpThreadId)
+- // WARNING: This can truncate thread IDs on x86_64.
+- *lpThreadId = (DWORD)h->m_hThread;
+- return h;
+-}
+-
+-
+-#if 0 // Deprecated, use CThread::GetCurrentThreadId() instead
+-DWORD WINAPI GetCurrentThreadId(void) {
+- // WARNING: This can truncate thread IDs on x86_64.
+- return (DWORD)pthread_self();
+-}
+-#endif
+-
+-HANDLE WINAPI GetCurrentThread(void) {
+- return (HANDLE)-1; // -1 a special value - pseudo handle
+-}
+-
+-HANDLE WINAPI GetCurrentProcess(void) {
+- return (HANDLE)-1; // -1 a special value - pseudo handle
+-}
+-
+-HANDLE _beginthreadex(
+- void *security,
+- unsigned stack_size,
+- int ( *start_address )( void * ),
+- void *arglist,
+- unsigned initflag,
+- unsigned *thrdaddr
+-) {
+-
+- HANDLE h = CreateThread(NULL, stack_size, start_address, arglist, initflag, (LPDWORD)thrdaddr);
+- return h;
+-
+-}
+-
+-uintptr_t _beginthread(
+- void( *start_address )( void * ),
+- unsigned stack_size,
+- void *arglist
+-) {
+- HANDLE h = CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)start_address, arglist, 0, NULL);
+- return (uintptr_t)h;
+-}
+-
+-BOOL WINAPI GetThreadTimes (
+- HANDLE hThread,
+- LPFILETIME lpCreationTime,
+- LPFILETIME lpExitTime,
+- LPFILETIME lpKernelTime,
+- LPFILETIME lpUserTime
+-) {
+- if (!hThread)
+- return false;
+- if (!hThread->m_threadValid)
+- return false;
+-
+- if (hThread == (HANDLE)-1) {
+- if (lpCreationTime)
+- TimeTToFileTime(0,lpCreationTime);
+- if (lpExitTime)
+- TimeTToFileTime(time(NULL),lpExitTime);
+- if (lpKernelTime)
+- TimeTToFileTime(0,lpKernelTime);
+- if (lpUserTime)
+- TimeTToFileTime(0,lpUserTime);
+-
+- return true;
+- }
+-
+- if (lpCreationTime)
+- TimeTToFileTime(hThread->m_tmCreation,lpCreationTime);
+- if (lpExitTime)
+- TimeTToFileTime(time(NULL),lpExitTime);
+- if (lpKernelTime)
+- TimeTToFileTime(0,lpKernelTime);
+-
+-#ifdef __APPLE__
+- thread_info_data_t threadInfo;
+- mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX;
+-
+- if (hThread->m_machThreadPort == MACH_PORT_NULL)
+- hThread->m_machThreadPort = pthread_mach_thread_np(hThread->m_hThread);
+-
+- kern_return_t ret = thread_info(hThread->m_machThreadPort, THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount);
+- if (ret == KERN_SUCCESS)
+- {
+- thread_basic_info_t threadBasicInfo = (thread_basic_info_t)threadInfo;
+-
+- if (lpUserTime)
+- {
+- // User time.
+- unsigned long long time = ((__int64)threadBasicInfo->user_time.seconds * 10000000L) + threadBasicInfo->user_time.microseconds*10L;
+- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF);
+- lpUserTime->dwHighDateTime = (time >> 32);
+- }
+-
+- if (lpKernelTime)
+- {
+- // System time.
+- unsigned long long time = ((__int64)threadBasicInfo->system_time.seconds * 10000000L) + threadBasicInfo->system_time.microseconds*10L;
+- lpKernelTime->dwLowDateTime = (time & 0xFFFFFFFF);
+- lpKernelTime->dwHighDateTime = (time >> 32);
+- }
+- }
+- else
+- {
+- if (lpUserTime)
+- lpUserTime->dwLowDateTime = lpUserTime->dwHighDateTime = 0;
+-
+- if (lpKernelTime)
+- lpKernelTime->dwLowDateTime = lpKernelTime->dwHighDateTime = 0;
+- }
+-#elif _POSIX_THREAD_CPUTIME != -1
+- if(lpUserTime)
+- {
+- lpUserTime->dwLowDateTime = 0;
+- lpUserTime->dwHighDateTime = 0;
+- clockid_t clock;
+- if (pthread_getcpuclockid(hThread->m_hThread, &clock) == 0)
+- {
+- struct timespec tp = {};
+- clock_gettime(clock, &tp);
+- unsigned long long time = (unsigned long long)tp.tv_sec * 10000000 + (unsigned long long)tp.tv_nsec/100;
+- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF);
+- lpUserTime->dwHighDateTime = (time >> 32);
+- }
+- }
+-#else
+- if (lpUserTime)
+- TimeTToFileTime(0,lpUserTime);
+-#endif
+- return true;
+-}
+-
+-BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority)
+-{
+- return true;
+-}
+-
+-int GetThreadPriority(HANDLE hThread)
+-{
+- return 0;
+-}
+-
+-#endif
+-
+diff -Naur xbmc-11.0.1/xbmc/music/infoscanner/MusicInfoScanner.cpp xbmc-11.0.1.patch/xbmc/music/infoscanner/MusicInfoScanner.cpp
+--- xbmc-11.0.1/xbmc/music/infoscanner/MusicInfoScanner.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/music/infoscanner/MusicInfoScanner.cpp 2012-05-13 22:08:46.811190206 +0200
+@@ -57,7 +57,7 @@
+ using namespace XFILE;
+ using namespace MUSIC_GRABBER;
+
+-CMusicInfoScanner::CMusicInfoScanner()
++CMusicInfoScanner::CMusicInfoScanner() : CThread("CMusicInfoScanner")
+ {
+ m_bRunning = false;
+ m_pObserver = NULL;
+@@ -99,7 +99,7 @@
+
+ // Create the thread to count all files to be scanned
+ SetPriority( GetMinPriority() );
+- CThread fileCountReader(this);
++ CThread fileCountReader(this, "CMusicInfoScanner");
+ if (m_pObserver)
+ fileCountReader.Create();
+
+diff -Naur xbmc-11.0.1/xbmc/music/infoscanner/MusicInfoScraper.cpp xbmc-11.0.1.patch/xbmc/music/infoscanner/MusicInfoScraper.cpp
+--- xbmc-11.0.1/xbmc/music/infoscanner/MusicInfoScraper.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/music/infoscanner/MusicInfoScraper.cpp 2012-05-13 22:08:46.812190226 +0200
+@@ -28,7 +28,7 @@
+ using namespace ADDON;
+ using namespace std;
+
+-CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper)
++CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper) : CThread("CMusicInfoScraper")
+ {
+ m_bSucceeded=false;
+ m_bCanceled=false;
+diff -Naur xbmc-11.0.1/xbmc/music/LastFmManager.cpp xbmc-11.0.1.patch/xbmc/music/LastFmManager.cpp
+--- xbmc-11.0.1/xbmc/music/LastFmManager.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/music/LastFmManager.cpp 2012-05-13 22:08:46.810190186 +0200
+@@ -70,7 +70,7 @@
+
+ CLastFmManager* CLastFmManager::m_pInstance=NULL;
+
+-CLastFmManager::CLastFmManager()
++CLastFmManager::CLastFmManager() : CThread("CLastFmManager")
+ {
+ m_RadioTrackQueue = new CPlayList;
+ }
+@@ -534,7 +534,7 @@
+ if (iNrCachedTracks == 0)
+ {
+ //get more tracks
+- if (ThreadHandle() != NULL)
++ if (IsRunning())
+ {
+ m_hWorkerEvent.Set();
+ }
+@@ -633,7 +633,7 @@
+ {
+ m_RadioSession = "";
+ }
+- if (m_ThreadHandle)
++ if (IsRunning())
+ {
+ m_bStop = true;
+ m_hWorkerEvent.Set();
+diff -Naur xbmc-11.0.1/xbmc/network/AirPlayServer.cpp xbmc-11.0.1.patch/xbmc/network/AirPlayServer.cpp
+--- xbmc-11.0.1/xbmc/network/AirPlayServer.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/AirPlayServer.cpp 2012-05-13 22:08:46.813190246 +0200
+@@ -184,7 +184,7 @@
+ }
+ }
+
+-CAirPlayServer::CAirPlayServer(int port, bool nonlocal)
++CAirPlayServer::CAirPlayServer(int port, bool nonlocal) : CThread("AirPlayServer")
+ {
+ m_port = port;
+ m_nonlocal = nonlocal;
+diff -Naur xbmc-11.0.1/xbmc/network/AirTunesServer.cpp xbmc-11.0.1.patch/xbmc/network/AirTunesServer.cpp
+--- xbmc-11.0.1/xbmc/network/AirTunesServer.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/AirTunesServer.cpp 2012-05-13 22:08:46.871191395 +0200
+@@ -292,7 +292,7 @@
+ }
+ }
+
+-CAirTunesServer::CAirTunesServer(int port, bool nonlocal)
++CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("CAirTunesServer")
+ {
+ m_port = port;
+ m_pLibShairport = new DllLibShairport();
+diff -Naur xbmc-11.0.1/xbmc/network/libscrobbler/scrobbler.cpp xbmc-11.0.1.patch/xbmc/network/libscrobbler/scrobbler.cpp
+--- xbmc-11.0.1/xbmc/network/libscrobbler/scrobbler.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/libscrobbler/scrobbler.cpp 2012-05-13 22:08:46.816190305 +0200
+@@ -46,7 +46,7 @@
+ #define SCROBBLER_ACTION_NOWPLAYING 2
+
+ CScrobbler::CScrobbler(const CStdString &strHandshakeURL, const CStdString &strLogPrefix)
+- : CThread()
++ : CThread("CScrobbler")
+ {
+ m_bBanned = false;
+ m_bBadAuth = false;
+@@ -67,7 +67,7 @@
+ ResetState();
+ LoadCredentials();
+ LoadJournal();
+- if (!ThreadHandle())
++ if (!IsRunning())
+ Create();
+ }
+
+diff -Naur xbmc-11.0.1/xbmc/network/Network.h xbmc-11.0.1.patch/xbmc/network/Network.h
+--- xbmc-11.0.1/xbmc/network/Network.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/Network.h 2012-05-13 22:08:46.813190246 +0200
+@@ -24,6 +24,7 @@
+
+ #include
+ #include "utils/StdString.h"
++#include "system.h"
+
+ enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 };
+ enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 };
+diff -Naur xbmc-11.0.1/xbmc/network/TCPServer.cpp xbmc-11.0.1.patch/xbmc/network/TCPServer.cpp
+--- xbmc-11.0.1/xbmc/network/TCPServer.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/TCPServer.cpp 2012-05-13 22:08:46.814190266 +0200
+@@ -85,7 +85,7 @@
+ }
+ }
+
+-CTCPServer::CTCPServer(int port, bool nonlocal)
++CTCPServer::CTCPServer(int port, bool nonlocal) : CThread("CTCPServer")
+ {
+ m_port = port;
+ m_nonlocal = nonlocal;
+diff -Naur xbmc-11.0.1/xbmc/network/UdpClient.cpp xbmc-11.0.1.patch/xbmc/network/UdpClient.cpp
+--- xbmc-11.0.1/xbmc/network/UdpClient.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/UdpClient.cpp 2012-05-13 22:08:46.814190266 +0200
+@@ -35,7 +35,7 @@
+
+ #define UDPCLIENT_DEBUG_LEVEL LOGDEBUG
+
+-CUdpClient::CUdpClient(void) : CThread()
++CUdpClient::CUdpClient(void) : CThread("CUdpClient")
+ {}
+
+ CUdpClient::~CUdpClient(void)
+diff -Naur xbmc-11.0.1/xbmc/network/UdpClient.h xbmc-11.0.1.patch/xbmc/network/UdpClient.h
+--- xbmc-11.0.1/xbmc/network/UdpClient.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/network/UdpClient.h 2012-05-13 22:08:46.815190286 +0200
+@@ -25,6 +25,7 @@
+ #include "threads/CriticalSection.h"
+ #include
+ #include
++#include "system.h"
+
+ class CUdpClient : CThread
+ {
+diff -Naur xbmc-11.0.1/xbmc/peripherals/Peripherals.cpp xbmc-11.0.1.patch/xbmc/peripherals/Peripherals.cpp
+--- xbmc-11.0.1/xbmc/peripherals/Peripherals.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/peripherals/Peripherals.cpp 2012-05-13 22:08:46.940192765 +0200
+@@ -19,6 +19,7 @@
+ *
+ */
+
++#include "system.h"
+ #include "Peripherals.h"
+ #include "bus/PeripheralBus.h"
+ #include "devices/PeripheralBluetooth.h"
+diff -Naur xbmc-11.0.1/xbmc/pictures/GUIWindowSlideShow.cpp xbmc-11.0.1.patch/xbmc/pictures/GUIWindowSlideShow.cpp
+--- xbmc-11.0.1/xbmc/pictures/GUIWindowSlideShow.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/pictures/GUIWindowSlideShow.cpp 2012-05-13 22:08:46.816190305 +0200
+@@ -67,7 +67,7 @@
+
+ static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f };
+
+-CBackgroundPicLoader::CBackgroundPicLoader()
++CBackgroundPicLoader::CBackgroundPicLoader() : CThread("CBackgroundPicLoader")
+ {
+ m_pCallback = NULL;
+ m_isLoading = false;
+diff -Naur xbmc-11.0.1/xbmc/rendering/dx/RenderSystemDX.cpp xbmc-11.0.1.patch/xbmc/rendering/dx/RenderSystemDX.cpp
+--- xbmc-11.0.1/xbmc/rendering/dx/RenderSystemDX.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/rendering/dx/RenderSystemDX.cpp 2012-05-13 22:08:46.817190325 +0200
+@@ -569,7 +569,7 @@
+
+ //CVideoReferenceClock polls GetRasterStatus too,
+ //polling it from two threads at the same time is bad
+- if (g_advancedSettings.m_sleepBeforeFlip > 0 && g_VideoReferenceClock.ThreadHandle() == NULL)
++ if (g_advancedSettings.m_sleepBeforeFlip > 0 && !g_VideoReferenceClock.IsRunning())
+ {
+ //save current thread priority and set thread priority to THREAD_PRIORITY_TIME_CRITICAL
+ int priority = GetThreadPriority(GetCurrentThread());
+diff -Naur xbmc-11.0.1/xbmc/settings/AdvancedSettings.cpp xbmc-11.0.1.patch/xbmc/settings/AdvancedSettings.cpp
+--- xbmc-11.0.1/xbmc/settings/AdvancedSettings.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/settings/AdvancedSettings.cpp 2012-05-13 22:08:47.021194373 +0200
+@@ -96,12 +96,18 @@
+ m_videoAllowMpeg4VAAPI = false;
+ m_videoDisableBackgroundDeinterlace = false;
+ m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect
++ m_videoVDPAUdeintHD = -1;
++ m_videoVDPAUdeintSD = -1;
++ m_videoVDPAUtelecine = false;
++ m_videoVDPAUmaxHeight = -1;
++ m_videoVDPAUdeintSkipChromaHD = false;
+ m_DXVACheckCompatibility = false;
+ m_DXVACheckCompatibilityPresent = false;
+ m_DXVAForceProcessorRenderer = true;
+ m_DXVANoDeintProcForProgressive = false;
+ m_videoFpsDetect = 1;
+ m_videoDefaultLatency = 0.0;
++ m_vblankPolling = false;
+
+ m_musicUseTimeSeeking = true;
+ m_musicTimeSeekForward = 10;
+@@ -455,6 +461,11 @@
+ XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI);
+ XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
+ XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
++ XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD);
++ XMLUtils::GetInt(pElement,"vdpauSDdeint",m_videoVDPAUdeintSD);
++ XMLUtils::GetInt(pElement,"vdpauMaxHeight",m_videoVDPAUmaxHeight);
++ XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine);
++ XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD);
+
+ TiXmlElement* pAdjustRefreshrate = pElement->FirstChildElement("adjustrefreshrate");
+ if (pAdjustRefreshrate)
+@@ -544,6 +555,8 @@
+ //0 = disable fps detect, 1 = only detect on timestamps with uniform spacing, 2 detect on all timestamps
+ XMLUtils::GetInt(pElement, "fpsdetect", m_videoFpsDetect, 0, 2);
+
++ XMLUtils::GetBoolean(pElement,"vblankpolling", m_vblankPolling);
++
+ // Store global display latency settings
+ TiXmlElement* pVideoLatency = pElement->FirstChildElement("latency");
+ if (pVideoLatency)
+diff -Naur xbmc-11.0.1/xbmc/settings/AdvancedSettings.h xbmc-11.0.1.patch/xbmc/settings/AdvancedSettings.h
+--- xbmc-11.0.1/xbmc/settings/AdvancedSettings.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/settings/AdvancedSettings.h 2012-05-13 22:08:47.022194393 +0200
+@@ -111,6 +111,11 @@
+ int m_videoPercentSeekBackwardBig;
+ CStdString m_videoPPFFmpegDeint;
+ CStdString m_videoPPFFmpegPostProc;
++ int m_videoVDPAUdeintHD;
++ int m_videoVDPAUdeintSD;
++ bool m_videoVDPAUtelecine;
++ int m_videoVDPAUmaxHeight;
++ bool m_videoVDPAUdeintSkipChromaHD;
+ bool m_musicUseTimeSeeking;
+ int m_musicTimeSeekForward;
+ int m_musicTimeSeekBackward;
+@@ -143,6 +148,7 @@
+ bool m_DXVAForceProcessorRenderer;
+ bool m_DXVANoDeintProcForProgressive;
+ int m_videoFpsDetect;
++ bool m_vblankPolling;
+
+ CStdString m_videoDefaultPlayer;
+ CStdString m_videoDefaultDVDPlayer;
+diff -Naur xbmc-11.0.1/xbmc/settings/GUISettings.cpp xbmc-11.0.1.patch/xbmc/settings/GUISettings.cpp
+--- xbmc-11.0.1/xbmc/settings/GUISettings.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/settings/GUISettings.cpp 2012-05-13 22:08:46.957193103 +0200
+@@ -583,10 +583,15 @@
+
+ #ifdef HAVE_LIBVDPAU
+ AddBool(vp, "videoplayer.usevdpau", 13425, true);
++ AddBool(vp, "videoplayer.usevdpauinteroprgb", 13433, true);
++ AddBool(vp, "videoplayer.usevdpauinteropyuv", 13434, true);
+ #endif
+ #ifdef HAVE_LIBVA
+ AddBool(vp, "videoplayer.usevaapi", 13426, true);
+ #endif
++#ifdef HAVE_LIBXVBA
++ AddBool(vp, "videoplayer.usexvba", 13435, true);
++#endif
+ #ifdef HAS_DX
+ AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false);
+ #endif
+diff -Naur xbmc-11.0.1/xbmc/settings/GUIWindowSettingsCategory.cpp xbmc-11.0.1.patch/xbmc/settings/GUIWindowSettingsCategory.cpp
+--- xbmc-11.0.1/xbmc/settings/GUIWindowSettingsCategory.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/settings/GUIWindowSettingsCategory.cpp 2012-05-13 22:08:46.682187646 +0200
+@@ -549,6 +549,40 @@
+ pControl->SetEnabled(true);
+ }
+ }
++ else if (strSetting.Equals("videoplayer.usevdpauinteropyuv"))
++ {
++ bool hasInterop = false;
++#ifdef GL_NV_vdpau_interop
++ hasInterop = true;
++#endif
++ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
++ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop"))
++ {
++ pControl->SetEnabled(true);
++ }
++ else
++ {
++ pControl->SetEnabled(false);
++ g_guiSettings.SetBool("videoplayer.usevdpauinteropyuv",false);
++ }
++ }
++ else if (strSetting.Equals("videoplayer.usevdpauinteroprgb"))
++ {
++ bool hasInterop = false;
++#ifdef GL_NV_vdpau_interop
++ hasInterop = true;
++#endif
++ CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
++ if (pControl && hasInterop && glewIsSupported("GL_NV_vdpau_interop"))
++ {
++ pControl->SetEnabled(true);
++ }
++ else
++ {
++ pControl->SetEnabled(false);
++ g_guiSettings.SetBool("videoplayer.usevdpauinteroprgb",false);
++ }
++ }
+ else
+ #endif
+ if (strSetting.Equals("videoscreen.resolution"))
+diff -Naur xbmc-11.0.1/xbmc/settings/VideoSettings.h xbmc-11.0.1.patch/xbmc/settings/VideoSettings.h
+--- xbmc-11.0.1/xbmc/settings/VideoSettings.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/settings/VideoSettings.h 2012-05-13 22:08:46.958193123 +0200
+@@ -67,6 +67,8 @@
+
+ VS_INTERLACEMETHOD_SW_BLEND = 20,
+
++ VS_INTERLACEMETHOD_XVBA = 22,
++
+ VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value.
+ };
+
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp xbmc-11.0.1.patch/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp
+--- xbmc-11.0.1/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp 2012-05-13 22:08:46.821190405 +0200
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++int CThread::GetSchedRRPriority(void)
++{
++ return 96;
++}
++
++bool CThread::SetPrioritySched_RR(int iPriority)
++{
++ // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the
++ // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects
++ // the thread running away. OSX automatically does this with the CoreAudio audio
++ // device handler thread.
++ int32_t result;
++ thread_extended_policy_data_t theFixedPolicy;
++
++ // make thread fixed, set to 'true' for a non-fixed thread
++ theFixedPolicy.timeshare = false;
++ result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY,
++ (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
++
++ int policy;
++ struct sched_param param;
++ result = pthread_getschedparam(ThreadId(), &policy, ¶m );
++ // change from default SCHED_OTHER to SCHED_RR
++ policy = SCHED_RR;
++ result = pthread_setschedparam(ThreadId(), policy, ¶m );
++}
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/linux/ThreadSchedImpl.cpp xbmc-11.0.1.patch/xbmc/threads/platform/linux/ThreadSchedImpl.cpp
+--- xbmc-11.0.1/xbmc/threads/platform/linux/ThreadSchedImpl.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/linux/ThreadSchedImpl.cpp 2012-05-13 22:08:46.821190405 +0200
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++int CThread::GetSchedRRPriority(void)
++{
++ return GetNormalPriority();
++}
++
++bool CThread::SetPrioritySched_RR(int iPriority)
++{
++ return false;
++}
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/pthreads/ThreadImpl.cpp xbmc-11.0.1.patch/xbmc/threads/platform/pthreads/ThreadImpl.cpp
+--- xbmc-11.0.1/xbmc/threads/platform/pthreads/ThreadImpl.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/pthreads/ThreadImpl.cpp 2012-05-13 22:08:46.822190424 +0200
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include
++#include
++#include
++#include
++
++void CThread::Create(bool bAutoDelete, unsigned stacksize)
++{
++ if (m_ThreadId != 0)
++ {
++ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
++ exit(1);
++ }
++ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
++ m_iLastUsage = 0;
++ m_fLastUsage = 0.0f;
++ m_bAutoDelete = bAutoDelete;
++ m_bStop = false;
++ m_StopEvent.Reset();
++ m_TermEvent.Reset();
++ m_StartEvent.Reset();
++
++ pthread_attr_t attr;
++ pthread_attr_init(&attr);
++ if (stacksize > PTHREAD_STACK_MIN)
++ pthread_attr_setstacksize(&attr, stacksize);
++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++ if (pthread_create(&m_ThreadId, &attr, (void*(*)(void*))staticThread, this) != 0)
++ {
++ CLog::Log(LOGNOTICE, "%s - fatal error creating thread",__FUNCTION__);
++ }
++ pthread_attr_destroy(&attr);
++}
++
++void CThread::TermHandler()
++{
++
++}
++
++void CThread::SetThreadInfo()
++{
++ m_ThreadOpaque.LwpId = syscall(SYS_gettid);
++
++ // start thread with nice level of appication
++ int appNice = getpriority(PRIO_PROCESS, getpid());
++ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0)
++ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno));
++}
++
++ThreadIdentifier CThread::GetCurrentThreadId()
++{
++ return pthread_self();
++}
++
++bool CThread::IsCurrentThread(const ThreadIdentifier tid)
++{
++ return pthread_equal(pthread_self(), tid);
++}
++
++int CThread::GetMinPriority(void)
++{
++ // one level lower than application
++ return -1;
++}
++
++int CThread::GetMaxPriority(void)
++{
++ // one level higher than application
++ return 1;
++}
++
++int CThread::GetNormalPriority(void)
++{
++ // same level as application
++ return 0;
++}
++
++bool CThread::SetPriority(const int iPriority)
++{
++ bool bReturn = false;
++
++ // wait until thread is running, it needs to get its lwp id
++ m_StartEvent.Wait();
++
++ CSingleLock lock(m_CriticalSection);
++
++ // get min prio for SCHED_RR
++ int minRR = GetMaxPriority() + 1;
++
++ if (!m_ThreadId)
++ bReturn = false;
++ else if (iPriority >= minRR)
++ bReturn = SetPrioritySched_RR(iPriority);
++ else
++ {
++ // get user max prio
++ struct rlimit limit;
++ int userMaxPrio;
++ if (getrlimit(RLIMIT_NICE, &limit) == 0)
++ {
++ userMaxPrio = limit.rlim_cur - 20;
++ }
++ else
++ userMaxPrio = 0;
++
++ // keep priority in bounds
++ int prio = iPriority;
++ if (prio >= GetMaxPriority())
++ prio = std::min(GetMaxPriority(), userMaxPrio);
++ if (prio < GetMinPriority())
++ prio = GetMinPriority();
++
++ // nice level of application
++ int appNice = getpriority(PRIO_PROCESS, getpid());
++ if (prio)
++ prio = prio > 0 ? appNice-1 : appNice+1;
++
++ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, prio) == 0)
++ bReturn = true;
++ else
++ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno));
++ }
++
++ return bReturn;
++}
++
++int CThread::GetPriority()
++{
++ int iReturn;
++
++ // lwp id is valid after start signel has fired
++ m_StartEvent.Wait();
++
++ CSingleLock lock(m_CriticalSection);
++
++ int appNice = getpriority(PRIO_PROCESS, getpid());
++ int prio = getpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId);
++ iReturn = appNice - prio;
++
++ return iReturn;
++}
++
++bool CThread::WaitForThreadExit(unsigned int milliseconds)
++{
++ bool bReturn = m_TermEvent.WaitMSec(milliseconds);
++
++ return bReturn;
++}
++
++int64_t CThread::GetAbsoluteUsage()
++{
++ CSingleLock lock(m_CriticalSection);
++
++ if (!m_ThreadId)
++ return 0;
++
++ clockid_t clock;
++ int64_t time = 0;
++ if (pthread_getcpuclockid(m_ThreadId, &clock) == 0)
++ {
++ struct timespec tp;
++ clock_gettime(clock, &tp);
++ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100;
++ }
++ return time;
++}
++
++float CThread::GetRelativeUsage()
++{
++ unsigned int iTime = XbmcThreads::SystemClockMillis();
++ iTime *= 10000; // convert into 100ns tics
++
++ // only update every 1 second
++ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
++
++ int64_t iUsage = GetAbsoluteUsage();
++
++ if (m_iLastUsage > 0 && m_iLastTime > 0)
++ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
++
++ m_iLastUsage = iUsage;
++ m_iLastTime = iTime;
++
++ return m_fLastUsage;
++}
++
++int64_t CThread::GetCurrentThreadUsage()
++{
++ pthread_t tid = pthread_self();
++ clockid_t clock;
++ int64_t time = 0;
++ if (pthread_getcpuclockid(tid, &clock) == 0)
++ {
++ struct timespec tp;
++ clock_gettime(clock, &tp);
++ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100;
++ }
++ return time;
++}
++
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/pthreads/ThreadImpl.h xbmc-11.0.1.patch/xbmc/threads/platform/pthreads/ThreadImpl.h
+--- xbmc-11.0.1/xbmc/threads/platform/pthreads/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/pthreads/ThreadImpl.h 2012-05-13 22:08:46.822190424 +0200
+@@ -0,0 +1,39 @@
++/*
++* Copyright (C) 2005-2011 Team XBMC
++* http://www.xbmc.org
++*
++* This Program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by
++* the Free Software Foundation; either version 2, or (at your option)
++* any later version.
++*
++* This Program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with XBMC; see the file COPYING. If not, write to
++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++* http://www.gnu.org/copyleft/gpl.html
++*
++*/
++
++#pragma once
++
++#include
++
++struct threadOpaque
++{
++ pid_t LwpId;
++};
++
++typedef pthread_t ThreadIdentifier;
++typedef threadOpaque ThreadOpaque;
++typedef int THREADFUNC;
++
++namespace XbmcThreads
++{
++ inline static void ThreadSleep(unsigned int millis) { usleep(millis*1000); }
++}
++
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/ThreadImpl.cpp xbmc-11.0.1.patch/xbmc/threads/platform/ThreadImpl.cpp
+--- xbmc-11.0.1/xbmc/threads/platform/ThreadImpl.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/ThreadImpl.cpp 2012-05-13 22:08:46.820190385 +0200
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#pragma once
++
++#if (defined TARGET_POSIX)
++#include "threads/platform/pthreads/ThreadImpl.cpp"
++#if defined(TARGET_DARWIN_IOS)
++#include "threads/platform/darwin/ThreadSchedImpl.cpp"
++#else
++#include "threads/platform/linux/ThreadSchedImpl.cpp"
++#endif
++#elif (defined TARGET_WINDOWS)
++#include "threads/platform/win/ThreadImpl.cpp"
++#endif
++
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/ThreadImpl.h xbmc-11.0.1.patch/xbmc/threads/platform/ThreadImpl.h
+--- xbmc-11.0.1/xbmc/threads/platform/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/ThreadImpl.h 2012-05-13 22:08:46.820190385 +0200
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#pragma once
++
++#if (defined TARGET_POSIX)
++#include "threads/platform/pthreads/ThreadImpl.h"
++#elif (defined TARGET_WINDOWS)
++#include "threads/platform/win/ThreadImpl.h"
++#endif
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/win/ThreadImpl.cpp xbmc-11.0.1.patch/xbmc/threads/platform/win/ThreadImpl.cpp
+--- xbmc-11.0.1/xbmc/threads/platform/win/ThreadImpl.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/win/ThreadImpl.cpp 2012-05-13 22:08:46.823190444 +0200
+@@ -0,0 +1,207 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include
++
++
++void CThread::Create(bool bAutoDelete, unsigned stacksize)
++{
++ if (m_ThreadId != 0)
++ {
++ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__);
++ exit(1);
++ }
++ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
++ m_iLastUsage = 0;
++ m_fLastUsage = 0.0f;
++ m_bAutoDelete = bAutoDelete;
++ m_bStop = false;
++ m_StopEvent.Reset();
++ m_TermEvent.Reset();
++ m_StartEvent.Reset();
++
++ m_ThreadOpaque.handle = CreateThread(NULL,stacksize, (LPTHREAD_START_ROUTINE)&staticThread, this, 0, &m_ThreadId);
++ if (m_ThreadOpaque.handle == NULL)
++ {
++ CLog::Log(LOGERROR, "%s - fatal error creating thread", __FUNCTION__);
++ }
++}
++
++void CThread::TermHandler()
++{
++ CloseHandle(m_ThreadOpaque.handle);
++ m_ThreadOpaque.handle = NULL;
++}
++
++void CThread::SetThreadInfo()
++{
++ const unsigned int MS_VC_EXCEPTION = 0x406d1388;
++ struct THREADNAME_INFO
++ {
++ DWORD dwType; // must be 0x1000
++ LPCSTR szName; // pointer to name (in same addr space)
++ DWORD dwThreadID; // thread ID (-1 caller thread)
++ DWORD dwFlags; // reserved for future use, most be zero
++ } info;
++
++ info.dwType = 0x1000;
++ info.szName = m_ThreadName.c_str();
++ info.dwThreadID = m_ThreadId;
++ info.dwFlags = 0;
++
++ try
++ {
++ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
++ }
++ catch(...)
++ {
++ }
++}
++
++ThreadIdentifier CThread::GetCurrentThreadId()
++{
++ return ::GetCurrentThreadId();
++}
++
++bool CThread::IsCurrentThread(const ThreadIdentifier tid)
++{
++ return (::GetCurrentThreadId() == tid);
++}
++
++int CThread::GetMinPriority(void)
++{
++ return(THREAD_PRIORITY_IDLE);
++}
++
++int CThread::GetMaxPriority(void)
++{
++ return(THREAD_PRIORITY_HIGHEST);
++}
++
++int CThread::GetNormalPriority(void)
++{
++ return(THREAD_PRIORITY_NORMAL);
++}
++
++int CThread::GetSchedRRPriority(void)
++{
++ return GetNormalPriority();
++}
++
++bool CThread::SetPriority(const int iPriority)
++{
++ bool bReturn = false;
++
++ CSingleLock lock(m_CriticalSection);
++ if (m_ThreadOpaque.handle)
++ {
++ bReturn = SetThreadPriority(m_ThreadOpaque.handle, iPriority) == TRUE;
++ }
++
++ return bReturn;
++}
++
++int CThread::GetPriority()
++{
++ CSingleLock lock(m_CriticalSection);
++
++ int iReturn = THREAD_PRIORITY_NORMAL;
++ if (m_ThreadOpaque.handle)
++ {
++ iReturn = GetThreadPriority(m_ThreadOpaque.handle);
++ }
++ return iReturn;
++}
++
++bool CThread::WaitForThreadExit(unsigned int milliseconds)
++{
++ bool bReturn = true;
++
++ CSingleLock lock(m_CriticalSection);
++ if (m_ThreadId && m_ThreadOpaque.handle != NULL)
++ {
++ // boost priority of thread we are waiting on to same as caller
++ int callee = GetThreadPriority(m_ThreadOpaque.handle);
++ int caller = GetThreadPriority(GetCurrentThread());
++ if(caller > callee)
++ SetThreadPriority(m_ThreadOpaque.handle, caller);
++
++ lock.Leave();
++ bReturn = m_TermEvent.WaitMSec(milliseconds);
++ lock.Enter();
++
++ // restore thread priority if thread hasn't exited
++ if(caller > callee && m_ThreadOpaque.handle)
++ SetThreadPriority(m_ThreadOpaque.handle, callee);
++ }
++ return bReturn;
++}
++
++int64_t CThread::GetAbsoluteUsage()
++{
++ CSingleLock lock(m_CriticalSection);
++
++ if (!m_ThreadOpaque.handle)
++ return 0;
++
++ uint64_t time = 0;
++ FILETIME CreationTime, ExitTime, UserTime, KernelTime;
++ if( GetThreadTimes(m_ThreadOpaque.handle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
++ {
++ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
++ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
++ }
++ return time;
++}
++
++float CThread::GetRelativeUsage()
++{
++ unsigned int iTime = XbmcThreads::SystemClockMillis();
++ iTime *= 10000; // convert into 100ns tics
++
++ // only update every 1 second
++ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
++
++ int64_t iUsage = GetAbsoluteUsage();
++
++ if (m_iLastUsage > 0 && m_iLastTime > 0)
++ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
++
++ m_iLastUsage = iUsage;
++ m_iLastTime = iTime;
++
++ return m_fLastUsage;
++}
++
++int64_t CThread::GetCurrentThreadUsage()
++{
++ HANDLE h = GetCurrentThread();
++
++ uint64_t time = 0;
++ FILETIME CreationTime, ExitTime, UserTime, KernelTime;
++ if( GetThreadTimes(h, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
++ {
++ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime);
++ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime);
++ }
++ return time;
++}
++
+diff -Naur xbmc-11.0.1/xbmc/threads/platform/win/ThreadImpl.h xbmc-11.0.1.patch/xbmc/threads/platform/win/ThreadImpl.h
+--- xbmc-11.0.1/xbmc/threads/platform/win/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/platform/win/ThreadImpl.h 2012-05-13 22:08:46.823190444 +0200
+@@ -0,0 +1,40 @@
++/*
++* Copyright (C) 2005-2011 Team XBMC
++* http://www.xbmc.org
++*
++* This Program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by
++* the Free Software Foundation; either version 2, or (at your option)
++* any later version.
++*
++* This Program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with XBMC; see the file COPYING. If not, write to
++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++* http://www.gnu.org/copyleft/gpl.html
++*
++*/
++
++#pragma once
++
++#include
++
++
++struct threadOpaque
++{
++ HANDLE handle;
++};
++
++typedef DWORD ThreadIdentifier;
++typedef threadOpaque ThreadOpaque;
++typedef DWORD THREADFUNC;
++
++namespace XbmcThreads
++{
++ inline static void ThreadSleep(unsigned int millis) { Sleep(millis); }
++}
++
+diff -Naur xbmc-11.0.1/xbmc/threads/Thread.cpp xbmc-11.0.1.patch/xbmc/threads/Thread.cpp
+--- xbmc-11.0.1/xbmc/threads/Thread.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/Thread.cpp 2012-05-13 22:08:46.872191415 +0200
+@@ -20,41 +20,27 @@
+
+ #include "threads/SystemClock.h"
+ #include "Thread.h"
+-#ifndef _LINUX
+-#include
+-#include "utils/win32exception.h"
+-#ifndef _MT
+-#pragma message( "Please compile using multithreaded run-time libraries" )
+-#endif
+-typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter);
+-#else
+-#include "PlatformInclude.h"
+-#include "XHandle.h"
+-#include
+-typedef int (*PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter);
+-#endif
+-
+-#if defined(__GNUC__) && !defined(__clang__)
+-#include
+-using namespace __cxxabiv1;
+-#endif
+-
+ #include "utils/log.h"
+ #include "utils/TimeUtils.h"
+ #include "threads/ThreadLocal.h"
+
++#define __STDC_FORMAT_MACROS
++#include
++
+ static XbmcThreads::ThreadLocal currentThread;
+
++#include "threads/platform/ThreadImpl.cpp"
++
+ //////////////////////////////////////////////////////////////////////
+ // Construction/Destruction
+ //////////////////////////////////////////////////////////////////////
+
+-CThread::CThread(const char* ThreadName) : m_StopEvent(true,true)
++CThread::CThread(const char* ThreadName)
++: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true)
+ {
+ m_bStop = false;
+
+ m_bAutoDelete = false;
+- m_ThreadHandle = NULL;
+ m_ThreadId = 0;
+ m_iLastTime = 0;
+ m_iLastUsage = 0;
+@@ -66,12 +52,12 @@
+ m_ThreadName = ThreadName;
+ }
+
+-CThread::CThread(IRunnable* pRunnable, const char* ThreadName) : m_StopEvent(true,true)
++CThread::CThread(IRunnable* pRunnable, const char* ThreadName)
++: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true)
+ {
+ m_bStop = false;
+
+ m_bAutoDelete = false;
+- m_ThreadHandle = NULL;
+ m_ThreadId = 0;
+ m_iLastTime = 0;
+ m_iLastUsage = 0;
+@@ -85,171 +71,62 @@
+
+ CThread::~CThread()
+ {
+- if (m_ThreadHandle != NULL)
+- {
+- CloseHandle(m_ThreadHandle);
+- }
+- m_ThreadHandle = NULL;
+-
++ StopThread();
+ }
+
+-#ifndef _WIN32
+-void CThread::term_handler (int signum)
++bool CThread::IsRunning()
+ {
+- CLog::Log(LOGERROR,"thread 0x%lx (%lu) got signal %d. calling OnException and terminating thread abnormally.", (long unsigned int)pthread_self(), (long unsigned int)pthread_self(), signum);
+-
+- CThread* curThread = currentThread.get();
+- if (curThread)
+- {
+- curThread->m_bStop = TRUE;
+- curThread->m_StopEvent.Set();
+-
+- curThread->OnException();
+- if( curThread->IsAutoDelete() )
+- delete curThread;
+- }
+-
+- pthread_exit(NULL);
++ return m_ThreadId ? true : false;
+ }
+
+-int CThread::staticThread(void* data)
+-#else
+-DWORD WINAPI CThread::staticThread(LPVOID* data)
+-#endif
++THREADFUNC CThread::staticThread(void* data)
+ {
+ CThread* pThread = (CThread*)(data);
++ std::string name;
++ ThreadIdentifier id;
++ bool autodelete;
++
+ if (!pThread) {
+ CLog::Log(LOGERROR,"%s, sanity failed. thread is NULL.",__FUNCTION__);
+ return 1;
+ }
+
+- if (pThread->m_ThreadName.empty())
+- pThread->m_ThreadName = pThread->GetTypeName();
+- pThread->SetDebugCallStackName(pThread->m_ThreadName.c_str());
++ name = pThread->m_ThreadName;
++ id = pThread->m_ThreadId;
++ autodelete = pThread->m_bAutoDelete;
+
+- CLog::Log(LOGDEBUG,"Thread %s start, auto delete: %d", pThread->m_ThreadName.c_str(), pThread->IsAutoDelete());
++ pThread->SetThreadInfo();
++
++ CLog::Log(LOGNOTICE,"Thread %s start, auto delete: %s", name.c_str(), (autodelete ? "true" : "false"));
+
+ currentThread.set(pThread);
+-#ifndef _LINUX
+- /* install win32 exception translator */
+- win32_exception::install_handler();
+-#else
+- struct sigaction action;
+- action.sa_handler = term_handler;
+- sigemptyset (&action.sa_mask);
+- action.sa_flags = 0;
+- //sigaction (SIGABRT, &action, NULL);
+- //sigaction (SIGSEGV, &action, NULL);
+-#endif
++ pThread->m_StartEvent.Set();
+
++ pThread->OnStartup();
++ pThread->Process();
++ pThread->OnExit();
+
+- try
+- {
+- pThread->OnStartup();
+- }
+-#ifndef _LINUX
+- catch (const win32_exception &e)
+- {
+- e.writelog(__FUNCTION__);
+- if( pThread->IsAutoDelete() )
+- {
+- delete pThread;
+- _endthreadex(123);
+- return 0;
+- }
+- }
+-#endif
+- catch(...)
+- {
+- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread startup, aborting. auto delete: %d", __FUNCTION__, pThread->m_ThreadName.c_str(), pThread->IsAutoDelete());
+- if( pThread->IsAutoDelete() )
+- {
+- delete pThread;
+-#ifndef _LINUX
+- _endthreadex(123);
+-#endif
+- return 0;
+- }
+- }
++ // lock during termination
++ CSingleLock lock(pThread->m_CriticalSection);
+
+- try
+- {
+- pThread->Process();
+- }
+-#ifndef _LINUX
+- catch (const access_violation &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+- catch (const win32_exception &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+-#endif
+- catch(...)
+- {
+- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread process, attemping cleanup in OnExit", __FUNCTION__, pThread->m_ThreadName.c_str());
+- }
++ pThread->m_ThreadId = 0;
++ pThread->m_TermEvent.Set();
++ pThread->TermHandler();
+
+- try
+- {
+- pThread->OnExit();
+- }
+-#ifndef _LINUX
+- catch (const access_violation &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+- catch (const win32_exception &e)
+- {
+- e.writelog(__FUNCTION__);
+- }
+-#endif
+- catch(...)
+- {
+- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread exit", __FUNCTION__, pThread->m_ThreadName.c_str());
+- }
++ lock.Leave();
+
+- if ( pThread->IsAutoDelete() )
++ if (autodelete)
+ {
+- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId());
++ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", name.c_str(), (uint64_t)id);
+ delete pThread;
+ pThread = NULL;
+ }
+ else
+- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId());
+-
+-// DXMERGE - this looks like it might have used to have been useful for something...
+-// g_graphicsContext.DeleteThreadContext();
++ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", name.c_str(), (uint64_t)id);
+
+-#ifndef _LINUX
+- _endthreadex(123);
+-#endif
+ return 0;
+ }
+
+-void CThread::Create(bool bAutoDelete, unsigned stacksize)
+-{
+- if (m_ThreadHandle != NULL)
+- {
+- throw 1; //ERROR should not b possible!!!
+- }
+- m_iLastTime = XbmcThreads::SystemClockMillis() * 10000;
+- m_iLastUsage = 0;
+- m_fLastUsage = 0.0f;
+- m_bAutoDelete = bAutoDelete;
+- m_bStop = false;
+- m_StopEvent.Reset();
+-
+- m_ThreadHandle = (HANDLE)_beginthreadex(NULL, stacksize, (PBEGINTHREADEX_THREADFUNC)staticThread, (void*)this, 0, &m_ThreadId);
+-
+-#ifdef _LINUX
+- if (m_ThreadHandle && m_ThreadHandle->m_threadValid && m_bAutoDelete)
+- // FIXME: WinAPI can truncate 64bit pthread ids
+- pthread_detach(m_ThreadHandle->m_hThread);
+-#endif
+-}
+-
+ bool CThread::IsAutoDelete() const
+ {
+ return m_bAutoDelete;
+@@ -259,213 +136,17 @@
+ {
+ m_bStop = true;
+ m_StopEvent.Set();
+- if (m_ThreadHandle && bWait)
++ CSingleLock lock(m_CriticalSection);
++ if (m_ThreadId && bWait)
+ {
+- WaitForThreadExit(INFINITE);
+- CloseHandle(m_ThreadHandle);
+- m_ThreadHandle = NULL;
++ lock.Leave();
++ WaitForThreadExit(0xFFFFFFFF);
+ }
+ }
+
+ ThreadIdentifier CThread::ThreadId() const
+ {
+-#ifdef _LINUX
+- if (m_ThreadHandle && m_ThreadHandle->m_threadValid)
+- return m_ThreadHandle->m_hThread;
+- else
+- return 0;
+-#else
+ return m_ThreadId;
+-#endif
+-}
+-
+-
+-CThread::operator HANDLE()
+-{
+- return m_ThreadHandle;
+-}
+-
+-CThread::operator HANDLE() const
+-{
+- return m_ThreadHandle;
+-}
+-
+-bool CThread::SetPriority(const int iPriority)
+-// Set thread priority
+-// Return true for success
+-{
+- bool rtn = false;
+-
+- if (m_ThreadHandle)
+- {
+- rtn = SetThreadPriority( m_ThreadHandle, iPriority ) == TRUE;
+- }
+-
+- return(rtn);
+-}
+-
+-void CThread::SetPrioritySched_RR(void)
+-{
+-#ifdef __APPLE__
+- // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the
+- // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects
+- // the thread running away. OSX automatically does this with the CoreAudio audio
+- // device handler thread.
+- int32_t result;
+- thread_extended_policy_data_t theFixedPolicy;
+-
+- // make thread fixed, set to 'true' for a non-fixed thread
+- theFixedPolicy.timeshare = false;
+- result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY,
+- (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
+-
+- int policy;
+- struct sched_param param;
+- result = pthread_getschedparam(ThreadId(), &policy, ¶m );
+- // change from default SCHED_OTHER to SCHED_RR
+- policy = SCHED_RR;
+- result = pthread_setschedparam(ThreadId(), policy, ¶m );
+-#endif
+-}
+-
+-int CThread::GetMinPriority(void)
+-{
+-#if 0
+-//#if defined(__APPLE__)
+- struct sched_param sched;
+- int rtn, policy;
+-
+- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
+- int min = sched_get_priority_min(policy);
+-
+- return(min);
+-#else
+- return(THREAD_PRIORITY_IDLE);
+-#endif
+-}
+-
+-int CThread::GetMaxPriority(void)
+-{
+-#if 0
+-//#if defined(__APPLE__)
+- struct sched_param sched;
+- int rtn, policy;
+-
+- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
+- int max = sched_get_priority_max(policy);
+-
+- return(max);
+-#else
+- return(THREAD_PRIORITY_HIGHEST);
+-#endif
+-}
+-
+-int CThread::GetNormalPriority(void)
+-{
+-#if 0
+-//#if defined(__APPLE__)
+- struct sched_param sched;
+- int rtn, policy;
+-
+- rtn = pthread_getschedparam(ThreadId(), &policy, &sched);
+- int min = sched_get_priority_min(policy);
+- int max = sched_get_priority_max(policy);
+-
+- return( min + ((max-min) / 2) );
+-#else
+- return(THREAD_PRIORITY_NORMAL);
+-#endif
+-}
+-
+-
+-void CThread::SetDebugCallStackName( const char *name )
+-{
+-#ifdef _WIN32
+- const unsigned int MS_VC_EXCEPTION = 0x406d1388;
+- struct THREADNAME_INFO
+- {
+- DWORD dwType; // must be 0x1000
+- LPCSTR szName; // pointer to name (in same addr space)
+- DWORD dwThreadID; // thread ID (-1 caller thread)
+- DWORD dwFlags; // reserved for future use, most be zero
+- } info;
+-
+- info.dwType = 0x1000;
+- info.szName = name;
+- info.dwThreadID = m_ThreadId;
+- info.dwFlags = 0;
+-
+- try
+- {
+- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info);
+- }
+- catch(...)
+- {
+- }
+-#endif
+-}
+-
+-// Get the thread name using the implementation dependant typeid() class
+-// and attempt to clean it.
+-std::string CThread::GetTypeName(void)
+-{
+- std::string name = typeid(*this).name();
+-
+-#if defined(_MSC_VER)
+- // Visual Studio 2010 returns the name as "class CThread" etc
+- if (name.substr(0, 6) == "class ")
+- name = name.substr(6, name.length() - 6);
+-#elif defined(__GNUC__) && !defined(__clang__)
+- // gcc provides __cxa_demangle to demangle the name
+- char* demangled = NULL;
+- int status;
+-
+- demangled = __cxa_demangle(name.c_str(), NULL, 0, &status);
+- if (status == 0)
+- name = demangled;
+- else
+- CLog::Log(LOGDEBUG,"%s, __cxa_demangle(%s) failed with status %d", __FUNCTION__, name.c_str(), status);
+-
+- if (demangled)
+- free(demangled);
+-#endif
+-
+- return name;
+-}
+-
+-bool CThread::WaitForThreadExit(unsigned int milliseconds)
+-// Waits for thread to exit, timeout in given number of msec.
+-// Returns true when thread ended
+-{
+- if (!m_ThreadHandle) return true;
+-
+-#ifndef _LINUX
+- // boost priority of thread we are waiting on to same as caller
+- int callee = GetThreadPriority(m_ThreadHandle);
+- int caller = GetThreadPriority(GetCurrentThread());
+- if(caller > callee)
+- SetThreadPriority(m_ThreadHandle, caller);
+-
+- if (::WaitForSingleObject(m_ThreadHandle, milliseconds) != WAIT_TIMEOUT)
+- return true;
+-
+- // restore thread priority if thread hasn't exited
+- if(caller > callee)
+- SetThreadPriority(m_ThreadHandle, callee);
+-#else
+- if (!(m_ThreadHandle->m_threadValid) || pthread_join(m_ThreadHandle->m_hThread, NULL) == 0)
+- {
+- m_ThreadHandle->m_threadValid = false;
+- return true;
+- }
+-#endif
+-
+- return false;
+-}
+-
+-HANDLE CThread::ThreadHandle()
+-{
+- return m_ThreadHandle;
+ }
+
+ void CThread::Process()
+@@ -474,54 +155,14 @@
+ m_pRunnable->Run();
+ }
+
+-float CThread::GetRelativeUsage()
+-{
+- unsigned __int64 iTime = XbmcThreads::SystemClockMillis();
+- iTime *= 10000; // convert into 100ns tics
+-
+- // only update every 1 second
+- if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage;
+-
+- FILETIME CreationTime, ExitTime, UserTime, KernelTime;
+- if( GetThreadTimes( m_ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) )
+- {
+- unsigned __int64 iUsage = 0;
+- iUsage += (((unsigned __int64)UserTime.dwHighDateTime) << 32) + ((unsigned __int64)UserTime.dwLowDateTime);
+- iUsage += (((unsigned __int64)KernelTime.dwHighDateTime) << 32) + ((unsigned __int64)KernelTime.dwLowDateTime);
+-
+- if(m_iLastUsage > 0 && m_iLastTime > 0)
+- m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime );
+-
+- m_iLastUsage = iUsage;
+- m_iLastTime = iTime;
+-
+- return m_fLastUsage;
+- }
+- return 0.0f;
+-}
+-
+ bool CThread::IsCurrentThread() const
+ {
+ return IsCurrentThread(ThreadId());
+ }
+
+-
+-ThreadIdentifier CThread::GetCurrentThreadId()
++CThread* CThread::GetCurrentThread()
+ {
+-#ifdef _LINUX
+- return pthread_self();
+-#else
+- return ::GetCurrentThreadId();
+-#endif
+-}
+-
+-bool CThread::IsCurrentThread(const ThreadIdentifier tid)
+-{
+-#ifdef _LINUX
+- return pthread_equal(pthread_self(), tid);
+-#else
+- return (::GetCurrentThreadId() == tid);
+-#endif
++ return currentThread.get();
+ }
+
+ void CThread::Sleep(unsigned int milliseconds)
+@@ -529,7 +170,7 @@
+ if(milliseconds > 10 && IsCurrentThread())
+ m_StopEvent.WaitMSec(milliseconds);
+ else
+- ::Sleep(milliseconds);
++ XbmcThreads::ThreadSleep(milliseconds);
+ }
+
+
+diff -Naur xbmc-11.0.1/xbmc/threads/Thread.h xbmc-11.0.1.patch/xbmc/threads/Thread.h
+--- xbmc-11.0.1/xbmc/threads/Thread.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/Thread.h 2012-05-13 22:08:46.819190365 +0200
+@@ -23,19 +23,13 @@
+ //
+ //////////////////////////////////////////////////////////////////////
+
+-#if !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_) && !defined(AFX_THREAD_H__67621B15_8724_4B5D_9343_7667075C89F2__INCLUDED_)
+-#define AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_
+-
+-#if _MSC_VER > 1000
+ #pragma once
+-#endif // _MSC_VER > 1000
+
+ #include
+-#include "system.h" // for HANDLE
+-#ifdef _LINUX
+-#include "PlatformInclude.h"
+-#endif
++#include
+ #include "Event.h"
++#include "threads/ThreadImpl.h"
++#include "threads/ThreadLocal.h"
+
+ class IRunnable
+ {
+@@ -44,37 +38,36 @@
+ virtual ~IRunnable() {}
+ };
+
+-#ifdef CTHREAD
+-#undef CTHREAD
+-#endif
+-
+ // minimum as mandated by XTL
+ #define THREAD_MINSTACKSIZE 0x10000
+
+ class CThread
+ {
+ public:
+- CThread(const char* ThreadName = NULL);
+- CThread(IRunnable* pRunnable, const char* ThreadName = NULL);
++ CThread(const char* ThreadName);
++ CThread(IRunnable* pRunnable, const char* ThreadName);
+ virtual ~CThread();
+ void Create(bool bAutoDelete = false, unsigned stacksize = 0);
+ bool WaitForThreadExit(unsigned int milliseconds);
+ void Sleep(unsigned int milliseconds);
+ bool SetPriority(const int iPriority);
+- void SetPrioritySched_RR(void);
++ int GetPriority(void);
+ int GetMinPriority(void);
+ int GetMaxPriority(void);
+ int GetNormalPriority(void);
+- HANDLE ThreadHandle();
+- operator HANDLE();
+- operator HANDLE() const;
++ int GetSchedRRPriority(void);
++ bool SetPrioritySched_RR(int iPriority);
+ bool IsAutoDelete() const;
+ virtual void StopThread(bool bWait = true);
+ float GetRelativeUsage(); // returns the relative cpu usage of this thread since last call
++ int64_t GetAbsoluteUsage();
+ bool IsCurrentThread() const;
++ bool IsRunning();
+
+ static bool IsCurrentThread(const ThreadIdentifier tid);
+ static ThreadIdentifier GetCurrentThreadId();
++ static CThread* GetCurrentThread();
++ static int64_t GetCurrentThreadUsage();
+ protected:
+ virtual void OnStartup(){};
+ virtual void OnExit(){};
+@@ -82,7 +75,6 @@
+ virtual void Process();
+
+ volatile bool m_bStop;
+- HANDLE m_ThreadHandle;
+
+ enum WaitResponse { WAIT_INTERRUPTED = -1, WAIT_SIGNALED = 0, WAIT_TIMEDOUT = 1 };
+
+@@ -108,36 +100,22 @@
+ }
+
+ private:
+- /*! \brief set the threadname for the debugger/callstack, implementation dependent.
+- */
+- void SetDebugCallStackName( const char *threadName );
+- std::string GetTypeName(void);
+-
+-private:
++ static THREADFUNC staticThread(void *data);
+ ThreadIdentifier ThreadId() const;
++ void SetThreadInfo();
++ void TermHandler();
++
++ ThreadIdentifier m_ThreadId;
++ ThreadOpaque m_ThreadOpaque;
+ bool m_bAutoDelete;
+ CEvent m_StopEvent;
+- unsigned m_ThreadId; // This value is unreliable on platforms using pthreads
+- // Use m_ThreadHandle->m_hThread instead
++ CEvent m_TermEvent;
++ CEvent m_StartEvent;
++ CCriticalSection m_CriticalSection;
+ IRunnable* m_pRunnable;
+-
+- unsigned __int64 m_iLastUsage;
+- unsigned __int64 m_iLastTime;
++ uint64_t m_iLastUsage;
++ uint64_t m_iLastTime;
+ float m_fLastUsage;
+
+ std::string m_ThreadName;
+-
+-#ifdef _LINUX
+- static void term_handler (int signum);
+-#endif
+-
+-#ifndef _WIN32
+- static int staticThread(void* data);
+-#else
+- static DWORD WINAPI staticThread(LPVOID* data);
+-#endif
+-
+-private:
+ };
+-
+-#endif // !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_)
+diff -Naur xbmc-11.0.1/xbmc/threads/ThreadImpl.h xbmc-11.0.1.patch/xbmc/threads/ThreadImpl.h
+--- xbmc-11.0.1/xbmc/threads/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/threads/ThreadImpl.h 2012-05-13 22:08:46.819190365 +0200
+@@ -0,0 +1,25 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#pragma once
++
++#include "threads/platform/ThreadImpl.h"
++
+diff -Naur xbmc-11.0.1/xbmc/utils/ActorProtocol.cpp xbmc-11.0.1.patch/xbmc/utils/ActorProtocol.cpp
+--- xbmc-11.0.1/xbmc/utils/ActorProtocol.cpp 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/ActorProtocol.cpp 2012-05-13 22:08:46.700188003 +0200
+@@ -0,0 +1,254 @@
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include "ActorProtocol.h"
++
++using namespace Actor;
++
++void Message::Release()
++{
++ bool skip;
++ origin->Lock();
++ skip = isSync ? !isSyncFini : false;
++ isSyncFini = true;
++ origin->Unlock();
++
++ if (skip)
++ return;
++
++ // free data buffer
++ if (data != buffer)
++ delete [] data;
++
++ // delete event in case of sync message
++ if (event)
++ delete event;
++
++ origin->ReturnMessage(this);
++}
++
++bool Message::Reply(int sig, void *data /* = NULL*/, int size /* = 0 */)
++{
++ if (!isSync)
++ {
++ if (isOut)
++ return origin->SendInMessage(sig, data, size);
++ else
++ return origin->SendOutMessage(sig, data, size);
++ }
++
++ origin->Lock();
++
++ if (!isSyncTimeout)
++ {
++ Message *msg = origin->GetMessage();
++ msg->signal = sig;
++ msg->isOut = !isOut;
++ replyMessage = msg;
++ if (data)
++ {
++ if (size > MSG_INTERNAL_BUFFER_SIZE)
++ msg->data = new uint8_t[size];
++ else
++ msg->data = msg->buffer;
++ memcpy(msg->data, data, size);
++ }
++ }
++
++ origin->Unlock();
++
++ if (event)
++ event->Set();
++
++ return true;
++}
++
++Protocol::~Protocol()
++{
++ Message *msg;
++ Purge();
++ while (!freeMessageQueue.empty())
++ {
++ msg = freeMessageQueue.front();
++ freeMessageQueue.pop();
++ delete msg;
++ }
++}
++
++Message *Protocol::GetMessage()
++{
++ Message *msg;
++
++ CSingleLock lock(criticalSection);
++
++ if (!freeMessageQueue.empty())
++ {
++ msg = freeMessageQueue.front();
++ freeMessageQueue.pop();
++ }
++ else
++ msg = new Message();
++
++ msg->isSync = false;
++ msg->isSyncFini = false;
++ msg->isSyncTimeout = false;
++ msg->event = NULL;
++ msg->data = NULL;
++ msg->payloadSize = 0;
++ msg->replyMessage = NULL;
++ msg->origin = this;
++
++ return msg;
++}
++
++void Protocol::ReturnMessage(Message *msg)
++{
++ CSingleLock lock(criticalSection);
++
++ freeMessageQueue.push(msg);
++}
++
++bool Protocol::SendOutMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */)
++{
++ Message *msg;
++ if (outMsg)
++ msg = outMsg;
++ else
++ msg = GetMessage();
++
++ msg->signal = signal;
++ msg->isOut = true;
++
++ if (data)
++ {
++ if (size > MSG_INTERNAL_BUFFER_SIZE)
++ msg->data = new uint8_t[size];
++ else
++ msg->data = msg->buffer;
++ memcpy(msg->data, data, size);
++ }
++
++ { CSingleLock lock(criticalSection);
++ outMessages.push(msg);
++ }
++ containerOutEvent->Set();
++
++ return true;
++}
++
++bool Protocol::SendInMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */)
++{
++ Message *msg;
++ if (outMsg)
++ msg = outMsg;
++ else
++ msg = GetMessage();
++
++ msg->signal = signal;
++ msg->isOut = false;
++
++ if (data)
++ {
++ if (size > MSG_INTERNAL_BUFFER_SIZE)
++ msg->data = new uint8_t[size];
++ else
++ msg->data = msg->buffer;
++ memcpy(msg->data, data, size);
++ }
++
++ { CSingleLock lock(criticalSection);
++ inMessages.push(msg);
++ }
++ containerInEvent->Set();
++
++ return true;
++}
++
++
++bool Protocol::SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data /* = NULL */, int size /* = 0 */)
++{
++ Message *msg = GetMessage();
++ msg->isOut = true;
++ msg->isSync = true;
++ msg->event = new CEvent;
++ msg->event->Reset();
++ SendOutMessage(signal, data, size, msg);
++
++ if (!msg->event->WaitMSec(timeout))
++ {
++ msg->origin->Lock();
++ if (msg->replyMessage)
++ *retMsg = msg->replyMessage;
++ else
++ {
++ *retMsg = NULL;
++ msg->isSyncTimeout = true;
++ }
++ msg->origin->Unlock();
++ }
++ else
++ *retMsg = msg->replyMessage;
++
++ msg->Release();
++
++ if (*retMsg)
++ return true;
++ else
++ return false;
++}
++
++bool Protocol::ReceiveOutMessage(Message **msg)
++{
++ CSingleLock lock(criticalSection);
++
++ if (outMessages.empty() || outDefered)
++ return false;
++
++ *msg = outMessages.front();
++ outMessages.pop();
++
++ return true;
++}
++
++bool Protocol::ReceiveInMessage(Message **msg)
++{
++ CSingleLock lock(criticalSection);
++
++ if (inMessages.empty() || inDefered)
++ return false;
++
++ *msg = inMessages.front();
++ inMessages.pop();
++
++ return true;
++}
++
++
++void Protocol::Purge()
++{
++ Message *msg;
++
++ while (ReceiveInMessage(&msg))
++ msg->Release();
++
++ while (ReceiveOutMessage(&msg))
++ msg->Release();
++}
+diff -Naur xbmc-11.0.1/xbmc/utils/ActorProtocol.h xbmc-11.0.1.patch/xbmc/utils/ActorProtocol.h
+--- xbmc-11.0.1/xbmc/utils/ActorProtocol.h 1970-01-01 01:00:00.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/ActorProtocol.h 2012-05-13 22:08:46.700188003 +0200
+@@ -0,0 +1,89 @@
++
++#pragma once
++
++/*
++ * Copyright (C) 2005-2011 Team XBMC
++ * http://www.xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This Program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ * http://www.gnu.org/copyleft/gpl.html
++ *
++ */
++
++#include "threads/Thread.h"
++#include "utils/log.h"
++#include
++#include "memory.h"
++
++#define MSG_INTERNAL_BUFFER_SIZE 32
++
++namespace Actor
++{
++
++class Protocol;
++
++class Message
++{
++ friend class Protocol;
++public:
++ int signal;
++ bool isSync;
++ bool isSyncFini;
++ bool isOut;
++ bool isSyncTimeout;
++ int payloadSize;
++ uint8_t buffer[MSG_INTERNAL_BUFFER_SIZE];
++ uint8_t *data;
++ Message *replyMessage;
++ Protocol *origin;
++ CEvent *event;
++
++ void Release();
++ bool Reply(int sig, void *data = NULL, int size = 0);
++
++private:
++ Message() {isSync = false; data = NULL; event = NULL; replyMessage = NULL;};
++};
++
++class Protocol
++{
++public:
++ Protocol(std::string name, CEvent* inEvent, CEvent *outEvent)
++ : inDefered(false), outDefered(false), portName(name) {containerInEvent = inEvent; containerOutEvent = outEvent;};
++ virtual ~Protocol();
++ Message *GetMessage();
++ void ReturnMessage(Message *msg);
++ bool SendOutMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL);
++ bool SendInMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL);
++ bool SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data = NULL, int size = 0);
++ bool ReceiveOutMessage(Message **msg);
++ bool ReceiveInMessage(Message **msg);
++ void Purge();
++ void DeferIn(bool value) {inDefered = value;};
++ void DeferOut(bool value) {outDefered = value;};
++ void Lock() {criticalSection.lock();};
++ void Unlock() {criticalSection.unlock();};
++ std::string portName;
++
++protected:
++ CEvent *containerInEvent, *containerOutEvent;
++ CCriticalSection criticalSection;
++ std::queue outMessages;
++ std::queue inMessages;
++ std::queue freeMessageQueue;
++ bool inDefered, outDefered;
++};
++
++}
+diff -Naur xbmc-11.0.1/xbmc/utils/AlarmClock.cpp xbmc-11.0.1.patch/xbmc/utils/AlarmClock.cpp
+--- xbmc-11.0.1/xbmc/utils/AlarmClock.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/AlarmClock.cpp 2012-05-13 22:08:46.823190444 +0200
+@@ -28,7 +28,7 @@
+
+ using namespace std;
+
+-CAlarmClock::CAlarmClock() : m_bIsRunning(false)
++CAlarmClock::CAlarmClock() : CThread("CAlarmClock"), m_bIsRunning(false)
+ {
+ }
+
+diff -Naur xbmc-11.0.1/xbmc/utils/AsyncFileCopy.cpp xbmc-11.0.1.patch/xbmc/utils/AsyncFileCopy.cpp
+--- xbmc-11.0.1/xbmc/utils/AsyncFileCopy.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/AsyncFileCopy.cpp 2012-05-13 22:08:46.824190464 +0200
+@@ -26,7 +26,7 @@
+ #include "log.h"
+ #include "utils/TimeUtils.h"
+
+-CAsyncFileCopy::CAsyncFileCopy()
++CAsyncFileCopy::CAsyncFileCopy() : CThread("CAsyncFileCopy")
+ {
+ m_cancelled = false;
+ m_succeeded = false;
+diff -Naur xbmc-11.0.1/xbmc/utils/DownloadQueue.cpp xbmc-11.0.1.patch/xbmc/utils/DownloadQueue.cpp
+--- xbmc-11.0.1/xbmc/utils/DownloadQueue.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/DownloadQueue.cpp 2012-05-13 22:08:46.824190464 +0200
+@@ -32,7 +32,7 @@
+
+ WORD CDownloadQueue::m_wNextQueueId = 0;
+
+-CDownloadQueue::CDownloadQueue(void) : CThread()
++CDownloadQueue::CDownloadQueue(void) : CThread("CDownloadQueue")
+ {
+ m_bStop = false;
+ m_wQueueId = m_wNextQueueId++;
+diff -Naur xbmc-11.0.1/xbmc/utils/DownloadQueue.h xbmc-11.0.1.patch/xbmc/utils/DownloadQueue.h
+--- xbmc-11.0.1/xbmc/utils/DownloadQueue.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/DownloadQueue.h 2012-05-13 22:08:46.825190483 +0200
+@@ -26,6 +26,8 @@
+ #include "threads/CriticalSection.h"
+ #include "StdString.h"
+
++#include "system.h"
++
+ struct TICKET
+ {
+ TICKET(WORD aQueueId, DWORD aItemId)
+diff -Naur xbmc-11.0.1/xbmc/utils/DownloadQueueManager.h xbmc-11.0.1.patch/xbmc/utils/DownloadQueueManager.h
+--- xbmc-11.0.1/xbmc/utils/DownloadQueueManager.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/DownloadQueueManager.h 2012-05-13 22:08:46.825190483 +0200
+@@ -22,6 +22,7 @@
+ */
+
+ #include "DownloadQueue.h"
++#include "system.h"
+
+ #define MAX_DOWNLOAD_QUEUES 3
+
+diff -Naur xbmc-11.0.1/xbmc/utils/JobManager.cpp xbmc-11.0.1.patch/xbmc/utils/JobManager.cpp
+--- xbmc-11.0.1/xbmc/utils/JobManager.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/JobManager.cpp 2012-05-13 22:08:46.826190502 +0200
+@@ -24,6 +24,9 @@
+ #include "threads/SingleLock.h"
+ #include "utils/log.h"
+
++#include "system.h"
++
++
+ using namespace std;
+
+ bool CJob::ShouldCancel(unsigned int progress, unsigned int total) const
+diff -Naur xbmc-11.0.1/xbmc/utils/LCD.h xbmc-11.0.1.patch/xbmc/utils/LCD.h
+--- xbmc-11.0.1/xbmc/utils/LCD.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/LCD.h 2012-05-13 22:08:46.826190502 +0200
+@@ -68,8 +68,9 @@
+ void LoadSkin(const CStdString &xmlFile);
+ void Reset();
+ void Render(LCD_MODE mode);
+- ILCD() : m_disableOnPlay(DISABLE_ON_PLAY_NONE),
+- m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {}
++ ILCD() : CThread("ILCD"),
++ m_disableOnPlay(DISABLE_ON_PLAY_NONE),
++ m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {}
+ protected:
+ virtual void Process() = 0;
+ void StringToLCDCharSet(CStdString& strText);
+diff -Naur xbmc-11.0.1/xbmc/utils/Makefile xbmc-11.0.1.patch/xbmc/utils/Makefile
+--- xbmc-11.0.1/xbmc/utils/Makefile 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/Makefile 2012-05-13 22:08:46.701188023 +0200
+@@ -57,6 +57,7 @@
+ Weather.cpp \
+ Win32Exception.cpp \
+ XMLUtils.cpp \
++ ActorProtocol.cpp \
+
+ LIB=utils.a
+
+diff -Naur xbmc-11.0.1/xbmc/utils/RssReader.cpp xbmc-11.0.1.patch/xbmc/utils/RssReader.cpp
+--- xbmc-11.0.1/xbmc/utils/RssReader.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/RssReader.cpp 2012-05-13 22:08:46.827190522 +0200
+@@ -44,7 +44,7 @@
+ // Construction/Destruction
+ //////////////////////////////////////////////////////////////////////
+
+-CRssReader::CRssReader() : CThread()
++CRssReader::CRssReader() : CThread("CRssReader")
+ {
+ m_pObserver = NULL;
+ m_spacesBetweenFeeds = 0;
+diff -Naur xbmc-11.0.1/xbmc/utils/RssReader.h xbmc-11.0.1.patch/xbmc/utils/RssReader.h
+--- xbmc-11.0.1/xbmc/utils/RssReader.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/RssReader.h 2012-05-13 22:08:46.827190522 +0200
+@@ -39,6 +39,9 @@
+
+ #include "tinyXML/tinyxml.h"
+
++#include "system.h"
++
++
+ #define RSS_COLOR_BODY 0
+ #define RSS_COLOR_HEADLINE 1
+ #define RSS_COLOR_CHANNEL 2
+diff -Naur xbmc-11.0.1/xbmc/utils/Splash.cpp xbmc-11.0.1.patch/xbmc/utils/Splash.cpp
+--- xbmc-11.0.1/xbmc/utils/Splash.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/Splash.cpp 2012-05-13 22:08:46.828190542 +0200
+@@ -31,7 +31,7 @@
+
+ using namespace XFILE;
+
+-CSplash::CSplash(const CStdString& imageName)
++CSplash::CSplash(const CStdString& imageName) : CThread("CSplash")
+ {
+ m_ImageName = imageName;
+ fade = 0.5;
+@@ -139,5 +139,5 @@
+
+ bool CSplash::IsRunning()
+ {
+- return (m_ThreadHandle != NULL);
++ return (IsRunning());
+ }
+diff -Naur xbmc-11.0.1/xbmc/utils/TuxBoxUtil.cpp xbmc-11.0.1.patch/xbmc/utils/TuxBoxUtil.cpp
+--- xbmc-11.0.1/xbmc/utils/TuxBoxUtil.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/utils/TuxBoxUtil.cpp 2012-05-13 22:08:46.829190562 +0200
+@@ -48,7 +48,7 @@
+ CTuxBoxUtil g_tuxbox;
+ CTuxBoxService g_tuxboxService;
+
+-CTuxBoxService::CTuxBoxService()
++CTuxBoxService::CTuxBoxService() : CThread("CTuxBoxService")
+ {
+ }
+ CTuxBoxService::~CTuxBoxService()
+diff -Naur xbmc-11.0.1/xbmc/video/dialogs/GUIDialogVideoSettings.cpp xbmc-11.0.1.patch/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+--- xbmc-11.0.1/xbmc/video/dialogs/GUIDialogVideoSettings.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/video/dialogs/GUIDialogVideoSettings.cpp 2012-05-13 22:18:16.222981047 +0200
+@@ -105,12 +105,12 @@
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_INVERSE_TELECINE , 16314));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL , 16311));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL , 16310));
+- entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16021));
++ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_BOB , 16326));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF, 16318));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF , 16317));
+- entries.push_back(make_pair(VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE , 16314));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BOB , 16320));
+ entries.push_back(make_pair(VS_INTERLACEMETHOD_DXVA_BEST , 16321));
++ entries.push_back(make_pair(VS_INTERLACEMETHOD_XVBA , 16327));
+
+ /* remove unsupported methods */
+ for(vector >::iterator it = entries.begin(); it != entries.end();)
+diff -Naur xbmc-11.0.1/xbmc/video/VideoInfoDownloader.cpp xbmc-11.0.1.patch/xbmc/video/VideoInfoDownloader.cpp
+--- xbmc-11.0.1/xbmc/video/VideoInfoDownloader.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/video/VideoInfoDownloader.cpp 2012-05-13 22:08:46.829190562 +0200
+@@ -116,7 +116,7 @@
+ m_state = FIND_MOVIE;
+ m_strMovie = strMovie;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (m_state != DO_NOTHING)
+@@ -160,7 +160,7 @@
+ { // threaded version
+ m_state = GET_DETAILS;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (!m_found)
+@@ -195,7 +195,7 @@
+ { // threaded version
+ m_state = GET_EPISODE_DETAILS;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (!m_found)
+@@ -230,7 +230,7 @@
+ { // threaded version
+ m_state = GET_EPISODE_LIST;
+ m_found = 0;
+- if (ThreadHandle())
++ if (IsRunning())
+ StopThread();
+ Create();
+ while (!m_found)
+diff -Naur xbmc-11.0.1/xbmc/video/VideoInfoDownloader.h xbmc-11.0.1.patch/xbmc/video/VideoInfoDownloader.h
+--- xbmc-11.0.1/xbmc/video/VideoInfoDownloader.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/video/VideoInfoDownloader.h 2012-05-13 22:08:46.830190582 +0200
+@@ -42,7 +42,7 @@
+ class CVideoInfoDownloader : public CThread
+ {
+ public:
+- CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : m_info(scraper) {}
++ CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : CThread("CVideoInfoDownloader"), m_info(scraper) {}
+ virtual ~CVideoInfoDownloader() {}
+
+ // threaded lookup functions
+diff -Naur xbmc-11.0.1/xbmc/video/VideoInfoScanner.cpp xbmc-11.0.1.patch/xbmc/video/VideoInfoScanner.cpp
+--- xbmc-11.0.1/xbmc/video/VideoInfoScanner.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/video/VideoInfoScanner.cpp 2012-05-13 22:08:46.831190602 +0200
+@@ -54,7 +54,7 @@
+ namespace VIDEO
+ {
+
+- CVideoInfoScanner::CVideoInfoScanner()
++ CVideoInfoScanner::CVideoInfoScanner() : CThread("CVideoInfoScanner")
+ {
+ m_bRunning = false;
+ m_pObserver = NULL;
+diff -Naur xbmc-11.0.1/xbmc/video/VideoReferenceClock.cpp xbmc-11.0.1.patch/xbmc/video/VideoReferenceClock.cpp
+--- xbmc-11.0.1/xbmc/video/VideoReferenceClock.cpp 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/video/VideoReferenceClock.cpp 2012-05-13 22:08:47.011194174 +0200
+@@ -31,6 +31,7 @@
+ #include
+ #include
+ #include "windowing/WindowingFactory.h"
++ #include "settings/AdvancedSettings.h"
+ #define NVSETTINGSCMD "nvidia-settings -nt -q RefreshRate3"
+ #elif defined(__APPLE__) && !defined(__arm__)
+ #include
+@@ -107,7 +108,7 @@
+
+ #endif
+
+-CVideoReferenceClock::CVideoReferenceClock()
++CVideoReferenceClock::CVideoReferenceClock() : CThread("CVideoReferenceClock")
+ {
+ m_SystemFrequency = CurrentHostFrequency();
+ m_ClockSpeed = 1.0;
+@@ -118,7 +119,7 @@
+
+ #if defined(HAS_GLX) && defined(HAS_XRANDR)
+ m_Dpy = NULL;
+- m_UseNvSettings = true;
++ m_UseNvSettings = false;
+ #endif
+ }
+
+@@ -270,12 +271,21 @@
+ return false;
+ }
+
++ m_bIsATI = false;
++ m_bPolling = false;
++
+ CStdString Vendor = g_Windowing.GetRenderVendor();
+ Vendor.ToLower();
+ if (Vendor.compare(0, 3, "ati") == 0)
+ {
+ CLog::Log(LOGDEBUG, "CVideoReferenceClock: GL_VENDOR: %s, using ati workaround", Vendor.c_str());
+ m_bIsATI = true;
++ m_bPolling = true;
++ }
++ if (g_advancedSettings.m_vblankPolling)
++ {
++ m_bPolling = true;
++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: use polling");
+ }
+
+ m_vInfo = glXChooseVisual(m_Dpy, DefaultScreen(m_Dpy), singleBufferAttributes);
+@@ -285,7 +295,7 @@
+ return false;
+ }
+
+- if (!m_bIsATI)
++ if (!m_bPolling)
+ {
+ Swa.border_pixel = 0;
+ Swa.event_mask = StructureNotifyMask;
+@@ -313,7 +323,7 @@
+ return false;
+ }
+
+- if (!m_bIsATI)
++ if (!m_bPolling)
+ ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
+ else
+ ReturnV = glXMakeCurrent(m_Dpy, m_glPixmap, m_Context);
+@@ -324,7 +334,7 @@
+ return false;
+ }
+
+- if (!m_bIsATI)
++ if (!m_bPolling)
+ {
+ m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI");
+ if (!m_glXWaitVideoSyncSGI)
+@@ -369,6 +379,9 @@
+ UpdateRefreshrate(true); //forced refreshrate update
+ m_MissedVblanks = 0;
+
++ if (m_bPolling)
++ SetPriority(1);
++
+ return true;
+ }
+
+@@ -567,7 +580,7 @@
+ while(!m_bStop)
+ {
+ //wait for the next vblank
+- if (!m_bIsATI)
++ if (!m_bPolling)
+ {
+ ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount);
+ m_glXGetVideoSyncSGI(&VblankCount); //the vblank count returned by glXWaitVideoSyncSGI is not always correct
+@@ -591,7 +604,7 @@
+ sleepTime = std::max(int(300000LL/m_RefreshRate), sleepTime);
+
+ unsigned int iterations = 0;
+- while (VblankCount == PrevVblankCount && !m_bStop)
++ while (VblankCount == PrevVblankCount && iterations < 500 && !m_bStop)
+ {
+ usleep(sleepTime);
+ m_glXGetVideoSyncSGI(&VblankCount);
+@@ -652,7 +665,7 @@
+ }
+
+ CLog::Log(LOGDEBUG, "CVideoReferenceClock: Attaching glX context");
+- if (!m_bIsATI)
++ if (!m_bPolling)
+ ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
+ else
+ ReturnV = glXMakeCurrent(m_Dpy, m_glPixmap, m_Context);
+@@ -1275,6 +1288,9 @@
+
+ if (m_UseVblank) //when true the vblank is used as clock source
+ {
++ if (Target < m_CurrTime)
++ Target = m_CurrTime + 0.5/m_RefreshRate;
++
+ while (m_CurrTime < Target)
+ {
+ //calculate how long to sleep before we should have gotten a signal that a vblank happened
+diff -Naur xbmc-11.0.1/xbmc/video/VideoReferenceClock.h xbmc-11.0.1.patch/xbmc/video/VideoReferenceClock.h
+--- xbmc-11.0.1/xbmc/video/VideoReferenceClock.h 2012-03-21 23:57:32.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/video/VideoReferenceClock.h 2012-05-13 22:08:46.917192309 +0200
+@@ -125,6 +125,7 @@
+
+ bool m_UseNvSettings;
+ bool m_bIsATI;
++ bool m_bPolling;
+
+ #elif defined(_WIN32) && defined(HAS_DX)
+ bool SetupD3D();
+diff -Naur xbmc-11.0.1/xbmc/win32/PlatformDefs.h xbmc-11.0.1.patch/xbmc/win32/PlatformDefs.h
+--- xbmc-11.0.1/xbmc/win32/PlatformDefs.h 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/win32/PlatformDefs.h 2012-05-13 22:08:46.870191375 +0200
+@@ -33,7 +33,6 @@
+ typedef __int64 fpos64_t;
+ typedef __int64 __off64_t;
+ typedef long __off_t;
+-typedef unsigned long ThreadIdentifier;
+
+ #define ssize_t int
+
+diff -Naur xbmc-11.0.1/xbmc/win32/WindowHelper.cpp xbmc-11.0.1.patch/xbmc/win32/WindowHelper.cpp
+--- xbmc-11.0.1/xbmc/win32/WindowHelper.cpp 2012-03-21 23:57:34.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/win32/WindowHelper.cpp 2012-05-13 22:08:46.871191395 +0200
+@@ -28,7 +28,7 @@
+
+ CWHelper g_windowHelper;
+
+-CWHelper::CWHelper(void)
++CWHelper::CWHelper(void) : CThread("CWHelper")
+ {
+ m_hwnd = NULL;
+ m_hProcess = NULL;
+diff -Naur xbmc-11.0.1/xbmc/windowing/X11/WinSystemX11.cpp xbmc-11.0.1.patch/xbmc/windowing/X11/WinSystemX11.cpp
+--- xbmc-11.0.1/xbmc/windowing/X11/WinSystemX11.cpp 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/windowing/X11/WinSystemX11.cpp 2012-05-13 22:08:47.023194413 +0200
+@@ -35,6 +35,8 @@
+ #include
+ #include "cores/VideoRenderers/RenderManager.h"
+ #include "utils/TimeUtils.h"
++#include "settings/AdvancedSettings.h"
++#include "settings/GUISettings.h"
+
+ #if defined(HAS_XRANDR)
+ #include
+@@ -52,6 +54,7 @@
+ m_wmWindow = 0;
+ m_bWasFullScreenBeforeMinimize = false;
+ m_dpyLostTime = 0;
++ m_internalModeSwitch = false;
+
+ XSetErrorHandler(XErrorHandler);
+ }
+@@ -178,6 +181,45 @@
+ return false;
+ }
+
++void CWinSystemX11::RefreshWindow()
++{
++ // save current mode if this is not an internal request
++ if (!m_internalModeSwitch)
++ {
++ CLog::Log(LOGNOTICE, "CWinSystemX11::RefreshWindow - external or initial xrandr event");
++ m_xrandrOut = g_xrandr.GetCurrentOutput();
++ m_xrandrMode = g_xrandr.GetCurrentMode(m_xrandrOut.name);
++ }
++ m_internalModeSwitch = false;
++
++ g_xrandr.Query(true);
++ XOutput out = g_xrandr.GetCurrentOutput();
++ XMode mode = g_xrandr.GetCurrentMode(out.name);
++
++ RESOLUTION_INFO res;
++ unsigned int i;
++ bool found(false);
++ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i)
++ {
++ if (g_settings.m_ResInfo[i].strId == mode.id)
++ {
++ found = true;
++ break;
++ }
++ }
++
++ if (!found)
++ {
++ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution");
++ return;
++ }
++
++ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true);
++ g_guiSettings.SetInt("window.width", mode.w);
++ g_guiSettings.SetInt("window.height", mode.h);
++ g_settings.Save();
++}
++
+ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
+ {
+ m_nWidth = res.iWidth;
+@@ -193,13 +235,32 @@
+ mode.hz = res.fRefreshRate;
+ mode.id = res.strId;
+
+- if(m_bFullScreen)
++ XOutput currout = g_xrandr.GetCurrentOutput();
++ XMode currmode = g_xrandr.GetCurrentMode(currout.name);
++
++ if (m_xrandrOut.name.empty())
++ {
++ m_xrandrOut = currout;
++ m_xrandrMode = currmode;
++ }
++
++ if(!m_bFullScreen)
+ {
++ // reset to mode we had before internal mode switch
++ out = m_xrandrOut;
++ mode = m_xrandrMode;
++ }
++
++ // only call xrandr if mode changes
++ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h ||
++ currmode.hz != mode.hz || currmode.id != mode.id)
++ {
++ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr");
+ OnLostDevice();
++ m_internalModeSwitch = true;
+ g_xrandr.SetMode(out, mode);
+ }
+- else
+- g_xrandr.RestoreState();
++
+ #endif
+
+ int options = SDL_OPENGL;
+@@ -493,6 +554,7 @@
+ if (bGotEvent || bTimeout)
+ {
+ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__);
++ RefreshWindow();
+
+ CSingleLock lock(m_resourceSection);
+
+diff -Naur xbmc-11.0.1/xbmc/windowing/X11/WinSystemX11.h xbmc-11.0.1.patch/xbmc/windowing/X11/WinSystemX11.h
+--- xbmc-11.0.1/xbmc/windowing/X11/WinSystemX11.h 2012-03-21 23:57:33.000000000 +0100
++++ xbmc-11.0.1.patch/xbmc/windowing/X11/WinSystemX11.h 2012-05-13 22:08:47.024194433 +0200
+@@ -27,6 +27,7 @@
+ #include "utils/Stopwatch.h"
+ #include
+ #include "threads/CriticalSection.h"
++#include "XRandR.h"
+
+ class IDispResource;
+
+@@ -60,6 +61,9 @@
+ // Local to WinSystemX11 only
+ Display* GetDisplay() { return m_dpy; }
+ GLXWindow GetWindow() { return m_glWindow; }
++ GLXContext GetGlxContext() { return m_glContext; }
++ Window GetWmWindow() { return m_wmWindow; }
++ void RefreshWindow();
+
+ protected:
+ bool RefreshGlxContext();
+@@ -76,6 +80,9 @@
+ CCriticalSection m_resourceSection;
+ std::vector m_resources;
+ uint64_t m_dpyLostTime;
++ XOutput m_xrandrOut;
++ XMode m_xrandrMode;
++ bool m_internalModeSwitch;
+
+ private:
+ bool IsSuitableVisual(XVisualInfo *vInfo);