diff --git a/packages/mediacenter/xbmc-master-theme-Confluence/package.mk b/packages/mediacenter/xbmc-master-theme-Confluence/package.mk new file mode 100644 index 0000000000..f605dda03e --- /dev/null +++ b/packages/mediacenter/xbmc-master-theme-Confluence/package.mk @@ -0,0 +1,52 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +PKG_NAME="xbmc-master-theme-Confluence" +PKG_VERSION="14-088e9fa" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://www.xbmc.org" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain xbmc-master" +PKG_PRIORITY="optional" +PKG_SECTION="mediacenter" +PKG_SHORTDESC="xbmc-theme-Confluence: XBMC Mediacenter default theme" +PKG_LONGDESC="XBMC Media Center (which was formerly named Xbox Media Center) is a free and open source cross-platform media player and home entertainment system software with a 10-foot user interface designed for the living-room TV. Its graphical user interface allows the user to easily manage video, photos, podcasts, and music from a computer, optical disk, local network, and the internet using a remote control." + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +make_target() { + TexturePacker -input media/ \ + -output Textures.xbt \ + -dupecheck \ + -use_none +} + +makeinstall_target() { + mkdir -p $INSTALL/usr/share/xbmc/addons/skin.confluence + cp -R */ $INSTALL/usr/share/xbmc/addons/skin.confluence + cp *.txt $INSTALL/usr/share/xbmc/addons/skin.confluence + cp *.xml $INSTALL/usr/share/xbmc/addons/skin.confluence + cp *.png $INSTALL/usr/share/xbmc/addons/skin.confluence + rm -rf $INSTALL/usr/share/xbmc/addons/skin.confluence/media + + mkdir -p $INSTALL/usr/share/xbmc/addons/skin.confluence/media + cp Textures.xbt $INSTALL/usr/share/xbmc/addons/skin.confluence/media +} diff --git a/packages/mediacenter/xbmc-master-theme-Confluence/patches/xbmc-master-theme-Confluence-001-add_oe_settings_to_homescreen.patch b/packages/mediacenter/xbmc-master-theme-Confluence/patches/xbmc-master-theme-Confluence-001-add_oe_settings_to_homescreen.patch new file mode 100644 index 0000000000..79a3addf5a --- /dev/null +++ b/packages/mediacenter/xbmc-master-theme-Confluence/patches/xbmc-master-theme-Confluence-001-add_oe_settings_to_homescreen.patch @@ -0,0 +1,14 @@ +--- a/720p/IncludesHomeMenuItems.xml 2012-07-22 21:56:07.000000000 +0400 ++++ b/720p/IncludesHomeMenuItems.xml 2012-09-13 23:34:16.975470148 +0400 +@@ -189,6 +189,11 @@ + + ActivateWindow(Settings) + ++ ++ ButtonHomeSubCommonValues ++ ++ RunAddon(service.openelec.settings) ++ + + ButtonHomeSubCommonValues + diff --git a/packages/mediacenter/xbmc-master/config/advancedsettings.xml b/packages/mediacenter/xbmc-master/config/advancedsettings.xml new file mode 100644 index 0000000000..c54111aaa3 --- /dev/null +++ b/packages/mediacenter/xbmc-master/config/advancedsettings.xml @@ -0,0 +1,23 @@ + + + false + cputemp + gputemp + + + 30 + + + 4.0 + + diff --git a/packages/mediacenter/xbmc-master/config/appliance.xml b/packages/mediacenter/xbmc-master/config/appliance.xml new file mode 100644 index 0000000000..98fd49f28c --- /dev/null +++ b/packages/mediacenter/xbmc-master/config/appliance.xml @@ -0,0 +1,49 @@ + + +
+ + + + false + + + +
+ +
+ + + + true + + + + + + + + true + + + + + + + + true + + + +
+ +
+ + + + /usr/bin/setwakeup.sh + + + +
+ +
diff --git a/packages/mediacenter/xbmc-master/config/os.openelec.tv/addon.xml b/packages/mediacenter/xbmc-master/config/os.openelec.tv/addon.xml new file mode 100644 index 0000000000..206659f9da --- /dev/null +++ b/packages/mediacenter/xbmc-master/config/os.openelec.tv/addon.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/mediacenter/xbmc-master/config/repository.openelec.tv/addon.xml b/packages/mediacenter/xbmc-master/config/repository.openelec.tv/addon.xml new file mode 100644 index 0000000000..7b21ca7f12 --- /dev/null +++ b/packages/mediacenter/xbmc-master/config/repository.openelec.tv/addon.xml @@ -0,0 +1,17 @@ + + + + @ADDON_URL@/addons.xml + @ADDON_URL@/addons.xml.md5 + @ADDON_URL@ + + + Install Add-ons, Plugins, Games and Programs from [COLOR FF757677]Open[/COLOR][COLOR FF8ABEE2]ELEC[/COLOR] + Download and install Add-ons, Plugins, Games and Programs from the Official [COLOR FF757677]Open[/COLOR][COLOR FF8ABEE2]ELEC[/COLOR] addon repository.[CR] By using the official Repository you will be able to take advantage of our extensive file mirror service to help get you faster downloads from a region close to you.[CR] All addons on this repository have under gone basic testing, if you find a broken or not working addon please report it to [COLOR FF757677]Open[/COLOR][COLOR FF8ABEE2]ELEC[/COLOR] so we can take any action needed. + all + + diff --git a/packages/mediacenter/xbmc-master/config/repository.openelec.tv/icon.png b/packages/mediacenter/xbmc-master/config/repository.openelec.tv/icon.png new file mode 100644 index 0000000000..1147ae1d37 Binary files /dev/null and b/packages/mediacenter/xbmc-master/config/repository.openelec.tv/icon.png differ diff --git a/packages/mediacenter/xbmc-master/debug.d/xbmc.conf b/packages/mediacenter/xbmc-master/debug.d/xbmc.conf new file mode 100644 index 0000000000..7c6c362ac3 --- /dev/null +++ b/packages/mediacenter/xbmc-master/debug.d/xbmc.conf @@ -0,0 +1 @@ +XBMC_DEBUG="--debug" diff --git a/packages/mediacenter/xbmc-master/fonts/DejaVuSans.ttf b/packages/mediacenter/xbmc-master/fonts/DejaVuSans.ttf new file mode 100644 index 0000000000..84ca1d7503 Binary files /dev/null and b/packages/mediacenter/xbmc-master/fonts/DejaVuSans.ttf differ diff --git a/packages/mediacenter/xbmc-master/fonts/Trebuchet MS Bold.ttf b/packages/mediacenter/xbmc-master/fonts/Trebuchet MS Bold.ttf new file mode 100644 index 0000000000..867f56d776 Binary files /dev/null and b/packages/mediacenter/xbmc-master/fonts/Trebuchet MS Bold.ttf differ diff --git a/packages/mediacenter/xbmc-master/fonts/YanoneKaffeesatz-Bold.ttf b/packages/mediacenter/xbmc-master/fonts/YanoneKaffeesatz-Bold.ttf new file mode 100644 index 0000000000..e9964b0809 Binary files /dev/null and b/packages/mediacenter/xbmc-master/fonts/YanoneKaffeesatz-Bold.ttf differ diff --git a/packages/mediacenter/xbmc-master/package.mk b/packages/mediacenter/xbmc-master/package.mk new file mode 100644 index 0000000000..787277878a --- /dev/null +++ b/packages/mediacenter/xbmc-master/package.mk @@ -0,0 +1,512 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +PKG_NAME="xbmc-master" +PKG_VERSION="14-088e9fa" +PKG_REV="1" +PKG_ARCH="any" +PKG_LICENSE="GPL" +PKG_SITE="http://www.xbmc.org" +PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_DEPENDS_TARGET="toolchain boost Python zlib bzip2 systemd pciutils lzo pcre swig:host libass enca curl rtmpdump fontconfig fribidi gnutls tinyxml libjpeg-turbo libpng tiff freetype jasper libsamplerate libogg libcdio libmodplug faad2 flac libmpeg2 taglib libxml2 libxslt yajl sqlite libvorbis ffmpeg" +PKG_PRIORITY="optional" +PKG_SECTION="mediacenter" +PKG_SHORTDESC="xbmc: XBMC Mediacenter" +PKG_LONGDESC="XBMC Media Center (which was formerly named Xbox Media Center) is a free and open source cross-platform media player and home entertainment system software with a 10-foot user interface designed for the living-room TV. Its graphical user interface allows the user to easily manage video, photos, podcasts, and music from a computer, optical disk, local network, and the internet using a remote control." + +PKG_IS_ADDON="no" +PKG_AUTORECONF="no" + +# for dbus support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET dbus" + +# needed for hosttools (Texturepacker) + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET lzo:host SDL:host SDL_image:host" + +if [ "$DISPLAYSERVER" = "x11" ]; then +# for libX11 support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libX11 libXext" +# for libXrandr support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libXrandr" + XBMC_XORG="--enable-x11 --enable-xrandr" +else + XBMC_XORG="--disable-x11 --disable-xrandr" +fi + +if [ "$OPENGL" = "Mesa" ]; then +# for OpenGL (GLX) support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET Mesa glu glew" + XBMC_OPENGL="--enable-gl" +else + XBMC_OPENGL="--disable-gl" +fi + +if [ "$OPENGLES_SUPPORT" = yes ]; then +# for OpenGL-ES support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $OPENGLES" + XBMC_OPENGLES="--enable-gles" +else + XBMC_OPENGLES="--disable-gles" +fi + +if [ "$SDL_SUPPORT" = yes ]; then +# for SDL support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET SDL SDL_image" + XBMC_SDL="--enable-sdl" +else + XBMC_SDL="--disable-sdl" +fi + +if [ "$ALSA_SUPPORT" = yes ]; then +# for ALSA support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET alsa-lib" + XBMC_ALSA="--enable-alsa" +else + XBMC_ALSA="--disable-alsa" +fi + +if [ "$PULSEAUDIO_SUPPORT" = yes ]; then +# for PulseAudio support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET pulseaudio" + XBMC_PULSEAUDIO="--enable-pulse" +else + XBMC_PULSEAUDIO="--disable-pulse" +fi + +if [ "$ESPEAK_SUPPORT" = yes ]; then +# for espeak support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET espeak" +fi + +if [ "$CEC_SUPPORT" = yes ]; then +# for CEC support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libcec" + XBMC_CEC="--enable-libcec" +else + XBMC_CEC="--disable-libcec" +fi + +if [ "$XBMC_SCR_RSXS" = yes ]; then +# for RSXS Screensaver support + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libXt libXmu" + XBMC_RSXS="--enable-rsxs" +# fix build of RSXS Screensaver support if not using libiconv + export jm_cv_func_gettimeofday_clobber=no +else + XBMC_RSXS="--disable-rsxs" +fi + +if [ "$XBMC_VIS_PROJECTM" = yes ]; then +# for ProjectM Visualisation support + XBMC_PROJECTM="--enable-projectm" +else + XBMC_PROJECTM="--disable-projectm" +fi + +if [ "$XBMC_VIS_GOOM" = yes ]; then +# for GOOM Visualisation support + XBMC_GOOM="--enable-goom" +else + XBMC_GOOM="--disable-goom" +fi + +if [ "$XBMC_VIS_WAVEFORM" = yes ]; then +# for Waveform Visualisation support + XBMC_WAVEFORM="--enable-waveform" +else + XBMC_WAVEFORM="--disable-waveform" +fi + +if [ "$XBMC_VIS_SPECTRUM" = yes ]; then +# for Spectrum Visualisation support + XBMC_SPECTRUM="--enable-spectrum" +else + XBMC_SPECTRUM="--disable-spectrum" +fi + +if [ "$XBMC_VIS_FISHBMC" = yes ]; then +# for FishBMC Visualisation support + XBMC_FISHBMC="--enable-fishbmc" +else + XBMC_FISHBMC="--disable-fishbmc" +fi + +if [ "$JOYSTICK_SUPPORT" = yes ]; then +# for Joystick support + XBMC_JOYSTICK="--enable-joystick" +else + XBMC_JOYSTICK="--disable-joystick" +fi + +if [ "$OPTICAL_DRIVE_SUPPORT" = yes ]; then + XBMC_OPTICAL="--enable-optical-drive" +else + XBMC_OPTICAL="--disable-optical-drive" +fi + +if [ "$NONFREE_SUPPORT" = yes ]; then +# for non-free support + XBMC_NONFREE="--enable-non-free" +else + XBMC_NONFREE="--disable-non-free" +fi + +if [ "$DVDCSS_SUPPORT" = yes ]; then + XBMC_DVDCSS="--enable-dvdcss" +else + XBMC_DVDCSS="--disable-dvdcss" +fi + +if [ "$FAAC_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET faac" +fi + +if [ "$ENCODER_LAME" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET lame" + XBMC_LAMEENC="--enable-libmp3lame" +else + XBMC_LAMEENC="--disable-libmp3lame" +fi + +if [ "$BLURAY_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libbluray" + XBMC_BLURAY="--enable-libbluray" +else + XBMC_BLURAY="--disable-libbluray" +fi + +if [ "$AVAHI_DAEMON" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET avahi" + XBMC_AVAHI="--enable-avahi" +else + XBMC_AVAHI="--disable-avahi" +fi + +if [ "$MYSQL_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET mysql" + XBMC_MYSQL="--enable-mysql" +else + XBMC_MYSQL="--disable-mysql" +fi + +if [ "$AIRPLAY_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libplist" + XBMC_AIRPLAY="--enable-airplay" +else + XBMC_AIRPLAY="--disable-airplay" +fi + +if [ "$AIRTUNES_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libshairplay" + XBMC_AIRTUNES="--enable-airtunes" +else + XBMC_AIRTUNES="--disable-airtunes" +fi + +if [ "$NFS_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libnfs" + XBMC_NFS="--enable-nfs" +else + XBMC_NFS="--disable-nfs" +fi + +if [ "$AFP_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET afpfs-ng" + XBMC_AFP="--enable-afpclient" +else + XBMC_AFP="--disable-afpclient" +fi + +if [ "$SAMBA_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET samba" + XBMC_SAMBA="--enable-samba" +else + XBMC_SAMBA="--disable-samba" +fi + +if [ "$WEBSERVER" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libmicrohttpd" + XBMC_WEBSERVER="--enable-webserver" +else + XBMC_WEBSERVER="--disable-webserver" +fi + +if [ "$UPNP_SUPPORT" = yes ]; then + XBMC_UPNP="--enable-upnp" +else + XBMC_UPNP="--disable-upnp" +fi + +if [ "$SSHLIB_SUPPORT" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libssh" + XBMC_SSH="--enable-ssh" +else + XBMC_SSH="--disable-ssh" +fi + +if [ ! "$XBMCPLAYER_DRIVER" = default ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $XBMCPLAYER_DRIVER" + + if [ "$XBMCPLAYER_DRIVER" = bcm2835-driver ]; then + XBMC_OPENMAX="--enable-openmax" + XBMC_PLAYER="--enable-player=omxplayer" + XBMC_CODEC="--with-platform=raspberry-pi" + BCM2835_INCLUDES="-I$SYSROOT_PREFIX/usr/include/interface/vcos/pthreads/ \ + -I$SYSROOT_PREFIX/usr/include/interface/vmcs_host/linux" + XBMC_CFLAGS="$XBMC_CFLAGS $BCM2835_INCLUDES" + XBMC_CXXFLAGS="$XBMC_CXXFLAGS $BCM2835_INCLUDES" + elif [ "$XBMCPLAYER_DRIVER" = libfslvpuwrap ]; then + XBMC_CODEC="--enable-codec=imxvpu" + else + XBMC_OPENMAX="--disable-openmax" + fi +fi + +if [ "$VDPAU" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET libvdpau" + XBMC_VDPAU="--enable-vdpau" +else + XBMC_VDPAU="--disable-vdpau" +fi + +if [ "$VAAPI" = yes ]; then +# configure GPU drivers and dependencies: + get_graphicdrivers + + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $LIBVA" + XBMC_VAAPI="--enable-vaapi" +else + XBMC_VAAPI="--disable-vaapi" +fi + +if [ "$CRYSTALHD" = yes ]; then + PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET crystalhd" + XBMC_CRYSTALHD="--enable-crystalhd" +else + XBMC_CRYSTALHD="--disable-crystalhd" +fi + +export CXX_FOR_BUILD="$HOST_CXX" +export CC_FOR_BUILD="$HOST_CC" +export CXXFLAGS_FOR_BUILD="$HOST_CXXFLAGS" +export CFLAGS_FOR_BUILD="$HOST_CFLAGS" +export LDFLAGS_FOR_BUILD="$HOST_LDFLAGS" + +export PYTHON_VERSION="2.7" +export PYTHON_CPPFLAGS="-I$SYSROOT_PREFIX/usr/include/python$PYTHON_VERSION" +export PYTHON_LDFLAGS="-L$SYSROOT_PREFIX/usr/lib/python$PYTHON_VERSION -lpython$PYTHON_VERSION" +export PYTHON_SITE_PKG="$SYSROOT_PREFIX/usr/lib/python$PYTHON_VERSION/site-packages" +export ac_python_version="$PYTHON_VERSION" + +PKG_CONFIGURE_OPTS_TARGET="gl_cv_func_gettimeofday_clobber=no \ + ac_cv_lib_bluetooth_hci_devid=no \ + --disable-debug \ + --disable-optimizations \ + $XBMC_OPENGL \ + $XBMC_OPENGLES \ + $XBMC_SDL \ + $XBMC_OPENMAX \ + $XBMC_VDPAU \ + $XBMC_VAAPI \ + $XBMC_CRYSTALHD \ + --disable-vtbdecoder \ + --disable-tegra \ + --disable-profiling \ + $XBMC_JOYSTICK \ + $XBMC_CEC \ + --enable-udev \ + --disable-libusb \ + $XBMC_GOOM \ + $XBMC_RSXS \ + $XBMC_PROJECTM \ + $XBMC_WAVEFORM \ + $XBMC_SPECTRUM \ + $XBMC_FISHBMC \ + $XBMC_XORG \ + --disable-ccache \ + $XBMC_ALSA \ + $XBMC_PULSEAUDIO \ + --enable-rtmp \ + $XBMC_SAMBA \ + $XBMC_NFS \ + $XBMC_AFP \ + --enable-libvorbisenc \ + --disable-libcap \ + $XBMC_LAMEENC \ + $XBMC_DVDCSS \ + --disable-mid \ + --disable-hal \ + $XBMC_AVAHI \ + $XBMC_UPNP \ + $XBMC_MYSQL \ + $XBMC_SSH \ + $XBMC_AIRPLAY \ + $XBMC_AIRTUNES \ + $XBMC_NONFREE \ + --disable-asap-codec \ + $XBMC_WEBSERVER \ + $XBMC_OPTICAL \ + $XBMC_BLURAY \ + --enable-texturepacker \ + $XBMC_CODEC \ + $XBMC_PLAYER" + +pre_build_target() { +# adding fake Makefile for stripped skin + mkdir -p $PKG_BUILD/addons/skin.confluence/media + touch $PKG_BUILD/addons/skin.confluence/media/Makefile.in + +# autoreconf + BOOTSTRAP_STANDALONE=1 make -C $PKG_BUILD -f bootstrap.mk +} + +pre_configure_target() { +# xbmc fails to build in subdirs + cd $ROOT/$PKG_BUILD + rm -rf .$TARGET_NAME + +# xbmc fails to build with LTO optimization if build without GOLD support + [ ! "$GOLD_SUPPORT" = "yes" ] && strip_lto + +# Todo: XBMC segfaults on exit when building with LTO support + strip_lto + + export CFLAGS="$CFLAGS $XBMC_CFLAGS" + export CXXFLAGS="$CXXFLAGS $XBMC_CXXFLAGS" + export LIBS="$LIBS -lz" +} + +make_target() { +# build helpertools for host + make -C tools/depends/native/JsonSchemaBuilder \ + CXX="$HOST_CXX" CFLAGS="$HOST_CXXFLAGS" LFLAGS="$HOST_LDFLAGS" + +# setup skin dir from default skin + SKIN_DIR="skin.`tolower $SKIN_DEFAULT`" + +# setup default skin inside the sources + sed -i -e "s|skin.confluence|$SKIN_DIR|g" $ROOT/$PKG_BUILD/xbmc/settings/Settings.h + + make externals + make xbmc.bin + + if [ "$DISPLAYSERVER" = "x11" ]; then + make xbmc-xrandr + fi + + make -C tools/TexturePacker + cp -PR tools/TexturePacker/TexturePacker $ROOT/$TOOLCHAIN/bin +} + +post_makeinstall_target() { + rm -rf $INSTALL/usr/bin/xbmc + rm -rf $INSTALL/usr/bin/xbmc-standalone + rm -rf $INSTALL/usr/lib/xbmc/*.cmake + + mkdir -p $INSTALL/usr/lib/xbmc + cp $PKG_DIR/scripts/xbmc-config $INSTALL/usr/lib/xbmc + cp $PKG_DIR/scripts/xbmc-hacks $INSTALL/usr/lib/xbmc + cp $PKG_DIR/scripts/xbmc-sources $INSTALL/usr/lib/xbmc + + mkdir -p $INSTALL/usr/lib/openelec + cp $PKG_DIR/scripts/systemd-addon-wrapper $INSTALL/usr/lib/openelec + + mkdir -p $INSTALL/usr/bin + cp $PKG_DIR/scripts/cputemp $INSTALL/usr/bin + ln -sf cputemp $INSTALL/usr/bin/gputemp + cp $PKG_DIR/scripts/setwakeup.sh $INSTALL/usr/bin + cp tools/EventClients/Clients/XBMC\ Send/xbmc-send.py $INSTALL/usr/bin/xbmc-send + + if [ ! "$DISPLAYSERVER" = "x11" ]; then + rm -rf $INSTALL/usr/lib/xbmc/xbmc-xrandr + fi + + if [ ! "$XBMC_SCR_RSXS" = yes ]; then + rm -rf $INSTALL/usr/share/xbmc/addons/screensaver.rsxs.* + fi + + if [ ! "$XBMC_VIS_PROJECTM" = yes ]; then + rm -rf $INSTALL/usr/share/xbmc/addons/visualization.projectm + fi + + rm -rf $INSTALL/usr/share/applications + rm -rf $INSTALL/usr/share/icons + rm -rf $INSTALL/usr/share/xbmc/addons/repository.pvr-* + rm -rf $INSTALL/usr/share/xbmc/addons/script.module.pysqlite + rm -rf $INSTALL/usr/share/xbmc/addons/script.module.simplejson + rm -rf $INSTALL/usr/share/xbmc/addons/visualization.dxspectrum + rm -rf $INSTALL/usr/share/xbmc/addons/visualization.itunes + rm -rf $INSTALL/usr/share/xbmc/addons/visualization.milkdrop + rm -rf $INSTALL/usr/share/xbmc/addons/service.xbmc.versioncheck + rm -rf $INSTALL/usr/share/xsessions + + mkdir -p $INSTALL/usr/share/xbmc/addons + cp -R $PKG_DIR/config/os.openelec.tv $INSTALL/usr/share/xbmc/addons + $SED "s|@OS_VERSION@|$OS_VERSION|g" -i $INSTALL/usr/share/xbmc/addons/os.openelec.tv/addon.xml + cp -R $PKG_DIR/config/repository.openelec.tv $INSTALL/usr/share/xbmc/addons + $SED "s|@ADDON_URL@|$ADDON_URL|g" -i $INSTALL/usr/share/xbmc/addons/repository.openelec.tv/addon.xml + + mkdir -p $INSTALL/usr/lib/python"$PYTHON_VERSION"/site-packages/xbmc + cp -R tools/EventClients/lib/python/* $INSTALL/usr/lib/python"$PYTHON_VERSION"/site-packages/xbmc + +# install project specific configs + mkdir -p $INSTALL/usr/share/xbmc/config + if [ -f $PROJECT_DIR/$PROJECT/xbmc/guisettings.xml ]; then + cp -R $PROJECT_DIR/$PROJECT/xbmc/guisettings.xml $INSTALL/usr/share/xbmc/config + fi + + if [ -f $PROJECT_DIR/$PROJECT/xbmc/sources.xml ]; then + cp -R $PROJECT_DIR/$PROJECT/xbmc/sources.xml $INSTALL/usr/share/xbmc/config + fi + + mkdir -p $INSTALL/usr/share/xbmc/system/ + if [ -f $PROJECT_DIR/$PROJECT/xbmc/advancedsettings.xml ]; then + cp $PROJECT_DIR/$PROJECT/xbmc/advancedsettings.xml $INSTALL/usr/share/xbmc/system/ + else + cp $PKG_DIR/config/advancedsettings.xml $INSTALL/usr/share/xbmc/system/ + fi + + mkdir -p $INSTALL/usr/share/xbmc/system/settings + if [ -f $PROJECT_DIR/$PROJECT/xbmc/appliance.xml ]; then + cp $PROJECT_DIR/$PROJECT/xbmc/appliance.xml $INSTALL/usr/share/xbmc/system/settings + else + cp $PKG_DIR/config/appliance.xml $INSTALL/usr/share/xbmc/system/settings + fi + + if [ "$XBMC_EXTRA_FONTS" = yes ]; then + mkdir -p $INSTALL/usr/share/xbmc/media/Fonts + cp $PKG_DIR/fonts/*.ttf $INSTALL/usr/share/xbmc/media/Fonts + fi +} + +post_install() { +# link default.target to xbmc.target + ln -sf xbmc.target $INSTALL/usr/lib/systemd/system/default.target + + enable_service xbmc-autostart.service + enable_service xbmc-cleanlogs.service + enable_service xbmc-config.service + enable_service xbmc-hacks.service + enable_service xbmc-sources.service + enable_service xbmc-halt.service + enable_service xbmc-poweroff.service + enable_service xbmc-reboot.service + enable_service xbmc-waitonnetwork.service + enable_service xbmc.service + enable_service xbmc-lirc-suspend.service +} diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-101-fix_libdvd_xFLAGS-0.1.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-101-fix_libdvd_xFLAGS-0.1.patch new file mode 100644 index 0000000000..00df7bb51c --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-101-fix_libdvd_xFLAGS-0.1.patch @@ -0,0 +1,73 @@ +diff -Naur xbmc-master-14-088e9fa/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh +--- xbmc-master-14-088e9fa/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh 2014-05-01 16:53:36.000000000 +0200 ++++ xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh 2014-05-01 17:54:59.643325427 +0200 +@@ -56,17 +56,17 @@ + fi + + if test "$echo_cflags" = "yes"; then +- echo -I$prefix/include $dvdread_cflags $extracflags $threadcflags ++ echo $dvdread_cflags $extracflags $threadcflags + fi + + if test "$echo_minicflags" = "yes"; then +- echo -I$prefix/include -I$prefix/include/dvdnav $extracflags $threadcflags ++ echo $extracflags $threadcflags + fi + + if test "$echo_libs" = "yes"; then +- echo -L$libdir -ldvdnav $dvdread_libs $threadlib ++ echo -ldvdnav $dvdread_libs $threadlib + fi + + if test "$echo_minilibs" = "yes"; then +- echo -L$libdir -ldvdnavmini $threadlib ++ echo -ldvdnavmini $threadlib + fi +diff -Naur xbmc-master-14-088e9fa/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in +--- xbmc-master-14-088e9fa/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in 2014-05-01 16:53:36.000000000 +0200 ++++ xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in 2014-05-01 17:56:12.030447794 +0200 +@@ -7,5 +7,5 @@ + Description: DVD Navigation mini library + Version: @VERSION@ + +-Cflags: -I${includedir} @DVDREAD_CFLAGS@ @THREAD_CFLAGS@ +-Libs: -L${libdir} -ldvdnav @THREAD_LIBS@ ++Cflags: @DVDREAD_CFLAGS@ @THREAD_CFLAGS@ ++Libs: -ldvdnav @THREAD_LIBS@ +diff -Naur xbmc-master-14-088e9fa/lib/libdvd/libdvdnav/misc/dvdnav.pc.in xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdnav/misc/dvdnav.pc.in +--- xbmc-master-14-088e9fa/lib/libdvd/libdvdnav/misc/dvdnav.pc.in 2014-05-01 16:53:36.000000000 +0200 ++++ xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdnav/misc/dvdnav.pc.in 2014-05-01 17:55:50.427406667 +0200 +@@ -8,5 +8,5 @@ + Version: @VERSION@ + + Requires.private: dvdread >= 4.1.2 +-Cflags: -I${includedir} @THREAD_CFLAGS@ +-Libs: -L${libdir} -ldvdnav @THREAD_LIBS@ ++Cflags: @THREAD_CFLAGS@ ++Libs: -ldvdnav @THREAD_LIBS@ +diff -Naur xbmc-master-14-088e9fa/lib/libdvd/libdvdread/misc/dvdread-config.sh xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdread/misc/dvdread-config.sh +--- xbmc-master-14-088e9fa/lib/libdvd/libdvdread/misc/dvdread-config.sh 2014-05-01 16:53:36.000000000 +0200 ++++ xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdread/misc/dvdread-config.sh 2014-05-01 17:56:55.745553577 +0200 +@@ -48,9 +48,9 @@ + fi + + if test "$echo_cflags" = "yes"; then +- echo -I$prefix/include $extracflags ++ echo $extracflags + fi + + if test "$echo_libs" = "yes"; then +- echo -L$libdir $dvdreadlib ++ echo $dvdreadlib + fi +diff -Naur xbmc-master-14-088e9fa/lib/libdvd/libdvdread/misc/dvdread.pc.in xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdread/misc/dvdread.pc.in +--- xbmc-master-14-088e9fa/lib/libdvd/libdvdread/misc/dvdread.pc.in 2014-05-01 16:53:36.000000000 +0200 ++++ xbmc-master-14-088e9fa.patch/lib/libdvd/libdvdread/misc/dvdread.pc.in 2014-05-01 17:57:28.731937685 +0200 +@@ -7,5 +7,5 @@ + Description: Low level DVD access library + Version: @VERSION@ + +-Cflags: -I${includedir} +-Libs: -L${libdir} -ldvdread ++Cflags: -I. ++Libs: -ldvdread diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-102-disable_backslash-0.1.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-102-disable_backslash-0.1.patch new file mode 100644 index 0000000000..0888920258 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-102-disable_backslash-0.1.patch @@ -0,0 +1,12 @@ +diff -Naur xbmc-30a9070/system/keymaps/keyboard.xml xbmc-30a9070.patch/system/keymaps/keyboard.xml +--- xbmc-30a9070/system/keymaps/keyboard.xml 2011-07-28 06:20:13.000000000 +0200 ++++ xbmc-30a9070.patch/system/keymaps/keyboard.xml 2011-07-28 09:39:57.210973380 +0200 +@@ -90,7 +90,7 @@ + Number7 + Number8 + Number9 +- ToggleFullScreen ++ + FirstPage + LastPage + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-103-disable-online-check.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-103-disable-online-check.patch new file mode 100644 index 0000000000..6f357d3aa7 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-103-disable-online-check.patch @@ -0,0 +1,61 @@ +From 7503fd2355ab44503cf38809c5ba70ef2c0f2144 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 10 Jan 2014 19:44:16 +0200 +Subject: [PATCH] disable online check + +--- + xbmc/GUIInfoManager.cpp | 1 - + xbmc/utils/SystemInfo.cpp | 5 +---- + xbmc/windows/GUIWindowSystemInfo.cpp | 1 - + 3 files changed, 1 insertion(+), 6 deletions(-) + +diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp +index 10173ee..70a474a 100644 +--- a/xbmc/GUIInfoManager.cpp ++++ b/xbmc/GUIInfoManager.cpp +@@ -271,7 +271,6 @@ const infomap system_labels[] = {{ "hasnetwork", SYSTEM_ETHERNET_LINK_ACT + { "currentwindow", SYSTEM_CURRENT_WINDOW }, + { "currentcontrol", SYSTEM_CURRENT_CONTROL }, + { "dvdlabel", SYSTEM_DVD_LABEL }, +- { "internetstate", SYSTEM_INTERNET_STATE }, + { "kernelversion", SYSTEM_KERNEL_VERSION }, + { "uptime", SYSTEM_UPTIME }, + { "totaluptime", SYSTEM_TOTALUPTIME }, +diff --git a/xbmc/utils/SystemInfo.cpp b/xbmc/utils/SystemInfo.cpp +index c77d495..06459dc 100644 +--- a/xbmc/utils/SystemInfo.cpp ++++ b/xbmc/utils/SystemInfo.cpp +@@ -72,7 +72,6 @@ bool CSysInfoJob::DoWork() + { + m_info.systemUptime = GetSystemUpTime(false); + m_info.systemTotalUptime = GetSystemUpTime(true); +- m_info.internetState = GetInternetState(); + m_info.videoEncoder = GetVideoEncoder(); + m_info.cpuFrequency = GetCPUFreqInfo(); + m_info.kernelVersion = CSysInfo::GetKernelVersion(); +@@ -569,9 +568,7 @@ CStdString CSysInfo::GetKernelVersion() + + bool CSysInfo::HasInternet() + { +- if (m_info.internetState != CSysData::UNKNOWN) +- return m_info.internetState == CSysData::CONNECTED; +- return (m_info.internetState = CSysInfoJob::GetInternetState()) == CSysData::CONNECTED; ++ return m_info.internetState == CSysData::UNKNOWN; + } + + CStdString CSysInfo::GetHddSpaceInfo(int drive, bool shortText) +diff --git a/xbmc/windows/GUIWindowSystemInfo.cpp b/xbmc/windows/GUIWindowSystemInfo.cpp +index 60aa49d..a0a2e27 100644 +--- a/xbmc/windows/GUIWindowSystemInfo.cpp ++++ b/xbmc/windows/GUIWindowSystemInfo.cpp +@@ -126,7 +126,6 @@ void CGUIWindowSystemInfo::FrameMove() + SetControlLabel(i++, "%s: %s", 13160, NETWORK_GATEWAY_ADDRESS); + SetControlLabel(i++, "%s: %s", 13161, NETWORK_DNS1_ADDRESS); + SetControlLabel(i++, "%s: %s", 20307, NETWORK_DNS2_ADDRESS); +- SetControlLabel(i++, "%s %s", 13295, SYSTEM_INTERNET_STATE); + } + else if (m_section == CONTROL_BT_VIDEO) + { +-- +1.8.3.2 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-104-use-udevil-to-umount.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-104-use-udevil-to-umount.patch new file mode 100644 index 0000000000..86bfb5c4fe --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-104-use-udevil-to-umount.patch @@ -0,0 +1,39 @@ +From 855160db446fe0059f072b207d53c15ba18d952f Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Thu, 17 Apr 2014 12:12:50 +0300 +Subject: [PATCH] use udevil to umount + +--- + xbmc/linux/PosixMountProvider.cpp | 2 +- + xbmc/storage/linux/UDevProvider.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/linux/PosixMountProvider.cpp b/xbmc/linux/PosixMountProvider.cpp +index 2339709..7001563 100644 +--- a/xbmc/linux/PosixMountProvider.cpp ++++ b/xbmc/linux/PosixMountProvider.cpp +@@ -131,7 +131,7 @@ bool CPosixMountProvider::Eject(CStdString mountpath) + { + // just go ahead and try to umount the disk + // if it does umount, life is good, if not, no loss. +- std::string cmd = "umount \"" + mountpath + "\""; ++ std::string cmd = "udevil umount \"" + mountpath + "\""; + int status = system(cmd.c_str()); + + if (status == 0) +diff --git a/xbmc/storage/linux/UDevProvider.cpp b/xbmc/storage/linux/UDevProvider.cpp +index 73aa408..8bd02b6 100644 +--- a/xbmc/storage/linux/UDevProvider.cpp ++++ b/xbmc/storage/linux/UDevProvider.cpp +@@ -183,7 +183,7 @@ bool CUDevProvider::Eject(CStdString mountpath) + { + // just go ahead and try to umount the disk + // if it does umount, life is good, if not, no loss. +- std::string cmd = "umount \"" + mountpath + "\""; ++ std::string cmd = "udevil umount \"" + mountpath + "\""; + int status = system(cmd.c_str()); + + if (status == 0) +-- +1.9.1 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-501-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-501-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch new file mode 100644 index 0000000000..d58eeecb9d --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-501-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch @@ -0,0 +1,18 @@ +diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp +index 01a129e..07b4878 100644 +--- a/xbmc/interfaces/python/XBPython.cpp ++++ b/xbmc/interfaces/python/XBPython.cpp +@@ -445,10 +445,9 @@ bool XBPython::InitializeEngine() + // at http://docs.python.org/using/cmdline.html#environment-variables + + #if !defined(TARGET_WINDOWS) && !defined(TARGET_ANDROID) +- /* PYTHONOPTIMIZE is set off intentionally when using external Python. +- Reason for this is because we cannot be sure what version of Python +- was used to compile the various Python object files (i.e. .pyo, +- .pyc, etc.). */ ++ // Required for python to find optimized code (pyo) files ++ setenv("PYTHONOPTIMIZE", "1", 1); ++ + // check if we are running as real xbmc.app or just binary + if (!CUtil::GetFrameworksPath(true).empty()) + { diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-502-add_openelec.tv_RSS_news-0.1.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-502-add_openelec.tv_RSS_news-0.1.patch new file mode 100644 index 0000000000..f0b08b5e8d --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-502-add_openelec.tv_RSS_news-0.1.patch @@ -0,0 +1,11 @@ +diff -Naur xbmc-12.0.7/userdata/RssFeeds.xml xbmc-12.0.7.patch/userdata/RssFeeds.xml +--- xbmc-12.0.7/userdata/RssFeeds.xml 2013-03-15 14:25:26.000000000 +0100 ++++ xbmc-12.0.7.patch/userdata/RssFeeds.xml 2013-03-15 14:40:54.695338102 +0100 +@@ -3,6 +3,7 @@ + + + ++ http://feeds.openelec.tv/news + http://feeds.xbmc.org/xbmc + + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-990.15-depends-mark_our_wrapped_functions_as_used.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-990.15-depends-mark_our_wrapped_functions_as_used.patch new file mode 100644 index 0000000000..7e78fbb3b9 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-990.15-depends-mark_our_wrapped_functions_as_used.patch @@ -0,0 +1,458 @@ +From 0c2eaf5082a30fb06bad553775e805a745d59ee2 Mon Sep 17 00:00:00 2001 +From: theuni +Date: Tue, 22 Jan 2013 04:09:07 -0500 +Subject: [PATCH] depends: mark our wrapped functions as used + +otherwise they get stripped when enabling dead code stripping +--- + xbmc/cores/DllLoader/exports/wrapper.c | 138 ++++++++++++++++----------------- + 1 file changed, 69 insertions(+), 69 deletions(-) + +diff -Naur xbmc-f81d56e/xbmc/cores/DllLoader/exports/wrapper.c xbmc-f81d56e.patch/xbmc/cores/DllLoader/exports/wrapper.c +--- xbmc-f81d56e/xbmc/cores/DllLoader/exports/wrapper.c 2013-05-18 12:30:19.000000000 +0200 ++++ xbmc-f81d56e.patch/xbmc/cores/DllLoader/exports/wrapper.c 2013-05-18 16:55:55.222087716 +0200 +@@ -115,7 +115,7 @@ + int dll_setvbuf(FILE *stream, char *buf, int type, size_t size); + struct mntent *dll_getmntent(FILE *fp); + +-void *__wrap_dlopen(const char *filename, int flag) ++__attribute__((used)) void *__wrap_dlopen(const char *filename, int flag) + { + #if defined(TARGET_ANDROID) + return dll_dlopen(filename, flag); +@@ -124,213 +124,213 @@ + #endif + } + +-FILE *__wrap_popen(const char *command, const char *mode) ++__attribute__((used)) FILE *__wrap_popen(const char *command, const char *mode) + { + return dll_popen(command, mode); + } + +-void* __wrap_calloc( size_t num, size_t size ) ++__attribute__((used)) void* __wrap_calloc( size_t num, size_t size ) + { + return dllcalloc(num, size); + } + +-void* __wrap_malloc(size_t size) ++__attribute__((used)) void* __wrap_malloc(size_t size) + { + return dllmalloc(size); + } + +-void* __wrap_realloc( void *memblock, size_t size ) ++__attribute__((used)) void* __wrap_realloc( void *memblock, size_t size ) + { + return dllrealloc(memblock, size); + } + +-void __wrap_free( void* pPtr ) ++__attribute__((used)) void __wrap_free( void* pPtr ) + { + dllfree(pPtr); + } + +-int __wrap_open(const char *file, int oflag, ...) ++__attribute__((used)) int __wrap_open(const char *file, int oflag, ...) + { + return dll_open(file, oflag); + } + +-int __wrap_open64(const char *file, int oflag, ...) ++__attribute__((used)) int __wrap_open64(const char *file, int oflag, ...) + { + return dll_open(file, oflag); + } + +-int __wrap_close(int fd) ++__attribute__((used)) int __wrap_close(int fd) + { + return dll_close(fd); + } + +-ssize_t __wrap_write(int fd, const void *buf, size_t count) ++__attribute__((used)) ssize_t __wrap_write(int fd, const void *buf, size_t count) + { + return dll_write(fd, buf, count); + } + +-ssize_t __wrap_read(int fd, void *buf, size_t count) ++__attribute__((used)) ssize_t __wrap_read(int fd, void *buf, size_t count) + { + return dll_read(fd, buf, count); + } + +-__off_t __wrap_lseek(int fildes, __off_t offset, int whence) ++__attribute__((used)) __off_t __wrap_lseek(int fildes, __off_t offset, int whence) + { + return dll_lseek(fildes, offset, whence); + } + +-__off64_t __wrap_lseek64(int fildes, __off64_t offset, int whence) ++__attribute__((used)) __off64_t __wrap_lseek64(int fildes, __off64_t offset, int whence) + { + __off64_t seekRes = dll_lseeki64(fildes, offset, whence); + return seekRes; + } + +-int __wrap_fclose(FILE *fp) ++__attribute__((used)) int __wrap_fclose(FILE *fp) + { + return dll_fclose(fp); + } + +-int __wrap_ferror(FILE *stream) ++__attribute__((used)) int __wrap_ferror(FILE *stream) + { + return dll_ferror(stream); + } + +-void __wrap_clearerr(FILE *stream) ++__attribute__((used)) void __wrap_clearerr(FILE *stream) + { + return dll_clearerr(stream); + } + +-int __wrap_feof(FILE *stream) ++__attribute__((used)) int __wrap_feof(FILE *stream) + { + return dll_feof(stream); + } + +-int __wrap_fileno(FILE *stream) ++__attribute__((used)) int __wrap_fileno(FILE *stream) + { + return dll_fileno(stream); + } + +-FILE *__wrap_fopen(const char *path, const char *mode) ++__attribute__((used)) FILE *__wrap_fopen(const char *path, const char *mode) + { + return dll_fopen(path, mode); + } + +-FILE *__wrap_fopen64(const char *path, const char *mode) ++__attribute__((used)) FILE *__wrap_fopen64(const char *path, const char *mode) + { + return dll_fopen(path, mode); + } + +-FILE *__wrap_fdopen(int fildes, const char *mode) ++__attribute__((used)) FILE *__wrap_fdopen(int fildes, const char *mode) + { + return dll_fdopen(fildes, mode); + } + +-FILE *__wrap_freopen(const char *path, const char *mode, FILE *stream) ++__attribute__((used)) FILE *__wrap_freopen(const char *path, const char *mode, FILE *stream) + { + return dll_freopen(path, mode, stream); + } + +-size_t __wrap_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) ++__attribute__((used)) size_t __wrap_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) + { + return dll_fread(ptr, size, nmemb, stream); + } + +-size_t __wrap_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) ++__attribute__((used)) size_t __wrap_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) + { + return dll_fwrite(ptr, size, nmemb, stream); + } + +-int __wrap_fflush(FILE *stream) ++__attribute__((used)) int __wrap_fflush(FILE *stream) + { + return dll_fflush(stream); + } + +-int __wrap_fputc(int c, FILE *stream) ++__attribute__((used)) int __wrap_fputc(int c, FILE *stream) + { + return dll_fputc(c, stream); + } + +-int __wrap_fputs(const char *s, FILE *stream) ++__attribute__((used)) int __wrap_fputs(const char *s, FILE *stream) + { + return dll_fputs(s, stream); + } + +-int __wrap__IO_putc(int c, FILE *stream) ++__attribute__((used)) int __wrap__IO_putc(int c, FILE *stream) + { + return dll_putc(c, stream); + } + +-int __wrap_fseek(FILE *stream, long offset, int whence) ++__attribute__((used)) int __wrap_fseek(FILE *stream, long offset, int whence) + { + return dll_fseek(stream, offset, whence); + } + +-int __wrap_fseeko64(FILE *stream, off64_t offset, int whence) ++__attribute__((used)) int __wrap_fseeko64(FILE *stream, off64_t offset, int whence) + { + return dll_fseek64(stream, offset, whence); + } + +-long __wrap_ftell(FILE *stream) ++__attribute__((used)) long __wrap_ftell(FILE *stream) + { + return dll_ftell(stream); + } + +-off64_t __wrap_ftello64(FILE *stream) ++__attribute__((used)) off64_t __wrap_ftello64(FILE *stream) + { + return dll_ftell64(stream); + } + +-void __wrap_rewind(FILE *stream) ++__attribute__((used)) void __wrap_rewind(FILE *stream) + { + dll_rewind(stream); + } + +-int __wrap_fgetpos(FILE *stream, fpos_t *pos) ++__attribute__((used)) int __wrap_fgetpos(FILE *stream, fpos_t *pos) + { + return dll_fgetpos(stream, pos); + } + +-int __wrap_fgetpos64(FILE *stream, fpos64_t *pos) ++__attribute__((used)) int __wrap_fgetpos64(FILE *stream, fpos64_t *pos) + { + return dll_fgetpos64(stream, pos); + } + +-int __wrap_fsetpos(FILE *stream, fpos_t *pos) ++__attribute__((used)) int __wrap_fsetpos(FILE *stream, fpos_t *pos) + { + return dll_fsetpos(stream, pos); + } + +-int __wrap_fsetpos64(FILE *stream, fpos64_t *pos) ++__attribute__((used)) int __wrap_fsetpos64(FILE *stream, fpos64_t *pos) + { + return dll_fsetpos64(stream, pos); + } + +-DIR * __wrap_opendir(const char *name) ++__attribute__((used)) DIR * __wrap_opendir(const char *name) + { + return dll_opendir(name); + } + +-struct dirent * __wrap_readdir(DIR* dirp) ++__attribute__((used)) struct dirent * __wrap_readdir(DIR* dirp) + { + return dll_readdir(dirp); + } + +-struct dirent * __wrap_readdir64(DIR* dirp) ++__attribute__((used)) struct dirent * __wrap_readdir64(DIR* dirp) + { + return dll_readdir(dirp); + } + +-int __wrap_closedir(DIR* dirp) ++__attribute__((used)) int __wrap_closedir(DIR* dirp) + { + return dll_closedir(dirp); + } + +-void __wrap_rewinddir(DIR* dirp) ++__attribute__((used)) void __wrap_rewinddir(DIR* dirp) + { + dll_rewinddir(dirp); + } + +-int __wrap_fprintf(FILE *stream, const char *format, ...) ++__attribute__((used)) int __wrap_fprintf(FILE *stream, const char *format, ...) + { + int res; + va_list va; +@@ -340,12 +340,12 @@ + return res; + } + +-int __wrap_vfprintf(FILE *stream, const char *format, va_list ap) ++__attribute__((used)) int __wrap_vfprintf(FILE *stream, const char *format, va_list ap) + { + return dll_vfprintf(stream, format, ap); + } + +-int __wrap_printf(const char *format, ...) ++__attribute__((used)) int __wrap_printf(const char *format, ...) + { + int res; + va_list va; +@@ -355,42 +355,42 @@ + return res; + } + +-int __wrap_fgetc(FILE *stream) ++__attribute__((used)) int __wrap_fgetc(FILE *stream) + { + return dll_fgetc(stream); + } + +-char *__wrap_fgets(char *s, int size, FILE *stream) ++__attribute__((used)) char *__wrap_fgets(char *s, int size, FILE *stream) + { + return dll_fgets(s, size, stream); + } + +-int __wrap__IO_getc(FILE *stream) ++__attribute__((used)) int __wrap__IO_getc(FILE *stream) + { + return dll_getc(stream); + } + +-int __wrap__IO_getc_unlocked(FILE *stream) ++__attribute__((used)) int __wrap__IO_getc_unlocked(FILE *stream) + { + return dll_getc(stream); + } + +-int __wrap_getc_unlocked(FILE *stream) ++__attribute__((used)) int __wrap_getc_unlocked(FILE *stream) + { + return dll_getc(stream); + } + +-int __wrap_ungetc(int c, FILE *stream) ++__attribute__((used)) int __wrap_ungetc(int c, FILE *stream) + { + return dll_ungetc(c, stream); + } + +-int __wrap_getc(FILE *stream) ++__attribute__((used)) int __wrap_getc(FILE *stream) + { + return dll_getc(stream); + } + +-int __wrap_ioctl(int d, unsigned long int request, ...) ++__attribute__((used)) int __wrap_ioctl(int d, unsigned long int request, ...) + { + int res; + va_list va; +@@ -400,57 +400,57 @@ + return res; + } + +-int __wrap__stat(const char *path, struct _stat *buffer) ++__attribute__((used)) int __wrap__stat(const char *path, struct _stat *buffer) + { + return dll_stat(path, buffer); + } + +-int __wrap_stat(const char *path, struct _stat *buffer) ++__attribute__((used)) int __wrap_stat(const char *path, struct _stat *buffer) + { + return dll_stat(path, buffer); + } + +-int __wrap___xstat64(int __ver, const char *__filename, struct stat64 *__stat_buf) ++__attribute__((used)) int __wrap___xstat64(int __ver, const char *__filename, struct stat64 *__stat_buf) + { + return dll_stat64(__filename, __stat_buf); + } + +-int __wrap___lxstat64(int __ver, const char *__filename, struct stat64 *__stat_buf) ++__attribute__((used)) int __wrap___lxstat64(int __ver, const char *__filename, struct stat64 *__stat_buf) + { + return dll_stat64(__filename, __stat_buf); + } + +-void __wrap_flockfile(FILE *file) ++__attribute__((used)) void __wrap_flockfile(FILE *file) + { + dll_flockfile(file); + } + +-int __wrap_ftrylockfile(FILE *file) ++__attribute__((used)) int __wrap_ftrylockfile(FILE *file) + { + return dll_ftrylockfile(file); + } + +-void __wrap_funlockfile(FILE *file) ++__attribute__((used)) void __wrap_funlockfile(FILE *file) + { + dll_funlockfile(file); + } + +-int __wrap___fxstat64(int ver, int fd, struct stat64 *buf) ++__attribute__((used)) int __wrap___fxstat64(int ver, int fd, struct stat64 *buf) + { + return dll_fstat64(fd, buf); + } + +-int __wrap_fstat(int fd, struct _stat *buf) ++__attribute__((used)) int __wrap_fstat(int fd, struct _stat *buf) + { + return dll_fstat(fd, buf); + } + +-int __wrap_setvbuf(FILE *stream, char *buf, int type, size_t size) ++__attribute__((used)) int __wrap_setvbuf(FILE *stream, char *buf, int type, size_t size) + { + return dll_setvbuf(stream, buf, type, size); + } + +-struct mntent *__wrap_getmntent(FILE *fp) ++__attribute__((used)) struct mntent *__wrap_getmntent(FILE *fp) + { + #ifdef _LINUX + return dll_getmntent(fp); +@@ -464,12 +464,12 @@ + // thing to actually call our wrapped functions. + #if _FORTIFY_SOURCE > 1 + +-size_t __wrap___fread_chk(void * ptr, size_t ptrlen, size_t size, size_t n, FILE * stream) ++__attribute__((used)) size_t __wrap___fread_chk(void * ptr, size_t ptrlen, size_t size, size_t n, FILE * stream) + { + return dll_fread(ptr, size, n, stream); + } + +-int __wrap___printf_chk(int flag, const char *format, ...) ++__attribute__((used)) int __wrap___printf_chk(int flag, const char *format, ...) + { + int res; + va_list va; +@@ -479,12 +479,12 @@ + return res; + } + +-int __wrap___vfprintf_chk(FILE* stream, int flag, const char *format, _G_va_list ap) ++__attribute__((used)) int __wrap___vfprintf_chk(FILE* stream, int flag, const char *format, _G_va_list ap) + { + return dll_vfprintf(stream, format, ap); + } + +-int __wrap___fprintf_chk(FILE * stream, int flag, const char *format, ...) ++__attribute__((used)) int __wrap___fprintf_chk(FILE * stream, int flag, const char *format, ...) + { + int res; + va_list va; +@@ -494,12 +494,12 @@ + return res; + } + +-char *__wrap___fgets_chk(char *s, size_t size, int n, FILE *stream) ++__attribute__((used)) char *__wrap___fgets_chk(char *s, size_t size, int n, FILE *stream) + { + return dll_fgets(s, n, stream); + } + +-size_t __wrap___read_chk(int fd, void *buf, size_t nbytes, size_t buflen) ++__attribute__((used)) size_t __wrap___read_chk(int fd, void *buf, size_t nbytes, size_t buflen) + { + return dll_read(fd, buf, nbytes); + } diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.01-fernetmenta-fixes-40dad6e.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.01-fernetmenta-fixes-40dad6e.patch new file mode 100644 index 0000000000..5ec3bbe576 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.01-fernetmenta-fixes-40dad6e.patch @@ -0,0 +1,3603 @@ +From 8b2e394a1d9b4b0a3942ae1d2f76aaa20916119e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:34:39 +0200 +Subject: [PATCH 01/31] videoplayer: adapt lateness detection and dropping to + buffering + +--- + xbmc/cores/VideoRenderers/RenderManager.cpp | 16 +- + xbmc/cores/VideoRenderers/RenderManager.h | 12 +- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 15 +- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 31 ++++ + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 + + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 194 +++++++++++++++++---- + xbmc/cores/dvdplayer/DVDPlayerVideo.h | 23 +++ + 7 files changed, 260 insertions(+), 38 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index 6832721..f4b381e 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -286,6 +286,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi + m_bIsStarted = true; + m_bReconfigured = true; + m_presentstep = PRESENT_IDLE; ++ m_presentpts = DVD_NOPTS_VALUE; ++ m_sleeptime = 1.0; + m_presentevent.notifyAll(); + + m_firstFlipPage = false; // tempfix +@@ -629,7 +631,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) + m_pRenderer->SetViewMode(iViewMode); + } + +-void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) ++void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) + { + { CSharedLock lock(m_sharedSection); + +@@ -697,6 +699,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L + m.timestamp = timestamp; + m.presentfield = sync; + m.presentmethod = presentmethod; ++ m.pts = pts; + requeue(m_queued, m_free); + + /* signal to any waiters to check state */ +@@ -1065,6 +1068,8 @@ void CXBMCRenderManager::PrepareNextRender() + m_discard.push_back(m_presentsource); + m_presentsource = idx; + m_queued.pop_front(); ++ m_sleeptime = m_Queue[idx].timestamp - clocktime; ++ m_presentpts = m_Queue[idx].pts; + m_presentevent.notifyAll(); + } + } +@@ -1081,3 +1086,12 @@ void CXBMCRenderManager::DiscardBuffer() + m_presentstep = PRESENT_IDLE; + m_presentevent.notifyAll(); + } ++ ++bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel) ++{ ++ CSingleLock lock(m_presentlock); ++ sleeptime = m_sleeptime; ++ pts = m_presentpts; ++ bufferLevel = m_queued.size() + m_discard.size(); ++ return true; ++} +diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h +index c469795..949c652b 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoRenderers/RenderManager.h +@@ -98,10 +98,11 @@ class CXBMCRenderManager + * + * @param bStop reference to stop flag of calling thread + * @param timestamp of frame delivered with AddVideoPicture ++ * @param pts used for lateness detection + * @param source depreciated + * @param sync signals frame, top, or bottom field + */ +- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); ++ void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); + unsigned int PreInit(); + void UnInit(); + bool Flush(); +@@ -176,6 +177,12 @@ class CXBMCRenderManager + int WaitForBuffer(volatile bool& bStop, int timeout = 100); + + /** ++ * Can be called by player for lateness detection. This is done best by ++ * looking at the end of the queue. ++ */ ++ bool GetStats(double &sleeptime, double &pts, int &bufferLevel); ++ ++ /** + * Video player call this on flush in oder to discard any queued frames + */ + void DiscardBuffer(); +@@ -222,6 +229,7 @@ class CXBMCRenderManager + + struct SPresent + { ++ double pts; + double timestamp; + EFIELDSYNC presentfield; + EPRESENTMETHOD presentmethod; +@@ -233,6 +241,8 @@ class CXBMCRenderManager + + ERenderFormat m_format; + ++ double m_sleeptime; ++ double m_presentpts; + double m_presentcorr; + double m_presenterr; + double m_errorbuff[ERRORBUFFSIZE]; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +index 1553789..7761f7fa 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +@@ -134,6 +134,10 @@ struct DVDVideoUserData + #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped + #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data + ++#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage ++#define DVP_FLAG_NO_POSTPROC 0x00000100 ++#define DVP_FLAG_DRAIN 0x00000200 ++ + // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2! + + #define DVP_QSCALE_UNKNOWN 0 +@@ -151,6 +155,9 @@ class CDVDCodecOptions; + #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data + #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data + #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again ++#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped ++#define VC_HURRY 0x00000040 ++ + class CDVDVideoCodec + { + public: +@@ -268,7 +275,6 @@ class CDVDVideoCodec + return 0; + } + +- + /** + * Number of references to old pictures that are allowed to + * be retained when calling decode on the next demux packet +@@ -285,4 +291,11 @@ class CDVDVideoCodec + * Interact with user settings so that user disabled codecs are disabled + */ + static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id); ++ ++ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) ++ { ++ return false; ++ } ++ ++ virtual void SetCodecControl(int flags) {} + }; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index b6c1e04..275a0a1 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -167,6 +167,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() + m_iLastKeyframe = 0; + m_dts = DVD_NOPTS_VALUE; + m_started = false; ++ m_decoderPts = DVD_NOPTS_VALUE; + } + + CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() +@@ -342,6 +343,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop) + { + if( m_pCodecContext ) + { ++ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint()) ++ { ++ m_requestSkipDeint = true; ++ bDrop = false; ++ } ++ else ++ m_requestSkipDeint = false; ++ + // i don't know exactly how high this should be set + // couldn't find any good docs on it. think it varies + // from codec to codec on what it does +@@ -543,6 +552,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + void CDVDVideoCodecFFmpeg::Reset() + { + m_started = false; ++ m_decoderPts = DVD_NOPTS_VALUE; + m_iLastKeyframe = m_pCodecContext->has_b_frames; + avcodec_flush_buffers(m_pCodecContext); + +@@ -640,6 +650,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + ++ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) ++ m_decoderPts = pDvdVideoPicture->pts; ++ else ++ m_decoderPts = m_dts; ++ ++ if (m_requestSkipDeint) ++ { ++ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT; ++ m_skippedDeint = 1; ++ } ++ else ++ m_skippedDeint = 0; ++ ++ m_requestSkipDeint = false; ++ pDvdVideoPicture->iFlags |= m_codecControlFlags; ++ + if(!m_started) + pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; + +@@ -821,3 +847,8 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences() + else + return 0; + } ++ ++void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) ++{ ++ m_codecControlFlags = flags; ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index 75ac0f2..51e4c80 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -50,6 +50,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec + virtual int Check (AVCodecContext* avctx) = 0; + virtual void Reset () {} + virtual unsigned GetAllowedReferences() { return 0; } ++ virtual bool CanSkipDeint() {return false; } + virtual const std::string Name() = 0; + virtual CCriticalSection* Section() { return NULL; } + }; +@@ -67,6 +68,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec + virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open + virtual unsigned GetConvergeCount(); + virtual unsigned GetAllowedReferences(); ++ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;} ++ virtual void SetCodecControl(int flags); + + bool IsHardwareAllowed() { return !m_bSoftware; } + IHardwareDecoder * GetHardware() { return m_pHardware; }; +@@ -122,4 +125,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec + double m_dts; + bool m_started; + std::vector m_formats; ++ double m_decoderPts, m_decoderInterval; ++ int m_skippedDeint; ++ bool m_requestSkipDeint; ++ int m_codecControlFlags; + }; +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 99b3155..4fad1a3 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -38,6 +38,7 @@ + #include "DVDCodecs/DVDCodecs.h" + #include "DVDCodecs/Overlay/DVDOverlayCodecCC.h" + #include "DVDCodecs/Overlay/DVDOverlaySSA.h" ++#include "guilib/GraphicContext.h" + #include + #include + #include +@@ -320,8 +321,10 @@ void CDVDPlayerVideo::Process() + + int iDropped = 0; //frames dropped in a row + bool bRequestDrop = false; ++ int iDropDirective; + + m_videoStats.Start(); ++ m_droppingStats.Reset(); + + while (!m_bStop) + { +@@ -431,6 +434,7 @@ void CDVDPlayerVideo::Process() + picture.iFlags &= ~DVP_FLAG_ALLOCATED; + m_packets.clear(); + m_started = false; ++ m_droppingStats.Reset(); + } + else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) + { +@@ -443,6 +447,7 @@ void CDVDPlayerVideo::Process() + //we need to recalculate the framerate + //TODO: this needs to be set on a streamchange instead + ResetFrameRateCalc(); ++ m_droppingStats.Reset(); + + m_stalled = true; + m_started = false; +@@ -460,8 +465,10 @@ void CDVDPlayerVideo::Process() + m_speed = static_cast(pMsg)->m_value; + if(m_speed == DVD_PLAYSPEED_PAUSE) + m_iNrOfPicturesNotToSkip = 0; ++ + if (m_pVideoCodec) + m_pVideoCodec->SetSpeed(m_speed); ++ m_droppingStats.Reset(); + } + else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) + { +@@ -507,6 +514,28 @@ void CDVDPlayerVideo::Process() + m_iNrOfPicturesNotToSkip = 1; + } + ++ bRequestDrop = false; ++ iDropDirective = CalcDropRequirement(pts); ++ if (iDropDirective & EOS_VERYLATE) ++ { ++ if (m_bAllowDrop) ++ { ++ m_pullupCorrection.Flush(); ++ bRequestDrop = true; ++ } ++ } ++ int codecControl = 0; ++ if (iDropDirective & EOS_BUFFER_LEVEL) ++ codecControl |= DVP_FLAG_DRAIN; ++ if (m_speed > DVD_PLAYSPEED_NORMAL) ++ codecControl |= DVP_FLAG_NO_POSTPROC; ++ m_pVideoCodec->SetCodecControl(codecControl); ++ if (iDropDirective & EOS_DROPPED) ++ { ++ m_iDroppedFrames++; ++ iDropped++; ++ } ++ + if (m_messageQueue.GetDataSize() == 0 + || m_speed < 0) + { +@@ -559,15 +588,7 @@ void CDVDPlayerVideo::Process() + } + + m_videoStats.AddSampleBytes(pPacket->iSize); +- // assume decoder dropped a picture if it didn't give us any +- // picture from a demux packet, this should be reasonable +- // for libavformat as a demuxer as it normally packetizes +- // pictures when they come from demuxer +- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) +- { +- m_iDroppedFrames++; +- iDropped++; +- } ++ + // reset the request, the following while loop may break before + // setting the flag to a new value + bRequestDrop = false; +@@ -1176,33 +1197,12 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + m_FlipTimeStamp += max(0.0, iSleepTime); + m_FlipTimeStamp += iFrameDuration; + +- if (iSleepTime <= 0 && m_speed) +- m_iLateFrames++; +- else +- m_iLateFrames = 0; +- +- // ask decoder to drop frames next round, as we are very late +- if(m_iLateFrames > 10) ++ if ((pPicture->iFlags & DVP_FLAG_DROPPED)) + { +- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP)) +- { +- //if we're calculating the framerate, +- //don't drop frames until we've calculated a stable framerate +- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL) +- { +- result |= EOS_VERYLATE; +- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it +- } +- m_iDroppedRequest++; +- } +- } +- else +- { +- m_iDroppedRequest = 0; +- } +- +- if( (pPicture->iFlags & DVP_FLAG_DROPPED) ) ++ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate); ++ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__); + return result | EOS_DROPPED; ++ } + + // set fieldsync if picture is interlaced + EFIELDSYNC mDisplayField = FS_NONE; +@@ -1235,7 +1235,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + if (index < 0) + return EOS_DROPPED; + +- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); ++ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField); + + return result; + #else +@@ -1535,3 +1535,127 @@ void CDVDPlayerVideo::CalcFrameRate() + m_iFrameRateCount = 0; + } + } ++ ++int CDVDPlayerVideo::CalcDropRequirement(double pts) ++{ ++ int result = 0; ++ double iSleepTime; ++ double iDecoderPts, iRenderPts; ++ double iInterval; ++ int interlaced; ++ double iGain; ++ double iLateness; ++ bool bNewFrame; ++ int iSkippedDeint = 0; ++ int iBufferLevel; ++ ++ // get decoder stats ++ if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced)) ++ iDecoderPts = pts; ++ if (iDecoderPts == DVD_NOPTS_VALUE) ++ iDecoderPts = pts; ++ ++ // get render stats ++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); ++ ++ if (iBufferLevel < 0) ++ result |= EOS_BUFFER_LEVEL; ++ else if (iBufferLevel < 2) ++ { ++ result |= EOS_BUFFER_LEVEL; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel); ++ } ++ ++ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts; ++ ++ if (interlaced) ++ iInterval = 2/m_fFrameRate*(double)DVD_TIME_BASE; ++ else ++ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; ++ ++ if (m_droppingStats.m_lastDecoderPts > 0 ++ && bNewFrame ++ && m_bAllowDrop ++ && m_droppingStats.m_dropRequests > 0) ++ { ++ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE; ++ if (iSkippedDeint) ++ { ++ CDroppingStats::CGain gain; ++ gain.gain = 1/m_fFrameRate; ++ gain.pts = iDecoderPts; ++ m_droppingStats.m_gain.push_back(gain); ++ m_droppingStats.m_totalGain += gain.gain; ++ result |= EOS_DROPPED; ++ m_droppingStats.m_dropRequests = 0; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped de-interlacing cycle, Sleeptime: %f, Bufferlevel: %d", iSleepTime, iBufferLevel); ++ } ++ else if (iGain > 1/m_fFrameRate) ++ { ++ CDroppingStats::CGain gain; ++ gain.gain = iGain; ++ gain.pts = iDecoderPts; ++ m_droppingStats.m_gain.push_back(gain); ++ m_droppingStats.m_totalGain += iGain; ++ result |= EOS_DROPPED; ++ m_droppingStats.m_dropRequests = 0; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); ++ } ++ } ++ m_droppingStats.m_lastDecoderPts = iDecoderPts; ++ ++ // subtract gains ++ while (!m_droppingStats.m_gain.empty() && ++ iRenderPts >= m_droppingStats.m_gain.front().pts) ++ { ++ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain; ++ m_droppingStats.m_gain.pop_front(); ++ } ++ ++ // calculate lateness ++ iLateness = iSleepTime + m_droppingStats.m_totalGain; ++ if (iLateness < 0 && m_speed) ++ { ++ if (bNewFrame) ++ m_droppingStats.m_lateFrames++; ++ ++ // if lateness is smaller than frametime, we observe this state ++ // for 10 cycles ++ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate) ++ { ++ // is frame allowed to skip ++ if (m_iNrOfPicturesNotToSkip <= 0) ++ { ++ result |= EOS_VERYLATE; ++ if (bNewFrame) ++ m_droppingStats.m_dropRequests++; ++ } ++ } ++ } ++ else ++ { ++ m_droppingStats.m_dropRequests = 0; ++ m_droppingStats.m_lateFrames = 0; ++ } ++ m_droppingStats.m_lastRenderPts = iRenderPts; ++ return result; ++} ++ ++void CDroppingStats::Reset() ++{ ++ m_gain.clear(); ++ m_totalGain = 0; ++ m_lastDecoderPts = 0; ++ m_lastRenderPts = 0; ++ m_lateFrames = 0; ++ m_dropRequests = 0; ++} ++ ++void CDroppingStats::AddOutputDropGain(double pts, double frametime) ++{ ++ CDroppingStats::CGain gain; ++ gain.gain = frametime; ++ gain.pts = pts; ++ m_gain.push_back(gain); ++ m_totalGain += frametime; ++} +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +index f8ad541..186e271 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +@@ -36,6 +36,25 @@ class CDVDOverlayCodecCC; + + #define VIDEO_PICTURE_QUEUE_SIZE 1 + ++class CDroppingStats ++{ ++public: ++ void Reset(); ++ void AddOutputDropGain(double pts, double frametime); ++ struct CGain ++ { ++ double gain; ++ double pts; ++ }; ++ std::deque m_gain; ++ double m_totalGain; ++ double m_lastDecoderPts; ++ double m_lastRenderPts; ++ unsigned int m_lateFrames; ++ unsigned int m_dropRequests; ++}; ++ ++ + class CDVDPlayerVideo : public CThread + { + public: +@@ -104,6 +123,7 @@ class CDVDPlayerVideo : public CThread + #define EOS_ABORT 1 + #define EOS_DROPPED 2 + #define EOS_VERYLATE 4 ++#define EOS_BUFFER_LEVEL 8 + + void AutoCrop(DVDVideoPicture* pPicture); + void AutoCrop(DVDVideoPicture *pPicture, RECT &crop); +@@ -129,6 +149,7 @@ class CDVDPlayerVideo : public CThread + + void ResetFrameRateCalc(); + void CalcFrameRate(); ++ int CalcDropRequirement(double pts); + + double m_fFrameRate; //framerate of the video currently playing + bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps +@@ -182,5 +203,7 @@ class CDVDPlayerVideo : public CThread + CPullupCorrection m_pullupCorrection; + + std::list m_packets; ++ ++ CDroppingStats m_droppingStats; + }; + +-- +1.9.1 + + +From e39d9892089539a7b18bb3fe1191865ea45190ba Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 2 Sep 2012 16:05:21 +0200 +Subject: [PATCH 02/31] video player: present correct pts to user for a/v sync + (after buffering in renderer) + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 25 +++++++++++++++++++++++++ + xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +- + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 4fad1a3..1d29b6f 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1455,6 +1455,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc() + g_advancedSettings.m_videoFpsDetect == 0; + } + ++double CDVDPlayerVideo::GetCurrentPts() ++{ ++ double iSleepTime, iRenderPts; ++ int iBufferLevel; ++ ++ // get render stats ++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); ++ ++ if( m_stalled ) ++ iRenderPts = DVD_NOPTS_VALUE; ++ else ++ iRenderPts = iRenderPts - max(0.0, iSleepTime); ++ ++ return iRenderPts; ++} ++ + #define MAXFRAMERATEDIFF 0.01 + #define MAXFRAMESERR 1000 + +@@ -1573,6 +1589,15 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) + else + iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; + ++ ++ m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval; ++ ++ if( m_stalled ) ++ m_iCurrentPts = DVD_NOPTS_VALUE; ++ else ++ m_iCurrentPts = iRenderPts - max(0.0, iSleepTime); ++ ++ + if (m_droppingStats.m_lastDecoderPts > 0 + && bNewFrame + && m_bAllowDrop +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +index 186e271..59c7f09 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +@@ -100,7 +100,7 @@ class CDVDPlayerVideo : public CThread + + bool InitializedOutputDevice(); + +- double GetCurrentPts() { return m_iCurrentPts; } ++ double GetCurrentPts(); + int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); } + + double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ +-- +1.9.1 + + +From 0570c7ff2c7179228fc9a27f7b3ccfac94b7bdfb Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sat, 16 Feb 2013 18:25:53 +0100 +Subject: [PATCH 03/31] videoplayer: some rework and documentation + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 28 ++++++++++++++++++++-- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 11 +++++++++ + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 2 +- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- + 4 files changed, 39 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +index 7761f7fa..2fbc656 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +@@ -156,7 +156,6 @@ class CDVDCodecOptions; + #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data + #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again + #define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped +-#define VC_HURRY 0x00000040 + + class CDVDVideoCodec + { +@@ -292,10 +291,35 @@ class CDVDVideoCodec + */ + static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id); + +- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) ++ /* For calculation of dropping requirements player asks for some information. ++ * ++ * - pts : right after decoder, used to detect gaps (dropped frames in decoder) ++ * - skippedDeint : indicates if decoder has just skipped a deinterlacing cycle ++ * instead of dropping a full frame ++ * - interlaced : when detecting gaps in pts, player needs to know whether ++ * it's interlaced or not ++ * ++ * If codec does not implement this method, pts of decoded frame at input ++ * video player is used. In case coded does post-proc and de-interlacing there ++ * may be quite some frames queued up between exit decoder and entry player. ++ */ ++ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced) + { + return false; + } + ++ /** ++ * Codec can be informed by player with the following flags: ++ * ++ * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off ++ * postprocessing and de-interlacing ++ * ++ * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing. ++ * If video buffers in RenderManager are about to run dry, ++ * this is signaled to codec. Codec can wait for post-proc ++ * to be finished instead of returning empty and getting another ++ * packet. ++ * ++ */ + virtual void SetCodecControl(int flags) {} + }; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 275a0a1..6bbb84d 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -848,6 +848,17 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences() + return 0; + } + ++bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &interlaced) ++{ ++ pts = m_decoderPts; ++ skippedDeint = m_skippedDeint; ++ if (m_pFrame) ++ interlaced = m_pFrame->interlaced_frame; ++ else ++ interlaced = 0; ++ return true; ++} ++ + void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) + { + m_codecControlFlags = flags; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index 51e4c80..fa3269c 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -68,7 +68,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec + virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open + virtual unsigned GetConvergeCount(); + virtual unsigned GetAllowedReferences(); +- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;} ++ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced); + virtual void SetCodecControl(int flags); + + bool IsHardwareAllowed() { return !m_bSoftware; } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 1d29b6f..ee07f30 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1566,7 +1566,7 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) + int iBufferLevel; + + // get decoder stats +- if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced)) ++ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) + iDecoderPts = pts; + if (iDecoderPts == DVD_NOPTS_VALUE) + iDecoderPts = pts; +-- +1.9.1 + + +From 381675ecca0d1fb63fd8aa9f6ec739e5c18ee4f8 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sat, 1 Jun 2013 11:21:19 +0200 +Subject: [PATCH 04/31] renderer: bump buffers to 5 + +--- + xbmc/cores/VideoRenderers/BaseRenderer.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h +index dc2712a..9edfbd4 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.h ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.h +@@ -29,7 +29,7 @@ + + #define MAX_PLANES 3 + #define MAX_FIELDS 3 +-#define NUM_BUFFERS 3 ++#define NUM_BUFFERS 5 + + class CSetting; + +-- +1.9.1 + + +From 35ba3c519542ad7b02b592bb2c2c9ff8a05719ce Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:41:31 +0200 +Subject: [PATCH 05/31] videoplayer: update frametime, it might change due to + fps detection + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index ee07f30..b3175cd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -708,6 +708,8 @@ void CDVDPlayerVideo::Process() + + int iResult = OutputPicture(&picture, pts); + ++ frametime = (double)DVD_TIME_BASE/m_fFrameRate; ++ + if(m_started == false) + { + m_codecname = m_pVideoCodec->GetName(); +-- +1.9.1 + + +From f12924d8f83c0dffb4275a7a56846f82a57aed2b Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:43:06 +0200 +Subject: [PATCH 06/31] videoplayer: give streams with invalid fps a chance for + fps detection + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index b3175cd..9c36bdb 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1497,7 +1497,7 @@ void CDVDPlayerVideo::CalcFrameRate() + double frameduration = m_pullupCorrection.GetFrameDuration(); + + if (frameduration == DVD_NOPTS_VALUE || +- (g_advancedSettings.m_videoFpsDetect == 1 && m_pullupCorrection.GetPatternLength() > 1)) ++ (g_advancedSettings.m_videoFpsDetect == 1 && (m_pullupCorrection.GetPatternLength() > 1 && !m_bFpsInvalid))) + { + //reset the stored framerates if no good framerate was detected + m_fStableFrameRate = 0.0; +-- +1.9.1 + + +From 56524c7db6419b70dff776dab252bcf0d6c9a457 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:49:05 +0200 +Subject: [PATCH 07/31] dvdplayer: allow rewinding at end of stream, do a seek + after rewind + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 3f2e0df..097af37 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1633,7 +1633,7 @@ void CDVDPlayer::HandlePlaySpeed() + + } + else if (m_CurrentVideo.id >= 0 +- && m_CurrentVideo.inited == true ++ && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file + && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() + && m_SpeedState.lasttime != GetTime()) + { +@@ -2294,6 +2294,12 @@ void CDVDPlayer::HandleMessages() + pvrinputstream->Pause( speed == 0 ); + } + ++ // do a seek after rewind, clock is not in sync with current pts ++ if (m_playSpeed < 0 && speed >= 0) ++ { ++ m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true)); ++ } ++ + // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE + // audioplayer, stops outputing audio to audiorendere, but still tries to + // sleep an correct amount for each packet +-- +1.9.1 + + +From 52736a2ab8fc4264c02a1712449db2a91df95f1e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 20 Aug 2012 16:06:39 +0200 +Subject: [PATCH 08/31] dvdplayer: observe pts counter overflow + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 197 ++++++++++++++++++++- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 4 + + 2 files changed, 200 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 872c81f..eda7dc9 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -18,7 +18,6 @@ + * + */ + +-#include "system.h" + #ifndef __STDC_CONSTANT_MACROS + #define __STDC_CONSTANT_MACROS + #endif +@@ -26,6 +25,7 @@ + #define __STDC_LIMIT_MACROS + #endif + #ifdef TARGET_POSIX ++#include "system.h" + #include "stdint.h" + #endif + #include "DVDDemuxFFmpeg.h" +@@ -417,6 +417,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + + CreateStreams(); + ++ m_bPtsWrapChecked = false; ++ m_bPtsWrap = false; ++ + return true; + } + +@@ -558,6 +561,12 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num) + if (pts == (int64_t)AV_NOPTS_VALUE) + return DVD_NOPTS_VALUE; + ++ if (m_bPtsWrap) ++ { ++ if (pts < m_iStartTime && pts < m_iEndTime) ++ pts += m_iMaxTime; ++ } ++ + // do calculations in floats as they can easily overflow otherwise + // we don't care for having a completly exact timestamp anyway + double timestamp = (double)pts * num / den; +@@ -697,6 +706,24 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + m_pkt.pkt.pts = AV_NOPTS_VALUE; + } + ++ if (!m_bPtsWrapChecked && m_pFormatContext->iformat->flags & AVFMT_TS_DISCONT) ++ { ++ int defaultStream = av_find_default_stream_index(m_pFormatContext); ++ int64_t duration = m_pFormatContext->streams[defaultStream]->duration * 1.5; ++ m_iMaxTime = 1LL<streams[defaultStream]->pts_wrap_bits; ++ m_iStartTime = m_pFormatContext->streams[defaultStream]->start_time; ++ if (m_iStartTime != DVD_NOPTS_VALUE) ++ { ++ m_iEndTime = (m_iStartTime + duration) & ~m_iMaxTime; ++ if (m_iEndTime < m_iStartTime) ++ { ++ CLog::Log(LOGNOTICE,"CDVDDemuxFFmpeg::Read - file contains pts overflow"); ++ m_bPtsWrap = true; ++ } ++ } ++ m_bPtsWrapChecked = true; ++ } ++ + // copy contents into our own packet + pPacket->iSize = m_pkt.pkt.size; + +@@ -830,7 +857,16 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) + ret = av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0); + + if(ret >= 0) ++ { + UpdateCurrentPTS(); ++ ++ // seek may fail silently on streams which allow discontinuity ++ // if current timestamp is way off asume a pts overflow and try bisect seek ++ if (m_bPtsWrap && fabs(time - m_iCurrentPts/1000) > 10000) ++ { ++ ret = SeekTimeDiscont(seek_pts, backwords) ? 1 : -1; ++ } ++ } + } + + if(m_iCurrentPts == DVD_NOPTS_VALUE) +@@ -849,6 +885,165 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) + return (ret >= 0); + } + ++bool CDVDDemuxFFmpeg::SeekTimeDiscont(int64_t pts, bool backwards) ++{ ++ // this code is taken from ffmpeg function ff_gen_search ++ // it is modified to assume a pts overflow if timestamp < start_time ++ if (!m_pFormatContext->iformat->read_timestamp) ++ return false; ++ ++ int defaultStream = av_find_default_stream_index(m_pFormatContext); ++ ++ if (defaultStream < 0) ++ { ++ return false; ++ } ++ ++ // timestamp for default must be expressed in AV_TIME_BASE units ++ pts = av_rescale_rnd(pts, m_pFormatContext->streams[defaultStream]->time_base.den, ++ AV_TIME_BASE * (int64_t)m_pFormatContext->streams[defaultStream]->time_base.num, ++ AV_ROUND_NEAR_INF); ++ ++ int64_t pos, pos_min, pos_max, pos_limit, ts, ts_min, ts_max; ++ int64_t start_pos, filesize; ++ int no_change; ++ ++ pos_min = m_pFormatContext->data_offset; ++ ts_min = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &pos_min, INT64_MAX); ++ if (ts_min == AV_NOPTS_VALUE) ++ return false; ++ ++ if(ts_min >= pts) ++ { ++ pos = pos_min; ++ return true; ++ } ++ ++ int step= 1024; ++ filesize = m_pInput->GetLength(); ++ pos_max = filesize - 1; ++ do ++ { ++ pos_max -= step; ++ ts_max = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &pos_max, pos_max + step); ++ step += step; ++ }while (ts_max == AV_NOPTS_VALUE && pos_max >= step); ++ ++ if (ts_max == AV_NOPTS_VALUE) ++ return false; ++ ++ if (ts_max < m_iStartTime && ts_max < m_iEndTime) ++ ts_max += m_iMaxTime; ++ ++ for(;;) ++ { ++ int64_t tmp_pos = pos_max + 1; ++ int64_t tmp_ts = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &tmp_pos, INT64_MAX); ++ if(tmp_ts == AV_NOPTS_VALUE) ++ break; ++ ++ if (tmp_ts < m_iStartTime && tmp_ts < m_iEndTime) ++ tmp_ts += m_iMaxTime; ++ ++ ts_max = tmp_ts; ++ pos_max = tmp_pos; ++ if (tmp_pos >= filesize) ++ break; ++ } ++ pos_limit = pos_max; ++ ++ if(ts_max <= pts) ++ { ++ bool ret = SeekByte(pos_max); ++ if (ret) ++ { ++ m_iCurrentPts = ConvertTimestamp(ts_max, m_pFormatContext->streams[defaultStream]->time_base.den, ++ m_pFormatContext->streams[defaultStream]->time_base.num); ++ } ++ return ret; ++ } ++ ++ if(ts_min > ts_max) ++ { ++ return false; ++ } ++ else if (ts_min == ts_max) ++ { ++ pos_limit = pos_min; ++ } ++ ++ no_change=0; ++ while (pos_min < pos_limit) ++ { ++ if (no_change == 0) ++ { ++ int64_t approximate_keyframe_distance= pos_max - pos_limit; ++ // interpolate position (better than dichotomy) ++ pos = av_rescale_rnd(pts - ts_min, pos_max - pos_min, ++ ts_max - ts_min, AV_ROUND_NEAR_INF) ++ + pos_min - approximate_keyframe_distance; ++ } ++ else if (no_change == 1) ++ { ++ // bisection, if interpolation failed to change min or max pos last time ++ pos = (pos_min + pos_limit) >> 1; ++ } ++ else ++ { ++ /* linear search if bisection failed, can only happen if there ++ are very few or no keyframes between min/max */ ++ pos = pos_min; ++ } ++ if (pos <= pos_min) ++ pos= pos_min + 1; ++ else if (pos > pos_limit) ++ pos= pos_limit; ++ start_pos = pos; ++ ++ ts = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &pos, INT64_MAX); ++ if (pos == pos_max) ++ no_change++; ++ else ++ no_change=0; ++ ++ if (ts == AV_NOPTS_VALUE) ++ { ++ return false; ++ } ++ ++ if (ts < m_iStartTime && ts < m_iEndTime) ++ ts += m_iMaxTime; ++ ++ if (pts <= ts) ++ { ++ pos_limit = start_pos - 1; ++ pos_max = pos; ++ ts_max = ts; ++ } ++ if (pts >= ts) ++ { ++ pos_min = pos; ++ ts_min = ts; ++ } ++ } ++ ++ pos = (backwards) ? pos_min : pos_max; ++ ts = (backwards) ? ts_min : ts_max; ++ ++ bool ret = SeekByte(pos); ++ if (ret) ++ { ++ m_iCurrentPts = ConvertTimestamp(ts, m_pFormatContext->streams[defaultStream]->time_base.den, ++ m_pFormatContext->streams[defaultStream]->time_base.num); ++ } ++ ++ return ret; ++} ++ + bool CDVDDemuxFFmpeg::SeekByte(int64_t pos) + { + CSingleLock lock(m_critSection); +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index 44e101c..3b0f615 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -99,6 +99,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux + DemuxPacket* Read(); + + bool SeekTime(int time, bool backwords = false, double* startpts = NULL); ++ bool SeekTimeDiscont(int64_t pts, bool backwards); + bool SeekByte(int64_t pos); + int GetStreamLength(); + CDemuxStream* GetStream(int iStreamId); +@@ -153,5 +154,8 @@ class CDVDDemuxFFmpeg : public CDVDDemux + AVPacket pkt; // packet ffmpeg returned + int result; // result from av_read_packet + }m_pkt; ++ ++ bool m_bPtsWrap, m_bPtsWrapChecked; ++ int64_t m_iStartTime, m_iMaxTime, m_iEndTime; + }; + +-- +1.9.1 + + +From b73d59d45e8c2f0b882cde7e549a82aee59f82ac Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Tue, 2 Oct 2012 13:02:10 +0200 +Subject: [PATCH 09/31] dvdplayer: avoid short screen flicker caused by + unnecessary reconfigure of renderer + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 9c36bdb..322a581 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1054,13 +1054,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + + #ifdef HAS_VIDEO_PLAYBACK + double config_framerate = m_bFpsInvalid ? 0.0 : m_fFrameRate; ++ double render_framerate = g_graphicsContext.GetFPS(); ++ if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_OFF) ++ render_framerate = config_framerate; + /* check so that our format or aspect has changed. if it has, reconfigure renderer */ + if (!g_renderManager.IsConfigured() + || ( m_output.width != pPicture->iWidth ) + || ( m_output.height != pPicture->iHeight ) + || ( m_output.dwidth != pPicture->iDisplayWidth ) + || ( m_output.dheight != pPicture->iDisplayHeight ) +- || ( m_output.framerate != config_framerate ) ++ || (!m_bFpsInvalid && fmod(m_output.framerate, config_framerate) != 0.0 && render_framerate != config_framerate) + || ( m_output.color_format != (unsigned int)pPicture->format ) + || ( m_output.extended_format != pPicture->extended_format ) + || ( m_output.color_matrix != pPicture->color_matrix && pPicture->color_matrix != 0 ) // don't reconfigure on unspecified +-- +1.9.1 + + +From 11c8f418d34212924278702cf6355ca6ed11496e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 11 Oct 2012 12:05:50 +0200 +Subject: [PATCH 10/31] vdpau: advanced settings for auto deinterlacing + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 8 ++++---- + xbmc/settings/AdvancedSettings.cpp | 4 ++++ + xbmc/settings/AdvancedSettings.h | 2 ++ + 3 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +index 719b70a..9c962ae 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +@@ -1962,10 +1962,10 @@ EINTERLACEMETHOD CMixer::GetDeinterlacingMethod(bool log /* = false */) + if (method == VS_INTERLACEMETHOD_AUTO) + { + int deint = -1; +-// if (m_config.outHeight >= 720) +-// deint = g_advancedSettings.m_videoVDPAUdeintHD; +-// else +-// deint = g_advancedSettings.m_videoVDPAUdeintSD; ++ if (m_config.outHeight >= 720) ++ deint = g_advancedSettings.m_videoVDPAUdeintHD; ++ else ++ deint = g_advancedSettings.m_videoVDPAUdeintSD; + + if (deint != -1) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index a13330f..0d5e546 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -163,6 +163,8 @@ void CAdvancedSettings::Initialize() + m_videoAutoScaleMaxFps = 30.0f; + m_videoDisableBackgroundDeinterlace = false; + m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect ++ m_videoVDPAUdeintHD = -1; ++ m_videoVDPAUdeintSD = -1; + m_videoVDPAUtelecine = false; + m_videoVDPAUdeintSkipChromaHD = false; + m_DXVACheckCompatibility = false; +@@ -600,6 +602,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) + XMLUtils::GetBoolean(pElement,"disableswmultithreading",m_videoDisableSWMultithreading); + XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); + XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); ++ XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD); ++ XMLUtils::GetInt(pElement,"vdpauSDdeint",m_videoVDPAUdeintSD); + XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine); + XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD); + +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index 3b417a6..7075f05 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -160,6 +160,8 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + int m_videoPercentSeekBackwardBig; + CStdString m_videoPPFFmpegDeint; + CStdString m_videoPPFFmpegPostProc; ++ int m_videoVDPAUdeintHD; ++ int m_videoVDPAUdeintSD; + bool m_videoVDPAUtelecine; + bool m_videoVDPAUdeintSkipChromaHD; + bool m_musicUseTimeSeeking; +-- +1.9.1 + + +From 4da96e30c0b33a844c203ccc68ac52c027cad150 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Fri, 2 Nov 2012 13:20:03 +0100 +Subject: [PATCH 11/31] player: fix rewind + +--- + xbmc/cores/dvdplayer/DVDMessage.h | 5 ++++- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 30 +++++++++++++++++++----------- + xbmc/cores/dvdplayer/DVDPlayer.h | 7 ++++--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 +++- + xbmc/cores/dvdplayer/DVDPlayerVideo.h | 1 + + 5 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDMessage.h b/xbmc/cores/dvdplayer/DVDMessage.h +index 2ea8b8f..e8274f9 100644 +--- a/xbmc/cores/dvdplayer/DVDMessage.h ++++ b/xbmc/cores/dvdplayer/DVDMessage.h +@@ -220,7 +220,7 @@ class CDVDMsgPlayerSetState : public CDVDMsg + class CDVDMsgPlayerSeek : public CDVDMsg + { + public: +- CDVDMsgPlayerSeek(int time, bool backward, bool flush = true, bool accurate = true, bool restore = true, bool trickplay = false) ++ CDVDMsgPlayerSeek(int time, bool backward, bool flush = true, bool accurate = true, bool restore = true, bool trickplay = false, bool sync = true) + : CDVDMsg(PLAYER_SEEK) + , m_time(time) + , m_backward(backward) +@@ -228,6 +228,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg + , m_accurate(accurate) + , m_restore(restore) + , m_trickplay(trickplay) ++ , m_sync(sync) + {} + int GetTime() { return m_time; } + bool GetBackward() { return m_backward; } +@@ -235,6 +236,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg + bool GetAccurate() { return m_accurate; } + bool GetRestore() { return m_restore; } + bool GetTrickPlay() { return m_trickplay; } ++ bool GetSync() { return m_sync; } + private: + int m_time; + bool m_backward; +@@ -242,6 +244,7 @@ class CDVDMsgPlayerSeek : public CDVDMsg + bool m_accurate; + bool m_restore; // whether to restore any EDL cut time + bool m_trickplay; ++ bool m_sync; + }; + + class CDVDMsgPlayerSeekChapter : public CDVDMsg +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 097af37..c41b0b7 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1634,11 +1634,13 @@ void CDVDPlayer::HandlePlaySpeed() + } + else if (m_CurrentVideo.id >= 0 + && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file +- && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() ++ && (m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() || fabs(m_SpeedState.lastabstime - CDVDClock::GetAbsoluteClock()) > DVD_MSEC_TO_TIME(200)) ++ && (m_dvdPlayerVideo.GetCurrentPts() != DVD_NOPTS_VALUE) + && m_SpeedState.lasttime != GetTime()) + { + m_SpeedState.lastpts = m_dvdPlayerVideo.GetCurrentPts(); + m_SpeedState.lasttime = GetTime(); ++ m_SpeedState.lastabstime = CDVDClock::GetAbsoluteClock(); + // check how much off clock video is when ff/rw:ing + // a problem here is that seeking isn't very accurate + // and since the clock will be resynced after seek +@@ -1657,7 +1659,7 @@ void CDVDPlayer::HandlePlaySpeed() + { + CLog::Log(LOGDEBUG, "CDVDPlayer::Process - Seeking to catch up"); + int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset + 500000.0 * m_playSpeed / DVD_PLAYSPEED_NORMAL); +- m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true)); ++ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true, false)); + } + } + } +@@ -2143,7 +2145,7 @@ void CDVDPlayer::HandleMessages() + else + m_StateInput.dts = start; + +- FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate()); ++ FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate(), msg.GetSync()); + } + else + CLog::Log(LOGWARNING, "error while seeking"); +@@ -2279,9 +2281,10 @@ void CDVDPlayer::HandleMessages() + double offset; + offset = CDVDClock::GetAbsoluteClock() - m_State.timestamp; + offset *= m_playSpeed / DVD_PLAYSPEED_NORMAL; ++ offset = DVD_TIME_TO_MSEC(offset); + if(offset > 1000) offset = 1000; + if(offset < -1000) offset = -1000; +- m_State.time += DVD_TIME_TO_MSEC(offset); ++ m_State.time += offset; + m_State.timestamp = CDVDClock::GetAbsoluteClock(); + } + +@@ -2297,7 +2300,8 @@ void CDVDPlayer::HandleMessages() + // do a seek after rewind, clock is not in sync with current pts + if (m_playSpeed < 0 && speed >= 0) + { +- m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true)); ++ int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset); ++ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, true, true, false, false, true)); + } + + // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE +@@ -3294,7 +3298,7 @@ bool CDVDPlayer::CloseTeletextStream(bool bWaitForBuffers) + return true; + } + +-void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) ++void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync) + { + double startpts; + if(accurate) +@@ -3306,19 +3310,23 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) + if(startpts != DVD_NOPTS_VALUE) + startpts -= m_offset_pts; + +- m_CurrentAudio.inited = false; ++ if (sync) ++ { ++ m_CurrentAudio.inited = false; ++ m_CurrentVideo.inited = false; ++ m_CurrentSubtitle.inited = false; ++ m_CurrentTeletext.inited = false; ++ } ++ + m_CurrentAudio.dts = DVD_NOPTS_VALUE; + m_CurrentAudio.startpts = startpts; + +- m_CurrentVideo.inited = false; + m_CurrentVideo.dts = DVD_NOPTS_VALUE; + m_CurrentVideo.startpts = startpts; + +- m_CurrentSubtitle.inited = false; + m_CurrentSubtitle.dts = DVD_NOPTS_VALUE; + m_CurrentSubtitle.startpts = startpts; + +- m_CurrentTeletext.inited = false; + m_CurrentTeletext.dts = DVD_NOPTS_VALUE; + m_CurrentTeletext.startpts = startpts; + +@@ -3362,7 +3370,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) + m_CurrentTeletext.started = false; + } + +- if(pts != DVD_NOPTS_VALUE) ++ if(pts != DVD_NOPTS_VALUE && sync) + m_clock.Discontinuity(pts); + UpdatePlayState(0); + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h +index e2a836b..6ecaf3f 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -308,7 +308,7 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer + bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset); + + +- void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true); ++ void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true, bool sync = true); + + void HandleMessages(); + void HandlePlaySpeed(); +@@ -357,8 +357,9 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer + int m_playSpeed; + struct SSpeedState + { +- double lastpts; // holds last display pts during ff/rw operations +- double lasttime; ++ double lastpts; // holds last display pts during ff/rw operations ++ int64_t lasttime; ++ double lastabstime; + } m_SpeedState; + + int m_errorCount; +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 322a581..9c5469b 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1470,7 +1470,7 @@ double CDVDPlayerVideo::GetCurrentPts() + + if( m_stalled ) + iRenderPts = DVD_NOPTS_VALUE; +- else ++ else if ( m_speed == DVD_PLAYSPEED_NORMAL) + iRenderPts = iRenderPts - max(0.0, iSleepTime); + + return iRenderPts; +@@ -1570,6 +1570,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) + int iSkippedDeint = 0; + int iBufferLevel; + ++ m_droppingStats.m_lastPts = pts; ++ + // get decoder stats + if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) + iDecoderPts = pts; +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +index 59c7f09..65dea76 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +@@ -50,6 +50,7 @@ class CDroppingStats + double m_totalGain; + double m_lastDecoderPts; + double m_lastRenderPts; ++ double m_lastPts; + unsigned int m_lateFrames; + unsigned int m_dropRequests; + }; +-- +1.9.1 + + +From d7de75d7c04355b6bbc834b2c4d12ce3fa3234b7 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 24 Dec 2012 16:02:42 +0100 +Subject: [PATCH 12/31] pvr: increase changes counter of stream on stream + change, cosmetics after dd307930d39d92f145a01a16600cd00e01ec39be + +--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp +index 6c8e6db..95cc18f 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp +@@ -328,9 +328,7 @@ void CDVDDemuxPVRClient::RequestStreams() + if (stm) + { + st = dynamic_cast(stm); +- if (!st +- || (st->codec != (AVCodecID)props.stream[i].iCodecId) +- || (st->iChannels != props.stream[i].iChannels)) ++ if (!st || (st->codec != (AVCodecID)props.stream[i].iCodecId)) + DisposeStream(i); + } + if (!m_streams[i]) +@@ -347,6 +345,7 @@ void CDVDDemuxPVRClient::RequestStreams() + st->iBitsPerSample = props.stream[i].iBitsPerSample; + m_streams[i] = st; + st->m_parser_split = true; ++ st->changes++; + } + else if (props.stream[i].iCodecType == XBMC_CODEC_TYPE_VIDEO) + { +-- +1.9.1 + + +From 4cc882624c5d58b3f9f3922b1887a6e07c708a40 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Fri, 14 Dec 2012 14:19:15 +0100 +Subject: [PATCH 13/31] pvr: do not show selection dialog for a single menu + hook + +--- + xbmc/pvr/addons/PVRClients.cpp | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp +index 14c9cde..57b18a5 100644 +--- a/xbmc/pvr/addons/PVRClients.cpp ++++ b/xbmc/pvr/addons/PVRClients.cpp +@@ -733,6 +733,7 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CF + { + hooks = client->GetMenuHooks(); + std::vector hookIDs; ++ int selection = 0; + + CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); + pDialog->Reset(); +@@ -743,9 +744,11 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CF + pDialog->Add(client->GetString(hooks->at(i).iLocalizedStringId)); + hookIDs.push_back(i); + } +- pDialog->DoModal(); +- +- int selection = pDialog->GetSelectedLabel(); ++ if (hookIDs.size() > 1) ++ { ++ pDialog->DoModal(); ++ selection = pDialog->GetSelectedLabel(); ++ } + if (selection >= 0) + client->CallMenuHook(hooks->at(hookIDs.at(selection)), item); + } +-- +1.9.1 + + +From d606020220c81523be3e5170ab1b64ee647a7168 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 24 Mar 2013 16:04:48 +0100 +Subject: [PATCH 14/31] linux: use CLOCK_MONOTONIC_RAW as this is not subject + to NTP + +--- + xbmc/threads/SystemClock.cpp | 2 +- + xbmc/utils/TimeUtils.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/threads/SystemClock.cpp b/xbmc/threads/SystemClock.cpp +index 657a154..35e3abf 100644 +--- a/xbmc/threads/SystemClock.cpp ++++ b/xbmc/threads/SystemClock.cpp +@@ -43,7 +43,7 @@ namespace XbmcThreads + now_time = (uint64_t)timeGetTime(); + #else + struct timespec ts = {}; +- clock_gettime(CLOCK_MONOTONIC, &ts); ++ clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + now_time = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); + #endif + if (!start_time_set) +diff --git a/xbmc/utils/TimeUtils.cpp b/xbmc/utils/TimeUtils.cpp +index c06b8c5..4390d2e 100644 +--- a/xbmc/utils/TimeUtils.cpp ++++ b/xbmc/utils/TimeUtils.cpp +@@ -43,7 +43,7 @@ int64_t CurrentHostCounter(void) + return( (int64_t)PerformanceCount.QuadPart ); + #else + struct timespec now; +- clock_gettime(CLOCK_MONOTONIC, &now); ++ clock_gettime(CLOCK_MONOTONIC_RAW, &now); + return( ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec ); + #endif + } +-- +1.9.1 + + +From 5959ff6e728f22c6cc6086cb5e39a0c58fefa07b Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 28 Mar 2013 15:18:53 +0100 +Subject: [PATCH 15/31] OMXPlayer: some caching fixes for pvr + +--- + xbmc/cores/omxplayer/OMXPlayer.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp +index 502df4a..c8579a2 100644 +--- a/xbmc/cores/omxplayer/OMXPlayer.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayer.cpp +@@ -2548,7 +2548,8 @@ void COMXPlayer::HandleMessages() + m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), (speed < 0), true, false, false, true)); + + m_playSpeed = speed; +- m_caching = CACHESTATE_DONE; ++ if (m_caching != CACHESTATE_PVR && m_playSpeed != DVD_PLAYSPEED_NORMAL) ++ m_caching = CACHESTATE_DONE; + m_clock.SetSpeed(speed); + m_av_clock.OMXSetSpeed(speed); + m_av_clock.OMXPause(); +-- +1.9.1 + + +From 79db06b63ec9bbb30ce0bb8027808d2c0967fa4f Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 28 Mar 2013 20:50:59 +0100 +Subject: [PATCH 16/31] fix incorrect display of fps when dr kicks in + +--- + xbmc/Application.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 79bfa63..d863c6b 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2331,10 +2331,11 @@ void CApplication::Render() + if (frameTime < singleFrameTime) + Sleep(singleFrameTime - frameTime); + } +- m_lastFrameTime = XbmcThreads::SystemClockMillis(); + + if (flip) + g_graphicsContext.Flip(dirtyRegions); ++ ++ m_lastFrameTime = XbmcThreads::SystemClockMillis(); + CTimeUtils::UpdateFrameTime(flip); + + g_renderManager.UpdateResolution(); +-- +1.9.1 + + +From f5d25c94791473ff296257e1bb7b35be267bc7d2 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 11 Jun 2013 16:20:29 +0200 +Subject: [PATCH 17/31] renderer: allow some lateness within vblank interval + +--- + xbmc/cores/VideoRenderers/RenderManager.cpp | 12 ++++++++++-- + xbmc/cores/VideoRenderers/RenderManager.h | 1 + + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index f4b381e..5e9f666 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -380,6 +380,8 @@ void CXBMCRenderManager::FrameFinish() + if(g_graphicsContext.IsFullScreenVideo()) + WaitPresentTime(m.timestamp); + ++ m_clock_framefinish = GetPresentTime(); ++ + { CSingleLock lock(m_presentlock); + + if(m_presentstep == PRESENT_FRAME) +@@ -1032,6 +1034,12 @@ void CXBMCRenderManager::PrepareNextRender() + + double clocktime = GetPresentTime(); + double frametime = 1.0 / GetMaximumFPS(); ++ double correction = 0.0; ++ int fps = g_VideoReferenceClock.GetRefreshRate(); ++ if((fps > 0) && g_graphicsContext.IsFullScreenVideo() && (clocktime != m_clock_framefinish)) ++ { ++ correction = frametime; ++ } + + /* see if any future queued frames are already due */ + std::deque::reverse_iterator curr, prev; +@@ -1040,8 +1048,8 @@ void CXBMCRenderManager::PrepareNextRender() + ++prev; + while (prev != m_queued.rend()) + { +- if(clocktime > m_Queue[*prev].timestamp /* previous frame is late */ +- && clocktime > m_Queue[*curr].timestamp - frametime) /* selected frame is close to it's display time */ ++ if(clocktime > m_Queue[*prev].timestamp + correction /* previous frame is late */ ++ && clocktime > m_Queue[*curr].timestamp - frametime + correction) /* selected frame is close to it's display time */ + break; + ++curr; + ++prev; +diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h +index 949c652b..d84ff6c 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoRenderers/RenderManager.h +@@ -252,6 +252,7 @@ class CXBMCRenderManager + XbmcThreads::ConditionVariable m_presentevent; + CCriticalSection m_presentlock; + CEvent m_flushEvent; ++ double m_clock_framefinish; + + + OVERLAY::CRenderer m_overlays; +-- +1.9.1 + + +From 04dfa8be7362e22e339a8f23df47230b841388bc Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 25 Jul 2013 17:18:13 +0200 +Subject: [PATCH 18/31] ActiveAE: slightly reduce buffer size + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index 27c237b..a01f77c 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -30,8 +30,8 @@ using namespace ActiveAE; + #include "settings/AdvancedSettings.h" + #include "windowing/WindowingFactory.h" + +-#define MAX_CACHE_LEVEL 0.5 // total cache time of stream in seconds +-#define MAX_WATER_LEVEL 0.25 // buffered time after stream stages in seconds ++#define MAX_CACHE_LEVEL 0.4 // total cache time of stream in seconds ++#define MAX_WATER_LEVEL 0.2 // buffered time after stream stages in seconds + #define MAX_BUFFER_TIME 0.1 // max time of a buffer in seconds + + void CEngineStats::Reset(unsigned int sampleRate) +-- +1.9.1 + + +From f7370bcc07fb1cd8ab03baa9fff133569c5b8668 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 4 Aug 2013 10:11:16 +0200 +Subject: [PATCH 19/31] Revert "vdpau: comment some features that will be added + later" + +This reverts commit e00b4f65864d623ab4d2e9e5c06db138e661f1cf. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +index 9c962ae..485c5d3 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +@@ -1092,8 +1092,7 @@ int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame) + m_bufferStats.IncDecoded(); + m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); + +- //TODO +- // m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); ++ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); + } + + int retval = 0; +@@ -2286,8 +2285,7 @@ void CMixer::InitCycle() + int flags; + uint64_t latency; + m_config.stats->GetParams(latency, flags); +- // TODO +- if (0) //flags & DVP_FLAG_NO_POSTPROC) ++ if (flags & DVP_FLAG_NO_POSTPROC) + SetPostProcFeatures(false); + else + SetPostProcFeatures(true); +@@ -2299,8 +2297,7 @@ void CMixer::InitCycle() + bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED; + m_SeenInterlaceFlag |= interlaced; + +- // TODO +- if (//!(flags & DVP_FLAG_NO_POSTPROC) && ++ if (!(flags & DVP_FLAG_NO_POSTPROC) && + (mode == VS_DEINTERLACEMODE_FORCE || + (mode == VS_DEINTERLACEMODE_AUTO && interlaced))) + { +@@ -2322,8 +2319,7 @@ void CMixer::InitCycle() + m_config.stats->SetCanSkipDeint(true); + } + +- // TODO +- if (0) //m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT) ++ if (m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT) + { + m_mixersteps = 1; + } +-- +1.9.1 + + +From 90335f7140d075a7c182767bd205c78eec93063a Mon Sep 17 00:00:00 2001 +From: Marcel Groothuis +Date: Thu, 5 Dec 2013 22:02:50 +0100 +Subject: [PATCH 21/31] ffmpeg demuxer: faster channel change for PVR addons + without internal demuxing (such as MediaPortal, ArgusTV, MythTV, NextPVR) + Credits: FernetMenta, Davilla, Popcornmix, Whaupt + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 143 ++++++++++++++++++--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 5 +- + .../dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 13 +- + 3 files changed, 139 insertions(+), 22 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index eda7dc9..6266fba 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -52,6 +52,8 @@ + #include "URL.h" + #include "cores/FFmpeg.h" + ++#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE) ++ + void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo) + { + if(!m_stream) return; +@@ -153,6 +155,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux() + m_program = UINT_MAX; + m_pkt.result = -1; + memset(&m_pkt.pkt, 0, sizeof(AVPacket)); ++ m_streaminfo = true; /* set to true if we want to look for streams before playback */ + } + + CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg() +@@ -173,10 +176,11 @@ bool CDVDDemuxFFmpeg::Aborted() + return false; + } + +-bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) ++bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + { + AVInputFormat* iformat = NULL; + std::string strFile; ++ m_streaminfo = streaminfo; + m_iCurrentPts = DVD_NOPTS_VALUE; + m_speed = DVD_PLAYSPEED_NORMAL; + m_program = UINT_MAX; +@@ -187,8 +191,6 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + m_pInput = pInput; + strFile = m_pInput->GetFileName(); + +- bool streaminfo = true; /* set to true if we want to look for streams before playback*/ +- + if( m_pInput->GetContent().length() > 0 ) + { + std::string content = m_pInput->GetContent(); +@@ -378,13 +380,12 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm" + m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0; + +- if (streaminfo) ++ if (m_streaminfo) + { +- /* too speed up dvd switches, only analyse very short */ ++ /* to speed up dvd switches, only analyse very short */ + if(m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)) + m_pFormatContext->max_analyze_duration = 500000; + +- + CLog::Log(LOGDEBUG, "%s - avformat_find_stream_info starting", __FUNCTION__); + int iErr = avformat_find_stream_info(m_pFormatContext, NULL); + if (iErr < 0) +@@ -404,6 +405,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + } + CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__); + } ++ else ++ m_program = 0; ++ + // reset any timeout + m_timeout.SetInfinite(); + +@@ -457,7 +461,7 @@ void CDVDDemuxFFmpeg::Reset() + { + CDVDInputStream* pInputStream = m_pInput; + Dispose(); +- Open(pInputStream); ++ Open(pInputStream, m_streaminfo); + } + + void CDVDDemuxFFmpeg::Flush() +@@ -652,25 +656,32 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + } + else + { ++ ParsePacket(&m_pkt.pkt); ++ + AVStream *stream = m_pFormatContext->streams[m_pkt.pkt.stream_index]; + +- if (m_program != UINT_MAX) ++ if (IsVideoReady()) + { +- /* check so packet belongs to selected program */ +- for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) ++ if (m_program != UINT_MAX) + { +- if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) ++ /* check so packet belongs to selected program */ ++ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) + { +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); +- break; ++ if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) ++ { ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ break; ++ } + } +- } + +- if (!pPacket) +- bReturnEmpty = true; ++ if (!pPacket) ++ bReturnEmpty = true; ++ } ++ else ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); + } + else +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ bReturnEmpty = true; + + if (pPacket) + { +@@ -1611,3 +1622,101 @@ bool CDVDDemuxFFmpeg::IsProgramChange() + } + return false; + } ++ ++void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt) ++{ ++ AVStream *st = m_pFormatContext->streams[pkt->stream_index]; ++ CDemuxStream *stream = GetStreamInternal(pkt->stream_index); ++ ++ // if the stream is new, tell ffmpeg to parse the stream ++ if (!stream && !st->parser) ++ { ++ st->need_parsing = AVSTREAM_PARSE_FULL; ++ } ++ ++ // split extradata ++ if(st->parser && st->parser->parser->split && !st->codec->extradata) ++ { ++ int i = st->parser->parser->split(st->codec, pkt->data, pkt->size); ++ if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) ++ { ++ // Found extradata, fill it in. This will cause ++ // a new stream to be created and used. ++ st->codec->extradata_size = i; ++ st->codec->extradata = (uint8_t*)av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); ++ if (st->codec->extradata) ++ { ++ CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::Read() fetching extradata, extradata_size(%d)", st->codec->extradata_size); ++ memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size); ++ memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE); ++ } ++ else ++ { ++ st->codec->extradata_size = 0; ++ } ++ } ++ } ++ ++ // for video we need a decoder to get desired information into codec context ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) ++ { ++ // open a decoder, it will be cleared down by ffmpeg on closing the stream ++ if (!st->codec->codec) ++ { ++ const AVCodec* codec; ++ AVDictionary *thread_opt = NULL; ++ codec = avcodec_find_decoder(st->codec->codec_id); ++ // Force thread count to 1 since the h264 decoder will not extract ++ // SPS and PPS to extradata during multi-threaded decoding ++ av_dict_set(&thread_opt, "threads", "1", 0); ++ avcodec_open2(st->codec, codec, &thread_opt); ++ ++ av_dict_free(&thread_opt); ++ } ++ ++ // We don't need to actually decode here ++ // we just want to transport SPS data into codec context ++ st->codec->skip_idct = AVDISCARD_ALL; ++ st->codec->skip_frame = AVDISCARD_ALL; ++ st->codec->skip_loop_filter = AVDISCARD_ALL; ++ ++ // We are looking for an IDR frame ++ AVFrame picture; ++ memset(&picture, 0, sizeof(AVFrame)); ++ picture.pts = picture.pkt_dts = picture.pkt_pts = picture.best_effort_timestamp = AV_NOPTS_VALUE; ++ picture.pkt_pos = -1; ++ picture.key_frame = 1; ++ picture.format = -1; ++ ++ int got_picture = 0; ++ avcodec_decode_video2(st->codec, &picture, &got_picture, pkt); ++ } ++} ++ ++bool CDVDDemuxFFmpeg::IsVideoReady() ++{ ++ AVStream *st; ++ if(m_program != UINT_MAX) ++ { ++ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) ++ { ++ int idx = m_pFormatContext->programs[m_program]->stream_index[i]; ++ st = m_pFormatContext->streams[idx]; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) ++ return false; ++ } ++ } ++ else ++ { ++ for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) ++ { ++ st = m_pFormatContext->streams[i]; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) ++ return false; ++ } ++ } ++ return true; ++} +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index 3b0f615..083182e 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -88,7 +88,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux + CDVDDemuxFFmpeg(); + virtual ~CDVDDemuxFFmpeg(); + +- bool Open(CDVDInputStream* pInput); ++ bool Open(CDVDInputStream* pInput, bool streaminfo = true); + void Dispose(); + void Reset(); + void Flush(); +@@ -127,6 +127,8 @@ class CDVDDemuxFFmpeg : public CDVDDemux + CDemuxStream* GetStreamInternal(int iStreamId); + void CreateStreams(unsigned int program = UINT_MAX); + void DisposeStreams(); ++ void ParsePacket(AVPacket *pkt); ++ bool IsVideoReady(); + + AVDictionary *GetFFMpegOptionsFromURL(const CURL &url); + double ConvertTimestamp(int64_t pts, int den, int num); +@@ -157,5 +159,6 @@ class CDVDDemuxFFmpeg : public CDVDDemux + + bool m_bPtsWrap, m_bPtsWrapChecked; + int64_t m_iStartTime, m_iMaxTime, m_iEndTime; ++ bool m_streaminfo; + }; + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +index ca689d0..f383563 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +@@ -99,26 +99,31 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + #endif + ++ bool streaminfo = true; /* Look for streams before playback */ + if (pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream; + CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream(); ++ ++ /* Don't parse the streaminfo for live streams to reduce the channel switch time */ ++ bool liveStream = (pInputStream->GetFileName().substr(0, 14) == "pvr://channels"); ++ streaminfo = !liveStream; ++ + if(pOtherStream) + { + /* Used for MediaPortal PVR addon (uses PVR otherstream for playback of rtsp streams) */ + if (pOtherStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG)) + { + auto_ptr demuxer(new CDVDDemuxFFmpeg()); +- if(demuxer->Open(pOtherStream)) ++ if(demuxer->Open(pOtherStream, streaminfo)) + return demuxer.release(); + else + return NULL; + } + } + +- std::string filename = pInputStream->GetFileName(); + /* Use PVR demuxer only for live streams */ +- if (filename.substr(0, 14) == "pvr://channels") ++ if (liveStream) + { + boost::shared_ptr client; + if (g_PVRClients->GetPlayingClient(client) && +@@ -134,7 +139,7 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + + auto_ptr demuxer(new CDVDDemuxFFmpeg()); +- if(demuxer->Open(pInputStream)) ++ if(demuxer->Open(pInputStream, streaminfo)) + return demuxer.release(); + else + return NULL; +-- +1.9.1 + + +From 8aaaf75e93f67c6a1edca07ccc6116204676db7e Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 14 Nov 2013 20:35:04 +0100 +Subject: [PATCH 22/31] ffmpeg demuxer: make sure we start mpegts video with an + i-frame + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 31 +++++++++++++++++++++- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 1 + + 2 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 6266fba..c6472b8 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -376,6 +376,13 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0) + m_pFormatContext->max_analyze_duration = 500000; + ++ bool short_analyze = false; ++ if (iformat && (strcmp(iformat->name, "mpegts") == 0)) ++ { ++ m_pFormatContext->max_analyze_duration = 500000; ++ short_analyze = true; ++ } ++ + // we need to know if this is matroska or avi later + m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm" + m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0; +@@ -404,6 +411,12 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + } + } + CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__); ++ ++ if (short_analyze) ++ { ++ // make sure we start video with an i-frame ++ ResetVideoStreams(); ++ } + } + else + m_program = 0; +@@ -1658,7 +1671,7 @@ void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt) + } + + // for video we need a decoder to get desired information into codec context +- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->codec->extradata && + (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) + { + // open a decoder, it will be cleared down by ffmpeg on closing the stream +@@ -1720,3 +1733,19 @@ bool CDVDDemuxFFmpeg::IsVideoReady() + } + return true; + } ++ ++void CDVDDemuxFFmpeg::ResetVideoStreams() ++{ ++ AVStream *st; ++ for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) ++ { ++ st = m_pFormatContext->streams[i]; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ++ { ++ if (st->codec->extradata) ++ m_dllAvUtil.av_free(st->codec->extradata); ++ st->codec->extradata = NULL; ++ st->codec->width = 0; ++ } ++ } ++} +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index 083182e..26ee264 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -129,6 +129,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux + void DisposeStreams(); + void ParsePacket(AVPacket *pkt); + bool IsVideoReady(); ++ void ResetVideoStreams(); + + AVDictionary *GetFFMpegOptionsFromURL(const CURL &url); + double ConvertTimestamp(int64_t pts, int den, int num); +-- +1.9.1 + + +From b1a69aca87ab81242602fbbff061b9be2a32fefe Mon Sep 17 00:00:00 2001 +From: Wolfgang Haupt +Date: Thu, 5 Dec 2013 22:11:57 +0100 +Subject: [PATCH 23/31] DVDFactoryDemuxer: skip streaminfo for udp tcp and + pvr-channels + +--- + .../dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 14 ++++++--- + xbmc/utils/URIUtils.cpp | 35 ++++++++++++++++++++++ + xbmc/utils/URIUtils.h | 4 +++ + 3 files changed, 49 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +index f383563..d6580fd 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +@@ -105,9 +105,9 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream; + CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream(); + +- /* Don't parse the streaminfo for live streams to reduce the channel switch time */ +- bool liveStream = (pInputStream->GetFileName().substr(0, 14) == "pvr://channels"); +- streaminfo = !liveStream; ++ /* Don't parse the streaminfo for some cases of streams to reduce the channel switch time */ ++ bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName()); ++ streaminfo = !useFastswitch; + + if(pOtherStream) + { +@@ -123,7 +123,7 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + + /* Use PVR demuxer only for live streams */ +- if (liveStream) ++ if (URIUtils::IsPVRChannel(pInputStream->GetFileName())) + { + boost::shared_ptr client; + if (g_PVRClients->GetPlayingClient(client) && +@@ -138,6 +138,12 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + } + ++ if (pInputStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG)) ++ { ++ bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName()); ++ streaminfo = !useFastswitch; ++ } ++ + auto_ptr demuxer(new CDVDDemuxFFmpeg()); + if(demuxer->Open(pInputStream, streaminfo)) + return demuxer.release(); +diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp +index fd2eb5a..22932b7 100644 +--- a/xbmc/utils/URIUtils.cpp ++++ b/xbmc/utils/URIUtils.cpp +@@ -788,6 +788,36 @@ bool URIUtils::IsFTP(const CStdString& strFile) + StringUtils::StartsWithNoCase(strFile2, "ftps:"); + } + ++bool URIUtils::IsUDP(const CStdString& strFile) ++{ ++ CStdString strFile2(strFile); ++ ++ if (IsStack(strFile)) ++ strFile2 = CStackDirectory::GetFirstStackedFile(strFile); ++ ++ return StringUtils::StartsWithNoCase(strFile2, "udp:"); ++} ++ ++bool URIUtils::IsTCP(const CStdString& strFile) ++{ ++ CStdString strFile2(strFile); ++ ++ if (IsStack(strFile)) ++ strFile2 = CStackDirectory::GetFirstStackedFile(strFile); ++ ++ return StringUtils::StartsWithNoCase(strFile2, "tcp:"); ++} ++ ++bool URIUtils::IsPVRChannel(const CStdString& strFile) ++{ ++ CStdString strFile2(strFile); ++ ++ if (IsStack(strFile)) ++ strFile2 = CStackDirectory::GetFirstStackedFile(strFile); ++ ++ return StringUtils::StartsWithNoCase(strFile2, "pvr://channels"); ++} ++ + bool URIUtils::IsDAV(const CStdString& strFile) + { + CStdString strFile2(strFile); +@@ -1284,3 +1314,8 @@ bool URIUtils::UpdateUrlEncoding(std::string &strFilename) + strFilename = newFilename; + return true; + } ++ ++bool URIUtils::IsUsingFastSwitch(const CStdString& strFile) ++{ ++ return IsUDP(strFile) || IsTCP(strFile) || IsPVRChannel(strFile); ++} +diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h +index b94e94c..b45630f 100644 +--- a/xbmc/utils/URIUtils.h ++++ b/xbmc/utils/URIUtils.h +@@ -88,6 +88,8 @@ class URIUtils + static bool IsDOSPath(const CStdString &path); + static bool IsDVD(const CStdString& strFile); + static bool IsFTP(const CStdString& strFile); ++ static bool IsUDP(const CStdString& strFile); ++ static bool IsTCP(const CStdString& strFile); + static bool IsHD(const CStdString& strFileName); + static bool IsHDHomeRun(const CStdString& strFile); + static bool IsSlingbox(const CStdString& strFile); +@@ -127,6 +129,8 @@ class URIUtils + static bool IsAndroidApp(const CStdString& strFile); + static bool IsLibraryFolder(const CStdString& strFile); + static bool IsLibraryContent(const std::string& strFile); ++ static bool IsPVRChannel(const CStdString& strFile); ++ static bool IsUsingFastSwitch(const CStdString& strFile); + + static void AddSlashAtEnd(std::string& strFolder); + static bool HasSlashAtEnd(const std::string& strFile, bool checkURL = false); +-- +1.9.1 + + +From e73bfd14cbcfe83c21110b19e08d6f52f41f81e7 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 28 Jan 2014 08:43:29 +0100 +Subject: [PATCH 24/31] squash fast switch + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 23 ++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index c6472b8..63f1372 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -1710,15 +1710,19 @@ void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt) + bool CDVDDemuxFFmpeg::IsVideoReady() + { + AVStream *st; ++ bool hasVideo = false; + if(m_program != UINT_MAX) + { + for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) + { + int idx = m_pFormatContext->programs[m_program]->stream_index[i]; + st = m_pFormatContext->streams[idx]; +- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && +- (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) +- return false; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ++ { ++ if (st->codec->width && st->codec->pix_fmt != PIX_FMT_NONE) ++ return true; ++ hasVideo = true; ++ } + } + } + else +@@ -1726,12 +1730,15 @@ bool CDVDDemuxFFmpeg::IsVideoReady() + for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) + { + st = m_pFormatContext->streams[i]; +- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && +- (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) +- return false; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ++ { ++ if (st->codec->width && st->codec->pix_fmt != PIX_FMT_NONE) ++ return true; ++ hasVideo = true; ++ } + } + } +- return true; ++ return !hasVideo; + } + + void CDVDDemuxFFmpeg::ResetVideoStreams() +@@ -1743,7 +1750,7 @@ void CDVDDemuxFFmpeg::ResetVideoStreams() + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + { + if (st->codec->extradata) +- m_dllAvUtil.av_free(st->codec->extradata); ++ av_free(st->codec->extradata); + st->codec->extradata = NULL; + st->codec->width = 0; + } +-- +1.9.1 + + +From 62afa1ee0982f4c68ce5a885220576f5751af81a Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 13 Apr 2014 10:52:26 +0200 +Subject: [PATCH 25/31] squash fast channel + +--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 13 ++++++++++--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 1 + + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 63f1372..0e4be8e 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -156,6 +156,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux() + m_pkt.result = -1; + memset(&m_pkt.pkt, 0, sizeof(AVPacket)); + m_streaminfo = true; /* set to true if we want to look for streams before playback */ ++ m_checkvideo = false; + } + + CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg() +@@ -376,11 +377,10 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0) + m_pFormatContext->max_analyze_duration = 500000; + +- bool short_analyze = false; + if (iformat && (strcmp(iformat->name, "mpegts") == 0)) + { + m_pFormatContext->max_analyze_duration = 500000; +- short_analyze = true; ++ m_checkvideo = true; + } + + // we need to know if this is matroska or avi later +@@ -412,14 +412,17 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + } + CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__); + +- if (short_analyze) ++ if (m_checkvideo) + { + // make sure we start video with an i-frame + ResetVideoStreams(); + } + } + else ++ { + m_program = 0; ++ m_checkvideo = true; ++ } + + // reset any timeout + m_timeout.SetInfinite(); +@@ -1711,6 +1714,10 @@ bool CDVDDemuxFFmpeg::IsVideoReady() + { + AVStream *st; + bool hasVideo = false; ++ ++ if(!m_checkvideo) ++ return true; ++ + if(m_program != UINT_MAX) + { + for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index 26ee264..322a3b8 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -161,5 +161,6 @@ class CDVDDemuxFFmpeg : public CDVDDemux + bool m_bPtsWrap, m_bPtsWrapChecked; + int64_t m_iStartTime, m_iMaxTime, m_iEndTime; + bool m_streaminfo; ++ bool m_checkvideo; + }; + +-- +1.9.1 + + +From 6a8561267a785e169a01ecda71ac9676744f2bbd Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 22 Dec 2013 14:52:29 +0100 +Subject: [PATCH 26/31] linux: add shared lib for sse4 operations + +--- + Makefile.in | 8 ++- + configure.in | 18 +++++++ + xbmc/DllPaths_generated.h.in | 3 ++ + xbmc/linux/sse4/CopyFrame.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++ + xbmc/linux/sse4/DllLibSSE4.h | 43 ++++++++++++++++ + xbmc/linux/sse4/Makefile.in | 20 ++++++++ + 6 files changed, 206 insertions(+), 1 deletion(-) + create mode 100644 xbmc/linux/sse4/CopyFrame.cpp + create mode 100644 xbmc/linux/sse4/DllLibSSE4.h + create mode 100644 xbmc/linux/sse4/Makefile.in + +diff --git a/Makefile.in b/Makefile.in +index 002bb23..78211b3 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -311,6 +311,12 @@ CHECK_LIBADD=@WAYLAND_TEST_LIBS@ + endif + endif + ++ifeq (@USE_SSE4@,1) ++LIBSSE4+=sse4 ++sse4 : force ++ $(MAKE) -C xbmc/linux/sse4 ++endif ++ + CHECK_PROGRAMS = xbmc-test + + CLEAN_FILES += $(CHECK_PROGRAMS) $(CHECK_EXTENSIONS) +@@ -438,7 +444,7 @@ endif + + codecs: papcodecs dvdpcodecs dvdpextcodecs + +-libs: libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH) ++libs: $(LIBSSE4) libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH) + + externals: codecs libs visualizations screensavers libaddon pvraddons + +diff --git a/configure.in b/configure.in +index 3fcb178..9140b25 100644 +--- a/configure.in ++++ b/configure.in +@@ -827,6 +827,19 @@ elif test "$use_arch" = "arm"; then + fi + fi + ++use_sse4=no ++if test "$ARCH" = "x86_64-linux" || test "$ARCH" = "i486-linux"; then ++ SAVE_CFLAGS="$CFLAGS" ++ CFLAGS="-msse4.1" ++ AC_COMPILE_IFELSE( ++ [AC_LANG_SOURCE([int foo;])], ++ [ use_sse4=yes ++ USE_SSE4=1], ++ [ use_sse=no ++ USE_SSE4=0]) ++ CFLAGS="$SAVE_CFLAGS" ++fi ++ + # Checks for library functions. + AC_FUNC_ALLOCA + AC_FUNC_CHOWN +@@ -2598,6 +2611,10 @@ if test "$use_codec_libstagefright" = "yes"; then + OUTPUT_FILES="$OUTPUT_FILES xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile" + fi + ++if test "$use_sse4" = "yes"; then ++OUTPUT_FILES="$OUTPUT_FILES xbmc/linux/sse4/Makefile" ++fi ++ + OUTPUT_FILES="$OUTPUT_FILES \ + xbmc/interfaces/python/Makefile \ + xbmc/interfaces/python/test/Makefile" +@@ -2676,6 +2693,7 @@ AC_SUBST(USE_ANDROID) + AC_SUBST(GTEST_CONFIGURED) + AC_SUBST(USE_DOXYGEN) + AC_SUBST(USE_PVR_ADDONS) ++AC_SUBST(USE_SSE4) + + # pushd and popd are not available in other shells besides bash, so implement + # our own pushd/popd functions +diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in +index 8e81555..dd6e0ed 100644 +--- a/xbmc/DllPaths_generated.h.in ++++ b/xbmc/DllPaths_generated.h.in +@@ -94,4 +94,7 @@ + /* xkbcommon */ + #define DLL_PATH_XKBCOMMON "@XKBCOMMON_LIBRARY_SONAME@" + ++/* sse4 */ ++#define DLL_PATH_LIBSSE4 "special://xbmcbin/system/libsse4-@ARCH@.so" ++ + #endif +diff --git a/xbmc/linux/sse4/CopyFrame.cpp b/xbmc/linux/sse4/CopyFrame.cpp +new file mode 100644 +index 0000000..6d23d83 +--- /dev/null ++++ b/xbmc/linux/sse4/CopyFrame.cpp +@@ -0,0 +1,115 @@ ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This library 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. ++ * ++ * This library 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 General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "smmintrin.h" ++ ++#define CACHED_BUFFER_SIZE 4096 ++typedef unsigned int UINT; ++ ++extern "C" ++{ ++ ++/* ++ * http://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers ++ * COPIES VIDEO FRAMES FROM USWC MEMORY TO WB SYSTEM MEMORY VIA CACHED BUFFER ++ * ASSUMES PITCH IS A MULTIPLE OF 64B CACHE LINE SIZE, WIDTH MAY NOT BE ++ */ ++void copy_frame( void * pSrc, void * pDest, void * pCacheBlock, ++ UINT width, UINT height, UINT pitch ) ++{ ++ __m128i x0, x1, x2, x3; ++ __m128i *pLoad; ++ __m128i *pStore; ++ __m128i *pCache; ++ UINT x, y, yLoad, yStore; ++ UINT rowsPerBlock; ++ UINT width64; ++ UINT extraPitch; ++ ++ ++ rowsPerBlock = CACHED_BUFFER_SIZE / pitch; ++ width64 = (width + 63) & ~0x03f; ++ extraPitch = (pitch - width64) / 16; ++ ++ pLoad = (__m128i *)pSrc; ++ pStore = (__m128i *)pDest; ++ ++ // COPY THROUGH 4KB CACHED BUFFER ++ for( y = 0; y < height; y += rowsPerBlock ) ++ { ++ // ROWS LEFT TO COPY AT END ++ if( y + rowsPerBlock > height ) ++ rowsPerBlock = height - y; ++ ++ pCache = (__m128i *)pCacheBlock; ++ ++ _mm_mfence(); ++ ++ // LOAD ROWS OF PITCH WIDTH INTO CACHED BLOCK ++ for( yLoad = 0; yLoad < rowsPerBlock; yLoad++ ) ++ { ++ // COPY A ROW, CACHE LINE AT A TIME ++ for( x = 0; x < pitch; x +=64 ) ++ { ++ x0 = _mm_stream_load_si128( pLoad +0 ); ++ x1 = _mm_stream_load_si128( pLoad +1 ); ++ x2 = _mm_stream_load_si128( pLoad +2 ); ++ x3 = _mm_stream_load_si128( pLoad +3 ); ++ ++ _mm_store_si128( pCache +0, x0 ); ++ _mm_store_si128( pCache +1, x1 ); ++ _mm_store_si128( pCache +2, x2 ); ++ _mm_store_si128( pCache +3, x3 ); ++ ++ pCache += 4; ++ pLoad += 4; ++ } ++ } ++ ++ _mm_mfence(); ++ ++ pCache = (__m128i *)pCacheBlock; ++ ++ // STORE ROWS OF FRAME WIDTH FROM CACHED BLOCK ++ for( yStore = 0; yStore < rowsPerBlock; yStore++ ) ++ { ++ // copy a row, cache line at a time ++ for( x = 0; x < width64; x +=64 ) ++ { ++ x0 = _mm_load_si128( pCache ); ++ x1 = _mm_load_si128( pCache +1 ); ++ x2 = _mm_load_si128( pCache +2 ); ++ x3 = _mm_load_si128( pCache +3 ); ++ ++ _mm_stream_si128( pStore, x0 ); ++ _mm_stream_si128( pStore +1, x1 ); ++ _mm_stream_si128( pStore +2, x2 ); ++ _mm_stream_si128( pStore +3, x3 ); ++ ++ pCache += 4; ++ pStore += 4; ++ } ++ ++ pCache += extraPitch; ++ pStore += extraPitch; ++ } ++ } ++} ++} +diff --git a/xbmc/linux/sse4/DllLibSSE4.h b/xbmc/linux/sse4/DllLibSSE4.h +new file mode 100644 +index 0000000..01424ac +--- /dev/null ++++ b/xbmc/linux/sse4/DllLibSSE4.h +@@ -0,0 +1,43 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://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, see ++ * . ++ * ++ */ ++ ++#include "DynamicDll.h" ++ ++extern "C" { ++ ++} ++ ++class DllLibSSE4Interface ++{ ++public: ++ virtual ~DllLibSSE4Interface() {} ++ virtual void copy_frame(void * pSrc, void * pDest, void * pCacheBlock, UINT width, UINT height, UINT pitch) = 0; ++}; ++ ++class DllLibSSE4 : public DllDynamic, DllLibSSE4Interface ++{ ++ DECLARE_DLL_WRAPPER(DllLibSSE4, DLL_PATH_LIBSSE4) ++ DEFINE_METHOD6(void, copy_frame, (void *p1, void *p2, void *p3, UINT p4, UINT p5, UINT p6)) ++ ++ BEGIN_METHOD_RESOLVE() ++ RESOLVE_METHOD(copy_frame) ++ END_METHOD_RESOLVE() ++}; +diff --git a/xbmc/linux/sse4/Makefile.in b/xbmc/linux/sse4/Makefile.in +new file mode 100644 +index 0000000..45aa826 +--- /dev/null ++++ b/xbmc/linux/sse4/Makefile.in +@@ -0,0 +1,20 @@ ++ARCH=@ARCH@ ++DEFINES+= ++CXXFLAGS=-fPIC -msse4.1 ++LIBNAME=libsse4 ++OBJS=CopyFrame.o ++ ++LIB_SHARED=@abs_top_srcdir@/system/$(LIBNAME)-$(ARCH).so ++ ++all: $(LIB_SHARED) ++ ++$(LIB_SHARED): $(OBJS) ++ $(CXX) $(CFLAGS) $(LDFLAGS) -shared -g -o $(LIB_SHARED) $(OBJS) ++ ++CLEAN_FILES = \ ++ $(LIB_SHARED) \ ++ ++DISTCLEAN_FILES= \ ++ Makefile \ ++ ++include ../../../Makefile.include +-- +1.9.1 + + +From 2e6de7059eabe3c19d50d4dd171f4fa0842acffe Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 19 Dec 2013 15:36:11 +0100 +Subject: [PATCH 27/31] vaapi: option to enable sw filters + +--- + language/English/strings.po | 17 ++- + system/settings/settings.xml | 15 ++ + xbmc/cores/VideoRenderers/RenderManager.cpp | 4 +- + xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp | 1 + + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 76 +++++++++-- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 3 + + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 152 +++++++++++++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 31 +++++ + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 32 ++--- + 9 files changed, 290 insertions(+), 41 deletions(-) + +diff --git a/language/English/strings.po b/language/English/strings.po +index a2e539e..17c9274 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -6092,7 +6092,13 @@ msgctxt "#13456" + msgid "Hardware accelerated" + msgstr "" + +-#empty strings from id 13457 to 13499 ++#. Option for video related setting #13454: sw filter ++#: system/settings/settings.xml ++msgctxt "#13457" ++msgid "Use SW Filter for VAAPI" ++msgstr "" ++ ++#empty strings from id 13458 to 13499 + + #: system/settings/settings.xml + msgctxt "#13500" +@@ -15167,7 +15173,14 @@ msgctxt "#36431" + msgid "Defines whether video decoding should be performed in software (requires more CPU) or with hardware acceleration where possible." + msgstr "" + +-#empty strings from id 36432 to 36499 ++#. Description for video related setting #13457: vaapi sw filter ++#: system/settings/settings.xml ++msgctxt "#36432" ++msgid "This option enables the deinterlacing methods available for software decoding. It gives the possiblity to use high quality deinterlacers in combination with VAAPI." ++msgstr "" ++ ++#empty strings from id 36433 to 36499 ++ + #end reservation + + #: system/settings/settings.xml +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 0e4e952..ba17337 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -715,6 +715,21 @@ + false + + ++ ++ HAVE_LIBVA ++ ++ ++ ++ true ++ 1 ++ ++ ++ true ++ ++ 3 ++ false ++ ++ + + HasDXVA2 + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index 5e9f666..32ce5bb 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -988,10 +988,10 @@ EINTERLACEMETHOD CXBMCRenderManager::AutoInterlaceMethodInternal(EINTERLACEMETHO + if (mInt == VS_INTERLACEMETHOD_NONE) + return VS_INTERLACEMETHOD_NONE; + +- if(!m_pRenderer->Supports(mInt)) ++ if(m_pRenderer && !m_pRenderer->Supports(mInt)) + mInt = VS_INTERLACEMETHOD_AUTO; + +- if (mInt == VS_INTERLACEMETHOD_AUTO) ++ if (m_pRenderer && mInt == VS_INTERLACEMETHOD_AUTO) + return m_pRenderer->AutoInterlaceMethod(); + + return mInt; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp +index 2958d43..06e0010 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp +@@ -464,6 +464,7 @@ static const EFormatMap g_format_map[] = { + , { PIX_FMT_YUV420P16, RENDER_FMT_YUV420P16 } + , { PIX_FMT_UYVY422, RENDER_FMT_UYVY422 } + , { PIX_FMT_YUYV422, RENDER_FMT_YUYV422 } ++, { PIX_FMT_NV12, RENDER_FMT_NV12 } + , { PIX_FMT_VAAPI_VLD, RENDER_FMT_VAAPI } + , { PIX_FMT_DXVA2_VLD, RENDER_FMT_DXVA } + , { PIX_FMT_NONE , RENDER_FMT_NONE } +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 6bbb84d..f308c09 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -38,6 +38,7 @@ + #include "utils/log.h" + #include "boost/shared_ptr.hpp" + #include "threads/Atomics.h" ++#include "settings/MediaSettings.h" + + #ifndef TARGET_POSIX + #define RINT(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5))) +@@ -168,6 +169,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() + m_dts = DVD_NOPTS_VALUE; + m_started = false; + m_decoderPts = DVD_NOPTS_VALUE; ++ m_interlace = false; + } + + CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() +@@ -375,7 +377,7 @@ unsigned int CDVDVideoCodecFFmpeg::SetFilters(unsigned int flags) + { + m_filters_next.clear(); + +- if(m_pHardware) ++ if(m_pHardware && !m_pHardware->UseFilter()) + return 0; + + if(flags & FILTER_ROTATE) +@@ -449,10 +451,10 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + if(section) + lock = shared_ptr(new CSingleLock(*section)); + +- int result; ++ int result = 0; + if(pData) + result = m_pHardware->Check(m_pCodecContext); +- else ++ else if (!m_pHardware->UseFilter()) + result = m_pHardware->Decode(m_pCodecContext, NULL); + + if(result) +@@ -507,19 +509,60 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + || m_pCodecContext->codec_id == AV_CODEC_ID_SVQ3) + m_started = true; + +- if(m_pHardware == NULL) ++ m_interlace = m_pFrame->interlaced_frame; ++ ++ if(m_pHardware == NULL || m_pHardware->UseFilter()) + { ++ if (m_pHardware) ++ { ++ m_pFrame->pkt_dts = pts_dtoi(m_dts); ++ int result = m_pHardware->Decode(m_pCodecContext, m_pFrame); ++ if (result == VC_BUFFER || result == VC_ERROR) ++ return result; ++ m_pHardware->MapFrame(m_pCodecContext, m_pFrame); ++ m_dts = pts_itod(m_pFrame->pkt_dts); ++ m_pFrame->pkt_dts = 0; ++ } ++ + bool need_scale = std::find( m_formats.begin() + , m_formats.end() +- , m_pCodecContext->pix_fmt) == m_formats.end(); ++ , m_pFrame->format) == m_formats.end(); + + bool need_reopen = false; ++ ++ ++ // ask codec to do deinterlacing if possible ++ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); ++ ++ unsigned int mFilters = 0; ++ ++ if (mDeintMode != VS_DEINTERLACEMODE_OFF) ++ { ++ if (mDeintMode == VS_DEINTERLACEMODE_FORCE || ++ m_pFrame->interlaced_frame) ++ { ++ if (mInt == VS_INTERLACEMETHOD_DEINTERLACE) ++ mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY; ++ else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF) ++ mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED; ++ ++ if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters) ++ mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; ++ } ++ } ++ ++ if (!g_renderManager.Supports(RENDERFEATURE_ROTATION)) ++ mFilters |= CDVDVideoCodec::FILTER_ROTATE; ++ ++ SetFilters(mFilters); ++ + if(!m_filters.Equals(m_filters_next)) + need_reopen = true; + + if(m_pFilterIn) + { +- if(m_pFilterIn->outputs[0]->format != m_pCodecContext->pix_fmt ++ if(m_pFilterIn->outputs[0]->format != m_pFrame->format + || m_pFilterIn->outputs[0]->w != m_pCodecContext->width + || m_pFilterIn->outputs[0]->h != m_pCodecContext->height) + need_reopen = true; +@@ -536,7 +579,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + } + + int result; +- if(m_pHardware) ++ if(m_pHardware && !m_pHardware->UseFilter()) + result = m_pHardware->Decode(m_pCodecContext, m_pFrame); + else if(m_pFilterGraph) + result = FilterProcess(m_pFrame); +@@ -620,6 +663,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->chroma_position = m_pCodecContext->chroma_sample_location; + pDvdVideoPicture->color_primaries = m_pCodecContext->color_primaries; + pDvdVideoPicture->color_transfer = m_pCodecContext->color_trc; ++ pDvdVideoPicture->color_matrix = m_pCodecContext->colorspace; + if(m_pCodecContext->color_range == AVCOL_RANGE_JPEG + || m_pCodecContext->pix_fmt == PIX_FMT_YUVJ420P) + pDvdVideoPicture->color_range = 1; +@@ -643,7 +687,11 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->qscale_type = DVP_QSCALE_UNKNOWN; + } + +- pDvdVideoPicture->dts = m_dts; ++ if (pDvdVideoPicture->iRepeatPicture) ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ else ++ pDvdVideoPicture->dts = m_dts; ++ + m_dts = DVD_NOPTS_VALUE; + if (m_pFrame->reordered_opaque) + pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque); +@@ -674,7 +722,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + + bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture) + { +- if(m_pHardware) ++ if(m_pHardware && !m_pHardware->UseFilter()) + return m_pHardware->GetPicture(m_pCodecContext, m_pFrame, pDvdVideoPicture); + + if(!GetPictureCommon(pDvdVideoPicture)) +@@ -694,6 +742,7 @@ bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture) + pix_fmt = (PixelFormat)m_pFrame->format; + + pDvdVideoPicture->format = CDVDCodecUtils::EFormatFromPixfmt(pix_fmt); ++ + return true; + } + +@@ -707,7 +756,7 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale) + if (filters.empty() && !scale) + return 0; + +- if (m_pHardware) ++ if (m_pHardware && !m_pHardware->UseFilter()) + { + CLog::Log(LOGWARNING, "CDVDVideoCodecFFmpeg::FilterOpen - skipped opening filters on hardware decode"); + return 0; +@@ -725,7 +774,7 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale) + CStdString args = StringUtils::Format("%d:%d:%d:%d:%d:%d:%d", + m_pCodecContext->width, + m_pCodecContext->height, +- m_pCodecContext->pix_fmt, ++ m_pFrame->format, + m_pCodecContext->time_base.num, + m_pCodecContext->time_base.den, + m_pCodecContext->sample_aspect_ratio.num, +@@ -852,10 +901,7 @@ bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &in + { + pts = m_decoderPts; + skippedDeint = m_skippedDeint; +- if (m_pFrame) +- interlaced = m_pFrame->interlaced_frame; +- else +- interlaced = 0; ++ interlaced = m_interlace; + return true; + } + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index fa3269c..6baf42a 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -53,6 +53,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec + virtual bool CanSkipDeint() {return false; } + virtual const std::string Name() = 0; + virtual CCriticalSection* Section() { return NULL; } ++ virtual bool UseFilter() { return false; } ++ virtual bool MapFrame(AVCodecContext* avctx, AVFrame* frame) { return false; } + }; + + CDVDVideoCodecFFmpeg(); +@@ -129,4 +131,5 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec + int m_skippedDeint; + bool m_requestSkipDeint; + int m_codecControlFlags; ++ bool m_interlace; + }; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +index 386d50a..315f3ca 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +@@ -26,6 +26,15 @@ + #include + #include "utils/log.h" + #include "threads/SingleLock.h" ++#include "XMemUtils.h" ++#include "utils/CPUInfo.h" ++#include "settings/Settings.h" ++ ++extern "C" { ++#include "libavutil/avutil.h" ++} ++ ++#define CACHED_BUFFER_SIZE 4096 + + #define CHECK(a) \ + do { \ +@@ -168,12 +177,17 @@ CDecoder::CDecoder() + m_context = 0; + m_hwaccel = (vaapi_context*)calloc(1, sizeof(vaapi_context)); + memset(m_surfaces, 0, sizeof(*m_surfaces)); ++ m_frame_buffer = NULL; ++ m_cache = NULL; + } + + CDecoder::~CDecoder() + { + Close(); + free(m_hwaccel); ++ _aligned_free(m_frame_buffer); ++ _aligned_free(m_cache); ++ m_dllSSE4.Unload(); + } + + void CDecoder::RelBuffer(uint8_t *data) +@@ -393,6 +407,11 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su + if (!EnsureContext(avctx)) + return false; + ++ if (avctx->width <= 1920 && avctx->height <= 1088) ++ CheckUseFilter(); ++ else ++ m_use_filter = false; ++ + m_hwaccel->display = m_display->get(); + + avctx->hwaccel_context = m_hwaccel; +@@ -475,7 +494,35 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) + return status; + + if(frame) ++ { ++ if (m_use_filter) ++ { ++ VASurfaceID surface = GetSurfaceID(frame); ++ std::list::iterator it; ++ for(it = m_surfaces_used.begin(); it != m_surfaces_used.end(); ++it) ++ { ++ if((*it)->m_id == surface) ++ { ++ m_holder.surface = *it; ++ break; ++ } ++ } ++ if (it == m_surfaces_used.end()) ++ { ++ CLog::Log(LOGERROR, "VAAPI::Decode - surface not found"); ++ return VC_ERROR; ++ } ++ CProcPic pic; ++ memset(&pic.frame, 0, sizeof(AVFrame)); ++ av_frame_ref(&pic.frame, frame); ++ pic.surface = *it; ++ m_surfaces_proc.push_back(pic); ++ if (m_surfaces_proc.size() < m_renderbuffers_count) ++ return VC_BUFFER; ++ } ++ + return VC_BUFFER | VC_PICTURE; ++ } + else + return VC_BUFFER; + } +@@ -553,4 +600,109 @@ unsigned CDecoder::GetAllowedReferences() + return m_renderbuffers_count; + } + ++void CDecoder::Reset() ++{ ++ m_surfaces_proc.clear(); ++} ++ ++void CDecoder::CheckUseFilter() ++{ ++ m_use_filter = true; ++ _aligned_free(m_frame_buffer); ++ _aligned_free(m_cache); ++ if (CSettings::Get().GetBool("videoplayer.usevaapiswfilter")) ++ { ++ if (!(g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_SSE4)) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter cpu does not support SSE4"); ++ m_use_filter = false; ++ return; ++ } ++ if (!m_dllSSE4.Load()) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter failed loading sse4 lib"); ++ m_use_filter = false; ++ return; ++ } ++ VAImage image; ++ VASurfaceID surface = m_surfaces_free.front()->m_id; ++ VAStatus status = vaDeriveImage(m_display->get(), surface, &image); ++ m_use_filter = true; ++ if (status != VA_STATUS_SUCCESS) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter vaDeriveImage not supported"); ++ m_use_filter = false; ++ } ++ if (image.format.fourcc != VA_FOURCC_NV12) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter image format not NV12"); ++ m_use_filter = false; ++ } ++ if ((image.pitches[0] % 64) || (image.pitches[1] % 64)) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter patches no multiple of 64"); ++ m_use_filter = false; ++ } ++ if (m_use_filter) ++ { ++ m_frame_buffer = (uint8_t*)_aligned_malloc(image.height*image.width*2 + 256, 64); ++ m_cache = (uint8_t*)_aligned_malloc(CACHED_BUFFER_SIZE, 64); ++ } ++ vaDestroyImage(m_display->get(),image.image_id); ++ } ++ else ++ { ++ m_use_filter = false; ++ } ++} ++ ++bool CDecoder::MapFrame(AVCodecContext* avctx, AVFrame* frame) ++{ ++ if (m_surfaces_proc.empty()) ++ { ++ return false; ++ } ++ if(frame) ++ { ++ CProcPic pic = m_surfaces_proc.front(); ++ m_surfaces_proc.pop_front(); ++ VASurfaceID surface = pic.surface->m_id; ++ VASurfaceStatus surf_status; ++ VAImage image; ++ uint8_t *buf; ++ CHECK(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status)) ++ while (surf_status != VASurfaceReady) ++ { ++ Sleep(1); ++ CHECK(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status)) ++ } ++ CHECK(vaDeriveImage(m_display->get(), surface, &image)); ++ CHECK(vaMapBuffer(m_display->get(), image.buf, (void**)&buf)) ++ ++ uint8_t *src, *dst; ++ src = buf + image.offsets[0]; ++ dst = m_frame_buffer + image.offsets[0]; ++ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height, image.pitches[0]); ++ src = buf + image.offsets[1]; ++ dst = m_frame_buffer + image.offsets[1]; ++ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height/2, image.pitches[1]); ++ ++ av_frame_unref(frame); ++ av_frame_move_ref(frame, &pic.frame); ++ ++ frame->format = AV_PIX_FMT_NV12; ++ frame->data[0] = m_frame_buffer + image.offsets[0]; ++ frame->linesize[0] = image.pitches[0]; ++ frame->data[1] = m_frame_buffer + image.offsets[1]; ++ frame->linesize[1] = image.pitches[1]; ++ frame->data[2] = NULL; ++ frame->data[3] = NULL; ++ frame->pkt_size = image.data_size; ++ ++ CHECK(vaUnmapBuffer(m_display->get(), image.buf)) ++ CHECK(vaDestroyImage(m_display->get(),image.image_id)) ++ } ++ return true; ++} ++ + #endif +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +index ec99162..616b124 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +@@ -27,9 +27,11 @@ + #include + #include + #include ++#include "linux/sse4/DllLibSSE4.h" + + extern "C" { + #include "libavcodec/vaapi.h" ++#include "libavcodec/avcodec.h" + } + + namespace VAAPI { +@@ -102,11 +104,31 @@ struct CHolder + {} + }; + ++struct CProcPic ++{ ++ AVFrame frame; ++ CSurfacePtr surface; ++ CProcPic() ++ {} ++ CProcPic(const CProcPic &other) ++ { ++ memcpy(&this->frame, &other.frame, sizeof(AVFrame)); ++ surface = other.surface; ++ } ++ CProcPic & operator= (const CProcPic &other) ++ { ++ memcpy(&this->frame, &other.frame, sizeof(AVFrame)); ++ surface = other.surface; ++ return *this; ++ } ++}; ++ + class CDecoder + : public CDVDVideoCodecFFmpeg::IHardwareDecoder + { + bool EnsureContext(AVCodecContext *avctx); + bool EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count); ++ void CheckUseFilter(); + public: + CDecoder(); + ~CDecoder(); +@@ -115,9 +137,12 @@ class CDecoder + virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture); + virtual int Check (AVCodecContext* avctx); + virtual void Close(); ++ virtual void Reset(); + virtual const std::string Name() { return "vaapi"; } + virtual CCriticalSection* Section() { if(m_display) return m_display.get(); else return NULL; } + virtual unsigned GetAllowedReferences(); ++ virtual bool UseFilter() { return m_use_filter; } ++ virtual bool MapFrame(AVCodecContext* avctx, AVFrame* frame); + + int GetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags); + void RelBuffer(uint8_t *data); +@@ -133,14 +158,20 @@ class CDecoder + int m_refs; + std::list m_surfaces_used; + std::list m_surfaces_free; ++ std::list m_surfaces_proc; + + CDisplayPtr m_display; + VAConfigID m_config; + VAContextID m_context; ++ bool m_use_filter; ++ uint8_t *m_frame_buffer; ++ uint8_t *m_cache; + + vaapi_context *m_hwaccel; + + CHolder m_holder; // silly struct to pass data to renderer ++ ++ DllLibSSE4 m_dllSSE4; + }; + + } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 9c5469b..b30e450 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -554,28 +554,6 @@ void CDVDPlayerVideo::Process() + // decoder still needs to provide an empty image structure, with correct flags + m_pVideoCodec->SetDropState(bRequestDrop); + +- // ask codec to do deinterlacing if possible +- EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; +- EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); +- +- unsigned int mFilters = 0; +- +- if (mDeintMode != VS_DEINTERLACEMODE_OFF) +- { +- if (mInt == VS_INTERLACEMETHOD_DEINTERLACE) +- mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY; +- else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF) +- mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED; +- +- if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters) +- mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; +- } +- +- if (!g_renderManager.Supports(RENDERFEATURE_ROTATION)) +- mFilters |= CDVDVideoCodec::FILTER_ROTATE; +- +- mFilters = m_pVideoCodec->SetFilters(mFilters); +- + int iDecoderState = m_pVideoCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts); + + // buffer packets so we can recover should decoder flush for some reason +@@ -662,6 +640,8 @@ void CDVDPlayerVideo::Process() + + //Deinterlace if codec said format was interlaced or if we have selected we want to deinterlace + //this video ++ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); + if ((mDeintMode == VS_DEINTERLACEMODE_AUTO && (picture.iFlags & DVP_FLAG_INTERLACED)) || mDeintMode == VS_DEINTERLACEMODE_FORCE) + { + if(mInt == VS_INTERLACEMETHOD_SW_BLEND) +@@ -704,7 +684,15 @@ void CDVDPlayerVideo::Process() + } + + if (picture.iRepeatPicture) ++ { ++ double pts; ++ int skipped, deint; ++ m_pVideoCodec->GetCodecStats(pts, skipped, deint); ++ picture.iDuration = frametime; ++ if (deint && (frametime <= 0.02*DVD_TIME_BASE)) ++ picture.iDuration *= 2; + picture.iDuration *= picture.iRepeatPicture + 1; ++ } + + int iResult = OutputPicture(&picture, pts); + +-- +1.9.1 + + +From 6d4f961cdac4c91aa8288dc35a618f735eb8868a Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 24 Jan 2014 18:29:33 +0100 +Subject: [PATCH 28/31] dvdplayer: flush ffmpeg after hw decoder returned an + error + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index f308c09..830ce60 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -458,7 +458,12 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + result = m_pHardware->Decode(m_pCodecContext, NULL); + + if(result) ++ { ++ if (result & VC_ERROR) ++ avcodec_flush_buffers(m_pCodecContext); ++ + return result; ++ } + } + + if(m_pFilterGraph) +@@ -580,7 +585,11 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + + int result; + if(m_pHardware && !m_pHardware->UseFilter()) ++ { + result = m_pHardware->Decode(m_pCodecContext, m_pFrame); ++ if (result & VC_ERROR) ++ avcodec_flush_buffers(m_pCodecContext); ++ } + else if(m_pFilterGraph) + result = FilterProcess(m_pFrame); + else +-- +1.9.1 + + +From bce0b976b37a99b3acddc2b1368f984c5c3bf712 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 28 Jan 2014 10:05:26 +0100 +Subject: [PATCH 29/31] xbmc pr 3080 + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 830ce60..8715afb 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -482,6 +482,14 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + av_init_packet(&avpkt); + avpkt.data = pData; + avpkt.size = iSize; ++#define SET_PKT_TS(ts) \ ++ if(ts != DVD_NOPTS_VALUE)\ ++ avpkt.ts = (ts / DVD_TIME_BASE) * AV_TIME_BASE;\ ++ else\ ++ avpkt.ts = AV_NOPTS_VALUE ++ SET_PKT_TS(pts); ++ SET_PKT_TS(dts); ++#undef SET_PKT_TS + /* We lie, but this flag is only used by pngdec.c. + * Setting it correctly would allow CorePNG decoding. */ + avpkt.flags = AV_PKT_FLAG_KEY; +@@ -702,8 +710,10 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->dts = m_dts; + + m_dts = DVD_NOPTS_VALUE; +- if (m_pFrame->reordered_opaque) +- pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque); ++ ++ int64_t bpts = av_frame_get_best_effort_timestamp(m_pFrame); ++ if(bpts != AV_NOPTS_VALUE) ++ pDvdVideoPicture->pts = (double)bpts * DVD_TIME_BASE / AV_TIME_BASE; + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + +-- +1.9.1 + + +From c0100ee3de95343854714e52635291d58150da74 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 28 Jan 2014 17:24:58 +0100 +Subject: [PATCH 30/31] set preatpicture if pts is equal to last frame + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 8715afb..dec00d5 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -713,7 +713,15 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + + int64_t bpts = av_frame_get_best_effort_timestamp(m_pFrame); + if(bpts != AV_NOPTS_VALUE) ++ { + pDvdVideoPicture->pts = (double)bpts * DVD_TIME_BASE / AV_TIME_BASE; ++ if (pDvdVideoPicture->pts == m_decoderPts) ++ { ++ pDvdVideoPicture->iRepeatPicture = -0.5; ++ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ } ++ } + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + +-- +1.9.1 + + +From 40dad6e6f9c1a96ac4e2f337e348b03f1e029bd3 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 11 Feb 2014 18:15:06 +0100 +Subject: [PATCH 31/31] ActiveAE: add some debug logging + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +index 0287e73..6904cb9 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +@@ -276,7 +276,13 @@ unsigned int CActiveAEStream::AddData(void *data, unsigned int size) + } + } + if (!m_inMsgEvent.WaitMSec(200)) ++ { ++ double cachetime = GetCacheTime(); ++ CSingleLock lock(m_streamLock); ++ CLog::Log(LOGWARNING, "CActiveAEStream::AddData - timeout waiting for buffer, paused: %d, cache time: %f, free buffers: %d", ++ m_paused, cachetime, m_streamFreeBuffers); + break; ++ } + } + return copied; + } +-- +1.9.1 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch new file mode 100644 index 0000000000..3f331b1574 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch @@ -0,0 +1,29 @@ +From 4f6188bc2bcee52ab3a150fff336b58c11f8928a Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 22 Mar 2014 22:18:28 +0200 +Subject: [PATCH] dont set _NET_WM_STATE_FULLSCREEN + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 6 ------ + 1 files changed, 0 insertions(+), 6 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index c95f4ec..d12e050 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -903,12 +903,6 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: + InputOutput, vi->visual, + mask, &swa); + +- if (fullscreen && hasWM) +- { +- Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); +- XChangeProperty(m_dpy, m_mainWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); +- } +- + // define invisible cursor + Pixmap bitmapNoData; + XColor black; +-- +1.7.2.5 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.10-disable-minimize.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.10-disable-minimize.patch new file mode 100644 index 0000000000..c0fe5a62ab --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.10-disable-minimize.patch @@ -0,0 +1,18 @@ +commit 17807066bc04cd28bba89fd176d4d0f69ead9728 +Author: Stefan Saraev +Date: Sat Oct 12 16:18:50 2013 +0300 + + disable minimize + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index b5d40c0..18bea9d 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -5448,7 +5448,6 @@ bool CApplication::SwitchToFullScreen() + + void CApplication::Minimize() + { +- g_Windowing.Minimize(); + } + + PLAYERCOREID CApplication::GetCurrentPlayer() diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.12-run-tzdata-setup-on-timezone-change.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.12-run-tzdata-setup-on-timezone-change.patch new file mode 100644 index 0000000000..51a7e52381 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.12-run-tzdata-setup-on-timezone-change.patch @@ -0,0 +1,26 @@ +From 25be1b385303a8114d7e227ffab52a22de42ccd1 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 26 Nov 2013 20:53:08 +0200 +Subject: [PATCH] run tzdata-setup on timezone change + +--- + xbmc/linux/LinuxTimezone.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/linux/LinuxTimezone.cpp b/xbmc/linux/LinuxTimezone.cpp +index be7bce6..4000181 100644 +--- a/xbmc/linux/LinuxTimezone.cpp ++++ b/xbmc/linux/LinuxTimezone.cpp +@@ -158,6 +158,9 @@ void CLinuxTimezone::OnSettingChanged(const CSetting *setting) + const std::string &settingId = setting->GetId(); + if (settingId == "locale.timezone") + { ++ const std::string cmd = std::string("sh /usr/lib/openelec/tzdata-setup ") + ((CSettingString*)setting)->GetValue().c_str(); ++ system(cmd.c_str()); ++ + SetTimezone(((CSettingString*)setting)->GetValue()); + + CDateTime::ResetTimezoneBias(); +-- +1.8.3.2 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.00-service-addons-use-a-wrapper-to-setup-systemd.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.00-service-addons-use-a-wrapper-to-setup-systemd.patch new file mode 100644 index 0000000000..d81adcd3f1 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.00-service-addons-use-a-wrapper-to-setup-systemd.patch @@ -0,0 +1,97 @@ +From 9c1dea43c9b9b66c48d057d3c0e44cd4a807e4dc Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Fri, 20 Dec 2013 00:36:34 +0200 +Subject: [PATCH] service addons: use a wrapper to setup systemd + +--- + xbmc/addons/AddonDatabase.cpp | 3 +++ + xbmc/addons/AddonInstaller.cpp | 10 ++++++++++ + xbmc/addons/AddonInstaller.h | 2 ++ + 3 files changed, 15 insertions(+) + +diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp +index 4202363..105749f 100644 +--- a/xbmc/addons/AddonDatabase.cpp ++++ b/xbmc/addons/AddonDatabase.cpp +@@ -20,6 +20,7 @@ + + #include "AddonDatabase.h" + #include "addons/AddonManager.h" ++#include "addons/AddonInstaller.h" + #include "utils/log.h" + #include "utils/Variant.h" + #include "utils/StringUtils.h" +@@ -581,6 +582,7 @@ bool CAddonDatabase::DisableAddon(const CStdString &addonID, bool disable /* = t + boost::shared_ptr service = boost::dynamic_pointer_cast(addon); + if (service) + service->Stop(); ++ CAddonInstaller::Get().CallOEWrapper(addonID, true); + } + // restart the pvr manager when disabling a pvr add-on with the pvr manager enabled + else if (CAddonMgr::Get().GetAddon(addonID, addon, ADDON_PVRDLL, false) && addon && +@@ -601,6 +603,7 @@ bool CAddonDatabase::DisableAddon(const CStdString &addonID, bool disable /* = t + // If the addon is a service, start it + if (CAddonMgr::Get().GetAddon(addonID, addon, ADDON_SERVICE, false) && addon && disabled) + { ++ CAddonInstaller::Get().CallOEWrapper(addonID, false); + boost::shared_ptr service = boost::dynamic_pointer_cast(addon); + if (service) + service->Start(); +diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp +index 8c9f241..d2f4610 100644 +--- a/xbmc/addons/AddonInstaller.cpp ++++ b/xbmc/addons/AddonInstaller.cpp +@@ -70,6 +70,13 @@ CAddonInstaller &CAddonInstaller::Get() + return addonInstaller; + } + ++void CAddonInstaller::CallOEWrapper(const std::string& ID, bool disable) ++{ ++ char cmd[255]; ++ snprintf(cmd, sizeof(cmd), "/usr/lib/openelec/systemd-addon-wrapper %s %d", ID.c_str(), disable); ++ system(cmd); ++} ++ + void CAddonInstaller::OnJobComplete(unsigned int jobID, bool success, CJob* job) + { + if (success) +@@ -586,6 +593,7 @@ bool CAddonInstallJob::OnPreInstall() + boost::shared_ptr service = boost::dynamic_pointer_cast(addon); + if (service) + service->Stop(); ++ CAddonInstaller::Get().CallOEWrapper(m_addon->ID(), true); + CAddonMgr::Get().RemoveAddon(m_addon->ID()); // remove it + return running; + } +@@ -713,6 +721,7 @@ void CAddonInstallJob::OnPostInstall(bool reloadAddon) + AddonPtr addon; + CAddonMgr::Get().GetAddon(m_addon->ID(), addon); + boost::shared_ptr service = boost::dynamic_pointer_cast(addon); ++ CAddonInstaller::Get().CallOEWrapper(m_addon->ID(), false); + if (service) + service->Start(); + } +@@ -794,6 +803,7 @@ bool CAddonUnInstallJob::DoWork() + boost::shared_ptr service = boost::dynamic_pointer_cast(m_addon); + if (service) + service->Stop(); ++ CAddonInstaller::Get().CallOEWrapper(m_addon->ID(), true); + } + + AddonPtr repoPtr = CAddonInstallJob::GetRepoForAddon(m_addon); +diff --git a/xbmc/addons/AddonInstaller.h b/xbmc/addons/AddonInstaller.h +index 39cab93..2938c7f 100644 +--- a/xbmc/addons/AddonInstaller.h ++++ b/xbmc/addons/AddonInstaller.h +@@ -29,6 +29,8 @@ class CAddonInstaller : public IJobCallback + public: + static CAddonInstaller &Get(); + ++ void CallOEWrapper(const std::string& ID, bool disable); ++ + bool IsDownloading() const; + void GetInstallList(ADDON::VECADDONS &addons) const; + bool GetProgress(const CStdString &addonID, unsigned int &percent) const; +-- +1.8.3.2 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.80.01-PR4592.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.80.01-PR4592.patch new file mode 100644 index 0000000000..ecc9edc561 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.80.01-PR4592.patch @@ -0,0 +1,62 @@ +From 6a926768eba981c6498f852fe26dfa6644da82ac Mon Sep 17 00:00:00 2001 +From: "Chris \"Koying\" Browet" +Date: Wed, 23 Apr 2014 16:33:19 +0200 +Subject: [PATCH] FIX: [linux] fix & optimize input device checking + +--- + xbmc/input/linux/LinuxInputDevices.cpp | 12 +++++++++++- + xbmc/input/linux/LinuxInputDevices.h | 1 + + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp +index 4b642ae..f11ec01 100644 +--- a/xbmc/input/linux/LinuxInputDevices.cpp ++++ b/xbmc/input/linux/LinuxInputDevices.cpp +@@ -936,6 +936,11 @@ char* CLinuxInputDevice::GetDeviceName() + return m_deviceName; + } + ++std::string CLinuxInputDevice::GetFileName() ++{ ++ return m_fileName; ++} ++ + bool CLinuxInputDevice::IsUnplugged() + { + return m_bUnplugged; +@@ -945,6 +950,11 @@ bool CLinuxInputDevices::CheckDevice(const char *device) + { + int fd; + ++ // Does the device exists? ++ struct stat buffer; ++ if (stat(device, &buffer) != 0) ++ return false; ++ + /* Check if we are able to open the device */ + fd = open(device, O_RDWR); + if (fd < 0) +@@ -1016,7 +1026,7 @@ void CLinuxInputDevices::CheckHotplugged() + + for (size_t j = 0; j < m_devices.size(); j++) + { +- if (strcmp(m_devices[j]->GetDeviceName(),buf) == 0) ++ if (m_devices[j]->GetFileName().compare(buf) == 0) + { + ispresent = true; + break; +diff --git a/xbmc/input/linux/LinuxInputDevices.h b/xbmc/input/linux/LinuxInputDevices.h +index c385ed7..a406d9c 100644 +--- a/xbmc/input/linux/LinuxInputDevices.h ++++ b/xbmc/input/linux/LinuxInputDevices.h +@@ -42,6 +42,7 @@ class CLinuxInputDevice + ~CLinuxInputDevice(); + XBMC_Event ReadEvent(); + char* GetDeviceName(); ++ std::string GetFileName(); + bool IsUnplugged(); + + private: +-- +1.9.1 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.80.02-PR4624.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.80.02-PR4624.patch new file mode 100644 index 0000000000..2c23e9e047 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.80.02-PR4624.patch @@ -0,0 +1,31 @@ +From 3fae42dcad347a3a3b6d1a2ed0ba8c0d7f172de0 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Wed, 30 Apr 2014 15:29:51 +0200 +Subject: [PATCH] paplayer: dvdplayercodec - check if seek is possible before + trying to seek + +--- + xbmc/cores/paplayer/DVDPlayerCodec.cpp | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/paplayer/DVDPlayerCodec.cpp b/xbmc/cores/paplayer/DVDPlayerCodec.cpp +index c60abc8..89e9dbe 100644 +--- a/xbmc/cores/paplayer/DVDPlayerCodec.cpp ++++ b/xbmc/cores/paplayer/DVDPlayerCodec.cpp +@@ -202,8 +202,11 @@ bool DVDPlayerCodec::Init(const CStdString &strFile, unsigned int filecache) + } + else + { +- m_pInputStream->Seek(0, SEEK_SET); +- m_pDemuxer->Reset(); ++ if (m_pInputStream->Seek(0, SEEK_POSSIBLE)) ++ { ++ m_pInputStream->Seek(0, SEEK_SET); ++ m_pDemuxer->Reset(); ++ } + m_bCanSeek = false; + } + +-- +1.9.1 + diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.90-show_rss-setting_in_standard_group.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.90-show_rss-setting_in_standard_group.patch new file mode 100644 index 0000000000..50186d7813 --- /dev/null +++ b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.90-show_rss-setting_in_standard_group.patch @@ -0,0 +1,12 @@ +diff -Naur xbmc-13.alpha-536cf62/system/settings/settings.xml xbmc-13.alpha-536cf62.patch/system/settings/settings.xml +--- xbmc-13.alpha-536cf62/system/settings/settings.xml 2014-01-29 18:31:46.000000000 +0100 ++++ xbmc-13.alpha-536cf62.patch/system/settings/settings.xml 2014-01-31 13:12:46.789297639 +0100 +@@ -91,7 +91,7 @@ + + + +- 1 ++ 0 + true + + diff --git a/packages/mediacenter/xbmc-master/profile.d/02-xbmc.conf b/packages/mediacenter/xbmc-master/profile.d/02-xbmc.conf new file mode 100644 index 0000000000..882e7d0f0a --- /dev/null +++ b/packages/mediacenter/xbmc-master/profile.d/02-xbmc.conf @@ -0,0 +1,29 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +# PATH +for addon in /storage/.xbmc/addons/*/bin /usr/lib/xbmc/addons/*/bin; do + [ -d "$addon" ] && PATH="$PATH:$addon" +done +export PATH + +# LD_LIBRARY_PATH +for addon in /storage/.xbmc/addons/*/lib /usr/lib/xbmc/addons/*/lib; do + [ -d "$addon" ] && LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$addon" +done +export LD_LIBRARY_PATH diff --git a/packages/mediacenter/xbmc-master/profile.d/03-addons.conf b/packages/mediacenter/xbmc-master/profile.d/03-addons.conf new file mode 100644 index 0000000000..bdd7525920 --- /dev/null +++ b/packages/mediacenter/xbmc-master/profile.d/03-addons.conf @@ -0,0 +1,40 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +oe_setup_addon() { + if [ ! -z $1 ] ; then + DEF="/storage/.xbmc/addons/$1/settings-default.xml" + CUR="/storage/.xbmc/userdata/addon_data/$1/settings.xml" + + # copy defaults + if [ -f "$DEF" -a ! -f "$CUR" ] ; then + cp "$DEF" "$CUR" + fi + + # parse config + [ -f "$DEF" ] && eval $(cat "$DEF" | awk -F\" '{print $2"=\""$4"\""}' | sed '/^=/d') + [ -f "$CUR" ] && eval $(cat "$CUR" | awk -F\" '{print $2"=\""$4"\""}' | sed '/^=/d') + + # export some useful variables + ADDON_DIR="$HOME/.xbmc/addons/$1" + ADDON_HOME="$HOME/.xbmc/userdata/addon_data/$1" + ADDON_LOG_FILE="$ADDON_HOME/service.log" + + [ ! -d $ADDON_HOME ] && mkdir -p $ADDON_HOME + fi +} diff --git a/packages/mediacenter/xbmc-master/scripts/cputemp b/packages/mediacenter/xbmc-master/scripts/cputemp new file mode 100755 index 0000000000..1136827f2d --- /dev/null +++ b/packages/mediacenter/xbmc-master/scripts/cputemp @@ -0,0 +1,67 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +# inspired by +# https://github.com/xtranophilist/gnome-shell-extension-cpu-temperature/blob/master/extension.js + +TEMP=0 + +if [ $(basename "$0") = "gputemp" -o "$1" = "gpu" ]; then + if which lspci >/dev/null; then + if lspci -n | grep 0300 | grep -q 10de; then + [ -x /usr/bin/nvidia-smi ] && TEMP=`/usr/bin/nvidia-smi -q -x | grep 'gpu_temp' | awk '{ print $1 }' | sed 's,,,g'` + fi + fi +fi + +if [ "$1" = "cpu" -o "$TEMP" = "0" ]; then + if [ -f /sys/class/hwmon/hwmon1/temp1_input ]; then + # used on Asus systems (ie. AT5IONT-I) + TEMP=`cat /sys/class/hwmon/hwmon1/temp1_input` + elif [ -f /sys/devices/platform/coretemp.0/temp1_input ]; then + # used with coretemp + TEMP=`cat /sys/devices/platform/coretemp.0/temp1_input` + elif [ -f /sys/devices/platform/coretemp.0/temp2_input ]; then + # used with coretemp + TEMP=`cat /sys/devices/platform/coretemp.0/temp2_input` + elif [ -f /sys/bus/acpi/devices/LNXTHERM\:00/thermal_zone/temp ]; then + # used on some intel systems + TEMP=`cat /sys/bus/acpi/devices/LNXTHERM\:00/thermal_zone/temp` + elif [ -f /sys/devices/virtual/thermal/thermal_zone0/temp ]; then + # used on some intel systems + TEMP=`cat /sys/devices/virtual/thermal/thermal_zone0/temp` + elif [ -f /sys/class/hwmon/hwmon0/temp1_input ]; then + # hwmon for new 2.6.39, 3.0 linux kernels + TEMP=`cat /sys/class/hwmon/hwmon0/temp1_input` + elif [ -f /sys/class/hwmon/hwmon0/device/temp1_input ]; then + # used on AMD systems + TEMP=`cat /sys/class/hwmon/hwmon0/device/temp1_input` + elif [ -f /sys/class/hwmon/hwmon0/device/temp2_input ]; then + # used on ION systems + TEMP=`cat /sys/class/hwmon/hwmon0/device/temp2_input` + elif [ -f /sys/class/thermal/thermal_zone0/temp ]; then + # used on RaspberryPi + TEMP=`cat /sys/class/thermal/thermal_zone0/temp` + fi + + TEMP="$(( $TEMP / 1000 ))" +fi + +echo "${TEMP} C" diff --git a/packages/mediacenter/xbmc-master/scripts/setwakeup.sh b/packages/mediacenter/xbmc-master/scripts/setwakeup.sh new file mode 100755 index 0000000000..76aa3d7c26 --- /dev/null +++ b/packages/mediacenter/xbmc-master/scripts/setwakeup.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +if [ -f /sys/class/rtc/rtc0/wakealarm ]; then + logger -t setwakeup.sh "### Setting system wakeup time ###" + echo 0 > /sys/class/rtc/rtc0/wakealarm + echo $1 > /sys/class/rtc/rtc0/wakealarm + logger -t setwakeup.sh "### $(cat /proc/driver/rtc) ###" +fi diff --git a/packages/mediacenter/xbmc-master/scripts/systemd-addon-wrapper b/packages/mediacenter/xbmc-master/scripts/systemd-addon-wrapper new file mode 100755 index 0000000000..e963c61af9 --- /dev/null +++ b/packages/mediacenter/xbmc-master/scripts/systemd-addon-wrapper @@ -0,0 +1,34 @@ +#!/bin/sh +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +if [ ! -d /storage/.config/system.d ] ; then + mkdir -p /storage/.config/system.d +fi + +if [ -f "/storage/.xbmc/addons/$1/system.d/$1.service" ] ; then + if [ $2 -eq 1 ] ; then + # disable = true: cleanup + systemctl stop "$1.service" + systemctl disable "/storage/.xbmc/addons/$1/system.d/$1.service" + else + # disable = false: setup + systemctl enable "/storage/.xbmc/addons/$1/system.d/$1.service" + systemctl start "$1.service" + fi +fi diff --git a/packages/mediacenter/xbmc-master/scripts/xbmc-config b/packages/mediacenter/xbmc-master/scripts/xbmc-config new file mode 100755 index 0000000000..1ad05bf38e --- /dev/null +++ b/packages/mediacenter/xbmc-master/scripts/xbmc-config @@ -0,0 +1,26 @@ +#!/bin/sh +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +if [ -e /run/lirc/lircd.irtrans ]; then + XBMC_ARGS="--lircdev /run/lirc/lircd.irtrans" +else + XBMC_ARGS="--lircdev /run/lirc/lircd" +fi + +echo "XBMC_ARGS=\"$XBMC_ARGS\"" > /run/openelec/xbmc.conf diff --git a/packages/mediacenter/xbmc-master/scripts/xbmc-hacks b/packages/mediacenter/xbmc-master/scripts/xbmc-hacks new file mode 100755 index 0000000000..2fabd47a19 --- /dev/null +++ b/packages/mediacenter/xbmc-master/scripts/xbmc-hacks @@ -0,0 +1,27 @@ +#!/bin/sh +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +# hack: make addon-bins executable + chmod +x /storage/.xbmc/addons/*/bin/* + +# hack: update RSSnews.xml in userdata + if [ -f /storage/.xbmc/userdata/RssFeeds.xml ]; then + sed -e "s,http://openelec.tv/news?format=feed&type=rss,http://feeds.openelec.tv/news,g" \ + -i /storage/.xbmc/userdata/RssFeeds.xml + fi diff --git a/packages/mediacenter/xbmc-master/scripts/xbmc-sources b/packages/mediacenter/xbmc-master/scripts/xbmc-sources new file mode 100755 index 0000000000..12fa659a8f --- /dev/null +++ b/packages/mediacenter/xbmc-master/scripts/xbmc-sources @@ -0,0 +1,85 @@ +#!/bin/sh +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +. /etc/profile + +# +# setup XBMC sources +# + + if [ ! -f $HOME/.xbmc/userdata/sources.xml ]; then + if [ -f /usr/share/xbmc/config/sources.xml ]; then + # include project specific sources + cp /usr/share/xbmc/config/sources.xml $HOME/.xbmc/userdata + else + cat > $HOME/.xbmc/userdata/sources.xml << EOF + + + + + + Music + $HOME/music/ + + + + + + Pictures + $HOME/pictures/ + + + +EOF + fi + fi + +# +# common setup guisettings +# + + if [ ! -f $HOME/.xbmc/userdata/guisettings.xml ] ; then + echo "" > $HOME/.xbmc/userdata/guisettings.xml + + cat >> $HOME/.xbmc/userdata/guisettings.xml << EOF + + $HOME/screenshots/ + +EOF + + # + # include project specific options + # + + if [ -f /usr/share/xbmc/config/guisettings.xml ]; then + cat /usr/share/xbmc/config/guisettings.xml >> $HOME/.xbmc/userdata/guisettings.xml + fi + + echo "" >> $HOME/.xbmc/userdata/guisettings.xml + fi diff --git a/packages/mediacenter/xbmc-master/sleep.d.serial/10-addon-sleep.sh b/packages/mediacenter/xbmc-master/sleep.d.serial/10-addon-sleep.sh new file mode 100755 index 0000000000..e44529791e --- /dev/null +++ b/packages/mediacenter/xbmc-master/sleep.d.serial/10-addon-sleep.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +. /etc/profile + +# see https://wiki.archlinux.org/index.php/Power_Management#Hooks_in_.2Fusr.2Flib.2Fsystemd.2Fsystem-sleep + +for script in $HOME/.xbmc/addons/*/sleep.d/*.power; do + progress "running addon sleep script $script ($@)..." + sh $script $@ +done + +exit 0 \ No newline at end of file diff --git a/packages/mediacenter/xbmc-master/sleep.d.serial/20-custon-sleep.sh b/packages/mediacenter/xbmc-master/sleep.d.serial/20-custon-sleep.sh new file mode 100755 index 0000000000..3ad0e0c04e --- /dev/null +++ b/packages/mediacenter/xbmc-master/sleep.d.serial/20-custon-sleep.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2013 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +. /etc/profile + +# see https://wiki.archlinux.org/index.php/Power_Management#Hooks_in_.2Fusr.2Flib.2Fsystemd.2Fsystem-sleep + +for script in $HOME/.config/sleep.d/*.power; do + if [ -f $script ]; then + progress "running custom sleep script $script ($@)..." + sh $script $@ + fi +done + +exit 0 \ No newline at end of file diff --git a/packages/mediacenter/xbmc-master/sleep.d/openelec-sleep.sh b/packages/mediacenter/xbmc-master/sleep.d/openelec-sleep.sh new file mode 100755 index 0000000000..6b314cd7bd --- /dev/null +++ b/packages/mediacenter/xbmc-master/sleep.d/openelec-sleep.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +. /etc/profile + +run_scripts() +{ + list_scripts $1 + for script in $SCRIPTS ; do + progress "running sleep script $script ($1)..." + sh /usr/lib/systemd/system-sleep.serial/$script $1 + done +} + +list_scripts() +{ + case $1 in + pre) + SCRIPTS=$(ls /usr/lib/systemd/system-sleep.serial/ | sort) + ;; + post) + SCRIPTS=$(ls /usr/lib/systemd/system-sleep.serial/ | sort -r) + ;; + esac +} + +run_scripts $1 + +exit 0 diff --git a/packages/mediacenter/xbmc-master/splash/splash.png b/packages/mediacenter/xbmc-master/splash/splash.png new file mode 100644 index 0000000000..6b2897b0a1 Binary files /dev/null and b/packages/mediacenter/xbmc-master/splash/splash.png differ diff --git a/packages/mediacenter/xbmc-master/splash/splash1.png b/packages/mediacenter/xbmc-master/splash/splash1.png new file mode 100644 index 0000000000..ac0aa0052f Binary files /dev/null and b/packages/mediacenter/xbmc-master/splash/splash1.png differ diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-autostart.service b/packages/mediacenter/xbmc-master/system.d/xbmc-autostart.service new file mode 100644 index 0000000000..2e98307e0f --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-autostart.service @@ -0,0 +1,13 @@ +[Unit] +Description=XBMC user autostart script +Before=xbmc.service +After=graphical.target + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=-/bin/sh -c ". /etc/profile; exec /bin/sh /storage/.config/autostart.sh" +RemainAfterExit=yes + +[Install] +WantedBy=xbmc.service diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-cleanlogs.service b/packages/mediacenter/xbmc-master/system.d/xbmc-cleanlogs.service new file mode 100644 index 0000000000..9faab0eec2 --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-cleanlogs.service @@ -0,0 +1,13 @@ +[Unit] +Description=XBMC clean debug logs +ConditionKernelCommandLine=!debugging +ConditionPathExists=!/storage/.cache/debug.openelec +Before=xbmc.service + +[Service] +Type=oneshot +ExecStart=-/bin/sh -c 'rm -rf /storage/.xbmc/userdata/addon_data/*/*.log /storage/.xbmc/userdata/addon_data/*/log/*' +RemainAfterExit=yes + +[Install] +WantedBy=xbmc.service diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-config.service b/packages/mediacenter/xbmc-master/system.d/xbmc-config.service new file mode 100644 index 0000000000..cb0f33faf8 --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-config.service @@ -0,0 +1,12 @@ +[Unit] +Description=XBMC configfile writer +Before=xbmc.service + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=/usr/lib/xbmc/xbmc-config +RemainAfterExit=yes + +[Install] +WantedBy=xbmc.service diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-hacks.service b/packages/mediacenter/xbmc-master/system.d/xbmc-hacks.service new file mode 100644 index 0000000000..efb48a6ac3 --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-hacks.service @@ -0,0 +1,12 @@ +[Unit] +Description=XBMC hacks +Before=xbmc.service + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=/usr/lib/xbmc/xbmc-hacks +RemainAfterExit=yes + +[Install] +WantedBy=xbmc.service diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-halt.service b/packages/mediacenter/xbmc-master/system.d/xbmc-halt.service new file mode 100644 index 0000000000..16ab30c50e --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-halt.service @@ -0,0 +1,14 @@ +[Unit] +Description=XBMC halt script +After=xbmc.service +Before=systemd-halt.service +DefaultDependencies=no + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=-/bin/sh /storage/.config/shutdown.sh halt +RemainAfterExit=yes + +[Install] +WantedBy=halt.target diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-lirc-suspend.service b/packages/mediacenter/xbmc-master/system.d/xbmc-lirc-suspend.service new file mode 100644 index 0000000000..f229b6b193 --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-lirc-suspend.service @@ -0,0 +1,13 @@ +[Unit] +Description=LIRC sleep hook +Before=sleep.target +StopWhenUnneeded=yes + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=-/usr/bin/xbmc-send --host=127.0.0.1 -a "LIRC.Stop" +ExecStop=-/usr/bin/xbmc-send --host=127.0.0.1 -a "LIRC.Start" + +[Install] +WantedBy=sleep.target diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-poweroff.service b/packages/mediacenter/xbmc-master/system.d/xbmc-poweroff.service new file mode 100644 index 0000000000..8a607da56a --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-poweroff.service @@ -0,0 +1,14 @@ +[Unit] +Description=XBMC poweroff script +After=xbmc.service +Before=systemd-poweroff.service +DefaultDependencies=no + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=-/bin/sh /storage/.config/shutdown.sh poweroff +RemainAfterExit=yes + +[Install] +WantedBy=poweroff.target diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-reboot.service b/packages/mediacenter/xbmc-master/system.d/xbmc-reboot.service new file mode 100644 index 0000000000..7ee1d5dabe --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-reboot.service @@ -0,0 +1,14 @@ +[Unit] +Description=XBMC reboot script +After=xbmc.service +Before=systemd-reboot.service +DefaultDependencies=no + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=-/bin/sh /storage/.config/shutdown.sh reboot +RemainAfterExit=yes + +[Install] +WantedBy=reboot.target diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-sources.service b/packages/mediacenter/xbmc-master/system.d/xbmc-sources.service new file mode 100644 index 0000000000..48e6dfb8a7 --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-sources.service @@ -0,0 +1,12 @@ +[Unit] +Description=XBMC sources Setup +Before=xbmc.service + +[Service] +Type=oneshot +Environment=HOME=/storage +ExecStart=/usr/lib/xbmc/xbmc-sources +RemainAfterExit=yes + +[Install] +WantedBy=xbmc.service diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-waitonnetwork.service b/packages/mediacenter/xbmc-master/system.d/xbmc-waitonnetwork.service new file mode 100644 index 0000000000..dc27a793ee --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc-waitonnetwork.service @@ -0,0 +1,17 @@ +[Unit] +Description=Wait on network +After=connman.service +Before=xorg.service fbset.service + +ConditionPathExists=/storage/.cache/openelec/network_wait + +[Service] +Type=oneshot +EnvironmentFile=/storage/.cache/openelec/network_wait +ExecStartPre=/bin/sh -c 'echo "waiting on Network to come online ... (max. $WAIT_NETWORK_TIME sec.)" +ExecStart=/usr/bin/cm-online ${WAIT_NETWORK_TIME} +StandardOutput=tty +RemainAfterExit=yes + +[Install] +WantedBy=xbmc.service diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc.service b/packages/mediacenter/xbmc-master/system.d/xbmc.service new file mode 100644 index 0000000000..545d31c62e --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc.service @@ -0,0 +1,21 @@ +[Unit] +Description=XBMC Media Center +After=graphical.target +Requires=graphical.target + +[Service] +Environment=DISPLAY=:0.0 +Environment=SDL_MOUSE_RELATIVE=0 +Environment=HOME=/storage +EnvironmentFile=-/run/openelec/xbmc.conf +EnvironmentFile=-/run/openelec/debug/xbmc.conf +ExecStart=/bin/sh -c ". /etc/profile; exec /usr/lib/xbmc/xbmc.bin --standalone -fs $XBMC_ARGS $XBMC_DEBUG" +# keep KillMode=process unless there is no good reason to switch to cgroup +KillMode=process +TimeoutStopSec=5 +Restart=always +RestartSec=2 +StartLimitInterval=0 + +[Install] +WantedBy=xbmc.target diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc.target b/packages/mediacenter/xbmc-master/system.d/xbmc.target new file mode 100644 index 0000000000..02e0fc0c82 --- /dev/null +++ b/packages/mediacenter/xbmc-master/system.d/xbmc.target @@ -0,0 +1,9 @@ +[Unit] +Description=XBMC Mediacenter Interface +Requires=multi-user.target graphical.target +After=graphical.target +Conflicts=rescue.target +AllowIsolate=yes + +[Install] +Alias=default.target diff --git a/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc-userdirs.conf b/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc-userdirs.conf new file mode 100644 index 0000000000..62552cdc49 --- /dev/null +++ b/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc-userdirs.conf @@ -0,0 +1,24 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +d /storage/.xbmc/userdata 0755 root root - - +d /storage/music 0755 root root - - +d /storage/pictures 0755 root root - - +d /storage/tvshows 0755 root root - - +d /storage/videos 0755 root root - - +d /storage/screenshots 0755 root root - - diff --git a/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc.conf b/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc.conf new file mode 100644 index 0000000000..24bcf7a5b7 --- /dev/null +++ b/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc.conf @@ -0,0 +1,19 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2014 Stephan Raue (stephan@openelec.tv) +# +# OpenELEC 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 of the License, or +# (at your option) any later version. +# +# OpenELEC 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 OpenELEC. If not, see . +################################################################################ + +d /run/xbmc 0755 root root - - diff --git a/projects/Cuboxi/patches/xbmc-master/xbmc-001-imx6_support.patch b/projects/Cuboxi/patches/xbmc-master/xbmc-001-imx6_support.patch new file mode 100644 index 0000000000..0bec4d85f4 --- /dev/null +++ b/projects/Cuboxi/patches/xbmc-master/xbmc-001-imx6_support.patch @@ -0,0 +1,3548 @@ +diff -Naur xbmc-13b4/configure.in xbmc-imx6-13b4/configure.in +--- xbmc-13b4/configure.in 2014-04-24 11:49:30.784354037 +0200 ++++ xbmc-imx6-13b4/configure.in 2014-04-24 11:50:13.695216693 +0200 +@@ -558,7 +558,7 @@ + + AC_ARG_ENABLE([codec], + [AS_HELP_STRING([--enable-codec], +- [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec, libstagefright)])], ++ [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec, libstagefright and imxvpu)])], + [add_codecs=$enableval], + [add_codecs=no]) + +@@ -1034,6 +1034,15 @@ + AC_MSG_RESULT($wayland_disabled) + fi + ++# i.MX6 ++AC_MSG_CHECKING([for i.MX framebuffer support]) ++AC_CHECK_HEADER([linux/mxcfb.h], have_imxfb=yes,have_imxfb=no) ++AC_MSG_RESULT($have_imxfb) ++if test "x$have_imxfb" = "xyes"; then ++ AC_DEFINE([HAS_IMXFB], [1], [Whether i.MX framebuffer support is enabled.]) ++ AC_SUBST([USE_IMXFB], 1) ++fi ++ + # Checks for platforms libraries. + if test "$use_gles" = "yes"; then + use_gl="no" +@@ -1991,6 +2000,17 @@ + *libstagefright*) + XB_ADD_CODEC([LIBSTAGEFRIGHT], [libstagefright], [$codecs]) + ;; ++ *imxvpu*) ++ AC_CHECK_HEADER([imx-mm/vpu/vpu_wrapper.h],, AC_MSG_ERROR($missing_headers)) ++ AC_CHECK_LIB([vpu], main, LIBS="$LIBS -lfslvpuwrap -lvpu", AC_MSG_ERROR($missing_library)) ++ XB_ADD_CODEC([IMXVPU], [imxvpu], [$codecs]) ++ CXXFLAGS="$CXXFLAGS -Wno-psabi -DLINUX " ++ CFLAGS="$CFLAGS -DLINUX" ++ if test "$use_x11" = "no"; then ++ CXXFLAGS="$CXXFLAGS -DEGL_API_FB" ++ CFLAGS="$CFLAGS -DEGL_API_FB" ++ fi ++ ;; + *) + esac + done +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp 2014-04-24 11:49:41.288075640 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -279,14 +279,16 @@ + if (format == AE_FMT_U8) return AV_SAMPLE_FMT_U8; + else if (format == AE_FMT_S16NE) return AV_SAMPLE_FMT_S16; + else if (format == AE_FMT_S32NE) return AV_SAMPLE_FMT_S32; +- else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32; ++ else if (format == AE_FMT_S24NE4H) return AV_SAMPLE_FMT_S32; ++ else if (format == AE_FMT_S24NE4L) return AV_SAMPLE_FMT_S32; + else if (format == AE_FMT_FLOAT) return AV_SAMPLE_FMT_FLT; + else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL; + + else if (format == AE_FMT_U8P) return AV_SAMPLE_FMT_U8P; + else if (format == AE_FMT_S16NEP) return AV_SAMPLE_FMT_S16P; + else if (format == AE_FMT_S32NEP) return AV_SAMPLE_FMT_S32P; +- else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P; ++ else if (format == AE_FMT_S24NE4HP) return AV_SAMPLE_FMT_S32P; ++ else if (format == AE_FMT_S24NE4LP) return AV_SAMPLE_FMT_S32P; + else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP; + else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; + +@@ -298,14 +300,14 @@ + if (format == AV_SAMPLE_FMT_U8) return AE_FMT_U8; + else if (format == AV_SAMPLE_FMT_S16) return AE_FMT_S16NE; + else if (format == AV_SAMPLE_FMT_S32 && bits == 32) return AE_FMT_S32NE; +- else if (format == AV_SAMPLE_FMT_S32 && bits == 24) return AE_FMT_S24NE4; ++ else if (format == AV_SAMPLE_FMT_S32 && bits == 24) return AE_FMT_S24NE4H; + else if (format == AV_SAMPLE_FMT_FLT) return AE_FMT_FLOAT; + else if (format == AV_SAMPLE_FMT_DBL) return AE_FMT_DOUBLE; + + else if (format == AV_SAMPLE_FMT_U8P) return AE_FMT_U8P; + else if (format == AV_SAMPLE_FMT_S16P) return AE_FMT_S16NEP; + else if (format == AV_SAMPLE_FMT_S32P && bits == 32) return AE_FMT_S32NEP; +- else if (format == AV_SAMPLE_FMT_S32P && bits == 24) return AE_FMT_S24NE4P; ++ else if (format == AV_SAMPLE_FMT_S32P && bits == 24) return AE_FMT_S24NE4HP; + else if (format == AV_SAMPLE_FMT_FLTP) return AE_FMT_FLOATP; + else if (format == AV_SAMPLE_FMT_DBLP) return AE_FMT_DOUBLEP; + +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp 2014-04-24 11:49:41.280075852 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -796,6 +796,12 @@ + } + } + ++static inline void RShift8_32_buf(uint32_t *src, uint32_t *dst, uint32_t count) ++{ ++ while (count--) ++ *dst++ = *src++ >> 8; ++} ++ + unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples) + { + uint8_t *buffer = samples->pkt->data[0]; +@@ -816,14 +822,22 @@ + case NEED_BYTESWAP: + Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels); + break; ++ case NEED_RSHIFT8: ++ RShift8_32_buf((uint32_t *)buffer, (uint32_t *)buffer, frames * samples->pkt->config.channels); ++ break; + case CHECK_CONVERT: + ConvertInit(samples); + if (m_convertState == NEED_CONVERT) + buffer = Convert(samples); + else if (m_convertState == NEED_BYTESWAP) + Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels); ++ else if (m_convertState == NEED_RSHIFT8) ++ RShift8_32_buf((uint32_t *)buffer, (uint32_t *)buffer, frames * samples->pkt->config.channels); ++ else if (m_convertState == SKIP_OUTPUT) ++ frames = 0; + break; +- default: ++ case SKIP_OUTPUT: ++ frames = 0; + break; + } + +@@ -862,15 +876,38 @@ + + void CActiveAESink::ConvertInit(CSampleBuffer* samples) + { +- if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat) ++ AEDataFormat srcFmt = CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample); ++ ++ if (srcFmt != m_sinkFormat.m_dataFormat) + { +- m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat); +- if (m_convertBuffer) +- _aligned_free(m_convertBuffer); +- m_convertBufferSampleSize = samples->pkt->max_nb_samples; +- m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16); +- memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize); +- m_convertState = NEED_CONVERT; ++ switch (srcFmt) ++ { ++ case AE_FMT_FLOAT: ++ case AE_FMT_FLOATP: ++ m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat); ++ if (m_convertBuffer) ++ _aligned_free(m_convertBuffer); ++ m_convertBufferSampleSize = samples->pkt->max_nb_samples; ++ m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16); ++ memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize); ++ m_convertState = NEED_CONVERT; ++ break; ++ case AE_FMT_S24NE4H: ++ m_convertState = (m_sinkFormat.m_dataFormat == AE_FMT_S24NE4L) ? NEED_RSHIFT8 : SKIP_OUTPUT; ++ break; ++ case AE_FMT_S24NE4HP: ++ m_convertState = (m_sinkFormat.m_dataFormat == AE_FMT_S24NE4LP) ? NEED_RSHIFT8 : SKIP_OUTPUT; ++ break; ++ default: ++ m_convertState = SKIP_OUTPUT; ++ break; ++ } ++ ++ if (m_convertState == SKIP_OUTPUT) ++ { ++ CLog::Log(LOGERROR, "CActiveAESink::ConvertInit - cannot convert from %s to %s", ++ CAEUtil::DataFormatToStr(srcFmt), CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat)); ++ } + } + else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat)) + { +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h +--- xbmc-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h 2014-04-24 11:49:41.288075640 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h 2014-04-24 11:50:14.007208425 +0200 +@@ -139,6 +139,8 @@ + NEED_CONVERT, + NEED_BYTESWAP, + SKIP_CONVERT, ++ NEED_RSHIFT8, ++ SKIP_OUTPUT + } m_convertState; + + std::string m_deviceFriendlyName; +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-04-24 11:49:41.256076488 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -268,7 +268,7 @@ + case AE_FMT_S16NE : return SND_PCM_FORMAT_S16; + case AE_FMT_S16LE : return SND_PCM_FORMAT_S16_LE; + case AE_FMT_S16BE : return SND_PCM_FORMAT_S16_BE; +- case AE_FMT_S24NE4: return SND_PCM_FORMAT_S24; ++ case AE_FMT_S24NE4L: return SND_PCM_FORMAT_S24; + #ifdef __BIG_ENDIAN__ + case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3BE; + #else +@@ -343,7 +343,7 @@ + { + /* if we opened in 32bit and only have 24bits, pack into 24 */ + if (fmtBits == 32 && bits == 24) +- i = AE_FMT_S24NE4; ++ i = AE_FMT_S24NE4L; + else + continue; + } +@@ -720,7 +720,10 @@ + * will automatically add "@" instead to enable surroundXX mangling. + * We don't want to do that if "default" can handle multichannel + * itself (e.g. in case of a pulseaudio server). */ +- EnumerateDevice(list, "default", "", config); ++ ++ /* For Wandboard, we do not enurate default device as it will be grabbed ++ * as one of the sysdefault devices... */ ++ + + void **hints; + +@@ -771,8 +774,8 @@ + * found by the enumeration process. Skip them as well ("hw", "dmix", + * "plughw", "dsnoop"). */ + ++ /* For wandboard all devices are prefixed by sysdefault so do not ignore them */ + else if (baseName != "default" +- && baseName != "sysdefault" + && baseName != "surround40" + && baseName != "surround41" + && baseName != "surround50" +@@ -881,6 +884,22 @@ + + AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) + { ++ std::size_t found; ++ ++ /* Hack : Check for specific wandboard sound device names */ ++ found = name.find("imxspdif"); ++ if (found!=std::string::npos) ++ return AE_DEVTYPE_IEC958; ++ ++ found = name.find("imxhdmisoc"); ++ if (found!=std::string::npos) ++ return AE_DEVTYPE_HDMI; ++ ++ found = name.find("sgtl5000audio"); ++ if (found!=std::string::npos) ++ return AE_DEVTYPE_PCM; ++ ++ + if (name.substr(0, 4) == "hdmi") + return AE_DEVTYPE_HDMI; + else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp 2014-04-24 11:49:41.268076170 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -80,9 +80,9 @@ + case AE_FMT_S24LE3: return PA_SAMPLE_S24LE; + case AE_FMT_S24BE3: return PA_SAMPLE_S24BE; + case AE_FMT_S24NE3: return PA_SAMPLE_S24NE; +- case AE_FMT_S24LE4: return PA_SAMPLE_S24_32LE; +- case AE_FMT_S24BE4: return PA_SAMPLE_S24_32BE; +- case AE_FMT_S24NE4: return PA_SAMPLE_S24_32NE; ++ case AE_FMT_S24LE4L: return PA_SAMPLE_S24_32LE; ++ case AE_FMT_S24BE4L: return PA_SAMPLE_S24_32BE; ++ case AE_FMT_S24NE4L: return PA_SAMPLE_S24_32NE; + case AE_FMT_S32BE : return PA_SAMPLE_S32BE; + case AE_FMT_S32LE : return PA_SAMPLE_S32LE; + case AE_FMT_S32NE : return PA_SAMPLE_S32NE; +@@ -119,9 +119,9 @@ + AE_FMT_S24LE3, + AE_FMT_S24BE3, + AE_FMT_S24NE3, +- AE_FMT_S24LE4, +- AE_FMT_S24BE4, +- AE_FMT_S24NE4, ++ AE_FMT_S24LE4L, ++ AE_FMT_S24BE4L, ++ AE_FMT_S24NE4L, + AE_FMT_S32BE, + AE_FMT_S32LE, + AE_FMT_S32NE, +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp 2014-04-24 11:49:41.276075958 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -111,7 +111,7 @@ + /* Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> -> 24 bit int -> 16 bit int */ + static const sampleFormat testFormats[] = { {KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, AE_FMT_FLOAT}, + {KSDATAFORMAT_SUBTYPE_PCM, 32, 32, AE_FMT_S32NE}, +- {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4}, ++ {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4H}, + {KSDATAFORMAT_SUBTYPE_PCM, 24, 24, AE_FMT_S24NE3}, + {KSDATAFORMAT_SUBTYPE_PCM, 16, 16, AE_FMT_S16NE} }; + +@@ -758,7 +758,7 @@ + wfxex.Format.wBitsPerSample = CAEUtil::DataFormatToBits((AEDataFormat) p); + wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); + wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; +- if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4) ++ if (p <= AE_FMT_S24NE4H && p >= AE_FMT_S24BE4H) + { + wfxex.Samples.wValidBitsPerSample = 24; + } +@@ -1149,7 +1149,7 @@ + else if (wfxex.Samples.wValidBitsPerSample == 32) + format.m_dataFormat = AE_FMT_S32NE; + else +- format.m_dataFormat = AE_FMT_S24NE4; ++ format.m_dataFormat = AE_FMT_S24NE4H; + } + else if (wfxex.Format.wBitsPerSample == 24) + format.m_dataFormat = AE_FMT_S24NE3; +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h +--- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h 2014-04-24 11:49:41.296075428 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEAudioFormat.h 2014-04-24 11:50:14.011208319 +0200 +@@ -41,9 +41,13 @@ + AE_FMT_S32LE, + AE_FMT_S32NE, + +- AE_FMT_S24BE4, +- AE_FMT_S24LE4, +- AE_FMT_S24NE4, /* S24 in 4 bytes */ ++ AE_FMT_S24BE4H, ++ AE_FMT_S24LE4H, ++ AE_FMT_S24NE4H, /* S24 in upper 4 bytes */ ++ ++ AE_FMT_S24BE4L, ++ AE_FMT_S24LE4L, ++ AE_FMT_S24NE4L, /* S24 in lower 4 bytes */ + + AE_FMT_S24BE3, + AE_FMT_S24LE3, +@@ -65,7 +69,8 @@ + AE_FMT_U8P, + AE_FMT_S16NEP, + AE_FMT_S32NEP, +- AE_FMT_S24NE4P, ++ AE_FMT_S24NE4HP, ++ AE_FMT_S24NE4LP, + AE_FMT_S24NE3P, + AE_FMT_DOUBLEP, + AE_FMT_FLOATP, +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-04-24 11:49:41.292075533 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -69,18 +69,22 @@ + #ifdef __BIG_ENDIAN__ + case AE_FMT_S16NE : return &S16BE_Float; + case AE_FMT_S32NE : return &S32BE_Float; +- case AE_FMT_S24NE4: return &S24BE4_Float; ++ case AE_FMT_S24NE4H: return &S24BE4H_Float; ++ case AE_FMT_S24NE4L: return &S24BE4L_Float; + case AE_FMT_S24NE3: return &S24BE3_Float; + #else + case AE_FMT_S16NE : return &S16LE_Float; + case AE_FMT_S32NE : return &S32LE_Float; +- case AE_FMT_S24NE4: return &S24LE4_Float; ++ case AE_FMT_S24NE4H: return &S24LE4H_Float; ++ case AE_FMT_S24NE4L: return &S24LE4L_Float; + case AE_FMT_S24NE3: return &S24LE3_Float; + #endif + case AE_FMT_S16LE : return &S16LE_Float; + case AE_FMT_S16BE : return &S16BE_Float; +- case AE_FMT_S24LE4: return &S24LE4_Float; +- case AE_FMT_S24BE4: return &S24BE4_Float; ++ case AE_FMT_S24LE4H: return &S24LE4H_Float; ++ case AE_FMT_S24LE4L: return &S24LE4L_Float; ++ case AE_FMT_S24BE4H: return &S24BE4H_Float; ++ case AE_FMT_S24BE4L: return &S24BE4L_Float; + case AE_FMT_S24LE3: return &S24LE3_Float; + case AE_FMT_S24BE3: return &S24BE3_Float; + #if defined(__ARM_NEON__) +@@ -112,7 +116,8 @@ + #endif + case AE_FMT_S16LE : return &Float_S16LE; + case AE_FMT_S16BE : return &Float_S16BE; +- case AE_FMT_S24NE4: return &Float_S24NE4; ++ case AE_FMT_S24NE4H: return &Float_S24NE4H; ++ case AE_FMT_S24NE4L: return &Float_S24NE4L; + case AE_FMT_S24NE3: return &Float_S24NE3; + #if defined(__ARM_NEON__) + case AE_FMT_S32LE : return &Float_S32LE_Neon; +@@ -210,7 +215,17 @@ + return samples; + } + +-unsigned int CAEConvert::S24LE4_Float(uint8_t *data, const unsigned int samples, float *dest) ++unsigned int CAEConvert::S24LE4H_Float(uint8_t *data, const unsigned int samples, float *dest) ++{ ++ for (unsigned int i = 0; i < samples; ++i, data += 4) ++ { ++ int s = (data[3] << 24) | (data[2] << 16) | (data[1] << 8); ++ *dest++ = (float)s * INT32_SCALE; ++ } ++ return samples; ++} ++ ++unsigned int CAEConvert::S24LE4L_Float(uint8_t *data, const unsigned int samples, float *dest) + { + for (unsigned int i = 0; i < samples; ++i, data += 4) + { +@@ -220,7 +235,7 @@ + return samples; + } + +-unsigned int CAEConvert::S24BE4_Float(uint8_t *data, const unsigned int samples, float *dest) ++unsigned int CAEConvert::S24BE4H_Float(uint8_t *data, const unsigned int samples, float *dest) + { + for (unsigned int i = 0; i < samples; ++i, data += 4) + { +@@ -230,6 +245,16 @@ + return samples; + } + ++unsigned int CAEConvert::S24BE4L_Float(uint8_t *data, const unsigned int samples, float *dest) ++{ ++ for (unsigned int i = 0; i < samples; ++i, data += 4) ++ { ++ int s = (data[1] << 24) | (data[2] << 16) | (data[3] << 8); ++ *dest++ = (float)s * INT32_SCALE; ++ } ++ return samples; ++} ++ + unsigned int CAEConvert::S24LE3_Float(uint8_t *data, const unsigned int samples, float *dest) + { + for (unsigned int i = 0; i < samples; ++i, data += 3) +@@ -244,7 +269,7 @@ + { + for (unsigned int i = 0; i < samples; ++i, data += 3) + { +- int s = (data[1] << 24) | (data[2] << 16) | (data[3] << 8); ++ int s = (data[0] << 24) | (data[1] << 16) | (data[2] << 8); + *dest++ = (float)s * INT32_SCALE; + } + return samples; +@@ -786,7 +811,7 @@ + return samples << 1; + } + +-unsigned int CAEConvert::Float_S24NE4(float *data, const unsigned int samples, uint8_t *dest) ++unsigned int CAEConvert::Float_S24NE4H(float *data, const unsigned int samples, uint8_t *dest) + { + int32_t *dst = (int32_t*)dest; + #ifdef __SSE2__ +@@ -797,7 +822,7 @@ + /* work around invalid alignment */ + while ((((uintptr_t)data & 0xF) || ((uintptr_t)dest & 0xF)) && count > 0) + { +- dst[0] = (safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; ++ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) << 8; + ++data; + ++dst; + --count; +@@ -816,7 +841,7 @@ + { + const uint32_t odd = count - even; + if (odd == 1) +- dst[0] = (safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; ++ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) << 8; + else + { + __m128 in; +@@ -841,7 +866,69 @@ + _mm_empty(); + #else /* no SSE2 */ + for (uint32_t i = 0; i < samples; ++i) +- *dst++ = (safeRound(*data++ * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; ++ *dst++ = safeRound(*data++ * ((float)INT24_MAX+.5f)) << 8; ++ #endif ++ ++ return samples << 2; ++} ++ ++unsigned int CAEConvert::Float_S24NE4L(float *data, const unsigned int samples, uint8_t *dest) ++{ ++ int32_t *dst = (int32_t*)dest; ++ #ifdef __SSE2__ ++ ++ const __m128i msk = _mm_set1_epi32(0xFFFFFF); ++ const __m128 mul = _mm_set_ps1((float)INT24_MAX+.5f); ++ unsigned int count = samples; ++ ++ /* work around invalid alignment */ ++ while ((((uintptr_t)data & 0xF) || ((uintptr_t)dest & 0xF)) && count > 0) ++ { ++ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF; ++ ++data; ++ ++dst; ++ --count; ++ } ++ ++ const uint32_t even = count & ~0x3; ++ for (uint32_t i = 0; i < even; i += 4, data += 4, dst += 4) ++ { ++ __m128 in = _mm_mul_ps(_mm_load_ps(data), mul); ++ __m128i con = _mm_cvtps_epi32(in); ++ con = _mm_and_si128(con, msk); ++ memcpy(dst, &con, sizeof(int32_t) * 4); ++ } ++ ++ if (count != even) ++ { ++ const uint32_t odd = count - even; ++ if (odd == 1) ++ dst[0] = safeRound(data[0] * ((float)INT24_MAX+.5f)) & 0xFFFFFF; ++ else ++ { ++ __m128 in; ++ if (odd == 2) ++ { ++ in = _mm_setr_ps(data[0], data[1], 0, 0); ++ in = _mm_mul_ps(in, mul); ++ __m128i con = _mm_cvtps_epi32(in); ++ con = _mm_and_si128(con, msk); ++ memcpy(dst, &con, sizeof(int32_t) * 2); ++ } ++ else ++ { ++ in = _mm_setr_ps(data[0], data[1], data[2], 0); ++ in = _mm_mul_ps(in, mul); ++ __m128i con = _mm_cvtps_epi32(in); ++ con = _mm_and_si128(con, msk); ++ memcpy(dst, &con, sizeof(int32_t) * 3); ++ } ++ } ++ } ++ _mm_empty(); ++ #else /* no SSE2 */ ++ for (uint32_t i = 0; i < samples; ++i) ++ *dst++ = safeRound(*data++ * ((float)INT24_MAX+.5f)) & 0xFFFFFF; + #endif + + return samples << 2; +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h +--- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h 2014-04-24 11:49:41.292075533 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEConvert.h 2014-04-24 11:50:14.007208425 +0200 +@@ -28,8 +28,10 @@ + static unsigned int S8_Float (uint8_t *data, const unsigned int samples, float *dest); + static unsigned int S16LE_Float (uint8_t *data, const unsigned int samples, float *dest); + static unsigned int S16BE_Float (uint8_t *data, const unsigned int samples, float *dest); +- static unsigned int S24LE4_Float(uint8_t *data, const unsigned int samples, float *dest); +- static unsigned int S24BE4_Float(uint8_t *data, const unsigned int samples, float *dest); ++ static unsigned int S24LE4H_Float(uint8_t *data, const unsigned int samples, float *dest); ++ static unsigned int S24LE4L_Float(uint8_t *data, const unsigned int samples, float *dest); ++ static unsigned int S24BE4H_Float(uint8_t *data, const unsigned int samples, float *dest); ++ static unsigned int S24BE4L_Float(uint8_t *data, const unsigned int samples, float *dest); + static unsigned int S24LE3_Float(uint8_t *data, const unsigned int samples, float *dest); + static unsigned int S24BE3_Float(uint8_t *data, const unsigned int samples, float *dest); + static unsigned int S32LE_Float (uint8_t *data, const unsigned int samples, float *dest); +@@ -41,7 +43,8 @@ + static unsigned int Float_S8 (float *data, const unsigned int samples, uint8_t *dest); + static unsigned int Float_S16LE (float *data, const unsigned int samples, uint8_t *dest); + static unsigned int Float_S16BE (float *data, const unsigned int samples, uint8_t *dest); +- static unsigned int Float_S24NE4(float *data, const unsigned int samples, uint8_t *dest); ++ static unsigned int Float_S24NE4H(float *data, const unsigned int samples, uint8_t *dest); ++ static unsigned int Float_S24NE4L(float *data, const unsigned int samples, uint8_t *dest); + static unsigned int Float_S24NE3(float *data, const unsigned int samples, uint8_t *dest); + static unsigned int Float_S32LE (float *data, const unsigned int samples, uint8_t *dest); + static unsigned int Float_S32BE (float *data, const unsigned int samples, uint8_t *dest); +diff -Naur xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp +--- xbmc-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp 2014-04-24 11:49:41.296075428 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/AudioEngine/Utils/AEUtil.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -92,9 +92,13 @@ + 32, /* S32LE */ + 32, /* S32NE */ + +- 32, /* S24BE */ +- 32, /* S24LE */ +- 32, /* S24NE */ ++ 32, /* S24BE4H */ ++ 32, /* S24LE4H */ ++ 32, /* S24NE4H */ ++ ++ 32, /* S24BE4L */ ++ 32, /* S24LE4L */ ++ 32, /* S24NE4L */ + + 24, /* S24BE3 */ + 24, /* S24LE3 */ +@@ -114,8 +118,9 @@ + 8, /* U8P */ + 16, /* S16NEP */ + 32, /* S32NEP */ +- 32, /* S24NEP */ +- 24, /* S24NE3P*/ ++ 32, /* S24NE4HP */ ++ 32, /* S24NE4LP */ ++ 24, /* S24NE3P */ + sizeof(double) << 3, /* DOUBLEP */ + sizeof(float ) << 3 /* FLOATP */ + }; +@@ -125,7 +130,8 @@ + + const unsigned int CAEUtil::DataFormatToUsedBits(const enum AEDataFormat dataFormat) + { +- if (dataFormat == AE_FMT_S24BE4 || dataFormat == AE_FMT_S24LE4 || dataFormat == AE_FMT_S24NE4) ++ if (dataFormat == AE_FMT_S24BE4H || dataFormat == AE_FMT_S24LE4H || dataFormat == AE_FMT_S24NE4H || ++ dataFormat == AE_FMT_S24BE4L || dataFormat == AE_FMT_S24LE4L || dataFormat == AE_FMT_S24NE4L) + return 24; + else + return DataFormatToBits(dataFormat); +@@ -149,9 +155,13 @@ + "AE_FMT_S32LE", + "AE_FMT_S32NE", + +- "AE_FMT_S24BE4", +- "AE_FMT_S24LE4", +- "AE_FMT_S24NE4", /* S24 in 4 bytes */ ++ "AE_FMT_S24BE4H", ++ "AE_FMT_S24LE4H", ++ "AE_FMT_S24NE4H", /* S24 in upper 4 bytes */ ++ ++ "AE_FMT_S24BE4L", ++ "AE_FMT_S24LE4L", ++ "AE_FMT_S24NE4L", /* S24 in lower 4 bytes */ + + "AE_FMT_S24BE3", + "AE_FMT_S24LE3", +@@ -173,7 +183,8 @@ + "AE_FMT_U8P", + "AE_FMT_S16NEP", + "AE_FMT_S32NEP", +- "AE_FMT_S24NE4P", ++ "AE_FMT_S24NE4HP", ++ "AE_FMT_S24NE4LP", + "AE_FMT_S24NE3P", + "AE_FMT_DOUBLEP", + "AE_FMT_FLOATP" +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-04-24 11:49:41.204077867 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -35,6 +35,9 @@ + #include "Video/DVDVideoCodecFFmpeg.h" + #include "Video/DVDVideoCodecOpenMax.h" + #include "Video/DVDVideoCodecLibMpeg2.h" ++#if defined(HAS_IMXVPU) ++#include "Video/DVDVideoCodecIMX.h" ++#endif + #include "Video/DVDVideoCodecStageFright.h" + #if defined(HAVE_LIBCRYSTALHD) + #include "Video/DVDVideoCodecCrystalHD.h" +@@ -191,7 +194,11 @@ + #elif defined(TARGET_POSIX) && !defined(TARGET_DARWIN) + hwSupport += "VAAPI:no "; + #endif +- ++#if defined(HAS_IMXVPU) ++ hwSupport += "iMXVPU:yes "; ++#else ++ hwSupport += "iMXVPU:no "; ++#endif + CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); + #if defined(HAS_LIBAMCODEC) + // amcodec can handle dvd playback. +@@ -205,6 +212,15 @@ + } + } + ++/*#endif*/ ++ ++#if defined(HAS_IMXVPU) ++ if (!hint.software) ++ { ++ if ( (pCodec = OpenCodec(new CDVDVideoCodecIMX(), hint, options)) ) return pCodec; ++ } ++#endif ++ + #if defined(TARGET_DARWIN_OSX) + if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda")) + { +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-04-24 11:49:41.200077973 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h 2014-04-24 11:50:14.007208425 +0200 +@@ -27,6 +27,7 @@ + #include + #include + #include "cores/VideoRenderers/RenderFormats.h" ++#include "DVDVideoCodecInfo.h" + + struct DVDCodecAvailableType + { +@@ -91,6 +92,11 @@ + struct { + CDVDMediaCodecInfo *mediacodec; + }; ++ ++ struct { ++ CDVDVideoCodecBuffer *codecinfo; ++ }; ++ + }; + + unsigned int iFlags; +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2014-04-24 11:50:14.007208425 +0200 +@@ -0,0 +1,1501 @@ ++/* ++ * Copyright (C) 2010-2013 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, see ++ * . ++ * ++ */ ++ ++#include "DVDVideoCodecIMX.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "threads/SingleLock.h" ++#include "utils/log.h" ++#include "DVDClock.h" ++#include "threads/Atomics.h" ++ ++ ++// FIXME get rid of these defines properly ++#define FRAME_ALIGN 16 ++#define MEDIAINFO 1 ++#define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1)) ++#define Align(ptr,align) (((unsigned int)ptr + (align) - 1)/(align)*(align)) ++ ++// Extrace physical and virtual addresses from CDVDVideoCodecBuffer pointers ++#define GET_PHYS_ADDR(buf) (buf)->data[1] ++#define GET_VIRT_ADDR(buf) (buf)->data[0] ++#define GET_DEINTERLACER(buf) (buf)->data[2] ++#define GET_FIELDTYPE(buf) (buf)->data[3] ++ ++// Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU ++const int CDVDVideoCodecIMX::m_extraVpuBuffers = 6; ++const int CDVDVideoCodecIMX::m_maxVpuDecodeLoops = 5; ++CCriticalSection CDVDVideoCodecIMX::m_codecBufferLock; ++ ++bool CDVDVideoCodecIMX::VpuAllocBuffers(VpuMemInfo *pMemBlock) ++{ ++ int i, size; ++ void* ptr; ++ VpuMemDesc vpuMem; ++ VpuDecRetCode ret; ++ ++ for(i=0; inSubBlockNum; i++) ++ { ++ size = pMemBlock->MemSubBlock[i].nAlignment + pMemBlock->MemSubBlock[i].nSize; ++ if (pMemBlock->MemSubBlock[i].MemType == VPU_MEM_VIRT) ++ { // Allocate standard virtual memory ++ ptr = malloc(size); ++ if(ptr == NULL) ++ { ++ CLog::Log(LOGERROR, "%s - Unable to malloc %d bytes.\n", __FUNCTION__, size); ++ goto AllocFailure; ++ } ++ pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(ptr, pMemBlock->MemSubBlock[i].nAlignment); ++ ++ m_decMemInfo.nVirtNum++; ++ m_decMemInfo.virtMem = (void**)realloc(m_decMemInfo.virtMem, m_decMemInfo.nVirtNum*sizeof(void*)); ++ m_decMemInfo.virtMem[m_decMemInfo.nVirtNum-1] = ptr; ++ } ++ else ++ { // Allocate contigous mem for DMA ++ vpuMem.nSize = size; ++ ret = VPU_DecGetMem(&vpuMem); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - Unable alloc %d bytes of physical memory (%d).\n", __FUNCTION__, size, ret); ++ goto AllocFailure; ++ } ++ pMemBlock->MemSubBlock[i].pVirtAddr = (unsigned char*)Align(vpuMem.nVirtAddr, pMemBlock->MemSubBlock[i].nAlignment); ++ pMemBlock->MemSubBlock[i].pPhyAddr = (unsigned char*)Align(vpuMem.nPhyAddr, pMemBlock->MemSubBlock[i].nAlignment); ++ ++ m_decMemInfo.nPhyNum++; ++ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = size; ++ } ++ } ++ ++ return true; ++ ++AllocFailure: ++ VpuFreeBuffers(); ++ return false; ++} ++ ++int CDVDVideoCodecIMX::VpuFindBuffer(void *frameAddr) ++{ ++ for (int i=0; i1) ++ { ++ ySize=Align(ySize,nAlign); ++ uvSize=Align(uvSize,nAlign); ++ } ++ ++ m_outputBuffers = new CDVDVideoCodecIMXBuffer*[m_vpuFrameBufferNum]; ++ ++ for (int i=0 ; i < m_vpuFrameBufferNum; i++) ++ { ++ totalSize=(ySize+uvSize+mvSize+nAlign)*1; ++ ++ vpuMem.nSize=totalSize; ++ ret = VPU_DecGetMem(&vpuMem); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s: vpu malloc frame buf failure: ret=%d \r\n",__FUNCTION__,ret); ++ return false; ++ } ++ ++ //record memory info for release ++ m_decMemInfo.nPhyNum++; ++ m_decMemInfo.phyMem = (VpuMemDesc*)realloc(m_decMemInfo.phyMem, m_decMemInfo.nPhyNum*sizeof(VpuMemDesc)); ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nPhyAddr = vpuMem.nPhyAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nVirtAddr = vpuMem.nVirtAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nCpuAddr = vpuMem.nCpuAddr; ++ m_decMemInfo.phyMem[m_decMemInfo.nPhyNum-1].nSize = vpuMem.nSize; ++ ++ //fill frameBuf ++ ptr=(unsigned char*)vpuMem.nPhyAddr; ++ ptrVirt=(unsigned char*)vpuMem.nVirtAddr; ++ ++ //align the base address ++ if(nAlign>1) ++ { ++ ptr=(unsigned char*)Align(ptr,nAlign); ++ ptrVirt=(unsigned char*)Align(ptrVirt,nAlign); ++ } ++ ++ // fill stride info ++ m_vpuFrameBuffers[i].nStrideY=yStride; ++ m_vpuFrameBuffers[i].nStrideC=uvStride; ++ ++ // fill phy addr ++ m_vpuFrameBuffers[i].pbufY=ptr; ++ m_vpuFrameBuffers[i].pbufCb=ptr+ySize; ++ m_vpuFrameBuffers[i].pbufCr=0; ++ m_vpuFrameBuffers[i].pbufMvCol=ptr+ySize+uvSize; ++ //ptr+=ySize+uSize+vSize+mvSize; ++ // fill virt addr ++ m_vpuFrameBuffers[i].pbufVirtY=ptrVirt; ++ m_vpuFrameBuffers[i].pbufVirtCb=ptrVirt+ySize; ++ m_vpuFrameBuffers[i].pbufVirtCr=0; ++ m_vpuFrameBuffers[i].pbufVirtMvCol=ptrVirt+ySize+uvSize; ++ //ptrVirt+=ySize+uSize+vSize+mvSize; ++ ++ m_vpuFrameBuffers[i].pbufY_tilebot=0; ++ m_vpuFrameBuffers[i].pbufCb_tilebot=0; ++ m_vpuFrameBuffers[i].pbufVirtY_tilebot=0; ++ m_vpuFrameBuffers[i].pbufVirtCb_tilebot=0; ++ ++#ifdef TRACE_FRAMES ++ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(i); ++#else ++ m_outputBuffers[i] = new CDVDVideoCodecIMXBuffer(); ++#endif ++ } ++ ++ if (m_initInfo.nInterlace) ++ { ++ CLog::Log(LOGNOTICE, "IMX: Enable hardware deinterlacing\n"); ++ if (!m_deinterlacer.Init(m_initInfo.nPicWidth, m_initInfo.nPicHeight, GetAllowedReferences()+1, nAlign)) ++ { ++ CLog::Log(LOGWARNING, "IMX: Failed to initialize IPU buffers: deinterlacing disabled\n"); ++ } ++ else ++ { ++ for (int i=0; iOpen(hints.codec, (uint8_t *)hints.extradata, hints.extrasize, true); ++ } ++ } ++ break; ++ case CODEC_ID_VC1: ++ m_decOpenParam.CodecFormat = VPU_V_VC1_AP; ++ m_pFormatName = "iMX-vc1"; ++ break; ++/* FIXME TODO ++ * => for this type we have to set height, width, nChromaInterleave and nMapType ++ case CODEC_ID_MJPEG: ++ m_decOpenParam.CodecFormat = VPU_V_MJPG; ++ m_pFormatName = "iMX-mjpg"; ++ break;*/ ++ case CODEC_ID_CAVS: ++ case CODEC_ID_AVS: ++ m_decOpenParam.CodecFormat = VPU_V_AVS; ++ m_pFormatName = "iMX-AVS"; ++ break; ++ case CODEC_ID_RV10: ++ case CODEC_ID_RV20: ++ case CODEC_ID_RV30: ++ case CODEC_ID_RV40: ++ m_decOpenParam.CodecFormat = VPU_V_RV; ++ m_pFormatName = "iMX-RV"; ++ break; ++ case CODEC_ID_KMVC: ++ m_decOpenParam.CodecFormat = VPU_V_AVC_MVC; ++ m_pFormatName = "iMX-MVC"; ++ break; ++ case CODEC_ID_VP8: ++ m_decOpenParam.CodecFormat = VPU_V_VP8; ++ m_pFormatName = "iMX-vp8"; ++ break; ++ case CODEC_ID_MPEG4: ++ switch(m_hints.codec_tag) ++ { ++ case _4CC('D','I','V','X'): ++ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX4 ++ m_pFormatName = "iMX-divx4"; ++ break; ++ case _4CC('D','X','5','0'): ++ case _4CC('D','I','V','5'): ++ m_decOpenParam.CodecFormat = VPU_V_XVID; // VPU_V_DIVX56 ++ m_pFormatName = "iMX-divx5"; ++ break; ++ case _4CC('X','V','I','D'): ++ case _4CC('M','P','4','V'): ++ case _4CC('P','M','P','4'): ++ case _4CC('F','M','P','4'): ++ m_decOpenParam.CodecFormat = VPU_V_XVID; ++ m_pFormatName = "iMX-xvid"; ++ break; ++ default: ++ CLog::Log(LOGERROR, "iMX VPU : MPEG4 codec tag %d is not (yet) handled.\n", m_hints.codec_tag); ++ return false; ++ } ++ break; ++ default: ++ CLog::Log(LOGERROR, "iMX VPU : codecid %d is not (yet) handled.\n", m_hints.codec); ++ return false; ++ } ++ ++ return true; ++} ++ ++void CDVDVideoCodecIMX::Dispose(void) ++{ ++ VpuDecRetCode ret; ++ bool VPU_loaded = m_vpuHandle; ++ ++ // Block render thread from using that framebuffers ++ Enter(); ++ ++ // Release last buffer ++ if(m_lastBuffer) ++ SAFE_RELEASE(m_lastBuffer); ++ ++ // Invalidate output buffers to prevent the renderer from mapping this memory ++ for (int i=0; iReleaseFramebuffer(&m_vpuHandle); ++ SAFE_RELEASE(m_outputBuffers[i]); ++ } ++ ++ Leave(); ++ ++ if (m_vpuHandle) ++ { ++ ret = VPU_DecFlushAll(m_vpuHandle); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); ++ } ++ ret = VPU_DecClose(m_vpuHandle); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU close failed with error code %d.\n", __FUNCTION__, ret); ++ } ++ m_vpuHandle = 0; ++ } ++ ++ m_frameCounter = 0; ++ m_deinterlacer.Close(); ++ ++ // Clear memory ++ if (m_outputBuffers != NULL) ++ { ++ delete m_outputBuffers; ++ m_outputBuffers = NULL; ++ } ++ ++ VpuFreeBuffers(); ++ m_vpuFrameBufferNum = 0; ++ ++ if (m_vpuFrameBuffers != NULL) ++ { ++ delete m_vpuFrameBuffers; ++ m_vpuFrameBuffers = NULL; ++ } ++ ++ if (VPU_loaded) ++ { ++ ret = VPU_DecUnLoad(); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU unload failed with error code %d.\n", __FUNCTION__, ret); ++ } ++ } ++ ++ if (m_converter) ++ { ++ m_converter->Close(); ++ SAFE_DELETE(m_converter); ++ } ++ return; ++} ++ ++int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts) ++{ ++ VpuDecFrameLengthInfo frameLengthInfo; ++ VpuBufferNode inData; ++ VpuDecRetCode ret; ++ int decRet = 0; ++ int retStatus = 0; ++ int demuxer_bytes = iSize; ++ uint8_t *demuxer_content = pData; ++ int retries = 0; ++ int idx; ++ ++#ifdef IMX_PROFILE ++ static unsigned long long previous, current; ++ unsigned long long before_dec; ++#endif ++ ++ if (!m_vpuHandle) ++ { ++ VpuOpen(); ++ if (!m_vpuHandle) ++ return VC_ERROR; ++ } ++ ++ for (int i=0; i < m_vpuFrameBufferNum; i++) ++ { ++ if (m_outputBuffers[i]->Rendered()) ++ { ++ ret = m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); ++ } ++ } ++ } ++ ++#ifdef IMX_PROFILE ++ current = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGDEBUG, "%s - delta time decode : %llu - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, current - previous, iSize, dts, pts); ++ previous = current; ++#endif ++ ++ if ((pData && iSize) || ++ (m_bytesToBeConsumed)) ++ { ++ if ((m_convert_bitstream) && (iSize)) ++ { ++ // convert demuxer packet from bitstream to bytestream (AnnexB) ++ if (m_converter->Convert(demuxer_content, demuxer_bytes)) ++ { ++ demuxer_content = m_converter->GetConvertBuffer(); ++ demuxer_bytes = m_converter->GetConvertSize(); ++ } ++ else ++ CLog::Log(LOGERROR,"%s - bitstream_convert error", __FUNCTION__); ++ } ++ ++ inData.nSize = demuxer_bytes; ++ inData.pPhyAddr = NULL; ++ inData.pVirAddr = demuxer_content; ++ // FIXME TODO VP8 & DivX3 require specific sCodecData values ++ if ((m_decOpenParam.CodecFormat == VPU_V_MPEG2) || ++ (m_decOpenParam.CodecFormat == VPU_V_VC1_AP)|| ++ (m_decOpenParam.CodecFormat == VPU_V_XVID)) ++ { ++ inData.sCodecData.pData = (unsigned char *)m_hints.extradata; ++ inData.sCodecData.nSize = m_hints.extrasize; ++ } ++ else ++ { ++ inData.sCodecData.pData = NULL; ++ inData.sCodecData.nSize = 0; ++ } ++ ++ while (true) // Decode as long as the VPU consumes data ++ { ++#ifdef IMX_PROFILE ++ before_dec = XbmcThreads::SystemClockMillis(); ++#endif ++ if (m_frameReported) ++ m_bytesToBeConsumed += inData.nSize; ++ ret = VPU_DecDecodeBuf(m_vpuHandle, &inData, &decRet); ++#ifdef IMX_PROFILE ++ CLog::Log(LOGDEBUG, "%s - VPU dec 0x%x decode takes : %lld\n\n", __FUNCTION__, decRet, XbmcThreads::SystemClockMillis() - before_dec); ++#endif ++ ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU decode failed with error code %d.\n", __FUNCTION__, ret); ++ goto out_error; ++ } ++ ++ if (decRet & VPU_DEC_INIT_OK) ++ // VPU decoding init OK : We can retrieve stream info ++ { ++ ret = VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo); ++ if (ret == VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGDEBUG, "%s - VPU Init Stream Info : %dx%d (interlaced : %d - Minframe : %d)"\ ++ " - Align : %d bytes - crop : %d %d %d %d - Q16Ratio : %x\n", __FUNCTION__, ++ m_initInfo.nPicWidth, m_initInfo.nPicHeight, m_initInfo.nInterlace, m_initInfo.nMinFrameBufferCount, ++ m_initInfo.nAddressAlignment, m_initInfo.PicCropRect.nLeft, m_initInfo.PicCropRect.nTop, ++ m_initInfo.PicCropRect.nRight, m_initInfo.PicCropRect.nBottom, m_initInfo.nQ16ShiftWidthDivHeightRatio); ++ if (VpuAllocFrameBuffers()) ++ { ++ ret = VPU_DecRegisterFrameBuffer(m_vpuHandle, m_vpuFrameBuffers, m_vpuFrameBufferNum); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU error while registering frame buffers (%d).\n", __FUNCTION__, ret); ++ goto out_error; ++ } ++ } ++ else ++ { ++ goto out_error; ++ } ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "%s - VPU get initial info failed (%d).\n", __FUNCTION__, ret); ++ goto out_error; ++ } ++ } //VPU_DEC_INIT_OK ++ ++ if (decRet & VPU_DEC_ONE_FRM_CONSUMED) ++ { ++ ret = VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret); ++ } ++ m_bytesToBeConsumed -= (frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength); ++ if (frameLengthInfo.pFrame) ++ { ++ idx = VpuFindBuffer(frameLengthInfo.pFrame->pbufY); ++ if (m_bytesToBeConsumed < 50) ++ m_bytesToBeConsumed = 0; ++ if (idx != -1) ++ { ++ if (m_previousPts != DVD_NOPTS_VALUE) ++ { ++ m_outputBuffers[idx]->SetPts(m_previousPts); ++ m_previousPts = DVD_NOPTS_VALUE; ++ } ++ else ++ m_outputBuffers[idx]->SetPts(pts); ++ } ++ else ++ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); ++ } ++ } //VPU_DEC_ONE_FRM_CONSUMED ++ ++ if (decRet & VPU_DEC_OUTPUT_DIS) ++ // Frame ready to be displayed ++ { ++ if (retStatus & VC_PICTURE) ++ CLog::Log(LOGERROR, "%s - Second picture in the same decode call !\n", __FUNCTION__); ++ ++ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); ++ goto out_error; ++ } ++ ++ // Some codecs (VC1?) lie about their frame size (mod 16). Adjust... ++ m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); ++ m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); ++ ++ retStatus |= VC_PICTURE; ++ } //VPU_DEC_OUTPUT_DIS ++ ++ // According to libfslvpuwrap: If this flag is set then the frame should ++ // be dropped. It is just returned to gather decoder information but not ++ // for display. ++ if (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS) ++ { ++ ret = VPU_DecGetOutputFrame(m_vpuHandle, &m_frameInfo); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret); ++ goto out_error; ++ } ++ ++ // Display frame ++ ret = VPU_DecOutFrameDisplayed(m_vpuHandle, m_frameInfo.pDisplayFrameBuf); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s: VPU Clear frame display failure(%d)\n",__FUNCTION__,ret); ++ goto out_error; ++ } ++ } //VPU_DEC_OUTPUT_MOSAIC_DIS ++ ++ if (decRet & VPU_DEC_OUTPUT_REPEAT) ++ { ++ CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__); ++ } ++ if (decRet & VPU_DEC_OUTPUT_DROPPED) ++ { ++ CLog::Log(LOGDEBUG, "%s - Frame dropped.\n", __FUNCTION__); ++ } ++ if (decRet & VPU_DEC_NO_ENOUGH_BUF) ++ { ++ CLog::Log(LOGERROR, "%s - No frame buffer available.\n", __FUNCTION__); ++ } ++ if (decRet & VPU_DEC_SKIP) ++ { ++ CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__); ++ } ++ if (decRet & VPU_DEC_FLUSH) ++ { ++ CLog::Log(LOGNOTICE, "%s - VPU requires a flush.\n", __FUNCTION__); ++ Reset(); ++ retStatus = VC_FLUSHED; ++ } ++ if (decRet & VPU_DEC_OUTPUT_EOS) ++ { ++ CLog::Log(LOGNOTICE, "%s - EOS encountered.\n", __FUNCTION__); ++ } ++ if ((decRet & VPU_DEC_NO_ENOUGH_INBUF) || ++ (decRet & VPU_DEC_OUTPUT_DIS)) ++ { ++ // We are done with VPU decoder that time ++ break; ++ } ++ ++ retries++; ++ if (retries >= m_maxVpuDecodeLoops) ++ { ++ CLog::Log(LOGERROR, "%s - Leaving VPU decoding loop after %d iterations\n", __FUNCTION__, m_maxVpuDecodeLoops); ++ break; ++ } ++ ++ if (!(decRet & VPU_DEC_INPUT_USED)) ++ { ++ CLog::Log(LOGERROR, "%s - input not used : addr %p size :%d!\n", __FUNCTION__, inData.pVirAddr, inData.nSize); ++ } ++ ++ // Let's process again as VPU_DEC_NO_ENOUGH_INBUF was not set ++ // and we don't have an image ready if we reach that point ++ inData.pVirAddr = NULL; ++ inData.nSize = 0; ++ } // Decode loop ++ } //(pData && iSize) ++ ++ if (retStatus == 0) ++ { ++ retStatus |= VC_BUFFER; ++ } ++ ++ if (m_bytesToBeConsumed > 0) ++ { ++ // Remember the current pts because the data which has just ++ // been sent to the VPU has not yet been consumed. ++ // This pts is related to the frame that will be consumed ++ // at next call... ++ m_previousPts = pts; ++ } ++ // Store current dts (will be used only if VC_PICTURE is set) ++ m_dts = dts; ++ ++#ifdef IMX_PROFILE ++ CLog::Log(LOGDEBUG, "%s - returns %x - duration %lld\n", __FUNCTION__, retStatus, XbmcThreads::SystemClockMillis() - previous); ++#endif ++ return retStatus; ++ ++out_error: ++ return VC_ERROR; ++} ++ ++void CDVDVideoCodecIMX::Reset() ++{ ++ int ret; ++ ++ CLog::Log(LOGDEBUG, "%s - called\n", __FUNCTION__); ++ ++ // Release last buffer ++ if(m_lastBuffer) ++ SAFE_RELEASE(m_lastBuffer); ++ ++ // Invalidate all buffers ++ for(int i=0; i < m_vpuFrameBufferNum; i++) ++ m_outputBuffers[i]->ReleaseFramebuffer(&m_vpuHandle); ++ ++ m_frameCounter = 0; ++ m_deinterlacer.Reset(); ++ m_bytesToBeConsumed = 0; ++ m_previousPts = DVD_NOPTS_VALUE; ++ ++ // Flush VPU ++ ret = VPU_DecFlushAll(m_vpuHandle); ++ if (ret != VPU_DEC_RET_SUCCESS) ++ { ++ CLog::Log(LOGERROR, "%s - VPU flush failed with error code %d.\n", __FUNCTION__, ret); ++ } ++ ++} ++ ++unsigned CDVDVideoCodecIMX::GetAllowedReferences() ++{ ++ return 3; ++} ++ ++bool CDVDVideoCodecIMX::ClearPicture(DVDVideoPicture* pDvdVideoPicture) ++{ ++ if (pDvdVideoPicture) ++ { ++ SAFE_RELEASE(pDvdVideoPicture->codecinfo); ++ } ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture) ++{ ++#ifdef IMX_PROFILE ++ static unsigned int previous = 0; ++ unsigned int current; ++ ++ current = XbmcThreads::SystemClockMillis(); ++ CLog::Log(LOGDEBUG, "%s tm:%03d\n", __FUNCTION__, current - previous); ++ previous = current; ++#endif ++ ++ m_frameCounter++; ++ ++ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; ++ if (m_dropState) ++ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; ++ else ++ pDvdVideoPicture->iFlags &= ~DVP_FLAG_DROPPED; ++ ++ pDvdVideoPicture->format = RENDER_FMT_IMXMAP; ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ pDvdVideoPicture->iWidth = m_frameInfo.pExtInfo->FrmCropRect.nRight - m_frameInfo.pExtInfo->FrmCropRect.nLeft; ++ pDvdVideoPicture->iHeight = m_frameInfo.pExtInfo->FrmCropRect.nBottom - m_frameInfo.pExtInfo->FrmCropRect.nTop; ++ ++ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; ++ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; ++ ++ int idx = VpuFindBuffer(m_frameInfo.pDisplayFrameBuf->pbufY); ++ if (idx != -1) ++ { ++ CDVDVideoCodecIMXBuffer *buffer = m_outputBuffers[idx]; ++ ++ pDvdVideoPicture->pts = buffer->GetPts(); ++ pDvdVideoPicture->dts = m_dts; ++ if (!m_usePTS) ++ { ++ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ } ++ ++ buffer->Queue(&m_frameInfo, m_lastBuffer); ++ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "+ %02d dts %f pts %f (VPU)\n", idx, pDvdVideoPicture->dts, pDvdVideoPicture->pts); ++#endif ++ ++ /* ++ // This does not work reliably since some streams do not report ++ // correctly if a frame is interlaced. ++ if (m_frameInfo.eFieldType != VPU_FIELD_NONE) ++ GET_DEINTERLACER(buffer) = (uint8_t*)&m_deinterlacer; ++ else ++ GET_DEINTERLACER(buffer) = NULL; ++ */ ++ ++ pDvdVideoPicture->codecinfo = buffer; ++ pDvdVideoPicture->codecinfo->Lock(); ++ ++ // Save last buffer ++ if (m_lastBuffer) ++ SAFE_RELEASE(m_lastBuffer); ++ ++ m_lastBuffer = buffer; ++ m_lastBuffer->Lock(); ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "%s - could not find frame buffer\n", __FUNCTION__); ++ } ++ ++ return true; ++} ++ ++void CDVDVideoCodecIMX::SetDropState(bool bDrop) ++{ ++ ++ // We are fast enough to continue to really decode every frames ++ // and avoid artefacts... ++ // (Of course these frames won't be rendered but only decoded !) ++ ++ if (m_dropState != bDrop) ++ { ++ m_dropState = bDrop; ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "%s : %d\n", __FUNCTION__, bDrop); ++#endif ++ } ++} ++ ++void CDVDVideoCodecIMX::Enter() ++{ ++ m_codecBufferLock.lock(); ++} ++ ++void CDVDVideoCodecIMX::Leave() ++{ ++ m_codecBufferLock.unlock(); ++} ++ ++/*******************************************/ ++ ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(int idx) ++ : m_refs(1) ++ , m_idx(idx) ++#else ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer() ++ : m_refs(1) ++#endif ++ , m_frameBuffer(NULL) ++ , m_rendered(false) ++ , m_pts(DVD_NOPTS_VALUE) ++ , m_previousBuffer(NULL) ++{ ++ GET_DEINTERLACER(this) = NULL; ++} ++ ++void CDVDVideoCodecIMXBuffer::Lock() ++{ ++#ifdef TRACE_FRAMES ++ long count = AtomicIncrement(&m_refs); ++ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (VPU)\n", m_idx, count); ++#else ++ AtomicIncrement(&m_refs); ++#endif ++} ++ ++long CDVDVideoCodecIMXBuffer::Release() ++{ ++ long count = AtomicDecrement(&m_refs); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (VPU)\n", m_idx, count); ++#endif ++ if (count == 2) ++ { ++ // Only referenced by the coded and its next frame, release the previous ++ SAFE_RELEASE(m_previousBuffer); ++ } ++ if (count == 1) ++ { ++ // If count drops to 1 then the only reference is being held by the codec ++ // that it can be released in the next Decode call. ++ if(m_frameBuffer != NULL) ++ { ++ m_rendered = true; ++ SAFE_RELEASE(m_previousBuffer); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "R %02d (VPU)\n", m_idx); ++#endif ++ } ++ } ++ else if (count == 0) ++ { ++ delete this; ++ } ++ ++ return count; ++} ++ ++bool CDVDVideoCodecIMXBuffer::IsValid() ++{ ++ return m_frameBuffer != NULL; ++} ++ ++bool CDVDVideoCodecIMXBuffer::Rendered() const ++{ ++ return m_rendered; ++} ++ ++void CDVDVideoCodecIMXBuffer::Queue(VpuDecOutFrameInfo *frameInfo, ++ CDVDVideoCodecIMXBuffer *previous) ++{ ++ // No lock necessary because at this time there is definitely no ++ // thread still holding a reference ++ m_frameBuffer = frameInfo->pDisplayFrameBuf; ++ m_rendered = false; ++ m_previousBuffer = previous; ++ if (m_previousBuffer) ++ m_previousBuffer->Lock(); ++ ++ iWidth = frameInfo->pExtInfo->nFrmWidth; ++ iHeight = frameInfo->pExtInfo->nFrmHeight; ++ GET_VIRT_ADDR(this) = m_frameBuffer->pbufVirtY; ++ GET_PHYS_ADDR(this) = m_frameBuffer->pbufY; ++ GET_FIELDTYPE(this) = (uint8_t*)frameInfo->eFieldType; ++} ++ ++VpuDecRetCode CDVDVideoCodecIMXBuffer::ReleaseFramebuffer(VpuDecHandle *handle) ++{ ++ // Again no lock required because this is only issued after the last ++ // external reference was released ++ VpuDecRetCode ret = VPU_DEC_RET_FAILURE; ++ ++ if((m_frameBuffer != NULL) && *handle) ++ { ++ ret = VPU_DecOutFrameDisplayed(*handle, m_frameBuffer); ++ if(ret != VPU_DEC_RET_SUCCESS) ++ CLog::Log(LOGERROR, "%s: vpu clear frame display failure: ret=%d \r\n",__FUNCTION__,ret); ++ } ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "- %02d (VPU)\n", m_idx); ++#endif ++ m_rendered = false; ++ m_frameBuffer = NULL; ++ m_pts = DVD_NOPTS_VALUE; ++ SAFE_RELEASE(m_previousBuffer); ++ ++ return ret; ++} ++ ++void CDVDVideoCodecIMXBuffer::SetPts(double pts) ++{ ++ m_pts = pts; ++} ++ ++double CDVDVideoCodecIMXBuffer::GetPts(void) const ++{ ++ return m_pts; ++} ++ ++CDVDVideoCodecIMXBuffer *CDVDVideoCodecIMXBuffer::GetPreviousBuffer() const ++{ ++ return m_previousBuffer; ++} ++ ++CDVDVideoCodecIMXBuffer::~CDVDVideoCodecIMXBuffer() ++{ ++ assert(m_refs == 0); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "~ %02d (VPU)\n", m_idx); ++#endif ++} ++ ++#ifdef TRACE_FRAMES ++CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer(int idx) ++ : m_refs(1) ++ , m_idx(idx) ++#else ++CDVDVideoCodecIPUBuffer::CDVDVideoCodecIPUBuffer() ++ : m_refs(1) ++#endif ++ , m_source(NULL) ++ , m_pPhyAddr(NULL) ++ , m_pVirtAddr(NULL) ++ , m_nSize(0) ++{ ++} ++ ++CDVDVideoCodecIPUBuffer::~CDVDVideoCodecIPUBuffer() ++{ ++ assert(m_refs == 0); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "~ %02d (IPU)\n", m_idx); ++#endif ++} ++ ++void CDVDVideoCodecIPUBuffer::Lock() ++{ ++#ifdef TRACE_FRAMES ++ long count = AtomicIncrement(&m_refs); ++ CLog::Log(LOGDEBUG, "R+ %02d - ref : %d (IPU)\n", m_idx, count); ++#else ++ AtomicIncrement(&m_refs); ++#endif ++ ++} ++ ++long CDVDVideoCodecIPUBuffer::Release() ++{ ++ long count = AtomicDecrement(&m_refs); ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "R- %02d - ref : %d (IPU)\n", m_idx, count); ++#endif ++ if (count == 1) ++ { ++ ReleaseFrameBuffer(); ++ } ++ else if (count == 0) ++ { ++ delete this; ++ } ++ ++ return count; ++} ++ ++bool CDVDVideoCodecIPUBuffer::IsValid() ++{ ++ return m_source && m_source->IsValid() && m_pPhyAddr; ++} ++ ++bool CDVDVideoCodecIPUBuffer::Process(int fd, CDVDVideoCodecIMXBuffer *buffer, ++ VpuFieldType fieldType, int fieldFmt, ++ bool lowMotion) ++{ ++ CDVDVideoCodecIMXBuffer *previousBuffer; ++ struct ipu_task task; ++ memset(&task, 0, sizeof(task)); ++ task.priority = IPU_TASK_PRIORITY_HIGH; ++ ++ if (lowMotion) ++ previousBuffer = buffer->GetPreviousBuffer(); ++ else ++ previousBuffer = NULL; ++ ++ SAFE_RELEASE(m_source); ++ ++ iWidth = buffer->iWidth; ++ iHeight = buffer->iHeight; ++ ++ // Input is the VPU decoded frame ++ task.input.width = iWidth; ++ task.input.height = iHeight; ++ task.input.format = IPU_PIX_FMT_NV12; ++ ++ // Output is our IPU buffer ++ task.output.width = iWidth; ++ task.output.height = iHeight; ++ task.output.format = IPU_PIX_FMT_NV12; ++ task.output.paddr = (int)GET_PHYS_ADDR(this); ++ ++ // Fill current and next buffer address ++ if (lowMotion && previousBuffer && previousBuffer->IsValid()) ++ { ++ task.input.paddr = (int)GET_PHYS_ADDR(previousBuffer); ++ task.input.paddr_n = (int)GET_PHYS_ADDR(buffer); ++ task.input.deinterlace.motion = LOW_MOTION; ++ } ++ else ++ { ++ task.input.paddr = (int)GET_PHYS_ADDR(buffer); ++ task.input.deinterlace.motion = HIGH_MOTION; ++ } ++ ++ task.input.deinterlace.enable = 1; ++ task.input.deinterlace.field_fmt = fieldFmt; ++ ++ switch (fieldType) ++ { ++ case VPU_FIELD_TOP: ++ case VPU_FIELD_TB: ++ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_TOP; ++ break; ++ case VPU_FIELD_BOTTOM: ++ case VPU_FIELD_BT: ++ task.input.deinterlace.field_fmt |= IPU_DEINTERLACE_FIELD_BOTTOM; ++ break; ++ default: ++ break; ++ } ++ ++#ifdef IMX_PROFILE ++ unsigned int time = XbmcThreads::SystemClockMillis(); ++#endif ++ int ret = ioctl(fd, IPU_QUEUE_TASK, &task); ++#ifdef IMX_PROFILE ++ CLog::Log(LOGDEBUG, "DEINT: tm:%d\n", XbmcThreads::SystemClockMillis() - time); ++#endif ++ if (ret < 0) ++ { ++ CLog::Log(LOGERROR, "IPU task failed: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ buffer->Lock(); ++ ++ // Remember the source buffer. This is actually not necessary since the output ++ // buffer is the one that is used by the renderer. But keep it bound for now ++ // since this state is used in IsValid which then needs to become a flag in ++ // this class. ++ m_source = buffer; ++ m_source->Lock(); ++ ++ buffer->Release(); ++ ++ return true; ++} ++ ++void CDVDVideoCodecIPUBuffer::ReleaseFrameBuffer() ++{ ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "- %02d (IPU)\n", m_idx); ++#endif ++ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); ++ SAFE_RELEASE(m_source); ++} ++ ++bool CDVDVideoCodecIPUBuffer::Allocate(int fd, int width, int height, int nAlign) ++{ ++ m_iWidth = Align(width,FRAME_ALIGN); ++ m_iHeight = Align(height,(2*FRAME_ALIGN)); ++ // NV12 == 12 bpp ++ m_nSize = m_iWidth*m_iHeight*12/8; ++ m_pPhyAddr = m_nSize; ++ ++ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; ++ ++ int r = ioctl(fd, IPU_ALLOC, &m_pPhyAddr); ++ if (r < 0) ++ { ++ m_pPhyAddr = 0; ++ CLog::Log(LOGERROR, "ioctl IPU_ALLOC fail: disable deinterlacing: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ CLog::Log(LOGNOTICE, "IPU: alloc %d bytes for frame of %dx%d at 0x%x\n", ++ m_nSize, m_iWidth, m_iHeight, m_pPhyAddr); ++ ++ m_pVirtAddr = (uint8_t*)mmap(0, m_nSize, PROT_READ | PROT_WRITE, MAP_SHARED, ++ fd, m_pPhyAddr); ++ if (!m_pVirtAddr) ++ { ++ CLog::Log(LOGERROR, "IPU mmap failed: disable deinterlacing: %s\n", strerror(errno)); ++ return false; ++ } ++ ++ if (nAlign>1) ++ { ++ GET_PHYS_ADDR(this) = (uint8_t*)Align(m_pPhyAddr, nAlign); ++ GET_VIRT_ADDR(this) = (uint8_t*)Align(m_pVirtAddr, nAlign); ++ } ++ else ++ { ++ GET_PHYS_ADDR(this) = (uint8_t*)m_pPhyAddr; ++ GET_VIRT_ADDR(this) = (uint8_t*)m_pVirtAddr; ++ } ++ ++ GET_DEINTERLACER(this) = NULL; ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIPUBuffer::Free(int fd) ++{ ++ CSingleLock lock(CDVDVideoCodecIMX::m_codecBufferLock); ++ bool ret = true; ++ ++ // Unmap virtual memory ++ if (m_pVirtAddr != NULL) ++ { ++ if(munmap(m_pVirtAddr, m_nSize)) ++ { ++ CLog::Log(LOGERROR, "IPU unmap failed: %s\n", strerror(errno)); ++ ret = false; ++ } ++ ++ m_pVirtAddr = NULL; ++ } ++ ++ // Free IPU memory ++ if (m_pPhyAddr) ++ { ++ if (ioctl(fd, IPU_FREE, &m_pPhyAddr)) ++ { ++ CLog::Log(LOGERROR, "IPU free buffer 0x%x failed: %s\n", ++ m_pPhyAddr, strerror(errno)); ++ ret = false; ++ } ++ ++ m_pPhyAddr = 0; ++ } ++ ++ GET_PHYS_ADDR(this) = GET_VIRT_ADDR(this) = NULL; ++ SAFE_RELEASE(m_source); ++ ++ return ret; ++} ++ ++CDVDVideoCodecIPUBuffers::CDVDVideoCodecIPUBuffers() ++ : m_ipuHandle(0) ++ , m_bufferNum(0) ++ , m_buffers(NULL) ++ , m_currentFieldFmt(0) ++{ ++} ++ ++CDVDVideoCodecIPUBuffers::~CDVDVideoCodecIPUBuffers() ++{ ++ Close(); ++} ++ ++bool CDVDVideoCodecIPUBuffers::Init(int width, int height, int numBuffers, int nAlign) ++{ ++ if (numBuffers<=0) ++ { ++ CLog::Log(LOGERROR, "IPU Init: invalid number of buffers: %d\n", numBuffers); ++ return false; ++ } ++ ++ m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); ++ if (m_ipuHandle<=0) ++ { ++ CLog::Log(LOGWARNING, "Failed to initialize IPU: deinterlacing disabled: %s\n", ++ strerror(errno)); ++ m_ipuHandle = 0; ++ return false; ++ } ++ ++ m_bufferNum = numBuffers; ++ m_buffers = new CDVDVideoCodecIPUBuffer*[m_bufferNum]; ++ m_currentFieldFmt = 0; ++ ++ for (int i=0; i < m_bufferNum; i++) ++ { ++#ifdef TRACE_FRAMES ++ m_buffers[i] = new CDVDVideoCodecIPUBuffer(i); ++#else ++ m_buffers[i] = new CDVDVideoCodecIPUBuffer; ++#endif ++ if (!m_buffers[i]->Allocate(m_ipuHandle, width, height, nAlign)) ++ { ++ Close(); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++bool CDVDVideoCodecIPUBuffers::Reset() ++{ ++ for (int i=0; i < m_bufferNum; i++) ++ m_buffers[i]->ReleaseFrameBuffer(); ++ m_currentFieldFmt = 0; ++} ++ ++bool CDVDVideoCodecIPUBuffers::Close() ++{ ++ bool ret = true; ++ ++ if (m_ipuHandle) ++ { ++ for (int i=0; i < m_bufferNum; i++) ++ { ++ if (m_buffers[i] == NULL ) continue; ++ if (!m_buffers[i]->Free(m_ipuHandle)) ++ ret = false; ++ } ++ ++ // Close IPU device ++ if (close(m_ipuHandle)) ++ { ++ CLog::Log(LOGERROR, "IPU failed to close interface: %s\n", strerror(errno)); ++ ret = false; ++ } ++ ++ m_ipuHandle = 0; ++ } ++ ++ if (m_buffers) ++ { ++ for (int i=0; i < m_bufferNum; i++) ++ SAFE_RELEASE(m_buffers[i]); ++ ++ delete m_buffers; ++ m_buffers = NULL; ++ } ++ ++ m_bufferNum = 0; ++ return true; ++} ++ ++CDVDVideoCodecIPUBuffer * ++CDVDVideoCodecIPUBuffers::Process(CDVDVideoCodecBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion) ++{ ++ CDVDVideoCodecIPUBuffer *target = NULL; ++ bool ret = true; ++ ++ // TODO: Needs further checks on real streams ++ if (!m_bufferNum /*|| (fieldType == VPU_FIELD_NONE)*/) ++ return NULL; ++ ++ for (int i=0; i < m_bufferNum; i++ ) ++ { ++ if (!m_buffers[i]->Rendered()) continue; ++ ++ // IPU process: ++ // SRC: Current VPU physical buffer address + last VPU buffer address ++ // DST: IPU buffer[i] ++ ret = m_buffers[i]->Process(m_ipuHandle, (CDVDVideoCodecIMXBuffer*)sourceBuffer, ++ fieldType, m_currentFieldFmt/* | IPU_DEINTERLACE_RATE_EN*/, ++ lowMotion); ++ if (ret) ++ { ++#ifdef TRACE_FRAMES ++ CLog::Log(LOGDEBUG, "+ %02d (IPU)\n", i); ++#endif ++ target = m_buffers[i]; ++ } ++ break; ++ } ++ ++ // Buffers are there but there is no free one, this is an error! ++ // Rendering will continue with unprocessed frames ... ++ if (ret && target==NULL) ++ { ++ CLog::Log(LOGERROR, "Deinterlacing: did not find free buffer, forward unprocessed frame\n"); ++ } ++ ++ // Toggle frame index bit ++ //m_currentFieldFmt ^= IPU_DEINTERLACE_RATE_FRAME1; ++ ++ return target; ++} +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2014-04-24 11:50:14.007208425 +0200 +@@ -0,0 +1,215 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 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, see ++ * . ++ * ++ */ ++#include ++#include ++#include "DVDVideoCodec.h" ++#include "DVDStreamInfo.h" ++#include "DVDVideoCodecInfo.h" ++#include "threads/CriticalSection.h" ++#include "utils/BitstreamConverter.h" ++ ++ ++//#define IMX_PROFILE ++//#define TRACE_FRAMES ++ ++class CDecMemInfo ++{ ++public: ++ CDecMemInfo() ++ : nVirtNum(0) ++ , virtMem(NULL) ++ , nPhyNum(0) ++ , phyMem(NULL) ++ {} ++ ++ //virtual mem info ++ int nVirtNum; ++ void** virtMem; ++ ++ //phy mem info ++ int nPhyNum; ++ VpuMemDesc* phyMem; ++}; ++ ++class CDVDVideoCodecIPUBuffer; ++ ++class CDVDVideoCodecIMXBuffer : public CDVDVideoCodecBuffer ++{ ++public: ++#ifdef TRACE_FRAMES ++ CDVDVideoCodecIMXBuffer(int idx); ++#else ++ CDVDVideoCodecIMXBuffer(); ++#endif ++ ++ // reference counting ++ virtual void Lock(); ++ virtual long Release(); ++ virtual bool IsValid(); ++ ++ bool Rendered() const; ++ void Queue(VpuDecOutFrameInfo *frameInfo, ++ CDVDVideoCodecIMXBuffer *previous); ++ VpuDecRetCode ReleaseFramebuffer(VpuDecHandle *handle); ++ void SetPts(double pts); ++ double GetPts(void) const; ++ CDVDVideoCodecIMXBuffer *GetPreviousBuffer() const; ++ ++private: ++ // private because we are reference counted ++ virtual ~CDVDVideoCodecIMXBuffer(); ++ ++private: ++#ifdef TRACE_FRAMES ++ int m_idx; ++#endif ++ long m_refs; ++ VpuFrameBuffer *m_frameBuffer; ++ bool m_rendered; ++ double m_pts; ++ CDVDVideoCodecIMXBuffer *m_previousBuffer; // Holds a the reference counted ++ // previous buffer ++}; ++ ++// Shared buffer that holds an IPU allocated memory block and serves as target ++// for IPU operations such as deinterlacing, rotation or color conversion. ++class CDVDVideoCodecIPUBuffer : public CDVDVideoCodecBuffer ++{ ++public: ++#ifdef TRACE_FRAMES ++ CDVDVideoCodecIPUBuffer(int idx); ++#else ++ CDVDVideoCodecIPUBuffer(); ++#endif ++ ++ // reference counting ++ virtual void Lock(); ++ virtual long Release(); ++ virtual bool IsValid(); ++ ++ // Returns whether the buffer is ready to be used ++ bool Rendered() const { return m_source == NULL; } ++ bool Process(int fd, CDVDVideoCodecIMXBuffer *buffer, ++ VpuFieldType fieldType, int fieldFmt, ++ bool lowMotion); ++ void ReleaseFrameBuffer(); ++ ++ bool Allocate(int fd, int width, int height, int nAlign); ++ bool Free(int fd); ++ ++private: ++ virtual ~CDVDVideoCodecIPUBuffer(); ++ ++private: ++#ifdef TRACE_FRAMES ++ int m_idx; ++#endif ++ long m_refs; ++ CDVDVideoCodecBuffer *m_source; ++ int m_pPhyAddr; ++ uint8_t *m_pVirtAddr; ++ int m_iWidth; ++ int m_iHeight; ++ int m_nSize; ++}; ++ ++// Collection class that manages a pool of IPU buffers that are used for ++// deinterlacing. In future they can also serve rotation or color conversion ++// buffers. ++class CDVDVideoCodecIPUBuffers ++{ ++ public: ++ CDVDVideoCodecIPUBuffers(); ++ ~CDVDVideoCodecIPUBuffers(); ++ ++ bool Init(int width, int height, int numBuffers, int nAlign); ++ bool Reset(); ++ bool Close(); ++ ++ CDVDVideoCodecIPUBuffer *Process(CDVDVideoCodecBuffer *sourceBuffer, ++ VpuFieldType fieldType, bool lowMotion); ++ ++ private: ++ int m_ipuHandle; ++ int m_bufferNum; ++ CDVDVideoCodecIPUBuffer **m_buffers; ++ int m_currentFieldFmt; ++}; ++ ++ ++class CDVDVideoCodecIMX : public CDVDVideoCodec ++{ ++ friend class CDVDVideoCodecIMXBuffer; ++ friend class CDVDVideoCodecIPUBuffer; ++ ++public: ++ CDVDVideoCodecIMX(); ++ virtual ~CDVDVideoCodecIMX(); ++ ++ // Methods from CDVDVideoCodec which require overrides ++ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); ++ virtual void Dispose(void); ++ virtual int Decode(BYTE *pData, int iSize, double dts, double pts); ++ virtual void Reset(void); ++ virtual bool ClearPicture(DVDVideoPicture *pDvdVideoPicture); ++ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); ++ virtual void SetDropState(bool bDrop); ++ virtual const char* GetName(void) { return (const char*)m_pFormatName; } ++ virtual unsigned GetAllowedReferences(); ++ ++ static void Enter(); ++ static void Leave(); ++ ++protected: ++ ++ bool VpuOpen(); ++ bool VpuAllocBuffers(VpuMemInfo *); ++ bool VpuFreeBuffers(); ++ bool VpuAllocFrameBuffers(); ++ int VpuFindBuffer(void *frameAddr); ++ ++ static const int m_extraVpuBuffers; // Number of additional buffers for VPU ++ static const int m_maxVpuDecodeLoops; // Maximum iterations in VPU decoding loop ++ static CCriticalSection m_codecBufferLock; ++ ++ CDVDStreamInfo m_hints; // Hints from demuxer at stream opening ++ const char *m_pFormatName; // Current decoder format name ++ VpuDecOpenParam m_decOpenParam; // Parameters required to call VPU_DecOpen ++ CDecMemInfo m_decMemInfo; // VPU dedicated memory description ++ VpuDecHandle m_vpuHandle; // Handle for VPU library calls ++ VpuDecInitInfo m_initInfo; // Initial info returned from VPU at decoding start ++ bool m_dropState; // Current drop state ++ int m_vpuFrameBufferNum; // Total number of allocated frame buffers ++ VpuFrameBuffer *m_vpuFrameBuffers; // Table of VPU frame buffers description ++ CDVDVideoCodecIPUBuffers m_deinterlacer; ++ CDVDVideoCodecIMXBuffer **m_outputBuffers; ++ CDVDVideoCodecIMXBuffer *m_lastBuffer; ++ VpuMemDesc *m_extraMem; // Table of allocated extra Memory ++ int m_frameCounter; // Decoded frames counter ++ bool m_usePTS; // State whether pts out of decoding process should be used ++ VpuDecOutFrameInfo m_frameInfo; ++ CBitstreamConverter *m_converter; ++ bool m_convert_bitstream; ++ int m_bytesToBeConsumed; // Remaining bytes in VPU ++ double m_previousPts; // Enable to keep pts when needed ++ bool m_frameReported; // State whether the frame consumed event will be reported by libfslvpu ++ double m_dts; // Current dts ++}; +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h 2014-04-24 11:50:14.007208425 +0200 +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://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, see ++ * . ++ * ++ */ ++ ++#ifndef DVDVIDEOCODECINFO_H ++#define DVDVIDEOCODECINFO_H ++ ++class CDVDVideoCodecBuffer ++{ ++public: ++ // reference counting ++ virtual void Lock() = 0; ++ virtual long Release() = 0; ++ virtual bool IsValid() = 0; ++ ++ uint32_t iWidth; ++ uint32_t iHeight; ++ uint8_t* data[4]; // [4] = alpha channel, currently not used ++ int iLineSize[4]; // [4] = alpha channel, currently not used ++}; ++ ++#endif // DVDVIDEOCODECINFO_H +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-04-24 11:49:41.192078185 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2014-04-24 11:50:14.007208425 +0200 +@@ -24,6 +24,9 @@ + SRCS += OpenMaxVideo.cpp + SRCS += DVDVideoCodecOpenMax.cpp + endif ++ifeq (@USE_IMXVPU@,1) ++SRCS += DVDVideoCodecIMX.cpp ++endif + ifeq (@USE_LIBAMCODEC@,1) + SRCS += AMLCodec.cpp + SRCS += DVDVideoCodecAmlogic.cpp +diff -Naur xbmc-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +--- xbmc-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-04-24 11:49:41.128079881 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp 2014-04-24 11:50:14.003208531 +0200 +@@ -995,6 +995,8 @@ + case RENDER_FMT_EGLIMG: return "EGLIMG"; + case RENDER_FMT_BYPASS: return "BYPASS"; + case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; ++ case RENDER_FMT_YV12_BUFFER: return "YV12BUF"; ++ case RENDER_FMT_IMXMAP: return "IMXMAP"; + case RENDER_FMT_NONE: return "NONE"; + } + return "UNKNOWN"; +diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +--- xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-04-24 11:49:41.300075322 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp 2014-04-24 11:50:14.011208319 +0200 +@@ -75,6 +75,17 @@ + static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + #endif + ++#ifdef HAS_IMXVPU ++#include "windowing/egl/EGLWrapper.h" ++#include "DVDCodecs/Video/DVDVideoCodecIMX.h" ++ ++#define GL_VIV_NV12 0x8FC1 ++typedef void (GL_APIENTRYP PFNGLTEXDIRECTVIVMAPPROC) (GLenum Target, GLsizei Width, GLsizei Height, GLenum Format, GLvoid ** Logical, const GLuint * Physical); ++typedef void (GL_APIENTRYP PFNGLTEXDIRECTINVALIDATEVIVPROC) (GLenum Target); ++static PFNGLTEXDIRECTVIVMAPPROC glTexDirectVIVMap; ++static PFNGLTEXDIRECTINVALIDATEVIVPROC glTexDirectInvalidateVIV; ++#endif ++ + #if defined(TARGET_ANDROID) + #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h" + #endif +@@ -99,6 +110,7 @@ + #if defined(TARGET_ANDROID) + mediacodec = NULL; + #endif ++ codecinfo = NULL; + } + + CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER() +@@ -150,6 +162,12 @@ + if (!glEGLImageTargetTexture2DOES) + glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES"); + #endif ++#ifdef HAS_IMXVPU ++ if (!glTexDirectVIVMap) ++ glTexDirectVIVMap = (PFNGLTEXDIRECTVIVMAPPROC) CEGLWrapper::GetProcAddress("glTexDirectVIVMap"); ++ if (!glTexDirectInvalidateVIV) ++ glTexDirectInvalidateVIV = (PFNGLTEXDIRECTINVALIDATEVIVPROC) CEGLWrapper::GetProcAddress("glTexDirectInvalidateVIV"); ++#endif + } + + CLinuxRendererGLES::~CLinuxRendererGLES() +@@ -278,6 +296,10 @@ + { + return source; + } ++ if ( m_renderMethod & RENDER_IMXMAP ) ++ { ++ return source; ++ } + + #ifdef HAVE_VIDEOTOOLBOXDECODER + if (m_renderMethod & RENDER_CVREF ) +@@ -603,6 +625,10 @@ + #if defined(TARGET_ANDROID) + m_formats.push_back(RENDER_FMT_MEDIACODEC); + #endif ++ m_formats.push_back(RENDER_FMT_YV12_BUFFER); ++#ifdef HAS_IMXVPU ++ m_formats.push_back(RENDER_FMT_IMXMAP); ++#endif + + // setup the background colour + m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff; +@@ -713,6 +739,16 @@ + m_renderMethod = RENDER_MEDIACODEC; + break; + } ++ else if (m_format == RENDER_FMT_YV12_BUFFER) ++ { ++ CLog::Log(LOGNOTICE, "GL: Using YV12 Buffer render method"); ++ } ++ else if (m_format == RENDER_FMT_IMXMAP) ++ { ++ CLog::Log(LOGNOTICE, "GL: Using IMXMAP render method"); ++ m_renderMethod = RENDER_IMXMAP; ++ break; ++ } + else if (m_format == RENDER_FMT_BYPASS) + { + CLog::Log(LOGNOTICE, "GL: Using BYPASS render method"); +@@ -805,6 +841,18 @@ + m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture; + m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture; + } ++ else if (m_format == RENDER_FMT_YV12_BUFFER) ++ { ++ m_textureUpload = &CLinuxRendererGLES::UploadYV12BufferTexture; ++ m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture; ++ m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture; ++ } ++ else if (m_format == RENDER_FMT_IMXMAP) ++ { ++ m_textureUpload = &CLinuxRendererGLES::UploadIMXMAPTexture; ++ m_textureCreate = &CLinuxRendererGLES::CreateIMXMAPTexture; ++ m_textureDelete = &CLinuxRendererGLES::DeleteIMXMAPTexture; ++ } + else + { + // default to YV12 texture handlers +@@ -956,6 +1004,10 @@ + { + RenderSurfaceTexture(index, m_currentField); + } ++ else if (m_renderMethod & RENDER_IMXMAP) ++ { ++ RenderIMXMAPTexture(index, m_currentField); ++ } + else + { + RenderSoftware(index, m_currentField); +@@ -1160,7 +1212,7 @@ + // imgwidth *= planes[0].pixpertex_x; + // imgheight *= planes[0].pixpertex_y; + // } +-// ++// + // glBegin(GL_QUADS); + // + // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1); +@@ -1582,6 +1634,85 @@ + #endif + } + ++void CLinuxRendererGLES::RenderIMXMAPTexture(int index, int field) ++{ ++#if defined(HAS_IMXVPU) ++#ifdef DEBUG_VERBOSE ++ unsigned int time = XbmcThreads::SystemClockMillis(); ++#endif ++ ++ YUVPLANE &plane = m_buffers[index].fields[field][0]; ++ CDVDVideoCodecBuffer* codecinfo = m_buffers[index].codecinfo; ++ ++ if(codecinfo == NULL) return; ++ ++ CDVDVideoCodecIMX::Enter(); ++ ++ if(!codecinfo->IsValid()) ++ { ++ CDVDVideoCodecIMX::Leave(); ++ return; ++ } ++ ++ glDisable(GL_DEPTH_TEST); ++ ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(m_textureTarget, plane.id); ++ ++ g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); ++ ++ GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip ++ GLfloat ver[4][4]; ++ GLfloat tex[4][2]; ++ GLfloat col[3] = {1.0f, 1.0f, 1.0f}; ++ ++ GLint posLoc = g_Windowing.GUIShaderGetPos(); ++ GLint texLoc = g_Windowing.GUIShaderGetCoord0(); ++ GLint colLoc = g_Windowing.GUIShaderGetCol(); ++ ++ glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver); ++ glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex); ++ glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col); ++ ++ glEnableVertexAttribArray(posLoc); ++ glEnableVertexAttribArray(texLoc); ++ glEnableVertexAttribArray(colLoc); ++ ++ // Set vertex coordinates ++ for(int i = 0; i < 4; i++) ++ { ++ ver[i][0] = m_rotatedDestCoords[i].x; ++ ver[i][1] = m_rotatedDestCoords[i].y; ++ ver[i][2] = 0.0f;// set z to 0 ++ ver[i][3] = 1.0f; ++ } ++ ++ // Set texture coordinates ++ tex[0][0] = tex[3][0] = plane.rect.x1; ++ tex[0][1] = tex[1][1] = plane.rect.y1; ++ tex[1][0] = tex[2][0] = plane.rect.x2; ++ tex[2][1] = tex[3][1] = plane.rect.y2; ++ ++ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); ++ ++ glDisableVertexAttribArray(posLoc); ++ glDisableVertexAttribArray(texLoc); ++ glDisableVertexAttribArray(colLoc); ++ ++ g_Windowing.DisableGUIShader(); ++ VerifyGLState(); ++ ++ glBindTexture(m_textureTarget, 0); ++ VerifyGLState(); ++ ++ CDVDVideoCodecIMX::Leave(); ++ ++#ifdef DEBUG_VERBOSE ++ CLog::Log(LOGDEBUG, "RenderIMXMAPTexture %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time); ++#endif ++#endif ++} ++ + bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) + { + if (!m_bValidated) +@@ -2303,7 +2434,7 @@ + + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +- // This is necessary for non-power-of-two textures ++ // This is necessary for non-power-of-two textures + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +@@ -2409,7 +2540,7 @@ + + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +- // This is necessary for non-power-of-two textures ++ // This is necessary for non-power-of-two textures + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + +@@ -2483,6 +2614,84 @@ + return true; + } + ++//******************************************************************************************************** ++// Buffer creation, deletion, copying + clearing ++//******************************************************************************************************** ++void CLinuxRendererGLES::UploadYV12BufferTexture(int index) ++{ ++ YUVBUFFER& buf = m_buffers[index]; ++ YV12Image* im = &buf.image; ++ YUVFIELDS& fields = buf.fields; ++ ++ if (!buf.codecinfo || !(im->flags & IMAGE_FLAG_READY)) ++ 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 ++ , buf.codecinfo->iLineSize[0]*2, im->bpp, buf.codecinfo->data[0] ); ++ ++ // Load Odd Y fields ++ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex ++ , im->width, im->height >> 1 ++ , buf.codecinfo->iLineSize[0]*2, im->bpp, buf.codecinfo->data[0] + buf.codecinfo->iLineSize[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) ++ , buf.codecinfo->iLineSize[1]*2, im->bpp, buf.codecinfo->data[1] ); ++ ++ LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , buf.codecinfo->iLineSize[2]*2, im->bpp, buf.codecinfo->data[2] ); ++ ++ // 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) ++ , buf.codecinfo->iLineSize[1]*2, im->bpp, buf.codecinfo->data[1] + buf.codecinfo->iLineSize[1] ); ++ ++ LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) ++ , buf.codecinfo->iLineSize[2]*2, im->bpp, buf.codecinfo->data[2] + buf.codecinfo->iLineSize[2] ); ++ } ++ else ++ { ++ // Load Y plane ++ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex ++ , im->width, im->height ++ , buf.codecinfo->iLineSize[0], im->bpp, buf.codecinfo->data[0] ); ++ ++ //load U plane ++ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> im->cshift_y ++ , buf.codecinfo->iLineSize[1], im->bpp, buf.codecinfo->data[1] ); ++ ++ //load V plane ++ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex ++ , im->width >> im->cshift_x, im->height >> im->cshift_y ++ , buf.codecinfo->iLineSize[2], im->bpp, buf.codecinfo->data[2] ); ++ } ++ ++ VerifyGLState(); ++ ++ CalculateTextureSourceRects(index, 3); ++ ++ glDisable(m_textureTarget); ++} ++ + void CLinuxRendererGLES::SetTextureFilter(GLenum method) + { + for (int i = 0 ; iIsValid()) ++ { ++ CDVDVideoCodecIMX::Leave(); ++ return; ++ } ++ ++ YUVPLANE &plane = m_buffers[index].fields[0][0]; ++ CDVDVideoCodecIPUBuffers *deinterlacer = (CDVDVideoCodecIPUBuffers*)codecinfo->data[2]; ++ ++ if (deinterlacer) ++ { ++ EDEINTERLACEMODE deinterlacemode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ ++ if (deinterlacemode != VS_DEINTERLACEMODE_OFF) ++ { ++ CDVDVideoCodecBuffer *deint; ++ EINTERLACEMETHOD interlacemethod = CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod; ++ deint = deinterlacer->Process(codecinfo, (VpuFieldType)(int)codecinfo->data[3], ++ interlacemethod == VS_INTERLACEMETHOD_DEINTERLACE); ++ if (deint) ++ { ++ SAFE_RELEASE(buf.codecinfo); ++ buf.codecinfo = deint; ++ buf.codecinfo->Lock(); ++ codecinfo = buf.codecinfo; ++ } ++ } ++ } ++ ++ glActiveTexture(GL_TEXTURE0); ++ glBindTexture(m_textureTarget, plane.id); ++ ++ GLuint physical = ~0U; ++ GLvoid *virt = (GLvoid*)codecinfo->data[0]; ++ glTexDirectVIVMap(m_textureTarget, codecinfo->iWidth, codecinfo->iHeight, GL_VIV_NV12, ++ (GLvoid **)&virt, &physical); ++ glTexDirectInvalidateVIV(m_textureTarget); ++ ++ glBindTexture(m_textureTarget, 0); ++ ++ plane.flipindex = m_buffers[index].flipindex; ++ plane.texwidth = codecinfo->iWidth; ++ plane.texheight = codecinfo->iHeight; ++ ++ CalculateTextureSourceRects(index, 1); ++ ++ CDVDVideoCodecIMX::Leave(); ++ } ++ ++#endif ++} ++void CLinuxRendererGLES::DeleteIMXMAPTexture(int index) ++{ ++ YUVBUFFER &buf = m_buffers[index]; ++ YUVPLANE &plane = buf.fields[0][0]; ++ ++ if(plane.id && glIsTexture(plane.id)) ++ glDeleteTextures(1, &plane.id); ++ plane.id = 0; ++ ++ SAFE_RELEASE(buf.codecinfo); ++} ++bool CLinuxRendererGLES::CreateIMXMAPTexture(int index) ++{ ++ YV12Image &im = m_buffers[index].image; ++ YUVFIELDS &fields = m_buffers[index].fields; ++ YUVPLANE &plane = fields[0][0]; ++ ++ DeleteEGLIMGTexture(index); ++ ++ memset(&im , 0, sizeof(im)); ++ memset(&fields, 0, sizeof(fields)); ++ ++ im.height = m_sourceHeight; ++ im.width = m_sourceWidth; ++ ++ plane.texwidth = 0; // Must be actual frame width for pseudo-cropping ++ plane.texheight = 0; // Must be actual frame height for pseudo-cropping ++ plane.pixpertex_x = 1; ++ plane.pixpertex_y = 1; ++ ++ glEnable(m_textureTarget); ++ glGenTextures(1, &plane.id); ++ VerifyGLState(); ++ ++ glBindTexture(m_textureTarget, plane.id); ++ ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ ++ glDisable(m_textureTarget); ++ return true; ++} ++ ++ + bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature) + { + // Player controls render, let it dictate available render features +@@ -2578,9 +2895,14 @@ + if(m_renderMethod & RENDER_CVREF) + return false; + ++#ifdef HAS_IMXVPU ++ if(mode == VS_DEINTERLACEMODE_AUTO) ++ return true; ++#else + if(mode == VS_DEINTERLACEMODE_AUTO + || mode == VS_DEINTERLACEMODE_FORCE) + return true; ++#endif + + return false; + } +@@ -2609,6 +2931,15 @@ + if(method == VS_INTERLACEMETHOD_AUTO) + return true; + ++ if(m_renderMethod & RENDER_IMXMAP) ++ { ++ if(method == VS_INTERLACEMETHOD_DEINTERLACE ++ || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) ++ return true; ++ else ++ return false; ++ } ++ + #if defined(__i386__) || defined(__x86_64__) + if(method == VS_INTERLACEMETHOD_DEINTERLACE + || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF +@@ -2657,6 +2988,9 @@ + if(m_renderMethod & RENDER_CVREF) + return VS_INTERLACEMETHOD_NONE; + ++ if(m_renderMethod & RENDER_IMXMAP) ++ return VS_INTERLACEMETHOD_DEINTERLACE_HALF; ++ + #if defined(__i386__) || defined(__x86_64__) + return VS_INTERLACEMETHOD_DEINTERLACE_HALF; + #else +@@ -2741,5 +3075,16 @@ + } + #endif + ++void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index) ++{ ++ YUVBUFFER &buf = m_buffers[index]; ++ ++ SAFE_RELEASE(buf.codecinfo); ++ buf.codecinfo = codecinfo; ++ ++ if (codecinfo) ++ codecinfo->Lock(); ++} ++ + #endif + +diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +--- xbmc-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-04-24 11:49:41.304075216 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/LinuxRendererGLES.h 2014-04-24 11:50:14.011208319 +0200 +@@ -33,6 +33,7 @@ + #include "guilib/GraphicContext.h" + #include "BaseRenderer.h" + #include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" ++#include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecInfo.h" + + class CRenderCapture; + +@@ -89,7 +90,8 @@ + RENDER_CVREF = 0x080, + RENDER_BYPASS = 0x100, + RENDER_EGLIMG = 0x200, +- RENDER_MEDIACODEC = 0x400 ++ RENDER_MEDIACODEC = 0x400, ++ RENDER_IMXMAP = 0x800 + }; + + enum RenderQuality +@@ -173,6 +175,7 @@ + // mediaCodec + virtual void AddProcessor(CDVDMediaCodecInfo *mediacodec, int index); + #endif ++ virtual void AddProcessor(CDVDVideoCodecBuffer *codecinfo, int index); + + protected: + virtual void Render(DWORD flags, int index); +@@ -212,6 +215,12 @@ + void DeleteSurfaceTexture(int index); + bool CreateSurfaceTexture(int index); + ++ void UploadYV12BufferTexture(int index); ++ ++ void UploadIMXMAPTexture(int index); ++ void DeleteIMXMAPTexture(int index); ++ bool CreateIMXMAPTexture(int index); ++ + void CalculateTextureSourceRects(int source, int num_planes); + + // renderers +@@ -222,6 +231,7 @@ + void RenderEglImage(int index, int field); // Android OES texture + void RenderCoreVideoRef(int index, int field); // CoreVideo reference + void RenderSurfaceTexture(int index, int field);// MediaCodec rendering using SurfaceTexture ++ void RenderIMXMAPTexture(int index, int field); // IMXMAP rendering + + CFrameBufferObject m_fbo; + +@@ -288,6 +298,7 @@ + // mediacodec + CDVDMediaCodecInfo *mediacodec; + #endif ++ CDVDVideoCodecBuffer *codecinfo; + }; + + typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS]; +diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/RenderFormats.h xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderFormats.h +--- xbmc-13b4/xbmc/cores/VideoRenderers/RenderFormats.h 2014-04-24 11:49:41.300075322 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderFormats.h 2014-04-24 11:50:14.011208319 +0200 +@@ -37,6 +37,8 @@ + RENDER_FMT_BYPASS, + RENDER_FMT_EGLIMG, + RENDER_FMT_MEDIACODEC, ++ RENDER_FMT_YV12_BUFFER, ++ RENDER_FMT_IMXMAP, + }; + + #endif +diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp +--- xbmc-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-04-24 11:49:41.308075110 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/RenderManager.cpp 2014-04-24 11:50:14.011208319 +0200 +@@ -928,6 +928,10 @@ + else if(pic.format == RENDER_FMT_MEDIACODEC) + m_pRenderer->AddProcessor(pic.mediacodec, index); + #endif ++#ifdef HAS_IMXVPU ++ else if(pic.format == RENDER_FMT_YV12_BUFFER || pic.format == RENDER_FMT_IMXMAP) ++ m_pRenderer->AddProcessor(pic.codecinfo, index); ++#endif + + m_pRenderer->ReleaseImage(index, false); + +diff -Naur xbmc-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp xbmc-imx6-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp +--- xbmc-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2014-04-24 11:49:41.304075216 +0200 ++++ xbmc-imx6-13b4/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp 2014-04-24 11:50:14.011208319 +0200 +@@ -39,12 +39,12 @@ + // + // Transformation matrixes for different colorspaces. + // +-static float yuv_coef_bt601[4][4] = ++static float yuv_coef_bt601[4][4] = + { + { 1.0f, 1.0f, 1.0f, 0.0f }, + { 0.0f, -0.344f, 1.773f, 0.0f }, + { 1.403f, -0.714f, 0.0f, 0.0f }, +- { 0.0f, 0.0f, 0.0f, 0.0f } ++ { 0.0f, 0.0f, 0.0f, 0.0f } + }; + + static float yuv_coef_bt709[4][4] = +@@ -55,7 +55,7 @@ + { 0.0f, 0.0f, 0.0f, 0.0f } + }; + +-static float yuv_coef_ebu[4][4] = ++static float yuv_coef_ebu[4][4] = + { + { 1.0f, 1.0f, 1.0f, 0.0f }, + { 0.0f, -0.3960f, 2.029f, 0.0f }, +@@ -74,19 +74,19 @@ + static float** PickYUVConversionMatrix(unsigned flags) + { + // Pick the matrix. +- ++ + switch(CONF_FLAGS_YUVCOEF_MASK(flags)) + { + case CONF_FLAGS_YUVCOEF_240M: + return (float**)yuv_coef_smtp240m; break; + case CONF_FLAGS_YUVCOEF_BT709: + return (float**)yuv_coef_bt709; break; +- case CONF_FLAGS_YUVCOEF_BT601: ++ case CONF_FLAGS_YUVCOEF_BT601: + return (float**)yuv_coef_bt601; break; + case CONF_FLAGS_YUVCOEF_EBU: + return (float**)yuv_coef_ebu; break; + } +- ++ + return (float**)yuv_coef_bt601; + } + +@@ -228,7 +228,7 @@ + m_hProj = -1; + m_hModel = -1; + m_hAlpha = -1; +- if (m_format == RENDER_FMT_YUV420P) ++ if (m_format == RENDER_FMT_YUV420P || m_format == RENDER_FMT_YV12_BUFFER) + m_defines += "#define XBMC_YV12\n"; + else if (m_format == RENDER_FMT_NV12) + m_defines += "#define XBMC_NV12\n"; +diff -Naur xbmc-13b4/xbmc/input/linux/LinuxInputDevices.cpp xbmc-imx6-13b4/xbmc/input/linux/LinuxInputDevices.cpp +diff -Naur xbmc-13b4/xbmc/powermanagement/PowerManager.cpp xbmc-imx6-13b4/xbmc/powermanagement/PowerManager.cpp +diff -Naur xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +--- xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2014-04-24 11:50:14.019208107 +0200 +@@ -0,0 +1,321 @@ ++/* ++ * Copyright (C) 2011-2013 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, see ++ * . ++ * ++ */ ++ ++#include ++#include "system.h" ++#include ++ ++#include "EGLNativeTypeIMX.h" ++#include ++#include ++#include ++#include "utils/log.h" ++#include "utils/RegExp.h" ++#include "utils/StringUtils.h" ++#include "utils/Environment.h" ++#include "guilib/gui3d.h" ++#include "windowing/WindowingFactory.h" ++#include "cores/AudioEngine/AEFactory.h" ++#include ++ ++CEGLNativeTypeIMX::CEGLNativeTypeIMX() ++ : m_display(NULL) ++ , m_window(NULL) ++{ ++} ++ ++CEGLNativeTypeIMX::~CEGLNativeTypeIMX() ++{ ++} ++ ++bool CEGLNativeTypeIMX::CheckCompatibility() ++{ ++ std::ifstream file("/sys/class/graphics/fb0/fsl_disp_dev_property"); ++ return file; ++} ++ ++void CEGLNativeTypeIMX::Initialize() ++{ ++ int fd; ++ ++ fd = open("/dev/fb0",O_RDWR); ++ if (fd < 0) ++ { ++ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); ++ return; ++ } ++ ++ // Unblank the fb ++ if (ioctl(fd, FBIOBLANK, 0) < 0) ++ { ++ CLog::Log(LOGERROR, "%s - Error while unblanking fb0.\n", __FUNCTION__); ++ } ++ ++ close(fd); ++ ++ // Check if we can change the framebuffer resolution ++ fd = open("/sys/class/graphics/fb0/mode", O_RDWR); ++ if (fd >= 0) ++ { ++ CLog::Log(LOGNOTICE, "%s - graphics sysfs is writable", __FUNCTION__); ++ m_readonly = false; ++ } ++ else ++ { ++ CLog::Log(LOGNOTICE, "%s - graphics sysfs is read-only", __FUNCTION__); ++ m_readonly = true; ++ } ++ close(fd); ++ ++ return; ++} ++ ++void CEGLNativeTypeIMX::Destroy() ++{ ++ struct fb_fix_screeninfo fixed_info; ++ void *fb_buffer; ++ int fd; ++ ++ fd = open("/dev/fb0",O_RDWR); ++ if (fd < 0) ++ { ++ CLog::Log(LOGERROR, "%s - Error while opening /dev/fb0.\n", __FUNCTION__); ++ return; ++ } ++ ++ ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); ++ // Black fb0 ++ fb_buffer = mmap(NULL, fixed_info.smem_len, PROT_WRITE, MAP_SHARED, fd, 0); ++ if (fb_buffer == MAP_FAILED) ++ { ++ CLog::Log(LOGERROR, "%s - fb mmap failed %s.\n", __FUNCTION__, strerror(errno)); ++ } ++ else ++ { ++ memset(fb_buffer, 0x0, fixed_info.smem_len); ++ munmap(fb_buffer, fixed_info.smem_len); ++ } ++ ++ close(fd); ++ ++ return; ++} ++ ++bool CEGLNativeTypeIMX::CreateNativeDisplay() ++{ ++ // Force double-buffering ++ CEnvironment::setenv("FB_MULTI_BUFFER", "2", 0); ++ ++ // EGL will be rendered on fb0 ++ m_display = fbGetDisplayByIndex(0); ++ m_nativeDisplay = &m_display; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::CreateNativeWindow() ++{ ++ m_window = fbCreateWindow(m_display, 0, 0, 0, 0); ++ m_nativeWindow = &m_window; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const ++{ ++ if (!nativeDisplay) ++ return false; ++ if (!m_nativeDisplay) ++ return false; ++ *nativeDisplay = (XBNativeDisplayType*)m_nativeDisplay; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::GetNativeWindow(XBNativeWindowType **nativeWindow) const ++{ ++ if (!nativeWindow) ++ return false; ++ if (!m_nativeWindow || !m_window) ++ return false; ++ *nativeWindow = (XBNativeWindowType*)m_nativeWindow; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::DestroyNativeDisplay() ++{ ++ if (m_display) ++ fbDestroyDisplay(m_display); ++ m_display = NULL; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::DestroyNativeWindow() ++{ ++ if (m_window) ++ fbDestroyWindow(m_window); ++ m_window = NULL; ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::GetNativeResolution(RESOLUTION_INFO *res) const ++{ ++ std::string mode; ++ get_sysfs_str("/sys/class/graphics/fb0/mode", mode); ++ return ModeToResolution(mode, res); ++} ++ ++bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) ++{ ++ if (m_readonly) ++ return false; ++ ++ std::string mode; ++ get_sysfs_str("/sys/class/graphics/fb0/mode", mode); ++ if (res.strId == mode) ++ return false; ++ ++ DestroyNativeWindow(); ++ DestroyNativeDisplay(); ++ ++ set_sysfs_str("/sys/class/graphics/fb0/mode", res.strId); ++ ++ CreateNativeDisplay(); ++ ++ CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); ++ ++ // Reset AE ++ CAEFactory::DeviceChange(); ++ ++ return true; ++} ++ ++bool CEGLNativeTypeIMX::ProbeResolutions(std::vector &resolutions) ++{ ++ if (m_readonly) ++ return false; ++ ++ std::string valstr; ++ get_sysfs_str("/sys/class/graphics/fb0/modes", valstr); ++ std::vector probe_str; ++ StringUtils::SplitString(valstr, "\n", probe_str); ++ ++ resolutions.clear(); ++ RESOLUTION_INFO res; ++ for (size_t i = 0; i < probe_str.size(); i++) ++ { ++ if(!StringUtils::StartsWith(probe_str[i], "S:")) ++ continue; ++ if(ModeToResolution(probe_str[i], &res)) ++ resolutions.push_back(res); ++ } ++ return resolutions.size() > 0; ++} ++ ++bool CEGLNativeTypeIMX::GetPreferredResolution(RESOLUTION_INFO *res) const ++{ ++ return GetNativeResolution(res); ++} ++ ++bool CEGLNativeTypeIMX::ShowWindow(bool show) ++{ ++ // Force vsync by default ++ eglSwapInterval(g_Windowing.GetEGLDisplay(), 1); ++ EGLint result = eglGetError(); ++ if(result != EGL_SUCCESS) ++ CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, result); ++ ++ return false; ++} ++ ++int CEGLNativeTypeIMX::get_sysfs_str(std::string path, std::string& valstr) const ++{ ++ int len; ++ char buf[256] = {0}; ++ ++ int fd = open(path.c_str(), O_RDONLY); ++ if (fd >= 0) ++ { ++ while ((len = read(fd, buf, 255)) > 0) ++ valstr.append(buf, len); ++ close(fd); ++ } ++ else ++ { ++ CLog::Log(LOGERROR, "%s: error reading %s",__FUNCTION__, path.c_str()); ++ valstr = "fail"; ++ return -1; ++ } ++ return 0; ++} ++ ++int CEGLNativeTypeIMX::set_sysfs_str(std::string path, std::string val) const ++{ ++ int fd = open(path.c_str(), O_WRONLY); ++ if (fd >= 0) ++ { ++ val += '\n'; ++ write(fd, val.c_str(), val.size()); ++ close(fd); ++ return 0; ++ } ++ CLog::Log(LOGERROR, "%s: error writing %s",__FUNCTION__, path.c_str()); ++ return -1; ++} ++ ++bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) const ++{ ++ if (!res) ++ return false; ++ ++ res->iWidth = 0; ++ res->iHeight= 0; ++ ++ if(mode.empty()) ++ return false; ++ ++ std::string fromMode = StringUtils::Mid(mode, 2); ++ StringUtils::Trim(fromMode); ++ ++ CRegExp split(true); ++ split.RegComp("([0-9]+)x([0-9]+)([pi])-([0-9]+)"); ++ if (split.RegFind(fromMode) < 0) ++ return false; ++ ++ int w = atoi(split.GetMatch(1).c_str()); ++ int h = atoi(split.GetMatch(2).c_str()); ++ std::string p = split.GetMatch(3); ++ int r = atoi(split.GetMatch(4).c_str()); ++ ++ res->iWidth = w; ++ res->iHeight= h; ++ res->iScreenWidth = w; ++ res->iScreenHeight= h; ++ res->fRefreshRate = r; ++ res->dwFlags = p[0] == 'p' ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED; ++ ++ res->iScreen = 0; ++ res->bFullScreen = true; ++ res->iSubtitles = (int)(0.965 * res->iHeight); ++ res->fPixelRatio = 1.0f; ++ res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, ++ res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); ++ res->strId = mode; ++ ++ return res->iWidth > 0 && res->iHeight> 0; ++} ++ +diff -Naur xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h +--- xbmc-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h 1970-01-01 01:00:00.000000000 +0100 ++++ xbmc-imx6-13b4/xbmc/windowing/egl/EGLNativeTypeIMX.h 2014-04-24 11:50:14.019208107 +0200 +@@ -0,0 +1,60 @@ ++#pragma once ++ ++/* ++ * Copyright (C) 2011-2013 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, see ++ * . ++ * ++ */ ++#include ++#include "EGLNativeType.h" ++#include "EGL/eglvivante.h" ++ ++class CEGLNativeTypeIMX : public CEGLNativeType ++{ ++public: ++ CEGLNativeTypeIMX(); ++ virtual ~CEGLNativeTypeIMX(); ++ virtual std::string GetNativeName() const { return "iMX"; } ++ virtual bool CheckCompatibility(); ++ virtual void Initialize(); ++ virtual void Destroy(); ++ virtual int GetQuirks() { return EGL_QUIRK_NONE; } ++ ++ virtual bool CreateNativeDisplay(); ++ virtual bool CreateNativeWindow(); ++ virtual bool GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const; ++ virtual bool GetNativeWindow(XBNativeWindowType **nativeWindow) const; ++ ++ virtual bool DestroyNativeWindow(); ++ virtual bool DestroyNativeDisplay(); ++ ++ virtual bool GetNativeResolution(RESOLUTION_INFO *res) const; ++ virtual bool SetNativeResolution(const RESOLUTION_INFO &res); ++ virtual bool ProbeResolutions(std::vector &resolutions); ++ virtual bool GetPreferredResolution(RESOLUTION_INFO *res) const; ++ ++ virtual bool ShowWindow(bool show); ++ ++protected: ++ bool m_readonly; ++ int get_sysfs_str(std::string path, std::string& valstr) const; ++ int set_sysfs_str(std::string path, std::string val) const; ++ bool ModeToResolution(std::string mode, RESOLUTION_INFO *res) const; ++ ++ EGLNativeDisplayType m_display; ++ EGLNativeWindowType m_window; ++}; +diff -Naur xbmc-13b4/xbmc/windowing/egl/EGLWrapper.cpp xbmc-imx6-13b4/xbmc/windowing/egl/EGLWrapper.cpp +--- xbmc-13b4/xbmc/windowing/egl/EGLWrapper.cpp 2014-04-24 11:49:41.748063448 +0200 ++++ xbmc-imx6-13b4/xbmc/windowing/egl/EGLWrapper.cpp 2014-04-24 11:50:14.019208107 +0200 +@@ -17,16 +17,17 @@ + * . + * + */ +- + #include "system.h" + + #ifdef HAS_EGL +- + #include "utils/log.h" + #include "EGLNativeTypeAndroid.h" + #include "EGLNativeTypeAmlogic.h" + #include "EGLNativeTypeRaspberryPI.h" + #include "EGLNativeTypeWayland.h" ++#ifdef HAS_IMXVPU ++#include "EGLNativeTypeIMX.h" ++#endif + #include "EGLWrapper.h" + + #define CheckError() m_result = eglGetError(); if(m_result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x",__FUNCTION__, m_result); +@@ -83,7 +84,11 @@ + if ((nativeGuess = CreateEGLNativeType(implementation)) || + (nativeGuess = CreateEGLNativeType(implementation)) || + (nativeGuess = CreateEGLNativeType(implementation)) || +- (nativeGuess = CreateEGLNativeType(implementation))) ++ (nativeGuess = CreateEGLNativeType(implementation)) ++#ifdef HAS_IMXFB ++ || (nativeGuess = CreateEGLNativeType(implementation)) ++#endif ++ ) + { + m_nativeTypes = nativeGuess; + +diff -Naur xbmc-13b4/xbmc/windowing/egl/Makefile.in xbmc-imx6-13b4/xbmc/windowing/egl/Makefile.in +--- xbmc-13b4/xbmc/windowing/egl/Makefile.in 2014-04-24 11:49:41.736063766 +0200 ++++ xbmc-imx6-13b4/xbmc/windowing/egl/Makefile.in 2014-04-24 11:50:14.019208107 +0200 +@@ -24,6 +24,10 @@ + wayland/XBMCSurface.cpp + endif + ++ifeq (@USE_IMXFB@,1) ++SRCS+= EGLNativeTypeIMX.cpp ++endif ++ + LIB = windowing_egl.a + + include ../../../Makefile.include diff --git a/tools/mkpkg/mkpkg_xbmc b/tools/mkpkg/mkpkg_xbmc-helix similarity index 98% rename from tools/mkpkg/mkpkg_xbmc rename to tools/mkpkg/mkpkg_xbmc-helix index 0f761a2664..87a71f6af0 100755 --- a/tools/mkpkg/mkpkg_xbmc +++ b/tools/mkpkg/mkpkg_xbmc-helix @@ -19,10 +19,10 @@ # http://www.gnu.org/copyleft/gpl.html ################################################################################ -PKG_NAME="xbmc" +PKG_NAME="xbmc-master" PKG_VERSION="" GIT_REPO="-b master git://github.com/xbmc/xbmc.git" -DEST_DIR="$PKG_NAME-master" +DEST_DIR="$PKG_NAME" echo "getting sources..." if [ ! -d $DEST_DIR-latest ]; then