From c7d6e7b678efe1c90c8e2df28a3f9606d5369c40 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 8 Feb 2012 06:29:57 +0100 Subject: [PATCH] xbmc-pvr: readd missing patch Signed-off-by: Stephan Raue --- ...428afb48c6495f8bc1a1f55f82aa5f722021.patch | 7002 +++++++++++++++++ 1 file changed, 7002 insertions(+) create mode 100644 packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-992cf35-902.01-xvba_support-4bf8428afb48c6495f8bc1a1f55f82aa5f722021.patch diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-992cf35-902.01-xvba_support-4bf8428afb48c6495f8bc1a1f55f82aa5f722021.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-992cf35-902.01-xvba_support-4bf8428afb48c6495f8bc1a1f55f82aa5f722021.patch new file mode 100644 index 0000000000..78d6f4042d --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-992cf35-902.01-xvba_support-4bf8428afb48c6495f8bc1a1f55f82aa5f722021.patch @@ -0,0 +1,7002 @@ +diff -Naur xbmc-1fef727/configure.in xbmc-1fef727.patch/configure.in +--- xbmc-1fef727/configure.in 2012-02-07 12:47:09.000000000 +0100 ++++ xbmc-1fef727.patch/configure.in 2012-02-07 14:30:17.968097582 +0100 +@@ -98,6 +98,8 @@ + vaapi_disabled="== VAAPI support manually disabled. ==" + crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. ==" + crystalhd_disabled="== CrystalHD support manually disabled. ==" ++xvba_not_found="== Could not find amdxvba.h. XVBA support disabled. ==" ++xvba_disabled="== XVBA support manually disabled. ==" + vdadecoder_enabled="== VDADecoder support enabled. ==" + vdadecoder_disabled="== VDADecoder support manually disabled. ==" + vtbdecoder_enabled="== VTBDecoder support enabled. ==" +@@ -204,6 +206,12 @@ + [enable CrystalHD decoding (default is auto)])], + [use_crystalhd=$enableval], + [use_crystalhd=auto]) ++ ++AC_ARG_ENABLE([xvba], ++ [AS_HELP_STRING([--enable-xvba], ++ [enable XVBA decoding (default is auto)])], ++ [use_xvba=$enableval], ++ [use_xvba=auto]) + + AC_ARG_ENABLE([vdadecoder], + [AS_HELP_STRING([--enable-vdadecoder], +@@ -1382,6 +1390,38 @@ + USE_CRYSTALHD=0 + fi + ++# XVBA ++if test "x$use_xvba" != "xno"; then ++ if test "$host_vendor" = "apple" ; then ++ if test "x$use_xvba" = "xyes"; then ++ AC_MSG_ERROR([XVBA not supported on this platform]) ++ else ++ use_xvba="no" ++ AC_MSG_NOTICE($xvba_disabled) ++ fi ++ USE_XVBA=0 ++ else ++ initial_val=$use_xvba ++ AC_CHECK_HEADER([amd/amdxvba.h],, use_xvba=no, [#include ]) ++ ++ if test "x$use_xvba" = "xno"; then ++ if test "x$initial_val" = "xyes"; then ++ AC_MSG_ERROR($xvba_not_found) ++ else ++ AC_MSG_RESULT($xvba_not_found) ++ fi ++ USE_XVBA=0 ++ else ++ AC_DEFINE([HAVE_LIBXVBA], [1], [Define to 1 if you have the 'xvba' header (amdxvba.h)]) ++ USE_XVBA=1 ++ fi ++ fi ++else ++ AC_MSG_NOTICE($xvba_disabled) ++ USE_XVBA=0 ++fi ++ ++ + # VDADecoder + if test "x$use_vdadecoder" != "xno"; then + if test "$host_vendor" = "apple" ; then +@@ -1578,6 +1618,12 @@ + final_message="$final_message\n CrystalHD:\tNo" + fi + ++if test "x$use_xvba" != "xno"; then ++ final_message="$final_message\n XVBA:\t\tYes" ++else ++ final_message="$final_message\n XVBA:\t\tNo" ++fi ++ + if test "x$use_vdadecoder" != "xno"; then + final_message="$final_message\n VDADecoder:\tYes" + else +@@ -1943,6 +1989,7 @@ + AC_SUBST(USE_VDPAU) + AC_SUBST(USE_VAAPI) + AC_SUBST(USE_CRYSTALHD) ++AC_SUBST(USE_XVBA) + AC_SUBST(USE_LIBSMBCLIENT) + AC_SUBST(USE_LIBNFS) + AC_SUBST(USE_LIBAFPCLIENT) +@@ -2085,6 +2132,7 @@ + --enable-gpl \ + `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \ + `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \ ++ `if test "x$use_xvba" != "xno"; then echo --enable-xvba; else echo --disable-xvba; fi` \ + --enable-protocol=http \ + --enable-pthreads \ + --enable-runtime-cpudetect \ +diff -Naur xbmc-1fef727/language/English/strings.xml xbmc-1fef727.patch/language/English/strings.xml +--- xbmc-1fef727/language/English/strings.xml 2012-02-07 12:47:05.000000000 +0100 ++++ xbmc-1fef727.patch/language/English/strings.xml 2012-02-07 14:30:17.970097621 +0100 +@@ -1230,6 +1230,8 @@ + Allow hardware acceleration (OpenMax) + Pixel Shaders + Allow hardware acceleration (VideoToolbox) ++ Allow hardware acceleration (XVBA) ++ Use XvBA shared surfaces + + A/V sync method + Audio clock +diff -Naur xbmc-1fef727/lib/ffmpeg/configure xbmc-1fef727.patch/lib/ffmpeg/configure +--- xbmc-1fef727/lib/ffmpeg/configure 2012-02-07 12:46:58.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/configure 2012-02-07 14:30:17.994098094 +0100 +@@ -111,6 +111,7 @@ + --disable-vaapi disable VAAPI code + --disable-vdpau disable VDPAU code + --disable-dxva2 disable DXVA2 code ++ --disable-xvba disable XVBA code + --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) + --enable-hardcoded-tables use hardcoded tables instead of runtime generation + --enable-memalign-hack emulate memalign, interferes with memory debuggers +@@ -932,6 +933,7 @@ + swscale_alpha + vaapi + vdpau ++ xvba + version3 + x11grab + zlib +@@ -1240,6 +1242,7 @@ + h264_dxva2_hwaccel_deps="dxva2api_h" + h264_dxva2_hwaccel_select="dxva2 h264_decoder" + h264_vaapi_hwaccel_select="vaapi" ++h264_xvba_hwaccel_select="xvba" + h264_vdpau_decoder_select="vdpau h264_decoder" + imc_decoder_select="fft mdct" + jpegls_decoder_select="golomb" +@@ -1263,6 +1266,7 @@ + mpeg2_dxva2_hwaccel_select="dxva2 mpeg2video_decoder" + mpeg2_vaapi_hwaccel_select="vaapi mpeg2video_decoder" + mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder" ++mpeg2_xvba_hwaccel_select="xvba mpeg2video_decoder" + mpeg4_vdpau_decoder_deps="vdpau_vdpau_h vdpau_vdpau_x11_h vdpau_mpeg4_support" + mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder" + mpeg_xvmc_decoder_deps="X11_extensions_XvMClib_h" +@@ -1306,6 +1310,7 @@ + vc1_dxva2_hwaccel_deps="dxva2api_h DXVA_PictureParameters_wDecodedPictureIndex" + vc1_dxva2_hwaccel_select="dxva2 vc1_decoder" + vc1_vaapi_hwaccel_select="vaapi vc1_decoder" ++vc1_xvba_hwaccel_select="xvba vc1_decoder" + vc1_vdpau_decoder_select="vdpau vc1_decoder" + vorbis_decoder_select="mdct" + vorbis_encoder_select="mdct" +@@ -1327,12 +1332,14 @@ + wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" + wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" + wmv3_vdpau_decoder_select="vc1_vdpau_decoder" ++wmv3_xvba_hwaccel_select="vc1_xvba_hwaccel" + zlib_decoder_select="zlib" + zlib_encoder_select="zlib" + zmbv_decoder_select="zlib" + zmbv_encoder_select="zlib" + + vaapi_deps="va_va_h" ++xvba_deps="amd_amdxvba_h" + vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" + + # parsers +@@ -2762,6 +2769,7 @@ + check_header termios.h + check_header vdpau/vdpau.h + check_header vdpau/vdpau_x11.h ++check_header amd/amdxvba.h + check_cpp_condition vdpau/vdpau.h "defined(VDP_DECODER_PROFILE_MPEG4_PART2_SP)" && enable vdpau_mpeg4_support + + check_header X11/extensions/XvMClib.h +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/allcodecs.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/allcodecs.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/allcodecs.c 2012-02-07 12:47:01.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/allcodecs.c 2012-02-07 14:30:17.996098134 +0100 +@@ -57,13 +57,17 @@ + REGISTER_HWACCEL (H263_VAAPI, h263_vaapi); + REGISTER_HWACCEL (H264_DXVA2, h264_dxva2); + REGISTER_HWACCEL (H264_VAAPI, h264_vaapi); ++ REGISTER_HWACCEL (H264_XVBA, h264_xvba); + REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2); + REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi); + REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi); ++ REGISTER_HWACCEL (MPEG2_XVBA, mpeg2_xvba); + REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2); + REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi); ++ REGISTER_HWACCEL (VC1_XVBA, vc1_xvba); + REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2); + REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi); ++ REGISTER_HWACCEL (WMV3_XVBA, wmv3_xvba); + + /* video codecs */ + REGISTER_ENCODER (A64MULTI, a64multi); +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/h264.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/h264.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/h264.c 2012-02-07 12:47:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/h264.c 2012-02-07 14:30:17.998098174 +0100 +@@ -55,6 +55,7 @@ + static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = { + PIX_FMT_DXVA2_VLD, + PIX_FMT_VAAPI_VLD, ++ PIX_FMT_XVBA_VLD, + PIX_FMT_YUVJ420P, + PIX_FMT_NONE + }; +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/Makefile xbmc-1fef727.patch/lib/ffmpeg/libavcodec/Makefile +--- xbmc-1fef727/lib/ffmpeg/libavcodec/Makefile 2012-02-07 12:46:59.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/Makefile 2012-02-07 14:30:17.996098134 +0100 +@@ -3,7 +3,7 @@ + NAME = avcodec + FFLIBS = avcore avutil + +-HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h ++HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h xvba.h + + OBJS = allcodecs.o \ + audioconvert.o \ +@@ -43,6 +43,7 @@ + OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes) + OBJS-$(CONFIG_VAAPI) += vaapi.o + OBJS-$(CONFIG_VDPAU) += vdpau.o ++OBJS-$(CONFIG_XVBA) += xvba.o + + # decoders/encoders/hardware accelerators + OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o +@@ -169,6 +170,7 @@ + mpegvideo.o error_resilience.o + OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o + OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o ++OBJS-$(CONFIG_H264_XVBA_HWACCEL) += xvba_h264.o + OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o + OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o + OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o +@@ -246,6 +248,7 @@ + mpegvideo.o error_resilience.o + OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o + OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o ++OBJS-$(CONFIG_MPEG2_XVBA_HWACCEL) += xvba_mpeg2.o + OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o \ + mpegvideo.o error_resilience.o + OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpegvideo_enc.o \ +@@ -379,6 +382,7 @@ + intrax8.o intrax8dsp.o + OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o + OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o ++OBJS-$(CONFIG_VC1_XVBA_HWACCEL) += xvba_vc1.o + OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o + OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o + OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o +@@ -647,6 +651,7 @@ + SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h + SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h + SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h ++SKIPHEADERS-$(CONFIG_XVBA) += xvba_internal.h + SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h + SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h + SKIPHEADERS += mpegaudio3.h +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/mpegvideo.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/mpegvideo.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/mpegvideo.c 2012-02-07 12:46:59.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/mpegvideo.c 2012-02-07 14:30:18.000098213 +0100 +@@ -117,6 +117,7 @@ + const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = { + PIX_FMT_DXVA2_VLD, + PIX_FMT_VAAPI_VLD, ++ PIX_FMT_XVBA_VLD, + PIX_FMT_YUV420P, + PIX_FMT_NONE + }; +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvba.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvba.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba.c 2012-02-07 14:30:18.001098232 +0100 +@@ -0,0 +1,65 @@ ++/* ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++ ++/** ++ * \addtogroup XVBA_Decoding ++ * ++ * @{ ++ */ ++ ++#include ++#include "xvba.h" ++#include "avcodec.h" ++ ++int ff_xvba_translate_profile(int profile) { ++ ++ if (profile == 66) ++ return 1; ++ else if (profile == 77) ++ return 2; ++ else if (profile == 100) ++ return 3; ++ else if (profile == 0) ++ return 4; ++ else if (profile == 1) ++ return 5; ++ else if (profile == 3) ++ return 6; ++ else ++ return -1; ++} ++ ++void ff_xvba_add_slice_data(struct xvba_render_state *render, const void *buffer, uint32_t size) { ++ ++ render->buffers = av_fast_realloc( ++ render->buffers, ++ &render->buffers_alllocated, ++ sizeof(struct xvba_bitstream_buffers)*(render->num_slices + 1) ++ ); ++ ++ render->buffers[render->num_slices].buffer = buffer; ++ render->buffers[render->num_slices].size = size; ++ ++ render->num_slices++; ++} ++ +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvba.h xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba.h +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvba.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba.h 2012-02-07 14:30:18.001098232 +0100 +@@ -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 -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_h264.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_h264.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_h264.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_h264.c 2012-02-07 14:30:18.002098252 +0100 +@@ -0,0 +1,180 @@ ++/* ++ * H.264 HW decode acceleration through XVBA ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "xvba.h" ++#include "xvba_internal.h" ++#include "h264.h" ++#include ++ ++/** @file ++ * This file implements the glue code between FFmpeg's and XvBA API's ++ * structures for H.264 decoding. ++ */ ++ ++ ++/** Initialize and start decoding a frame with XVBA. */ ++static int start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ H264Context * const h = avctx->priv_data; ++ MpegEncContext * const s = &h->s; ++ struct xvba_render_state *render; ++ XVBAPictureDescriptor *pic_descriptor; ++ int i; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0]; ++ assert(render); ++ ++ if (render->picture_descriptor == 0) ++ return -1; ++ ++ pic_descriptor = render->picture_descriptor; ++ ++ for (i = 0; i < 2; ++i) { ++ int foc = s->current_picture_ptr->field_poc[i]; ++ if (foc == INT_MAX) ++ foc = 0; ++ pic_descriptor->avc_curr_field_order_cnt_list[i] = foc; ++ } ++ ++ pic_descriptor->avc_frame_num = h->frame_num; ++ ++ render->num_slices = 0; ++ ++ return 0; ++} ++ ++/** End a hardware decoding based frame. */ ++static int end_frame(AVCodecContext *avctx) ++{ ++ H264Context * const h = avctx->priv_data; ++ MpegEncContext * const s = &h->s; ++ struct xvba_render_state *render; ++ XVBAPictureDescriptor *pic_descriptor; ++ XVBAQuantMatrixAvc *iq_matrix; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0]; ++ assert(render); ++ ++ if (render->picture_descriptor == 0 || render->iq_matrix == 0) ++ return -1; ++ ++ pic_descriptor = render->picture_descriptor; ++ iq_matrix = render->iq_matrix; ++ ++ av_dlog(avctx, "end_frame()\n"); ++ ++ /* Fill in Picture Parameters*/ ++ pic_descriptor->profile = ff_xvba_translate_profile(avctx->profile); ++ pic_descriptor->level = avctx->level; ++ pic_descriptor->width_in_mb = s->mb_width; ++ pic_descriptor->height_in_mb = s->mb_height; ++ pic_descriptor->picture_structure = s->picture_structure; ++ pic_descriptor->chroma_format = s->chroma_format ? s->chroma_format : 1; ++ pic_descriptor->avc_intra_flag = (h->slice_type == FF_I_TYPE) ? 1 : 0; ++ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0; ++ ++ pic_descriptor->avc_bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; ++ pic_descriptor->avc_bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; ++ pic_descriptor->avc_log2_max_frame_num_minus4 = h->sps.log2_max_frame_num -4; ++ pic_descriptor->avc_pic_order_cnt_type = h->sps.poc_type; ++ pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; ++ pic_descriptor->avc_num_ref_frames = h->sps.ref_frame_count; ++ pic_descriptor->avc_reserved_8bit = 0; ++ ++ pic_descriptor->avc_num_slice_groups_minus1 = h->pps.slice_group_count - 1; ++ pic_descriptor->avc_num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; ++ pic_descriptor->avc_num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; ++ ++ pic_descriptor->avc_pic_init_qp_minus26 = h->pps.init_qp - 26; ++ pic_descriptor->avc_pic_init_qs_minus26 = h->pps.init_qs - 26; ++ pic_descriptor->avc_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; ++ pic_descriptor->avc_second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; ++ pic_descriptor->avc_slice_group_change_rate_minus1 = 0; // not implemented in ffmpeg ++ pic_descriptor->avc_reserved_16bit = 0; // must be 0 ++ memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0 ++ memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0 ++ ++ // sps ++ pic_descriptor->sps_info.avc.delta_pic_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; ++ pic_descriptor->sps_info.avc.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; ++ pic_descriptor->sps_info.avc.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; ++ pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag; ++ pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag = h->sps.mb_aff; ++ pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag; ++ pic_descriptor->sps_info.avc.xvba_avc_sps_reserved = 0; ++ ++ // pps ++ pic_descriptor->pps_info.avc.entropy_coding_mode_flag = h->pps.cabac; ++ pic_descriptor->pps_info.avc.pic_order_present_flag = h->pps.pic_order_present; ++ pic_descriptor->pps_info.avc.weighted_pred_flag = h->pps.weighted_pred; ++ pic_descriptor->pps_info.avc.weighted_bipred_idc = h->pps.weighted_bipred_idc; ++ pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; ++ pic_descriptor->pps_info.avc.constrained_intra_pred_flag = h->pps.constrained_intra_pred; ++ pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; ++ pic_descriptor->pps_info.avc.transform_8x8_mode_flag = h->pps.transform_8x8_mode; ++ pic_descriptor->pps_info.avc.xvba_avc_pps_reserved = 0; // must be 0 ++ ++ memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4)); ++ memcpy(iq_matrix->bScalingLists8x8, h->pps.scaling_matrix8, sizeof(iq_matrix->bScalingLists8x8)); ++ ++ // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs ++ if (!h->got_first_iframe) { ++ if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE) ++ return -1; ++ h->got_first_iframe = 1; ++ } ++ ++ ff_draw_horiz_band(s, 0, s->avctx->height); ++ ++ return 0; ++} ++ ++/** Decode the given H.264 slice with VA API. */ ++static int decode_slice(AVCodecContext *avctx, ++ const uint8_t *buffer, ++ uint32_t size) ++{ ++ H264Context * const h = avctx->priv_data; ++ MpegEncContext * const s = &h->s; ++ struct xvba_render_state *render; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0]; ++ assert(render); ++ ++ ff_xvba_add_slice_data(render, buffer, size); ++ ++ return 0; ++} ++ ++AVHWAccel ff_h264_xvba_hwaccel = { ++ .name = "h264_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_H264, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .capabilities = 0, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++ .priv_data_size = 0, ++}; +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_internal.h xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_internal.h +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_internal.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_internal.h 2012-02-07 14:30:18.002098252 +0100 +@@ -0,0 +1,24 @@ ++/* ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++int ff_xvba_translate_profile(int profile); ++void ff_xvba_add_slice_data(struct xvba_render_state *render, const uint8_t *buffer, uint32_t size); +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_mpeg2.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_mpeg2.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_mpeg2.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_mpeg2.c 2012-02-07 14:30:18.003098272 +0100 +@@ -0,0 +1,52 @@ ++/* ++ * MPEG-2 HW decode acceleration through XVBA ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "dsputil.h" ++ ++static int start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) ++{ ++ struct MpegEncContext * const s = avctx->priv_data; ++ return 0; ++} ++ ++static int end_frame(AVCodecContext *avctx) ++{ ++ return 0; ++} ++ ++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ struct MpegEncContext * const s = avctx->priv_data; ++ return 0; ++} ++ ++AVHWAccel ff_mpeg2_xvba_hwaccel = { ++ .name = "mpeg2_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_MPEG2VIDEO, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .capabilities = 0, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++ .priv_data_size = 0, ++}; +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_vc1.c xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_vc1.c +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvba_vc1.c 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvba_vc1.c 2012-02-07 14:30:18.003098272 +0100 +@@ -0,0 +1,194 @@ ++/* ++ * VC-1 HW decode acceleration through XVBA ++ * ++ * Copyright (C) 2005-2011 Team XBMC ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include "xvba.h" ++#include "xvba_internal.h" ++#include "vc1.h" ++#include "vc1data.h" ++#include ++ ++ ++/** @file ++ * Implement structures of ffmpeg <-> XvBA ++ */ ++ ++/* Initialize and start decoding a frame with XvBA */ ++static int start_frame(AVCodecContext *avctx, ++ av_unused const uint8_t *buffer, ++ av_unused uint32_t size) ++{ ++ VC1Context * const v = avctx->priv_data; ++ MpegEncContext * const s = &v->s; ++ struct xvba_render_state *render; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0]; ++ assert(render); ++ ++ render->num_slices = 0; ++ return 0; ++} ++ ++/* End a hardware decoding based frame */ ++static int end_frame(AVCodecContext *avctx) ++{ ++ VC1Context* const v = avctx->priv_data; ++ MpegEncContext* const s = &v->s; ++ struct xvba_render_state *render, *last, *next; ++ XVBAPictureDescriptor *pic_descriptor; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0]; ++ assert(render); ++ ++ if (render->picture_descriptor == 0) ++ return -1; ++ ++ pic_descriptor = render->picture_descriptor; ++ ++ av_dlog(avctx, "xvba_vc1_end_frame()\n"); ++ ++ memset(pic_descriptor, 0, sizeof(*pic_descriptor)); ++ ++ /* Fill in Parameters - for reference see AMD sdk documentation */ ++ pic_descriptor->profile = ff_xvba_translate_profile(v->profile); ++ pic_descriptor->level = v->level; ++ //done like in va-driver and vaapi ++ if (v->profile == PROFILE_ADVANCED) { ++ pic_descriptor->width_in_mb = s->avctx->coded_width; ++ pic_descriptor->height_in_mb = s->avctx->coded_height; ++ } else { ++ pic_descriptor->width_in_mb = s->mb_width; ++ pic_descriptor->height_in_mb = s->mb_height; ++ } ++ pic_descriptor->picture_structure = s->picture_structure; ++ // xvba-video set this to 1 only 4:2:0 supported ++ // doc says: if not set, choose 1 - we try this ++ pic_descriptor->chroma_format = 1; ++ pic_descriptor->avc_intra_flag = s->pict_type == FF_I_TYPE || v->bi_type == 1; ++ pic_descriptor->avc_reference = (s->current_picture_ptr->reference & 3) ? 1 : 0; ++ ++ // VC-1 explicit parameters see page 30 of sdk ++ // sps_info ++ pic_descriptor->sps_info.vc1.postprocflag = v->postprocflag; ++ ++ // done as in vaapi ++ pic_descriptor->sps_info.vc1.pulldown = v->broadcast; ++ pic_descriptor->sps_info.vc1.interlace = v->interlace; ++ pic_descriptor->sps_info.vc1.tfcntrflag = v->tfcntrflag; ++ pic_descriptor->sps_info.vc1.finterpflag = v->finterpflag; ++ pic_descriptor->sps_info.vc1.reserved = 1; ++ // eventually check if this makes sense together with interlace ++ pic_descriptor->sps_info.vc1.psf = v->psf; ++ // what about if it is a frame (page 31) ++ // looked at xvba-driver ++ pic_descriptor->sps_info.vc1.second_field = !s->first_field; ++ pic_descriptor->sps_info.vc1.xvba_vc1_sps_reserved = 0; ++ ++ // VC-1 explicit parameters see page 30 of sdk ++ // pps_info ++ pic_descriptor->pps_info.vc1.panscan_flag = v->panscanflag; ++ pic_descriptor->pps_info.vc1.refdist_flag = v->refdist_flag; ++ pic_descriptor->pps_info.vc1.loopfilter = s->loop_filter; ++ pic_descriptor->pps_info.vc1.fastuvmc = v->fastuvmc; ++ pic_descriptor->pps_info.vc1.extended_mv = v->extended_mv; ++ pic_descriptor->pps_info.vc1.dquant = v->dquant; ++ pic_descriptor->pps_info.vc1.vstransform = v->vstransform; ++ pic_descriptor->pps_info.vc1.overlap = v->overlap; ++ pic_descriptor->pps_info.vc1.quantizer = v->quantizer_mode; ++ pic_descriptor->pps_info.vc1.extended_dmv = v->extended_dmv; ++ pic_descriptor->pps_info.vc1.maxbframes = s->avctx->max_b_frames; ++ pic_descriptor->pps_info.vc1.rangered = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : v->rangered; ++ pic_descriptor->pps_info.vc1.syncmarker = (pic_descriptor->profile == PROFILE_SIMPLE) ? 0 : s->resync_marker; ++ pic_descriptor->pps_info.vc1.multires = v->multires; ++ pic_descriptor->pps_info.vc1.reserved = 1; ++ pic_descriptor->pps_info.vc1.range_mapy_flag = v->range_mapy_flag; ++ pic_descriptor->pps_info.vc1.range_mapy = v->range_mapy; ++ pic_descriptor->pps_info.vc1.range_mapuv_flag = v->range_mapuv_flag; ++ pic_descriptor->pps_info.vc1.range_mapuv = v->range_mapuv; ++ pic_descriptor->pps_info.vc1.xvba_vc1_pps_reserved = 0; ++ ++ pic_descriptor->past_surface = 0; ++ pic_descriptor->future_surface = 0; ++ switch (s->pict_type) { ++ case FF_B_TYPE: ++ next = (struct xvba_render_state *)s->next_picture.data[0]; ++ assert(next); ++ if (next) ++ pic_descriptor->past_surface = next->surface; ++ // fall-through ++ case FF_P_TYPE: ++ last = (struct xvba_render_state *)s->last_picture.data[0]; ++ assert(last); ++ if (last) ++ pic_descriptor->future_surface = last->surface; ++ break; ++ } ++ ++ ff_draw_horiz_band(s, 0, s->avctx->height); ++ ++ return 0; ++} ++ ++static int decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) ++{ ++ VC1Context* const v = avctx->priv_data; ++ MpegEncContext* const s = &v->s; ++ struct xvba_render_state *render; ++ ++ render = (struct xvba_render_state *)s->current_picture_ptr->data[0]; ++ assert(render); ++ ++ if (avctx->codec_id == CODEC_ID_VC1 && ++ size >= 4 && IS_MARKER(AV_RB32(buffer))) { ++ buffer += 4; ++ size -= 4; ++ } ++ ++ ff_xvba_add_slice_data(render, buffer, size); ++ ++ return 0; ++} ++ ++#if CONFIG_WMV3_XVBA_HWACCEL ++AVHWAccel ff_wmv3_xvba_hwaccel = { ++ .name = "wmv3_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_WMV3, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .capabilities = 0, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++ .priv_data_size = 0, ++}; ++#endif ++ ++AVHWAccel ff_vc1_xvba_hwaccel = { ++ .name = "vc1_xvba", ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = CODEC_ID_VC1, ++ .pix_fmt = PIX_FMT_XVBA_VLD, ++ .capabilities = 0, ++ .start_frame = start_frame, ++ .end_frame = end_frame, ++ .decode_slice = decode_slice, ++ .priv_data_size = 0, ++}; +diff -Naur xbmc-1fef727/lib/ffmpeg/libavcodec/xvmc_internal.h xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvmc_internal.h +--- xbmc-1fef727/lib/ffmpeg/libavcodec/xvmc_internal.h 2012-02-07 12:47:01.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavcodec/xvmc_internal.h 2012-02-07 14:30:18.004098292 +0100 +@@ -1,5 +1,7 @@ + /* +- * XVideo Motion Compensation internal functions ++ * HW decode acceleration for MPEG-2, H.264 and VC-1 ++ * ++ * Copyright (C) 2005-2011 Team XBMC + * + * This file is part of FFmpeg. + * +diff -Naur xbmc-1fef727/lib/ffmpeg/libavutil/pixdesc.c xbmc-1fef727.patch/lib/ffmpeg/libavutil/pixdesc.c +--- xbmc-1fef727/lib/ffmpeg/libavutil/pixdesc.c 2012-02-07 12:46:58.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavutil/pixdesc.c 2012-02-07 14:30:18.005098312 +0100 +@@ -717,6 +717,12 @@ + .log2_chroma_h = 1, + .flags = PIX_FMT_HWACCEL, + }, ++ [PIX_FMT_XVBA_VLD] = { ++ .name = "xvba_vld", ++ .log2_chroma_w = 1, ++ .log2_chroma_h = 1, ++ .flags = PIX_FMT_HWACCEL, ++ }, + [PIX_FMT_YUV420P16LE] = { + .name = "yuv420p16le", + .nb_components= 3, +diff -Naur xbmc-1fef727/lib/ffmpeg/libavutil/pixfmt.h xbmc-1fef727.patch/lib/ffmpeg/libavutil/pixfmt.h +--- xbmc-1fef727/lib/ffmpeg/libavutil/pixfmt.h 2012-02-07 12:46:58.000000000 +0100 ++++ xbmc-1fef727.patch/lib/ffmpeg/libavutil/pixfmt.h 2012-02-07 14:30:18.005098312 +0100 +@@ -127,6 +127,7 @@ + PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer ++ PIX_FMT_XVBA_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers + + PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 + PIX_FMT_RGB444LE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), little-endian, most significant bits to 0 +diff -Naur xbmc-1fef727/lib/UnrarXLib/extract.cpp xbmc-1fef727.patch/lib/UnrarXLib/extract.cpp +--- xbmc-1fef727/lib/UnrarXLib/extract.cpp 2012-02-07 12:46:53.000000000 +0100 ++++ xbmc-1fef727.patch/lib/UnrarXLib/extract.cpp 2012-02-07 14:30:17.982097858 +0100 +@@ -1,9 +1,5 @@ + #include "rar.hpp" + #include "Util.h" +-#ifdef _LINUX +-#include "XSyncUtils.h" +-#include "XEventUtils.h" +-#endif + + // a cautious wrapper around strncpy + char *strncpy_null_terminated(char *dest, const char *src, size_t n) +diff -Naur xbmc-1fef727/lib/UnrarXLib/unpack15.cpp xbmc-1fef727.patch/lib/UnrarXLib/unpack15.cpp +--- xbmc-1fef727/lib/UnrarXLib/unpack15.cpp 2012-02-07 12:46:53.000000000 +0100 ++++ xbmc-1fef727.patch/lib/UnrarXLib/unpack15.cpp 2012-02-07 14:30:17.992098054 +0100 +@@ -1,7 +1,3 @@ +-#ifdef _LINUX +-#include "XSyncUtils.h" +-#endif +- + #define STARTL1 2 + static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00, + 0xee00,0xf000,0xf200,0xf200,0xffff}; +diff -Naur xbmc-1fef727/lib/UnrarXLib/unpack.cpp xbmc-1fef727.patch/lib/UnrarXLib/unpack.cpp +--- xbmc-1fef727/lib/UnrarXLib/unpack.cpp 2012-02-07 12:46:53.000000000 +0100 ++++ xbmc-1fef727.patch/lib/UnrarXLib/unpack.cpp 2012-02-07 14:30:17.991098035 +0100 +@@ -8,11 +8,6 @@ + #include "unpack20.cpp" + #endif + +-#ifdef _LINUX +-#include "XSyncUtils.h" +-#include "XEventUtils.h" +-#endif +- + Unpack::Unpack(ComprDataIO *DataIO) + { + UnpIO=DataIO; +diff -Naur xbmc-1fef727/xbmc/ApplicationMessenger.cpp xbmc-1fef727.patch/xbmc/ApplicationMessenger.cpp +--- xbmc-1fef727/xbmc/ApplicationMessenger.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/ApplicationMessenger.cpp 2012-02-07 14:30:18.007098350 +0100 +@@ -73,7 +73,7 @@ + + using namespace std; + +-CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) ++CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("CDelayedMessage") + { + m_msg.dwMessage = msg.dwMessage; + m_msg.dwParam1 = msg.dwParam1; +diff -Naur xbmc-1fef727/xbmc/cdrip/CDDAReader.cpp xbmc-1fef727.patch/xbmc/cdrip/CDDAReader.cpp +--- xbmc-1fef727/xbmc/cdrip/CDDAReader.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cdrip/CDDAReader.cpp 2012-02-07 14:30:18.007098350 +0100 +@@ -29,7 +29,7 @@ + + #define SECTOR_COUNT 52 + +-CCDDAReader::CCDDAReader() ++CCDDAReader::CCDDAReader() : CThread("CCDDAReader") + { + m_sRipBuffer[0].pbtStream = NULL; + m_sRipBuffer[1].pbtStream = NULL; +diff -Naur xbmc-1fef727/xbmc/cores/DllLoader/exports/emu_kernel32.cpp xbmc-1fef727.patch/xbmc/cores/DllLoader/exports/emu_kernel32.cpp +--- xbmc-1fef727/xbmc/cores/DllLoader/exports/emu_kernel32.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/DllLoader/exports/emu_kernel32.cpp 2012-02-07 14:30:18.008098370 +0100 +@@ -240,15 +240,6 @@ + #endif + } + +-extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime) +-{ +- // since the xbox has only one process, we just take the current thread +- HANDLE h = GetCurrentThread(); +- BOOL res = GetThreadTimes(h, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); +- +- return res; +-} +- + extern "C" int WINAPI dllDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process + HANDLE hSourceHandle, // handle to duplicate + HANDLE hTargetProcessHandle, // handle to target process +diff -Naur xbmc-1fef727/xbmc/cores/DllLoader/exports/emu_kernel32.h xbmc-1fef727.patch/xbmc/cores/DllLoader/exports/emu_kernel32.h +--- xbmc-1fef727/xbmc/cores/DllLoader/exports/emu_kernel32.h 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/DllLoader/exports/emu_kernel32.h 2012-02-07 14:30:18.009098390 +0100 +@@ -686,7 +686,6 @@ + + extern "C" HGLOBAL WINAPI dllLoadResource(HMODULE module, HRSRC res); + extern "C" HRSRC WINAPI dllFindResourceA(HMODULE module, LPCTSTR name, LPCTSTR type); +-extern "C" BOOL WINAPI dllGetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); + extern "C" int WINAPI dllGetLocaleInfoA(LCID Locale, LCTYPE LCType, LPTSTR lpLCData, int cchData); + extern "C" UINT WINAPI dllGetConsoleCP(); + extern "C" UINT WINAPI dllGetConsoleOutputCP(); +diff -Naur xbmc-1fef727/xbmc/cores/DummyVideoPlayer.cpp xbmc-1fef727.patch/xbmc/cores/DummyVideoPlayer.cpp +--- xbmc-1fef727/xbmc/cores/DummyVideoPlayer.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/DummyVideoPlayer.cpp 2012-02-07 14:30:18.009098390 +0100 +@@ -33,7 +33,7 @@ + + CDummyVideoPlayer::CDummyVideoPlayer(IPlayerCallback& callback) + : IPlayer(callback), +- CThread() ++ CThread("CDummyVideoPlayer") + { + m_paused = false; + m_clock = 0; +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp 2012-02-07 14:30:18.016098528 +0100 +@@ -323,7 +323,7 @@ + #pragma mark - + #endif + CMPCOutputThread::CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015) : +- CThread(), ++ CThread("CMPCOutputThread"), + m_dll(dll), + m_device(device), + m_has_bcm70015(has_bcm70015), +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp 2012-02-07 14:30:18.018098568 +0100 +@@ -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 @@ + dec->Release(); + } + #endif ++#ifdef HAVE_LIBXVBA ++ if(*cur == PIX_FMT_XVBA_VLD && g_guiSettings.GetBool("videoplayer.usexvba")) ++ { ++ if(ctx->GetHardware()) ++ return *cur; ++ ++ XVBA::CDecoder* dec = new XVBA::CDecoder(); ++ if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount)) ++ { ++ ctx->SetHardware(dec); ++ return *cur; ++ } ++ else ++ dec->Release(); ++ } ++#endif + #ifdef HAVE_LIBVA + // mpeg4 vaapi decoding is disabled + if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi") +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2012-02-07 14:30:18.017098548 +0100 +@@ -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 { + VAAPI::CHolder* vaapi; + }; ++ struct { ++ XVBA::CDecoder* xvba; ++ }; + + struct { + COpenMax *openMax; +@@ -109,6 +113,8 @@ + FMT_VAAPI, + FMT_OMXEGL, + FMT_CVBREF, ++ FMT_XVBA, ++ FMT_XVBA_YV12, + } format; + }; + +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2012-02-07 14:30:18.018098568 +0100 +@@ -17,6 +17,10 @@ + DVDVideoCodecCrystalHD.cpp \ + + endif ++ifeq (@USE_XVBA@,1) ++SRCS+= XVBA.cpp \ ++ ++endif + ifeq (@USE_VDA@,1) + SRCS+= DVDVideoCodecVDA.cpp \ + +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.cpp 2012-02-07 14:30:18.021098627 +0100 +@@ -0,0 +1,1401 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include "system.h" ++#ifdef HAVE_LIBXVBA ++#include ++#include ++#include "XVBA.h" ++#include "windowing/WindowingFactory.h" ++#include "guilib/GraphicContext.h" ++#include "settings/GUISettings.h" ++#include "utils/TimeUtils.h" ++ ++using namespace XVBA; ++ ++// XVBA interface ++ ++#define XVBA_LIBRARY "libXvBAW.so.1" ++ ++typedef Bool (*XVBAQueryExtensionProc) (Display *dpy, int *vers); ++typedef Status (*XVBACreateContextProc) (void *input, void *output); ++typedef Status (*XVBADestroyContextProc) (void *context); ++typedef Bool (*XVBAGetSessionInfoProc) (void *input, void *output); ++typedef Status (*XVBACreateSurfaceProc) (void *input, void *output); ++typedef Status (*XVBACreateGLSharedSurfaceProc)(void *input, void *output); ++typedef Status (*XVBADestroySurfaceProc) (void *surface); ++typedef Status (*XVBACreateDecodeBuffersProc) (void *input, void *output); ++typedef Status (*XVBADestroyDecodeBuffersProc) (void *input); ++typedef Status (*XVBAGetCapDecodeProc) (void *input, void *output); ++typedef Status (*XVBACreateDecodeProc) (void *input, void *output); ++typedef Status (*XVBADestroyDecodeProc) (void *session); ++typedef Status (*XVBAStartDecodePictureProc) (void *input); ++typedef Status (*XVBADecodePictureProc) (void *input); ++typedef Status (*XVBAEndDecodePictureProc) (void *input); ++typedef Status (*XVBASyncSurfaceProc) (void *input, void *output); ++typedef Status (*XVBAGetSurfaceProc) (void *input); ++typedef Status (*XVBATransferSurfaceProc) (void *input); ++ ++static struct ++{ ++ XVBAQueryExtensionProc QueryExtension; ++ XVBACreateContextProc CreateContext; ++ XVBADestroyContextProc DestroyContext; ++ XVBAGetSessionInfoProc GetSessionInfo; ++ XVBACreateSurfaceProc CreateSurface; ++ XVBACreateGLSharedSurfaceProc CreateGLSharedSurface; ++ XVBADestroySurfaceProc DestroySurface; ++ XVBACreateDecodeBuffersProc CreateDecodeBuffers; ++ XVBADestroyDecodeBuffersProc DestroyDecodeBuffers; ++ XVBAGetCapDecodeProc GetCapDecode; ++ XVBACreateDecodeProc CreateDecode; ++ XVBADestroyDecodeProc DestroyDecode; ++ XVBAStartDecodePictureProc StartDecodePicture; ++ XVBADecodePictureProc DecodePicture; ++ XVBAEndDecodePictureProc EndDecodePicture; ++ XVBASyncSurfaceProc SyncSurface; ++ XVBAGetSurfaceProc GetSurface; ++ XVBATransferSurfaceProc TransferSurface; ++}g_XVBA_vtable; ++ ++//----------------------------------------------------------------------------- ++//----------------------------------------------------------------------------- ++ ++CXVBAContext *CXVBAContext::m_context = 0; ++CCriticalSection CXVBAContext::m_section; ++Display *CXVBAContext::m_display = 0; ++ ++CXVBAContext::CXVBAContext() ++{ ++ m_context = 0; ++ m_dlHandle = 0; ++ m_xvbaContext = 0; ++ m_refCount = 0; ++} ++ ++void CXVBAContext::Release() ++{ ++ CSingleLock lock(m_section); ++ ++ m_refCount--; ++ if (m_refCount <= 0) ++ { ++ Close(); ++ delete this; ++ m_context = 0; ++ } ++} ++ ++void CXVBAContext::Close() ++{ ++ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder context"); ++ ++ DestroyContext(); ++ if (m_dlHandle) ++ { ++ dlclose(m_dlHandle); ++ m_dlHandle = 0; ++ } ++} ++ ++bool CXVBAContext::EnsureContext(CXVBAContext **ctx) ++{ ++ CSingleLock lock(m_section); ++ ++ if (m_context) ++ { ++ m_context->m_refCount++; ++ *ctx = m_context; ++ return true; ++ } ++ ++ m_context = new CXVBAContext(); ++ *ctx = m_context; ++ { ++ CSingleLock gLock(g_graphicsContext); ++ if (!m_context->LoadSymbols() || !m_context->CreateContext()) ++ { ++ delete m_context; ++ m_context = 0; ++ return false; ++ } ++ } ++ ++ m_context->m_refCount++; ++ ++ *ctx = m_context; ++ return true; ++} ++ ++bool CXVBAContext::LoadSymbols() ++{ ++ if (!m_dlHandle) ++ { ++ m_dlHandle = dlopen(XVBA_LIBRARY, RTLD_LAZY); ++ if (!m_dlHandle) ++ { ++ const char* error = dlerror(); ++ if (!error) ++ error = "dlerror() returned NULL"; ++ ++ CLog::Log(LOGERROR,"XVBA::LoadSymbols: Unable to get handle to lib: %s", error); ++ return false; ++ } ++ } ++ else ++ return true; ++ ++#define INIT_PROC(PREFIX, PROC) do { \ ++ g_##PREFIX##_vtable.PROC = (PREFIX##PROC##Proc) \ ++ dlsym(m_dlHandle, #PREFIX #PROC); \ ++ } while (0) ++ ++#define INIT_PROC_CHECK(PREFIX, PROC) do { \ ++ dlerror(); \ ++ INIT_PROC(PREFIX, PROC); \ ++ if (dlerror()) { \ ++ dlclose(m_dlHandle); \ ++ m_dlHandle = NULL; \ ++ return false; \ ++ } \ ++ } while (0) ++ ++#define XVBA_INIT_PROC(PROC) INIT_PROC_CHECK(XVBA, PROC) ++ ++ XVBA_INIT_PROC(QueryExtension); ++ XVBA_INIT_PROC(CreateContext); ++ XVBA_INIT_PROC(DestroyContext); ++ XVBA_INIT_PROC(GetSessionInfo); ++ XVBA_INIT_PROC(CreateSurface); ++ XVBA_INIT_PROC(CreateGLSharedSurface); ++ XVBA_INIT_PROC(DestroySurface); ++ XVBA_INIT_PROC(CreateDecodeBuffers); ++ XVBA_INIT_PROC(DestroyDecodeBuffers); ++ XVBA_INIT_PROC(GetCapDecode); ++ XVBA_INIT_PROC(CreateDecode); ++ XVBA_INIT_PROC(DestroyDecode); ++ XVBA_INIT_PROC(StartDecodePicture); ++ XVBA_INIT_PROC(DecodePicture); ++ XVBA_INIT_PROC(EndDecodePicture); ++ XVBA_INIT_PROC(SyncSurface); ++ XVBA_INIT_PROC(GetSurface); ++ XVBA_INIT_PROC(TransferSurface); ++ ++#undef XVBA_INIT_PROC ++#undef INIT_PROC ++ ++ return true; ++} ++ ++bool CXVBAContext::CreateContext() ++{ ++ if (m_xvbaContext) ++ return true; ++ ++ CLog::Log(LOGNOTICE,"XVBA::CreateContext - creating decoder context"); ++ ++ Drawable window; ++ { CSingleLock lock(g_graphicsContext); ++ if (!m_display) ++ m_display = XOpenDisplay(NULL); ++ window = 0; ++ } ++ ++ int version; ++ if (!g_XVBA_vtable.QueryExtension(m_display, &version)) ++ return false; ++ CLog::Log(LOGNOTICE,"XVBA::CreateContext - opening xvba version: %i", version); ++ ++ // create XVBA Context ++ XVBA_Create_Context_Input contextInput; ++ XVBA_Create_Context_Output contextOutput; ++ contextInput.size = sizeof(contextInput); ++ contextInput.display = m_display; ++ contextInput.draw = window; ++ contextOutput.size = sizeof(contextOutput); ++ if(Success != g_XVBA_vtable.CreateContext(&contextInput, &contextOutput)) ++ { ++ CLog::Log(LOGERROR,"XVBA::CreateContext - failed to create context"); ++ return false; ++ } ++ m_xvbaContext = contextOutput.context; ++ ++ return true; ++} ++ ++void CXVBAContext::DestroyContext() ++{ ++ if (!m_xvbaContext) ++ return; ++ ++ g_XVBA_vtable.DestroyContext(m_xvbaContext); ++ m_xvbaContext = 0; ++// XCloseDisplay(m_display); ++} ++ ++void *CXVBAContext::GetContext() ++{ ++ return m_xvbaContext; ++} ++ ++//----------------------------------------------------------------------------- ++//----------------------------------------------------------------------------- ++ ++static unsigned int decoderId = 0; ++ ++CDecoder::CDecoder() ++{ ++ m_context = 0; ++ m_xvbaSession = 0; ++ m_flipBuffer = 0; ++} ++ ++CDecoder::~CDecoder() ++{ ++ Close(); ++} ++ ++typedef struct { ++ unsigned int size; ++ unsigned int num_of_decodecaps; ++ XVBADecodeCap decode_caps_list[]; ++} XVBA_GetCapDecode_Output_Base; ++ ++void CDecoder::OnLostDevice() ++{ ++ CLog::Log(LOGNOTICE,"XVBA::OnLostDevice event"); ++ ++ CExclusiveLock lock(m_decoderSection); ++ DestroySession(); ++ if (m_context) ++ m_context->Release(); ++ m_context = 0; ++ ++ m_displayState = XVBA_LOST; ++ m_displayEvent.Reset(); ++} ++ ++void CDecoder::OnResetDevice() ++{ ++ CLog::Log(LOGNOTICE,"XVBA::OnResetDevice event"); ++ ++ CExclusiveLock lock(m_displaySection); ++ if (m_displayState == XVBA_LOST) ++ { ++ m_displayState = XVBA_RESET; ++ m_displayEvent.Set(); ++ } ++} ++ ++bool CDecoder::Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces) ++{ ++ std::string Vendor = g_Windowing.GetRenderVendor(); ++ std::transform(Vendor.begin(), Vendor.end(), Vendor.begin(), ::tolower); ++ if (Vendor.compare(0, 3, "ati") != 0) ++ { ++ return false; ++ } ++ ++ m_decoderId = decoderId++; ++ ++ CLog::Log(LOGNOTICE,"(XVBA::Open) opening xvba decoder, id: %d", m_decoderId); ++ ++ if(avctx->coded_width == 0 ++ || avctx->coded_height == 0) ++ { ++ CLog::Log(LOGWARNING,"(XVBA) no width/height available, can't init"); ++ return false; ++ } ++ ++ if (!m_dllAvUtil.Load()) ++ return false; ++ ++ if (!CXVBAContext::EnsureContext(&m_context)) ++ return false; ++ ++ // xvba get session info ++ XVBA_GetSessionInfo_Input sessionInput; ++ XVBA_GetSessionInfo_Output sessionOutput; ++ sessionInput.size = sizeof(sessionInput); ++ sessionInput.context = m_context->GetContext(); ++ sessionOutput.size = sizeof(sessionOutput); ++ if (Success != g_XVBA_vtable.GetSessionInfo(&sessionInput, &sessionOutput)) ++ { ++ CLog::Log(LOGERROR,"(XVBA) can't get session info"); ++ return false; ++ } ++ if (sessionOutput.getcapdecode_output_size == 0) ++ { ++ CLog::Log(LOGERROR,"(XVBA) session decode not supported"); ++ return false; ++ } ++ ++ // get decoder capabilities ++ XVBA_GetCapDecode_Input capInput; ++ XVBA_GetCapDecode_Output *capOutput; ++ capInput.size = sizeof(capInput); ++ capInput.context = m_context->GetContext(); ++ capOutput = (XVBA_GetCapDecode_Output *)calloc(sessionOutput.getcapdecode_output_size, 1); ++ capOutput->size = sessionOutput.getcapdecode_output_size; ++ if (Success != g_XVBA_vtable.GetCapDecode(&capInput, capOutput)) ++ { ++ CLog::Log(LOGERROR,"(XVBA) can't get decode capabilities"); ++ return false; ++ } ++ ++ int match = -1; ++ if (avctx->codec_id == CODEC_ID_H264) ++ { ++ // search for profile high ++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i) ++ { ++ if (capOutput->decode_caps_list[i].capability_id == XVBA_H264 && ++ capOutput->decode_caps_list[i].flags == XVBA_H264_HIGH) ++ { ++ match = (int) i; ++ break; ++ } ++ } ++ if (match < 0) ++ { ++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_H264_HIGH not found"); ++ } ++ } ++ else if (avctx->codec_id == CODEC_ID_VC1) ++ { ++ // search for profile advanced ++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i) ++ { ++ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 && ++ capOutput->decode_caps_list[i].flags == XVBA_VC1_ADVANCED) ++ { ++ match = (int) i; ++ break; ++ } ++ } ++ if (match < 0) ++ { ++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_ADVANCED not found"); ++ } ++ } ++ else if (avctx->codec_id == CODEC_ID_MPEG2VIDEO) ++ { ++ // search for profile high ++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i) ++ { ++ if (capOutput->decode_caps_list[i].capability_id == XVBA_MPEG2_VLD) ++ { ++ // XXX: uncomment when implemented ++ // match = (int) i; ++ // break; ++ } ++ } ++ if (match < 0) ++ { ++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_MPEG2_VLD not found"); ++ } ++ } ++ else if (avctx->codec_id == CODEC_ID_WMV3) ++ { ++ // search for profile high ++ for (unsigned int i = 0; i < capOutput->num_of_decodecaps; ++i) ++ { ++ if (capOutput->decode_caps_list[i].capability_id == XVBA_VC1 && ++ capOutput->decode_caps_list[i].flags == XVBA_VC1_MAIN) ++ { ++ match = (int) i; ++ break; ++ } ++ } ++ if (match < 0) ++ { ++ CLog::Log(LOGNOTICE, "(XVBA::Open) - profile XVBA_VC1_MAIN not found"); ++ } ++ } ++ ++ if (match < 0) ++ { ++ free(capOutput); ++ return false; ++ } ++ ++ CLog::Log(LOGNOTICE,"(XVBA) using decoder capability id: %i flags: %i", ++ capOutput->decode_caps_list[match].capability_id, ++ capOutput->decode_caps_list[match].flags); ++ CLog::Log(LOGNOTICE,"(XVBA) using surface type: %x", ++ capOutput->decode_caps_list[match].surface_type); ++ ++ m_decoderCap = capOutput->decode_caps_list[match]; ++ ++ free(capOutput); ++ ++ // set some varables ++ m_xvbaSession = 0; ++ m_xvbaBufferPool.data_buffer = 0; ++ m_xvbaBufferPool.iq_matrix_buffer = 0; ++ m_xvbaBufferPool.picture_descriptor_buffer = 0; ++ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64; ++ m_surfaceWidth = 0; ++ m_surfaceHeight = 0; ++ m_presentPicture = 0; ++ m_numRenderBuffers = surfaces; ++ m_flipBuffer = new RenderPicture[m_numRenderBuffers]; ++ for (unsigned int i = 0; i < m_numRenderBuffers; ++i) ++ { ++ m_flipBuffer[i].outPic = 0; ++ m_flipBuffer[i].glSurface[0] = ++ m_flipBuffer[i].glSurface[1] = ++ m_flipBuffer[i].glSurface[2] = 0; ++ m_flipBuffer[i].glTexture[0] = ++ m_flipBuffer[i].glTexture[1] = ++ m_flipBuffer[i].glTexture[2] = 0; ++ } ++ for (unsigned int j = 0; j < NUM_OUTPUT_PICS; ++j) ++ m_freeOutPic.push_back(&m_allOutPic[j]); ++ m_displayState = XVBA_OPEN; ++ ++ // setup ffmpeg ++ avctx->thread_count = 1; ++ avctx->get_buffer = CDecoder::FFGetBuffer; ++ avctx->release_buffer = CDecoder::FFReleaseBuffer; ++ avctx->draw_horiz_band = CDecoder::FFDrawSlice; ++ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; ++ ++ g_Windowing.Register(this); ++ return true; ++} ++ ++void CDecoder::Close() ++{ ++ CLog::Log(LOGNOTICE, "XVBA::Close - closing decoder, id: %d", m_decoderId); ++ ++ if (!m_context) ++ return; ++ ++ FinishGL(); ++ ++ DestroySession(); ++ if (m_context) ++ m_context->Release(); ++ m_context = 0; ++ ++ while (!m_videoSurfaces.empty()) ++ { ++ xvba_render_state *render = m_videoSurfaces.back(); ++ if(render->buffers_alllocated > 0) ++ m_dllAvUtil.av_free(render->buffers); ++ m_videoSurfaces.pop_back(); ++ free(render); ++ } ++ ++ if (m_flipBuffer) ++ delete [] m_flipBuffer; ++ ++ g_Windowing.Unregister(this); ++ m_dllAvUtil.Unload(); ++} ++ ++void CDecoder::ResetState() ++{ ++ picAge.b_age = picAge.ip_age[0] = picAge.ip_age[1] = 256*256*256*64; ++ m_presentPicture = 0; ++ m_freeOutPic.clear(); ++ m_usedOutPic.clear(); ++ for (int j = 0; j < NUM_OUTPUT_PICS; ++j) ++ m_freeOutPic.push_back(&m_allOutPic[j]); ++ m_displayState = XVBA_OPEN; ++} ++ ++int CDecoder::Check(AVCodecContext* avctx) ++{ ++ EDisplayState state; ++ ++ { CSharedLock lock(m_displaySection); ++ state = m_displayState; ++ } ++ ++ if (state == XVBA_LOST) ++ { ++ CLog::Log(LOGNOTICE,"XVBA::Check waiting for display reset event"); ++ if (!m_displayEvent.WaitMSec(2000)) ++ { ++ CLog::Log(LOGERROR, "XVBA::Check - device didn't reset in reasonable time"); ++ return VC_ERROR; ++ } ++ { CSharedLock lock(m_displaySection); ++ state = m_displayState; ++ } ++ } ++ if (state == XVBA_RESET || state == XVBA_ERROR) ++ { ++ CLog::Log(LOGNOTICE,"XVBA::Check - Attempting recovery"); ++ ++ CSingleLock gLock(g_graphicsContext); ++ CExclusiveLock lock(m_decoderSection); ++ ++ DestroySession(); ++ ResetState(); ++ CXVBAContext::EnsureContext(&m_context); ++ ++ if (state == XVBA_RESET) ++ return VC_FLUSHED; ++ else ++ return VC_ERROR; ++ } ++ return 0; ++} ++ ++void CDecoder::SetError(const char* function, const char* msg, int line) ++{ ++ CLog::Log(LOGERROR, "XVBA::%s - %s, line %d", function, msg, line); ++ CExclusiveLock lock(m_displaySection); ++ m_displayState = XVBA_ERROR; ++} ++ ++bool CDecoder::CreateSession(AVCodecContext* avctx) ++{ ++ m_surfaceWidth = (avctx->coded_width+15) & ~15; ++ m_surfaceHeight = (avctx->coded_height+15) & ~15; ++ ++ m_vidWidth = avctx->width; ++ m_vidHeight = avctx->height; ++ ++ XVBA_Create_Decode_Session_Input sessionInput; ++ XVBA_Create_Decode_Session_Output sessionOutput; ++ ++ sessionInput.size = sizeof(sessionInput); ++ sessionInput.width = m_surfaceWidth; ++ sessionInput.height = m_surfaceHeight; ++ sessionInput.context = m_context->GetContext(); ++ sessionInput.decode_cap = &m_decoderCap; ++ sessionOutput.size = sizeof(sessionOutput); ++ ++ if (Success != g_XVBA_vtable.CreateDecode(&sessionInput, &sessionOutput)) ++ { ++ SetError(__FUNCTION__, "failed to create decoder session", __LINE__); ++ CLog::Log(LOGERROR, "Decoder failed with following stats: m_surfaceWidth %u, m_surfaceHeight %u," ++ " m_vidWidth %u, m_vidHeight %u, coded_width %d, coded_height %d", ++ m_surfaceWidth, ++ m_surfaceHeight, ++ m_vidWidth, ++ m_vidHeight, ++ avctx->coded_width, ++ avctx->coded_height); ++ return false; ++ } ++ m_xvbaSession = sessionOutput.session; ++ ++ ++ // create decode buffers ++ XVBA_Create_DecodeBuff_Input bufferInput; ++ XVBA_Create_DecodeBuff_Output bufferOutput; ++ ++ bufferInput.size = sizeof(bufferInput); ++ bufferInput.session = m_xvbaSession; ++ bufferInput.buffer_type = XVBA_PICTURE_DESCRIPTION_BUFFER; ++ bufferInput.num_of_buffers = 1; ++ bufferOutput.size = sizeof(bufferOutput); ++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput) ++ || bufferOutput.num_of_buffers_in_list != 1) ++ { ++ SetError(__FUNCTION__, "failed to create picture buffer", __LINE__); ++ return false; ++ } ++ m_xvbaBufferPool.picture_descriptor_buffer = bufferOutput.buffer_list; ++ ++ // data buffer ++ bufferInput.buffer_type = XVBA_DATA_BUFFER; ++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput) ++ || bufferOutput.num_of_buffers_in_list != 1) ++ { ++ SetError(__FUNCTION__, "failed to create data buffer", __LINE__); ++ return false; ++ } ++ m_xvbaBufferPool.data_buffer = bufferOutput.buffer_list; ++ ++ // QO Buffer ++ bufferInput.buffer_type = XVBA_QM_BUFFER; ++ if (Success != g_XVBA_vtable.CreateDecodeBuffers(&bufferInput, &bufferOutput) ++ || bufferOutput.num_of_buffers_in_list != 1) ++ { ++ SetError(__FUNCTION__, "failed to create qm buffer", __LINE__); ++ return false; ++ } ++ m_xvbaBufferPool.iq_matrix_buffer = bufferOutput.buffer_list; ++ ++ return true; ++} ++ ++void CDecoder::DestroySession() ++{ ++ XVBA_Destroy_Decode_Buffers_Input bufInput; ++ bufInput.size = sizeof(bufInput); ++ bufInput.num_of_buffers_in_list = 1; ++ ++ for (unsigned int i=0; isurface) ++ { ++ g_XVBA_vtable.DestroySurface(render->surface); ++ render->surface = 0; ++ render->picture_descriptor = 0; ++ render->iq_matrix = 0; ++ } ++ } ++ ++ if (m_xvbaSession) ++ g_XVBA_vtable.DestroyDecode(m_xvbaSession); ++ m_xvbaSession = 0; ++} ++ ++bool CDecoder::IsSurfaceValid(xvba_render_state *render) ++{ ++ // find render state in queue ++ bool found(false); ++ unsigned int i; ++ for(i = 0; i < m_videoSurfaces.size(); ++i) ++ { ++ if(m_videoSurfaces[i] == render) ++ { ++ found = true; ++ break; ++ } ++ } ++ if (!found) ++ { ++ CLog::Log(LOGERROR,"%s - video surface not found", __FUNCTION__); ++ return false; ++ } ++ if (m_videoSurfaces[i]->surface == 0) ++ { ++ m_videoSurfaces[i]->state = 0; ++ return false; ++ } ++ ++ return true; ++} ++ ++bool CDecoder::EnsureDataControlBuffers(unsigned int num) ++{ ++ if (m_xvbaBufferPool.data_control_buffers.size() >= num) ++ return true; ++ ++ unsigned int missing = num - m_xvbaBufferPool.data_control_buffers.size(); ++ ++ XVBA_Create_DecodeBuff_Input bufferInput; ++ XVBA_Create_DecodeBuff_Output bufferOutput; ++ bufferInput.size = sizeof(bufferInput); ++ bufferInput.session = m_xvbaSession; ++ bufferInput.buffer_type = XVBA_DATA_CTRL_BUFFER; ++ bufferInput.num_of_buffers = 1; ++ bufferOutput.size = sizeof(bufferOutput); ++ ++ for (unsigned int i=0; iopaque; ++ CDecoder* xvba = (CDecoder*)ctx->GetHardware(); ++ unsigned int i; ++ ++ CSharedLock lock(xvba->m_decoderSection); ++ ++ xvba_render_state * render = NULL; ++ render = (xvba_render_state*)pic->data[0]; ++ if(!render) ++ { ++ CLog::Log(LOGERROR, "XVBA::FFReleaseBuffer - invalid context handle provided"); ++ return; ++ } ++ ++ for(i=0; i<4; i++) ++ pic->data[i]= NULL; ++ ++ // find render state in queue ++ if (!xvba->IsSurfaceValid(render)) ++ { ++ CLog::Log(LOGDEBUG, "XVBA::FFReleaseBuffer - ignoring invalid buffer"); ++ return; ++ } ++ ++ render->state &= ~FF_XVBA_STATE_USED_FOR_REFERENCE; ++} ++ ++void CDecoder::FFDrawSlice(struct AVCodecContext *avctx, ++ const AVFrame *src, int offset[4], ++ int y, int type, int height) ++{ ++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque; ++ CDecoder* xvba = (CDecoder*)ctx->GetHardware(); ++ ++ CSharedLock lock(xvba->m_decoderSection); ++ ++ { CSharedLock dLock(xvba->m_displaySection); ++ if(xvba->m_displayState != XVBA_OPEN) ++ return; ++ } ++ ++ if(src->linesize[0] || src->linesize[1] || src->linesize[2] ++ || offset[0] || offset[1] || offset[2]) ++ { ++ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid linesizes or offsets provided"); ++ return; ++ } ++ ++ xvba_render_state * render; ++ ++ render = (xvba_render_state*)src->data[0]; ++ if(!render) ++ { ++ CLog::Log(LOGERROR, "XVBA::FFDrawSlice - invalid context handle provided"); ++ return; ++ } ++ ++ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid ++ if (!xvba->IsSurfaceValid(render)) ++ { ++ CLog::Log(LOGWARNING, "XVBA::FFDrawSlice - ignoring invalid buffer"); ++ return; ++ } ++ ++ // decoding ++ XVBA_Decode_Picture_Start_Input startInput; ++ startInput.size = sizeof(startInput); ++ startInput.session = xvba->m_xvbaSession; ++ startInput.target_surface = render->surface; ++ { CSingleLock lock(xvba->m_apiSec); ++ if (Success != g_XVBA_vtable.StartDecodePicture(&startInput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed to start decoding", __LINE__); ++ return; ++ } ++ } ++ XVBA_Decode_Picture_Input picInput; ++ picInput.size = sizeof(picInput); ++ picInput.session = xvba->m_xvbaSession; ++ XVBABufferDescriptor *list[2]; ++ picInput.buffer_list = list; ++ list[0] = xvba->m_xvbaBufferPool.picture_descriptor_buffer; ++ picInput.num_of_buffers_in_list = 1; ++ if (avctx->codec_id == CODEC_ID_H264) ++ { ++ list[1] = xvba->m_xvbaBufferPool.iq_matrix_buffer; ++ picInput.num_of_buffers_in_list = 2; ++ } ++ ++ { CSingleLock lock(xvba->m_apiSec); ++ if (Success != g_XVBA_vtable.DecodePicture(&picInput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed to decode picture 1", __LINE__); ++ return; ++ } ++ } ++ ++ if (!xvba->EnsureDataControlBuffers(render->num_slices)) ++ return; ++ ++ XVBADataCtrl *dataControl; ++ int location = 0; ++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer = 0; ++ for (unsigned int j = 0; j < render->num_slices; ++j) ++ { ++ int startCodeSize = 0; ++ uint8_t startCode[] = {0x00,0x00,0x01}; ++ if (avctx->codec_id == CODEC_ID_H264) ++ { ++ startCodeSize = 3; ++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location, ++ startCode, 3); ++ } ++ else if (avctx->codec_id == CODEC_ID_VC1 && ++ (memcmp(render->buffers[j].buffer, startCode, 3) != 0)) ++ { ++ startCodeSize = 4; ++ uint8_t sdf = 0x0d; ++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location, ++ startCode, 3); ++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+3, ++ &sdf, 1); ++ } ++ // check for potential buffer overwrite ++ unsigned int bytesToCopy = render->buffers[j].size; ++ unsigned int freeBufferSize = xvba->m_xvbaBufferPool.data_buffer->buffer_size - ++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer; ++ if (bytesToCopy >= freeBufferSize) ++ { ++ xvba->SetError(__FUNCTION__, "bitstream buffer too large, maybe corrupted packet", __LINE__); ++ return; ++ } ++ memcpy((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+location+startCodeSize, ++ render->buffers[j].buffer, ++ render->buffers[j].size); ++ dataControl = (XVBADataCtrl*)xvba->m_xvbaBufferPool.data_control_buffers[j]->bufferXVBA; ++ dataControl->SliceDataLocation = location; ++ dataControl->SliceBytesInBuffer = render->buffers[j].size+startCodeSize; ++ dataControl->SliceBitsInBuffer = dataControl->SliceBytesInBuffer * 8; ++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += dataControl->SliceBytesInBuffer; ++ location += dataControl->SliceBytesInBuffer; ++ } ++ ++ int bufSize = xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer; ++ int padding = bufSize % 128; ++ if (padding) ++ { ++ padding = 128 - padding; ++ xvba->m_xvbaBufferPool.data_buffer->data_size_in_buffer += padding; ++ memset((uint8_t*)xvba->m_xvbaBufferPool.data_buffer->bufferXVBA+bufSize,0,padding); ++ } ++ ++ picInput.num_of_buffers_in_list = 2; ++ for (unsigned int i = 0; i < render->num_slices; ++i) ++ { ++ list[0] = xvba->m_xvbaBufferPool.data_buffer; ++ list[0]->data_offset = 0; ++ list[1] = xvba->m_xvbaBufferPool.data_control_buffers[i]; ++ list[1]->data_size_in_buffer = sizeof(*dataControl); ++ { CSingleLock lock(xvba->m_apiSec); ++ if (Success != g_XVBA_vtable.DecodePicture(&picInput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed to decode picture 2", __LINE__); ++ return; ++ } ++ } ++ } ++ XVBA_Decode_Picture_End_Input endInput; ++ endInput.size = sizeof(endInput); ++ endInput.session = xvba->m_xvbaSession; ++ { CSingleLock lock(xvba->m_apiSec); ++ if (Success != g_XVBA_vtable.EndDecodePicture(&endInput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed to decode picture 3", __LINE__); ++ return; ++ } ++ } ++ ++ // decode sync and error ++ XVBA_Surface_Sync_Input syncInput; ++ XVBA_Surface_Sync_Output syncOutput; ++ syncInput.size = sizeof(syncInput); ++ syncInput.session = xvba->m_xvbaSession; ++ syncInput.surface = render->surface; ++ syncInput.query_status = XVBA_GET_SURFACE_STATUS; ++ syncOutput.size = sizeof(syncOutput); ++ int64_t start = CurrentHostCounter(); ++ while (1) ++ { ++ { CSingleLock lock(xvba->m_apiSec); ++ if (Success != g_XVBA_vtable.SyncSurface(&syncInput, &syncOutput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed sync surface 1", __LINE__); ++ return; ++ } ++ } ++ if (!(syncOutput.status_flags & XVBA_STILL_PENDING)) ++ break; ++ if (CurrentHostCounter() - start > CurrentHostFrequency()) ++ { ++ xvba->SetError(__FUNCTION__, "timed out waiting for surface", __LINE__); ++ break; ++ } ++ usleep(100); ++ } ++} ++ ++int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) ++{ ++ CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque; ++ CDecoder* xvba = (CDecoder*)ctx->GetHardware(); ++ struct pictureAge* pA = &xvba->picAge; ++ ++ pic->data[0] = ++ pic->data[1] = ++ pic->data[2] = ++ pic->data[3] = 0; ++ ++ pic->linesize[0] = ++ pic->linesize[1] = ++ pic->linesize[2] = ++ pic->linesize[3] = 0; ++ ++ CSharedLock lock(xvba->m_decoderSection); ++ ++ { CSharedLock dLock(xvba->m_displaySection); ++ if(xvba->m_displayState != XVBA_OPEN) ++ return -1; ++ } ++ ++ if (xvba->m_xvbaSession == 0) ++ { ++ if (!xvba->CreateSession(avctx)) ++ return -1; ++ } ++ ++ xvba_render_state * render = NULL; ++ // find unused surface ++ { CSingleLock lock(xvba->m_videoSurfaceSec); ++ for(unsigned int i = 0; i < xvba->m_videoSurfaces.size(); ++i) ++ { ++ if(!(xvba->m_videoSurfaces[i]->state & (FF_XVBA_STATE_USED_FOR_REFERENCE | FF_XVBA_STATE_USED_FOR_RENDER))) ++ { ++ render = xvba->m_videoSurfaces[i]; ++ render->state = 0; ++ break; ++ } ++ } ++ } ++ ++ // create a new render state ++ if (render == NULL) ++ { ++ render = (xvba_render_state*)calloc(sizeof(xvba_render_state), 1); ++ if (render == NULL) ++ { ++ CLog::Log(LOGERROR, "XVBA::FFGetBuffer - calloc failed"); ++ return -1; ++ } ++ render->surface = 0; ++ render->buffers_alllocated = 0; ++ CSingleLock lock(xvba->m_videoSurfaceSec); ++ xvba->m_videoSurfaces.push_back(render); ++ } ++ ++ // create a new surface ++ if (render->surface == 0) ++ { ++ XVBA_Create_Surface_Input surfaceInput; ++ XVBA_Create_Surface_Output surfaceOutput; ++ surfaceInput.size = sizeof(surfaceInput); ++ surfaceInput.surface_type = xvba->m_decoderCap.surface_type; ++ surfaceInput.width = xvba->m_surfaceWidth; ++ surfaceInput.height = xvba->m_surfaceHeight; ++ surfaceInput.session = xvba->m_xvbaSession; ++ surfaceOutput.size = sizeof(surfaceOutput); ++ { CSingleLock lock(xvba->m_apiSec); ++ if (Success != g_XVBA_vtable.CreateSurface(&surfaceInput, &surfaceOutput)) ++ { ++ xvba->SetError(__FUNCTION__, "failed to create video surface", __LINE__); ++ return -1; ++ } ++ } ++ render->surface = surfaceOutput.surface; ++ render->picture_descriptor = (XVBAPictureDescriptor *)xvba->m_xvbaBufferPool.picture_descriptor_buffer->bufferXVBA; ++ render->iq_matrix = (XVBAQuantMatrixAvc *)xvba->m_xvbaBufferPool.iq_matrix_buffer->bufferXVBA; ++ CLog::Log(LOGDEBUG, "XVBA::FFGetBuffer - created video surface"); ++ } ++ ++ if (render == NULL) ++ return -1; ++ ++ pic->data[0] = (uint8_t*)render; ++ ++ if(pic->reference) ++ { ++ pic->age = pA->ip_age[0]; ++ pA->ip_age[0]= pA->ip_age[1]+1; ++ pA->ip_age[1]= 1; ++ pA->b_age++; ++ } ++ else ++ { ++ pic->age = pA->b_age; ++ pA->ip_age[0]++; ++ pA->ip_age[1]++; ++ pA->b_age = 1; ++ } ++ pic->type= FF_BUFFER_TYPE_USER; ++ ++ render->state |= FF_XVBA_STATE_USED_FOR_REFERENCE; ++ pic->reordered_opaque= avctx->reordered_opaque; ++ ++ return 0; ++} ++ ++int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) ++{ ++ int result = Check(avctx); ++ if (result) ++ return result; ++ ++ CSharedLock lock(m_decoderSection); ++ ++ int iReturn(0); ++ if(frame) ++ { // we have a new frame from decoder ++ ++ xvba_render_state * render = (xvba_render_state*)frame->data[0]; ++ if(!render) ++ return VC_ERROR; ++ ++ // ffmpeg vc-1 decoder does not flush, make sure the data buffer is still valid ++ if (!IsSurfaceValid(render)) ++ { ++ CLog::Log(LOGWARNING, "XVBA::Decode - ignoring invalid buffer"); ++ return VC_BUFFER; ++ } ++ ++ render->state |= FF_XVBA_STATE_USED_FOR_RENDER; ++ ++ CSingleLock lock(m_outPicSec); ++ if (m_freeOutPic.empty()) ++ { ++ return VC_ERROR; ++ } ++ OutputPicture *outPic = m_freeOutPic.front(); ++ m_freeOutPic.pop_front(); ++ memset(&outPic->dvdPic, 0, sizeof(DVDVideoPicture)); ++ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&outPic->dvdPic); ++ outPic->render = render; ++ ++ if (g_guiSettings.GetBool("videoplayer.usexvbasharedsurface")) ++ outPic->dvdPic.format = DVDVideoPicture::FMT_XVBA; ++ else ++ outPic->dvdPic.format = DVDVideoPicture::FMT_XVBA_YV12; ++ outPic->dvdPic.iWidth = m_surfaceWidth; ++ outPic->dvdPic.iHeight = m_surfaceHeight; ++ outPic->dvdPic.xvba = this; ++ ++ m_usedOutPic.push_back(outPic); ++ lock.Leave(); ++ ++ iReturn |= VC_PICTURE; ++ } ++ ++ { CSingleLock lock(m_outPicSec); ++ if (!m_freeOutPic.empty()) ++ iReturn |= VC_BUFFER; ++ } ++ ++ return iReturn; ++} ++ ++bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) ++{ ++ CSharedLock lock(m_decoderSection); ++ ++ { CSharedLock dLock(m_displaySection); ++ if(m_displayState != XVBA_OPEN) ++ return false; ++ } ++ ++ { CSingleLock lock(m_outPicSec); ++ ++ if (DiscardPresentPicture()) ++ CLog::Log(LOGWARNING,"XVBA::GetPicture: old presentPicture was still valid - now discarded"); ++ if (m_usedOutPic.size() > 0) ++ { ++ m_presentPicture = m_usedOutPic.front(); ++ m_usedOutPic.pop_front(); ++ *picture = m_presentPicture->dvdPic; ++ } ++ else ++ { ++ CLog::Log(LOGERROR,"XVBA::GetPicture: no picture"); ++ return false; ++ } ++ } ++ return true; ++} ++ ++bool CDecoder::DiscardPresentPicture() ++{ ++ CSingleLock lock(m_outPicSec); ++ if (m_presentPicture) ++ { ++ if (m_presentPicture->render) ++ m_presentPicture->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER; ++ m_presentPicture->render = NULL; ++ m_freeOutPic.push_back(m_presentPicture); ++ m_presentPicture = NULL; ++ return true; ++ } ++ return false; ++} ++ ++void CDecoder::Present(int index) ++{ ++ CSharedLock lock(m_decoderSection); ++ ++ { CSharedLock dLock(m_displaySection); ++ if(m_displayState != XVBA_OPEN) ++ return; ++ } ++ ++ if (!m_presentPicture) ++ { ++ // use last picture, we might processing a still frame here ++ int lastIndex = (index + m_numRenderBuffers -1) % m_numRenderBuffers; ++ m_presentPicture = m_flipBuffer[lastIndex].outPic; ++ m_flipBuffer[lastIndex].isDuplicate = true; ++ if (!m_presentPicture) ++ { ++ CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL"); ++ return; ++ } ++ } ++ ++ if (m_flipBuffer[index].outPic && !m_flipBuffer[index].isDuplicate) ++ { ++ if (m_flipBuffer[index].outPic->render) ++ { ++ CSingleLock lock(m_videoSurfaceSec); ++ m_flipBuffer[index].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER; ++ m_flipBuffer[index].outPic->render = NULL; ++ } ++ CSingleLock lock(m_outPicSec); ++ m_freeOutPic.push_back(m_flipBuffer[index].outPic); ++ m_flipBuffer[index].outPic = NULL; ++ } ++ ++ m_flipBuffer[index].outPic = m_presentPicture; ++ m_flipBuffer[index].isDuplicate = false; ++ m_presentPicture = NULL; ++} ++ ++void CDecoder::CopyYV12(int index, uint8_t *dest) ++{ ++ CSharedLock lock(m_decoderSection); ++ ++ { CSharedLock dLock(m_displaySection); ++ if(m_displayState != XVBA_OPEN) ++ return; ++ } ++ ++ if (!m_flipBuffer[index].outPic) ++ { ++ CLog::Log(LOGWARNING, "XVBA::Present: present picture is NULL"); ++ return; ++ } ++ ++ XVBA_GetSurface_Target target; ++ target.size = sizeof(target); ++ target.surfaceType = XVBA_YV12; ++ target.flag = XVBA_FRAME; ++ ++ XVBA_Get_Surface_Input input; ++ input.size = sizeof(input); ++ input.session = m_xvbaSession; ++ input.src_surface = m_flipBuffer[index].outPic->render->surface; ++ input.target_buffer = dest; ++ input.target_pitch = m_surfaceWidth; ++ input.target_width = m_surfaceWidth; ++ input.target_height = m_surfaceHeight; ++ input.target_parameter = target; ++ { CSingleLock lock(m_apiSec); ++ if (Success != g_XVBA_vtable.GetSurface(&input)) ++ { ++ CLog::Log(LOGERROR,"(XVBA::CopyYV12) failed to get surface"); ++ } ++ } ++} ++ ++void CDecoder::Reset() ++{ ++ ++} ++ ++int CDecoder::UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget) ++{ ++ CSharedLock lock(m_decoderSection); ++ ++ { CSharedLock dLock(m_displaySection); ++ if(m_displayState != XVBA_OPEN) ++ return -1; ++ } ++ ++ if (!m_flipBuffer[index].outPic || ++ !m_flipBuffer[index].outPic->render || ++ !m_flipBuffer[index].outPic->render->surface) ++ return -1; ++ ++ int i = field; ++// unsigned int first, last; ++// first = last = 0; ++// if (field != XVBA_FRAME) ++// { ++// first = 1; ++// last = 2; ++// } ++// for (unsigned int i = first; i <= last; ++i) ++ { ++ XVBA_SURFACE_FLAG field; ++ if (i==0) field = XVBA_FRAME; ++ else if (i==1) field = XVBA_TOP_FIELD; ++ else field = XVBA_BOTTOM_FIELD; ++ ++ if (!glIsTexture(m_flipBuffer[index].glTexture[i])) ++ { ++ glEnable(textureTarget); ++ glGenTextures(1, &m_flipBuffer[index].glTexture[i]); ++ glBindTexture(textureTarget, m_flipBuffer[index].glTexture[i]); ++ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 4); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_surfaceWidth, m_surfaceHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); ++ ++ XVBA_Create_GLShared_Surface_Input surfInput; ++ XVBA_Create_GLShared_Surface_Output surfOutput; ++ surfInput.size = sizeof(surfInput); ++ surfInput.session = m_xvbaSession; ++ surfInput.gltexture = m_flipBuffer[index].glTexture[i]; ++ surfInput.glcontext = glXGetCurrentContext(); ++ surfOutput.size = sizeof(surfOutput); ++ surfOutput.surface = 0; ++ if (Success != g_XVBA_vtable.CreateGLSharedSurface(&surfInput, &surfOutput)) ++ { ++ CLog::Log(LOGERROR,"(XVBA) failed to create shared surface"); ++ return -1; ++ } ++ m_flipBuffer[index].glSurface[i] = surfOutput.surface; ++ CLog::Log(LOGDEBUG, "XVBA::GetTexture - created shared surface"); ++ } ++ ++ XVBA_Transfer_Surface_Input transInput; ++ transInput.size = sizeof(transInput); ++ transInput.session = m_xvbaSession; ++ transInput.src_surface = m_flipBuffer[index].outPic->render->surface; ++ transInput.target_surface = m_flipBuffer[index].glSurface[i]; ++ transInput.flag = field; ++ { CSingleLock lock(m_apiSec); ++ if (Success != g_XVBA_vtable.TransferSurface(&transInput)) ++ { ++ CLog::Log(LOGERROR,"(XVBA) failed to transfer surface"); ++ return -1; ++ } ++ } ++ } ++ ++// { CSingleLock lock(m_videoSurfaceSec); ++// m_flipBuffer[index].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER; ++// m_flipBuffer[index].outPic->render = NULL; ++// } ++// { ++// CSingleLock lock(m_outPicSec); ++// m_freeOutPic.push_back(m_flipBuffer[index].outPic); ++// m_flipBuffer[index].outPic = NULL; ++// } ++ ++ return 1; ++} ++ ++GLuint CDecoder::GetTexture(int index, XVBA_SURFACE_FLAG field) ++{ ++ return m_flipBuffer[index].glTexture[field]; ++} ++ ++CRect CDecoder::GetCropRect() ++{ ++ CRect crop; ++ crop.x1 = 0; ++ crop.y1 = 0; ++ crop.x2 = m_vidWidth; ++ crop.y2 = m_vidHeight; ++ return crop; ++} ++ ++void CDecoder::FinishGL() ++{ ++ CLog::Log(LOGNOTICE, "XVBA::FinishGL - clearing down gl resources"); ++ ++ CExclusiveLock lock(m_decoderSection); ++ // if decoder was created with non supported codec, we would not have a flipBuffer and segfault ++ if(!m_flipBuffer) ++ return; ++ ++ for (unsigned int i=0; irender) ++ { ++ { CSingleLock lock(m_videoSurfaceSec); ++ m_flipBuffer[i].outPic->render->state &= ~FF_XVBA_STATE_USED_FOR_RENDER; ++ m_flipBuffer[i].outPic->render = NULL; ++ } ++ { CSingleLock lock(m_outPicSec); ++ m_freeOutPic.push_back(m_flipBuffer[i].outPic); ++ m_flipBuffer[i].outPic = 0; ++ } ++ } ++ ++ for (unsigned int j=0; j<3; ++j) ++ { ++ if (glIsTexture(m_flipBuffer[i].glTexture[j])) ++ { ++ glDeleteTextures(1, &m_flipBuffer[i].glTexture[j]); ++ m_flipBuffer[i].glTexture[j] = 0; ++ CLog::Log(LOGDEBUG, "XVBA::FinishGL - destroyed texture, index: %d, field %d", i, j); ++ } ++ if (m_flipBuffer[i].glSurface[j] && m_xvbaSession) ++ { ++ { CSingleLock lock(m_apiSec); ++ g_XVBA_vtable.DestroySurface(m_flipBuffer[i].glSurface[j]); ++ } ++ m_flipBuffer[i].glSurface[j] = 0; ++ CLog::Log(LOGDEBUG, "XVBA::FinishGL - destroyed shared surface"); ++ } ++ } ++ } ++} ++ ++#endif +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDCodecs/Video/XVBA.h 2012-02-07 14:30:18.021098627 +0100 +@@ -0,0 +1,161 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++#pragma once ++ ++#include "X11/Xlib.h" ++#include "amd/amdxvba.h" ++#include "DllAvCodec.h" ++#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h" ++#include "threads/CriticalSection.h" ++#include "threads/SharedSection.h" ++#include "threads/Event.h" ++#include "guilib/DispResource.h" ++#include "guilib/Geometry.h" ++#include "libavcodec/xvba.h" ++#include ++#include ++ ++#define NUM_OUTPUT_PICS 7 ++ ++namespace XVBA ++{ ++ ++struct pictureAge ++{ ++ int b_age; ++ int ip_age[2]; ++}; ++ ++enum EDisplayState ++{ XVBA_OPEN ++, XVBA_RESET ++, XVBA_LOST ++, XVBA_ERROR ++}; ++ ++class CXVBAContext ++{ ++public: ++ static bool EnsureContext(CXVBAContext **ctx); ++ void *GetContext(); ++ void Release(); ++private: ++ CXVBAContext(); ++ void Close(); ++ bool LoadSymbols(); ++ bool CreateContext(); ++ void DestroyContext(); ++ static CXVBAContext *m_context; ++ static CCriticalSection m_section; ++ static Display *m_display; ++ int m_refCount; ++ void *m_dlHandle; ++ void *m_xvbaContext; ++}; ++ ++class CDecoder : public CDVDVideoCodecFFmpeg::IHardwareDecoder, ++ public IDispResource ++{ ++public: ++ CDecoder(); ++ virtual ~CDecoder(); ++ virtual void OnLostDevice(); ++ virtual void OnResetDevice(); ++ ++ virtual bool Open(AVCodecContext* avctx, const enum PixelFormat fmt, unsigned int surfaces = 0); ++ virtual int Decode (AVCodecContext* avctx, AVFrame* frame); ++ virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture); ++ virtual void Reset(); ++ virtual void Close(); ++ virtual int Check(AVCodecContext* avctx); ++ virtual const std::string Name() { return "xvba"; } ++ ++ void Present(int index); ++ void CopyYV12(int index, uint8_t *dest); ++ int UploadTexture(int index, XVBA_SURFACE_FLAG field, GLenum textureTarget); ++ GLuint GetTexture(int index, XVBA_SURFACE_FLAG field); ++ CRect GetCropRect(); ++ void FinishGL(); ++ ++protected: ++ bool CreateSession(AVCodecContext* avctx); ++ void DestroySession(); ++ bool EnsureDataControlBuffers(unsigned int num); ++ bool DiscardPresentPicture(); ++ void ResetState(); ++ void SetError(const char* function, const char* msg, int line); ++ bool IsSurfaceValid(xvba_render_state *render); ++ ++ // callbacks for ffmpeg ++ static void FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic); ++ static void FFDrawSlice(struct AVCodecContext *avctx, ++ const AVFrame *src, int offset[4], ++ int y, int type, int height); ++ static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic); ++ ++ DllAvUtil m_dllAvUtil; ++ CXVBAContext *m_context; ++ CSharedSection m_displaySection, m_decoderSection; ++ CEvent m_displayEvent; ++ EDisplayState m_displayState; ++ ++ unsigned int m_surfaceWidth, m_surfaceHeight; ++ unsigned int m_vidWidth, m_vidHeight; ++ unsigned int m_numRenderBuffers; ++ ++ XVBADecodeCap m_decoderCap; ++ void *m_xvbaSession; ++ unsigned int m_decoderId; ++ struct XVBABufferPool ++ { ++ XVBABufferDescriptor *picture_descriptor_buffer; ++ XVBABufferDescriptor *iq_matrix_buffer; ++ XVBABufferDescriptor *data_buffer; ++ std::vector data_control_buffers; ++ }; ++ XVBABufferPool m_xvbaBufferPool; ++ ++ std::vector m_videoSurfaces; ++ pictureAge picAge; ++ ++ struct OutputPicture ++ { ++ DVDVideoPicture dvdPic; ++ xvba_render_state *render; ++ void *glSurface; ++ }; ++ struct RenderPicture ++ { ++ OutputPicture *outPic; ++ bool isDuplicate; ++ void *glSurface[3]; ++ GLuint glTexture[3]; ++ }; ++ CCriticalSection m_outPicSec, m_videoSurfaceSec; ++ CCriticalSection m_apiSec; ++ OutputPicture m_allOutPic[NUM_OUTPUT_PICS]; ++ std::deque m_freeOutPic; ++ std::deque m_usedOutPic; ++ OutputPicture *m_presentPicture; ++ RenderPicture *m_flipBuffer; ++}; ++ ++} +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2012-02-07 14:30:18.023098666 +0100 +@@ -19,7 +19,6 @@ + * + */ + +-#include "threads/SystemClock.h" + #include "system.h" + #ifndef __STDC_CONSTANT_MACROS + #define __STDC_CONSTANT_MACROS +@@ -43,6 +42,7 @@ + #include "filesystem/Directory.h" + #include "utils/log.h" + #include "threads/Thread.h" ++#include "threads/SystemClock.h" + #include "utils/TimeUtils.h" + + void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo) +@@ -153,16 +153,12 @@ + ++it; + } + +-#ifdef _MSC_VER +-static __declspec(thread) CDVDDemuxFFmpeg* g_demuxer = 0; +-#else +-static TLS g_tls; +-#define g_demuxer (*((CDVDDemuxFFmpeg**)g_tls.Get())) +-#endif ++static XbmcThreads::ThreadLocal g_demuxer; + + static int interrupt_cb(void) + { +- if(g_demuxer && g_demuxer->Aborted()) ++ CDVDDemuxFFmpeg* demuxer = g_demuxer.get(); ++ if(demuxer && demuxer->Aborted()) + return 1; + return 0; + } +@@ -234,7 +230,7 @@ + std::string strFile; + m_iCurrentPts = DVD_NOPTS_VALUE; + m_speed = DVD_PLAYSPEED_NORMAL; +- g_demuxer = this; ++ g_demuxer.set(this); + m_program = UINT_MAX; + + if (!pInput) return false; +@@ -506,7 +502,7 @@ + + void CDVDDemuxFFmpeg::Dispose() + { +- g_demuxer = this; ++ g_demuxer.set(this); + + if (m_pFormatContext) + { +@@ -555,7 +551,7 @@ + + void CDVDDemuxFFmpeg::Flush() + { +- g_demuxer = this; ++ g_demuxer.set(this); + + // naughty usage of an internal ffmpeg function + if (m_pFormatContext) +@@ -571,7 +567,7 @@ + + void CDVDDemuxFFmpeg::SetSpeed(int iSpeed) + { +- g_demuxer = this; ++ g_demuxer.set(this); + + if(!m_pFormatContext) + return; +@@ -633,7 +629,7 @@ + + DemuxPacket* CDVDDemuxFFmpeg::Read() + { +- g_demuxer = this; ++ g_demuxer.set(this); + + AVPacket pkt; + DemuxPacket* pPacket = NULL; +@@ -832,7 +828,7 @@ + + bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) + { +- g_demuxer = this; ++ g_demuxer.set(this); + + if(time < 0) + time = 0; +@@ -892,7 +888,7 @@ + + bool CDVDDemuxFFmpeg::SeekByte(__int64 pos) + { +- g_demuxer = this; ++ g_demuxer.set(this); + + CSingleLock lock(m_critSection); + int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE); +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.cpp 2012-02-07 14:30:18.024098686 +0100 +@@ -21,6 +21,7 @@ + + #include "DVDPerformanceCounter.h" + #include "DVDMessageQueue.h" ++#include "utils/TimeUtils.h" + + #include "dvd_config.h" + +@@ -68,22 +69,16 @@ + + inline __int64 get_thread_cpu_usage(ProcessPerformance* p) + { +- if (p->hThread) ++ if (p->thread) + { +- FILETIME dummy; +- FILETIME current_time_thread; +- FILETIME current_time_system; + ULARGE_INTEGER old_time_thread; + ULARGE_INTEGER old_time_system; + + old_time_thread.QuadPart = p->timer_thread.QuadPart; + old_time_system.QuadPart = p->timer_system.QuadPart; + +- GetThreadTimes(p->hThread, &dummy, &dummy, ¤t_time_thread, &dummy); +- GetSystemTimeAsFileTime(¤t_time_system); +- +- FILETIME_TO_ULARGE_INTEGER(p->timer_thread, current_time_thread); +- FILETIME_TO_ULARGE_INTEGER(p->timer_system, current_time_system); ++ p->timer_thread.QuadPart = p->thread->GetAbsoluteUsage(); ++ p->timer_system.QuadPart = CurrentHostCounter(); + + __int64 threadTime = (p->timer_thread.QuadPart - old_time_thread.QuadPart); + __int64 systemTime = (p->timer_system.QuadPart - old_time_system.QuadPart); +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDPerformanceCounter.h xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.h +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDPerformanceCounter.h 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPerformanceCounter.h 2012-02-07 14:30:18.025098706 +0100 +@@ -24,7 +24,7 @@ + #define FILETIME_TO_ULARGE_INTEGER(ularge, filetime) { ularge.u.HighPart = filetime.dwHighDateTime; ularge.u.LowPart = filetime.dwLowDateTime; } + + #include "system.h" +- ++#include "threads/Thread.h" + #include "threads/SingleLock.h" + + class CDVDMessageQueue; +@@ -33,7 +33,7 @@ + { + ULARGE_INTEGER timer_thread; + ULARGE_INTEGER timer_system; +- HANDLE hThread; ++ CThread* thread; + } ProcessPerformance; + + class CDVDPerformanceCounter +@@ -45,20 +45,20 @@ + bool Initialize(); + void DeInitialize(); + +- void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; } +- void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; } ++ void EnableAudioQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pAudioQueue = pQueue; } ++ void DisableAudioQueue() { CSingleLock lock(m_critSection); m_pAudioQueue = NULL; } + +- void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; } +- void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; } ++ void EnableVideoQueue(CDVDMessageQueue* pQueue) { CSingleLock lock(m_critSection); m_pVideoQueue = pQueue; } ++ void DisableVideoQueue() { CSingleLock lock(m_critSection); m_pVideoQueue = NULL; } + +- void EnableVideoDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = hThread; } +- void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.hThread = NULL; } ++ void EnableVideoDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = thread; } ++ void DisableVideoDecodePerformance() { CSingleLock lock(m_critSection); m_videoDecodePerformance.thread = NULL; } + +- void EnableAudioDecodePerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = hThread; } +- void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.hThread = NULL; } ++ void EnableAudioDecodePerformance(CThread *thread) { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = thread; } ++ void DisableAudioDecodePerformance() { CSingleLock lock(m_critSection); m_audioDecodePerformance.thread = NULL; } + +- void EnableMainPerformance(HANDLE hThread) { CSingleLock lock(m_critSection); m_mainPerformance.hThread = hThread; } +- void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.hThread = NULL; } ++ void EnableMainPerformance(CThread *thread) { CSingleLock lock(m_critSection); m_mainPerformance.thread = thread; } ++ void DisableMainPerformance() { CSingleLock lock(m_critSection); m_mainPerformance.thread = NULL; } + + CDVDMessageQueue* m_pAudioQueue; + CDVDMessageQueue* m_pVideoQueue; +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp 2012-02-07 14:30:18.029098786 +0100 +@@ -518,7 +518,7 @@ + m_decode.msg = NULL; + m_decode.Release(); + +- g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle()); ++ g_dvdPerformanceCounter.EnableAudioDecodePerformance(this); + + #ifdef _WIN32 + CoInitializeEx(NULL, COINIT_MULTITHREADED); +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDPlayer.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPlayer.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDPlayer.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPlayer.cpp 2012-02-07 14:30:18.028098766 +0100 +@@ -341,7 +341,7 @@ + + // if playing a file close it first + // this has to be changed so we won't have to close it. +- if(ThreadHandle()) ++ if(IsRunning()) + CloseFile(); + + m_bAbortRequest = false; +@@ -432,9 +432,8 @@ + + m_messenger.Init(); + +- g_dvdPerformanceCounter.EnableMainPerformance(ThreadHandle()); +- + CUtil::ClearTempFonts(); ++ g_dvdPerformanceCounter.EnableMainPerformance(this); + } + + bool CDVDPlayer::OpenInputStream() +@@ -2707,7 +2706,7 @@ + m_dvdPlayerAudio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); + + /* audio normally won't consume full cpu, so let it have prio */ +- m_dvdPlayerAudio.SetPriority(GetThreadPriority(*this)+1); ++ m_dvdPlayerAudio.SetPriority(GetPriority()+1); + + return true; + } +@@ -2769,11 +2768,11 @@ + // the CoreAudio audio device handler thread. We do the same for + // the DVDPlayerVideo thread so it can run to sleep without getting + // swapped out by a busy OS. +- m_dvdPlayerVideo.SetPrioritySched_RR(); ++ m_dvdPlayerVideo.SetPriority(GetSchedRRPriority()); + #else + /* use same priority for video thread as demuxing thread, as */ + /* otherwise demuxer will starve if video consumes the full cpu */ +- m_dvdPlayerVideo.SetPriority(GetThreadPriority(*this)); ++ m_dvdPlayerVideo.SetPriority(GetPriority()); + #endif + return true; + +diff -Naur xbmc-1fef727/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +--- xbmc-1fef727/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2012-02-07 14:30:18.030098805 +0100 +@@ -189,7 +189,7 @@ + return false; + } + +- if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && g_VideoReferenceClock.ThreadHandle() == NULL) ++ if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && !g_VideoReferenceClock.IsRunning()) + { + g_VideoReferenceClock.Create(); + //we have to wait for the clock to start otherwise alsa can cause trouble +@@ -288,7 +288,7 @@ + m_iCurrentPts = DVD_NOPTS_VALUE; + m_FlipTimeStamp = m_pClock->GetAbsoluteClock(); + +- g_dvdPerformanceCounter.EnableVideoDecodePerformance(ThreadHandle()); ++ g_dvdPerformanceCounter.EnableVideoDecodePerformance(this); + } + + void CDVDPlayerVideo::Process() +@@ -1049,6 +1049,14 @@ + 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 -Naur xbmc-1fef727/xbmc/cores/paplayer/PAPlayer.cpp xbmc-1fef727.patch/xbmc/cores/paplayer/PAPlayer.cpp +--- xbmc-1fef727/xbmc/cores/paplayer/PAPlayer.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/paplayer/PAPlayer.cpp 2012-02-07 14:30:18.031098824 +0100 +@@ -52,7 +52,7 @@ + // Supporting all open audio codec standards. + // First one being nullsoft's nsv audio decoder format + +-PAPlayer::PAPlayer(IPlayerCallback& callback) : IPlayer(callback) ++PAPlayer::PAPlayer(IPlayerCallback& callback) : CThread("PAPlayer"), IPlayer(callback) + { + m_bIsPlaying = false; + m_bPaused = false; +@@ -168,7 +168,7 @@ + + *m_currentFile = file; + +- if (ThreadHandle() == NULL) ++ if (!IsRunning()) + Create(); + + m_startEvent.Set(); +diff -Naur xbmc-1fef727/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp xbmc-1fef727.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +--- xbmc-1fef727/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp 2012-02-07 14:30:18.012098450 +0100 +@@ -61,6 +61,9 @@ + VA_MICRO_VERSION == 0 && VA_SDS_VERSION < 5))) + + #endif ++#ifdef HAVE_LIBXVBA ++#include "cores/dvdplayer/DVDCodecs/Video/XVBA.h" ++#endif + + #ifdef HAS_GLX + #include +@@ -121,6 +124,10 @@ + #ifdef HAVE_LIBVDPAU + vdpau = NULL; + #endif ++#ifdef HAVE_LIBXVBA ++ xvba = NULL; ++ xvba_tmp = NULL; ++#endif + } + + CLinuxRendererGL::YUVBUFFER::~YUVBUFFER() +@@ -160,6 +167,7 @@ + m_rgbPbo = 0; + + m_dllSwScale = new DllSwScale; ++ m_bValidated = false; + } + + CLinuxRendererGL::~CLinuxRendererGL() +@@ -224,7 +232,7 @@ + + void CLinuxRendererGL::ManageTextures() + { +- m_NumYV12Buffers = 2; ++ m_NumYV12Buffers = 3; + //m_iYV12RenderBuffer = 0; + return; + } +@@ -569,6 +577,11 @@ + m_bValidated = false; + } + ++unsigned int CLinuxRendererGL::GetProcessorSize() ++{ ++ return m_NumYV12Buffers; ++} ++ + void CLinuxRendererGL::Update(bool bPauseDrawing) + { + if (!m_bConfigured) return; +@@ -730,14 +743,15 @@ + { + CSingleLock lock(g_graphicsContext); + m_bConfigured = false; +- m_bValidated = false; +- UnInit(); ++ if (m_bValidated) ++ UnInit(); ++ + m_resolution = g_guiSettings.m_LookAndFeelResolution; + if ( m_resolution == RES_WINDOW ) + m_resolution = RES_DESKTOP; + + m_iYV12RenderBuffer = 0; +- m_NumYV12Buffers = 2; ++ m_NumYV12Buffers = 3; + + // setup the background colour + m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; +@@ -817,7 +831,7 @@ + case VS_SCALINGMETHOD_LINEAR: + SetTextureFilter(m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR); + m_renderQuality = RQ_SINGLEPASS; +- if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) && m_nonLinStretch) ++ if (((m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) && m_nonLinStretch) + { + m_pVideoFilterShader = new StretchFilterShader(); + if (!m_pVideoFilterShader->CompileAndLink()) +@@ -898,6 +912,11 @@ + CLog::Log(LOGNOTICE, "GL: Using VAAPI render method"); + m_renderMethod = RENDER_VAAPI; + } ++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA) ++ { ++ CLog::Log(LOGNOTICE, "GL: Using XVBA render method"); ++ m_renderMethod = RENDER_XVBA; ++ } + else + { + int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod"); +@@ -1032,6 +1051,18 @@ + m_textureCreate = &CLinuxRendererGL::CreateVAAPITexture; + m_textureDelete = &CLinuxRendererGL::DeleteVAAPITexture; + } ++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA) ++ { ++ m_textureUpload = &CLinuxRendererGL::UploadXVBATexture; ++ m_textureCreate = &CLinuxRendererGL::CreateXVBATexture; ++ m_textureDelete = &CLinuxRendererGL::DeleteXVBATexture; ++ } ++ else if (CONF_FLAGS_FORMAT_MASK(m_iFlags) == CONF_FLAGS_FORMAT_XVBA_YV12) ++ { ++ m_textureUpload = &CLinuxRendererGL::UploadXVBAyv12Texture; ++ m_textureCreate = &CLinuxRendererGL::CreateXVBAyv12Texture; ++ m_textureDelete = &CLinuxRendererGL::DeleteXVBAyv12Texture; ++ } + else + { + // setup default YV12 texture handlers +@@ -1125,6 +1156,13 @@ + RenderVDPAU(renderBuffer, m_currentField); + } + #endif ++#ifdef HAVE_LIBXVBA ++ else if (m_renderMethod & RENDER_XVBA) ++ { ++ UpdateVideoFilter(); ++ RenderXVBA(renderBuffer, m_currentField); ++ } ++#endif + #ifdef HAVE_LIBVA + else if (m_renderMethod & RENDER_VAAPI) + { +@@ -1598,6 +1636,77 @@ + #endif + } + ++void CLinuxRendererGL::RenderXVBA(int index, int field) ++{ ++#ifdef HAVE_LIBXVBA ++ YUVPLANE &plane = m_buffers[index].fields[field][0]; ++ ++ glEnable(m_textureTarget); ++ glActiveTextureARB(GL_TEXTURE0); ++ glBindTexture(m_textureTarget, plane.id); ++ ++ // Try some clamping or wrapping ++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ ++ if (m_pVideoFilterShader) ++ { ++ GLint filter; ++ if (!m_pVideoFilterShader->GetTextureFilter(filter)) ++ filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; ++ ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); ++ m_pVideoFilterShader->SetSourceTexture(0); ++ m_pVideoFilterShader->SetWidth(m_sourceWidth); ++ m_pVideoFilterShader->SetHeight(m_sourceHeight); ++ ++ //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer ++ //having non-linear stretch on breaks the alignment ++ if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu()) ++ m_pVideoFilterShader->SetNonLinStretch(1.0); ++ else ++ m_pVideoFilterShader->SetNonLinStretch(pow(g_settings.m_fPixelRatio, g_advancedSettings.m_videoNonLinStretchRatio)); ++ ++ m_pVideoFilterShader->Enable(); ++ } ++ else ++ { ++ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); ++ } ++ ++ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); ++ VerifyGLState(); ++ ++ glBegin(GL_QUADS); ++ if (m_textureTarget==GL_TEXTURE_2D) ++ { ++ glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_destRect.x1, m_destRect.y1); ++ glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_destRect.x2, m_destRect.y1); ++ glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_destRect.x2, m_destRect.y2); ++ glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_destRect.x1, m_destRect.y2); ++ } ++ else ++ { ++ glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f); ++ glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f); ++ glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f); ++ glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f); ++ } ++ glEnd(); ++ VerifyGLState(); ++ ++ if (m_pVideoFilterShader) ++ m_pVideoFilterShader->Disable(); ++ ++ glBindTexture (m_textureTarget, 0); ++ glDisable(m_textureTarget); ++#endif ++} ++ ++ + void CLinuxRendererGL::RenderSoftware(int index, int field) + { + YUVPLANES &planes = m_buffers[index].fields[field]; +@@ -2352,6 +2461,424 @@ + #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); ++ SAFE_RELEASE(m_buffers[index].xvba_tmp); ++ ++ 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][0]; ++ YUVPLANE &planeFallback = fields[0][1]; ++ ++ DeleteXVBATexture(index); ++ ++ memset(&im , 0, sizeof(im)); ++ memset(&fields, 0, sizeof(fields)); ++ im.height = m_sourceHeight; ++ im.width = m_sourceWidth; ++ ++ for(int f = 0;fSet(); ++#endif ++ return true; ++} ++ ++void CLinuxRendererGL::UploadXVBATexture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ XVBA::CDecoder *xvba = m_buffers[index].xvba; ++ ++ if (m_buffers[index].xvba_tmp) ++ { ++ SAFE_RELEASE(m_buffers[index].xvba); ++ xvba = m_buffers[index].xvba = m_buffers[index].xvba_tmp; ++ m_buffers[index].xvba_tmp = NULL; ++ } ++ ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &planeFallback = fields[0][1]; ++ YUVPLANE &plane = fields[m_currentField][0]; ++ ++ if (!xvba) ++ { ++ fields[0][0].id = planeFallback.id; ++ fields[1][0].id = planeFallback.id; ++ fields[2][0].id = planeFallback.id; ++ m_eventTexturesDone[index]->Set(); ++ return; ++ } ++ ++ XVBA_SURFACE_FLAG field; ++ if (m_currentField == FIELD_TOP) ++ field = XVBA_TOP_FIELD; ++ else if (m_currentField == FIELD_BOT) ++ field = XVBA_BOTTOM_FIELD; ++ else ++ field = XVBA_FRAME; ++ ++ glEnable(m_textureTarget); ++ if (xvba->UploadTexture(index, field, m_textureTarget) == 1) ++ plane.id = xvba->GetTexture(index, field); ++ ++ // crop texture ++ CRect crop = xvba->GetCropRect(); ++ plane.rect = m_sourceRect; ++ plane.rect.x1 += crop.x1; ++ plane.rect.x2 -= m_sourceWidth - crop.x2; ++ plane.rect.y1 += crop.y1; ++ plane.rect.y2 -= m_sourceHeight - crop.y2; ++ plane.rect.y1 /= plane.pixpertex_y; ++ plane.rect.y2 /= plane.pixpertex_y; ++ plane.rect.x1 /= plane.pixpertex_x; ++ plane.rect.x2 /= plane.pixpertex_x; ++ if (m_textureTarget == GL_TEXTURE_2D) ++ { ++ plane.rect.y1 /= plane.texheight; ++ plane.rect.y2 /= plane.texheight; ++ plane.rect.x1 /= plane.texwidth; ++ plane.rect.x2 /= plane.texwidth; ++ } ++ ++ glDisable(m_textureTarget); ++ ++ m_eventTexturesDone[index]->Set(); ++#endif ++} ++ ++//******************************************************************************************************** ++// XVBA YV12 Texture creation, deletion, copying + clearing ++//******************************************************************************************************** ++void CLinuxRendererGL::DeleteXVBAyv12Texture(int index) ++{ ++#ifdef HAVE_LIBXVBA ++ YV12Image &im = m_buffers[index].image; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ GLuint *pbo = m_buffers[index].pbo; ++ ++ if (m_buffers[index].xvba) ++ m_buffers[index].xvba->FinishGL(); ++ ++ SAFE_RELEASE(m_buffers[index].xvba); ++ SAFE_RELEASE(m_buffers[index].xvba_tmp); ++ ++ if( fields[FIELD_FULL][0].id == 0 ) return; ++ ++ /* finish up all textures, and delete them */ ++ g_graphicsContext.BeginPaint(); //FIXME ++ for(int f = 0;f> im.cshift_x; ++ im.stride[2] = im.width >> im.cshift_x; ++ ++ im.planesize[0] = im.stride[0] * im.height; ++ im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y ); ++ im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y ); ++ ++ im.plane[1] = im.plane[2] = 0; ++ pbo[1] = pbo[2] = 0; ++ ++ bool pboSetup = false; ++ if (m_pboUsed) ++ { ++ pboSetup = true; ++ ++ glGenBuffersARB(1, pbo); ++ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[0]); ++ glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, im.planesize[0] + im.planesize[0]/2 + PBO_OFFSET, 0, GL_STREAM_DRAW_ARB); ++ void* pboPtr = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); ++ if (pboPtr) ++ { ++ im.plane[0] = (BYTE*) pboPtr + PBO_OFFSET; ++ memset(im.plane[0], 0, im.planesize[0]); ++ } ++ else ++ { ++ CLog::Log(LOGWARNING,"GL: failed to set up pixel buffer object"); ++ pboSetup = false; ++ } ++ ++ if (!pboSetup) ++ { ++ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[0]); ++ glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); ++ glDeleteBuffersARB(1, pbo); ++ memset(m_buffers[index].pbo, 0, sizeof(m_buffers[index].pbo)); ++ } ++ ++ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); ++ } ++ ++ if (!pboSetup) ++ { ++ im.plane[0] = new BYTE[im.planesize[0]+im.planesize[0]/2]; ++ } ++ ++ glEnable(m_textureTarget); ++ for(int f = 0;f> fieldshift; ++ ++ if (m_renderMethod & RENDER_SW) ++ { ++ planes[1].texwidth = 0; ++ planes[1].texheight = 0; ++ planes[2].texwidth = 0; ++ planes[2].texheight = 0; ++ } ++ else ++ { ++ planes[1].texwidth = planes[0].texwidth >> im.cshift_x; ++ planes[1].texheight = planes[0].texheight >> im.cshift_y; ++ planes[2].texwidth = planes[0].texwidth >> im.cshift_x; ++ planes[2].texheight = planes[0].texheight >> im.cshift_y; ++ } ++ ++ for (int p = 0; p < 3; p++) ++ { ++ planes[p].pixpertex_x = 1; ++ planes[p].pixpertex_y = 1; ++ } ++ ++ if(m_renderMethod & RENDER_POT) ++ { ++ for(int p = 0; p < 3; p++) ++ { ++ planes[p].texwidth = NP2(planes[p].texwidth); ++ planes[p].texheight = NP2(planes[p].texheight); ++ } ++ } ++ ++ for(int p = 0; p < 3; p++) ++ { ++ YUVPLANE &plane = planes[p]; ++ if (plane.texwidth * plane.texheight == 0) ++ continue; ++ ++ glBindTexture(m_textureTarget, plane.id); ++ if (m_renderMethod & RENDER_SW) ++ { ++ glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); ++ } ++ else ++ { ++ GLint format; ++ if (p == 2) //V plane needs an alpha texture ++ format = GL_ALPHA; ++ else ++ format = GL_LUMINANCE; ++ ++ glTexImage2D(m_textureTarget, 0, format, plane.texwidth, plane.texheight, 0, format, GL_UNSIGNED_BYTE, NULL); ++ } ++ ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ VerifyGLState(); ++ } ++ } ++ glDisable(m_textureTarget); ++ m_eventTexturesDone[index]->Set(); ++#endif ++ return true; ++} ++ ++void CLinuxRendererGL::UploadXVBAyv12Texture(int source) ++{ ++#ifdef HAVE_LIBXVBA ++ YUVBUFFER& buf = m_buffers[source]; ++ YV12Image* im = &buf.image; ++ YUVFIELDS& fields = buf.fields; ++ XVBA::CDecoder *xvba = m_buffers[source].xvba; ++ ++ if (m_buffers[source].xvba_tmp) ++ { ++ SAFE_RELEASE(m_buffers[source].xvba); ++ xvba = m_buffers[source].xvba = m_buffers[source].xvba_tmp; ++ m_buffers[source].xvba_tmp = NULL; ++ } ++ ++ if (!(im->flags&IMAGE_FLAG_READY) || !xvba) ++ { ++ m_eventTexturesDone[source]->Set(); ++ return; ++ } ++ ++ bool deinterlacing; ++ if (m_currentField == FIELD_FULL) ++ deinterlacing = false; ++ else ++ deinterlacing = true; ++ ++ glEnable(m_textureTarget); ++ VerifyGLState(); ++ ++ glPixelStorei(GL_UNPACK_ALIGNMENT,1); ++ ++ if (deinterlacing) ++ { ++ // Load Even Y Field ++ LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex ++ , im->width, im->height >> 1 ++ , im->stride[0]*2, im->plane[0] ); ++ ++ //load Odd Y Field ++ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex ++ , im->width, im->height >> 1 ++ , im->stride[0]*2, im->plane[0] + im->stride[0], &buf.pbo[0] ) ; ++ ++ // Load Even U & V Fields ++ LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , im->stride[1]*2, im->plane[0] + im->planesize[0] + im->planesize[1], &buf.pbo[0] ); ++ ++ LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , im->stride[2]*2, im->plane[0] + im->planesize[0], &buf.pbo[0] ); ++ ++ // Load Odd U & V Fields ++ LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , im->stride[1]*2, im->plane[0] + im->stride[1] + im->planesize[0] + im->planesize[1], &buf.pbo[0] ); ++ ++ LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , im->stride[2]*2, im->plane[0] + im->stride[2] + im->planesize[0], &buf.pbo[0] ); ++ } ++ else ++ { ++ //Load Y plane ++ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex ++ , im->width, im->height ++ , im->stride[0], im->plane[0], &buf.pbo[0] ); ++ ++ //load U plane ++ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> im->cshift_y ++ , im->stride[1], im->plane[0] + im->planesize[0] + im->planesize[1] , &buf.pbo[0] ); ++ ++ //load V plane ++ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> im->cshift_y ++ , im->stride[2], im->plane[0] + im->planesize[0], &buf.pbo[0] ); ++ } ++ ++ m_eventTexturesDone[source]->Set(); ++ ++ VerifyGLState(); ++ ++ // crop texture ++ CRect crop = xvba->GetCropRect(); ++ m_sourceRect.x1 += crop.x1; ++ m_sourceRect.x2 -= m_sourceWidth - crop.x2; ++ m_sourceRect.y1 += crop.y1; ++ m_sourceRect.y2 -= m_sourceHeight - crop.y2; ++ CalculateTextureSourceRects(source, 3); ++ ++ glDisable(m_textureTarget); ++#endif ++} ++ + void CLinuxRendererGL::UploadYUV422PackedTexture(int source) + { + YUVBUFFER& buf = m_buffers[source]; +@@ -2935,6 +3462,9 @@ + if (m_renderMethod & RENDER_VAAPI) + return false; + ++ if (m_renderMethod & RENDER_XVBA) ++ return false; ++ + return (m_renderMethod & RENDER_GLSL) + || (m_renderMethod & RENDER_ARB) + || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); +@@ -2948,6 +3478,9 @@ + if (m_renderMethod & RENDER_VAAPI) + return false; + ++ if (m_renderMethod & RENDER_XVBA) ++ return false; ++ + return (m_renderMethod & RENDER_GLSL) + || (m_renderMethod & RENDER_ARB) + || ((m_renderMethod & RENDER_SW) && glewIsSupported("GL_ARB_imaging") == GL_TRUE); +@@ -2971,7 +3504,8 @@ + if (feature == RENDERFEATURE_NONLINSTRETCH) + { + if (((m_renderMethod & RENDER_GLSL) && !(m_renderMethod & RENDER_POT)) || +- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) ++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || ++ (m_renderMethod & RENDER_XVBA)) + return true; + } + +@@ -3034,10 +3568,22 @@ + return false; + #endif + +- if(method == VS_INTERLACEMETHOD_DEINTERLACE +- || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF +- || method == VS_INTERLACEMETHOD_SW_BLEND) +- return true; ++ if (CONF_FLAGS_FORMAT_MASK(m_iFlags) != CONF_FLAGS_FORMAT_XVBA) ++ { ++ if(method == VS_INTERLACEMETHOD_DEINTERLACE ++ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF ++ || method == VS_INTERLACEMETHOD_SW_BLEND) ++ return true; ++ } ++ ++ if(m_renderMethod & RENDER_XVBA) ++ { ++ if (method == VS_INTERLACEMETHOD_RENDER_BOB_INVERTED ++ || method == VS_INTERLACEMETHOD_RENDER_BOB) ++ return true; ++ else ++ return false; ++ } + + if((method == VS_INTERLACEMETHOD_RENDER_BLEND + || method == VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED +@@ -3069,7 +3615,7 @@ + || method == VS_SCALINGMETHOD_LANCZOS3) + { + if ((glewIsSupported("GL_EXT_framebuffer_object") && (m_renderMethod & RENDER_GLSL)) || +- (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI)) ++ (m_renderMethod & RENDER_VDPAU) || (m_renderMethod & RENDER_VAAPI) || (m_renderMethod & RENDER_XVBA)) + { + // spline36 and lanczos3 are only allowed through advancedsettings.xml + if(method != VS_SCALINGMETHOD_SPLINE36 +@@ -3128,7 +3674,7 @@ + pbo = true; + + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.pbo[plane]); +- glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.image.planesize[plane] + PBO_OFFSET, NULL, GL_STREAM_DRAW_ARB); ++ glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, buff.image.planesize[plane] + buff.image.planesize[plane]/2 + PBO_OFFSET, NULL, GL_STREAM_DRAW_ARB); + buff.image.plane[plane] = (BYTE*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB) + PBO_OFFSET; + } + if(pbo) +@@ -3152,4 +3698,13 @@ + } + #endif + ++#ifdef HAVE_LIBXVBA ++void CLinuxRendererGL::AddProcessor(XVBA::CDecoder* xvba) ++{ ++ YUVBUFFER &buf = m_buffers[NextYV12Texture()]; ++ SAFE_RELEASE(buf.xvba_tmp); ++ buf.xvba_tmp = (XVBA::CDecoder*)xvba->Acquire(); ++} ++#endif ++ + #endif +diff -Naur xbmc-1fef727/xbmc/cores/VideoRenderers/LinuxRendererGL.h xbmc-1fef727.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.h +--- xbmc-1fef727/xbmc/cores/VideoRenderers/LinuxRendererGL.h 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/VideoRenderers/LinuxRendererGL.h 2012-02-07 14:30:18.013098470 +0100 +@@ -40,6 +40,7 @@ + namespace Shaders { class BaseYUV2RGBShader; } + namespace Shaders { class BaseVideoFilterShader; } + namespace VAAPI { struct CHolder; } ++namespace XVBA { class CDecoder; } + + #define NUM_BUFFERS 3 + +@@ -94,6 +95,7 @@ + RENDER_VDPAU=0x08, + RENDER_POT=0x10, + RENDER_VAAPI=0x20, ++ RENDER_XVBA=0x40, + }; + + enum RenderQuality +@@ -141,6 +143,7 @@ + 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 @@ + #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 @@ + 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 @@ + void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer + void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware + void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware ++ void RenderXVBA(int renderBuffer, int field); // render using xvba hardware + + CFrameBufferObject m_fbo; + +@@ -270,6 +285,10 @@ + #ifdef HAVE_LIBVA + VAAPI::CHolder& vaapi; + #endif ++#ifdef HAVE_LIBXVBA ++ XVBA::CDecoder* xvba; ++ XVBA::CDecoder* xvba_tmp; ++#endif + }; + + typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; +diff -Naur xbmc-1fef727/xbmc/cores/VideoRenderers/RenderFlags.h xbmc-1fef727.patch/xbmc/cores/VideoRenderers/RenderFlags.h +--- xbmc-1fef727/xbmc/cores/VideoRenderers/RenderFlags.h 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/VideoRenderers/RenderFlags.h 2012-02-07 14:30:18.013098470 +0100 +@@ -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 -Naur xbmc-1fef727/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-1fef727.patch/xbmc/cores/VideoRenderers/RenderManager.cpp +--- xbmc-1fef727/xbmc/cores/VideoRenderers/RenderManager.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/VideoRenderers/RenderManager.cpp 2012-02-07 14:30:18.014098490 +0100 +@@ -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 */ +@@ -777,6 +781,25 @@ + else if(pic.format == DVDVideoPicture::FMT_VAAPI) + m_pRenderer->AddProcessor(*pic.vaapi); + #endif ++#ifdef HAVE_LIBXVBA ++ else if(pic.format == DVDVideoPicture::FMT_XVBA) ++ { ++ if (pic.xvba) ++ { ++ m_pRenderer->AddProcessor(pic.xvba); ++ pic.xvba->Present(index); ++ } ++ } ++ else if(pic.format == DVDVideoPicture::FMT_XVBA_YV12) ++ { ++ if (pic.xvba) ++ { ++ m_pRenderer->AddProcessor(pic.xvba); ++ pic.xvba->Present(index); ++ pic.xvba->CopyYV12(index, image.plane[0]); ++ } ++ } ++#endif + m_pRenderer->ReleaseImage(index, false); + + return index; +diff -Naur xbmc-1fef727/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp xbmc-1fef727.patch/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp +--- xbmc-1fef727/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2012-02-07 12:46:52.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2012-02-07 14:30:18.015098509 +0100 +@@ -186,6 +186,8 @@ + m_defines += "#define XBMC_YUY2\n"; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_UYVY) + m_defines += "#define XBMC_UYVY\n"; ++ 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 -Naur xbmc-1fef727/xbmc/dialogs/GUIDialogCache.cpp xbmc-1fef727.patch/xbmc/dialogs/GUIDialogCache.cpp +--- xbmc-1fef727/xbmc/dialogs/GUIDialogCache.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/dialogs/GUIDialogCache.cpp 2012-02-07 14:30:18.032098844 +0100 +@@ -29,7 +29,7 @@ + #include "threads/SingleLock.h" + #include "utils/TimeUtils.h" + +-CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg) ++CGUIDialogCache::CGUIDialogCache(DWORD dwDelay, const CStdString& strHeader, const CStdString& strMsg) : CThread("CGUIDialogCache") + { + m_pDlg = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); + +diff -Naur xbmc-1fef727/xbmc/filesystem/FileCache.cpp xbmc-1fef727.patch/xbmc/filesystem/FileCache.cpp +--- xbmc-1fef727/xbmc/filesystem/FileCache.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/FileCache.cpp 2012-02-07 14:30:18.032098844 +0100 +@@ -79,7 +79,7 @@ + }; + + +-CFileCache::CFileCache() ++CFileCache::CFileCache() : CThread("CFileCache") + { + m_bDeleteCache = true; + m_nSeekResult = 0; +@@ -95,7 +95,7 @@ + m_cacheFull = false; + } + +-CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache) ++CFileCache::CFileCache(CCacheStrategy *pCache, bool bDeleteCache) : CThread("CFileCache") + { + m_pCache = pCache; + m_bDeleteCache = bDeleteCache; +diff -Naur xbmc-1fef727/xbmc/filesystem/FilePipe.cpp xbmc-1fef727.patch/xbmc/filesystem/FilePipe.cpp +--- xbmc-1fef727/xbmc/filesystem/FilePipe.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/FilePipe.cpp 2012-02-07 14:30:18.033098864 +0100 +@@ -24,6 +24,8 @@ + #include "PipesManager.h" + #include "utils/StringUtils.h" + ++#define INFINITE 0xFFFFFFFF ++ + using namespace XFILE; + + CFilePipe::CFilePipe() : m_pos(0), m_length(-1), m_pipe(NULL) +diff -Naur xbmc-1fef727/xbmc/filesystem/FileRar.cpp xbmc-1fef727.patch/xbmc/filesystem/FileRar.cpp +--- xbmc-1fef727/xbmc/filesystem/FileRar.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/FileRar.cpp 2012-02-07 14:30:18.033098864 +0100 +@@ -43,7 +43,7 @@ + #define SEEKTIMOUT 30000 + + #ifdef HAS_FILESYSTEM_RAR +-CFileRarExtractThread::CFileRarExtractThread() : hRunning(true), hQuit(true) ++CFileRarExtractThread::CFileRarExtractThread() : CThread("CFileRarExtractThread"), hRunning(true), hQuit(true) + { + m_pArc = NULL; + m_pCmd = NULL; +diff -Naur xbmc-1fef727/xbmc/filesystem/HTSPDirectory.cpp xbmc-1fef727.patch/xbmc/filesystem/HTSPDirectory.cpp +--- xbmc-1fef727/xbmc/filesystem/HTSPDirectory.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/HTSPDirectory.cpp 2012-02-07 14:30:18.034098884 +0100 +@@ -76,7 +76,7 @@ + static CCriticalSection g_section; + + +-CHTSPDirectorySession::CHTSPDirectorySession() ++CHTSPDirectorySession::CHTSPDirectorySession() : CThread("CHTSPDirectorySession") + { + } + +diff -Naur xbmc-1fef727/xbmc/filesystem/LastFMDirectory.cpp xbmc-1fef727.patch/xbmc/filesystem/LastFMDirectory.cpp +--- xbmc-1fef727/xbmc/filesystem/LastFMDirectory.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/LastFMDirectory.cpp 2012-02-07 14:30:18.035098904 +0100 +@@ -69,7 +69,7 @@ + m_dlgProgress->Progress(); + } + +- CThread thread(this); ++ CThread thread(this, "CLastFMDirectory"); + m_strSource = url; + m_strDestination = "special://temp/lastfm.xml"; + thread.Create(); +diff -Naur xbmc-1fef727/xbmc/filesystem/MythSession.cpp xbmc-1fef727.patch/xbmc/filesystem/MythSession.cpp +--- xbmc-1fef727/xbmc/filesystem/MythSession.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/MythSession.cpp 2012-02-07 14:30:18.035098904 +0100 +@@ -359,7 +359,7 @@ + return; + } + +-CMythSession::CMythSession(const CURL& url) ++CMythSession::CMythSession(const CURL& url) : CThread("CMythSession") + { + m_control = NULL; + m_event = NULL; +diff -Naur xbmc-1fef727/xbmc/filesystem/PipesManager.cpp xbmc-1fef727.patch/xbmc/filesystem/PipesManager.cpp +--- xbmc-1fef727/xbmc/filesystem/PipesManager.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/PipesManager.cpp 2012-02-07 14:30:18.036098923 +0100 +@@ -23,6 +23,8 @@ + #include "threads/SingleLock.h" + #include "Application.h" + ++#define INFINITE 0xFFFFFFFF ++ + #ifndef min + #define min(a,b) ((a) < (b) ? (a) : (b)) + #endif +diff -Naur xbmc-1fef727/xbmc/filesystem/RarManager.h xbmc-1fef727.patch/xbmc/filesystem/RarManager.h +--- xbmc-1fef727/xbmc/filesystem/RarManager.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/RarManager.h 2012-02-07 14:30:18.037098942 +0100 +@@ -71,7 +71,7 @@ + CRarManager(); + ~CRarManager(); + bool CacheRarredFile(CStdString& strPathInCache, const CStdString& strRarPath, +- const CStdString& strPathInRar, BYTE bOptions = EXFILE_AUTODELETE, ++ const CStdString& strPathInRar, uint8_t bOptions = EXFILE_AUTODELETE, + const CStdString& strDir =RAR_DEFAULT_CACHE, const int64_t iSize=-1); + bool GetPathInCache(CStdString& strPathInCache, const CStdString& strRarPath, + const CStdString& strPathInRar = ""); +diff -Naur xbmc-1fef727/xbmc/filesystem/SAPDirectory.cpp xbmc-1fef727.patch/xbmc/filesystem/SAPDirectory.cpp +--- xbmc-1fef727/xbmc/filesystem/SAPDirectory.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/filesystem/SAPDirectory.cpp 2012-02-07 14:30:18.037098942 +0100 +@@ -272,7 +272,7 @@ + using namespace SDP; + + +-CSAPSessions::CSAPSessions() ++CSAPSessions::CSAPSessions() : CThread("CSAPSessions") + { + m_socket = INVALID_SOCKET; + } +@@ -486,7 +486,7 @@ + + CSingleLock lock(g_sapsessions.m_section); + +- if(g_sapsessions.ThreadHandle() == NULL) ++ if(!g_sapsessions.IsRunning()) + g_sapsessions.Create(); + + // check if we can find this session in our cache +diff -Naur xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp +--- xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.cpp 2012-02-07 14:30:18.039098982 +0100 +@@ -181,9 +181,9 @@ + m_threadState = state; + } + +-void CGUIPythonWindow::WaitForActionEvent(unsigned int timeout) ++void CGUIPythonWindow::WaitForActionEvent() + { +- g_pythonParser.WaitForEvent(m_actionEvent, timeout); ++ g_pythonParser.WaitForEvent(m_actionEvent); + m_actionEvent.Reset(); + } + +diff -Naur xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h +--- xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindow.h 2012-02-07 14:30:18.040099002 +0100 +@@ -51,7 +51,7 @@ + virtual bool OnAction(const CAction &action); + virtual bool OnBack(int actionID); + void SetCallbackWindow(void* state, void *object); +- void WaitForActionEvent(unsigned int timeout); ++ void WaitForActionEvent(); + void PulseActionEvent(); + void SetDestroyAfterDeinit(bool destroy = true); + protected: +diff -Naur xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp +--- xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.cpp 2012-02-07 14:30:18.041099022 +0100 +@@ -279,9 +279,9 @@ + UpdateButtons(); + } + +-void CGUIPythonWindowXML::WaitForActionEvent(unsigned int timeout) ++void CGUIPythonWindowXML::WaitForActionEvent() + { +- g_pythonParser.WaitForEvent(m_actionEvent, timeout); ++ g_pythonParser.WaitForEvent(m_actionEvent); + m_actionEvent.Reset(); + } + +diff -Naur xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h +--- xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXML.h 2012-02-07 14:30:18.041099022 +0100 +@@ -40,7 +40,7 @@ + virtual void AllocResources(bool forceLoad = false); + virtual void FreeResources(bool forceUnLoad = false); + void Process(unsigned int currentTime, CDirtyRegionList ®ions); +- void WaitForActionEvent(unsigned int timeout); ++ void WaitForActionEvent(); + void PulseActionEvent(); + void AddItem(CFileItemPtr fileItem,int itemPosition); + void RemoveItem(int itemPosition); +diff -Naur xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/window.cpp xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/window.cpp +--- xbmc-1fef727/xbmc/interfaces/python/xbmcmodule/window.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/xbmcmodule/window.cpp 2012-02-07 14:30:18.042099042 +0100 +@@ -540,11 +540,11 @@ + + CPyThreadState pyState; + if (WindowXML_Check(self)) +- ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent(INFINITE); ++ ((CGUIPythonWindowXML*)self->pWindow)->WaitForActionEvent(); + else if (WindowXMLDialog_Check(self)) +- ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent(INFINITE); ++ ((CGUIPythonWindowXMLDialog*)self->pWindow)->WaitForActionEvent(); + else +- ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent(INFINITE); ++ ((CGUIPythonWindow*)self->pWindow)->WaitForActionEvent(); + } + } + Py_INCREF(Py_None); +diff -Naur xbmc-1fef727/xbmc/interfaces/python/XBPython.cpp xbmc-1fef727.patch/xbmc/interfaces/python/XBPython.cpp +--- xbmc-1fef727/xbmc/interfaces/python/XBPython.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/XBPython.cpp 2012-02-07 14:30:18.038098962 +0100 +@@ -676,11 +676,11 @@ + m_globalEvent.Set(); + } + +-void XBPython::WaitForEvent(CEvent& hEvent, unsigned int timeout) ++void XBPython::WaitForEvent(CEvent& hEvent) + { + // wait for either this event our our global event + XbmcThreads::CEventGroup eventGroup(&hEvent, &m_globalEvent, NULL); +- eventGroup.wait(timeout); ++ eventGroup.wait(); + m_globalEvent.Reset(); + } + +diff -Naur xbmc-1fef727/xbmc/interfaces/python/XBPython.h xbmc-1fef727.patch/xbmc/interfaces/python/XBPython.h +--- xbmc-1fef727/xbmc/interfaces/python/XBPython.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/interfaces/python/XBPython.h 2012-02-07 14:30:18.039098982 +0100 +@@ -61,7 +61,7 @@ + void Process(); + + void PulseGlobalEvent(); +- void WaitForEvent(CEvent& hEvent, unsigned int timeout); ++ void WaitForEvent(CEvent& hEvent); + + int ScriptsSize(); + int GetPythonScriptId(int scriptPosition); +diff -Naur xbmc-1fef727/xbmc/linux/Makefile.in xbmc-1fef727.patch/xbmc/linux/Makefile.in +--- xbmc-1fef727/xbmc/linux/Makefile.in 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/Makefile.in 2012-02-07 14:30:18.043099062 +0100 +@@ -10,14 +10,11 @@ + LinuxResourceCounter.cpp \ + LinuxTimezone.cpp \ + PosixMountProvider.cpp \ +- XEventUtils.cpp \ + XFileUtils.cpp \ + XHandle.cpp \ + XLCDproc.cpp \ + XMemUtils.cpp \ +- XSyncUtils.cpp \ + XTimeUtils.cpp \ +- XThreadUtils.cpp \ + + LIB=linux.a + +diff -Naur xbmc-1fef727/xbmc/linux/PlatformDefs.h xbmc-1fef727.patch/xbmc/linux/PlatformDefs.h +--- xbmc-1fef727/xbmc/linux/PlatformDefs.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/PlatformDefs.h 2012-02-07 14:30:18.044099082 +0100 +@@ -182,8 +182,6 @@ + #define EXCEPTION_EXECUTE_HANDLER ... + //NOTE: dont try to define __except because it breaks g++ (already uses it). + +-typedef pthread_t ThreadIdentifier; +- + struct CXHandle; // forward declaration + typedef CXHandle* HANDLE; + +diff -Naur xbmc-1fef727/xbmc/linux/PlatformInclude.h xbmc-1fef727.patch/xbmc/linux/PlatformInclude.h +--- xbmc-1fef727/xbmc/linux/PlatformInclude.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/PlatformInclude.h 2012-02-07 14:30:18.044099082 +0100 +@@ -25,10 +25,7 @@ + #include "PlatformDefs.h" + #include "XHandlePublic.h" + #include "XFileUtils.h" +-#include "XSyncUtils.h" +-#include "XEventUtils.h" + #include "XTimeUtils.h" +-#include "XThreadUtils.h" + #include "XMemUtils.h" + #include "ConvUtils.h" + +diff -Naur xbmc-1fef727/xbmc/linux/XEventUtils.cpp xbmc-1fef727.patch/xbmc/linux/XEventUtils.cpp +--- xbmc-1fef727/xbmc/linux/XEventUtils.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XEventUtils.cpp 1970-01-01 01:00:00.000000000 +0100 +@@ -1,144 +0,0 @@ +-/* +- * Copyright (C) 2005-2008 Team XBMC +- * http://www.xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, write to +- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +- * http://www.gnu.org/copyleft/gpl.html +- * +- */ +- +-#include "system.h" +-#include "PlatformDefs.h" +-#include "XEventUtils.h" +-#include "XHandle.h" +-#include "utils/log.h" +-#include "threads/SingleLock.h" +- +-using namespace std; +- +-HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName) +-{ +- CXHandle *pHandle = new CXHandle(CXHandle::HND_EVENT); +- pHandle->m_bManualEvent = bManualReset; +- pHandle->m_hCond = new XbmcThreads::ConditionVariable(); +- pHandle->m_hMutex = new CCriticalSection(); +- pHandle->m_bEventSet = false; +- +- if (bInitialState) +- SetEvent(pHandle); +- +- return pHandle; +-} +- +-// +-// The state of a manual-reset event object remains signaled until it is set explicitly to the nonsignaled +-// state by the ResetEvent function. Any number of waiting threads, or threads that subsequently begin wait +-// operations for the specified event object by calling one of the wait functions, can be released while the +-// object's state is signaled. +-// +-// The state of an auto-reset event object remains signaled until a single waiting thread is released, at +-// which time the system automatically sets the state to nonsignaled. If no threads are waiting, the event +-// object's state remains signaled. +-// +-bool WINAPI SetEvent(HANDLE hEvent) +-{ +- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL) +- return false; +- +- CSingleLock lock(*(hEvent->m_hMutex)); +- hEvent->m_bEventSet = true; +- +- // we must guarantee that these handle's won't be deleted, until we are done +- list events = hEvent->m_hParents; +- for(list::iterator it = events.begin();it != events.end();it++) +- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS); +- +- lock.Leave(); +- +- for(list::iterator it = events.begin();it != events.end();it++) +- { +- SetEvent(*it); +- CloseHandle(*it); +- } +- +- DuplicateHandle(GetCurrentProcess(), hEvent, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS); +- +- if (hEvent->m_bManualEvent == true) +- hEvent->m_hCond->notifyAll(); +- else +- hEvent->m_hCond->notify(); +- +- CloseHandle(hEvent); +- +- return true; +-} +- +-bool WINAPI ResetEvent(HANDLE hEvent) +-{ +- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL) +- return false; +- +- CSingleLock lock(*(hEvent->m_hMutex)); +- hEvent->m_bEventSet = false; +- +- return true; +-} +- +-bool WINAPI PulseEvent(HANDLE hEvent) +-{ +- if (hEvent == NULL || hEvent->m_hCond == NULL || hEvent->m_hMutex == NULL) +- return false; +- +- CSingleLock lock(*(hEvent->m_hMutex)); +- // we must guarantee that these handle's won't be deleted, until we are done +- list events = hEvent->m_hParents; +- for(list::iterator it = events.begin();it != events.end();it++) +- DuplicateHandle(GetCurrentProcess(), *it, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS); +- +- if(events.size()) +- { +- CLog::Log(LOGWARNING,"PulseEvent - ineffecient multiwait detected"); +- hEvent->m_bEventSet = true; +- } +- +- lock.Leave(); +- +- for(list::iterator it = events.begin();it != events.end();it++) +- { +- SetEvent(*it); +- CloseHandle(*it); +- +- if (hEvent->m_bManualEvent == false) +- break; +- } +- +- // for multiwaits, we must yield some time to get the multiwaits to notice it was signaled +- if(events.size()) +- Sleep(10); +- +- // we should always unset the event on pulse +- { +- CSingleLock lock2(*(hEvent->m_hMutex)); +- hEvent->m_bEventSet = false; +- } +- +- if (hEvent->m_bManualEvent == true) +- hEvent->m_hCond->notifyAll(); +- else +- hEvent->m_hCond->notify(); +- +- return true; +-} +- +diff -Naur xbmc-1fef727/xbmc/linux/XEventUtils.h xbmc-1fef727.patch/xbmc/linux/XEventUtils.h +--- xbmc-1fef727/xbmc/linux/XEventUtils.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XEventUtils.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,38 +0,0 @@ +-#ifndef __X_EVENT_UTIL_H__ +-#define __X_EVENT_UTIL_H__ +- +-/* +- * Copyright (C) 2005-2008 Team XBMC +- * http://www.xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, write to +- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +- * http://www.gnu.org/copyleft/gpl.html +- * +- */ +- +-#include "XHandlePublic.h" +- +-#ifdef _LINUX +- +-HANDLE WINAPI CreateEvent(void *pDummySec, bool bManualReset, bool bInitialState, char *szDummyName); +-bool WINAPI SetEvent(HANDLE hEvent); +-bool WINAPI ResetEvent(HANDLE hEvent); +-bool WINAPI PulseEvent(HANDLE hEvent); +- +-#endif +- +- +-#endif +- +diff -Naur xbmc-1fef727/xbmc/linux/XHandle.cpp xbmc-1fef727.patch/xbmc/linux/XHandle.cpp +--- xbmc-1fef727/xbmc/linux/XHandle.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XHandle.cpp 2012-02-07 14:30:18.051099219 +0100 +@@ -20,12 +20,15 @@ + */ + + #include "XHandle.h" +-#include "XThreadUtils.h" + #include "utils/log.h" + #include "threads/SingleLock.h" + + int CXHandle::m_objectTracker[10] = {0}; + ++HANDLE WINAPI GetCurrentProcess(void) { ++ return (HANDLE)-1; // -1 a special value - pseudo handle ++} ++ + CXHandle::CXHandle() + { + Init(); +@@ -47,11 +50,6 @@ + + Init(); + +- if (m_threadValid) +- { +- CLog::Log(LOGERROR, "%s - thread handle copied instead of passed!", __FUNCTION__); +- } +- + if (src.m_hMutex) + m_hMutex = new CCriticalSection(); + +@@ -80,7 +78,7 @@ + CLog::Log(LOGERROR,"%s, destroying handle with ref count %d", __FUNCTION__, m_nRefCount); + assert(false); + } +- ++ + if (m_hMutex) { + delete m_hMutex; + } +@@ -93,10 +91,6 @@ + delete m_hCond; + } + +- if (m_threadValid) { +- pthread_join(m_hThread, NULL); +- } +- + if ( fd != 0 ) { + close(fd); + } +@@ -107,11 +101,9 @@ + { + fd=0; + m_hMutex=NULL; +- m_threadValid=false; + m_hCond=NULL; + m_type = HND_NULL; + RecursionCount=0; +- OwningThread=0; + m_bManualEvent=FALSE; + m_bEventSet=FALSE; + m_nFindFileIterator=0 ; +diff -Naur xbmc-1fef727/xbmc/linux/XHandle.h xbmc-1fef727.patch/xbmc/linux/XHandle.h +--- xbmc-1fef727/xbmc/linux/XHandle.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XHandle.h 2012-02-07 14:30:18.051099219 +0100 +@@ -25,7 +25,6 @@ + #ifndef _WIN32 + + #include +-#include + + #include "PlatformDefs.h" + #include "XHandlePublic.h" +@@ -36,7 +35,7 @@ + struct CXHandle { + + public: +- typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_THREAD, HND_FIND_FILE } HandleType; ++ typedef enum { HND_NULL = 0, HND_FILE, HND_EVENT, HND_MUTEX, HND_FIND_FILE } HandleType; + + CXHandle(); + CXHandle(HandleType nType); +@@ -47,8 +46,6 @@ + inline HandleType GetType() { return m_type; } + void ChangeType(HandleType newType); + +- ThreadIdentifier m_hThread; +- bool m_threadValid; + XbmcThreads::ConditionVariable *m_hCond; + std::list m_hParents; + +@@ -62,7 +59,6 @@ + // simulate mutex and critical section + CCriticalSection *m_hMutex; + int RecursionCount; // for mutex - for compatibility with WIN32 critical section +- pthread_t OwningThread; + int fd; + bool m_bManualEvent; + time_t m_tmCreation; +diff -Naur xbmc-1fef727/xbmc/linux/XMemUtils.cpp xbmc-1fef727.patch/xbmc/linux/XMemUtils.cpp +--- xbmc-1fef727/xbmc/linux/XMemUtils.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XMemUtils.cpp 2012-02-07 14:30:18.052099238 +0100 +@@ -25,6 +25,10 @@ + + #include "XMemUtils.h" + ++#ifdef __APPLE__ ++#include ++#endif ++ + #undef ALIGN + #define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1)) + +@@ -49,4 +53,130 @@ + free(pFull); + } + ++#ifndef _WIN32 ++ ++#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__) ++static FILE* procMeminfoFP = NULL; ++#endif ++ ++void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer) ++{ ++ if (!lpBuffer) ++ return; ++ ++ memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX)); ++ ++#ifdef __APPLE__ ++ uint64_t physmem; ++ size_t len = sizeof physmem; ++ int mib[2] = { CTL_HW, HW_MEMSIZE }; ++ size_t miblen = sizeof(mib) / sizeof(mib[0]); ++ ++ // Total physical memory. ++ if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem)) ++ lpBuffer->ullTotalPhys = physmem; ++ ++ // Virtual memory. ++ mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE; ++ struct xsw_usage swap; ++ len = sizeof(struct xsw_usage); ++ if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0) ++ { ++ lpBuffer->ullAvailPageFile = swap.xsu_avail; ++ lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total; ++ } ++ ++ // In use. ++ mach_port_t stat_port = mach_host_self(); ++ vm_statistics_data_t vm_stat; ++ mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t); ++ if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0) ++ { ++ // Find page size. ++ int pageSize; ++ mib[0] = CTL_HW; mib[1] = HW_PAGESIZE; ++ len = sizeof(int); ++ if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0) ++ { ++ uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize; ++ ++ lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used; ++ lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME. ++ } ++ } ++#elif defined(__FreeBSD__) ++ /* sysctl hw.physmem */ ++ size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0; ++ size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0; ++ ++ /* physmem */ ++ len = sizeof(physmem); ++ if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) { ++ lpBuffer->ullTotalPhys = physmem; ++ lpBuffer->ullTotalVirtual = physmem; ++ } ++ /* pagesize */ ++ len = sizeof(pagesize); ++ if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0) ++ pagesize = 4096; ++ /* mem_inactive */ ++ len = sizeof(mem_inactive); ++ if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0) ++ mem_inactive *= pagesize; ++ /* mem_cache */ ++ len = sizeof(mem_cache); ++ if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0) ++ mem_cache *= pagesize; ++ /* mem_free */ ++ len = sizeof(mem_free); ++ if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0) ++ mem_free *= pagesize; ++ ++ /* mem_avail = mem_inactive + mem_cache + mem_free */ ++ lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free; ++ lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free; ++ ++ if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0) ++ lpBuffer->ullAvailPageFile = swap_free * pagesize; ++#else ++ struct sysinfo info; ++ char name[32]; ++ unsigned val; ++ if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL) ++ sysinfo(&info); ++ else ++ { ++ memset(&info, 0, sizeof(struct sysinfo)); ++ info.mem_unit = 4096; ++ while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF) ++ { ++ if (strncmp("MemTotal:", name, 9) == 0) ++ info.totalram = val/4; ++ else if (strncmp("MemFree:", name, 8) == 0) ++ info.freeram = val/4; ++ else if (strncmp("Buffers:", name, 8) == 0) ++ info.bufferram += val/4; ++ else if (strncmp("Cached:", name, 7) == 0) ++ info.bufferram += val/4; ++ else if (strncmp("SwapTotal:", name, 10) == 0) ++ info.totalswap = val/4; ++ else if (strncmp("SwapFree:", name, 9) == 0) ++ info.freeswap = val/4; ++ else if (strncmp("HighTotal:", name, 10) == 0) ++ info.totalhigh = val/4; ++ else if (strncmp("HighFree:", name, 9) == 0) ++ info.freehigh = val/4; ++ } ++ rewind(procMeminfoFP); ++ fflush(procMeminfoFP); ++ } ++ lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit); ++ lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit); ++ lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit); ++ lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit); ++ lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit); ++#endif ++} ++ ++#endif + +diff -Naur xbmc-1fef727/xbmc/linux/XMemUtils.h xbmc-1fef727.patch/xbmc/linux/XMemUtils.h +--- xbmc-1fef727/xbmc/linux/XMemUtils.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XMemUtils.h 2012-02-07 14:30:18.053099258 +0100 +@@ -22,10 +22,14 @@ + * + */ + ++#include "linux/PlatformDefs.h" ++ + // aligned memory allocation and free. memory returned will be aligned to "alignTo" bytes. + // this is a linux (actually platfom free) implementation of the win32 CRT methods _aligned_malloc and _aligned_free. + void *_aligned_malloc(size_t s, size_t alignTo); + void _aligned_free(void *p) ; + ++void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer); ++ + #endif + +diff -Naur xbmc-1fef727/xbmc/linux/XSyncUtils.cpp xbmc-1fef727.patch/xbmc/linux/XSyncUtils.cpp +--- xbmc-1fef727/xbmc/linux/XSyncUtils.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XSyncUtils.cpp 1970-01-01 01:00:00.000000000 +0100 +@@ -1,169 +0,0 @@ +-/* +- * Copyright (C) 2005-2008 Team XBMC +- * http://www.xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, write to +- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +- * http://www.gnu.org/copyleft/gpl.html +- * +- */ +- +-#ifndef _WIN32 +- +- +-#include +-#include +-#include +-#include +-#include +-#ifdef __APPLE__ +-#include +-#endif +- +-#include "XSyncUtils.h" +-#include "XTimeUtils.h" +-#include "PlatformDefs.h" +-#include "XHandle.h" +-#include "XEventUtils.h" +- +-using namespace std; +-using namespace XbmcThreads; +- +-#include "../utils/log.h" +-#include "../utils/TimeUtils.h" +- +-#if defined(_LINUX) && !defined(__APPLE__) && !defined(__FreeBSD__) +-static FILE* procMeminfoFP = NULL; +-#endif +- +-void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer) +-{ +- if (!lpBuffer) +- return; +- +- memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX)); +- +-#ifdef __APPLE__ +- uint64_t physmem; +- size_t len = sizeof physmem; +- int mib[2] = { CTL_HW, HW_MEMSIZE }; +- size_t miblen = sizeof(mib) / sizeof(mib[0]); +- +- // Total physical memory. +- if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem)) +- lpBuffer->ullTotalPhys = physmem; +- +- // Virtual memory. +- mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE; +- struct xsw_usage swap; +- len = sizeof(struct xsw_usage); +- if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0) +- { +- lpBuffer->ullAvailPageFile = swap.xsu_avail; +- lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total; +- } +- +- // In use. +- mach_port_t stat_port = mach_host_self(); +- vm_statistics_data_t vm_stat; +- mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t); +- if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0) +- { +- // Find page size. +- int pageSize; +- mib[0] = CTL_HW; mib[1] = HW_PAGESIZE; +- len = sizeof(int); +- if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0) +- { +- uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize; +- +- lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used; +- lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME. +- } +- } +-#elif defined(__FreeBSD__) +- /* sysctl hw.physmem */ +- size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0; +- size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0; +- +- /* physmem */ +- len = sizeof(physmem); +- if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) { +- lpBuffer->ullTotalPhys = physmem; +- lpBuffer->ullTotalVirtual = physmem; +- } +- /* pagesize */ +- len = sizeof(pagesize); +- if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0) +- pagesize = 4096; +- /* mem_inactive */ +- len = sizeof(mem_inactive); +- if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0) +- mem_inactive *= pagesize; +- /* mem_cache */ +- len = sizeof(mem_cache); +- if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0) +- mem_cache *= pagesize; +- /* mem_free */ +- len = sizeof(mem_free); +- if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0) +- mem_free *= pagesize; +- +- /* mem_avail = mem_inactive + mem_cache + mem_free */ +- lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free; +- lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free; +- +- if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0) +- lpBuffer->ullAvailPageFile = swap_free * pagesize; +-#else +- struct sysinfo info; +- char name[32]; +- unsigned val; +- if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL) +- sysinfo(&info); +- else +- { +- memset(&info, 0, sizeof(struct sysinfo)); +- info.mem_unit = 4096; +- while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF) +- { +- if (strncmp("MemTotal:", name, 9) == 0) +- info.totalram = val/4; +- else if (strncmp("MemFree:", name, 8) == 0) +- info.freeram = val/4; +- else if (strncmp("Buffers:", name, 8) == 0) +- info.bufferram += val/4; +- else if (strncmp("Cached:", name, 7) == 0) +- info.bufferram += val/4; +- else if (strncmp("SwapTotal:", name, 10) == 0) +- info.totalswap = val/4; +- else if (strncmp("SwapFree:", name, 9) == 0) +- info.freeswap = val/4; +- else if (strncmp("HighTotal:", name, 10) == 0) +- info.totalhigh = val/4; +- else if (strncmp("HighFree:", name, 9) == 0) +- info.freehigh = val/4; +- } +- rewind(procMeminfoFP); +- fflush(procMeminfoFP); +- } +- lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit); +- lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit); +- lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit); +- lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit); +- lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit); +-#endif +-} +- +-#endif +diff -Naur xbmc-1fef727/xbmc/linux/XSyncUtils.h xbmc-1fef727.patch/xbmc/linux/XSyncUtils.h +--- xbmc-1fef727/xbmc/linux/XSyncUtils.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XSyncUtils.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,44 +0,0 @@ +-#ifndef __X_SYNC_UTILS_ +-#define __X_SYNC_UTILS_ +- +-/* +- * Copyright (C) 2005-2008 Team XBMC +- * http://www.xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, write to +- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +- * http://www.gnu.org/copyleft/gpl.html +- * +- */ +- +-#include "PlatformDefs.h" +-#include "XHandlePublic.h" +- +-#ifdef _LINUX +- +-#define STATUS_WAIT_0 ((DWORD )0x00000000L) +-#define WAIT_FAILED ((DWORD)0xFFFFFFFF) +-#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 ) +-#define WAIT_TIMEOUT 258L +-#define INFINITE 0xFFFFFFFF +-#define STATUS_ABANDONED_WAIT_0 0x00000080 +-#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 ) +-#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 ) +- +-void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer); +- +-#endif +- +-#endif +- +diff -Naur xbmc-1fef727/xbmc/linux/XThreadUtils.cpp xbmc-1fef727.patch/xbmc/linux/XThreadUtils.cpp +--- xbmc-1fef727/xbmc/linux/XThreadUtils.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/linux/XThreadUtils.cpp 1970-01-01 01:00:00.000000000 +0100 +@@ -1,210 +0,0 @@ +-/* +- * Copyright (C) 2005-2009 Team XBMC +- * http://www.xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, write to +- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +- * http://www.gnu.org/copyleft/gpl.html +- * +- */ +- +-#include "PlatformDefs.h" +-#include "XHandle.h" +-#include "XThreadUtils.h" +-#include "XTimeUtils.h" +-#include "XEventUtils.h" +-#include "system.h" +-#include "utils/log.h" +- +-#ifdef _LINUX +-#include +-#include +-#include +- +-HANDLE WINAPI CreateThread( +- LPSECURITY_ATTRIBUTES lpThreadAttributes, +- SIZE_T dwStackSize, +- LPTHREAD_START_ROUTINE lpStartAddress, +- LPVOID lpParameter, +- DWORD dwCreationFlags, +- LPDWORD lpThreadId +- ) { +- +- // a thread handle would actually contain an event +- // the event would mark if the thread is running or not. it will be used in the Wait functions. +- HANDLE h = CreateEvent(NULL, TRUE, FALSE, NULL); +- h->ChangeType(CXHandle::HND_THREAD); +-#ifdef __APPLE__ +- h->m_machThreadPort = MACH_PORT_NULL; +-#endif +- pthread_attr_t attr; +- pthread_attr_init(&attr); +- if (dwStackSize > PTHREAD_STACK_MIN) +- pthread_attr_setstacksize(&attr, dwStackSize); +- if (pthread_create(&(h->m_hThread), &attr, (void*(*)(void*))lpStartAddress, lpParameter) == 0) +- h->m_threadValid = true; +- else +- { +- CloseHandle(h); +- h = NULL; +- } +- pthread_attr_destroy(&attr); +- +- if (h && lpThreadId) +- // WARNING: This can truncate thread IDs on x86_64. +- *lpThreadId = (DWORD)h->m_hThread; +- return h; +-} +- +- +-#if 0 // Deprecated, use CThread::GetCurrentThreadId() instead +-DWORD WINAPI GetCurrentThreadId(void) { +- // WARNING: This can truncate thread IDs on x86_64. +- return (DWORD)pthread_self(); +-} +-#endif +- +-HANDLE WINAPI GetCurrentThread(void) { +- return (HANDLE)-1; // -1 a special value - pseudo handle +-} +- +-HANDLE WINAPI GetCurrentProcess(void) { +- return (HANDLE)-1; // -1 a special value - pseudo handle +-} +- +-HANDLE _beginthreadex( +- void *security, +- unsigned stack_size, +- int ( *start_address )( void * ), +- void *arglist, +- unsigned initflag, +- unsigned *thrdaddr +-) { +- +- HANDLE h = CreateThread(NULL, stack_size, start_address, arglist, initflag, (LPDWORD)thrdaddr); +- return h; +- +-} +- +-uintptr_t _beginthread( +- void( *start_address )( void * ), +- unsigned stack_size, +- void *arglist +-) { +- HANDLE h = CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)start_address, arglist, 0, NULL); +- return (uintptr_t)h; +-} +- +-BOOL WINAPI GetThreadTimes ( +- HANDLE hThread, +- LPFILETIME lpCreationTime, +- LPFILETIME lpExitTime, +- LPFILETIME lpKernelTime, +- LPFILETIME lpUserTime +-) { +- if (!hThread) +- return false; +- if (!hThread->m_threadValid) +- return false; +- +- if (hThread == (HANDLE)-1) { +- if (lpCreationTime) +- TimeTToFileTime(0,lpCreationTime); +- if (lpExitTime) +- TimeTToFileTime(time(NULL),lpExitTime); +- if (lpKernelTime) +- TimeTToFileTime(0,lpKernelTime); +- if (lpUserTime) +- TimeTToFileTime(0,lpUserTime); +- +- return true; +- } +- +- if (lpCreationTime) +- TimeTToFileTime(hThread->m_tmCreation,lpCreationTime); +- if (lpExitTime) +- TimeTToFileTime(time(NULL),lpExitTime); +- if (lpKernelTime) +- TimeTToFileTime(0,lpKernelTime); +- +-#ifdef __APPLE__ +- thread_info_data_t threadInfo; +- mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX; +- +- if (hThread->m_machThreadPort == MACH_PORT_NULL) +- hThread->m_machThreadPort = pthread_mach_thread_np(hThread->m_hThread); +- +- kern_return_t ret = thread_info(hThread->m_machThreadPort, THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount); +- if (ret == KERN_SUCCESS) +- { +- thread_basic_info_t threadBasicInfo = (thread_basic_info_t)threadInfo; +- +- if (lpUserTime) +- { +- // User time. +- unsigned long long time = ((__int64)threadBasicInfo->user_time.seconds * 10000000L) + threadBasicInfo->user_time.microseconds*10L; +- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF); +- lpUserTime->dwHighDateTime = (time >> 32); +- } +- +- if (lpKernelTime) +- { +- // System time. +- unsigned long long time = ((__int64)threadBasicInfo->system_time.seconds * 10000000L) + threadBasicInfo->system_time.microseconds*10L; +- lpKernelTime->dwLowDateTime = (time & 0xFFFFFFFF); +- lpKernelTime->dwHighDateTime = (time >> 32); +- } +- } +- else +- { +- if (lpUserTime) +- lpUserTime->dwLowDateTime = lpUserTime->dwHighDateTime = 0; +- +- if (lpKernelTime) +- lpKernelTime->dwLowDateTime = lpKernelTime->dwHighDateTime = 0; +- } +-#elif _POSIX_THREAD_CPUTIME != -1 +- if(lpUserTime) +- { +- lpUserTime->dwLowDateTime = 0; +- lpUserTime->dwHighDateTime = 0; +- clockid_t clock; +- if (pthread_getcpuclockid(hThread->m_hThread, &clock) == 0) +- { +- struct timespec tp = {}; +- clock_gettime(clock, &tp); +- unsigned long long time = (unsigned long long)tp.tv_sec * 10000000 + (unsigned long long)tp.tv_nsec/100; +- lpUserTime->dwLowDateTime = (time & 0xFFFFFFFF); +- lpUserTime->dwHighDateTime = (time >> 32); +- } +- } +-#else +- if (lpUserTime) +- TimeTToFileTime(0,lpUserTime); +-#endif +- return true; +-} +- +-BOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority) +-{ +- return true; +-} +- +-int GetThreadPriority(HANDLE hThread) +-{ +- return 0; +-} +- +-#endif +- +diff -Naur xbmc-1fef727/xbmc/music/infoscanner/MusicInfoScanner.cpp xbmc-1fef727.patch/xbmc/music/infoscanner/MusicInfoScanner.cpp +--- xbmc-1fef727/xbmc/music/infoscanner/MusicInfoScanner.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/music/infoscanner/MusicInfoScanner.cpp 2012-02-07 14:30:18.056099318 +0100 +@@ -57,7 +57,7 @@ + using namespace XFILE; + using namespace MUSIC_GRABBER; + +-CMusicInfoScanner::CMusicInfoScanner() ++CMusicInfoScanner::CMusicInfoScanner() : CThread("CMusicInfoScanner") + { + m_bRunning = false; + m_pObserver = NULL; +@@ -99,7 +99,7 @@ + + // Create the thread to count all files to be scanned + SetPriority( GetMinPriority() ); +- CThread fileCountReader(this); ++ CThread fileCountReader(this, "CMusicInfoScanner"); + if (m_pObserver) + fileCountReader.Create(); + +diff -Naur xbmc-1fef727/xbmc/music/infoscanner/MusicInfoScraper.cpp xbmc-1fef727.patch/xbmc/music/infoscanner/MusicInfoScraper.cpp +--- xbmc-1fef727/xbmc/music/infoscanner/MusicInfoScraper.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/music/infoscanner/MusicInfoScraper.cpp 2012-02-07 14:30:18.057099338 +0100 +@@ -28,7 +28,7 @@ + using namespace ADDON; + using namespace std; + +-CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper) ++CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper) : CThread("CMusicInfoScraper") + { + m_bSucceeded=false; + m_bCanceled=false; +diff -Naur xbmc-1fef727/xbmc/music/LastFmManager.cpp xbmc-1fef727.patch/xbmc/music/LastFmManager.cpp +--- xbmc-1fef727/xbmc/music/LastFmManager.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/music/LastFmManager.cpp 2012-02-07 14:30:18.055099298 +0100 +@@ -70,7 +70,7 @@ + + CLastFmManager* CLastFmManager::m_pInstance=NULL; + +-CLastFmManager::CLastFmManager() ++CLastFmManager::CLastFmManager() : CThread("CLastFmManager") + { + m_RadioTrackQueue = new CPlayList; + } +@@ -534,7 +534,7 @@ + if (iNrCachedTracks == 0) + { + //get more tracks +- if (ThreadHandle() != NULL) ++ if (IsRunning()) + { + m_hWorkerEvent.Set(); + } +@@ -633,7 +633,7 @@ + { + m_RadioSession = ""; + } +- if (m_ThreadHandle) ++ if (IsRunning()) + { + m_bStop = true; + m_hWorkerEvent.Set(); +diff -Naur xbmc-1fef727/xbmc/network/AirPlayServer.cpp xbmc-1fef727.patch/xbmc/network/AirPlayServer.cpp +--- xbmc-1fef727/xbmc/network/AirPlayServer.cpp 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/AirPlayServer.cpp 2012-02-07 14:30:18.058099358 +0100 +@@ -183,7 +183,7 @@ + } + } + +-CAirPlayServer::CAirPlayServer(int port, bool nonlocal) ++CAirPlayServer::CAirPlayServer(int port, bool nonlocal) : CThread("AirPlayServer") + { + m_port = port; + m_nonlocal = nonlocal; +diff -Naur xbmc-1fef727/xbmc/network/AirTunesServer.cpp xbmc-1fef727.patch/xbmc/network/AirTunesServer.cpp +--- xbmc-1fef727/xbmc/network/AirTunesServer.cpp 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/AirTunesServer.cpp 2012-02-07 14:30:18.058099358 +0100 +@@ -295,7 +295,7 @@ + } + } + +-CAirTunesServer::CAirTunesServer(int port, bool nonlocal) ++CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("CAirTunesServer") + { + m_port = port; + m_pLibShairport = new DllLibShairport(); +diff -Naur xbmc-1fef727/xbmc/network/libscrobbler/scrobbler.cpp xbmc-1fef727.patch/xbmc/network/libscrobbler/scrobbler.cpp +--- xbmc-1fef727/xbmc/network/libscrobbler/scrobbler.cpp 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/libscrobbler/scrobbler.cpp 2012-02-07 14:30:18.061099416 +0100 +@@ -46,7 +46,7 @@ + #define SCROBBLER_ACTION_NOWPLAYING 2 + + CScrobbler::CScrobbler(const CStdString &strHandshakeURL, const CStdString &strLogPrefix) +- : CThread() ++ : CThread("CScrobbler") + { + m_bBanned = false; + m_bBadAuth = false; +@@ -67,7 +67,7 @@ + ResetState(); + LoadCredentials(); + LoadJournal(); +- if (!ThreadHandle()) ++ if (!IsRunning()) + Create(); + } + +diff -Naur xbmc-1fef727/xbmc/network/Network.h xbmc-1fef727.patch/xbmc/network/Network.h +--- xbmc-1fef727/xbmc/network/Network.h 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/Network.h 2012-02-07 14:30:18.059099378 +0100 +@@ -24,6 +24,7 @@ + + #include + #include "utils/StdString.h" ++#include "system.h" + + enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 }; + enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 }; +diff -Naur xbmc-1fef727/xbmc/network/TCPServer.cpp xbmc-1fef727.patch/xbmc/network/TCPServer.cpp +--- xbmc-1fef727/xbmc/network/TCPServer.cpp 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/TCPServer.cpp 2012-02-07 14:30:18.059099378 +0100 +@@ -85,7 +85,7 @@ + } + } + +-CTCPServer::CTCPServer(int port, bool nonlocal) ++CTCPServer::CTCPServer(int port, bool nonlocal) : CThread("CTCPServer") + { + m_port = port; + m_nonlocal = nonlocal; +diff -Naur xbmc-1fef727/xbmc/network/UdpClient.cpp xbmc-1fef727.patch/xbmc/network/UdpClient.cpp +--- xbmc-1fef727/xbmc/network/UdpClient.cpp 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/UdpClient.cpp 2012-02-07 14:30:18.060099397 +0100 +@@ -35,7 +35,7 @@ + + #define UDPCLIENT_DEBUG_LEVEL LOGDEBUG + +-CUdpClient::CUdpClient(void) : CThread() ++CUdpClient::CUdpClient(void) : CThread("CUdpClient") + {} + + CUdpClient::~CUdpClient(void) +diff -Naur xbmc-1fef727/xbmc/network/UdpClient.h xbmc-1fef727.patch/xbmc/network/UdpClient.h +--- xbmc-1fef727/xbmc/network/UdpClient.h 2012-02-07 12:46:47.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/network/UdpClient.h 2012-02-07 14:30:18.060099397 +0100 +@@ -25,6 +25,7 @@ + #include "threads/CriticalSection.h" + #include + #include ++#include "system.h" + + class CUdpClient : CThread + { +diff -Naur xbmc-1fef727/xbmc/peripherals/Peripherals.cpp xbmc-1fef727.patch/xbmc/peripherals/Peripherals.cpp +--- xbmc-1fef727/xbmc/peripherals/Peripherals.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/peripherals/Peripherals.cpp 2012-02-07 14:30:18.062099436 +0100 +@@ -19,6 +19,7 @@ + * + */ + ++#include "system.h" + #include "Peripherals.h" + #include "bus/PeripheralBus.h" + #include "devices/PeripheralBluetooth.h" +diff -Naur xbmc-1fef727/xbmc/pictures/GUIWindowSlideShow.cpp xbmc-1fef727.patch/xbmc/pictures/GUIWindowSlideShow.cpp +--- xbmc-1fef727/xbmc/pictures/GUIWindowSlideShow.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/pictures/GUIWindowSlideShow.cpp 2012-02-07 14:30:18.063099456 +0100 +@@ -67,7 +67,7 @@ + + static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f }; + +-CBackgroundPicLoader::CBackgroundPicLoader() ++CBackgroundPicLoader::CBackgroundPicLoader() : CThread("CBackgroundPicLoader") + { + m_pCallback = NULL; + m_isLoading = false; +diff -Naur xbmc-1fef727/xbmc/rendering/dx/RenderSystemDX.cpp xbmc-1fef727.patch/xbmc/rendering/dx/RenderSystemDX.cpp +--- xbmc-1fef727/xbmc/rendering/dx/RenderSystemDX.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/rendering/dx/RenderSystemDX.cpp 2012-02-07 14:30:18.064099476 +0100 +@@ -569,7 +569,7 @@ + + //CVideoReferenceClock polls GetRasterStatus too, + //polling it from two threads at the same time is bad +- if (g_advancedSettings.m_sleepBeforeFlip > 0 && g_VideoReferenceClock.ThreadHandle() == NULL) ++ if (g_advancedSettings.m_sleepBeforeFlip > 0 && !g_VideoReferenceClock.IsRunning()) + { + //save current thread priority and set thread priority to THREAD_PRIORITY_TIME_CRITICAL + int priority = GetThreadPriority(GetCurrentThread()); +diff -Naur xbmc-1fef727/xbmc/settings/GUISettings.cpp xbmc-1fef727.patch/xbmc/settings/GUISettings.cpp +--- xbmc-1fef727/xbmc/settings/GUISettings.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/settings/GUISettings.cpp 2012-02-07 14:30:18.065099496 +0100 +@@ -587,6 +587,10 @@ + #ifdef HAVE_LIBVA + AddBool(vp, "videoplayer.usevaapi", 13426, true); + #endif ++#ifdef HAVE_LIBXVBA ++ AddBool(vp, "videoplayer.usexvba", 13433, true); ++ AddBool(vp, "videoplayer.usexvbasharedsurface", 13434, true); ++#endif + #ifdef HAS_DX + AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false); + #endif +diff -Naur xbmc-1fef727/xbmc/settings/GUIWindowSettingsCategory.cpp xbmc-1fef727.patch/xbmc/settings/GUIWindowSettingsCategory.cpp +--- xbmc-1fef727/xbmc/settings/GUIWindowSettingsCategory.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/settings/GUIWindowSettingsCategory.cpp 2012-02-07 14:30:18.067099534 +0100 +@@ -921,6 +921,15 @@ + 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 -Naur xbmc-1fef727/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp xbmc-1fef727.patch/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp +--- xbmc-1fef727/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/darwin/ThreadSchedImpl.cpp 2012-02-07 14:30:18.070099594 +0100 +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++int CThread::GetSchedRRPriority(void) ++{ ++ return 96; ++} ++ ++bool CThread::SetPrioritySched_RR(int iPriority) ++{ ++ // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the ++ // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects ++ // the thread running away. OSX automatically does this with the CoreAudio audio ++ // device handler thread. ++ int32_t result; ++ thread_extended_policy_data_t theFixedPolicy; ++ ++ // make thread fixed, set to 'true' for a non-fixed thread ++ theFixedPolicy.timeshare = false; ++ result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY, ++ (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); ++ ++ int policy; ++ struct sched_param param; ++ result = pthread_getschedparam(ThreadId(), &policy, ¶m ); ++ // change from default SCHED_OTHER to SCHED_RR ++ policy = SCHED_RR; ++ result = pthread_setschedparam(ThreadId(), policy, ¶m ); ++} +diff -Naur xbmc-1fef727/xbmc/threads/platform/linux/ThreadSchedImpl.cpp xbmc-1fef727.patch/xbmc/threads/platform/linux/ThreadSchedImpl.cpp +--- xbmc-1fef727/xbmc/threads/platform/linux/ThreadSchedImpl.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/linux/ThreadSchedImpl.cpp 2012-02-07 14:30:18.071099614 +0100 +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++int CThread::GetSchedRRPriority(void) ++{ ++ return GetNormalPriority(); ++} ++ ++bool CThread::SetPrioritySched_RR(int iPriority) ++{ ++ return false; ++} +diff -Naur xbmc-1fef727/xbmc/threads/platform/pthreads/ThreadImpl.cpp xbmc-1fef727.patch/xbmc/threads/platform/pthreads/ThreadImpl.cpp +--- xbmc-1fef727/xbmc/threads/platform/pthreads/ThreadImpl.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/pthreads/ThreadImpl.cpp 2012-02-07 14:30:18.072099634 +0100 +@@ -0,0 +1,220 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++void CThread::Create(bool bAutoDelete, unsigned stacksize) ++{ ++ if (m_ThreadId != 0) ++ { ++ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__); ++ exit(1); ++ } ++ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000; ++ m_iLastUsage = 0; ++ m_fLastUsage = 0.0f; ++ m_bAutoDelete = bAutoDelete; ++ m_bStop = false; ++ m_StopEvent.Reset(); ++ m_TermEvent.Reset(); ++ m_StartEvent.Reset(); ++ ++ pthread_attr_t attr; ++ pthread_attr_init(&attr); ++ if (stacksize > PTHREAD_STACK_MIN) ++ pthread_attr_setstacksize(&attr, stacksize); ++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ if (pthread_create(&m_ThreadId, &attr, (void*(*)(void*))staticThread, this) != 0) ++ { ++ CLog::Log(LOGNOTICE, "%s - fatal error creating thread",__FUNCTION__); ++ } ++ pthread_attr_destroy(&attr); ++} ++ ++void CThread::TermHandler() ++{ ++ ++} ++ ++void CThread::SetThreadInfo() ++{ ++ m_ThreadOpaque.LwpId = syscall(SYS_gettid); ++ ++ // start thread with nice level of appication ++ int appNice = getpriority(PRIO_PROCESS, getpid()); ++ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0) ++ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); ++} ++ ++ThreadIdentifier CThread::GetCurrentThreadId() ++{ ++ return pthread_self(); ++} ++ ++bool CThread::IsCurrentThread(const ThreadIdentifier tid) ++{ ++ return pthread_equal(pthread_self(), tid); ++} ++ ++int CThread::GetMinPriority(void) ++{ ++ // one level lower than application ++ return -1; ++} ++ ++int CThread::GetMaxPriority(void) ++{ ++ // one level higher than application ++ return 1; ++} ++ ++int CThread::GetNormalPriority(void) ++{ ++ // same level as application ++ return 0; ++} ++ ++bool CThread::SetPriority(const int iPriority) ++{ ++ bool bReturn = false; ++ ++ // wait until thread is running, it needs to get its lwp id ++ m_StartEvent.Wait(); ++ ++ CSingleLock lock(m_CriticalSection); ++ ++ // get min prio for SCHED_RR ++ int minRR = GetMaxPriority() + 1; ++ ++ if (!m_ThreadId) ++ bReturn = false; ++ else if (iPriority >= minRR) ++ bReturn = SetPrioritySched_RR(iPriority); ++ else ++ { ++ // get user max prio ++ struct rlimit limit; ++ int userMaxPrio; ++ if (getrlimit(RLIMIT_NICE, &limit) == 0) ++ { ++ userMaxPrio = limit.rlim_cur - 20; ++ } ++ else ++ userMaxPrio = 0; ++ ++ // keep priority in bounds ++ int prio = iPriority; ++ if (prio >= GetMaxPriority()) ++ prio = std::min(GetMaxPriority(), userMaxPrio); ++ if (prio < GetMinPriority()) ++ prio = GetMinPriority(); ++ ++ // nice level of application ++ int appNice = getpriority(PRIO_PROCESS, getpid()); ++ if (prio) ++ prio = prio > 0 ? appNice-1 : appNice+1; ++ ++ if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, prio) == 0) ++ bReturn = true; ++ else ++ CLog::Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); ++ } ++ ++ return bReturn; ++} ++ ++int CThread::GetPriority() ++{ ++ int iReturn; ++ ++ // lwp id is valid after start signel has fired ++ m_StartEvent.Wait(); ++ ++ CSingleLock lock(m_CriticalSection); ++ ++ int appNice = getpriority(PRIO_PROCESS, getpid()); ++ int prio = getpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId); ++ iReturn = appNice - prio; ++ ++ return iReturn; ++} ++ ++bool CThread::WaitForThreadExit(unsigned int milliseconds) ++{ ++ bool bReturn = m_TermEvent.WaitMSec(milliseconds); ++ ++ return bReturn; ++} ++ ++int64_t CThread::GetAbsoluteUsage() ++{ ++ CSingleLock lock(m_CriticalSection); ++ ++ if (!m_ThreadId) ++ return 0; ++ ++ clockid_t clock; ++ int64_t time = 0; ++ if (pthread_getcpuclockid(m_ThreadId, &clock) == 0) ++ { ++ struct timespec tp; ++ clock_gettime(clock, &tp); ++ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100; ++ } ++ return time; ++} ++ ++float CThread::GetRelativeUsage() ++{ ++ unsigned int iTime = XbmcThreads::SystemClockMillis(); ++ iTime *= 10000; // convert into 100ns tics ++ ++ // only update every 1 second ++ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage; ++ ++ int64_t iUsage = GetAbsoluteUsage(); ++ ++ if (m_iLastUsage > 0 && m_iLastTime > 0) ++ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime ); ++ ++ m_iLastUsage = iUsage; ++ m_iLastTime = iTime; ++ ++ return m_fLastUsage; ++} ++ ++int64_t CThread::GetCurrentThreadUsage() ++{ ++ pthread_t tid = pthread_self(); ++ clockid_t clock; ++ int64_t time = 0; ++ if (pthread_getcpuclockid(tid, &clock) == 0) ++ { ++ struct timespec tp; ++ clock_gettime(clock, &tp); ++ time = (int64_t)tp.tv_sec * 10000000 + tp.tv_nsec/100; ++ } ++ return time; ++} ++ +diff -Naur xbmc-1fef727/xbmc/threads/platform/pthreads/ThreadImpl.h xbmc-1fef727.patch/xbmc/threads/platform/pthreads/ThreadImpl.h +--- xbmc-1fef727/xbmc/threads/platform/pthreads/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/pthreads/ThreadImpl.h 2012-02-07 14:30:18.072099634 +0100 +@@ -0,0 +1,39 @@ ++/* ++* Copyright (C) 2005-2011 Team XBMC ++* http://www.xbmc.org ++* ++* This Program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License as published by ++* the Free Software Foundation; either version 2, or (at your option) ++* any later version. ++* ++* This Program is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License ++* along with XBMC; see the file COPYING. If not, write to ++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++* http://www.gnu.org/copyleft/gpl.html ++* ++*/ ++ ++#pragma once ++ ++#include ++ ++struct threadOpaque ++{ ++ pid_t LwpId; ++}; ++ ++typedef pthread_t ThreadIdentifier; ++typedef threadOpaque ThreadOpaque; ++typedef int THREADFUNC; ++ ++namespace XbmcThreads ++{ ++ inline static void ThreadSleep(unsigned int millis) { usleep(millis*1000); } ++} ++ +diff -Naur xbmc-1fef727/xbmc/threads/platform/ThreadImpl.cpp xbmc-1fef727.patch/xbmc/threads/platform/ThreadImpl.cpp +--- xbmc-1fef727/xbmc/threads/platform/ThreadImpl.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/ThreadImpl.cpp 2012-02-07 14:30:18.070099594 +0100 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#pragma once ++ ++#if (defined TARGET_POSIX) ++#include "threads/platform/pthreads/ThreadImpl.cpp" ++#if defined(TARGET_DARWIN_IOS) ++#include "threads/platform/darwin/ThreadSchedImpl.cpp" ++#else ++#include "threads/platform/linux/ThreadSchedImpl.cpp" ++#endif ++#elif (defined TARGET_WINDOWS) ++#include "threads/platform/win/ThreadImpl.cpp" ++#endif ++ +diff -Naur xbmc-1fef727/xbmc/threads/platform/ThreadImpl.h xbmc-1fef727.patch/xbmc/threads/platform/ThreadImpl.h +--- xbmc-1fef727/xbmc/threads/platform/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/ThreadImpl.h 2012-02-07 14:30:18.070099594 +0100 +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#pragma once ++ ++#if (defined TARGET_POSIX) ++#include "threads/platform/pthreads/ThreadImpl.h" ++#elif (defined TARGET_WINDOWS) ++#include "threads/platform/win/ThreadImpl.h" ++#endif +diff -Naur xbmc-1fef727/xbmc/threads/platform/win/ThreadImpl.cpp xbmc-1fef727.patch/xbmc/threads/platform/win/ThreadImpl.cpp +--- xbmc-1fef727/xbmc/threads/platform/win/ThreadImpl.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/win/ThreadImpl.cpp 2012-02-07 14:30:18.072099634 +0100 +@@ -0,0 +1,207 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include ++ ++ ++void CThread::Create(bool bAutoDelete, unsigned stacksize) ++{ ++ if (m_ThreadId != 0) ++ { ++ CLog::Log(LOGERROR, "%s - fatal error creating thread- old thread id not null", __FUNCTION__); ++ exit(1); ++ } ++ m_iLastTime = XbmcThreads::SystemClockMillis() * 10000; ++ m_iLastUsage = 0; ++ m_fLastUsage = 0.0f; ++ m_bAutoDelete = bAutoDelete; ++ m_bStop = false; ++ m_StopEvent.Reset(); ++ m_TermEvent.Reset(); ++ m_StartEvent.Reset(); ++ ++ m_ThreadOpaque.handle = CreateThread(NULL,stacksize, (LPTHREAD_START_ROUTINE)&staticThread, this, 0, &m_ThreadId); ++ if (m_ThreadOpaque.handle == NULL) ++ { ++ CLog::Log(LOGERROR, "%s - fatal error creating thread", __FUNCTION__); ++ } ++} ++ ++void CThread::TermHandler() ++{ ++ CloseHandle(m_ThreadOpaque.handle); ++ m_ThreadOpaque.handle = NULL; ++} ++ ++void CThread::SetThreadInfo() ++{ ++ const unsigned int MS_VC_EXCEPTION = 0x406d1388; ++ struct THREADNAME_INFO ++ { ++ DWORD dwType; // must be 0x1000 ++ LPCSTR szName; // pointer to name (in same addr space) ++ DWORD dwThreadID; // thread ID (-1 caller thread) ++ DWORD dwFlags; // reserved for future use, most be zero ++ } info; ++ ++ info.dwType = 0x1000; ++ info.szName = m_ThreadName.c_str(); ++ info.dwThreadID = m_ThreadId; ++ info.dwFlags = 0; ++ ++ try ++ { ++ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); ++ } ++ catch(...) ++ { ++ } ++} ++ ++ThreadIdentifier CThread::GetCurrentThreadId() ++{ ++ return ::GetCurrentThreadId(); ++} ++ ++bool CThread::IsCurrentThread(const ThreadIdentifier tid) ++{ ++ return (::GetCurrentThreadId() == tid); ++} ++ ++int CThread::GetMinPriority(void) ++{ ++ return(THREAD_PRIORITY_IDLE); ++} ++ ++int CThread::GetMaxPriority(void) ++{ ++ return(THREAD_PRIORITY_HIGHEST); ++} ++ ++int CThread::GetNormalPriority(void) ++{ ++ return(THREAD_PRIORITY_NORMAL); ++} ++ ++int CThread::GetSchedRRPriority(void) ++{ ++ return GetNormalPriority(); ++} ++ ++bool CThread::SetPriority(const int iPriority) ++{ ++ bool bReturn = false; ++ ++ CSingleLock lock(m_CriticalSection); ++ if (m_ThreadOpaque.handle) ++ { ++ bReturn = SetThreadPriority(m_ThreadOpaque.handle, iPriority) == TRUE; ++ } ++ ++ return bReturn; ++} ++ ++int CThread::GetPriority() ++{ ++ CSingleLock lock(m_CriticalSection); ++ ++ int iReturn = THREAD_PRIORITY_NORMAL; ++ if (m_ThreadOpaque.handle) ++ { ++ iReturn = GetThreadPriority(m_ThreadOpaque.handle); ++ } ++ return iReturn; ++} ++ ++bool CThread::WaitForThreadExit(unsigned int milliseconds) ++{ ++ bool bReturn = true; ++ ++ CSingleLock lock(m_CriticalSection); ++ if (m_ThreadId && m_ThreadOpaque.handle != NULL) ++ { ++ // boost priority of thread we are waiting on to same as caller ++ int callee = GetThreadPriority(m_ThreadOpaque.handle); ++ int caller = GetThreadPriority(GetCurrentThread()); ++ if(caller > callee) ++ SetThreadPriority(m_ThreadOpaque.handle, caller); ++ ++ lock.Leave(); ++ bReturn = m_TermEvent.WaitMSec(milliseconds); ++ lock.Enter(); ++ ++ // restore thread priority if thread hasn't exited ++ if(caller > callee && m_ThreadOpaque.handle) ++ SetThreadPriority(m_ThreadOpaque.handle, callee); ++ } ++ return bReturn; ++} ++ ++int64_t CThread::GetAbsoluteUsage() ++{ ++ CSingleLock lock(m_CriticalSection); ++ ++ if (!m_ThreadOpaque.handle) ++ return 0; ++ ++ uint64_t time = 0; ++ FILETIME CreationTime, ExitTime, UserTime, KernelTime; ++ if( GetThreadTimes(m_ThreadOpaque.handle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) ) ++ { ++ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime); ++ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime); ++ } ++ return time; ++} ++ ++float CThread::GetRelativeUsage() ++{ ++ unsigned int iTime = XbmcThreads::SystemClockMillis(); ++ iTime *= 10000; // convert into 100ns tics ++ ++ // only update every 1 second ++ if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage; ++ ++ int64_t iUsage = GetAbsoluteUsage(); ++ ++ if (m_iLastUsage > 0 && m_iLastTime > 0) ++ m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime ); ++ ++ m_iLastUsage = iUsage; ++ m_iLastTime = iTime; ++ ++ return m_fLastUsage; ++} ++ ++int64_t CThread::GetCurrentThreadUsage() ++{ ++ HANDLE h = GetCurrentThread(); ++ ++ uint64_t time = 0; ++ FILETIME CreationTime, ExitTime, UserTime, KernelTime; ++ if( GetThreadTimes(h, &CreationTime, &ExitTime, &KernelTime, &UserTime ) ) ++ { ++ time = (((uint64_t)UserTime.dwHighDateTime) << 32) + ((uint64_t)UserTime.dwLowDateTime); ++ time += (((uint64_t)KernelTime.dwHighDateTime) << 32) + ((uint64_t)KernelTime.dwLowDateTime); ++ } ++ return time; ++} ++ +diff -Naur xbmc-1fef727/xbmc/threads/platform/win/ThreadImpl.h xbmc-1fef727.patch/xbmc/threads/platform/win/ThreadImpl.h +--- xbmc-1fef727/xbmc/threads/platform/win/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/platform/win/ThreadImpl.h 2012-02-07 14:30:18.073099654 +0100 +@@ -0,0 +1,40 @@ ++/* ++* Copyright (C) 2005-2011 Team XBMC ++* http://www.xbmc.org ++* ++* This Program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License as published by ++* the Free Software Foundation; either version 2, or (at your option) ++* any later version. ++* ++* This Program is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License ++* along with XBMC; see the file COPYING. If not, write to ++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++* http://www.gnu.org/copyleft/gpl.html ++* ++*/ ++ ++#pragma once ++ ++#include ++ ++ ++struct threadOpaque ++{ ++ HANDLE handle; ++}; ++ ++typedef DWORD ThreadIdentifier; ++typedef threadOpaque ThreadOpaque; ++typedef DWORD THREADFUNC; ++ ++namespace XbmcThreads ++{ ++ inline static void ThreadSleep(unsigned int millis) { Sleep(millis); } ++} ++ +diff -Naur xbmc-1fef727/xbmc/threads/Thread.cpp xbmc-1fef727.patch/xbmc/threads/Thread.cpp +--- xbmc-1fef727/xbmc/threads/Thread.cpp 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/Thread.cpp 2012-02-07 14:30:18.068099554 +0100 +@@ -20,41 +20,27 @@ + + #include "threads/SystemClock.h" + #include "Thread.h" +-#ifndef _LINUX +-#include +-#include "utils/win32exception.h" +-#ifndef _MT +-#pragma message( "Please compile using multithreaded run-time libraries" ) +-#endif +-typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter); +-#else +-#include "PlatformInclude.h" +-#include "XHandle.h" +-#include +-typedef int (*PBEGINTHREADEX_THREADFUNC)(LPVOID lpThreadParameter); +-#endif +- +-#if defined(__GNUC__) && !defined(__clang__) +-#include +-using namespace __cxxabiv1; +-#endif +- + #include "utils/log.h" + #include "utils/TimeUtils.h" + #include "threads/ThreadLocal.h" + ++#define __STDC_FORMAT_MACROS ++#include ++ + static XbmcThreads::ThreadLocal currentThread; + ++#include "threads/platform/ThreadImpl.cpp" ++ + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// + +-CThread::CThread(const char* ThreadName) : m_StopEvent(true,true) ++CThread::CThread(const char* ThreadName) ++: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true) + { + m_bStop = false; + + m_bAutoDelete = false; +- m_ThreadHandle = NULL; + m_ThreadId = 0; + m_iLastTime = 0; + m_iLastUsage = 0; +@@ -66,12 +52,12 @@ + m_ThreadName = ThreadName; + } + +-CThread::CThread(IRunnable* pRunnable, const char* ThreadName) : m_StopEvent(true,true) ++CThread::CThread(IRunnable* pRunnable, const char* ThreadName) ++: m_StopEvent(true,true), m_TermEvent(true), m_StartEvent(true) + { + m_bStop = false; + + m_bAutoDelete = false; +- m_ThreadHandle = NULL; + m_ThreadId = 0; + m_iLastTime = 0; + m_iLastUsage = 0; +@@ -85,171 +71,62 @@ + + CThread::~CThread() + { +- if (m_ThreadHandle != NULL) +- { +- CloseHandle(m_ThreadHandle); +- } +- m_ThreadHandle = NULL; +- ++ StopThread(); + } + +-#ifndef _WIN32 +-void CThread::term_handler (int signum) ++bool CThread::IsRunning() + { +- CLog::Log(LOGERROR,"thread 0x%lx (%lu) got signal %d. calling OnException and terminating thread abnormally.", (long unsigned int)pthread_self(), (long unsigned int)pthread_self(), signum); +- +- CThread* curThread = currentThread.get(); +- if (curThread) +- { +- curThread->m_bStop = TRUE; +- curThread->m_StopEvent.Set(); +- +- curThread->OnException(); +- if( curThread->IsAutoDelete() ) +- delete curThread; +- } +- +- pthread_exit(NULL); ++ return m_ThreadId ? true : false; + } + +-int CThread::staticThread(void* data) +-#else +-DWORD WINAPI CThread::staticThread(LPVOID* data) +-#endif ++THREADFUNC CThread::staticThread(void* data) + { + CThread* pThread = (CThread*)(data); ++ std::string name; ++ ThreadIdentifier id; ++ bool autodelete; ++ + if (!pThread) { + CLog::Log(LOGERROR,"%s, sanity failed. thread is NULL.",__FUNCTION__); + return 1; + } + +- if (pThread->m_ThreadName.empty()) +- pThread->m_ThreadName = pThread->GetTypeName(); +- pThread->SetDebugCallStackName(pThread->m_ThreadName.c_str()); ++ name = pThread->m_ThreadName; ++ id = pThread->m_ThreadId; ++ autodelete = pThread->m_bAutoDelete; + +- CLog::Log(LOGDEBUG,"Thread %s start, auto delete: %d", pThread->m_ThreadName.c_str(), pThread->IsAutoDelete()); ++ pThread->SetThreadInfo(); ++ ++ CLog::Log(LOGNOTICE,"Thread %s start, auto delete: %s", name.c_str(), (autodelete ? "true" : "false")); + + currentThread.set(pThread); +-#ifndef _LINUX +- /* install win32 exception translator */ +- win32_exception::install_handler(); +-#else +- struct sigaction action; +- action.sa_handler = term_handler; +- sigemptyset (&action.sa_mask); +- action.sa_flags = 0; +- //sigaction (SIGABRT, &action, NULL); +- //sigaction (SIGSEGV, &action, NULL); +-#endif ++ pThread->m_StartEvent.Set(); + ++ pThread->OnStartup(); ++ pThread->Process(); ++ pThread->OnExit(); + +- try +- { +- pThread->OnStartup(); +- } +-#ifndef _LINUX +- catch (const win32_exception &e) +- { +- e.writelog(__FUNCTION__); +- if( pThread->IsAutoDelete() ) +- { +- delete pThread; +- _endthreadex(123); +- return 0; +- } +- } +-#endif +- catch(...) +- { +- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread startup, aborting. auto delete: %d", __FUNCTION__, pThread->m_ThreadName.c_str(), pThread->IsAutoDelete()); +- if( pThread->IsAutoDelete() ) +- { +- delete pThread; +-#ifndef _LINUX +- _endthreadex(123); +-#endif +- return 0; +- } +- } ++ // lock during termination ++ CSingleLock lock(pThread->m_CriticalSection); + +- try +- { +- pThread->Process(); +- } +-#ifndef _LINUX +- catch (const access_violation &e) +- { +- e.writelog(__FUNCTION__); +- } +- catch (const win32_exception &e) +- { +- e.writelog(__FUNCTION__); +- } +-#endif +- catch(...) +- { +- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread process, attemping cleanup in OnExit", __FUNCTION__, pThread->m_ThreadName.c_str()); +- } ++ pThread->m_ThreadId = 0; ++ pThread->m_TermEvent.Set(); ++ pThread->TermHandler(); + +- try +- { +- pThread->OnExit(); +- } +-#ifndef _LINUX +- catch (const access_violation &e) +- { +- e.writelog(__FUNCTION__); +- } +- catch (const win32_exception &e) +- { +- e.writelog(__FUNCTION__); +- } +-#endif +- catch(...) +- { +- CLog::Log(LOGERROR, "%s - thread %s, Unhandled exception caught in thread exit", __FUNCTION__, pThread->m_ThreadName.c_str()); +- } ++ lock.Leave(); + +- if ( pThread->IsAutoDelete() ) ++ if (autodelete) + { +- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId()); ++ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating (autodelete)", name.c_str(), (uint64_t)id); + delete pThread; + pThread = NULL; + } + else +- CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", pThread->m_ThreadName.c_str(), (uint64_t)CThread::GetCurrentThreadId()); +- +-// DXMERGE - this looks like it might have used to have been useful for something... +-// g_graphicsContext.DeleteThreadContext(); ++ CLog::Log(LOGDEBUG,"Thread %s %"PRIu64" terminating", name.c_str(), (uint64_t)id); + +-#ifndef _LINUX +- _endthreadex(123); +-#endif + return 0; + } + +-void CThread::Create(bool bAutoDelete, unsigned stacksize) +-{ +- if (m_ThreadHandle != NULL) +- { +- throw 1; //ERROR should not b possible!!! +- } +- m_iLastTime = XbmcThreads::SystemClockMillis() * 10000; +- m_iLastUsage = 0; +- m_fLastUsage = 0.0f; +- m_bAutoDelete = bAutoDelete; +- m_bStop = false; +- m_StopEvent.Reset(); +- +- m_ThreadHandle = (HANDLE)_beginthreadex(NULL, stacksize, (PBEGINTHREADEX_THREADFUNC)staticThread, (void*)this, 0, &m_ThreadId); +- +-#ifdef _LINUX +- if (m_ThreadHandle && m_ThreadHandle->m_threadValid && m_bAutoDelete) +- // FIXME: WinAPI can truncate 64bit pthread ids +- pthread_detach(m_ThreadHandle->m_hThread); +-#endif +-} +- + bool CThread::IsAutoDelete() const + { + return m_bAutoDelete; +@@ -259,213 +136,17 @@ + { + m_bStop = true; + m_StopEvent.Set(); +- if (m_ThreadHandle && bWait) ++ CSingleLock lock(m_CriticalSection); ++ if (m_ThreadId && bWait) + { +- WaitForThreadExit(INFINITE); +- CloseHandle(m_ThreadHandle); +- m_ThreadHandle = NULL; ++ lock.Leave(); ++ WaitForThreadExit(0xFFFFFFFF); + } + } + + ThreadIdentifier CThread::ThreadId() const + { +-#ifdef _LINUX +- if (m_ThreadHandle && m_ThreadHandle->m_threadValid) +- return m_ThreadHandle->m_hThread; +- else +- return 0; +-#else + return m_ThreadId; +-#endif +-} +- +- +-CThread::operator HANDLE() +-{ +- return m_ThreadHandle; +-} +- +-CThread::operator HANDLE() const +-{ +- return m_ThreadHandle; +-} +- +-bool CThread::SetPriority(const int iPriority) +-// Set thread priority +-// Return true for success +-{ +- bool rtn = false; +- +- if (m_ThreadHandle) +- { +- rtn = SetThreadPriority( m_ThreadHandle, iPriority ) == TRUE; +- } +- +- return(rtn); +-} +- +-void CThread::SetPrioritySched_RR(void) +-{ +-#ifdef __APPLE__ +- // Changing to SCHED_RR is safe under OSX, you don't need elevated privileges and the +- // OSX scheduler will monitor SCHED_RR threads and drop to SCHED_OTHER if it detects +- // the thread running away. OSX automatically does this with the CoreAudio audio +- // device handler thread. +- int32_t result; +- thread_extended_policy_data_t theFixedPolicy; +- +- // make thread fixed, set to 'true' for a non-fixed thread +- theFixedPolicy.timeshare = false; +- result = thread_policy_set(pthread_mach_thread_np(ThreadId()), THREAD_EXTENDED_POLICY, +- (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); +- +- int policy; +- struct sched_param param; +- result = pthread_getschedparam(ThreadId(), &policy, ¶m ); +- // change from default SCHED_OTHER to SCHED_RR +- policy = SCHED_RR; +- result = pthread_setschedparam(ThreadId(), policy, ¶m ); +-#endif +-} +- +-int CThread::GetMinPriority(void) +-{ +-#if 0 +-//#if defined(__APPLE__) +- struct sched_param sched; +- int rtn, policy; +- +- rtn = pthread_getschedparam(ThreadId(), &policy, &sched); +- int min = sched_get_priority_min(policy); +- +- return(min); +-#else +- return(THREAD_PRIORITY_IDLE); +-#endif +-} +- +-int CThread::GetMaxPriority(void) +-{ +-#if 0 +-//#if defined(__APPLE__) +- struct sched_param sched; +- int rtn, policy; +- +- rtn = pthread_getschedparam(ThreadId(), &policy, &sched); +- int max = sched_get_priority_max(policy); +- +- return(max); +-#else +- return(THREAD_PRIORITY_HIGHEST); +-#endif +-} +- +-int CThread::GetNormalPriority(void) +-{ +-#if 0 +-//#if defined(__APPLE__) +- struct sched_param sched; +- int rtn, policy; +- +- rtn = pthread_getschedparam(ThreadId(), &policy, &sched); +- int min = sched_get_priority_min(policy); +- int max = sched_get_priority_max(policy); +- +- return( min + ((max-min) / 2) ); +-#else +- return(THREAD_PRIORITY_NORMAL); +-#endif +-} +- +- +-void CThread::SetDebugCallStackName( const char *name ) +-{ +-#ifdef _WIN32 +- const unsigned int MS_VC_EXCEPTION = 0x406d1388; +- struct THREADNAME_INFO +- { +- DWORD dwType; // must be 0x1000 +- LPCSTR szName; // pointer to name (in same addr space) +- DWORD dwThreadID; // thread ID (-1 caller thread) +- DWORD dwFlags; // reserved for future use, most be zero +- } info; +- +- info.dwType = 0x1000; +- info.szName = name; +- info.dwThreadID = m_ThreadId; +- info.dwFlags = 0; +- +- try +- { +- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); +- } +- catch(...) +- { +- } +-#endif +-} +- +-// Get the thread name using the implementation dependant typeid() class +-// and attempt to clean it. +-std::string CThread::GetTypeName(void) +-{ +- std::string name = typeid(*this).name(); +- +-#if defined(_MSC_VER) +- // Visual Studio 2010 returns the name as "class CThread" etc +- if (name.substr(0, 6) == "class ") +- name = name.substr(6, name.length() - 6); +-#elif defined(__GNUC__) && !defined(__clang__) +- // gcc provides __cxa_demangle to demangle the name +- char* demangled = NULL; +- int status; +- +- demangled = __cxa_demangle(name.c_str(), NULL, 0, &status); +- if (status == 0) +- name = demangled; +- else +- CLog::Log(LOGDEBUG,"%s, __cxa_demangle(%s) failed with status %d", __FUNCTION__, name.c_str(), status); +- +- if (demangled) +- free(demangled); +-#endif +- +- return name; +-} +- +-bool CThread::WaitForThreadExit(unsigned int milliseconds) +-// Waits for thread to exit, timeout in given number of msec. +-// Returns true when thread ended +-{ +- if (!m_ThreadHandle) return true; +- +-#ifndef _LINUX +- // boost priority of thread we are waiting on to same as caller +- int callee = GetThreadPriority(m_ThreadHandle); +- int caller = GetThreadPriority(GetCurrentThread()); +- if(caller > callee) +- SetThreadPriority(m_ThreadHandle, caller); +- +- if (::WaitForSingleObject(m_ThreadHandle, milliseconds) != WAIT_TIMEOUT) +- return true; +- +- // restore thread priority if thread hasn't exited +- if(caller > callee) +- SetThreadPriority(m_ThreadHandle, callee); +-#else +- if (!(m_ThreadHandle->m_threadValid) || pthread_join(m_ThreadHandle->m_hThread, NULL) == 0) +- { +- m_ThreadHandle->m_threadValid = false; +- return true; +- } +-#endif +- +- return false; +-} +- +-HANDLE CThread::ThreadHandle() +-{ +- return m_ThreadHandle; + } + + void CThread::Process() +@@ -474,54 +155,14 @@ + m_pRunnable->Run(); + } + +-float CThread::GetRelativeUsage() +-{ +- unsigned __int64 iTime = XbmcThreads::SystemClockMillis(); +- iTime *= 10000; // convert into 100ns tics +- +- // only update every 1 second +- if( iTime < m_iLastTime + 1000*10000 ) return m_fLastUsage; +- +- FILETIME CreationTime, ExitTime, UserTime, KernelTime; +- if( GetThreadTimes( m_ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime ) ) +- { +- unsigned __int64 iUsage = 0; +- iUsage += (((unsigned __int64)UserTime.dwHighDateTime) << 32) + ((unsigned __int64)UserTime.dwLowDateTime); +- iUsage += (((unsigned __int64)KernelTime.dwHighDateTime) << 32) + ((unsigned __int64)KernelTime.dwLowDateTime); +- +- if(m_iLastUsage > 0 && m_iLastTime > 0) +- m_fLastUsage = (float)( iUsage - m_iLastUsage ) / (float)( iTime - m_iLastTime ); +- +- m_iLastUsage = iUsage; +- m_iLastTime = iTime; +- +- return m_fLastUsage; +- } +- return 0.0f; +-} +- + bool CThread::IsCurrentThread() const + { + return IsCurrentThread(ThreadId()); + } + +- +-ThreadIdentifier CThread::GetCurrentThreadId() ++CThread* CThread::GetCurrentThread() + { +-#ifdef _LINUX +- return pthread_self(); +-#else +- return ::GetCurrentThreadId(); +-#endif +-} +- +-bool CThread::IsCurrentThread(const ThreadIdentifier tid) +-{ +-#ifdef _LINUX +- return pthread_equal(pthread_self(), tid); +-#else +- return (::GetCurrentThreadId() == tid); +-#endif ++ return currentThread.get(); + } + + void CThread::Sleep(unsigned int milliseconds) +@@ -529,7 +170,7 @@ + if(milliseconds > 10 && IsCurrentThread()) + m_StopEvent.WaitMSec(milliseconds); + else +- ::Sleep(milliseconds); ++ XbmcThreads::ThreadSleep(milliseconds); + } + + +diff -Naur xbmc-1fef727/xbmc/threads/Thread.h xbmc-1fef727.patch/xbmc/threads/Thread.h +--- xbmc-1fef727/xbmc/threads/Thread.h 2012-02-07 12:46:50.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/Thread.h 2012-02-07 14:30:18.069099574 +0100 +@@ -23,19 +23,13 @@ + // + ////////////////////////////////////////////////////////////////////// + +-#if !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_) && !defined(AFX_THREAD_H__67621B15_8724_4B5D_9343_7667075C89F2__INCLUDED_) +-#define AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_ +- +-#if _MSC_VER > 1000 + #pragma once +-#endif // _MSC_VER > 1000 + + #include +-#include "system.h" // for HANDLE +-#ifdef _LINUX +-#include "PlatformInclude.h" +-#endif ++#include + #include "Event.h" ++#include "threads/ThreadImpl.h" ++#include "threads/ThreadLocal.h" + + class IRunnable + { +@@ -44,37 +38,36 @@ + virtual ~IRunnable() {} + }; + +-#ifdef CTHREAD +-#undef CTHREAD +-#endif +- + // minimum as mandated by XTL + #define THREAD_MINSTACKSIZE 0x10000 + + class CThread + { + public: +- CThread(const char* ThreadName = NULL); +- CThread(IRunnable* pRunnable, const char* ThreadName = NULL); ++ CThread(const char* ThreadName); ++ CThread(IRunnable* pRunnable, const char* ThreadName); + virtual ~CThread(); + void Create(bool bAutoDelete = false, unsigned stacksize = 0); + bool WaitForThreadExit(unsigned int milliseconds); + void Sleep(unsigned int milliseconds); + bool SetPriority(const int iPriority); +- void SetPrioritySched_RR(void); ++ int GetPriority(void); + int GetMinPriority(void); + int GetMaxPriority(void); + int GetNormalPriority(void); +- HANDLE ThreadHandle(); +- operator HANDLE(); +- operator HANDLE() const; ++ int GetSchedRRPriority(void); ++ bool SetPrioritySched_RR(int iPriority); + bool IsAutoDelete() const; + virtual void StopThread(bool bWait = true); + float GetRelativeUsage(); // returns the relative cpu usage of this thread since last call ++ int64_t GetAbsoluteUsage(); + bool IsCurrentThread() const; ++ bool IsRunning(); + + static bool IsCurrentThread(const ThreadIdentifier tid); + static ThreadIdentifier GetCurrentThreadId(); ++ static CThread* GetCurrentThread(); ++ static int64_t GetCurrentThreadUsage(); + protected: + virtual void OnStartup(){}; + virtual void OnExit(){}; +@@ -82,7 +75,6 @@ + virtual void Process(); + + volatile bool m_bStop; +- HANDLE m_ThreadHandle; + + enum WaitResponse { WAIT_INTERRUPTED = -1, WAIT_SIGNALED = 0, WAIT_TIMEDOUT = 1 }; + +@@ -108,36 +100,22 @@ + } + + private: +- /*! \brief set the threadname for the debugger/callstack, implementation dependent. +- */ +- void SetDebugCallStackName( const char *threadName ); +- std::string GetTypeName(void); +- +-private: ++ static THREADFUNC staticThread(void *data); + ThreadIdentifier ThreadId() const; ++ void SetThreadInfo(); ++ void TermHandler(); ++ ++ ThreadIdentifier m_ThreadId; ++ ThreadOpaque m_ThreadOpaque; + bool m_bAutoDelete; + CEvent m_StopEvent; +- unsigned m_ThreadId; // This value is unreliable on platforms using pthreads +- // Use m_ThreadHandle->m_hThread instead ++ CEvent m_TermEvent; ++ CEvent m_StartEvent; ++ CCriticalSection m_CriticalSection; + IRunnable* m_pRunnable; +- +- unsigned __int64 m_iLastUsage; +- unsigned __int64 m_iLastTime; ++ uint64_t m_iLastUsage; ++ uint64_t m_iLastTime; + float m_fLastUsage; + + std::string m_ThreadName; +- +-#ifdef _LINUX +- static void term_handler (int signum); +-#endif +- +-#ifndef _WIN32 +- static int staticThread(void* data); +-#else +- static DWORD WINAPI staticThread(LPVOID* data); +-#endif +- +-private: + }; +- +-#endif // !defined(AFX_THREAD_H__ACFB7357_B961_4AC1_9FB2_779526219817__INCLUDED_) +diff -Naur xbmc-1fef727/xbmc/threads/ThreadImpl.h xbmc-1fef727.patch/xbmc/threads/ThreadImpl.h +--- xbmc-1fef727/xbmc/threads/ThreadImpl.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/threads/ThreadImpl.h 2012-02-07 14:30:18.069099574 +0100 +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2005-2011 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#pragma once ++ ++#include "threads/platform/ThreadImpl.h" ++ +diff -Naur xbmc-1fef727/xbmc/utils/AlarmClock.cpp xbmc-1fef727.patch/xbmc/utils/AlarmClock.cpp +--- xbmc-1fef727/xbmc/utils/AlarmClock.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/AlarmClock.cpp 2012-02-07 14:30:18.073099654 +0100 +@@ -28,7 +28,7 @@ + + using namespace std; + +-CAlarmClock::CAlarmClock() : m_bIsRunning(false) ++CAlarmClock::CAlarmClock() : CThread("CAlarmClock"), m_bIsRunning(false) + { + } + +diff -Naur xbmc-1fef727/xbmc/utils/AsyncFileCopy.cpp xbmc-1fef727.patch/xbmc/utils/AsyncFileCopy.cpp +--- xbmc-1fef727/xbmc/utils/AsyncFileCopy.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/AsyncFileCopy.cpp 2012-02-07 14:30:18.074099674 +0100 +@@ -26,7 +26,7 @@ + #include "log.h" + #include "utils/TimeUtils.h" + +-CAsyncFileCopy::CAsyncFileCopy() ++CAsyncFileCopy::CAsyncFileCopy() : CThread("CAsyncFileCopy") + { + m_cancelled = false; + m_succeeded = false; +diff -Naur xbmc-1fef727/xbmc/utils/DownloadQueue.cpp xbmc-1fef727.patch/xbmc/utils/DownloadQueue.cpp +--- xbmc-1fef727/xbmc/utils/DownloadQueue.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/DownloadQueue.cpp 2012-02-07 14:30:18.074099674 +0100 +@@ -32,7 +32,7 @@ + + WORD CDownloadQueue::m_wNextQueueId = 0; + +-CDownloadQueue::CDownloadQueue(void) : CThread() ++CDownloadQueue::CDownloadQueue(void) : CThread("CDownloadQueue") + { + m_bStop = false; + m_wQueueId = m_wNextQueueId++; +diff -Naur xbmc-1fef727/xbmc/utils/DownloadQueue.h xbmc-1fef727.patch/xbmc/utils/DownloadQueue.h +--- xbmc-1fef727/xbmc/utils/DownloadQueue.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/DownloadQueue.h 2012-02-07 14:30:18.075099693 +0100 +@@ -26,6 +26,8 @@ + #include "threads/CriticalSection.h" + #include "StdString.h" + ++#include "system.h" ++ + struct TICKET + { + TICKET(WORD aQueueId, DWORD aItemId) +diff -Naur xbmc-1fef727/xbmc/utils/DownloadQueueManager.h xbmc-1fef727.patch/xbmc/utils/DownloadQueueManager.h +--- xbmc-1fef727/xbmc/utils/DownloadQueueManager.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/DownloadQueueManager.h 2012-02-07 14:30:18.075099693 +0100 +@@ -22,6 +22,7 @@ + */ + + #include "DownloadQueue.h" ++#include "system.h" + + #define MAX_DOWNLOAD_QUEUES 3 + +diff -Naur xbmc-1fef727/xbmc/utils/JobManager.cpp xbmc-1fef727.patch/xbmc/utils/JobManager.cpp +--- xbmc-1fef727/xbmc/utils/JobManager.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/JobManager.cpp 2012-02-07 14:30:18.076099712 +0100 +@@ -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 -Naur xbmc-1fef727/xbmc/utils/LCD.h xbmc-1fef727.patch/xbmc/utils/LCD.h +--- xbmc-1fef727/xbmc/utils/LCD.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/LCD.h 2012-02-07 14:30:18.076099712 +0100 +@@ -68,8 +68,9 @@ + void LoadSkin(const CStdString &xmlFile); + void Reset(); + void Render(LCD_MODE mode); +- ILCD() : m_disableOnPlay(DISABLE_ON_PLAY_NONE), +- m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {} ++ ILCD() : CThread("ILCD"), ++ m_disableOnPlay(DISABLE_ON_PLAY_NONE), ++ m_eCurrentCharset(CUSTOM_CHARSET_DEFAULT) {} + protected: + virtual void Process() = 0; + void StringToLCDCharSet(CStdString& strText); +diff -Naur xbmc-1fef727/xbmc/utils/RssReader.cpp xbmc-1fef727.patch/xbmc/utils/RssReader.cpp +--- xbmc-1fef727/xbmc/utils/RssReader.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/RssReader.cpp 2012-02-07 14:30:18.077099732 +0100 +@@ -44,7 +44,7 @@ + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// + +-CRssReader::CRssReader() : CThread() ++CRssReader::CRssReader() : CThread("CRssReader") + { + m_pObserver = NULL; + m_spacesBetweenFeeds = 0; +diff -Naur xbmc-1fef727/xbmc/utils/RssReader.h xbmc-1fef727.patch/xbmc/utils/RssReader.h +--- xbmc-1fef727/xbmc/utils/RssReader.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/RssReader.h 2012-02-07 14:30:18.077099732 +0100 +@@ -39,6 +39,9 @@ + + #include "tinyXML/tinyxml.h" + ++#include "system.h" ++ ++ + #define RSS_COLOR_BODY 0 + #define RSS_COLOR_HEADLINE 1 + #define RSS_COLOR_CHANNEL 2 +diff -Naur xbmc-1fef727/xbmc/utils/Splash.cpp xbmc-1fef727.patch/xbmc/utils/Splash.cpp +--- xbmc-1fef727/xbmc/utils/Splash.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/Splash.cpp 2012-02-07 14:30:18.078099752 +0100 +@@ -31,7 +31,7 @@ + + using namespace XFILE; + +-CSplash::CSplash(const CStdString& imageName) ++CSplash::CSplash(const CStdString& imageName) : CThread("CSplash") + { + m_ImageName = imageName; + fade = 0.5; +@@ -139,5 +139,5 @@ + + bool CSplash::IsRunning() + { +- return (m_ThreadHandle != NULL); ++ return (IsRunning()); + } +diff -Naur xbmc-1fef727/xbmc/utils/TuxBoxUtil.cpp xbmc-1fef727.patch/xbmc/utils/TuxBoxUtil.cpp +--- xbmc-1fef727/xbmc/utils/TuxBoxUtil.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/utils/TuxBoxUtil.cpp 2012-02-07 14:30:18.079099772 +0100 +@@ -48,7 +48,7 @@ + CTuxBoxUtil g_tuxbox; + CTuxBoxService g_tuxboxService; + +-CTuxBoxService::CTuxBoxService() ++CTuxBoxService::CTuxBoxService() : CThread("CTuxBoxService") + { + } + CTuxBoxService::~CTuxBoxService() +diff -Naur xbmc-1fef727/xbmc/video/VideoInfoDownloader.cpp xbmc-1fef727.patch/xbmc/video/VideoInfoDownloader.cpp +--- xbmc-1fef727/xbmc/video/VideoInfoDownloader.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/video/VideoInfoDownloader.cpp 2012-02-07 14:30:18.079099772 +0100 +@@ -116,7 +116,7 @@ + m_state = FIND_MOVIE; + m_strMovie = strMovie; + m_found = 0; +- if (ThreadHandle()) ++ if (IsRunning()) + StopThread(); + Create(); + while (m_state != DO_NOTHING) +@@ -160,7 +160,7 @@ + { // threaded version + m_state = GET_DETAILS; + m_found = 0; +- if (ThreadHandle()) ++ if (IsRunning()) + StopThread(); + Create(); + while (!m_found) +@@ -195,7 +195,7 @@ + { // threaded version + m_state = GET_EPISODE_DETAILS; + m_found = 0; +- if (ThreadHandle()) ++ if (IsRunning()) + StopThread(); + Create(); + while (!m_found) +@@ -230,7 +230,7 @@ + { // threaded version + m_state = GET_EPISODE_LIST; + m_found = 0; +- if (ThreadHandle()) ++ if (IsRunning()) + StopThread(); + Create(); + while (!m_found) +diff -Naur xbmc-1fef727/xbmc/video/VideoInfoDownloader.h xbmc-1fef727.patch/xbmc/video/VideoInfoDownloader.h +--- xbmc-1fef727/xbmc/video/VideoInfoDownloader.h 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/video/VideoInfoDownloader.h 2012-02-07 14:30:18.080099792 +0100 +@@ -42,7 +42,7 @@ + class CVideoInfoDownloader : public CThread + { + public: +- CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : m_info(scraper) {} ++ CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : CThread("CVideoInfoDownloader"), m_info(scraper) {} + virtual ~CVideoInfoDownloader() {} + + // threaded lookup functions +diff -Naur xbmc-1fef727/xbmc/video/VideoInfoScanner.cpp xbmc-1fef727.patch/xbmc/video/VideoInfoScanner.cpp +--- xbmc-1fef727/xbmc/video/VideoInfoScanner.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/video/VideoInfoScanner.cpp 2012-02-07 14:30:18.081099811 +0100 +@@ -54,7 +54,7 @@ + namespace VIDEO + { + +- CVideoInfoScanner::CVideoInfoScanner() ++ CVideoInfoScanner::CVideoInfoScanner() : CThread("CVideoInfoScanner") + { + m_bRunning = false; + m_pObserver = NULL; +diff -Naur xbmc-1fef727/xbmc/video/VideoReferenceClock.cpp xbmc-1fef727.patch/xbmc/video/VideoReferenceClock.cpp +--- xbmc-1fef727/xbmc/video/VideoReferenceClock.cpp 2012-02-07 12:46:48.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/video/VideoReferenceClock.cpp 2012-02-07 14:30:18.082099830 +0100 +@@ -107,7 +107,7 @@ + + #endif + +-CVideoReferenceClock::CVideoReferenceClock() ++CVideoReferenceClock::CVideoReferenceClock() : CThread("CVideoReferenceClock") + { + m_SystemFrequency = CurrentHostFrequency(); + m_ClockSpeed = 1.0; +@@ -161,6 +161,8 @@ + m_RefreshChanged = 0; + m_Started.Set(); + ++ SetPriority(1); ++ + if (SetupSuccess) + { + m_UseVblank = true; //tell other threads we're using vblank as clock +diff -Naur xbmc-1fef727/xbmc/win32/PlatformDefs.h xbmc-1fef727.patch/xbmc/win32/PlatformDefs.h +--- xbmc-1fef727/xbmc/win32/PlatformDefs.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/win32/PlatformDefs.h 2012-02-07 14:30:18.082099830 +0100 +@@ -33,7 +33,6 @@ + typedef __int64 fpos64_t; + typedef __int64 __off64_t; + typedef long __off_t; +-typedef unsigned long ThreadIdentifier; + + #define ssize_t int + +diff -Naur xbmc-1fef727/xbmc/win32/WindowHelper.cpp xbmc-1fef727.patch/xbmc/win32/WindowHelper.cpp +--- xbmc-1fef727/xbmc/win32/WindowHelper.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/win32/WindowHelper.cpp 2012-02-07 14:30:18.083099850 +0100 +@@ -28,7 +28,7 @@ + + CWHelper g_windowHelper; + +-CWHelper::CWHelper(void) ++CWHelper::CWHelper(void) : CThread("CWHelper") + { + m_hwnd = NULL; + m_hProcess = NULL; +diff -Naur xbmc-1fef727/xbmc/windowing/X11/WinSystemX11.cpp xbmc-1fef727.patch/xbmc/windowing/X11/WinSystemX11.cpp +--- xbmc-1fef727/xbmc/windowing/X11/WinSystemX11.cpp 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/windowing/X11/WinSystemX11.cpp 2012-02-07 14:30:43.758606503 +0100 +@@ -35,6 +35,8 @@ + #include + #include "cores/VideoRenderers/RenderManager.h" + #include "utils/TimeUtils.h" ++#include "settings/AdvancedSettings.h" ++#include "settings/GUISettings.h" + + #if defined(HAS_XRANDR) + #include +@@ -52,6 +54,7 @@ + m_wmWindow = 0; + m_bWasFullScreenBeforeMinimize = false; + m_dpyLostTime = 0; ++ m_internalModeSwitch = false; + + XSetErrorHandler(XErrorHandler); + } +@@ -178,6 +181,45 @@ + return false; + } + ++void CWinSystemX11::RefreshWindow() ++{ ++ // save current mode if this is not an internal request ++ if (!m_internalModeSwitch) ++ { ++ CLog::Log(LOGNOTICE, "CWinSystemX11::RefreshWindow - external or initial xrandr event"); ++ m_xrandrOut = g_xrandr.GetCurrentOutput(); ++ m_xrandrMode = g_xrandr.GetCurrentMode(m_xrandrOut.name); ++ } ++ m_internalModeSwitch = false; ++ ++ g_xrandr.Query(true); ++ XOutput out = g_xrandr.GetCurrentOutput(); ++ XMode mode = g_xrandr.GetCurrentMode(out.name); ++ ++ RESOLUTION_INFO res; ++ unsigned int i; ++ bool found(false); ++ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) ++ { ++ if (g_settings.m_ResInfo[i].strId == mode.id) ++ { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); ++ return; ++ } ++ ++ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); ++ g_guiSettings.SetInt("window.width", mode.w); ++ g_guiSettings.SetInt("window.height", mode.h); ++ g_settings.Save(); ++} ++ + bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) + { + m_nWidth = res.iWidth; +@@ -193,13 +235,32 @@ + mode.hz = res.fRefreshRate; + mode.id = res.strId; + +- if(m_bFullScreen) ++ XOutput currout = g_xrandr.GetCurrentOutput(); ++ XMode currmode = g_xrandr.GetCurrentMode(currout.name); ++ ++ if (m_xrandrOut.name.empty()) ++ { ++ m_xrandrOut = currout; ++ m_xrandrMode = currmode; ++ } ++ ++ if(!m_bFullScreen) + { ++ // reset to mode we had before internal mode switch ++ out = m_xrandrOut; ++ mode = m_xrandrMode; ++ } ++ ++ // only call xrandr if mode changes ++ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || ++ currmode.hz != mode.hz || currmode.id != mode.id) ++ { ++ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); + OnLostDevice(); ++ m_internalModeSwitch = true; + g_xrandr.SetMode(out, mode); + } +- else +- g_xrandr.RestoreState(); ++ + #endif + + int options = SDL_OPENGL; +@@ -493,6 +554,7 @@ + if (bGotEvent || bTimeout) + { + CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); ++ RefreshWindow(); + + CSingleLock lock(m_resourceSection); + +diff -Naur xbmc-1fef727/xbmc/windowing/X11/WinSystemX11.h xbmc-1fef727.patch/xbmc/windowing/X11/WinSystemX11.h +--- xbmc-1fef727/xbmc/windowing/X11/WinSystemX11.h 2012-02-07 12:46:51.000000000 +0100 ++++ xbmc-1fef727.patch/xbmc/windowing/X11/WinSystemX11.h 2012-02-07 14:30:18.085099890 +0100 +@@ -27,6 +27,7 @@ + #include "utils/Stopwatch.h" + #include + #include "threads/CriticalSection.h" ++#include "XRandR.h" + + class IDispResource; + +@@ -60,6 +61,7 @@ + // Local to WinSystemX11 only + Display* GetDisplay() { return m_dpy; } + GLXWindow GetWindow() { return m_glWindow; } ++ void RefreshWindow(); + + protected: + bool RefreshGlxContext(); +@@ -76,6 +78,9 @@ + CCriticalSection m_resourceSection; + std::vector m_resources; + uint64_t m_dpyLostTime; ++ XOutput m_xrandrOut; ++ XMode m_xrandrMode; ++ bool m_internalModeSwitch; + + private: + bool IsSuitableVisual(XVisualInfo *vInfo);