diff --git a/packages/mediacenter/xbmc-pvr/build b/packages/mediacenter/xbmc-pvr/build index 5cb9c795e6..70b853a76e 100755 --- a/packages/mediacenter/xbmc-pvr/build +++ b/packages/mediacenter/xbmc-pvr/build @@ -124,6 +124,12 @@ else XBMC_VAAPI="--disable-vaapi" fi +if [ "$XVBA" = yes ]; then + XBMC_XVBA="--enable-xvba" +else + XBMC_XVBA="--disable-xvba" +fi + if [ "$CRYSTALHD" = yes ]; then XBMC_CRYSTALHD="--enable-crystalhd" else @@ -184,6 +190,7 @@ cd $PKG_BUILD $XBMC_VDPAU \ $XBMC_VAAPI \ $XBMC_CRYSTALHD \ + $XBMC_XVBA \ --disable-vdadecoder \ --disable-vtbdecoder \ --disable-openmax \ diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-351-increase_YV12_buffers-0.1.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-351-increase_YV12_buffers-0.1.patch deleted file mode 100644 index bc842ab6d0..0000000000 --- a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-351-increase_YV12_buffers-0.1.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0c2185d62f858f7b41461b4141e731dc7ec01ca6 Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Thu, 11 Aug 2011 18:35:18 +0200 -Subject: [PATCH] LinuxRendererGL: increase buffers to 3 - ---- - xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -index 18c6da4..79a9d90 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp -@@ -223,7 +223,7 @@ bool CLinuxRendererGL::ValidateRenderer() - - void CLinuxRendererGL::ManageTextures() - { -- m_NumYV12Buffers = 2; -+ m_NumYV12Buffers = 3; - //m_iYV12RenderBuffer = 0; - return; - } -@@ -720,7 +720,7 @@ unsigned int CLinuxRendererGL::PreInit() - m_resolution = RES_PAL_4x3; - - m_iYV12RenderBuffer = 0; -- m_NumYV12Buffers = 2; -+ m_NumYV12Buffers = 3; - - // setup the background colour - m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; --- -1.7.5.4 - diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-353-limit_glxSwapBuffers_going_to_far_ahead-0.1.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-353-limit_glxSwapBuffers_going_to_far_ahead-0.1.patch deleted file mode 100644 index b7c38d53f1..0000000000 --- a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-353-limit_glxSwapBuffers_going_to_far_ahead-0.1.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff -Naur xbmc-4c32cde/xbmc/windowing/X11/WinSystemX11GL.cpp xbmc-4c32cde.patch/xbmc/windowing/X11/WinSystemX11GL.cpp ---- xbmc-4c32cde/xbmc/windowing/X11/WinSystemX11GL.cpp 2011-10-29 14:43:48.634117918 +0200 -+++ xbmc-4c32cde.patch/xbmc/windowing/X11/WinSystemX11GL.cpp 2011-10-29 14:45:56.207774711 +0200 -@@ -45,7 +45,27 @@ - { - CheckDisplayEvents(); - -- if(m_iVSyncMode == 3) -+ if(m_iVSyncMode == 2) -+ { -+ static unsigned int last = 0; -+ unsigned int now; -+ if(m_glXGetVideoSyncSGI(&now) != 0) -+ CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__); -+ -+ if (now == last) -+ { -+ if (m_glXWaitVideoSyncSGI(2, (last + 1) % 2, &now) != 0) -+ CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Returned error", __FUNCTION__); -+ if(m_glXGetVideoSyncSGI(&now) != 0) -+ CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__); -+ last = now + 1; -+ } -+ else -+ last = now; -+ -+ glXSwapBuffers(m_dpy, m_glWindow); -+ } -+ else if(m_iVSyncMode == 3) - { - glFinish(); - unsigned int before = 0, after = 0; -@@ -238,7 +258,6 @@ - else - m_glXSwapIntervalMESA = NULL; - -- - return true; - } - diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-354-vaapi_increase_number_of_video_surface_allocated-0.1.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-354-vaapi_increase_number_of_video_surface_allocated-0.1.patch deleted file mode 100644 index a03fb50292..0000000000 --- a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-354-vaapi_increase_number_of_video_surface_allocated-0.1.patch +++ /dev/null @@ -1,27 +0,0 @@ -From dff7d824c82f957e19ad56247134912d70862188 Mon Sep 17 00:00:00 2001 -From: FernetMenta -Date: Sun, 14 Aug 2011 11:21:32 +0200 -Subject: [PATCH] vaapi: increase number of video surface allocated - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 4 +++- - 1 files changed, 3 insertions(+), 1 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index bcc3fe1..326c390 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -358,7 +358,9 @@ bool CDecoder::EnsureContext(AVCodecContext *avctx) - else - m_refs = 2; - } -- return EnsureSurfaces(avctx, m_refs + 3); -+ // number of reference + 3 renderbuffers + Holder -+ // an extra one should not harm -+ return EnsureSurfaces(avctx, m_refs + 5); - } - - bool CDecoder::EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count) --- -1.7.5.4 - diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-810-include_system.h.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-810-include_system.h.patch new file mode 100644 index 0000000000..ba183709bc --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-810-include_system.h.patch @@ -0,0 +1,11 @@ +diff -Naur xbmc-f3b0020/xbmc/peripherals/Peripherals.cpp xbmc-f3b0020.patch/xbmc/peripherals/Peripherals.cpp +--- xbmc-f3b0020/xbmc/peripherals/Peripherals.cpp 2011-12-10 22:16:17.000000000 +0100 ++++ xbmc-f3b0020.patch/xbmc/peripherals/Peripherals.cpp 2011-12-11 18:25:13.143643374 +0100 +@@ -19,6 +19,7 @@ + * + */ + ++#include "system.h" + #include "Peripherals.h" + #include "bus/PeripheralBus.h" + #include "devices/PeripheralBluetooth.h" diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-901-xvba_support-e8d631f741bc32f75374a698b9a39b387c9aa0ab.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-901-xvba_support-e8d631f741bc32f75374a698b9a39b387c9aa0ab.patch new file mode 100644 index 0000000000..40bf2c2f94 --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-901-xvba_support-e8d631f741bc32f75374a698b9a39b387c9aa0ab.patch @@ -0,0 +1,7088 @@ +diff --git a/configure.in b/configure.in +index bca9239..66ccbcd 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 +@@ -1943,6 +1989,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) +@@ -2085,6 +2132,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 73405bf..58887a4 100644 +--- a/language/English/strings.xml ++++ b/language/English/strings.xml +@@ -1230,6 +1230,8 @@ + Allow hardware acceleration (OpenMax) + Pixel Shaders + Allow hardware acceleration (VideoToolbox) ++ Allow hardware acceleration (XVBA) ++ Use XvBA shared surfaces (highly experimental) + + 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..d159376 +--- /dev/null ++++ b/lib/ffmpeg/libavcodec/xvba_h264.c +@@ -0,0 +1,174 @@ ++/* ++ * 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); ++ ++ 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); ++ ++ 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..36daf34 +--- /dev/null ++++ b/lib/ffmpeg/libavcodec/xvba_vc1.c +@@ -0,0 +1,191 @@ ++/* ++ * 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); ++ ++ 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/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp +index adc89af..b5c6b1a 100644 +--- a/xbmc/ApplicationMessenger.cpp ++++ b/xbmc/ApplicationMessenger.cpp +@@ -70,7 +70,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 4961b7d..d6972ab 100644 +--- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp ++++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +@@ -60,6 +60,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 +@@ -120,6 +123,9 @@ CLinuxRendererGL::YUVBUFFER::YUVBUFFER() + #ifdef HAVE_LIBVDPAU + vdpau = NULL; + #endif ++#ifdef HAVE_LIBXVBA ++ xvba = NULL; ++#endif + } + + CLinuxRendererGL::YUVBUFFER::~YUVBUFFER() +@@ -223,7 +229,7 @@ bool CLinuxRendererGL::ValidateRenderer() + + void CLinuxRendererGL::ManageTextures() + { +- m_NumYV12Buffers = 2; ++ m_NumYV12Buffers = 3; + //m_iYV12RenderBuffer = 0; + return; + } +@@ -568,6 +574,11 @@ void CLinuxRendererGL::Flush() + m_bValidated = false; + } + ++unsigned int CLinuxRendererGL::GetProcessorSize() ++{ ++ return m_NumYV12Buffers; ++} ++ + void CLinuxRendererGL::Update(bool bPauseDrawing) + { + if (!m_bConfigured) return; +@@ -729,14 +740,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; +@@ -816,7 +828,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()) +@@ -897,6 +909,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"); +@@ -1031,6 +1048,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 +@@ -1124,6 +1153,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) + { +@@ -1597,6 +1633,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(0.0, 0.0); glVertex2f(m_destRect.x1, m_destRect.y1); ++ glTexCoord2f(1.0, 0.0); glVertex2f(m_destRect.x2, m_destRect.y1); ++ glTexCoord2f(1.0, 1.0); glVertex2f(m_destRect.x2, m_destRect.y2); ++ glTexCoord2f(0.0, 1.0); 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]; +@@ -2351,6 +2458,367 @@ void CLinuxRendererGL::UploadVAAPITexture(int index) + #endif + } + ++void CLinuxRendererGL::DeleteXVBATexture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ YUVPLANE &plane = m_buffers[index].fields[0][1]; ++ ++ if (m_buffers[index].xvba) ++ m_buffers[index].xvba->FinishGL(); ++ ++ SAFE_RELEASE(m_buffers[index].xvba); ++ ++ if(plane.id && glIsTexture(plane.id)) ++ glDeleteTextures(1, &plane.id); ++ plane.id = 0; ++ m_buffers[index].fields[0][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][1]; ++ ++ DeleteXVBATexture(index); ++ ++ memset(&im , 0, sizeof(im)); ++ memset(&fields, 0, sizeof(fields)); ++ im.height = m_sourceHeight; ++ im.width = m_sourceWidth; ++ ++ plane.texwidth = im.width; ++ plane.texheight = im.height; ++ ++ plane.pixpertex_x = 1; ++ plane.pixpertex_y = 1; ++ ++ glGenTextures(1, &plane.id); ++ fields[0][0].id = plane.id; ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++ return true; ++} ++ ++void CLinuxRendererGL::UploadXVBATexture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ XVBA::CDecoder *xvba = m_buffers[index].xvba; ++ ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][1]; ++ ++ if (!xvba) ++ { ++ fields[0][0].id = plane.id; ++ fields[1][0].id = plane.id; ++ fields[2][0].id = plane.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) ++ fields[m_currentField][0].id = xvba->GetTexture(index, field); ++ ++ glDisable(m_textureTarget); ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++} ++ ++//******************************************************************************************************** ++// XVBA YV12 Texture creation, deletion, copying + clearing ++//******************************************************************************************************** ++void CLinuxRendererGL::DeleteXVBAyv12Texture(int index) ++{ ++ YV12Image &im = m_buffers[index].image; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ GLuint *pbo = m_buffers[index].pbo; ++ ++ 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(); ++ return true; ++} ++ ++void CLinuxRendererGL::UploadXVBAyv12Texture(int source) ++{ ++ YUVBUFFER& buf = m_buffers[source]; ++ YV12Image* im = &buf.image; ++ YUVFIELDS& fields = buf.fields; ++ ++ if (!(im->flags&IMAGE_FLAG_READY)) ++ { ++ 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(); ++ ++ CalculateTextureSourceRects(source, 3); ++ ++ glDisable(m_textureTarget); ++} ++ + void CLinuxRendererGL::UploadYUV422PackedTexture(int source) + { + YUVBUFFER& buf = m_buffers[source]; +@@ -2934,6 +3402,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); +@@ -2947,6 +3418,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); +@@ -2970,7 +3444,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; + } + +@@ -3010,10 +3485,22 @@ bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method) + if(m_renderMethod & RENDER_VAAPI) + return false; + +- 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 (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((method == VS_INTERLACEMETHOD_RENDER_BLEND + || method == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED +@@ -3045,7 +3532,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 +@@ -3104,7 +3591,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) +@@ -3128,4 +3615,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); ++ buf.xvba = (XVBA::CDecoder*)xvba->Acquire(); ++} ++#endif ++ + #endif +diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h +index 38c84aa..9b8a5ae 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,9 @@ protected: + #ifdef HAVE_LIBVA + VAAPI::CHolder& vaapi; + #endif ++#ifdef HAVE_LIBXVBA ++ XVBA::CDecoder* xvba; ++#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 31bb49a..f9a7aa2 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 */ +@@ -639,11 +643,19 @@ void CXBMCRenderManager::Present() + } + } + ++#ifdef HAVE_LIBVA ++ /* wait for this present to be valid */ ++ if(g_graphicsContext.IsFullScreenVideo()) ++ WaitPresentTime(m_presenttime); ++#endif ++ + Render(true, 0, 255); + ++#ifndef HAVE_LIBVA + /* wait for this present to be valid */ + if(g_graphicsContext.IsFullScreenVideo()) + WaitPresentTime(m_presenttime); ++#endif + + m_presentevent.Set(); + } +@@ -779,6 +791,23 @@ 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) ++ { ++ pic.xvba->CopyYV12(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 1728e82..7b528ab 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 + 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..fd7e934 +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp +@@ -0,0 +1,1311 @@ ++/* ++ * 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 "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; ++ ++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 = g_Windowing.GetWindow(); ++ } ++ ++ 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; ++} ++ ++//----------------------------------------------------------------------------- ++//----------------------------------------------------------------------------- ++ ++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) ++{ ++ CLog::Log(LOGNOTICE,"(XVBA::Open) opening dxva decoder"); ++ ++ 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"); ++ ++ if (!m_context) ++ return; ++ ++ DestroySession(); ++ if (m_context) ++ m_context->Release(); ++ m_context = 0; ++ ++ if (m_flipBuffer) ++ delete [] m_flipBuffer; ++ ++ g_Windowing.Unregister(this); ++} ++ ++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) ++ { ++ CLog::Log(LOGNOTICE,"XVBA::Check - Attempting recovery"); ++ ++ CSingleLock gLock(g_graphicsContext); ++ CExclusiveLock lock(m_decoderSection); ++ ++ DestroySession(); ++ ResetState(); ++ CXVBAContext::EnsureContext(&m_context); ++ ++ return VC_FLUSHED; ++ } ++ 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_LOST; ++} ++ ++bool CDecoder::CreateSession(AVCodecContext* avctx) ++{ ++ m_surfaceWidth = (avctx->coded_width+15) & ~15; ++ m_surfaceHeight = (avctx->coded_height+15) & ~15; ++ ++ 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__); ++ 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; ibuffers_alllocated > 0) ++ m_dllAvUtil.av_free(render->buffers); ++ ++ m_videoSurfaces.pop_back(); ++ if (m_xvbaSession) ++ g_XVBA_vtable.DestroySurface(render->surface); ++ free(render); ++ } ++ ++ if (m_xvbaSession) ++ g_XVBA_vtable.DestroyDecode(m_xvbaSession); ++ m_xvbaSession = 0; ++} ++ ++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 ++ bool found(false); ++ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i) ++ { ++ if(xvba->m_videoSurfaces[i] == render) ++ { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ { ++ 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 ++ bool found(false); ++ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i) ++ { ++ if(xvba->m_videoSurfaces[i] == render) ++ { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ { ++ 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; ++ 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; ++ } ++ ++ 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); ++ } ++ 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); ++ 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; ++ 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) ++ { ++ 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); ++ } ++} ++ ++int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) ++{ ++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque; ++ CDecoder* xvba = (CDecoder*)ctx->GetHardware(); ++ struct pictureAge* pA = &xvba->picAge; ++ ++ 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 surface ++ 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; ++ } ++ 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); ++ if (Success != g_XVBA_vtable.CreateSurface(&surfaceInput, &surfaceOutput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed to create video surface", __LINE__); ++ return -1; ++ } ++ CSingleLock lock(xvba->m_videoSurfaceSec); ++ render->surface = surfaceOutput.surface; ++ render->buffers_alllocated = 0; ++ render->picture_descriptor = (XVBAPictureDescriptor *)xvba->m_xvbaBufferPool.picture_descriptor_buffer->bufferXVBA; ++ render->iq_matrix = (XVBAQuantMatrixAvc *)xvba->m_xvbaBufferPool.iq_matrix_buffer->bufferXVBA; ++ xvba->m_videoSurfaces.push_back(render); ++ } ++ ++ if (render == NULL) ++ return -1; ++ ++ pic->data[0] = (uint8_t*)render; ++ pic->data[1] = ++ pic->data[2] = ++ pic->data[3] = 0; ++ ++ pic->linesize[0] = ++ pic->linesize[1] = ++ pic->linesize[2] = ++ pic->linesize[3] = 0; ++ ++ 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; ++ 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 ++ bool found(false); ++ for(unsigned int i = 0; i < m_videoSurfaces.size(); ++i) ++ { ++ if(m_videoSurfaces[i] == render) ++ { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ { ++ CLog::Log(LOGWARNING, "XVBA::Decode - ignoring invalid buffer"); ++ 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) ++ { ++ CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL"); ++ return; ++ } ++ ++ if (m_flipBuffer[index].outPic) ++ { ++ 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_presentPicture = NULL; ++} ++ ++void CDecoder::CopyYV12(uint8_t *dest) ++{ ++ CSharedLock lock(m_decoderSection); ++ ++ { CSharedLock dLock(m_displaySection); ++ if(m_displayState != XVBA_OPEN) ++ return; ++ } ++ ++ if (!m_presentPicture) ++ { ++ 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_presentPicture->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; ++ if (Success != g_XVBA_vtable.GetSurface(&input)) ++ { ++ CLog::Log(LOGERROR,"(XVBA::CopyYV12) failed to get surface"); ++ } ++ ++ if (m_presentPicture->render) ++ { ++ CSingleLock lock(m_videoSurfaceSec); ++ m_presentPicture->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER; ++ m_presentPicture->render = NULL; ++ } ++ { ++ CSingleLock lock(m_outPicSec); ++ m_freeOutPic.push_back(m_presentPicture); ++ m_presentPicture = NULL; ++ } ++} ++ ++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) ++ 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; ++ } ++ ++ 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; ++ 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]; ++} ++ ++void CDecoder::FinishGL() ++{ ++ CLog::Log(LOGNOTICE, "XVBA::FinishGL - clearing down gl resources"); ++ ++ CSharedLock lock(m_decoderSection); ++ ++ for (unsigned int i=0; irender->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 (int j=0; j<3; ++j) ++ { ++ if (glIsTexture(m_flipBuffer[i].glTexture[j])) ++ { ++ glDeleteTextures(1, &m_flipBuffer[i].glTexture[j]); ++ m_flipBuffer[i].glTexture[j] = 0; ++ } ++ if (m_flipBuffer[i].glSurface[j]) ++ { ++ g_XVBA_vtable.DestroySurface(m_flipBuffer[i].glSurface[j]); ++ m_flipBuffer[i].glSurface[j] = 0; ++ } ++ } ++ } ++} ++ ++#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..f5c8a32 +--- /dev/null ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h +@@ -0,0 +1,153 @@ ++/* ++ * 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 "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 ++}; ++ ++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; ++ 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(uint8_t *dest); ++ int UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget); ++ GLuint GetTexture(int index, XVBA_SURFACE_FLAG field); ++ 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); ++ ++ // 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_numRenderBuffers; ++ ++ XVBADecodeCap m_decoderCap; ++ void *m_xvbaSession; ++ 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; ++ void *glSurface[3]; ++ GLuint glTexture[3]; ++ }; ++ CCriticalSection m_outPicSec, m_videoSurfaceSec; ++ 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 bb88c74..f5fd833 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 +@@ -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) +@@ -152,16 +152,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; + } +@@ -233,7 +229,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; +@@ -505,7 +501,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + + void CDVDDemuxFFmpeg::Dispose() + { +- g_demuxer = this; ++ g_demuxer.set(this); + + if (m_pFormatContext) + { +@@ -554,7 +550,7 @@ void CDVDDemuxFFmpeg::Reset() + + void CDVDDemuxFFmpeg::Flush() + { +- g_demuxer = this; ++ g_demuxer.set(this); + + // naughty usage of an internal ffmpeg function + if (m_pFormatContext) +@@ -570,7 +566,7 @@ void CDVDDemuxFFmpeg::Abort() + + void CDVDDemuxFFmpeg::SetSpeed(int iSpeed) + { +- g_demuxer = this; ++ g_demuxer.set(this); + + if(!m_pFormatContext) + return; +@@ -632,7 +628,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; +@@ -831,7 +827,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; +@@ -891,7 +887,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 6061909..af6175e 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -341,7 +341,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; +@@ -432,7 +432,7 @@ void CDVDPlayer::OnStartup() + + m_messenger.Init(); + +- g_dvdPerformanceCounter.EnableMainPerformance(ThreadHandle()); ++ g_dvdPerformanceCounter.EnableMainPerformance(this); + + CUtil::ClearTempFonts(); + } +@@ -2710,7 +2710,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; + } +@@ -2772,11 +2772,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 695cb7e..4c99c48 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 +@@ -288,7 +288,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() +@@ -1051,6 +1051,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 28a7c58..27c8930 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 8426af0..db02f17 100644 +--- a/xbmc/filesystem/FilePipe.cpp ++++ b/xbmc/filesystem/FilePipe.cpp +@@ -82,7 +82,7 @@ unsigned int CFilePipe::Read(void* lpBuf, int64_t uiBufSize) + if (!m_pipe) + return -1; + +- return m_pipe->Read((char *)lpBuf,uiBufSize,INFINITE); ++ return m_pipe->Read((char *)lpBuf,uiBufSize,0xFFFFFFFF); + } + + int CFilePipe::Write(const void* lpBuf, int64_t uiBufSize) +@@ -90,7 +90,7 @@ int CFilePipe::Write(const void* lpBuf, int64_t uiBufSize) + if (!m_pipe) + return -1; + +- return (int)(m_pipe->Write((const char *)lpBuf,uiBufSize,INFINITE)); // its not the size. its bool. either all was written or not. ++ return (int)(m_pipe->Write((const char *)lpBuf,uiBufSize,0xFFFFFFFF)); // its not the size. its bool. either all was written or not. + } + + void CFilePipe::SetEof() +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..1390020 100644 +--- a/xbmc/filesystem/PipesManager.cpp ++++ b/xbmc/filesystem/PipesManager.cpp +@@ -195,7 +195,7 @@ bool Pipe::Write(const char *buf, int nSize, int nWaitMillis) + break; + } + +- if ((unsigned int) nWaitMillis != INFINITE) ++ if ((unsigned int) nWaitMillis != 0xFFFFFFFF) + break; + } + } +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 8910bbc..9679be5 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..ebc60cc 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,132 @@ void _aligned_free(void *p) { + free(pFull); + } + ++#ifndef _WIN32 ++ ++#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__) ++static FILE* procMeminfoFP = NULL; ++#endif ++ ++void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) ++{ ++ if (!lpBuffer) ++ return; ++ ++ memset(lpBuffer, 0, sizeof(MEMORYSTATUS)); ++ lpBuffer->dwLength = sizeof(MEMORYSTATUS); ++ ++#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->dwTotalPhys = 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->dwAvailPageFile = swap.xsu_avail; ++ lpBuffer->dwTotalVirtual = lpBuffer->dwTotalPhys + 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->dwAvailPhys = lpBuffer->dwTotalPhys - used; ++ lpBuffer->dwAvailVirtual = lpBuffer->dwAvailPhys; // 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->dwTotalPhys = physmem; ++ lpBuffer->dwTotalVirtual = 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->dwAvailPhys = mem_inactive + mem_cache + mem_free; ++ lpBuffer->dwAvailVirtual = mem_inactive + mem_cache + mem_free; ++ ++ if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0) ++ lpBuffer->dwAvailPageFile = 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->dwLength = sizeof(MEMORYSTATUS); ++ lpBuffer->dwAvailPageFile = (info.freeswap * info.mem_unit); ++ lpBuffer->dwAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit); ++ lpBuffer->dwAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit); ++ lpBuffer->dwTotalPhys = (info.totalram * info.mem_unit); ++ lpBuffer->dwTotalVirtual = (info.totalram * info.mem_unit); ++#endif ++} ++ ++#endif + +diff --git a/xbmc/linux/XMemUtils.h b/xbmc/linux/XMemUtils.h +index d6d314a..d368012 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 GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer); ++ + #endif + +diff --git a/xbmc/linux/XSyncUtils.cpp b/xbmc/linux/XSyncUtils.cpp +deleted file mode 100644 +index 454ff85..0000000 +--- a/xbmc/linux/XSyncUtils.cpp ++++ /dev/null +@@ -1,171 +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 GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) +-{ +- if (!lpBuffer) +- return; +- +- memset(lpBuffer, 0, sizeof(MEMORYSTATUS)); +- lpBuffer->dwLength = sizeof(MEMORYSTATUS); +- +-#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->dwTotalPhys = 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->dwAvailPageFile = swap.xsu_avail; +- lpBuffer->dwTotalVirtual = lpBuffer->dwTotalPhys + 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->dwAvailPhys = lpBuffer->dwTotalPhys - used; +- lpBuffer->dwAvailVirtual = lpBuffer->dwAvailPhys; // 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->dwTotalPhys = physmem; +- lpBuffer->dwTotalVirtual = 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->dwAvailPhys = mem_inactive + mem_cache + mem_free; +- lpBuffer->dwAvailVirtual = mem_inactive + mem_cache + mem_free; +- +- if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0) +- lpBuffer->dwAvailPageFile = 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->dwLength = sizeof(MEMORYSTATUS); +- lpBuffer->dwAvailPageFile = (info.freeswap * info.mem_unit); +- lpBuffer->dwAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit); +- lpBuffer->dwAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit); +- lpBuffer->dwTotalPhys = (info.totalram * info.mem_unit); +- lpBuffer->dwTotalVirtual = (info.totalram * info.mem_unit); +-#endif +-} +- +-#endif +diff --git a/xbmc/linux/XSyncUtils.h b/xbmc/linux/XSyncUtils.h +deleted file mode 100644 +index c8effa2..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 GlobalMemoryStatus(LPMEMORYSTATUS 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/linux/XThreadUtils.h b/xbmc/linux/XThreadUtils.h +deleted file mode 100644 +index 41b659e..0000000 +--- a/xbmc/linux/XThreadUtils.h ++++ /dev/null +@@ -1,100 +0,0 @@ +-#ifndef __XTHREAD_UTILS__H__ +-#define __XTHREAD_UTILS__H__ +- +-/* +- * 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 +- +-HANDLE WINAPI CreateThread( +- LPSECURITY_ATTRIBUTES lpThreadAttributes, +- SIZE_T dwStackSize, +- LPTHREAD_START_ROUTINE lpStartAddress, +- LPVOID lpParameter, +- DWORD dwCreationFlags, +- LPDWORD lpThreadId +- ); +- +-HANDLE _beginthreadex( +- void *security, +- unsigned stack_size, +- int ( *start_address )( void * ), +- void *arglist, +- unsigned initflag, +- unsigned *thrdaddr +-); +- +-uintptr_t _beginthread( +- void( *start_address )( void * ), +- unsigned stack_size, +- void *arglist +-); +- +-#if 0 // Deprecated, use CThread::GetCurrentThreadId() instead +-DWORD WINAPI GetCurrentThreadId(void); +-#endif +- +-HANDLE WINAPI GetCurrentThread(void); +-HANDLE WINAPI GetCurrentProcess(void); +- +-BOOL WINAPI GetThreadTimes ( +- HANDLE hThread, +- LPFILETIME lpCreationTime, +- LPFILETIME lpExitTime, +- LPFILETIME lpKernelTime, +- LPFILETIME lpUserTime +-); +- +-int GetThreadPriority( +- HANDLE hThread +-); +- +-BOOL WINAPI SetThreadPriority( +- HANDLE hThread, +- int nPriority +-); +- +-// helper class for TLS handling +-class TLS +-{ +-public: +- TLS() +- { +- pthread_key_create(&m_key, free); +- } +- +- ~TLS() +- { +- pthread_key_delete(m_key); +- } +- +- void *Get() +- { +- if (pthread_getspecific(m_key) == NULL) +-pthread_setspecific(m_key, malloc(8)); +- +- return pthread_getspecific(m_key); +- } +- +- pthread_key_t m_key; +-}; +- +-#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 d4c58e4..3ac73f9 100644 +--- a/xbmc/network/AirPlayServer.cpp ++++ b/xbmc/network/AirPlayServer.cpp +@@ -168,7 +168,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/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/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp +index ffe47a5..a7b54d2 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 e61aa23..1ea4b9c 100644 +--- a/xbmc/rendering/dx/RenderSystemDX.cpp ++++ b/xbmc/rendering/dx/RenderSystemDX.cpp +@@ -553,7 +553,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 b87ab67..3084ae9 100644 +--- a/xbmc/settings/GUISettings.cpp ++++ b/xbmc/settings/GUISettings.cpp +@@ -587,6 +587,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, false); + #endif +diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp +index d262f50..fb40609 100644 +--- a/xbmc/settings/GUIWindowSettingsCategory.cpp ++++ b/xbmc/settings/GUIWindowSettingsCategory.cpp +@@ -931,6 +931,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..becc594 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,15 @@ void CThread::StopThread(bool bWait /*= true*/) + { + m_bStop = true; + m_StopEvent.Set(); +- if (m_ThreadHandle && bWait) ++ if (m_ThreadId && bWait) + { +- WaitForThreadExit(INFINITE); +- CloseHandle(m_ThreadHandle); +- m_ThreadHandle = NULL; ++ 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 +153,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 +168,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 0f61171..75af866 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 7892d64..6b45008 100644 +--- a/xbmc/utils/LCD.h ++++ b/xbmc/utils/LCD.h +@@ -66,8 +66,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 4fae348..7715dd9 100644 +--- a/xbmc/video/VideoInfoScanner.cpp ++++ b/xbmc/video/VideoInfoScanner.cpp +@@ -53,7 +53,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 076dc3a..4a997b0 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -106,7 +106,7 @@ using namespace std; + + #endif + +-CVideoReferenceClock::CVideoReferenceClock() ++CVideoReferenceClock::CVideoReferenceClock() : CThread("CVideoReferenceClock") + { + m_SystemFrequency = CurrentHostFrequency(); + m_ClockSpeed = 1.0; +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 62cf554..eb02e9a 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -139,8 +139,14 @@ bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RES + // register XRandR Events + #if defined(HAS_XRANDR) + int iReturn; ++#if defined(HAS_SDL) ++ m_info.info.x11.lock_func(); ++#endif + XRRQueryExtension(m_dpy, &m_RREventBase, &iReturn); + XRRSelectInput(m_dpy, m_wmWindow, RRScreenChangeNotifyMask); ++#if defined(HAS_SDL) ++ m_info.info.x11.unlock_func(); ++#endif + #endif + + m_bWindowCreated = true; +@@ -190,7 +196,12 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + mode.h = res.iHeight; + mode.hz = res.fRefreshRate; + mode.id = res.strId; +- ++ ++#if defined(HAS_SDL) ++ if (m_SDLSurface) ++ m_info.info.x11.lock_func(); ++#endif ++ + if(m_bFullScreen) + { + OnLostDevice(); +@@ -198,6 +209,11 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + } + else + g_xrandr.RestoreState(); ++ ++#if defined(HAS_SDL) ++ if (m_SDLSurface) ++ m_info.info.x11.unlock_func(); ++#endif + #endif + + int options = SDL_OPENGL; +@@ -316,30 +332,33 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) + bool CWinSystemX11::RefreshGlxContext() + { + bool retVal = false; +- SDL_SysWMinfo info; +- SDL_VERSION(&info.version); +- if (SDL_GetWMInfo(&info) <= 0) ++ SDL_VERSION(&m_info.version); ++ if (SDL_GetWMInfo(&m_info) <= 0) + { + CLog::Log(LOGERROR, "Failed to get window manager info from SDL"); + return false; + } + +- if(m_glWindow == info.info.x11.window && m_glContext) ++ if(m_glWindow == m_info.info.x11.window && m_glContext) + { + CLog::Log(LOGERROR, "GLX: Same window as before, refreshing context"); ++ m_info.info.x11.lock_func(); + glXMakeCurrent(m_dpy, None, NULL); + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); ++ m_info.info.x11.unlock_func(); + return true; + } + ++ m_info.info.x11.lock_func(); ++ + XVisualInfo vMask; + XVisualInfo *visuals; + XVisualInfo *vInfo = NULL; + int availableVisuals = 0; + vMask.screen = DefaultScreen(m_dpy); + XWindowAttributes winAttr; +- m_glWindow = info.info.x11.window; +- m_wmWindow = info.info.x11.wmwindow; ++ m_glWindow = m_info.info.x11.window; ++ m_wmWindow = m_info.info.x11.wmwindow; + + /* Assume a depth of 24 in case the below calls to XGetWindowAttributes() + or XGetVisualInfo() fail. That shouldn't happen unless something is +@@ -405,6 +424,8 @@ bool CWinSystemX11::RefreshGlxContext() + else + CLog::Log(LOGERROR, "GLX Error: vInfo is NULL!"); + ++ m_info.info.x11.unlock_func(); ++ + return retVal; + } + +@@ -471,6 +492,7 @@ void CWinSystemX11::CheckDisplayEvents() + bool bGotEvent(false); + bool bTimeout(false); + XEvent Event; ++ + while (XCheckTypedEvent(m_dpy, m_RREventBase + RRScreenChangeNotify, &Event)) + { + if (Event.type == m_RREventBase + RRScreenChangeNotify) +@@ -501,6 +523,7 @@ void CWinSystemX11::CheckDisplayEvents() + // reset fail safe timer + m_dpyLostTime = 0; + } ++ + #endif + } + +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 5b941be..4f1f2ae 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -28,6 +28,10 @@ + #include + #include "threads/CriticalSection.h" + ++#ifdef HAS_SDL ++#include ++#endif ++ + class IDispResource; + + class CWinSystemX11 : public CWinSystemBase +@@ -66,7 +70,10 @@ protected: + void CheckDisplayEvents(); + void OnLostDevice(); + ++#ifdef HAS_SDL + SDL_Surface* m_SDLSurface; ++ SDL_SysWMinfo m_info; ++#endif + GLXContext m_glContext; + GLXWindow m_glWindow; + Window m_wmWindow; +diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp +index ec02b10..1a10104 100644 +--- a/xbmc/windowing/X11/WinSystemX11GL.cpp ++++ b/xbmc/windowing/X11/WinSystemX11GL.cpp +@@ -43,6 +43,10 @@ CWinSystemX11GL::~CWinSystemX11GL() + + bool CWinSystemX11GL::PresentRenderImpl(const CDirtyRegionList& dirty) + { ++#if defined(HAS_SDL) ++ m_info.info.x11.lock_func(); ++#endif ++ + CheckDisplayEvents(); + + if(m_iVSyncMode == 3) +@@ -119,6 +123,10 @@ bool CWinSystemX11GL::PresentRenderImpl(const CDirtyRegionList& dirty) + else + glXSwapBuffers(m_dpy, m_glWindow); + ++#if defined(HAS_SDL) ++ m_info.info.x11.unlock_func(); ++#endif ++ + return true; + } + diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-902-xvba-thread_fixes.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-902-xvba-thread_fixes.patch new file mode 100644 index 0000000000..639c3cfa7c --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-902-xvba-thread_fixes.patch @@ -0,0 +1,12 @@ +diff -Naur xbmc-f3b0020/xbmc/network/AirTunesServer.cpp xbmc-f3b0020.patch/xbmc/network/AirTunesServer.cpp +--- xbmc-f3b0020/xbmc/network/AirTunesServer.cpp 2011-12-10 22:16:17.000000000 +0100 ++++ xbmc-f3b0020.patch/xbmc/network/AirTunesServer.cpp 2011-12-11 18:22:56.423945075 +0100 +@@ -279,7 +279,7 @@ + } + } + +-CAirTunesServer::CAirTunesServer(int port, bool nonlocal) ++CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("CAirTunesServer") + { + m_port = port; + m_pLibShairport = new DllLibShairport(); diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-901-vdpau_fix_deinterlacing_if_flag_toggles.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-951-vdpau_fix_deinterlacing_if_flag_toggles.patch similarity index 100% rename from packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-901-vdpau_fix_deinterlacing_if_flag_toggles.patch rename to packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-9847e43-951-vdpau_fix_deinterlacing_if_flag_toggles.patch