diff --git a/packages/mediacenter/package.mk b/packages/mediacenter/package.mk index b8607f6ee5..993d79630d 100644 --- a/packages/mediacenter/package.mk +++ b/packages/mediacenter/package.mk @@ -36,7 +36,7 @@ for i in $SKINS; do PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET $MEDIACENTER-theme-$i" done -if [ "$MEDIACENTER" = "xbmc" -o "$MEDIACENTER" = "xbmc-master" ]; then +if [ "$MEDIACENTER" = "xbmc" ]; then # some python stuff needed for various addons PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET Imaging" PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET simplejson" diff --git a/packages/mediacenter/service.openelec.settings/package.mk b/packages/mediacenter/service.openelec.settings/package.mk index 9972298023..097cc51294 100644 --- a/packages/mediacenter/service.openelec.settings/package.mk +++ b/packages/mediacenter/service.openelec.settings/package.mk @@ -17,11 +17,7 @@ ################################################################################ PKG_NAME="service.openelec.settings" -if [ "$XBMC" = "master" ]; then - PKG_VERSION="0.4.0" -else - PKG_VERSION="0.3.17" -fi +PKG_VERSION="0.3.17" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="prop." diff --git a/packages/mediacenter/xbmc-master-theme-Confluence/package.mk b/packages/mediacenter/xbmc-master-theme-Confluence/package.mk deleted file mode 100644 index dbd52978a0..0000000000 --- a/packages/mediacenter/xbmc-master-theme-Confluence/package.mk +++ /dev/null @@ -1,52 +0,0 @@ -################################################################################ -# 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-603c7fa" -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 deleted file mode 100644 index 79a3addf5a..0000000000 --- a/packages/mediacenter/xbmc-master-theme-Confluence/patches/xbmc-master-theme-Confluence-001-add_oe_settings_to_homescreen.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- 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 deleted file mode 100644 index c54111aaa3..0000000000 --- a/packages/mediacenter/xbmc-master/config/advancedsettings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - false - cputemp - gputemp - - - 30 - - - 4.0 - - diff --git a/packages/mediacenter/xbmc-master/config/appliance.xml b/packages/mediacenter/xbmc-master/config/appliance.xml deleted file mode 100644 index 98fd49f28c..0000000000 --- a/packages/mediacenter/xbmc-master/config/appliance.xml +++ /dev/null @@ -1,49 +0,0 @@ - - -
- - - - 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 deleted file mode 100644 index 206659f9da..0000000000 --- a/packages/mediacenter/xbmc-master/config/os.openelec.tv/addon.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/mediacenter/xbmc-master/config/repository.openelec.tv/addon.xml b/packages/mediacenter/xbmc-master/config/repository.openelec.tv/addon.xml deleted file mode 100644 index 7b21ca7f12..0000000000 --- a/packages/mediacenter/xbmc-master/config/repository.openelec.tv/addon.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - @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 deleted file mode 100644 index 1147ae1d37..0000000000 Binary files a/packages/mediacenter/xbmc-master/config/repository.openelec.tv/icon.png and /dev/null differ diff --git a/packages/mediacenter/xbmc-master/debug.d/xbmc.conf b/packages/mediacenter/xbmc-master/debug.d/xbmc.conf deleted file mode 100644 index 7c6c362ac3..0000000000 --- a/packages/mediacenter/xbmc-master/debug.d/xbmc.conf +++ /dev/null @@ -1 +0,0 @@ -XBMC_DEBUG="--debug" diff --git a/packages/mediacenter/xbmc-master/fonts/DejaVuSans.ttf b/packages/mediacenter/xbmc-master/fonts/DejaVuSans.ttf deleted file mode 100644 index 84ca1d7503..0000000000 Binary files a/packages/mediacenter/xbmc-master/fonts/DejaVuSans.ttf and /dev/null differ diff --git a/packages/mediacenter/xbmc-master/fonts/Trebuchet MS Bold.ttf b/packages/mediacenter/xbmc-master/fonts/Trebuchet MS Bold.ttf deleted file mode 100644 index 867f56d776..0000000000 Binary files a/packages/mediacenter/xbmc-master/fonts/Trebuchet MS Bold.ttf and /dev/null differ diff --git a/packages/mediacenter/xbmc-master/fonts/YanoneKaffeesatz-Bold.ttf b/packages/mediacenter/xbmc-master/fonts/YanoneKaffeesatz-Bold.ttf deleted file mode 100644 index e9964b0809..0000000000 Binary files a/packages/mediacenter/xbmc-master/fonts/YanoneKaffeesatz-Bold.ttf and /dev/null differ diff --git a/packages/mediacenter/xbmc-master/package.mk b/packages/mediacenter/xbmc-master/package.mk deleted file mode 100644 index 79b8af7fc4..0000000000 --- a/packages/mediacenter/xbmc-master/package.mk +++ /dev/null @@ -1,525 +0,0 @@ -################################################################################ -# 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-603c7fa" -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 libogg libcdio libmodplug faad2 flac libmpeg2 taglib libxml2 libxslt yajl sqlite libvorbis ffmpeg xbmc-master:host" -PKG_DEPENDS_HOST="toolchain" -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 nss-mdns" - 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_configure_host() { -# xbmc fails to build in subdirs - cd $ROOT/$PKG_BUILD - rm -rf .$HOST_NAME -} - -make_host() { - make -C tools/depends/native/JsonSchemaBuilder -} - -makeinstall_host() { - cp -PR tools/depends/native/JsonSchemaBuilder/native/JsonSchemaBuilder $ROOT/$TOOLCHAIN/bin -} - -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" - - export JSON_BUILDER=$ROOT/$TOOLCHAIN/bin/JsonSchemaBuilder -} - -make_target() { -# 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-051-add_ouya_controller_keymap.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-051-add_ouya_controller_keymap.patch deleted file mode 100644 index 5a6df63bf4..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-051-add_ouya_controller_keymap.patch +++ /dev/null @@ -1,338 +0,0 @@ -diff -Naur xbmc-master-14-5ec51aa.orig/system/keymaps/joystick.Ouya.Controller.xml xbmc-master-14-5ec51aa/system/keymaps/joystick.Ouya.Controller.xml ---- xbmc-master-14-5ec51aa.orig/system/keymaps/joystick.Ouya.Controller.xml 1969-12-31 16:00:00.000000000 -0800 -+++ xbmc-master-14-5ec51aa/system/keymaps/joystick.Ouya.Controller.xml 2014-06-06 16:31:54.812044875 -0700 -@@ -0,0 +1,334 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ AnalogSeekBack -+ AnalogSeekForward -+ ScrollUp -+ ScrollDown -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ AnalogRewind -+ AnalogFastForward -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ AnalogRewind -+ AnalogFastForward -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ AnalogMove -+ AnalogMove -+ ZoomOut -+ ZoomIn -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ CursorLeft -+ CursorRight -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ diff --git a/packages/mediacenter/xbmc-master/patches/xbmc-master-052-ps4_controller_support.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-052-ps4_controller_support.patch deleted file mode 100644 index 6beb85108b..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-052-ps4_controller_support.patch +++ /dev/null @@ -1,328 +0,0 @@ -diff -Naur xbmc-master-14-5ec51aa.orig/system/keymaps/joystick.PS4.Controller.xml xbmc-master-14-5ec51aa/system/keymaps/joystick.PS4.Controller.xml ---- xbmc-master-14-5ec51aa.orig/system/keymaps/joystick.PS4.Controller.xml 1969-12-31 16:00:00.000000000 -0800 -+++ xbmc-master-14-5ec51aa/system/keymaps/joystick.PS4.Controller.xml 2014-06-06 16:53:33.786191904 -0700 -@@ -0,0 +1,324 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Left -+ Right -+ Up -+ Down -+ AnalogSeekForward -+ AnalogSeekBack -+ ScrollUp -+ ScrollDown -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ StepBack -+ StepForward -+ BigStepForward -+ BigStepBack -+ -+ -+ -+ -+ -+ ChannelUp -+ ChannelDown -+ PreviousChannelGroup -+ NextChannelGroup -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ PreviousPicture -+ NextPicture -+ AnalogMove -+ AnalogMove -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 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 deleted file mode 100644 index 00df7bb51c..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-101-fix_libdvd_xFLAGS-0.1.patch +++ /dev/null @@ -1,73 +0,0 @@ -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 deleted file mode 100644 index 0888920258..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-102-disable_backslash-0.1.patch +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 57476fed62..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-103-disable-online-check.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 1716ffbf57a8d812f3bc7b26752e867066c36c44 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Sat, 7 Jun 2014 12:40:57 +0300 -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 456c733..0c20ae2 100644 ---- a/xbmc/GUIInfoManager.cpp -+++ b/xbmc/GUIInfoManager.cpp -@@ -273,7 +273,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 }, - { "osversioninfo", SYSTEM_OS_VERSION_INFO }, - { "kernelversion", SYSTEM_OS_VERSION_INFO }, // old, not correct name - { "uptime", SYSTEM_UPTIME }, -diff --git a/xbmc/utils/SystemInfo.cpp b/xbmc/utils/SystemInfo.cpp -index 55ed760..aefeb70 100644 ---- a/xbmc/utils/SystemInfo.cpp -+++ b/xbmc/utils/SystemInfo.cpp -@@ -240,7 +240,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.osVersionInfo = CSysInfo::GetOsPrettyNameWithVersion() + " (kernel: " + CSysInfo::GetKernelName() + " " + CSysInfo::GetKernelVersionFull() + ")"; -@@ -963,9 +962,7 @@ int CSysInfo::GetXbmcBitness(void) - - 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 03a23e3..1528939 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.9.1 - 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 deleted file mode 100644 index 86bfb5c4fe..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-104-use-udevil-to-umount.patch +++ /dev/null @@ -1,39 +0,0 @@ -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 deleted file mode 100644 index d58eeecb9d..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-501-enable_PYTHONOPTIMIZE_with_external_Python-0.1.patch +++ /dev/null @@ -1,18 +0,0 @@ -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 deleted file mode 100644 index f0b08b5e8d..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-502-add_openelec.tv_RSS_news-0.1.patch +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 7e78fbb3b9..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-990.15-depends-mark_our_wrapped_functions_as_used.patch +++ /dev/null @@ -1,458 +0,0 @@ -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.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-995.01-fernetmenta.patch deleted file mode 100644 index 9b4386061b..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.01-fernetmenta.patch +++ /dev/null @@ -1,3420 +0,0 @@ -From 653f57ae1d9895d66a0a4a188607ae9f93db7022 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:34:39 +0200 -Subject: [PATCH 09/35] 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 | 38 +++- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 41 +++++ - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 197 +++++++++++++++++---- - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 22 +++ - 7 files changed, 295 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 741017d..c5b24d6 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -136,6 +136,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 // see GetCodecStats -+#define DVP_FLAG_DRAIN 0x00000200 // see GetCodecStats -+ - // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2! - - #define DVP_QSCALE_UNKNOWN 0 -@@ -153,6 +157,8 @@ 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 -+ - class CDVDVideoCodec - { - public: -@@ -270,7 +276,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 -@@ -287,4 +292,35 @@ class CDVDVideoCodec - * Interact with user settings so that user disabled codecs are disabled - */ - static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id); -+ -+ /* For calculation of dropping requirements player asks for some information. -+ * -+ * - pts : right after decoder, used to detect gaps (dropped frames in decoder) -+ * - droppedPics : indicates if decoder has dropped a picture -+ * -1 means that decoder has no info on this. -+ * -+ * If codec does not implement this method, pts of decoded frame at input -+ * video player is used. In case decoder 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 &droppedPics) -+ { -+ droppedPics= -1; -+ 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 b6c1e04..c48108f 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,18 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences() - else - return 0; - } -+ -+bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &droppedPics) -+{ -+ pts = m_decoderPts; -+ if (m_skippedDeint) -+ droppedPics = m_skippedDeint; -+ else -+ droppedPics = -1; -+ 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 75ac0f2..1a80a48 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 GetCodecStats(double &pts, int &droppedPics); -+ 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 633e333..09b7772 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 -@@ -319,8 +320,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) - { -@@ -432,6 +435,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()) - { -@@ -444,6 +448,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; -@@ -463,6 +468,7 @@ void CDVDPlayerVideo::Process() - m_iNrOfPicturesNotToSkip = 0; - if (m_pVideoCodec) - m_pVideoCodec->SetSpeed(m_speed); -+ m_droppingStats.Reset(); - } - else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) - { -@@ -508,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) - { -@@ -560,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; -@@ -1182,33 +1202,12 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - m_FlipTimeStamp += max(0.0, iSleepTime); - m_FlipTimePts = pts; - -- 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; -@@ -1241,7 +1240,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 -@@ -1541,3 +1540,131 @@ void CDVDPlayerVideo::CalcFrameRate() - m_iFrameRateCount = 0; - } - } -+ -+int CDVDPlayerVideo::CalcDropRequirement(double pts) -+{ -+ int result = 0; -+ double iSleepTime; -+ double iDecoderPts, iRenderPts; -+ double iInterval; -+ double iGain; -+ double iLateness; -+ bool bNewFrame; -+ int iDroppedPics = -1; -+ int iBufferLevel; -+ -+ // get decoder stats -+ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iDroppedPics)) -+ 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; -+ -+ 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) -+ { -+ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE; -+ if (iDroppedPics > 0) -+ { -+ CDroppingStats::CGain gain; -+ gain.gain = iDroppedPics * 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 pictures, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); -+ } -+ else if (iDroppedPics < 0 && 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) -+ { -+ if (bNewFrame || m_droppingStats.m_dropRequests < 5) -+ { -+ result |= EOS_VERYLATE; -+ } -+ 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 296cae6..328edbf 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -37,6 +37,24 @@ 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 IDVDStreamPlayer - { - public: -@@ -105,6 +123,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayer - #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); -@@ -131,6 +150,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayer - - 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 -@@ -184,5 +204,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayer - CPullupCorrection m_pullupCorrection; - - std::list m_packets; -+ -+ CDroppingStats m_droppingStats; - }; - --- -1.9.3 - - -From 2efc326a47e290a801cd835296b6045e72d0e212 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 2 Sep 2012 16:05:21 +0200 -Subject: [PATCH 10/35] video player: present correct pts to user for a/v sync - (after buffering in renderer) - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 16 ++++++++++++++++ - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +- - 2 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 09b7772..24282cc 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1460,6 +1460,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 - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index 328edbf..1cca436 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -100,7 +100,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayer - - 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.3 - - -From 5f08b21d01b7c74e78024485a2b2d5874804b5f7 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sat, 1 Jun 2013 11:21:19 +0200 -Subject: [PATCH 11/35] 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 fb41ccf..f5e5677 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.3 - - -From 5e1bf08878926117994fc7e4ef011b0592bdd309 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:41:31 +0200 -Subject: [PATCH 12/35] 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 24282cc..5c219d6 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.3 - - -From a4f5190b81b1e1f46771282f4520e50256fc67c5 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:43:06 +0200 -Subject: [PATCH 13/35] 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 5c219d6..767f6bd 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1502,7 +1502,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.3 - - -From 6706086f632fb0a291e007851bedb8a1673c3cdb Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:49:05 +0200 -Subject: [PATCH 14/35] 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 85b9f1c..1b2f820 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -1595,7 +1595,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()) - { -@@ -2219,6 +2219,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.3 - - -From ece66466f1d6666816db1631a5be2b4c505fa926 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 20 Aug 2012 16:06:39 +0200 -Subject: [PATCH 15/35] 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 710482f..49eff5c 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" -@@ -427,6 +427,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) - - CreateStreams(); - -+ m_bPtsWrapChecked = false; -+ m_bPtsWrap = false; -+ - return true; - } - -@@ -568,6 +571,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; -@@ -707,6 +716,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; - -@@ -840,7 +867,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) -@@ -859,6 +895,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.3 - - -From d976c334c57f17e91c35a43af189ee43ffcfb56a Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Tue, 2 Oct 2012 13:02:10 +0200 -Subject: [PATCH 16/35] 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 767f6bd..f905008 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.3 - - -From abb0d4888fd5467b44e67d2050d06f33eb7bb2f3 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 11 Oct 2012 12:05:50 +0200 -Subject: [PATCH 17/35] 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 e58681b..3f87a7d 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -1970,10 +1970,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 6835504..7d50649 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -157,6 +157,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; -@@ -596,6 +598,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 c57a9fb..6c505a8 100644 ---- a/xbmc/settings/AdvancedSettings.h -+++ b/xbmc/settings/AdvancedSettings.h -@@ -163,6 +163,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.3 - - -From 4c23dd583f32e1e9a4327ccc910873163628cb9e Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Fri, 2 Nov 2012 13:20:03 +0100 -Subject: [PATCH 18/35] 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 be6603a..6ff2400 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 1b2f820..018f4f7 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -1596,11 +1596,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 -@@ -1619,7 +1621,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)); - } - } - } -@@ -2068,7 +2070,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"); -@@ -2204,9 +2206,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(); - } - -@@ -2222,7 +2225,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 -@@ -3120,7 +3124,7 @@ void CDVDPlayer::UpdateClockMaster() - } - } - --void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) -+void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync) - { - double startpts; - if(accurate) -@@ -3132,19 +3136,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; - -@@ -3188,7 +3196,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 bf73d27..91f63c0 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.h -+++ b/xbmc/cores/dvdplayer/DVDPlayer.h -@@ -302,7 +302,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(); -@@ -355,8 +355,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 f905008..3eb6315 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1475,7 +1475,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; -@@ -1574,6 +1574,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) - int iDroppedPics = -1; - int iBufferLevel; - -+ m_droppingStats.m_lastPts = pts; -+ - // get decoder stats - if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iDroppedPics)) - iDecoderPts = pts; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index 1cca436..e8e382a 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -51,6 +51,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.3 - - -From bb97ddfbeecb72e6067b13bce8f517819cfbe8a3 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 28 Mar 2013 15:18:53 +0100 -Subject: [PATCH 19/35] 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 80fe7c1..31b432f 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.3 - - -From 337b26bc138f08f17481b4c299d95dfc25a08eb9 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Thu, 28 Mar 2013 20:50:59 +0100 -Subject: [PATCH 20/35] 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 748b529..bb28233 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -2299,10 +2299,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.3 - - -From 02b1fb56e7a8c2ccd2ad9ae141bd8ec94cfe1240 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Tue, 11 Jun 2013 16:20:29 +0200 -Subject: [PATCH 21/35] 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.3 - - -From d43d32bd23616abac9e76713bf0c4bf71661c9dd Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Thu, 25 Jul 2013 17:18:13 +0200 -Subject: [PATCH 22/35] 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 2f71051..a824056 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -@@ -32,8 +32,8 @@ using namespace ActiveAE; - - #include "utils/TimeUtils.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.3 - - -From b32c6b6c720383e8f87137508d196fce0ebbe058 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 4 Aug 2013 10:11:16 +0200 -Subject: [PATCH 23/35] 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 3f87a7d..f7418e8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp -@@ -1097,8 +1097,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; -@@ -2294,8 +2293,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); -@@ -2307,8 +2305,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))) - { -@@ -2330,8 +2327,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.3 - - -From a0300251e43a107fdfac49f59e6456512f0de77a Mon Sep 17 00:00:00 2001 -From: Marcel Groothuis -Date: Thu, 5 Dec 2013 22:02:50 +0100 -Subject: [PATCH 24/35] 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 49eff5c..4d4be02 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(); -@@ -388,13 +390,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) -@@ -414,6 +415,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(); - -@@ -467,7 +471,7 @@ void CDVDDemuxFFmpeg::Reset() - { - CDVDInputStream* pInputStream = m_pInput; - Dispose(); -- Open(pInputStream); -+ Open(pInputStream, m_streaminfo); - } - - void CDVDDemuxFFmpeg::Flush() -@@ -662,25 +666,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) - { -@@ -1623,3 +1634,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.3 - - -From cffbdb13512718b083e6e49d7625efefcff1dc7c Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Thu, 14 Nov 2013 20:35:04 +0100 -Subject: [PATCH 25/35] 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 4d4be02..56eaccc 100644 ---- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp -@@ -386,6 +386,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; -@@ -414,6 +421,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; -@@ -1670,7 +1683,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 -@@ -1732,3 +1745,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.3 - - -From 6db875e37a4c23952ed114482ab4ec1e57941ba5 Mon Sep 17 00:00:00 2001 -From: Wolfgang Haupt -Date: Thu, 5 Dec 2013 22:11:57 +0100 -Subject: [PATCH 26/35] 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.3 - - -From 9ab279173cd4b4b750028f2ef3f4bd1a61a38bf5 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Tue, 28 Jan 2014 08:43:29 +0100 -Subject: [PATCH 27/35] 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 56eaccc..d0f13a1 100644 ---- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp -@@ -1722,15 +1722,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 -@@ -1738,12 +1742,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() -@@ -1755,7 +1762,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.3 - - -From 08634b062976edb8f7740b364e66017a1870756d Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 13 Apr 2014 10:52:26 +0200 -Subject: [PATCH 28/35] 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 d0f13a1..1aeae2b 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() -@@ -386,11 +387,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 -@@ -422,14 +422,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(); -@@ -1723,6 +1726,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.3 - - -From 7110f52260049d39134a6d5e102b67803994371d Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 22 Dec 2013 14:52:29 +0100 -Subject: [PATCH 29/35] 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 8642922..0988e60 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -314,6 +314,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) -@@ -441,7 +447,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 1766ce1..abbfcdf 100644 ---- a/configure.in -+++ b/configure.in -@@ -832,6 +832,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 -@@ -2583,6 +2596,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" -@@ -2661,6 +2678,7 @@ AC_SUBST(GTEST_CONFIGURED) - AC_SUBST(USE_DOXYGEN) - AC_SUBST(USE_PVR_ADDONS) - AC_SUBST(UPNP_DEFINES) -+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 baebb4d..dacbbd6 100644 ---- a/xbmc/DllPaths_generated.h.in -+++ b/xbmc/DllPaths_generated.h.in -@@ -92,4 +92,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.3 - - -From 1cb3a7dbbf78eb6c7967700fc33806e33265ff6f Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Thu, 19 Dec 2013 15:36:11 +0100 -Subject: [PATCH 30/35] 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 + - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 2 + - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 71 ++++++++-- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 4 + - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 152 +++++++++++++++++++++ - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 31 +++++ - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 30 ++-- - 10 files changed, 290 insertions(+), 37 deletions(-) - -diff --git a/language/English/strings.po b/language/English/strings.po -index fb26ead..c6822b1 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -6162,7 +6162,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" -@@ -15279,7 +15285,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 391bcee..c0f64ab 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/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index c5b24d6..3efc007 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -323,4 +323,6 @@ class CDVDVideoCodec - * - */ - virtual void SetCodecControl(int flags) {} -+ -+ virtual bool IsInterlaced() { return false; } - }; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index c48108f..3b70aa0 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, -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -index 1a80a48..25f1d25 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(); -@@ -70,6 +72,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - virtual unsigned GetAllowedReferences(); - virtual bool GetCodecStats(double &pts, int &droppedPics); - virtual void SetCodecControl(int flags); -+ virtual bool IsInterlaced() { return m_interlace; } - - bool IsHardwareAllowed() { return !m_bSoftware; } - IHardwareDecoder * GetHardware() { return m_pHardware; }; -@@ -129,4 +132,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 3eb6315..e17c712 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,13 @@ void CDVDPlayerVideo::Process() - } - - if (picture.iRepeatPicture) -+ { -+ bool deint = m_pVideoCodec->IsInterlaced(); -+ 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.3 - - -From 9cca95f06d9c4416b6d6aa99c4be3edf049bb16d Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Tue, 28 Jan 2014 10:05:26 +0100 -Subject: [PATCH 31/35] 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 3b70aa0..80915d4 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -477,6 +477,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; -@@ -693,8 +701,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.3 - - -From c72261a920896f3df7bd50464f696e4d2e74d850 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Tue, 28 Jan 2014 17:24:58 +0100 -Subject: [PATCH 32/35] 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 80915d4..ab36704 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -704,7 +704,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.3 - - -From d8f5bf2f3100616d3c47c4e17c8598318d9cb501 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Tue, 11 Feb 2014 18:15:06 +0100 -Subject: [PATCH 33/35] 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 ce67a31..58c8776 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp -@@ -263,7 +263,13 @@ unsigned int CActiveAEStream::AddData(uint8_t* const *data, unsigned int offset, - } - } - 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.3 - - -From a9d54ec6a768420d9582784bfeb39e72c1e9f774 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Sun, 25 May 2014 21:25:31 +0200 -Subject: [PATCH 34/35] squash swfilter - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index 315f3ca..4452cfb 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -519,6 +519,8 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) - m_surfaces_proc.push_back(pic); - if (m_surfaces_proc.size() < m_renderbuffers_count) - return VC_BUFFER; -+ -+ return VC_PICTURE; - } - - return VC_BUFFER | VC_PICTURE; --- -1.9.3 - - -From d69f623bea5e2b08ff0ad02fe573188842258164 Mon Sep 17 00:00:00 2001 -From: Rainer Hochecker -Date: Mon, 26 May 2014 08:07:39 +0200 -Subject: [PATCH 35/35] swfilter, squash me too - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -index 4452cfb..befb6d6 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp -@@ -517,7 +517,7 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) - av_frame_ref(&pic.frame, frame); - pic.surface = *it; - m_surfaces_proc.push_back(pic); -- if (m_surfaces_proc.size() < m_renderbuffers_count) -+ if (m_surfaces_proc.size() < m_renderbuffers_count + 1) - return VC_BUFFER; - - return VC_PICTURE; -@@ -526,7 +526,15 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) - return VC_BUFFER | VC_PICTURE; - } - else -- return VC_BUFFER; -+ { -+ if (m_use_filter) -+ { -+ if (m_surfaces_proc.size() < m_renderbuffers_count + 1) -+ return VC_BUFFER; -+ } -+ else -+ return VC_BUFFER; -+ } - } - - bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) --- -1.9.3 - 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 deleted file mode 100644 index 3f331b1574..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch +++ /dev/null @@ -1,29 +0,0 @@ -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 deleted file mode 100644 index c0fe5a62ab..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.10-disable-minimize.patch +++ /dev/null @@ -1,18 +0,0 @@ -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 deleted file mode 100644 index 51a7e52381..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-995.12-run-tzdata-setup-on-timezone-change.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index d81adcd3f1..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.00-service-addons-use-a-wrapper-to-setup-systemd.patch +++ /dev/null @@ -1,97 +0,0 @@ -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.03-0001-handle-SIGTERM.patch b/packages/mediacenter/xbmc-master/patches/xbmc-master-999.03-0001-handle-SIGTERM.patch deleted file mode 100644 index 6f86040bf5..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.03-0001-handle-SIGTERM.patch +++ /dev/null @@ -1,169 +0,0 @@ -From dbc86891d089a2a871be5a8663e8a5a9a1cffb53 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Thu, 5 Jun 2014 18:50:04 +0300 -Subject: [PATCH] handle SIGTERM - -In some situations, due to deadlocks or crashes, xbmc fails to exit properly in -CApplication::Stop(), so g_powerManager.Reboot() / g_powerManager.Powerdown() never gets -called, that's a big no-no for openelec as our users can't shutdown or reboot. -There are few addons reported to cause this behaviour: trakkt.tv, watchdog, weather.underground. - -I've also noticed that sometimes new threads (FileCache ??) get started AFTER -CApplication::Stop() is called, delaying shutdown with 1+ minute (2 curl timeoouts?). -The problem seems to be in CJobManager::CancelJobs() but I am too lame to understand where, -why, and how to fix it. - -To me, it seems best to let systemd handle it. systemd sends SIGTERM, then waits -TimeoutStopSec=xx seconds then sends SIGKILL,s so dont call g_application.Stop() from -ApplicationMessenger as it can not be trusted. save the requested exitcode instead -(that's required for CEC to switch off the tv) and do it from a simple SIGTERM handler instead. - -CEC thread has enough time (5 seconds in xbmc.service) to switch of the TV after receiving OnQuit. -As a side "effect", now guisettings.xml will ALWAYS be saved, even if shutdown / rebooot -is requested externaly (ssh, 3rdparty script). ---- - xbmc/Application.cpp | 10 ++++++++-- - xbmc/Application.h | 1 + - xbmc/ApplicationMessenger.cpp | 6 ++++-- - xbmc/XBApplicationEx.cpp | 1 + - xbmc/XBApplicationEx.h | 1 + - xbmc/main/main.cpp | 15 +++++++++++++++ - 6 files changed, 30 insertions(+), 4 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 7f1b764..4441969 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -3493,11 +3493,18 @@ bool CApplication::Cleanup() - } - } - -+void CApplication::SetExitCode(int exitCode) -+{ -+ // save it for CEC -+ m_ExitCode = exitCode; -+ m_ExitCodeSet = true; -+} -+ - void CApplication::Stop(int exitCode) - { - try - { -- CVariant vExitCode(exitCode); -+ CVariant vExitCode(m_ExitCode); - CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode); - - SaveFileState(true); -@@ -3521,7 +3528,6 @@ void CApplication::Stop(int exitCode) - - m_bStop = true; - m_AppFocused = false; -- m_ExitCode = exitCode; - CLog::Log(LOGNOTICE, "stop all"); - - // cancel any jobs from the jobmanager -diff --git a/xbmc/Application.h b/xbmc/Application.h -index 2243f15..97fb316 100644 ---- a/xbmc/Application.h -+++ b/xbmc/Application.h -@@ -149,6 +149,7 @@ public: - void StartPVRManager(bool bOpenPVRWindow = false); - void StopPVRManager(); - bool IsCurrentThread() const; -+ void SetExitCode(int exitCode); - void Stop(int exitCode); - void RestartApp(); - void UnloadSkin(bool forReload = false); -diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp -index 3524e89..54a15da 100644 ---- a/xbmc/ApplicationMessenger.cpp -+++ b/xbmc/ApplicationMessenger.cpp -@@ -259,13 +259,14 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) - - case TMSG_POWERDOWN: - { -- g_application.Stop(EXITCODE_POWERDOWN); -+ g_application.SetExitCode(EXITCODE_POWERDOWN); - g_powerManager.Powerdown(); - } - break; - - case TMSG_QUIT: - { -+ g_application.SetExitCode(EXITCODE_QUIT); - g_application.Stop(EXITCODE_QUIT); - } - break; -@@ -287,7 +288,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) - case TMSG_RESTART: - case TMSG_RESET: - { -- g_application.Stop(EXITCODE_REBOOT); -+ g_application.SetExitCode(EXITCODE_REBOOT); - g_powerManager.Reboot(); - } - break; -@@ -295,6 +296,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) - case TMSG_RESTARTAPP: - { - #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) -+ g_application.SetExitCode(EXITCODE_RESTARTAPP); - g_application.Stop(EXITCODE_RESTARTAPP); - #endif - } -diff --git a/xbmc/XBApplicationEx.cpp b/xbmc/XBApplicationEx.cpp -index ad6a145..6058938 100644 ---- a/xbmc/XBApplicationEx.cpp -+++ b/xbmc/XBApplicationEx.cpp -@@ -40,6 +40,7 @@ CXBApplicationEx::CXBApplicationEx() - m_bStop = false; - m_AppFocused = true; - m_ExitCode = EXITCODE_QUIT; -+ m_ExitCodeSet = false; - m_renderGUI = false; - } - -diff --git a/xbmc/XBApplicationEx.h b/xbmc/XBApplicationEx.h -index c46cba1..ed3f35f 100644 ---- a/xbmc/XBApplicationEx.h -+++ b/xbmc/XBApplicationEx.h -@@ -40,6 +40,7 @@ public: - // Variables for timing - bool m_bStop; - int m_ExitCode; -+ bool m_ExitCodeSet; - bool m_AppFocused; - bool m_renderGUI; - -diff --git a/xbmc/main/main.cpp b/xbmc/main/main.cpp -index ec86426..ad8fe6e 100644 ---- a/xbmc/main/main.cpp -+++ b/xbmc/main/main.cpp -@@ -40,9 +40,24 @@ - #include "input/linux/LIRC.h" - #endif - #include "XbmcContext.h" -+#include "Application.h" -+ -+void xbmc_term_handler(int signum) -+{ -+ CLog::Log(LOGINFO, "Received SIGTERM..."); -+ if (!g_application.m_ExitCodeSet) -+ g_application.SetExitCode(EXITCODE_RESTARTAPP); -+ g_application.Stop(EXITCODE_RESTARTAPP); -+} - - int main(int argc, char* argv[]) - { -+ // SIGTERM handler -+ struct sigaction action; -+ memset(&action, 0, sizeof(struct sigaction)); -+ action.sa_handler = xbmc_term_handler; -+ sigaction(SIGTERM, &action, NULL); -+ - // set up some xbmc specific relationships - XBMC::Context context; - --- -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 deleted file mode 100644 index 50186d7813..0000000000 --- a/packages/mediacenter/xbmc-master/patches/xbmc-master-999.90-show_rss-setting_in_standard_group.patch +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 882e7d0f0a..0000000000 --- a/packages/mediacenter/xbmc-master/profile.d/02-xbmc.conf +++ /dev/null @@ -1,29 +0,0 @@ -################################################################################ -# 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 deleted file mode 100644 index bdd7525920..0000000000 --- a/packages/mediacenter/xbmc-master/profile.d/03-addons.conf +++ /dev/null @@ -1,40 +0,0 @@ -################################################################################ -# 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 deleted file mode 100755 index 1136827f2d..0000000000 --- a/packages/mediacenter/xbmc-master/scripts/cputemp +++ /dev/null @@ -1,67 +0,0 @@ -#!/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 deleted file mode 100755 index 76aa3d7c26..0000000000 --- a/packages/mediacenter/xbmc-master/scripts/setwakeup.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/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 deleted file mode 100755 index e963c61af9..0000000000 --- a/packages/mediacenter/xbmc-master/scripts/systemd-addon-wrapper +++ /dev/null @@ -1,34 +0,0 @@ -#!/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 deleted file mode 100755 index 1ad05bf38e..0000000000 --- a/packages/mediacenter/xbmc-master/scripts/xbmc-config +++ /dev/null @@ -1,26 +0,0 @@ -#!/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 deleted file mode 100755 index 2fabd47a19..0000000000 --- a/packages/mediacenter/xbmc-master/scripts/xbmc-hacks +++ /dev/null @@ -1,27 +0,0 @@ -#!/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 deleted file mode 100755 index 12fa659a8f..0000000000 --- a/packages/mediacenter/xbmc-master/scripts/xbmc-sources +++ /dev/null @@ -1,85 +0,0 @@ -#!/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 deleted file mode 100755 index e44529791e..0000000000 --- a/packages/mediacenter/xbmc-master/sleep.d.serial/10-addon-sleep.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/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 deleted file mode 100755 index 3ad0e0c04e..0000000000 --- a/packages/mediacenter/xbmc-master/sleep.d.serial/20-custon-sleep.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/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 deleted file mode 100755 index 6b314cd7bd..0000000000 --- a/packages/mediacenter/xbmc-master/sleep.d/openelec-sleep.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/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 deleted file mode 100644 index 6b2897b0a1..0000000000 Binary files a/packages/mediacenter/xbmc-master/splash/splash.png and /dev/null differ diff --git a/packages/mediacenter/xbmc-master/splash/splash1.png b/packages/mediacenter/xbmc-master/splash/splash1.png deleted file mode 100644 index ac0aa0052f..0000000000 Binary files a/packages/mediacenter/xbmc-master/splash/splash1.png and /dev/null differ diff --git a/packages/mediacenter/xbmc-master/system.d/xbmc-autostart.service b/packages/mediacenter/xbmc-master/system.d/xbmc-autostart.service deleted file mode 100644 index 2e98307e0f..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-autostart.service +++ /dev/null @@ -1,13 +0,0 @@ -[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 deleted file mode 100644 index 9faab0eec2..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-cleanlogs.service +++ /dev/null @@ -1,13 +0,0 @@ -[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 deleted file mode 100644 index cb0f33faf8..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-config.service +++ /dev/null @@ -1,12 +0,0 @@ -[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 deleted file mode 100644 index efb48a6ac3..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-hacks.service +++ /dev/null @@ -1,12 +0,0 @@ -[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 deleted file mode 100644 index 16ab30c50e..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-halt.service +++ /dev/null @@ -1,14 +0,0 @@ -[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 deleted file mode 100644 index f229b6b193..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-lirc-suspend.service +++ /dev/null @@ -1,13 +0,0 @@ -[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 deleted file mode 100644 index 8a607da56a..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-poweroff.service +++ /dev/null @@ -1,14 +0,0 @@ -[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 deleted file mode 100644 index 7ee1d5dabe..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-reboot.service +++ /dev/null @@ -1,14 +0,0 @@ -[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 deleted file mode 100644 index 48e6dfb8a7..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-sources.service +++ /dev/null @@ -1,12 +0,0 @@ -[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 deleted file mode 100644 index dc27a793ee..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc-waitonnetwork.service +++ /dev/null @@ -1,17 +0,0 @@ -[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 deleted file mode 100644 index 545d31c62e..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc.service +++ /dev/null @@ -1,21 +0,0 @@ -[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 deleted file mode 100644 index 02e0fc0c82..0000000000 --- a/packages/mediacenter/xbmc-master/system.d/xbmc.target +++ /dev/null @@ -1,9 +0,0 @@ -[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 deleted file mode 100644 index 62552cdc49..0000000000 --- a/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc-userdirs.conf +++ /dev/null @@ -1,24 +0,0 @@ -################################################################################ -# 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 deleted file mode 100644 index 24bcf7a5b7..0000000000 --- a/packages/mediacenter/xbmc-master/tmpfiles.d/xbmc.conf +++ /dev/null @@ -1,19 +0,0 @@ -################################################################################ -# 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/ATV/options b/projects/ATV/options index 5beebc11c5..a71fa07480 100644 --- a/projects/ATV/options +++ b/projects/ATV/options @@ -1,8 +1,5 @@ # Name of the Distro to build (full name, without special characters) DISTRONAME="OpenELEC" - if [ "$XBMC" = master ]; then - DISTRONAME="OpenELEC_Helix" - fi # short project description DESCRIPTION="OpenELEC is a fast and userfriendly XBMC Mediacenter distribution." @@ -119,9 +116,6 @@ # Mediacenter to use (xbmc / no) MEDIACENTER="xbmc" - if [ "$XBMC" = master ]; then - MEDIACENTER="xbmc-master" - fi # Skins to install (Confluence) # Space separated list is supported, diff --git a/projects/Generic/options b/projects/Generic/options index 12bcc590d2..676b19f79f 100644 --- a/projects/Generic/options +++ b/projects/Generic/options @@ -1,8 +1,5 @@ # Name of the Distro to build (full name, without special characters) DISTRONAME="OpenELEC" - if [ "$XBMC" = master ]; then - DISTRONAME="OpenELEC_Helix" - fi # short project description DESCRIPTION="OpenELEC is a fast and userfriendly XBMC Mediacenter distribution." @@ -119,9 +116,6 @@ # Mediacenter to use (xbmc / no) MEDIACENTER="xbmc" - if [ "$XBMC" = master ]; then - MEDIACENTER="xbmc-master" - fi # Skins to install (Confluence) # Space separated list is supported, diff --git a/projects/RPi/options b/projects/RPi/options index 3c743b69ec..4ed0b43394 100644 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -1,8 +1,5 @@ # Name of the Distro to build (full name, without special characters) DISTRONAME="OpenELEC" - if [ "$XBMC" = master ]; then - DISTRONAME="OpenELEC_Helix" - fi # short project description DESCRIPTION="OpenELEC is a fast and userfriendly XBMC Mediacenter distribution." @@ -119,9 +116,6 @@ # Mediacenter to use (xbmc / no) MEDIACENTER="xbmc" - if [ "$XBMC" = master ]; then - MEDIACENTER="xbmc-master" - fi # Skins to install (Confluence) # Space separated list is supported, diff --git a/projects/RPi/patches/xbmc-master/xbmc-master-newclock3.patch b/projects/RPi/patches/xbmc-master/xbmc-master-newclock3.patch deleted file mode 100644 index 4d28fc7311..0000000000 --- a/projects/RPi/patches/xbmc-master/xbmc-master-newclock3.patch +++ /dev/null @@ -1,16213 +0,0 @@ -From 35419e975b9616f614faf987889361755b9a49d9 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Thu, 14 Nov 2013 19:48:41 +0000 -Subject: [PATCH 01/82] More efficient infobool expression evaluator - -Expession infobools are evaluated at runtime from one or more single infobools -and a combination of boolean NOT, AND and OR operators. Previously, parsing -produced a vector of operands (leaf nodes) and operators in postfix -(reverse-Polish) form, and evaluated all leaf nodes every time the expression -was evaluated. But this ignores the fact that in many cases, once one operand -of an AND or OR operation has been evaluated, there is no need to evaluate the -other operand because its value can have no effect on the ultimate result. It -is also worth noting that AND and OR operations are associative, meaning they -can be rearranged at runtime to better suit the selected skin. - -This patch rewrites the expression parsing and evaluation code. Now the -internal repreentation is in the form of a tree where leaf nodes represent a -single infobool, and branch nodes represent either an AND or an OR operation -on two or more child nodes. - -Expressions are rewritten at parse time into a form which favours the -formation of groups of associative nodes. These groups are then reordered at -evaluation time such that nodes whose value renders the evaluation of the -remainder of the group unnecessary tend to be evaluated first (these are -true nodes for OR subexpressions, or false nodes for AND subexpressions). -The end effect is to minimise the number of leaf nodes that need to be -evaluated in order to determine the value of the expression. The runtime -adaptability has the advantage of not being customised for any particular skin. - -The modifications to the expression at parse time fall into two groups: -1) Moving logical NOTs so that they are only applied to leaf nodes. - For example, rewriting ![A+B]|C as !A|!B|C allows reordering such that - any of the three leaves can be evaluated first. -2) Combining adjacent AND or OR operations such that each path from the root - to a leaf encounters a strictly alternating pattern of AND and OR - operations. So [A|B]|[C|D+[[E|F]|G] becomes A|B|C|[D+[E|F|G]]. - -I measured the effect while the Videos window of the default skin was open -(but idle) on a Raspberry Pi, and this reduced the CPU usage by 2.8% from -41.9% to 39.1%: - - Before After - Mean StdDev Mean StdDev Confidence Change -IdleCPU% 41.9 0.5 39.1 0.9 100.0% +7.0% ---- - xbmc/interfaces/info/InfoExpression.cpp | 313 +++++++++++++++++++++----------- - xbmc/interfaces/info/InfoExpression.h | 63 ++++++- - 2 files changed, 269 insertions(+), 107 deletions(-) - -diff --git a/xbmc/interfaces/info/InfoExpression.cpp b/xbmc/interfaces/info/InfoExpression.cpp -index f4d32c1..db461dd 100644 ---- a/xbmc/interfaces/info/InfoExpression.cpp -+++ b/xbmc/interfaces/info/InfoExpression.cpp -@@ -22,6 +22,9 @@ - #include - #include "utils/log.h" - #include "GUIInfoManager.h" -+#include -+#include -+#include - - using namespace std; - using namespace INFO; -@@ -40,21 +43,89 @@ void InfoSingle::Update(const CGUIListItem *item) - InfoExpression::InfoExpression(const std::string &expression, int context) - : InfoBool(expression, context) - { -- Parse(expression); -+ if (!Parse(expression)) -+ CLog::Log(LOGERROR, "Error parsing boolean expression %s", expression.c_str()); - } - - void InfoExpression::Update(const CGUIListItem *item) - { -- Evaluate(item, m_value); -+ m_value = m_expression_tree->Evaluate(item); - } - --#define OPERATOR_LB 5 --#define OPERATOR_RB 4 --#define OPERATOR_NOT 3 --#define OPERATOR_AND 2 --#define OPERATOR_OR 1 -+/* Expressions are rewritten at parse time into a form which favours the -+ * formation of groups of associative nodes. These groups are then reordered at -+ * evaluation time such that nodes whose value renders the evaluation of the -+ * remainder of the group unnecessary tend to be evaluated first (these are -+ * true nodes for OR subexpressions, or false nodes for AND subexpressions). -+ * The end effect is to minimise the number of leaf nodes that need to be -+ * evaluated in order to determine the value of the expression. The runtime -+ * adaptability has the advantage of not being customised for any particular skin. -+ * -+ * The modifications to the expression at parse time fall into two groups: -+ * 1) Moving logical NOTs so that they are only applied to leaf nodes. -+ * For example, rewriting ![A+B]|C as !A|!B|C allows reordering such that -+ * any of the three leaves can be evaluated first. -+ * 2) Combining adjacent AND or OR operations such that each path from the root -+ * to a leaf encounters a strictly alternating pattern of AND and OR -+ * operations. So [A|B]|[C|D+[[E|F]|G] becomes A|B|C|[D+[E|F|G]]. -+ */ -+ -+bool InfoExpression::InfoLeaf::Evaluate(const CGUIListItem *item) -+{ -+ return m_invert ^ m_info->Get(item); -+} - --short InfoExpression::GetOperator(const char ch) const -+InfoExpression::InfoAssociativeGroup::InfoAssociativeGroup( -+ bool and_not_or, -+ const InfoSubexpressionPtr &left, -+ const InfoSubexpressionPtr &right) -+ : m_and_not_or(and_not_or) -+{ -+ AddChild(right); -+ AddChild(left); -+} -+ -+void InfoExpression::InfoAssociativeGroup::AddChild(const InfoSubexpressionPtr &child) -+{ -+ m_children.push_front(child); // largely undoes the effect of parsing right-associative -+} -+ -+void InfoExpression::InfoAssociativeGroup::Merge(InfoAssociativeGroup *other) -+{ -+ m_children.splice(m_children.end(), other->m_children); -+} -+ -+bool InfoExpression::InfoAssociativeGroup::Evaluate(const CGUIListItem *item) -+{ -+ /* Handle either AND or OR by using the relation -+ * A AND B == !(!A OR !B) -+ * to convert ANDs into ORs -+ */ -+ std::list::iterator last = m_children.end(); -+ std::list::iterator it = m_children.begin(); -+ bool result = m_and_not_or ^ (*it)->Evaluate(item); -+ while (!result && ++it != last) -+ { -+ result = m_and_not_or ^ (*it)->Evaluate(item); -+ if (result) -+ { -+ /* Move this child to the head of the list so we evaluate faster next time */ -+ InfoSubexpressionPtr p = *it; -+ m_children.erase(it); -+ m_children.push_front(p); -+ } -+ } -+ return m_and_not_or ^ result; -+} -+ -+/* Expressions are parsed using the shunting-yard algorithm. Binary operators -+ * (AND/OR) are treated as right-associative so that we don't need to make a -+ * special case for the unary NOT operator. This has no effect upon the answers -+ * generated, though the initial sequence of evaluation of leaves may be -+ * different from what you might expect. -+ */ -+ -+InfoExpression::operator_t InfoExpression::GetOperator(char ch) - { - if (ch == '[') - return OPERATOR_LB; -@@ -67,122 +138,160 @@ short InfoExpression::GetOperator(const char ch) const - else if (ch == '|') - return OPERATOR_OR; - else -- return 0; -+ return OPERATOR_NONE; - } - --void InfoExpression::Parse(const std::string &expression) -+void InfoExpression::OperatorPop(std::stack &operator_stack, bool &invert, std::stack &node_types, std::stack &nodes) - { -- stack operators; -- std::string operand; -- for (unsigned int i = 0; i < expression.size(); i++) -+ operator_t op2 = operator_stack.top(); -+ operator_stack.pop(); -+ if (op2 == OPERATOR_NOT) - { -- if (GetOperator(expression[i])) -+ invert = !invert; -+ } -+ else -+ { -+ // At this point, it can only be OPERATOR_AND or OPERATOR_OR -+ if (invert) -+ op2 = (operator_t) (OPERATOR_AND ^ OPERATOR_OR ^ op2); -+ node_type_t new_type = op2 == OPERATOR_AND ? NODE_AND : NODE_OR; -+ -+ InfoSubexpressionPtr right = nodes.top(); -+ nodes.pop(); -+ InfoSubexpressionPtr left = nodes.top(); -+ -+ node_type_t right_type = node_types.top(); -+ node_types.pop(); -+ node_type_t left_type = node_types.top(); -+ -+ // Combine associative operations into the same node where possible -+ if (left_type == new_type && right_type == new_type) -+ (static_cast(left.get()))->Merge(static_cast(right.get())); -+ else if (left_type == new_type) -+ (static_cast(left.get()))->AddChild(right); -+ else - { -- // cleanup any operand, translate and put into our expression list -- if (!operand.empty()) -+ nodes.pop(); -+ node_types.pop(); -+ if (right_type == new_type) - { -- InfoPtr info = g_infoManager.Register(operand, m_context); -- if (info) -- { -- m_listItemDependent |= info->ListItemDependent(); -- m_postfix.push_back(m_operands.size()); -- m_operands.push_back(info); -- } -- operand.clear(); -+ (static_cast(right.get()))->AddChild(left); -+ nodes.push(right); - } -- // handle closing parenthesis -- if (expression[i] == ']') -- { -- while (!operators.empty()) -- { -- char oper = operators.top(); -- operators.pop(); -+ else -+ nodes.push(boost::make_shared(new_type == NODE_AND, left, right)); -+ node_types.push(new_type); -+ } -+ } -+} -+ -+void InfoExpression::ProcessOperator(operator_t op, std::stack &operator_stack, bool &invert, std::stack &node_types, std::stack &nodes) -+{ -+ // Handle any higher-priority stacked operators, except when the new operator is left-bracket. -+ // For a right-bracket, this will stop with the matching left-bracket at the top of the operator stack. -+ if (op != OPERATOR_LB) -+ { -+ while (operator_stack.size() > 0 && operator_stack.top() > op) -+ OperatorPop(operator_stack, invert, node_types, nodes); -+ } -+ if (op == OPERATOR_RB) -+ operator_stack.pop(); // remove the matching left-bracket -+ else -+ operator_stack.push(op); -+ if (op == OPERATOR_NOT) -+ invert = !invert; -+} - -- if (oper == '[') -- break; -+bool InfoExpression::ProcessOperand(std::string &operand, bool invert, std::stack &node_types, std::stack &nodes) -+{ -+ InfoPtr info = g_infoManager.Register(operand, m_context); -+ if (!info) -+ return false; -+ m_listItemDependent |= info->ListItemDependent(); -+ nodes.push(boost::make_shared(info, invert)); -+ node_types.push(NODE_LEAF); -+ operand.clear(); -+ return true; -+} - -- m_postfix.push_back(-GetOperator(oper)); // negative denotes operator -- } -+bool InfoExpression::Parse(const std::string &expression) -+{ -+ const char *s = expression.c_str(); -+ std::string operand; -+ std::stack operator_stack; -+ bool invert = false; -+ std::stack node_types; -+ std::stack nodes; -+ // The next two are for syntax-checking purposes -+ bool after_binaryoperator = true; -+ int bracket_count = 0; -+ -+ char c; -+ // Skip leading whitespace - don't want it to count as an operand if that's all there is -+ do -+ { -+ c = *s++; -+ } while (c == ' ' || c == '\t' || c == '\r' || c == '\n'); -+ s--; -+ while ((c = *s++) != '\0') -+ { -+ operator_t op; -+ if ((op = GetOperator(c)) != OPERATOR_NONE) -+ { -+ // Character is an operator -+ if ((!after_binaryoperator && (c == '!' || c == '[')) || -+ (after_binaryoperator && (c == ']' || c == '+' || c == '|'))) -+ { -+ CLog::Log(LOGERROR, "Misplaced %c", c); -+ return false; - } -- else -+ if (c == '[') -+ bracket_count++; -+ else if (c == ']' && bracket_count-- == 0) -+ { -+ CLog::Log(LOGERROR, "Unmatched ]"); -+ return false; -+ } -+ if (operand.size() > 0 && !ProcessOperand(operand, invert, node_types, nodes)) - { -- // all other operators we pop off the stack any operator -- // that has a higher priority than the one we have. -- while (!operators.empty() && GetOperator(operators.top()) > GetOperator(expression[i])) -- { -- // only handle parenthesis once they're closed. -- if (operators.top() == '[' && expression[i] != ']') -- break; -- -- m_postfix.push_back(-GetOperator(operators.top())); // negative denotes operator -- operators.pop(); -- } -- operators.push(expression[i]); -+ CLog::Log(LOGERROR, "Bad operand '%s'", operand.c_str()); -+ return false; - } -+ ProcessOperator(op, operator_stack, invert, node_types, nodes); -+ if (c == '+' || c == '|') -+ after_binaryoperator = true; -+ // Skip trailing whitespace - don't want it to count as an operand if that's all there is -+ do -+ { -+ c = *s++; -+ } while (c == ' ' || c == '\t' || c == '\r' || c == '\n'); -+ s--; - } - else - { -- operand += expression[i]; -+ // Character is part of operand -+ operand += c; -+ after_binaryoperator = false; - } - } -- -- if (!operand.empty()) -+ if (bracket_count > 0) - { -- InfoPtr info = g_infoManager.Register(operand, m_context); -- if (info) -- { -- m_listItemDependent |= info->ListItemDependent(); -- m_postfix.push_back(m_operands.size()); -- m_operands.push_back(info); -- } -+ CLog::Log(LOGERROR, "Unmatched ["); -+ return false; - } -- -- // finish up by adding any operators -- while (!operators.empty()) -+ if (after_binaryoperator) - { -- m_postfix.push_back(-GetOperator(operators.top())); // negative denotes operator -- operators.pop(); -+ CLog::Log(LOGERROR, "Missing operand"); -+ return false; - } -- -- // test evaluate -- bool test; -- if (!Evaluate(NULL, test)) -- CLog::Log(LOGERROR, "Error evaluating boolean expression %s", expression.c_str()); --} -- --bool InfoExpression::Evaluate(const CGUIListItem *item, bool &result) --{ -- stack save; -- for (vector::const_iterator it = m_postfix.begin(); it != m_postfix.end(); ++it) -+ if (operand.size() > 0 && !ProcessOperand(operand, invert, node_types, nodes)) - { -- short expr = *it; -- if (expr == -OPERATOR_NOT) -- { // NOT the top item on the stack -- if (save.empty()) return false; -- bool expr = save.top(); -- save.pop(); -- save.push(!expr); -- } -- else if (expr == -OPERATOR_AND) -- { // AND the top two items on the stack -- if (save.size() < 2) return false; -- bool right = save.top(); save.pop(); -- bool left = save.top(); save.pop(); -- save.push(left && right); -- } -- else if (expr == -OPERATOR_OR) -- { // OR the top two items on the stack -- if (save.size() < 2) return false; -- bool right = save.top(); save.pop(); -- bool left = save.top(); save.pop(); -- save.push(left || right); -- } -- else if (expr >= 0) // operand -- save.push(m_operands[expr]->Get(item)); -- } -- if (save.size() != 1) -+ CLog::Log(LOGERROR, "Bad operand '%s'", operand.c_str()); - return false; -- result = save.top(); -+ } -+ while (operator_stack.size() > 0) -+ OperatorPop(operator_stack, invert, node_types, nodes); -+ -+ m_expression_tree = nodes.top(); - return true; - } -- -diff --git a/xbmc/interfaces/info/InfoExpression.h b/xbmc/interfaces/info/InfoExpression.h -index 4e0faee..0a91399 100644 ---- a/xbmc/interfaces/info/InfoExpression.h -+++ b/xbmc/interfaces/info/InfoExpression.h -@@ -21,6 +21,8 @@ - #pragma once - - #include -+#include -+#include - #include "InfoBool.h" - - class CGUIListItem; -@@ -50,12 +52,63 @@ class InfoExpression : public InfoBool - - virtual void Update(const CGUIListItem *item); - private: -- void Parse(const std::string &expression); -- bool Evaluate(const CGUIListItem *item, bool &result); -- short GetOperator(const char ch) const; -+ typedef enum -+ { -+ OPERATOR_NONE = 0, -+ OPERATOR_LB, // 1 -+ OPERATOR_RB, // 2 -+ OPERATOR_OR, // 3 -+ OPERATOR_AND, // 4 -+ OPERATOR_NOT, // 5 -+ } operator_t; - -- std::vector m_postfix; ///< the postfix form of the expression (operators and operand indicies) -- std::vector m_operands; ///< the operands in the expression -+ typedef enum -+ { -+ NODE_LEAF, -+ NODE_AND, -+ NODE_OR, -+ } node_type_t; -+ -+ // An abstract base class for nodes in the expression tree -+ class InfoSubexpression -+ { -+ public: -+ virtual ~InfoSubexpression(void) {}; // so we can destruct derived classes using a pointer to their base class -+ virtual bool Evaluate(const CGUIListItem *item) = 0; -+ }; -+ -+ typedef boost::shared_ptr InfoSubexpressionPtr; -+ -+ // A leaf node in the expression tree -+ class InfoLeaf : public InfoSubexpression -+ { -+ public: -+ InfoLeaf(InfoPtr info, bool invert) : m_info(info), m_invert(invert) {}; -+ virtual bool Evaluate(const CGUIListItem *item); -+ private: -+ InfoPtr m_info; -+ bool m_invert; -+ }; -+ -+ // A branch node in the expression tree -+ class InfoAssociativeGroup : public InfoSubexpression -+ { -+ public: -+ InfoAssociativeGroup(bool and_not_or, const InfoSubexpressionPtr &left, const InfoSubexpressionPtr &right); -+ void AddChild(const InfoSubexpressionPtr &child); -+ void Merge(InfoAssociativeGroup *other); -+ virtual bool Evaluate(const CGUIListItem *item); -+ private: -+ bool m_and_not_or; -+ std::list m_children; -+ }; -+ -+ static operator_t GetOperator(char ch); -+ static void OperatorPop(std::stack &operator_stack, bool &invert, std::stack &node_types, std::stack &nodes); -+ static void ProcessOperator(operator_t op, std::stack &operator_stack, bool &invert, std::stack &node_types, std::stack &nodes); -+ bool ProcessOperand(std::string &operand, bool invert, std::stack &node_types, std::stack &nodes); -+ bool Parse(const std::string &expression); -+ InfoSubexpressionPtr m_expression_tree; - }; - - }; --- -1.9.3 - - -From 3ea2259e88b2b1b5036b6db81ec7b16bf505497f Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Mon, 24 Mar 2014 22:26:21 +0000 -Subject: [PATCH 02/82] Where an infobool expression failed to parse, evaluate - the infobool as false. Previously, this would result in a segfault due to the - dereferencing of an uninitialised pointer to the head of the expression tree. - ---- - xbmc/interfaces/info/InfoExpression.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/xbmc/interfaces/info/InfoExpression.cpp b/xbmc/interfaces/info/InfoExpression.cpp -index db461dd..7c54064 100644 ---- a/xbmc/interfaces/info/InfoExpression.cpp -+++ b/xbmc/interfaces/info/InfoExpression.cpp -@@ -44,7 +44,10 @@ InfoExpression::InfoExpression(const std::string &expression, int context) - : InfoBool(expression, context) - { - if (!Parse(expression)) -+ { - CLog::Log(LOGERROR, "Error parsing boolean expression %s", expression.c_str()); -+ m_expression_tree = boost::make_shared(g_infoManager.Register("false", 0), false); -+ } - } - - void InfoExpression::Update(const CGUIListItem *item) --- -1.9.3 - - -From 89f7abbd454aa88156ba54da164bde33992f7d5b Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 26 Nov 2013 20:09:48 +0000 -Subject: [PATCH 03/82] Add caching of infolabels - -The functions CGUIInfoLabel::GetLabel and CGUIInfoLabel::GetItemLabel take -a number of strings returned from CGUIInfoManager::GetImage or -CGUIInfoManager::GetLabel, and combine them with various constant strings -which were determined during CGUIInfoLabel::Parse. - -Rather than perform all the string operations on every call, this patch -changes to use a two-pass process: first it queries all the GetImage/GetLabel -strings, and then only if at least one of them has changed does it bother -rebuilding the resultant string - otherwise it re-uses the copy built on a -preceding call. - -CGUIInfoLabel::GetLabel/GetItemLabel are also changed to return string -references, rather than forcing an additional string copy. - -I have measured the effect while the Videos window of the default skin was -open (but idle) on a Raspberry Pi, and this reduced the CPU usage by 0.8% -from 36.2% to 35.4%: - - Before After - Mean StdDev Mean StdDev Confidence Change -IdleCPU% 36.2 0.5 35.4 0.5 99.9% +2.2% ---- - xbmc/guilib/GUIInfoTypes.cpp | 102 +++++++++++++++++++++++++++++++++---------- - xbmc/guilib/GUIInfoTypes.h | 11 ++++- - 2 files changed, 87 insertions(+), 26 deletions(-) - -diff --git a/xbmc/guilib/GUIInfoTypes.cpp b/xbmc/guilib/GUIInfoTypes.cpp -index 6977e0f..d78c26a 100644 ---- a/xbmc/guilib/GUIInfoTypes.cpp -+++ b/xbmc/guilib/GUIInfoTypes.cpp -@@ -136,37 +136,64 @@ void CGUIInfoLabel::SetLabel(const CStdString &label, const CStdString &fallback - Parse(label, context); - } - --CStdString CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdString *fallback /*= NULL*/) const -+const std::string &CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdString *fallback /*= NULL*/) const - { -- CStdString label; -- for (unsigned int i = 0; i < m_info.size(); i++) -+ for (unsigned int i = 0, j = 0; i < m_info.size(); i++) - { - const CInfoPortion &portion = m_info[i]; - if (portion.m_info) - { -- CStdString infoLabel; -+ std::string infoLabel; - if (preferImage) - infoLabel = g_infoManager.GetImage(portion.m_info, contextWindow, fallback); - if (infoLabel.empty()) - infoLabel = g_infoManager.GetLabel(portion.m_info, contextWindow, fallback); -- if (!infoLabel.empty()) -- label += portion.GetLabel(infoLabel); -+ if (j == m_labelPortions.size()) -+ m_labelPortions.push_back(infoLabel); -+ else if (infoLabel != m_labelPortions[j]) -+ { -+ m_labelPortions[j] = infoLabel; -+ m_labelDirty = true; -+ } -+ j++; - } -- else -- { // no info, so just append the prefix -- label += portion.m_prefix; -+ } -+ if (m_labelDirty) -+ { -+ m_label.clear(); -+ for (unsigned int i = 0, j= 0; i < m_info.size(); i++) -+ { -+ const CInfoPortion &portion = m_info[i]; -+ if (portion.m_info) -+ { -+ if (!m_labelPortions[j].empty()) -+ m_label += portion.GetLabel(m_labelPortions[j]); -+ j++; -+ } -+ else -+ { // no info, so just append the prefix -+ m_label += portion.m_prefix; -+ } - } -+ if (m_label.empty()) // empty label, use the fallback -+ m_label = m_fallback; -+ m_labelDirty = false; - } -- if (label.empty()) // empty label, use the fallback -- return m_fallback; -- return label; -+ return m_label; - } - --CStdString CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, CStdString *fallback /*= NULL*/) const -+const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, CStdString *fallback /*= NULL*/) const - { -- if (!item->IsFileItem()) return ""; -- CStdString label; -- for (unsigned int i = 0; i < m_info.size(); i++) -+ if (!item->IsFileItem()) -+ { -+ if (m_itemLabelDirty) -+ { -+ m_itemLabel = ""; -+ m_itemLabelDirty = false; -+ } -+ return m_itemLabel; -+ } -+ for (unsigned int i = 0, j = 0; i < m_info.size(); i++) - { - const CInfoPortion &portion = m_info[i]; - if (portion.m_info) -@@ -176,17 +203,38 @@ CStdString CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImag - infoLabel = g_infoManager.GetItemImage((const CFileItem *)item, portion.m_info, fallback); - else - infoLabel = g_infoManager.GetItemLabel((const CFileItem *)item, portion.m_info, fallback); -- if (!infoLabel.empty()) -- label += portion.GetLabel(infoLabel); -+ if (j == m_itemLabelPortions.size()) -+ m_itemLabelPortions.push_back(infoLabel); -+ else if (infoLabel != m_itemLabelPortions[j]) -+ { -+ m_itemLabelPortions[j] = infoLabel; -+ m_itemLabelDirty = true; -+ } -+ j++; - } -- else -- { // no info, so just append the prefix -- label += portion.m_prefix; -+ } -+ if (m_itemLabelDirty) -+ { -+ m_itemLabel.clear(); -+ for (unsigned int i = 0, j = 0; i < m_info.size(); i++) -+ { -+ const CInfoPortion &portion = m_info[i]; -+ if (portion.m_info) -+ { -+ if (!m_itemLabelPortions[j].empty()) -+ m_itemLabel += portion.GetLabel(m_itemLabelPortions[j]); -+ j++; -+ } -+ else -+ { // no info, so just append the prefix -+ m_itemLabel += portion.m_prefix; -+ } - } -+ if (m_itemLabel.empty()) -+ m_itemLabel = m_fallback; -+ m_itemLabelDirty = false; - } -- if (label.empty()) -- return m_fallback; -- return label; -+ return m_itemLabel; - } - - bool CGUIInfoLabel::IsEmpty() const -@@ -277,6 +325,12 @@ const static infoformat infoformatmap[] = {{ "$INFO[", FORMATINFO }, - void CGUIInfoLabel::Parse(const CStdString &label, int context) - { - m_info.clear(); -+ m_labelDirty = true; -+ m_label.clear(); -+ m_labelPortions.clear(); -+ m_itemLabelDirty = true; -+ m_itemLabel.clear(); -+ m_itemLabelPortions.clear(); - // Step 1: Replace all $LOCALIZE[number] with the real string - CStdString work = ReplaceLocalize(label); - // Step 2: Replace all $ADDON[id number] with the real string -diff --git a/xbmc/guilib/GUIInfoTypes.h b/xbmc/guilib/GUIInfoTypes.h -index 8c1c1dc..418b2c4 100644 ---- a/xbmc/guilib/GUIInfoTypes.h -+++ b/xbmc/guilib/GUIInfoTypes.h -@@ -83,7 +83,7 @@ class CGUIInfoLabel - \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL. - \return label (or image). - */ -- CStdString GetLabel(int contextWindow, bool preferImage = false, CStdString *fallback = NULL) const; -+ const std::string &GetLabel(int contextWindow, bool preferImage = false, CStdString *fallback = NULL) const; - - /*! - \brief Gets a label (or image) for a given listitem from the info manager. -@@ -92,7 +92,7 @@ class CGUIInfoLabel - \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL. - \return label (or image). - */ -- CStdString GetItemLabel(const CGUIListItem *item, bool preferImage = false, CStdString *fallback = NULL) const; -+ const std::string &GetItemLabel(const CGUIListItem *item, bool preferImage = false, CStdString *fallback = NULL) const; - - bool IsConstant() const; - bool IsEmpty() const; -@@ -132,6 +132,13 @@ class CGUIInfoLabel - - CStdString m_fallback; - std::vector m_info; -+ -+ mutable bool m_labelDirty; -+ mutable std::string m_label; -+ mutable std::vector m_labelPortions; -+ mutable bool m_itemLabelDirty; -+ mutable std::string m_itemLabel; -+ mutable std::vector m_itemLabelPortions; - }; - - #endif --- -1.9.3 - - -From 431ad06ca8c0299645f6fc79a6960199589748c7 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 10 Dec 2013 01:12:31 +0000 -Subject: [PATCH 04/82] De-duplication of string cache for non-item and item - labels - ---- - xbmc/guilib/GUIInfoTypes.cpp | 50 +++++++++++++++++++++++++------------------- - xbmc/guilib/GUIInfoTypes.h | 4 +--- - 2 files changed, 29 insertions(+), 25 deletions(-) - -diff --git a/xbmc/guilib/GUIInfoTypes.cpp b/xbmc/guilib/GUIInfoTypes.cpp -index d78c26a..8bd131f 100644 ---- a/xbmc/guilib/GUIInfoTypes.cpp -+++ b/xbmc/guilib/GUIInfoTypes.cpp -@@ -121,7 +121,7 @@ void CGUIInfoColor::Parse(const CStdString &label, int context) - m_color = g_colorManager.GetColor(label); - } - --CGUIInfoLabel::CGUIInfoLabel() -+CGUIInfoLabel::CGUIInfoLabel() : m_labelDirty(true) - { - } - -@@ -178,7 +178,10 @@ const std::string &CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, - if (m_label.empty()) // empty label, use the fallback - m_label = m_fallback; - m_labelDirty = false; -+ m_isLabelOfListItem = false; - } -+ else -+ assert(m_isLabelOfListItem == false); - return m_label; - } - -@@ -186,12 +189,15 @@ const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool pr - { - if (!item->IsFileItem()) - { -- if (m_itemLabelDirty) -+ if (m_labelDirty) - { -- m_itemLabel = ""; -- m_itemLabelDirty = false; -+ m_label = ""; -+ m_labelDirty = false; -+ m_isLabelOfListItem = true; - } -- return m_itemLabel; -+ else -+ assert(m_isLabelOfListItem == true); -+ return m_label; - } - for (unsigned int i = 0, j = 0; i < m_info.size(); i++) - { -@@ -203,38 +209,41 @@ const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool pr - infoLabel = g_infoManager.GetItemImage((const CFileItem *)item, portion.m_info, fallback); - else - infoLabel = g_infoManager.GetItemLabel((const CFileItem *)item, portion.m_info, fallback); -- if (j == m_itemLabelPortions.size()) -- m_itemLabelPortions.push_back(infoLabel); -- else if (infoLabel != m_itemLabelPortions[j]) -+ if (j == m_labelPortions.size()) -+ m_labelPortions.push_back(infoLabel); -+ else if (infoLabel != m_labelPortions[j]) - { -- m_itemLabelPortions[j] = infoLabel; -- m_itemLabelDirty = true; -+ m_labelPortions[j] = infoLabel; -+ m_labelDirty = true; - } - j++; - } - } -- if (m_itemLabelDirty) -+ if (m_labelDirty) - { -- m_itemLabel.clear(); -+ m_label.clear(); - for (unsigned int i = 0, j = 0; i < m_info.size(); i++) - { - const CInfoPortion &portion = m_info[i]; - if (portion.m_info) - { -- if (!m_itemLabelPortions[j].empty()) -- m_itemLabel += portion.GetLabel(m_itemLabelPortions[j]); -+ if (!m_labelPortions[j].empty()) -+ m_label += portion.GetLabel(m_labelPortions[j]); - j++; - } - else - { // no info, so just append the prefix -- m_itemLabel += portion.m_prefix; -+ m_label += portion.m_prefix; - } - } -- if (m_itemLabel.empty()) -- m_itemLabel = m_fallback; -- m_itemLabelDirty = false; -+ if (m_label.empty()) -+ m_label = m_fallback; -+ m_labelDirty = false; -+ m_isLabelOfListItem = true; - } -- return m_itemLabel; -+ else -+ assert(m_isLabelOfListItem == true); -+ return m_label; - } - - bool CGUIInfoLabel::IsEmpty() const -@@ -328,9 +337,6 @@ void CGUIInfoLabel::Parse(const CStdString &label, int context) - m_labelDirty = true; - m_label.clear(); - m_labelPortions.clear(); -- m_itemLabelDirty = true; -- m_itemLabel.clear(); -- m_itemLabelPortions.clear(); - // Step 1: Replace all $LOCALIZE[number] with the real string - CStdString work = ReplaceLocalize(label); - // Step 2: Replace all $ADDON[id number] with the real string -diff --git a/xbmc/guilib/GUIInfoTypes.h b/xbmc/guilib/GUIInfoTypes.h -index 418b2c4..6d9ebf7 100644 ---- a/xbmc/guilib/GUIInfoTypes.h -+++ b/xbmc/guilib/GUIInfoTypes.h -@@ -133,12 +133,10 @@ class CGUIInfoLabel - CStdString m_fallback; - std::vector m_info; - -+ mutable bool m_isLabelOfListItem; - mutable bool m_labelDirty; - mutable std::string m_label; - mutable std::vector m_labelPortions; -- mutable bool m_itemLabelDirty; -- mutable std::string m_itemLabel; -- mutable std::vector m_itemLabelPortions; - }; - - #endif --- -1.9.3 - - -From aac04a3876e7a79c126cc55f52d64ecfa6820c3b Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 11 Dec 2013 17:21:54 +0000 -Subject: [PATCH 05/82] Move the reference-counting of Begin and End calls from - DX and GL source files into GUIFontTTF.cpp. - ---- - xbmc/guilib/GUIFontTTF.cpp | 21 ++++++++ - xbmc/guilib/GUIFontTTF.h | 6 ++- - xbmc/guilib/GUIFontTTFDX.cpp | 79 +++++++++++++---------------- - xbmc/guilib/GUIFontTTFDX.h | 4 +- - xbmc/guilib/GUIFontTTFGL.cpp | 118 +++++++++++++++++++------------------------ - xbmc/guilib/GUIFontTTFGL.h | 4 +- - 6 files changed, 117 insertions(+), 115 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 9c8e516..90b9c4a 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -309,6 +309,27 @@ bool CGUIFontTTFBase::Load(const CStdString& strFilename, float height, float as - return true; - } - -+void CGUIFontTTFBase::Begin() -+{ -+ if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin()) -+ { -+ m_vertex_count = 0; -+ } -+ // Keep track of the nested begin/end calls. -+ m_nestedBeginCount++; -+} -+ -+void CGUIFontTTFBase::End() -+{ -+ if (m_nestedBeginCount == 0) -+ return; -+ -+ if (--m_nestedBeginCount > 0) -+ return; -+ -+ LastEnd(); -+} -+ - void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors, const vecText &text, uint32_t alignment, float maxPixelWidth, bool scrolling) - { - Begin(); -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index 9723a43..c1c4507 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -77,8 +77,8 @@ class CGUIFontTTFBase - - bool Load(const CStdString& strFilename, float height = 20.0f, float aspect = 1.0f, float lineSpacing = 1.0f, bool border = false); - -- virtual void Begin() = 0; -- virtual void End() = 0; -+ void Begin(); -+ void End(); - - const CStdString& GetFileName() const { return m_strFileName; }; - -@@ -169,6 +169,8 @@ class CGUIFontTTFBase - CStdString m_strFileName; - - private: -+ virtual bool FirstBegin() = 0; -+ virtual void LastEnd() = 0; - CGUIFontTTFBase(const CGUIFontTTFBase&); - CGUIFontTTFBase& operator=(const CGUIFontTTFBase&); - int m_referenceCount; -diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp -index e3eba24..2f90668 100644 ---- a/xbmc/guilib/GUIFontTTFDX.cpp -+++ b/xbmc/guilib/GUIFontTTFDX.cpp -@@ -51,65 +51,56 @@ CGUIFontTTFDX::~CGUIFontTTFDX(void) - free(m_index); - } - --void CGUIFontTTFDX::Begin() -+bool CGUIFontTTFDX::FirstBegin() - { - LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); - - if (pD3DDevice == NULL) -+ { - CLog::Log(LOGERROR, __FUNCTION__" - failed to get Direct3D device"); -+ return false; -+ } - -- if (m_nestedBeginCount == 0 && pD3DDevice != NULL && m_texture != NULL) -+ int unit = 0; -+ // just have to blit from our texture. -+ m_texture->BindToUnit(unit); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); // only use diffuse -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_DIFFUSE); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); -+ unit++; -+ -+ if(g_Windowing.UseLimitedColor()) - { -- int unit = 0; -- // just have to blit from our texture. -- m_texture->BindToUnit(unit); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); // only use diffuse -- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_DIFFUSE); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP , D3DTOP_ADD ); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_CURRENT) ; -+ pD3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(16,16,16,0) ); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG2, D3DTA_TFACTOR ); - unit++; -- -- if(g_Windowing.UseLimitedColor()) -- { -- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP , D3DTOP_ADD ); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_CURRENT) ; -- pD3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(16,16,16,0) ); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG2, D3DTA_TFACTOR ); -- unit++; -- } -- -- // no other texture stages needed -- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_DISABLE); -- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_DISABLE); -- -- pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); -- pD3DDevice->SetRenderState( D3DRS_FOGENABLE, FALSE ); -- pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); -- pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); -- pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); -- pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); -- pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); -- pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE); -- -- pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); -- m_vertex_count = 0; - } - -- // Keep track of the nested begin/end calls. -- m_nestedBeginCount++; -+ // no other texture stages needed -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_DISABLE); -+ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_DISABLE); -+ -+ pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); -+ pD3DDevice->SetRenderState( D3DRS_FOGENABLE, FALSE ); -+ pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); -+ pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); -+ pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); -+ pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); -+ pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); -+ pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE); -+ -+ pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); -+ return true; - } - --void CGUIFontTTFDX::End() -+void CGUIFontTTFDX::LastEnd() - { - LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); - -- if (m_nestedBeginCount == 0) -- return; -- -- if (--m_nestedBeginCount > 0) -- return; -- - if (m_vertex_count == 0) - return; - -diff --git a/xbmc/guilib/GUIFontTTFDX.h b/xbmc/guilib/GUIFontTTFDX.h -index 0431085..17dfefe 100644 ---- a/xbmc/guilib/GUIFontTTFDX.h -+++ b/xbmc/guilib/GUIFontTTFDX.h -@@ -41,8 +41,8 @@ class CGUIFontTTFDX : public CGUIFontTTFBase - CGUIFontTTFDX(const CStdString& strFileName); - virtual ~CGUIFontTTFDX(void); - -- virtual void Begin(); -- virtual void End(); -+ virtual bool FirstBegin(); -+ virtual void LastEnd(); - - protected: - virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index 3358a5a..93b7ea6 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -50,90 +50,78 @@ CGUIFontTTFGL::~CGUIFontTTFGL(void) - { - } - --void CGUIFontTTFGL::Begin() -+bool CGUIFontTTFGL::FirstBegin() - { -- if (m_nestedBeginCount == 0 && m_texture != NULL) -+ if (!m_bTextureLoaded) - { -- if (!m_bTextureLoaded) -- { -- // Have OpenGL generate a texture object handle for us -- glGenTextures(1, (GLuint*) &m_nTexture); -+ // Have OpenGL generate a texture object handle for us -+ glGenTextures(1, (GLuint*) &m_nTexture); - -- // Bind the texture object -- glBindTexture(GL_TEXTURE_2D, m_nTexture); -+ // Bind the texture object -+ glBindTexture(GL_TEXTURE_2D, m_nTexture); - #ifdef HAS_GL -- glEnable(GL_TEXTURE_2D); -+ glEnable(GL_TEXTURE_2D); - #endif -- // Set the texture's stretching properties -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ // Set the texture's stretching properties -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - -- // Set the texture image -- THIS WORKS, so the pixels must be wrong. -- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_texture->GetWidth(), m_texture->GetHeight(), 0, -- GL_ALPHA, GL_UNSIGNED_BYTE, m_texture->GetPixels()); -+ // Set the texture image -- THIS WORKS, so the pixels must be wrong. -+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_texture->GetWidth(), m_texture->GetHeight(), 0, -+ GL_ALPHA, GL_UNSIGNED_BYTE, m_texture->GetPixels()); - -- VerifyGLState(); -- m_bTextureLoaded = true; -- } -+ VerifyGLState(); -+ m_bTextureLoaded = true; -+ } - -- // Turn Blending On -- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE); -- glEnable(GL_BLEND); -+ // Turn Blending On -+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE); -+ glEnable(GL_BLEND); - #ifdef HAS_GL -- glEnable(GL_TEXTURE_2D); -+ glEnable(GL_TEXTURE_2D); - #endif -- glBindTexture(GL_TEXTURE_2D, m_nTexture); -+ glBindTexture(GL_TEXTURE_2D, m_nTexture); - - #ifdef HAS_GL -- glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE); -- glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE); -- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); -- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); -- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); -- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0); -- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); -- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR); -- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); -- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -- VerifyGLState(); -+ glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE); -+ glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE); -+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); -+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); -+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); -+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0); -+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); -+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR); -+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); -+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -+ VerifyGLState(); -+ -+ if(g_Windowing.UseLimitedColor()) -+ { -+ glActiveTexture(GL_TEXTURE1); -+ glBindTexture(GL_TEXTURE_2D, m_nTexture); // dummy bind -+ glEnable(GL_TEXTURE_2D); - -- if(g_Windowing.UseLimitedColor()) -- { -- glActiveTexture(GL_TEXTURE1); -- glBindTexture(GL_TEXTURE_2D, m_nTexture); // dummy bind -- glEnable(GL_TEXTURE_2D); -- -- const GLfloat rgba[4] = {16.0f / 255.0f, 16.0f / 255.0f, 16.0f / 255.0f, 0.0f}; -- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_COMBINE); -- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba); -- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB , GL_ADD); -- glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB , GL_PREVIOUS); -- glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB , GL_CONSTANT); -- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB , GL_SRC_COLOR); -- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB , GL_SRC_COLOR); -- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA , GL_REPLACE); -- glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA , GL_PREVIOUS); -- VerifyGLState(); -- } -+ const GLfloat rgba[4] = {16.0f / 255.0f, 16.0f / 255.0f, 16.0f / 255.0f, 0.0f}; -+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_COMBINE); -+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba); -+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB , GL_ADD); -+ glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB , GL_PREVIOUS); -+ glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB , GL_CONSTANT); -+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB , GL_SRC_COLOR); -+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB , GL_SRC_COLOR); -+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA , GL_REPLACE); -+ glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA , GL_PREVIOUS); -+ VerifyGLState(); -+ } - - #else -- g_Windowing.EnableGUIShader(SM_FONTS); -+ g_Windowing.EnableGUIShader(SM_FONTS); - #endif -- -- m_vertex_count = 0; -- } -- // Keep track of the nested begin/end calls. -- m_nestedBeginCount++; -+ return true; - } - --void CGUIFontTTFGL::End() -+void CGUIFontTTFGL::LastEnd() - { -- if (m_nestedBeginCount == 0) -- return; -- -- if (--m_nestedBeginCount > 0) -- return; -- - #ifdef HAS_GL - glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); - -diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h -index a0dacba..6736cf7 100644 ---- a/xbmc/guilib/GUIFontTTFGL.h -+++ b/xbmc/guilib/GUIFontTTFGL.h -@@ -41,8 +41,8 @@ class CGUIFontTTFGL : public CGUIFontTTFBase - CGUIFontTTFGL(const CStdString& strFileName); - virtual ~CGUIFontTTFGL(void); - -- virtual void Begin(); -- virtual void End(); -+ virtual bool FirstBegin(); -+ virtual void LastEnd(); - - protected: - virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); --- -1.9.3 - - -From 0bc34394428f3d54a73e4e2e5c6b0daf2f157a60 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 11 Dec 2013 18:47:54 +0000 -Subject: [PATCH 06/82] Convert CGUIFontTTFBase::m_vertex to be managed as a - std::vector. Also retired CGUIFontTTFBase::m_vertex_count and - CGUIFontTTFBase::m_vertex_size because these can be derived from vector - member functions. - ---- - xbmc/guilib/GUIFontTTF.cpp | 29 +++++------------------------ - xbmc/guilib/GUIFontTTF.h | 4 +--- - xbmc/guilib/GUIFontTTFDX.cpp | 12 ++++++------ - xbmc/guilib/GUIFontTTFGL.cpp | 12 ++++++------ - 4 files changed, 18 insertions(+), 39 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 90b9c4a..3f219d9 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -139,8 +139,7 @@ CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) - m_nestedBeginCount = 0; - - m_bTextureLoaded = false; -- m_vertex_size = 4*1024; -- m_vertex = (SVertex*)malloc(m_vertex_size * sizeof(SVertex)); -+ m_vertex.reserve(4*1024); - - m_face = NULL; - m_stroker = NULL; -@@ -155,7 +154,6 @@ CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) - m_textureScaleX = m_textureScaleY = 0.0; - m_ellipsesWidth = m_height = 0.0f; - m_color = 0; -- m_vertex_count = 0; - m_nTexture = 0; - } - -@@ -216,9 +214,7 @@ void CGUIFontTTFBase::Clear() - g_freeTypeLibrary.ReleaseStroker(m_stroker); - m_stroker = NULL; - -- free(m_vertex); -- m_vertex = NULL; -- m_vertex_count = 0; -+ m_vertex.clear(); - } - - bool CGUIFontTTFBase::Load(const CStdString& strFilename, float height, float aspect, float lineSpacing, bool border) -@@ -313,7 +309,7 @@ void CGUIFontTTFBase::Begin() - { - if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin()) - { -- m_vertex_count = 0; -+ m_vertex.clear(); - } - // Keep track of the nested begin/end calls. - m_nestedBeginCount++; -@@ -746,22 +742,9 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c - float tt = texture.y1 * m_textureScaleY; - float tb = texture.y2 * m_textureScaleY; - -- // grow the vertex buffer if required -- if(m_vertex_count >= m_vertex_size) -- { -- m_vertex_size *= 2; -- void* old = m_vertex; -- m_vertex = (SVertex*)realloc(m_vertex, m_vertex_size * sizeof(SVertex)); -- if (!m_vertex) -- { -- free(old); -- CLog::Log(LOGSEVERE, "%s: can't allocate %"PRIdS" bytes for texture", __FUNCTION__ , m_vertex_size * sizeof(SVertex)); -- return; -- } -- } -- -+ m_vertex.resize(m_vertex.size() + 4); -+ SVertex* v = &m_vertex[m_vertex.size() - 4]; - m_color = color; -- SVertex* v = m_vertex + m_vertex_count; - - unsigned char r = GET_R(color) - , g = GET_G(color) -@@ -828,8 +811,6 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c - v[3].y = y[2]; - v[3].z = z[2]; - #endif -- -- m_vertex_count+=4; - } - - // Oblique code - original taken from freetype2 (ftsynth.c) -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index c1c4507..35e3cf9 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -157,9 +157,7 @@ class CGUIFontTTFBase - bool m_bTextureLoaded; - unsigned int m_nTexture; - -- SVertex* m_vertex; -- int m_vertex_count; -- int m_vertex_size; -+ std::vector m_vertex; - - float m_textureScaleX; - float m_textureScaleY; -diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp -index 2f90668..6ef8984 100644 ---- a/xbmc/guilib/GUIFontTTFDX.cpp -+++ b/xbmc/guilib/GUIFontTTFDX.cpp -@@ -101,17 +101,17 @@ void CGUIFontTTFDX::LastEnd() - { - LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); - -- if (m_vertex_count == 0) -+ if (m_vertex.size() == 0) - return; - -- unsigned index_size = m_vertex_size * 6 / 4; -+ unsigned index_size = m_vertex.capacity() * 6 / 4; - if(m_index_size < index_size) - { - uint16_t* id = (uint16_t*)calloc(index_size, sizeof(uint16_t)); - if(id == NULL) - return; - -- for(int i = 0, b = 0; i < m_vertex_size; i += 4, b += 6) -+ for(int i = 0, b = 0; i < m_vertex.capacity(); i += 4, b += 6) - { - id[b+0] = i + 0; - id[b+1] = i + 1; -@@ -140,11 +140,11 @@ void CGUIFontTTFDX::LastEnd() - - pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST - , 0 -- , m_vertex_count -- , m_vertex_count / 2 -+ , m_vertex.size() -+ , m_vertex.size() / 2 - , m_index - , D3DFMT_INDEX16 -- , m_vertex -+ , &m_vertex[0] - , sizeof(SVertex)); - pD3DDevice->SetTransform(D3DTS_WORLD, &orig); - -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index 93b7ea6..a4e8571 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -125,13 +125,13 @@ void CGUIFontTTFGL::LastEnd() - #ifdef HAS_GL - glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); - -- glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, r)); -- glVertexPointer (3, GL_FLOAT , sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, x)); -- glTexCoordPointer(2, GL_FLOAT , sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, u)); -+ glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, r)); -+ glVertexPointer (3, GL_FLOAT , sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, x)); -+ glTexCoordPointer(2, GL_FLOAT , sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, u)); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -- glDrawArrays(GL_QUADS, 0, m_vertex_count); -+ glDrawArrays(GL_QUADS, 0, m_vertex.size()); - glPopClientAttrib(); - - glActiveTexture(GL_TEXTURE1); -@@ -147,10 +147,10 @@ void CGUIFontTTFGL::LastEnd() - GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); - - // stack object until VBOs will be used -- std::vector vecVertices( 6 * (m_vertex_count / 4) ); -+ std::vector vecVertices( 6 * (m_vertex.size() / 4) ); - SVertex *vertices = &vecVertices[0]; - -- for (int i=0; i -Date: Mon, 16 Dec 2013 18:58:12 +0000 -Subject: [PATCH 07/82] CGUIFontTTFBase::RenderCharacter can now append to - arbitrary vectors of vertices rather than only CGUIFontTTFBase::m_vertex - ---- - xbmc/guilib/GUIFontTTF.cpp | 12 +++++++----- - xbmc/guilib/GUIFontTTF.h | 2 +- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 3f219d9..1aaf68b 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -330,6 +330,8 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - { - Begin(); - -+ std::vector &vertices = m_vertex; -+ - // save the origin, which is scaled separately - m_originX = x; - m_originY = y; -@@ -410,7 +412,7 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - - for (int i = 0; i < 3; i++) - { -- RenderCharacter(startX + cursorX, startY, period, color, !scrolling); -+ RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices); - cursorX += period->advance; - } - break; -@@ -419,7 +421,7 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - else if (maxPixelWidth > 0 && cursorX > maxPixelWidth) - break; // exceeded max allowed width - stop rendering - -- RenderCharacter(startX + cursorX, startY, ch, color, !scrolling); -+ RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices); - if ( alignment & XBFONT_JUSTIFIED ) - { - if ((*pos & 0xffff) == L' ') -@@ -676,7 +678,7 @@ bool CGUIFontTTFBase::CacheCharacter(wchar_t letter, uint32_t style, Character * - return true; - } - --void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX) -+void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX, std::vector &vertices) - { - // actual image width isn't same as the character width as that is - // just baseline width and height should include the descent -@@ -742,8 +744,8 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c - float tt = texture.y1 * m_textureScaleY; - float tb = texture.y2 * m_textureScaleY; - -- m_vertex.resize(m_vertex.size() + 4); -- SVertex* v = &m_vertex[m_vertex.size() - 4]; -+ vertices.resize(vertices.size() + 4); -+ SVertex* v = &vertices[vertices.size() - 4]; - m_color = color; - - unsigned char r = GET_R(color) -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index 35e3cf9..4a6a696 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -109,7 +109,7 @@ class CGUIFontTTFBase - // Stuff for pre-rendering for speed - inline Character *GetCharacter(character_t letter); - bool CacheCharacter(wchar_t letter, uint32_t style, Character *ch); -- void RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX); -+ void RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX, std::vector &vertices); - void ClearCharacterCache(); - - virtual CBaseTexture* ReallocTexture(unsigned int& newHeight) = 0; --- -1.9.3 - - -From 96abf97cc233118b46670fc78a28d09f4c1c5335 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 15 Jan 2014 17:18:38 +0000 -Subject: [PATCH 08/82] Add a cache of font glyph bounding box vertices. This - is implemented as a template because ultimately we will key on different - parameters and store values of different types, depending upon whether we - have a GLES or non-GLES backend, and for GLES, whether or not the currently - applicable transformation matrices permit the use of hardware clipping. - ---- - xbmc/guilib/GUIFontCache.cpp | 105 ++++++++++++++++++++ - xbmc/guilib/GUIFontCache.h | 217 ++++++++++++++++++++++++++++++++++++++++++ - xbmc/guilib/GUIFontTTF.cpp | 181 +++++++++++++++++++---------------- - xbmc/guilib/GUIFontTTF.h | 5 + - xbmc/guilib/GUIFontTTFGL.cpp | 1 + - xbmc/guilib/GraphicContext.h | 1 + - xbmc/guilib/Makefile.in | 1 + - xbmc/guilib/TransformMatrix.h | 11 +++ - 8 files changed, 438 insertions(+), 84 deletions(-) - create mode 100644 xbmc/guilib/GUIFontCache.cpp - create mode 100644 xbmc/guilib/GUIFontCache.h - -diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp -new file mode 100644 -index 0000000..c029713 ---- /dev/null -+++ b/xbmc/guilib/GUIFontCache.cpp -@@ -0,0 +1,105 @@ -+/* -+ * 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 -+#include -+#include "utils/StdString.h" // required by GUIFontTTF.h -+#include "GUIFontTTF.h" -+#include "GraphicContext.h" -+ -+template -+void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry) -+{ -+ entry.m_key.m_pos = m_key.m_pos; -+ entry.m_key.m_colors.assign(m_key.m_colors.begin(), m_key.m_colors.end()); -+ entry.m_key.m_text.assign(m_key.m_text.begin(), m_key.m_text.end()); -+ entry.m_key.m_alignment = m_key.m_alignment; -+ entry.m_key.m_maxPixelWidth = m_key.m_maxPixelWidth; -+ entry.m_key.m_scrolling = m_key.m_scrolling; -+ entry.m_matrix = m_key.m_matrix; -+ entry.m_key.m_scaleX = m_key.m_scaleX; -+ entry.m_key.m_scaleY = m_key.m_scaleY; -+ -+ entry.m_lastUsedMillis = m_nowMillis; -+ entry.m_value.clear(); -+} -+ -+template -+CGUIFontCacheEntry::~CGUIFontCacheEntry() -+{ -+ delete &m_key.m_colors; -+ delete &m_key.m_text; -+ m_value.clear(); -+} -+ -+template -+Value &CGUIFontCache::Lookup(Position &pos, -+ const vecColors &colors, const vecText &text, -+ uint32_t alignment, float maxPixelWidth, -+ bool scrolling, -+ unsigned int nowMillis, bool &dirtyCache) -+{ -+ const CGUIFontCacheKey key(pos, -+ const_cast(colors), const_cast(text), -+ alignment, maxPixelWidth, -+ scrolling, g_graphicsContext.GetGUIMatrix(), -+ g_graphicsContext.GetGUIScaleX(), g_graphicsContext.GetGUIScaleY()); -+ EntryHashIterator i = m_list.get().find(key); -+ if (i == m_list.get().end()) -+ { -+ /* Cache miss */ -+ EntryAgeIterator oldest = m_list.get().begin(); -+ if (!m_list.get().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT) -+ { -+ /* The oldest existing entry is old enough to expire and reuse */ -+ m_list.get().modify(m_list.project(oldest), typename CGUIFontCacheEntry::Reassign(key, nowMillis)); -+ m_list.get().relocate(m_list.get().end(), oldest); -+ } -+ else -+ { -+ /* We need a new entry instead */ -+ /* Yes, this causes the creation an destruction of a temporary entry, but -+ * this code ought to only be used infrequently, when the cache needs to grow */ -+ m_list.get().push_back(CGUIFontCacheEntry(*this, key, nowMillis)); -+ } -+ dirtyCache = true; -+ return (--m_list.get().end())->m_value; -+ } -+ else -+ { -+ /* Cache hit */ -+ /* Update time in entry and move to the back of the list */ -+ i->m_lastUsedMillis = nowMillis; -+ m_list.get().relocate(m_list.get().end(), m_list.project(i)); -+ dirtyCache = false; -+ return i->m_value; -+ } -+} -+ -+template -+void CGUIFontCache::Flush() -+{ -+ m_list.get().clear(); -+} -+ -+template void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry); -+template CGUIFontCacheEntry::~CGUIFontCacheEntry(); -+template CGUIFontCacheStaticValue &CGUIFontCache::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &); -+template void CGUIFontCache::Flush(); -diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h -new file mode 100644 -index 0000000..ef65845 ---- /dev/null -+++ b/xbmc/guilib/GUIFontCache.h -@@ -0,0 +1,217 @@ -+/*! -+\file GUIFontCache.h -+\brief -+*/ -+ -+#ifndef CGUILIB_GUIFONTCACHE_H -+#define CGUILIB_GUIFONTCACHE_H -+#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 -+#include -+#include -+ -+#include -+#include -+ -+#include "boost/multi_index_container.hpp" -+#include "boost/multi_index/sequenced_index.hpp" -+#include "boost/multi_index/hashed_index.hpp" -+#include "boost/multi_index/member.hpp" -+ -+#include "TransformMatrix.h" -+ -+using namespace boost::multi_index; -+ -+#define FONT_CACHE_TIME_LIMIT (1000) -+ -+template class CGUIFontCache; -+class CGUIFontTTFBase; -+ -+template -+struct CGUIFontCacheKey -+{ -+ Position m_pos; -+ vecColors &m_colors; -+ vecText &m_text; -+ uint32_t m_alignment; -+ float m_maxPixelWidth; -+ bool m_scrolling; -+ const TransformMatrix &m_matrix; -+ float m_scaleX; -+ float m_scaleY; -+ -+ CGUIFontCacheKey(Position pos, -+ vecColors &colors, vecText &text, -+ uint32_t alignment, float maxPixelWidth, -+ bool scrolling, const TransformMatrix &matrix, -+ float scaleX, float scaleY) : -+ m_pos(pos), -+ m_colors(colors), m_text(text), -+ m_alignment(alignment), m_maxPixelWidth(maxPixelWidth), -+ m_scrolling(scrolling), m_matrix(matrix), -+ m_scaleX(scaleX), m_scaleY(scaleY) -+ {} -+}; -+ -+template -+struct CGUIFontCacheEntry -+{ -+ const CGUIFontCache &m_cache; -+ CGUIFontCacheKey m_key; -+ TransformMatrix m_matrix; -+ -+ /* These need to be declared as mutable to get round the fact that only -+ * const iterators are available. These fields do not affect comparison or -+ * hash functors, so from the container's point of view, they are mutable. */ -+ mutable unsigned int m_lastUsedMillis; -+ mutable Value m_value; -+ -+ CGUIFontCacheEntry(const CGUIFontCache &cache, const CGUIFontCacheKey &key, unsigned int nowMillis) : -+ m_cache(cache), -+ m_key(key.m_pos, -+ *new vecColors, *new vecText, -+ key.m_alignment, key.m_maxPixelWidth, -+ key.m_scrolling, m_matrix, -+ key.m_scaleX, key.m_scaleY), -+ m_lastUsedMillis(nowMillis) -+ { -+ m_key.m_colors.assign(key.m_colors.begin(), key.m_colors.end()); -+ m_key.m_text.assign(key.m_text.begin(), key.m_text.end()); -+ m_matrix = key.m_matrix; -+ } -+ -+ CGUIFontCacheEntry(const CGUIFontCacheEntry &other) : -+ m_cache(other.m_cache), -+ m_key(other.m_key.m_pos, -+ *new vecColors, *new vecText, -+ other.m_key.m_alignment, other.m_key.m_maxPixelWidth, -+ other.m_key.m_scrolling, m_matrix, -+ other.m_key.m_scaleX, other.m_key.m_scaleY), -+ m_lastUsedMillis(other.m_lastUsedMillis), -+ m_value(other.m_value) -+ { -+ m_key.m_colors.assign(other.m_key.m_colors.begin(), other.m_key.m_colors.end()); -+ m_key.m_text.assign(other.m_key.m_text.begin(), other.m_key.m_text.end()); -+ m_matrix = other.m_key.m_matrix; -+ } -+ -+ struct Reassign -+ { -+ Reassign(const CGUIFontCacheKey &key, unsigned int nowMillis) : m_key(key), m_nowMillis(nowMillis) {} -+ void operator()(CGUIFontCacheEntry &entry); -+ private: -+ const CGUIFontCacheKey &m_key; -+ unsigned int m_nowMillis; -+ }; -+ -+ ~CGUIFontCacheEntry(); -+}; -+ -+template -+struct CGUIFontCacheHash -+{ -+ size_t operator()(const CGUIFontCacheKey &key) const -+ { -+ /* Not much effort has gone into choosing this hash function */ -+ size_t hash = 0, i; -+ for (i = 0; i < 3 && i < key.m_text.size(); ++i) -+ hash += key.m_text[i]; -+ if (key.m_colors.size()) -+ hash += key.m_colors[0]; -+ hash += MatrixHashContribution(key); -+ return hash; -+ } -+}; -+ -+template -+struct CGUIFontCacheKeysMatch -+{ -+ bool operator()(const CGUIFontCacheKey &a, const CGUIFontCacheKey &b) const -+ { -+ return a.m_text == b.m_text && -+ a.m_colors == b.m_colors && -+ a.m_alignment == b.m_alignment && -+ a.m_scrolling == b.m_scrolling && -+ a.m_maxPixelWidth == b.m_maxPixelWidth && -+ Match(a.m_pos, a.m_matrix, b.m_pos, b.m_matrix, a.m_scrolling) && -+ a.m_scaleX == b.m_scaleX && -+ a.m_scaleY == b.m_scaleY; -+ } -+}; -+ -+template -+class CGUIFontCache -+{ -+ /* Empty structs used as tags to identify indexes */ -+ struct Age {}; -+ struct Hash {}; -+ -+ typedef multi_index_container< -+ CGUIFontCacheEntry, -+ indexed_by< -+ sequenced >, -+ hashed_unique, member, CGUIFontCacheKey, &CGUIFontCacheEntry::m_key>, CGUIFontCacheHash, CGUIFontCacheKeysMatch > -+ > -+ > EntryList; -+ -+ typedef typename EntryList::template index::type::iterator EntryAgeIterator; -+ typedef typename EntryList::template index::type::iterator EntryHashIterator; -+ -+ EntryList m_list; -+ -+public: -+ const CGUIFontTTFBase &m_font; -+ -+ CGUIFontCache(CGUIFontTTFBase &font) : m_font(font) {} -+ Value &Lookup(Position &pos, -+ const vecColors &colors, const vecText &text, -+ uint32_t alignment, float maxPixelWidth, -+ bool scrolling, -+ unsigned int nowMillis, bool &dirtyCache); -+ void Flush(); -+}; -+ -+struct CGUIFontCacheStaticPosition -+{ -+ float m_x; -+ float m_y; -+ CGUIFontCacheStaticPosition(float x, float y) : m_x(x), m_y(y) {} -+}; -+ -+typedef std::vector CGUIFontCacheStaticValue; -+ -+inline bool Match(const CGUIFontCacheStaticPosition &a, const TransformMatrix &a_m, -+ const CGUIFontCacheStaticPosition &b, const TransformMatrix &b_m, -+ bool scrolling) -+{ -+ return a.m_x == b.m_x && a.m_y == b.m_y && a_m == b_m; -+} -+ -+inline float MatrixHashContribution(const CGUIFontCacheKey &a) -+{ -+ /* Ensure horizontally translated versions end up in different buckets */ -+ return a.m_matrix.m[0][3]; -+} -+ -+#endif -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 1aaf68b..288e61a 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -27,6 +27,7 @@ - #include "utils/MathUtils.h" - #include "utils/log.h" - #include "windowing/WindowingFactory.h" -+#include "threads/SystemClock.h" - - #include - -@@ -131,7 +132,7 @@ class CFreeTypeLibrary - XBMC_GLOBAL_REF(CFreeTypeLibrary, g_freeTypeLibrary); // our freetype library - #define g_freeTypeLibrary XBMC_GLOBAL_USE(CFreeTypeLibrary) - --CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) -+CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this) - { - m_texture = NULL; - m_char = NULL; -@@ -330,108 +331,120 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - { - Begin(); - -- std::vector &vertices = m_vertex; -- -- // save the origin, which is scaled separately -- m_originX = x; -- m_originY = y; -- -- // Check if we will really need to truncate or justify the text -- if ( alignment & XBFONT_TRUNCATED ) -+ bool dirtyCache; -+ CGUIFontCacheStaticPosition staticPos(x, y); -+ std::vector &vertices = m_staticCache.Lookup(staticPos, -+ colors, text, -+ alignment, maxPixelWidth, -+ scrolling, -+ XbmcThreads::SystemClockMillis(), -+ dirtyCache); -+ if (dirtyCache) - { -- if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth) -- alignment &= ~XBFONT_TRUNCATED; -- } -- else if ( alignment & XBFONT_JUSTIFIED ) -- { -- if ( maxPixelWidth <= 0.0f ) -- alignment &= ~XBFONT_JUSTIFIED; -- } -+ // save the origin, which is scaled separately -+ m_originX = x; -+ m_originY = y; - -- // calculate sizing information -- float startX = 0; -- float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0; // vertical centering -+ // Check if we will really need to truncate or justify the text -+ if ( alignment & XBFONT_TRUNCATED ) -+ { -+ if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth) -+ alignment &= ~XBFONT_TRUNCATED; -+ } -+ else if ( alignment & XBFONT_JUSTIFIED ) -+ { -+ if ( maxPixelWidth <= 0.0f ) -+ alignment &= ~XBFONT_JUSTIFIED; -+ } - -- if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) ) -- { -- // Get the extent of this line -- float w = GetTextWidthInternal( text.begin(), text.end() ); -+ // calculate sizing information -+ float startX = 0; -+ float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0; // vertical centering - -- if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues -- w = maxPixelWidth; -+ if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) ) -+ { -+ // Get the extent of this line -+ float w = GetTextWidthInternal( text.begin(), text.end() ); - -- if ( alignment & XBFONT_CENTER_X) -- w *= 0.5f; -- // Offset this line's starting position -- startX -= w; -- } -+ if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues -+ w = maxPixelWidth; - -- float spacePerLetter = 0; // for justification effects -- if ( alignment & XBFONT_JUSTIFIED ) -- { -- // first compute the size of the text to render in both characters and pixels -- unsigned int lineChars = 0; -- float linePixels = 0; -- for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos) -+ if ( alignment & XBFONT_CENTER_X) -+ w *= 0.5f; -+ // Offset this line's starting position -+ startX -= w; -+ } -+ -+ float spacePerLetter = 0; // for justification effects -+ if ( alignment & XBFONT_JUSTIFIED ) - { -- Character *ch = GetCharacter(*pos); -- if (ch) -- { // spaces have multiple times the justification spacing of normal letters -- lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1; -- linePixels += ch->advance; -+ // first compute the size of the text to render in both characters and pixels -+ unsigned int lineChars = 0; -+ float linePixels = 0; -+ for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos) -+ { -+ Character *ch = GetCharacter(*pos); -+ if (ch) -+ { // spaces have multiple times the justification spacing of normal letters -+ lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1; -+ linePixels += ch->advance; -+ } - } -+ if (lineChars > 1) -+ spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1); - } -- if (lineChars > 1) -- spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1); -- } -- float cursorX = 0; // current position along the line -- -- for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos) -- { -- // If starting text on a new line, determine justification effects -- // Get the current letter in the CStdString -- color_t color = (*pos & 0xff0000) >> 16; -- if (color >= colors.size()) -- color = 0; -- color = colors[color]; -+ float cursorX = 0; // current position along the line - -- // grab the next character -- Character *ch = GetCharacter(*pos); -- if (!ch) continue; -- -- if ( alignment & XBFONT_TRUNCATED ) -+ for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos) - { -- // Check if we will be exceeded the max allowed width -- if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth ) -- { -- // Yup. Let's draw the ellipses, then bail -- // Perhaps we should really bail to the next line in this case?? -- Character *period = GetCharacter(L'.'); -- if (!period) -- break; -+ // If starting text on a new line, determine justification effects -+ // Get the current letter in the CStdString -+ color_t color = (*pos & 0xff0000) >> 16; -+ if (color >= colors.size()) -+ color = 0; -+ color = colors[color]; -+ -+ // grab the next character -+ Character *ch = GetCharacter(*pos); -+ if (!ch) continue; - -- for (int i = 0; i < 3; i++) -+ if ( alignment & XBFONT_TRUNCATED ) -+ { -+ // Check if we will be exceeded the max allowed width -+ if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth ) - { -- RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices); -- cursorX += period->advance; -+ // Yup. Let's draw the ellipses, then bail -+ // Perhaps we should really bail to the next line in this case?? -+ Character *period = GetCharacter(L'.'); -+ if (!period) -+ break; -+ -+ for (int i = 0; i < 3; i++) -+ { -+ RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices); -+ cursorX += period->advance; -+ } -+ break; - } -- break; - } -- } -- else if (maxPixelWidth > 0 && cursorX > maxPixelWidth) -- break; // exceeded max allowed width - stop rendering -+ else if (maxPixelWidth > 0 && cursorX > maxPixelWidth) -+ break; // exceeded max allowed width - stop rendering - -- RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices); -- if ( alignment & XBFONT_JUSTIFIED ) -- { -- if ((*pos & 0xffff) == L' ') -- cursorX += ch->advance + spacePerLetter * justification_word_weight; -+ RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices); -+ if ( alignment & XBFONT_JUSTIFIED ) -+ { -+ if ((*pos & 0xffff) == L' ') -+ cursorX += ch->advance + spacePerLetter * justification_word_weight; -+ else -+ cursorX += ch->advance + spacePerLetter; -+ } - else -- cursorX += ch->advance + spacePerLetter; -+ cursorX += ch->advance; - } -- else -- cursorX += ch->advance; - } -+ /* Append the new vertices (from the cache or otherwise) to the set collected -+ * since the first Begin() call */ -+ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); - - End(); - } -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index 4a6a696..7cb4669 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -64,6 +64,9 @@ struct SVertex - }; - - -+#include "GUIFontCache.h" -+ -+ - class CGUIFontTTFBase - { - friend class CGUIFont; -@@ -166,6 +169,8 @@ class CGUIFontTTFBase - - CStdString m_strFileName; - -+ CGUIFontCache m_staticCache; -+ - private: - virtual bool FirstBegin() = 0; - virtual void LastEnd() = 0; -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index a4e8571..cb56987 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -200,6 +200,7 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight) - m_textureScaleX = 1.0f / m_textureWidth; - if (m_textureHeight < newHeight) - CLog::Log(LOGWARNING, "%s: allocated new texture with height of %d, requested %d", __FUNCTION__, m_textureHeight, newHeight); -+ m_staticCache.Flush(); - - memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch()); - if (m_texture) -diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h -index 6c2dcd4..bab2457 100644 ---- a/xbmc/guilib/GraphicContext.h -+++ b/xbmc/guilib/GraphicContext.h -@@ -146,6 +146,7 @@ class CGraphicContext : public CCriticalSection, - inline void ScaleFinalCoords(float &x, float &y, float &z) const XBMC_FORCE_INLINE { m_finalTransform.matrix.TransformPosition(x, y, z); } - bool RectIsAngled(float x1, float y1, float x2, float y2) const; - -+ inline const TransformMatrix &GetGUIMatrix() const XBMC_FORCE_INLINE { return m_finalTransform.matrix; } - inline float GetGUIScaleX() const XBMC_FORCE_INLINE { return m_finalTransform.scaleX; } - inline float GetGUIScaleY() const XBMC_FORCE_INLINE { return m_finalTransform.scaleY; } - inline color_t MergeAlpha(color_t color) const XBMC_FORCE_INLINE -diff --git a/xbmc/guilib/Makefile.in b/xbmc/guilib/Makefile.in -index 086fb0d..af82979 100644 ---- a/xbmc/guilib/Makefile.in -+++ b/xbmc/guilib/Makefile.in -@@ -23,6 +23,7 @@ SRCS += GUIEditControl.cpp - SRCS += GUIFadeLabelControl.cpp - SRCS += GUIFixedListContainer.cpp - SRCS += GUIFont.cpp -+SRCS += GUIFontCache.cpp - SRCS += GUIFontManager.cpp - SRCS += GUIFontTTF.cpp - SRCS += GUIImage.cpp -diff --git a/xbmc/guilib/TransformMatrix.h b/xbmc/guilib/TransformMatrix.h -index f351c99..9036ba9 100644 ---- a/xbmc/guilib/TransformMatrix.h -+++ b/xbmc/guilib/TransformMatrix.h -@@ -245,3 +245,14 @@ class TransformMatrix - float alpha; - bool identity; - }; -+ -+inline bool operator==(const TransformMatrix &a, const TransformMatrix &b) -+{ -+ return a.alpha == b.alpha && ((a.identity && b.identity) || -+ (!a.identity && !b.identity && std::equal(&a.m[0][0], &a.m[0][0] + sizeof a.m / sizeof a.m[0][0], &b.m[0][0]))); -+} -+ -+inline bool operator!=(const TransformMatrix &a, const TransformMatrix &b) -+{ -+ return !operator==(a, b); -+} --- -1.9.3 - - -From 87a615ec2b918f622cdeb4d97ac383473d533c19 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Thu, 23 Jan 2014 22:24:17 +0000 -Subject: [PATCH 09/82] Lay the groundwork for hardware clipping. - -For glScissor() to replace CGraphicContext::ClipRect, a necessary condition -is that no shear or rotation is introduced between the coordinate systems -they use; this depends upon the settings of the GUI matrix m_finalTransform -as well as the OpenGL model-view and projection matrices. These all remain -unchanged between paired calls of CGUIShader::OnEnabled and -CGUIShader::OnDisabled, so we scan the matrices in CGUIShader::OnEnabled to -see whether hardware clipping is possible. - -Then, in CGUIFontTTFBase::RenderCharacter, we don't apply software clipping -in such cases. However, because vertices arising from multiple -CGUIFontTTFBase::DrawTextInternal calls (each of which often uses a different -clip rectangle) get lumped into the same vector, which only at the end is -passed to OpenGL for rendering, we need to wait a few commits before we can -actually apply hardware clipping. In the meantime, expect to see rendering -errors. ---- - xbmc/guilib/GUIFontTTF.cpp | 3 +- - xbmc/guilib/GUIShader.cpp | 80 +++++++++++++++++++++++++++++++- - xbmc/guilib/GUIShader.h | 11 +++++ - xbmc/guilib/GraphicContext.cpp | 10 ++++ - xbmc/guilib/GraphicContext.h | 1 + - xbmc/rendering/RenderSystem.h | 2 + - xbmc/rendering/gles/RenderSystemGLES.cpp | 22 +++++++++ - xbmc/rendering/gles/RenderSystemGLES.h | 2 + - 8 files changed, 128 insertions(+), 3 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 288e61a..19c7ff4 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -710,7 +710,8 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c - (posY + ch->offsetY + height) * g_graphicsContext.GetGUIScaleY()); - vertex += CPoint(m_originX, m_originY); - CRect texture(ch->left, ch->top, ch->right, ch->bottom); -- g_graphicsContext.ClipRect(vertex, texture); -+ if (!g_Windowing.ScissorsCanEffectClipping()) -+ g_graphicsContext.ClipRect(vertex, texture); - - // transform our positions - note, no scaling due to GUI calibration/resolution occurs - float x[4], y[4], z[4]; -diff --git a/xbmc/guilib/GUIShader.cpp b/xbmc/guilib/GUIShader.cpp -index 11089b8..53bce09 100644 ---- a/xbmc/guilib/GUIShader.cpp -+++ b/xbmc/guilib/GUIShader.cpp -@@ -26,6 +26,8 @@ - #include "GUIShader.h" - #include "MatrixGLES.h" - #include "utils/log.h" -+#include "windowing/egl/WinSystemEGL.h" -+#include "guilib/GraphicContext.h" - - CGUIShader::CGUIShader( const char *shader ) : CGLSLShaderProgram("guishader_vert.glsl", shader) - { -@@ -86,8 +88,82 @@ bool CGUIShader::OnEnabled() - { - // This is called after glUseProgram() - -- glUniformMatrix4fv(m_hProj, 1, GL_FALSE, g_matrices.GetMatrix(MM_PROJECTION)); -- glUniformMatrix4fv(m_hModel, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); -+ GLfloat *projMatrix = g_matrices.GetMatrix(MM_PROJECTION); -+ GLfloat *modelMatrix = g_matrices.GetMatrix(MM_MODELVIEW); -+ glUniformMatrix4fv(m_hProj, 1, GL_FALSE, projMatrix); -+ glUniformMatrix4fv(m_hModel, 1, GL_FALSE, modelMatrix); -+ -+ const TransformMatrix &guiMatrix = g_graphicsContext.GetGUIMatrix(); -+ CRect viewPort; // absolute positions of corners -+ g_Windowing.GetViewPort(viewPort); -+ -+ /* glScissor operates in window coordinates. In order that we can use it to -+ * perform clipping, we must ensure that there is an independent linear -+ * transformation from the coordinate system used by CGraphicContext::ClipRect -+ * to window coordinates, separately for X and Y (in other words, no -+ * rotation or shear is introduced at any stage). To do, this, we need to -+ * check that zeros are present in the following locations: -+ * -+ * GUI matrix: -+ * / * 0 * * \ -+ * | 0 * * * | -+ * \ 0 0 * * / -+ * ^ TransformMatrix::TransformX/Y/ZCoord are only ever called with -+ * input z = 0, so this column doesn't matter -+ * Model-view matrix: -+ * / * 0 0 * \ -+ * | 0 * 0 * | -+ * | 0 0 * * | -+ * \ * * * * / <- eye w has no influence on window x/y (last column below -+ * is either 0 or ignored) -+ * Projection matrix: -+ * / * 0 0 0 \ -+ * | 0 * 0 0 | -+ * | * * * * | <- normalised device coordinate z has no influence on window x/y -+ * \ 0 0 * 0 / -+ * -+ * Some of these zeros are not strictly required to ensure this, but they tend -+ * to be zeroed in the common case, so by checking for zeros here, we simplify -+ * the calculation of the window x/y coordinates further down the line. -+ * -+ * (Minor detail: we don't quite deal in window coordinates as defined by -+ * OpenGL, because CRenderSystemGLES::SetScissors flips the Y axis. But all -+ * that's needed to handle that is an effective negation at the stage where -+ * Y is in normalised device coordinates.) -+ */ -+ m_clipPossible = guiMatrix.m[0][1] == 0 && -+ guiMatrix.m[1][0] == 0 && -+ guiMatrix.m[2][0] == 0 && -+ guiMatrix.m[2][1] == 0 && -+ modelMatrix[0+1*4] == 0 && -+ modelMatrix[0+2*4] == 0 && -+ modelMatrix[1+0*4] == 0 && -+ modelMatrix[1+2*4] == 0 && -+ modelMatrix[2+0*4] == 0 && -+ modelMatrix[2+1*4] == 0 && -+ projMatrix[0+1*4] == 0 && -+ projMatrix[0+2*4] == 0 && -+ projMatrix[0+3*4] == 0 && -+ projMatrix[1+0*4] == 0 && -+ projMatrix[1+2*4] == 0 && -+ projMatrix[1+3*4] == 0 && -+ projMatrix[3+0*4] == 0 && -+ projMatrix[3+1*4] == 0 && -+ projMatrix[3+3*4] == 0; -+ if (m_clipPossible) -+ { -+ m_clipXFactor = guiMatrix.m[0][0] * modelMatrix[0+0*4] * projMatrix[0+0*4]; -+ m_clipXOffset = (guiMatrix.m[0][3] * modelMatrix[0+0*4] + modelMatrix[0+3*4]) * projMatrix[0+0*4]; -+ m_clipYFactor = guiMatrix.m[1][1] * modelMatrix[1+1*4] * projMatrix[1+1*4]; -+ m_clipYOffset = (guiMatrix.m[1][3] * modelMatrix[1+1*4] + modelMatrix[1+3*4]) * projMatrix[1+1*4]; -+ float clipW = (guiMatrix.m[2][3] * modelMatrix[2+2*4] + modelMatrix[2+3*4]) * projMatrix[3+2*4]; -+ float xMult = (viewPort.x2 - viewPort.x1) / (2 * clipW); -+ float yMult = (viewPort.y1 - viewPort.y2) / (2 * clipW); // correct for inverted window coordinate scheme -+ m_clipXFactor = m_clipXFactor * xMult; -+ m_clipXOffset = m_clipXOffset * xMult + (viewPort.x2 + viewPort.x1) / 2; -+ m_clipYFactor = m_clipYFactor * yMult; -+ m_clipYOffset = m_clipYOffset * yMult + (viewPort.y2 + viewPort.y1) / 2; -+ } - - return true; - } -diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h -index c7e95aa..86ce4cc 100644 ---- a/xbmc/guilib/GUIShader.h -+++ b/xbmc/guilib/GUIShader.h -@@ -41,6 +41,11 @@ class CGUIShader : public CGLSLShaderProgram - GLint GetCord1Loc() { return m_hCord1; } - GLint GetUniColLoc() { return m_hUniCol; } - GLint GetCoord0MatrixLoc() { return m_hCoord0Matrix; } -+ bool HardwareClipIsPossible() { return m_clipPossible; } -+ GLfloat GetClipXFactor() { return m_clipXFactor; } -+ GLfloat GetClipXOffset() { return m_clipXOffset; } -+ GLfloat GetClipYFactor() { return m_clipYFactor; } -+ GLfloat GetClipYOffset() { return m_clipYOffset; } - - protected: - GLint m_hTex0; -@@ -56,6 +61,12 @@ class CGUIShader : public CGLSLShaderProgram - - GLfloat *m_proj; - GLfloat *m_model; -+ -+ bool m_clipPossible; -+ GLfloat m_clipXFactor; -+ GLfloat m_clipXOffset; -+ GLfloat m_clipYFactor; -+ GLfloat m_clipYOffset; - }; - - #endif // GUI_SHADER_H -diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp -index 38f17a7..5bffdf5 100644 ---- a/xbmc/guilib/GraphicContext.cpp -+++ b/xbmc/guilib/GraphicContext.cpp -@@ -167,6 +167,16 @@ void CGraphicContext::ClipRect(CRect &vertex, CRect &texture, CRect *texture2) - } - } - -+CRect CGraphicContext::GetClipRegion() -+{ -+ if (m_clipRegions.empty()) -+ return CRect(0, 0, m_iScreenWidth, m_iScreenHeight); -+ CRect clipRegion(m_clipRegions.top()); -+ if (!m_origins.empty()) -+ clipRegion -= m_origins.top(); -+ return clipRegion; -+} -+ - bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheight, bool intersectPrevious /* = false */) - { - // transform coordinates - we may have a rotation which changes the positioning of the -diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h -index bab2457..0a27643 100644 ---- a/xbmc/guilib/GraphicContext.h -+++ b/xbmc/guilib/GraphicContext.h -@@ -199,6 +199,7 @@ class CGraphicContext : public CCriticalSection, - void ApplyHardwareTransform(); - void RestoreHardwareTransform(); - void ClipRect(CRect &vertex, CRect &texture, CRect *diffuse = NULL); -+ CRect GetClipRegion(); - inline void AddGUITransform() - { - m_transforms.push(m_finalTransform); -diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h -index fa64eba..c1dfb93 100644 ---- a/xbmc/rendering/RenderSystem.h -+++ b/xbmc/rendering/RenderSystem.h -@@ -110,6 +110,8 @@ class CRenderSystemBase - virtual void GetViewPort(CRect& viewPort) = 0; - virtual void RestoreViewPort() {}; - -+ virtual bool ScissorsCanEffectClipping() { return false; } -+ virtual CRect ClipRectToScissorRect(const CRect &rect) { return CRect(); } - virtual void SetScissors(const CRect &rect) = 0; - virtual void ResetScissors() = 0; - -diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp -index 653c9ec..deb3afc 100644 ---- a/xbmc/rendering/gles/RenderSystemGLES.cpp -+++ b/xbmc/rendering/gles/RenderSystemGLES.cpp -@@ -533,6 +533,28 @@ void CRenderSystemGLES::SetViewPort(CRect& viewPort) - m_viewPort[3] = viewPort.Height(); - } - -+bool CRenderSystemGLES::ScissorsCanEffectClipping() -+{ -+ if (m_pGUIshader[m_method]) -+ return m_pGUIshader[m_method]->HardwareClipIsPossible(); -+ -+ return false; -+} -+ -+CRect CRenderSystemGLES::ClipRectToScissorRect(const CRect &rect) -+{ -+ if (!m_pGUIshader[m_method]) -+ return CRect(); -+ float xFactor = m_pGUIshader[m_method]->GetClipXFactor(); -+ float xOffset = m_pGUIshader[m_method]->GetClipXOffset(); -+ float yFactor = m_pGUIshader[m_method]->GetClipYFactor(); -+ float yOffset = m_pGUIshader[m_method]->GetClipYOffset(); -+ return CRect(rect.x1 * xFactor + xOffset, -+ rect.y1 * yFactor + yOffset, -+ rect.x2 * xFactor + xOffset, -+ rect.y2 * yFactor + yOffset); -+} -+ - void CRenderSystemGLES::SetScissors(const CRect &rect) - { - if (!m_bRenderCreated) -diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h -index 98e398a..81ee49e 100644 ---- a/xbmc/rendering/gles/RenderSystemGLES.h -+++ b/xbmc/rendering/gles/RenderSystemGLES.h -@@ -63,6 +63,8 @@ class CRenderSystemGLES : public CRenderSystemBase - virtual void SetViewPort(CRect& viewPort); - virtual void GetViewPort(CRect& viewPort); - -+ virtual bool ScissorsCanEffectClipping(); -+ virtual CRect ClipRectToScissorRect(const CRect &rect); - virtual void SetScissors(const CRect& rect); - virtual void ResetScissors(); - --- -1.9.3 - - -From 2c2cd66f778cfe80f5addf0e31524f5adf401725 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Thu, 23 Jan 2014 16:42:22 +0000 -Subject: [PATCH 10/82] Increase font cache hit rate by keying on the - fractional part of m_originX and m_originY *after* they have been through the - graphics context's transformation matrix, plus the scale/rotation elements of - the matrix, rather than the origin in the original frame of reference plus - the complete transformation matrix. All vertices of individual glyph bounding - boxes are a constant offset from this position, and when the fractional part - of the translation is a match, the rounding of each vertex will be in the - same direction; this permits us to calculate the desired vertices from the - cached ones simply by adding the integer parts of the translations with no - additional rounding steps. - -Note that this requires that software clipping is *not* performed. ---- - xbmc/guilib/GUIFontCache.cpp | 8 +++++++ - xbmc/guilib/GUIFontCache.h | 43 +++++++++++++++++++++++++++++++++++ - xbmc/guilib/GUIFontTTF.cpp | 53 +++++++++++++++++++++++++++++++++++--------- - xbmc/guilib/GUIFontTTF.h | 1 + - 4 files changed, 95 insertions(+), 10 deletions(-) - -diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp -index c029713..b66c00b 100644 ---- a/xbmc/guilib/GUIFontCache.cpp -+++ b/xbmc/guilib/GUIFontCache.cpp -@@ -85,6 +85,9 @@ Value &CGUIFontCache::Lookup(Position &pos, - else - { - /* Cache hit */ -+ /* Update the translation arguments so that they hold the offset to apply -+ * to the cached values (but only in the dynamic case) */ -+ pos.UpdateWithOffsets(i->m_key.m_pos, scrolling); - /* Update time in entry and move to the back of the list */ - i->m_lastUsedMillis = nowMillis; - m_list.get().relocate(m_list.get().end(), m_list.project(i)); -@@ -103,3 +106,8 @@ template void CGUIFontCacheEntry::~CGUIFontCacheEntry(); - template CGUIFontCacheStaticValue &CGUIFontCache::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &); - template void CGUIFontCache::Flush(); -+ -+template void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry); -+template CGUIFontCacheEntry::~CGUIFontCacheEntry(); -+template CGUIFontCacheDynamicValue &CGUIFontCache::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &); -+template void CGUIFontCache::Flush(); -diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h -index ef65845..d913dee 100644 ---- a/xbmc/guilib/GUIFontCache.h -+++ b/xbmc/guilib/GUIFontCache.h -@@ -44,6 +44,7 @@ - using namespace boost::multi_index; - - #define FONT_CACHE_TIME_LIMIT (1000) -+#define FONT_CACHE_DIST_LIMIT (0.01) - - template class CGUIFontCache; - class CGUIFontTTFBase; -@@ -197,6 +198,7 @@ struct CGUIFontCacheStaticPosition - float m_x; - float m_y; - CGUIFontCacheStaticPosition(float x, float y) : m_x(x), m_y(y) {} -+ void UpdateWithOffsets(const CGUIFontCacheStaticPosition &cached, bool scrolling) {} - }; - - typedef std::vector CGUIFontCacheStaticValue; -@@ -214,4 +216,45 @@ inline float MatrixHashContribution(const CGUIFontCacheKey CGUIFontCacheDynamicValue; -+ -+inline bool Match(const CGUIFontCacheDynamicPosition &a, const TransformMatrix &a_m, -+ const CGUIFontCacheDynamicPosition &b, const TransformMatrix &b_m, -+ bool scrolling) -+{ -+ float diffX = a.m_x - b.m_x + FONT_CACHE_DIST_LIMIT; -+ float diffY = a.m_y - b.m_y + FONT_CACHE_DIST_LIMIT; -+ float diffZ = a.m_z - b.m_z + FONT_CACHE_DIST_LIMIT; -+ return (scrolling || diffX - floorf(diffX) < 2 * FONT_CACHE_DIST_LIMIT) && -+ diffY - floorf(diffY) < 2 * FONT_CACHE_DIST_LIMIT && -+ diffZ - floorf(diffZ) < 2 * FONT_CACHE_DIST_LIMIT && -+ a_m.m[0][0] == b_m.m[0][0] && -+ a_m.m[1][1] == b_m.m[1][1] && -+ a_m.m[2][2] == b_m.m[2][2]; -+ // We already know the first 3 columns of both matrices are diagonal, so no need to check the other elements -+} -+ -+inline float MatrixHashContribution(const CGUIFontCacheKey &a) -+{ -+ return 0; -+} -+ - #endif -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 19c7ff4..73f0e50 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -132,7 +132,7 @@ class CFreeTypeLibrary - XBMC_GLOBAL_REF(CFreeTypeLibrary, g_freeTypeLibrary); // our freetype library - #define g_freeTypeLibrary XBMC_GLOBAL_USE(CFreeTypeLibrary) - --CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this) -+CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this), m_dynamicCache(*this) - { - m_texture = NULL; - m_char = NULL; -@@ -332,13 +332,28 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - Begin(); - - bool dirtyCache; -+ bool hardwareClipping = g_Windowing.ScissorsCanEffectClipping(); - CGUIFontCacheStaticPosition staticPos(x, y); -- std::vector &vertices = m_staticCache.Lookup(staticPos, -- colors, text, -- alignment, maxPixelWidth, -- scrolling, -- XbmcThreads::SystemClockMillis(), -- dirtyCache); -+ CGUIFontCacheDynamicPosition dynamicPos; -+ if (hardwareClipping) -+ { -+ dynamicPos = CGUIFontCacheDynamicPosition(g_graphicsContext.ScaleFinalXCoord(x, y), -+ g_graphicsContext.ScaleFinalYCoord(x, y), -+ g_graphicsContext.ScaleFinalZCoord(x, y)); -+ } -+ std::vector &vertices = hardwareClipping ? -+ m_dynamicCache.Lookup(dynamicPos, -+ colors, text, -+ alignment, maxPixelWidth, -+ scrolling, -+ XbmcThreads::SystemClockMillis(), -+ dirtyCache) : -+ m_staticCache.Lookup(staticPos, -+ colors, text, -+ alignment, maxPixelWidth, -+ scrolling, -+ XbmcThreads::SystemClockMillis(), -+ dirtyCache); - if (dirtyCache) - { - // save the origin, which is scaled separately -@@ -441,10 +456,28 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - else - cursorX += ch->advance; - } -+ if (hardwareClipping) -+ /* Append the new vertices (which we have just constructed in the cache) -+ * to the set collected since the first Begin() call */ -+ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); -+ } -+ else if (hardwareClipping) -+ { -+ /* Apply the translation offset to the vertices from the cache after -+ * appending them to the set collected since the first Begin() call */ -+ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); -+ SVertex *v; -+ for (v = &*m_vertex.end() - vertices.size(); v != &*m_vertex.end(); v++) -+ { -+ v->x += dynamicPos.m_x; -+ v->y += dynamicPos.m_y; -+ v->z += dynamicPos.m_z; -+ } - } -- /* Append the new vertices (from the cache or otherwise) to the set collected -- * since the first Begin() call */ -- m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); -+ if (!hardwareClipping) -+ /* Append the new vertices (from the cache or otherwise) to the set collected -+ * since the first Begin() call */ -+ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); - - End(); - } -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index 7cb4669..78445ab 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -170,6 +170,7 @@ class CGUIFontTTFBase - CStdString m_strFileName; - - CGUIFontCache m_staticCache; -+ CGUIFontCache m_dynamicCache; - - private: - virtual bool FirstBegin() = 0; --- -1.9.3 - - -From aa09af31e58262051e8571223cc6fcefaf8d1697 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 8 Jan 2014 12:16:33 +0000 -Subject: [PATCH 11/82] Rewrite of scrolling text code. - -No longer shuffles the string round to minimise the number of characters -before the clipping rectangle; this doesn't save much on rendering time but -does harm the effectiveness of the cache. Now uses a pixel offset into the -string rather than a character + pixel offset, and plots the entire string -every time (execpt when the wrap point is visible, in which case the entire -string is plotted twice). - -It also makes motion smoother, because (possibly unintentionally) the -previous code preferred to align the scroll offset with character boundaries. -This would lead to uneven changes of position, especially when the width of -the character currently being scrolled off the edge was only slightly more -than an integral multiple of the scroll increment. ---- - xbmc/guilib/GUIFadeLabelControl.cpp | 8 +-- - xbmc/guilib/GUIFont.cpp | 123 +++++++++++++----------------------- - xbmc/guilib/GUIFont.h | 17 ++--- - xbmc/guilib/GUIRSSControl.cpp | 6 +- - xbmc/utils/RssReader.cpp | 2 +- - xbmc/utils/RssReader.h | 2 +- - 6 files changed, 58 insertions(+), 100 deletions(-) - -diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp -index d594c04..86ee73a 100644 ---- a/xbmc/guilib/GUIFadeLabelControl.cpp -+++ b/xbmc/guilib/GUIFadeLabelControl.cpp -@@ -109,18 +109,14 @@ void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &d - bool moveToNextLabel = false; - if (!m_scrollOut) - { -- vecText text; -- m_textLayout.GetFirstText(text); -- if (m_scrollInfo.characterPos && m_scrollInfo.characterPos < text.size()) -- text.erase(text.begin(), text.begin() + min((int)m_scrollInfo.characterPos - 1, (int)text.size())); -- if (m_label.font->GetTextWidth(text) < m_width) -+ if (m_scrollInfo.pixelPos + m_width > m_scrollInfo.m_textWidth) - { - if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL) - m_fadeAnim.QueueAnimation(ANIM_PROCESS_NORMAL); - moveToNextLabel = true; - } - } -- else if (m_scrollInfo.characterPos > m_textLayout.GetTextLength()) -+ else if (m_scrollInfo.pixelPos > m_scrollInfo.m_textWidth) - moveToNextLabel = true; - - // apply the fading animation -diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp -index a7ee668..eb8efdb 100644 ---- a/xbmc/guilib/GUIFont.cpp -+++ b/xbmc/guilib/GUIFont.cpp -@@ -36,7 +36,12 @@ CScrollInfo::CScrollInfo(unsigned int wait /* = 50 */, float pos /* = 0 */, - initialWait = wait; - initialPos = pos; - SetSpeed(speed ? speed : defaultSpeed); -- g_charsetConverter.utf8ToW(scrollSuffix, suffix); -+ CStdStringW wsuffix; -+ g_charsetConverter.utf8ToW(scrollSuffix, wsuffix); -+ suffix.clear(); -+ suffix.reserve(wsuffix.size()); -+ for (vecText::size_type i = 0; i < wsuffix.size(); i++) -+ suffix.push_back(wsuffix[i]); - Reset(); - } - -@@ -115,11 +120,12 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo) - { - // draw at our scroll position - // we handle the scrolling as follows: -- // We scroll on a per-pixel basis up until we have scrolled the first character outside -- // of our viewport, whereby we cycle the string around, and reset the scroll position. -- // -- // pixelPos is the amount in pixels to move the string by. -- // characterPos is the amount in characters to rotate the string by. -+ // We scroll on a per-pixel basis (eschewing the use of character indices -+ // which were also in use previously). The complete string, including suffix, -+ // is plotted to achieve the desired effect - normally just the one time, but -+ // if there is a wrap point within the viewport then it will be plotted twice. -+ // If the string is smaller than the viewport, then it may be plotted even -+ // more times than that. - // - if (scrollInfo.waitTime) - { -@@ -135,54 +141,19 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo) - // move along by the appropriate scroll amount - float scrollAmount = fabs(scrollInfo.GetPixelsPerFrame() * g_graphicsContext.GetGUIScaleX()); - -- if (scrollInfo.pixelSpeed > 0) -+ if (!scrollInfo.m_widthValid) - { -- // we want to move scrollAmount, grab the next character -- float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); -- if (scrollInfo.pixelPos + scrollAmount < charWidth) -- scrollInfo.pixelPos += scrollAmount; // within the current character -- else -- { // past the current character, decrement scrollAmount by the charWidth and move to the next character -- while (scrollInfo.pixelPos + scrollAmount >= charWidth) -- { -- scrollAmount -= (charWidth - scrollInfo.pixelPos); -- scrollInfo.pixelPos = 0; -- scrollInfo.characterPos++; -- if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size()) -- { -- scrollInfo.Reset(); -- break; -- } -- charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); -- } -- } -- } -- else if (scrollInfo.pixelSpeed < 0) -- { // scrolling backwards -- // we want to move scrollAmount, grab the next character -- float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); -- if (scrollInfo.pixelPos + scrollAmount < charWidth) -- scrollInfo.pixelPos += scrollAmount; // within the current character -- else -- { // past the current character, decrement scrollAmount by the charWidth and move to the next character -- while (scrollInfo.pixelPos + scrollAmount >= charWidth) -- { -- scrollAmount -= (charWidth - scrollInfo.pixelPos); -- scrollInfo.pixelPos = 0; -- if (scrollInfo.characterPos == 0) -- { -- scrollInfo.Reset(); -- scrollInfo.characterPos = text.size() + scrollInfo.suffix.size() - 1; -- break; -- } -- scrollInfo.characterPos--; -- charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); -- } -- } -+ /* Calculate the pixel width of the complete string */ -+ scrollInfo.m_textWidth = GetTextWidth(text); -+ scrollInfo.m_totalWidth = scrollInfo.m_textWidth + GetTextWidth(scrollInfo.suffix); -+ scrollInfo.m_widthValid = true; - } -+ scrollInfo.pixelPos += scrollAmount; -+ assert(scrollInfo.m_totalWidth != 0); -+ while (scrollInfo.pixelPos >= scrollInfo.m_totalWidth) -+ scrollInfo.pixelPos -= scrollInfo.m_totalWidth; - -- if(scrollInfo.characterPos != old.characterPos -- || scrollInfo.pixelPos != old.pixelPos) -+ if (scrollInfo.pixelPos != old.pixelPos) - return true; - else - return false; -@@ -194,39 +165,27 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo - if (!m_font) return; - if (!shadowColor) shadowColor = m_shadowColor; - -- float spaceWidth = GetCharWidth(L' '); -- // max chars on screen + extra margin chars -- vecText::size_type maxChars = -- std::min( -- (text.size() + (vecText::size_type)scrollInfo.suffix.size()), -- (vecText::size_type)((maxWidth * 1.05f) / spaceWidth)); -- - if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment)) - return; // nothing to render - -- maxWidth = ROUND((maxWidth + scrollInfo.pixelPos) / g_graphicsContext.GetGUIScaleX()); -+ if (!scrollInfo.m_widthValid) -+ { -+ /* Calculate the pixel width of the complete string */ -+ scrollInfo.m_textWidth = GetTextWidth(text); -+ scrollInfo.m_totalWidth = scrollInfo.m_textWidth + GetTextWidth(scrollInfo.suffix); -+ scrollInfo.m_widthValid = true; -+ } -+ -+ assert(scrollInfo.m_totalWidth != 0); -+ -+ float textPixelWidth = ROUND(scrollInfo.m_textWidth / g_graphicsContext.GetGUIScaleX()); -+ float suffixPixelWidth = ROUND((scrollInfo.m_totalWidth - scrollInfo.m_textWidth) / g_graphicsContext.GetGUIScaleX()); - -- float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); - float offset; - if(scrollInfo.pixelSpeed >= 0) - offset = scrollInfo.pixelPos; - else -- offset = charWidth - scrollInfo.pixelPos; -- -- // Now rotate our string as needed, only take a slightly larger then visible part of the text. -- unsigned int pos = scrollInfo.characterPos; -- vecText renderText; -- renderText.reserve(maxChars); -- for (vecText::size_type i = 0; i < maxChars; i++) -- { -- if (pos >= text.size() + scrollInfo.suffix.size()) -- pos = 0; -- if (pos < text.size()) -- renderText.push_back(text[pos]); -- else -- renderText.push_back(scrollInfo.suffix[pos - text.size()]); -- pos++; -- } -+ offset = scrollInfo.m_totalWidth - scrollInfo.pixelPos; - - vecColors renderColors; - for (unsigned int i = 0; i < colors.size(); i++) -@@ -239,9 +198,17 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo - vecColors shadowColors; - for (unsigned int i = 0; i < renderColors.size(); i++) - shadowColors.push_back((renderColors[i] & 0xff000000) != 0 ? shadowColor : 0); -- m_font->DrawTextInternal(x - offset + 1, y + 1, shadowColors, renderText, alignment, maxWidth + m_font->GetLineHeight(2.0f), scroll); -+ for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth) -+ { -+ m_font->DrawTextInternal(x + dx + 1, y + 1, shadowColors, text, alignment, textPixelWidth, scroll); -+ m_font->DrawTextInternal(x + dx + scrollInfo.m_textWidth + 1, y + 1, shadowColors, scrollInfo.suffix, alignment, suffixPixelWidth, scroll); -+ } -+ } -+ for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth) -+ { -+ m_font->DrawTextInternal(x + dx, y, renderColors, text, alignment, textPixelWidth, scroll); -+ m_font->DrawTextInternal(x + dx + scrollInfo.m_textWidth, y, renderColors, scrollInfo.suffix, alignment, suffixPixelWidth, scroll); - } -- m_font->DrawTextInternal(x - offset, y, renderColors, renderText, alignment, maxWidth + m_font->GetLineHeight(2.0f), scroll); - - g_graphicsContext.RestoreClipRegion(); - } -diff --git a/xbmc/guilib/GUIFont.h b/xbmc/guilib/GUIFont.h -index c55db48..09cf9b3 100644 ---- a/xbmc/guilib/GUIFont.h -+++ b/xbmc/guilib/GUIFont.h -@@ -64,7 +64,6 @@ class CScrollInfo - void Reset() - { - waitTime = initialWait; -- characterPos = 0; - // pixelPos is where we start the current letter, so is measured - // to the left of the text rendering's left edge. Thus, a negative - // value will mean the text starts to the right -@@ -72,25 +71,19 @@ class CScrollInfo - // privates: - m_averageFrameTime = 1000.f / abs(defaultSpeed); - m_lastFrameTime = 0; -- } -- uint32_t GetCurrentChar(const vecText &text) const -- { -- assert(text.size()); -- if (characterPos < text.size()) -- return text[characterPos]; -- else if (characterPos < text.size() + suffix.size()) -- return suffix[characterPos - text.size()]; -- return text[0]; -+ m_widthValid = false; - } - float GetPixelsPerFrame(); - - float pixelPos; - float pixelSpeed; - unsigned int waitTime; -- unsigned int characterPos; - unsigned int initialWait; - float initialPos; -- CStdStringW suffix; -+ vecText suffix; -+ mutable float m_textWidth; -+ mutable float m_totalWidth; -+ mutable bool m_widthValid; - - static const int defaultSpeed = 60; - private: -diff --git a/xbmc/guilib/GUIRSSControl.cpp b/xbmc/guilib/GUIRSSControl.cpp -index 712e118..203c138 100644 ---- a/xbmc/guilib/GUIRSSControl.cpp -+++ b/xbmc/guilib/GUIRSSControl.cpp -@@ -119,7 +119,9 @@ void CGUIRSSControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyre - dirty = true; - - if (CRssManager::Get().GetReader(GetID(), GetParentID(), this, m_pReader)) -- m_scrollInfo.characterPos = m_pReader->m_SavedScrollPos; -+ { -+ m_scrollInfo.pixelPos = m_pReader->m_savedScrollPixelPos; -+ } - else - { - if (m_strRSSTags != "") -@@ -177,7 +179,7 @@ void CGUIRSSControl::Render() - if (m_pReader) - { - m_pReader->CheckForUpdates(); -- m_pReader->m_SavedScrollPos = m_scrollInfo.characterPos; -+ m_pReader->m_savedScrollPixelPos = m_scrollInfo.pixelPos; - } - } - CGUIControl::Render(); -diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp -index 12bbeb5..505a02d 100644 ---- a/xbmc/utils/RssReader.cpp -+++ b/xbmc/utils/RssReader.cpp -@@ -54,7 +54,7 @@ CRssReader::CRssReader() : CThread("RSSReader") - m_pObserver = NULL; - m_spacesBetweenFeeds = 0; - m_bIsRunning = false; -- m_SavedScrollPos = 0; -+ m_savedScrollPixelPos = 0; - m_rtlText = false; - m_requestRefresh = false; - } -diff --git a/xbmc/utils/RssReader.h b/xbmc/utils/RssReader.h -index 2c6f366..b74faf2 100644 ---- a/xbmc/utils/RssReader.h -+++ b/xbmc/utils/RssReader.h -@@ -43,7 +43,7 @@ class CRssReader : public CThread - void SetObserver(IRssObserver* observer); - void CheckForUpdates(); - void requestRefresh(); -- unsigned int m_SavedScrollPos; -+ float m_savedScrollPixelPos; - - private: - void Process(); --- -1.9.3 - - -From 08ae1b29d2987df3738787df1267ddfe898df472 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Mon, 27 Jan 2014 23:21:10 +0000 -Subject: [PATCH 12/82] Move the application of the translation offsets into - the GLES code. Still all pure software at this stage. Main change is in the - data types at the interface between CGUIFontTTFBase and CGUIFontTTFGL. The - old way (array of vertices in m_vertex) are retained in addition, for the - sake`of cases that need to use software clipping on GLES, as well as for DX - and GL support where the new scheme is not (yet?) used. - ---- - xbmc/guilib/GUIFontTTF.cpp | 19 +++--------- - xbmc/guilib/GUIFontTTF.h | 17 +++++++++++ - xbmc/guilib/GUIFontTTFGL.cpp | 72 ++++++++++++++++++++++++++++++++------------ - 3 files changed, 73 insertions(+), 35 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 73f0e50..ad0a53b 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -215,6 +215,7 @@ void CGUIFontTTFBase::Clear() - g_freeTypeLibrary.ReleaseStroker(m_stroker); - m_stroker = NULL; - -+ m_vertexTrans.clear(); - m_vertex.clear(); - } - -@@ -310,6 +311,7 @@ void CGUIFontTTFBase::Begin() - { - if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin()) - { -+ m_vertexTrans.clear(); - m_vertex.clear(); - } - // Keep track of the nested begin/end calls. -@@ -457,23 +459,10 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - cursorX += ch->advance; - } - if (hardwareClipping) -- /* Append the new vertices (which we have just constructed in the cache) -- * to the set collected since the first Begin() call */ -- m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); -+ m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices)); - } - else if (hardwareClipping) -- { -- /* Apply the translation offset to the vertices from the cache after -- * appending them to the set collected since the first Begin() call */ -- m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end()); -- SVertex *v; -- for (v = &*m_vertex.end() - vertices.size(); v != &*m_vertex.end(); v++) -- { -- v->x += dynamicPos.m_x; -- v->y += dynamicPos.m_y; -- v->z += dynamicPos.m_z; -- } -- } -+ m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices)); - if (!hardwareClipping) - /* Append the new vertices (from the cache or otherwise) to the set collected - * since the first Begin() call */ -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index 78445ab..c71f90d 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -61,6 +61,14 @@ struct SVertex - unsigned char r, g, b, a; - #endif - float u, v; -+ struct SVertex Offset(float translate[3]) const -+ { -+ SVertex out = *this; -+ out.x += translate[0]; -+ out.y += translate[1]; -+ out.z += translate[2]; -+ return out; -+ } - }; - - -@@ -160,6 +168,15 @@ class CGUIFontTTFBase - bool m_bTextureLoaded; - unsigned int m_nTexture; - -+ struct CTranslatedVertices -+ { -+ float translateX; -+ float translateY; -+ float translateZ; -+ const std::vector *vertexBuffer; -+ CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer) {} -+ }; -+ std::vector m_vertexTrans; - std::vector m_vertex; - - float m_textureScaleX; -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index cb56987..f6aa081 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -146,34 +146,65 @@ void CGUIFontTTFGL::LastEnd() - GLint colLoc = g_Windowing.GUIShaderGetCol(); - GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); - -- // stack object until VBOs will be used -- std::vector vecVertices( 6 * (m_vertex.size() / 4) ); -- SVertex *vertices = &vecVertices[0]; -+ // Enable the attributes used by this shader -+ glEnableVertexAttribArray(posLoc); -+ glEnableVertexAttribArray(colLoc); -+ glEnableVertexAttribArray(tex0Loc); - -- for (size_t i=0; i 0) - { -- *vertices++ = m_vertex[i]; -- *vertices++ = m_vertex[i+1]; -- *vertices++ = m_vertex[i+2]; -+ // Deal with vertices that had to use software clipping -+ std::vector vecVertices( 6 * (m_vertex.size() / 4) ); -+ SVertex *vertices = &vecVertices[0]; - -- *vertices++ = m_vertex[i+1]; -- *vertices++ = m_vertex[i+3]; -- *vertices++ = m_vertex[i+2]; -- } -+ for (size_t i=0; i 0) -+ { -+ // Deal with the vertices that can be hardware clipped and therefore translated -+ std::vector vecVertices; -+ for (size_t i = 0; i < m_vertexTrans.size(); i++) -+ { -+ float translate[3] = { m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ }; -+ for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4) -+ { -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j].Offset(translate)); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate)); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate)); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate)); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3].Offset(translate)); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate)); -+ } -+ } -+ SVertex *vertices = &vecVertices[0]; - -- glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); -+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x)); -+ // Normalize color values. Does not affect Performance at all. -+ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r)); -+ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u)); -+ -+ glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); -+ } - -+ // Disable the attributes used by this shader - glDisableVertexAttribArray(posLoc); - glDisableVertexAttribArray(colLoc); - glDisableVertexAttribArray(tex0Loc); -@@ -201,6 +232,7 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight) - if (m_textureHeight < newHeight) - CLog::Log(LOGWARNING, "%s: allocated new texture with height of %d, requested %d", __FUNCTION__, m_textureHeight, newHeight); - m_staticCache.Flush(); -+ m_dynamicCache.Flush(); - - memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch()); - if (m_texture) --- -1.9.3 - - -From 96e5d3e05b9ac2cef47d2e2a6fc13c407f1f672e Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 15 Jan 2014 15:28:06 +0000 -Subject: [PATCH 13/82] Rather than applying the translation offsets to the - vertices, now applies them to the model view matrix from the top of the - matrix stack and pushes it over to OpenGL. The vertices themselves are still - all held client-side. - ---- - xbmc/guilib/GUIFontTTF.h | 8 ------- - xbmc/guilib/GUIFontTTFGL.cpp | 40 +++++++++++++++++++++----------- - xbmc/guilib/GUIShader.h | 1 + - xbmc/rendering/gles/RenderSystemGLES.cpp | 8 +++++++ - xbmc/rendering/gles/RenderSystemGLES.h | 1 + - 5 files changed, 36 insertions(+), 22 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index c71f90d..fde2085 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -61,14 +61,6 @@ struct SVertex - unsigned char r, g, b, a; - #endif - float u, v; -- struct SVertex Offset(float translate[3]) const -- { -- SVertex out = *this; -- out.x += translate[0]; -- out.y += translate[1]; -- out.z += translate[2]; -- return out; -- } - }; - - -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index f6aa081..fbffaa0 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -29,6 +29,7 @@ - #include "utils/log.h" - #include "utils/GLUtils.h" - #include "windowing/WindowingFactory.h" -+#include "guilib/MatrixGLES.h" - - // stuff for freetype - #include -@@ -145,6 +146,7 @@ void CGUIFontTTFGL::LastEnd() - GLint posLoc = g_Windowing.GUIShaderGetPos(); - GLint colLoc = g_Windowing.GUIShaderGetCol(); - GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); -+ GLint modelLoc = g_Windowing.GUIShaderGetModel(); - - // Enable the attributes used by this shader - glEnableVertexAttribArray(posLoc); -@@ -183,25 +185,35 @@ void CGUIFontTTFGL::LastEnd() - std::vector vecVertices; - for (size_t i = 0; i < m_vertexTrans.size(); i++) - { -- float translate[3] = { m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ }; -+ // Apply the translation to the currently active (top-of-stack) model view matrix -+ g_matrices.MatrixMode(MM_MODELVIEW); -+ g_matrices.PushMatrix(); -+ g_matrices.Translatef(m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ); -+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); -+ -+ vecVertices.clear(); - for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4) - { -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j].Offset(translate)); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate)); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate)); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate)); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3].Offset(translate)); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate)); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j]); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3]); -+ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]); - } -- } -- SVertex *vertices = &vecVertices[0]; -+ SVertex *vertices = &vecVertices[0]; - -- glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x)); -- // Normalize color values. Does not affect Performance at all. -- glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r)); -- glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u)); -+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x)); -+ // Normalize color values. Does not affect Performance at all. -+ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r)); -+ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u)); - -- glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); -+ glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); -+ -+ g_matrices.PopMatrix(); -+ } -+ // Restore the original model view matrix -+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); - } - - // Disable the attributes used by this shader -diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h -index 86ce4cc..ba01956 100644 ---- a/xbmc/guilib/GUIShader.h -+++ b/xbmc/guilib/GUIShader.h -@@ -41,6 +41,7 @@ class CGUIShader : public CGLSLShaderProgram - GLint GetCord1Loc() { return m_hCord1; } - GLint GetUniColLoc() { return m_hUniCol; } - GLint GetCoord0MatrixLoc() { return m_hCoord0Matrix; } -+ GLint GetModelLoc() { return m_hModel; } - bool HardwareClipIsPossible() { return m_clipPossible; } - GLfloat GetClipXFactor() { return m_clipXFactor; } - GLfloat GetClipXOffset() { return m_clipXOffset; } -diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp -index deb3afc..0904d1f 100644 ---- a/xbmc/rendering/gles/RenderSystemGLES.cpp -+++ b/xbmc/rendering/gles/RenderSystemGLES.cpp -@@ -691,4 +691,12 @@ bool CRenderSystemGLES::SupportsStereo(RENDER_STEREO_MODE mode) - } - } - -+GLint CRenderSystemGLES::GUIShaderGetModel() -+{ -+ if (m_pGUIshader[m_method]) -+ return m_pGUIshader[m_method]->GetModelLoc(); -+ -+ return -1; -+} -+ - #endif -diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h -index 81ee49e..d2f9cd1 100644 ---- a/xbmc/rendering/gles/RenderSystemGLES.h -+++ b/xbmc/rendering/gles/RenderSystemGLES.h -@@ -91,6 +91,7 @@ class CRenderSystemGLES : public CRenderSystemBase - GLint GUIShaderGetCoord1(); - GLint GUIShaderGetUniCol(); - GLint GUIShaderGetCoord0Matrix(); -+ GLint GUIShaderGetModel(); - - protected: - virtual void SetVSyncImpl(bool enable) = 0; --- -1.9.3 - - -From a831b39d8b967665371ccc99a9e8ee1679d8ae54 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 29 Jan 2014 13:21:19 +0000 -Subject: [PATCH 14/82] Enable hardware clipping. - ---- - xbmc/guilib/GUIFontTTF.cpp | 4 ++-- - xbmc/guilib/GUIFontTTF.h | 5 ++++- - xbmc/guilib/GUIFontTTFGL.cpp | 6 ++++++ - 3 files changed, 12 insertions(+), 3 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index ad0a53b..4dc4c8e 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -459,10 +459,10 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - cursorX += ch->advance; - } - if (hardwareClipping) -- m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices)); -+ m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices, g_graphicsContext.GetClipRegion())); - } - else if (hardwareClipping) -- m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices)); -+ m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices, g_graphicsContext.GetClipRegion())); - if (!hardwareClipping) - /* Append the new vertices (from the cache or otherwise) to the set collected - * since the first Begin() call */ -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index fde2085..5e7c31f 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -27,6 +27,8 @@ - * - */ - -+#include "Geometry.h" -+ - // forward definition - class CBaseTexture; - -@@ -166,7 +168,8 @@ class CGUIFontTTFBase - float translateY; - float translateZ; - const std::vector *vertexBuffer; -- CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer) {} -+ CRect clip; -+ CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {} - }; - std::vector m_vertexTrans; - std::vector m_vertex; -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index fbffaa0..b7618e1 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -185,6 +185,10 @@ void CGUIFontTTFGL::LastEnd() - std::vector vecVertices; - for (size_t i = 0; i < m_vertexTrans.size(); i++) - { -+ // Apply the clip rectangle -+ CRect clip = g_Windowing.ClipRectToScissorRect(m_vertexTrans[i].clip); -+ g_graphicsContext.SetScissors(clip); -+ - // Apply the translation to the currently active (top-of-stack) model view matrix - g_matrices.MatrixMode(MM_MODELVIEW); - g_matrices.PushMatrix(); -@@ -212,6 +216,8 @@ void CGUIFontTTFGL::LastEnd() - - g_matrices.PopMatrix(); - } -+ // Restore the original scissor rectangle -+ g_graphicsContext.ResetScissors(); - // Restore the original model view matrix - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); - } --- -1.9.3 - - -From c65c7b0f23d31b1677b0cd60355eb28d05865977 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 15 Jan 2014 15:32:51 +0000 -Subject: [PATCH 15/82] Move the vertex data across to a vertex buffer object - just prior to drawing. - ---- - xbmc/guilib/GUIFontTTFGL.cpp | 24 +++++++++++++++++++----- - 1 file changed, 19 insertions(+), 5 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index b7618e1..0df3749 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -207,12 +207,24 @@ void CGUIFontTTFGL::LastEnd() - } - SVertex *vertices = &vecVertices[0]; - -- glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x)); -- // Normalize color values. Does not affect Performance at all. -- glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r)); -- glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u)); -- -+ // Generate a unique buffer object name and put it in vertexBuffer -+ GLuint vertexBuffer; -+ glGenBuffers(1, &vertexBuffer); -+ // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point -+ glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); -+ // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER -+ // binding point (i.e. our buffer object) and initialise it from the -+ // specified client-side pointer -+ glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof *vertices, vertices, GL_STATIC_DRAW); -+ // Set up the offsets of the various vertex attributes within the buffer -+ // object bound to GL_ARRAY_BUFFER -+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x)); -+ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r)); -+ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u)); -+ // Do the actual drawing operation, using the full set of vertices in the buffer - glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); -+ // Release the buffer name for reuse -+ glDeleteBuffers(1, &vertexBuffer); - - g_matrices.PopMatrix(); - } -@@ -220,6 +232,8 @@ void CGUIFontTTFGL::LastEnd() - g_graphicsContext.ResetScissors(); - // Restore the original model view matrix - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); -+ // Unbind GL_ARRAY_BUFFER -+ glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - // Disable the attributes used by this shader --- -1.9.3 - - -From aff1d0b71b7a455daba6bbd29496fcdc9169e37e Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Wed, 15 Jan 2014 16:04:04 +0000 -Subject: [PATCH 16/82] Move vertex data into an OpenGL VBO when the font cache - entry is populated. The font cache now stores the "name" (handle) of the VBO, - rather than a vector of vertices. - ---- - xbmc/guilib/GUIFontCache.cpp | 6 ++++ - xbmc/guilib/GUIFontCache.h | 30 +++++++++++++++++- - xbmc/guilib/GUIFontTTF.cpp | 15 +++++++-- - xbmc/guilib/GUIFontTTF.h | 7 +++-- - xbmc/guilib/GUIFontTTFGL.cpp | 74 ++++++++++++++++++++++++++++++-------------- - xbmc/guilib/GUIFontTTFGL.h | 5 +++ - 6 files changed, 107 insertions(+), 30 deletions(-) - -diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp -index b66c00b..895fa72 100644 ---- a/xbmc/guilib/GUIFontCache.cpp -+++ b/xbmc/guilib/GUIFontCache.cpp -@@ -111,3 +111,9 @@ template void CGUIFontCacheEntry::~CGUIFontCacheEntry(); - template CGUIFontCacheDynamicValue &CGUIFontCache::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &); - template void CGUIFontCache::Flush(); -+ -+void CVertexBuffer::clear() -+{ -+ if (m_font != NULL) -+ m_font->DestroyVertexBuffer(*this); -+} -diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h -index d913dee..ff766bf 100644 ---- a/xbmc/guilib/GUIFontCache.h -+++ b/xbmc/guilib/GUIFontCache.h -@@ -234,7 +234,35 @@ struct CGUIFontCacheDynamicPosition - } - }; - --typedef std::vector CGUIFontCacheDynamicValue; -+struct CVertexBuffer -+{ -+ void *bufferHandle; -+ size_t size; -+ CVertexBuffer() : bufferHandle(NULL), size(0), m_font(NULL) {} -+ CVertexBuffer(void *bufferHandle, size_t size, const CGUIFontTTFBase *font) : bufferHandle(bufferHandle), size(size), m_font(font) {} -+ CVertexBuffer(const CVertexBuffer &other) : bufferHandle(other.bufferHandle), size(other.size), m_font(other.m_font) -+ { -+ /* In practice, the copy constructor is only called before a vertex buffer -+ * has been attached. If this should ever change, we'll need another support -+ * function in GUIFontTTFGL/DX to duplicate a buffer, given its handle. */ -+ assert(other.bufferHandle == 0); -+ } -+ CVertexBuffer &operator=(CVertexBuffer &other) -+ { -+ /* This is used with move-assignment semantics for initialising the object in the font cache */ -+ assert(bufferHandle == 0); -+ bufferHandle = other.bufferHandle; -+ other.bufferHandle = 0; -+ size = other.size; -+ m_font = other.m_font; -+ return *this; -+ } -+ void clear(); -+private: -+ const CGUIFontTTFBase *m_font; -+}; -+ -+typedef CVertexBuffer CGUIFontCacheDynamicValue; - - inline bool Match(const CGUIFontCacheDynamicPosition &a, const TransformMatrix &a_m, - const CGUIFontCacheDynamicPosition &b, const TransformMatrix &b_m, -diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp -index 4dc4c8e..8b25306 100644 ---- a/xbmc/guilib/GUIFontTTF.cpp -+++ b/xbmc/guilib/GUIFontTTF.cpp -@@ -343,13 +343,18 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - g_graphicsContext.ScaleFinalYCoord(x, y), - g_graphicsContext.ScaleFinalZCoord(x, y)); - } -- std::vector &vertices = hardwareClipping ? -+ CVertexBuffer unusedVertexBuffer; -+ CVertexBuffer &vertexBuffer = hardwareClipping ? - m_dynamicCache.Lookup(dynamicPos, - colors, text, - alignment, maxPixelWidth, - scrolling, - XbmcThreads::SystemClockMillis(), - dirtyCache) : -+ unusedVertexBuffer; -+ std::vector tempVertices; -+ std::vector &vertices = hardwareClipping ? -+ tempVertices : - m_staticCache.Lookup(staticPos, - colors, text, - alignment, maxPixelWidth, -@@ -459,10 +464,14 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors - cursorX += ch->advance; - } - if (hardwareClipping) -- m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices, g_graphicsContext.GetClipRegion())); -+ { -+ CVertexBuffer newVertexBuffer = CreateVertexBuffer(tempVertices); -+ vertexBuffer = newVertexBuffer; -+ m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertexBuffer, g_graphicsContext.GetClipRegion())); -+ } - } - else if (hardwareClipping) -- m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices, g_graphicsContext.GetClipRegion())); -+ m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertexBuffer, g_graphicsContext.GetClipRegion())); - if (!hardwareClipping) - /* Append the new vertices (from the cache or otherwise) to the set collected - * since the first Begin() call */ -diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h -index 5e7c31f..b1cd525 100644 ---- a/xbmc/guilib/GUIFontTTF.h -+++ b/xbmc/guilib/GUIFontTTF.h -@@ -84,6 +84,9 @@ class CGUIFontTTFBase - - void Begin(); - void End(); -+ /* The next two should only be called if we've declared we can do hardware clipping */ -+ virtual CVertexBuffer CreateVertexBuffer(const std::vector &vertices) const { assert(false); return CVertexBuffer(); } -+ virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const {} - - const CStdString& GetFileName() const { return m_strFileName; }; - -@@ -167,9 +170,9 @@ class CGUIFontTTFBase - float translateX; - float translateY; - float translateZ; -- const std::vector *vertexBuffer; -+ const CVertexBuffer *vertexBuffer; - CRect clip; -- CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {} -+ CTranslatedVertices(float translateX, float translateY, float translateZ, const CVertexBuffer *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {} - }; - std::vector m_vertexTrans; - std::vector m_vertex; -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index 0df3749..1cd684b7 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -49,6 +49,10 @@ CGUIFontTTFGL::CGUIFontTTFGL(const CStdString& strFileName) - - CGUIFontTTFGL::~CGUIFontTTFGL(void) - { -+ // It's important that all the CGUIFontCacheEntry objects are -+ // destructed before the CGUIFontTTFGL goes out of scope, because -+ // our virtual methods won't be accessible after this point -+ m_dynamicCache.Flush(); - } - - bool CGUIFontTTFGL::FirstBegin() -@@ -182,7 +186,6 @@ void CGUIFontTTFGL::LastEnd() - if (m_vertexTrans.size() > 0) - { - // Deal with the vertices that can be hardware clipped and therefore translated -- std::vector vecVertices; - for (size_t i = 0; i < m_vertexTrans.size(); i++) - { - // Apply the clip rectangle -@@ -195,36 +198,17 @@ void CGUIFontTTFGL::LastEnd() - g_matrices.Translatef(m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ); - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); - -- vecVertices.clear(); -- for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4) -- { -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j]); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3]); -- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]); -- } -- SVertex *vertices = &vecVertices[0]; -- -- // Generate a unique buffer object name and put it in vertexBuffer -- GLuint vertexBuffer; -- glGenBuffers(1, &vertexBuffer); - // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point -- glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); -- // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER -- // binding point (i.e. our buffer object) and initialise it from the -- // specified client-side pointer -- glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof *vertices, vertices, GL_STATIC_DRAW); -+ glBindBuffer(GL_ARRAY_BUFFER, (GLuint) m_vertexTrans[i].vertexBuffer->bufferHandle); -+ - // Set up the offsets of the various vertex attributes within the buffer - // object bound to GL_ARRAY_BUFFER - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x)); - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r)); - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u)); -+ - // Do the actual drawing operation, using the full set of vertices in the buffer -- glDrawArrays(GL_TRIANGLES, 0, vecVertices.size()); -- // Release the buffer name for reuse -- glDeleteBuffers(1, &vertexBuffer); -+ glDrawArrays(GL_TRIANGLES, 0, 6 * m_vertexTrans[i].vertexBuffer->size); - - g_matrices.PopMatrix(); - } -@@ -245,6 +229,48 @@ void CGUIFontTTFGL::LastEnd() - #endif - } - -+#if HAS_GLES -+CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector &vertices) const -+{ -+ // Rearrange the vertices to describe triangles -+ std::vector triangleVertices; -+ triangleVertices.reserve(vertices.size() * 6 / 4); -+ for (size_t i = 0; i < vertices.size(); i += 4) -+ { -+ triangleVertices.push_back(vertices[i]); -+ triangleVertices.push_back(vertices[i+1]); -+ triangleVertices.push_back(vertices[i+2]); -+ triangleVertices.push_back(vertices[i+1]); -+ triangleVertices.push_back(vertices[i+3]); -+ triangleVertices.push_back(vertices[i+2]); -+ } -+ -+ // Generate a unique buffer object name and put it in bufferHandle -+ GLuint bufferHandle; -+ glGenBuffers(1, &bufferHandle); -+ // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point -+ glBindBuffer(GL_ARRAY_BUFFER, bufferHandle); -+ // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER -+ // binding point (i.e. our buffer object) and initialise it from the -+ // specified client-side pointer -+ glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof (SVertex), &triangleVertices[0], GL_STATIC_DRAW); -+ // Unbind GL_ARRAY_BUFFER -+ glBindBuffer(GL_ARRAY_BUFFER, 0); -+ -+ return CVertexBuffer((void *) bufferHandle, vertices.size() / 4, this); -+} -+ -+void CGUIFontTTFGL::DestroyVertexBuffer(CVertexBuffer &buffer) const -+{ -+ if (buffer.bufferHandle != 0) -+ { -+ // Release the buffer name for reuse -+ glDeleteBuffers(1, (GLuint *) &buffer.bufferHandle); -+ buffer.bufferHandle = 0; -+ } -+} -+#endif -+ - CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight) - { - newHeight = CBaseTexture::PadPow2(newHeight); -diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h -index 6736cf7..168fb21 100644 ---- a/xbmc/guilib/GUIFontTTFGL.h -+++ b/xbmc/guilib/GUIFontTTFGL.h -@@ -29,6 +29,7 @@ - - - #include "GUIFontTTF.h" -+#include "system.h" - - - /*! -@@ -43,6 +44,10 @@ class CGUIFontTTFGL : public CGUIFontTTFBase - - virtual bool FirstBegin(); - virtual void LastEnd(); -+#if HAS_GLES -+ virtual CVertexBuffer CreateVertexBuffer(const std::vector &vertices) const; -+ virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const; -+#endif - - protected: - virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); --- -1.9.3 - - -From a91376b246a7faabbeed9fec5b2510f1ec9917fc Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Thu, 16 Jan 2014 16:29:42 +0000 -Subject: [PATCH 17/82] Switch from glDrawArrays() to glDrawElements(). This - involves setting up a static VBO containing the indexes necessary to convert - from quads to triangles on the fly in the GPU. - ---- - xbmc/guilib/GUIFontTTFGL.cpp | 72 +++++++++++++++++++++++++------------ - xbmc/guilib/GUIFontTTFGL.h | 9 +++++ - xbmc/windowing/egl/WinSystemEGL.cpp | 17 +++++++++ - 3 files changed, 76 insertions(+), 22 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index 1cd684b7..d476409 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -186,6 +186,10 @@ void CGUIFontTTFGL::LastEnd() - if (m_vertexTrans.size() > 0) - { - // Deal with the vertices that can be hardware clipped and therefore translated -+ -+ // Bind our pre-calculated array to GL_ELEMENT_ARRAY_BUFFER -+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementArrayHandle); -+ - for (size_t i = 0; i < m_vertexTrans.size(); i++) - { - // Apply the clip rectangle -@@ -201,14 +205,21 @@ void CGUIFontTTFGL::LastEnd() - // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point - glBindBuffer(GL_ARRAY_BUFFER, (GLuint) m_vertexTrans[i].vertexBuffer->bufferHandle); - -- // Set up the offsets of the various vertex attributes within the buffer -- // object bound to GL_ARRAY_BUFFER -- glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x)); -- glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r)); -- glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u)); -+ // Do the actual drawing operation, split into groups of characters no -+ // larger than the pre-determined size of the element array -+ for (size_t character = 0; m_vertexTrans[i].vertexBuffer->size > character; character += ELEMENT_ARRAY_MAX_CHAR_INDEX) -+ { -+ size_t count = m_vertexTrans[i].vertexBuffer->size - character; -+ count = std::min(count, ELEMENT_ARRAY_MAX_CHAR_INDEX); -+ -+ // Set up the offsets of the various vertex attributes within the buffer -+ // object bound to GL_ARRAY_BUFFER -+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, x))); -+ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, r))); -+ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, u))); - -- // Do the actual drawing operation, using the full set of vertices in the buffer -- glDrawArrays(GL_TRIANGLES, 0, 6 * m_vertexTrans[i].vertexBuffer->size); -+ glDrawElements(GL_TRIANGLES, 6 * count, GL_UNSIGNED_SHORT, 0); -+ } - - g_matrices.PopMatrix(); - } -@@ -216,8 +227,9 @@ void CGUIFontTTFGL::LastEnd() - g_graphicsContext.ResetScissors(); - // Restore the original model view matrix - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); -- // Unbind GL_ARRAY_BUFFER -+ // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER - glBindBuffer(GL_ARRAY_BUFFER, 0); -+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - // Disable the attributes used by this shader -@@ -232,19 +244,6 @@ void CGUIFontTTFGL::LastEnd() - #if HAS_GLES - CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector &vertices) const - { -- // Rearrange the vertices to describe triangles -- std::vector triangleVertices; -- triangleVertices.reserve(vertices.size() * 6 / 4); -- for (size_t i = 0; i < vertices.size(); i += 4) -- { -- triangleVertices.push_back(vertices[i]); -- triangleVertices.push_back(vertices[i+1]); -- triangleVertices.push_back(vertices[i+2]); -- triangleVertices.push_back(vertices[i+1]); -- triangleVertices.push_back(vertices[i+3]); -- triangleVertices.push_back(vertices[i+2]); -- } -- - // Generate a unique buffer object name and put it in bufferHandle - GLuint bufferHandle; - glGenBuffers(1, &bufferHandle); -@@ -253,7 +252,7 @@ CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector &vert - // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER - // binding point (i.e. our buffer object) and initialise it from the - // specified client-side pointer -- glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof (SVertex), &triangleVertices[0], GL_STATIC_DRAW); -+ glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof (SVertex), &vertices[0], GL_STATIC_DRAW); - // Unbind GL_ARRAY_BUFFER - glBindBuffer(GL_ARRAY_BUFFER, 0); - -@@ -348,4 +347,33 @@ void CGUIFontTTFGL::DeleteHardwareTexture() - } - } - -+#if HAS_GLES -+void CGUIFontTTFGL::CreateStaticVertexBuffers(void) -+{ -+ // Bind a new buffer to the OpenGL context's GL_ELEMENT_ARRAY_BUFFER binding point -+ glGenBuffers(1, &m_elementArrayHandle); -+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementArrayHandle); -+ // Create an array holding the mesh indices to convert quads to triangles -+ GLushort index[ELEMENT_ARRAY_MAX_CHAR_INDEX][6]; -+ for (size_t i = 0; i < ELEMENT_ARRAY_MAX_CHAR_INDEX; i++) -+ { -+ index[i][0] = 4*i; -+ index[i][1] = 4*i+1; -+ index[i][2] = 4*i+2; -+ index[i][3] = 4*i+1; -+ index[i][4] = 4*i+3; -+ index[i][5] = 4*i+2; -+ } -+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof index, index, GL_STATIC_DRAW); -+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -+} -+ -+void CGUIFontTTFGL::DestroyStaticVertexBuffers(void) -+{ -+ glDeleteBuffers(1, &m_elementArrayHandle); -+} -+ -+GLuint CGUIFontTTFGL::m_elementArrayHandle; -+#endif -+ - #endif -diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h -index 168fb21..a14ab7a 100644 ---- a/xbmc/guilib/GUIFontTTFGL.h -+++ b/xbmc/guilib/GUIFontTTFGL.h -@@ -30,6 +30,7 @@ - - #include "GUIFontTTF.h" - #include "system.h" -+#include "system_gl.h" - - - /*! -@@ -47,6 +48,8 @@ class CGUIFontTTFGL : public CGUIFontTTFBase - #if HAS_GLES - virtual CVertexBuffer CreateVertexBuffer(const std::vector &vertices) const; - virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const; -+ static void CreateStaticVertexBuffers(void); -+ static void DestroyStaticVertexBuffers(void); - #endif - - protected: -@@ -54,6 +57,12 @@ class CGUIFontTTFGL : public CGUIFontTTFBase - virtual bool CopyCharToTexture(FT_BitmapGlyph bitGlyph, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2); - virtual void DeleteHardwareTexture(); - -+#if HAS_GLES -+#define ELEMENT_ARRAY_MAX_CHAR_INDEX (1000) -+ -+ static GLuint m_elementArrayHandle; -+#endif -+ - }; - - #endif -diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp -index 6de3532..258a293 100644 ---- a/xbmc/windowing/egl/WinSystemEGL.cpp -+++ b/xbmc/windowing/egl/WinSystemEGL.cpp -@@ -29,6 +29,7 @@ - #include "settings/AdvancedSettings.h" - #include "settings/Settings.h" - #include "settings/DisplaySettings.h" -+#include "guilib/GUIFontTTFGL.h" - #include "utils/log.h" - #include "EGLWrapper.h" - #include "EGLQuirks.h" -@@ -193,6 +194,9 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res) - return false; - } - -+#if HAS_GLES -+ bool newContext = false; -+#endif - if (m_context == EGL_NO_CONTEXT) - { - if (!m_egl->CreateContext(m_display, m_config, contextAttrs, &m_context)) -@@ -200,6 +204,9 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res) - CLog::Log(LOGERROR, "%s: Could not create context",__FUNCTION__); - return false; - } -+#if HAS_GLES -+ newContext = true; -+#endif - } - - if (!m_egl->BindContext(m_display, m_surface, m_context)) -@@ -208,6 +215,11 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res) - return false; - } - -+#if HAS_GLES -+ if (newContext) -+ CGUIFontTTFGL::CreateStaticVertexBuffers(); -+#endif -+ - // for the non-trivial dirty region modes, we need the EGL buffer to be preserved across updates - if (g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_COST_REDUCTION || - g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_UNION) -@@ -229,7 +241,12 @@ bool CWinSystemEGL::DestroyWindowSystem() - DestroyWindow(); - - if (m_context != EGL_NO_CONTEXT) -+ { -+#if HAS_GLES -+ CGUIFontTTFGL::DestroyStaticVertexBuffers(); -+#endif - m_egl->DestroyContext(m_display, m_context); -+ } - m_context = EGL_NO_CONTEXT; - - if (m_display != EGL_NO_DISPLAY) --- -1.9.3 - - -From de5a34228b32d0c909dbbb083e1be84ecffef6e4 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 4 Feb 2014 16:17:57 +0000 -Subject: [PATCH 18/82] Update Windows project files - ---- - project/VS2010Express/XBMC.vcxproj | 2 ++ - project/VS2010Express/XBMC.vcxproj.filters | 6 ++++++ - 2 files changed, 8 insertions(+) - -diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj -index 79e0219..936d5a1 100644 ---- a/project/VS2010Express/XBMC.vcxproj -+++ b/project/VS2010Express/XBMC.vcxproj -@@ -425,6 +425,7 @@ - - - -+ - - - -@@ -1740,6 +1741,7 @@ - - - -+ - - - -diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters -index 29f0879..e5a18dd 100644 ---- a/project/VS2010Express/XBMC.vcxproj.filters -+++ b/project/VS2010Express/XBMC.vcxproj.filters -@@ -1006,6 +1006,9 @@ - - guilib - -+ -+ guilib -+ - - guilib - -@@ -3918,6 +3921,9 @@ - - guilib - -+ -+ guilib -+ - - guilib - --- -1.9.3 - - -From d152a2347c58841fb80b74a829496793048e0b6b Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 4 Feb 2014 16:49:45 +0000 -Subject: [PATCH 19/82] Update XCode project file - ---- - XBMC.xcodeproj/project.pbxproj | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj -index 6adc55d..ebe3151 100644 ---- a/XBMC.xcodeproj/project.pbxproj -+++ b/XBMC.xcodeproj/project.pbxproj -@@ -168,6 +168,9 @@ - 1D638128161E211E003603ED /* PeripheralImon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D638126161E211E003603ED /* PeripheralImon.cpp */; }; - 1DAFDB7C16DFDCA7007F8C68 /* PeripheralBusCEC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DAFDB7A16DFDCA7007F8C68 /* PeripheralBusCEC.cpp */; }; - 1DE0443515828F4B005DDB4D /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DE0443315828F4B005DDB4D /* Exception.cpp */; }; -+ 2FD7EC5F18A14FE50047F86C /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */; }; -+ 2FD7EC6018A14FE50047F86C /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */; }; -+ 2FD7EC6118A14FE50047F86C /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */; }; - 32C631281423A90F00F18420 /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32C631261423A90F00F18420 /* JpegIO.cpp */; }; - 36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443B15821E2800727135 /* DatabaseUtils.cpp */; }; - 36A9444115821E7C00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443F15821E7C00727135 /* SortUtils.cpp */; }; -@@ -4016,6 +4019,8 @@ - 1DAFDB7B16DFDCA7007F8C68 /* PeripheralBusCEC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusCEC.h; sourceTree = ""; }; - 1DE0443315828F4B005DDB4D /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Exception.cpp; path = commons/Exception.cpp; sourceTree = ""; }; - 1DE0443415828F4B005DDB4D /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = commons/Exception.h; sourceTree = ""; }; -+ 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIFontCache.cpp; sourceTree = ""; }; -+ 2FD7EC5E18A14FE50047F86C /* GUIFontCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIFontCache.h; sourceTree = ""; }; - 32C631261423A90F00F18420 /* JpegIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JpegIO.cpp; sourceTree = ""; }; - 32C631271423A90F00F18420 /* JpegIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JpegIO.h; sourceTree = ""; }; - 36A9443B15821E2800727135 /* DatabaseUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseUtils.cpp; sourceTree = ""; }; -@@ -6526,6 +6531,8 @@ - 18B7C76A1294222E009E7A26 /* GUIFixedListContainer.cpp */, - 18B7C7101294222D009E7A26 /* GUIFixedListContainer.h */, - 18B7C76B1294222E009E7A26 /* GUIFont.cpp */, -+ 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */, -+ 2FD7EC5E18A14FE50047F86C /* GUIFontCache.h */, - 18B7C7111294222D009E7A26 /* GUIFont.h */, - 18B7C76C1294222E009E7A26 /* GUIFontManager.cpp */, - 18B7C7121294222D009E7A26 /* GUIFontManager.h */, -@@ -11846,6 +11853,7 @@ - 7CCDACC119275D790074CF51 /* NptAppleAutoreleasePool.mm in Sources */, - 7CCDACCA19275D790074CF51 /* NptAppleLogConfig.mm in Sources */, - 7CAA469019427AED00008885 /* PosixDirectory.cpp in Sources */, -+ 2FD7EC5F18A14FE50047F86C /* GUIFontCache.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -@@ -13039,6 +13047,7 @@ - 7CCDACC319275D790074CF51 /* NptAppleAutoreleasePool.mm in Sources */, - 7CCDACCC19275D790074CF51 /* NptAppleLogConfig.mm in Sources */, - 7CAA469219427AED00008885 /* PosixDirectory.cpp in Sources */, -+ 2FD7EC6118A14FE50047F86C /* GUIFontCache.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -@@ -14234,6 +14243,7 @@ - 7CCDACC219275D790074CF51 /* NptAppleAutoreleasePool.mm in Sources */, - 7CCDACCB19275D790074CF51 /* NptAppleLogConfig.mm in Sources */, - 7CAA469119427AED00008885 /* PosixDirectory.cpp in Sources */, -+ 2FD7EC6018A14FE50047F86C /* GUIFontCache.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; --- -1.9.3 - - -From 53f2f931d8afcb8a0abe5e5b34da5d511ab866e2 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 4 Feb 2014 17:44:34 +0000 -Subject: [PATCH 20/82] Clang seems to be more picky than gcc about some C++ - template syntax - ---- - xbmc/guilib/GUIFontCache.cpp | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp -index 895fa72..bd84b9a 100644 ---- a/xbmc/guilib/GUIFontCache.cpp -+++ b/xbmc/guilib/GUIFontCache.cpp -@@ -61,26 +61,26 @@ Value &CGUIFontCache::Lookup(Position &pos, - alignment, maxPixelWidth, - scrolling, g_graphicsContext.GetGUIMatrix(), - g_graphicsContext.GetGUIScaleX(), g_graphicsContext.GetGUIScaleY()); -- EntryHashIterator i = m_list.get().find(key); -- if (i == m_list.get().end()) -+ EntryHashIterator i = m_list.template get().find(key); -+ if (i == m_list.template get().end()) - { - /* Cache miss */ -- EntryAgeIterator oldest = m_list.get().begin(); -- if (!m_list.get().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT) -+ EntryAgeIterator oldest = m_list.template get().begin(); -+ if (!m_list.template get().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT) - { - /* The oldest existing entry is old enough to expire and reuse */ -- m_list.get().modify(m_list.project(oldest), typename CGUIFontCacheEntry::Reassign(key, nowMillis)); -- m_list.get().relocate(m_list.get().end(), oldest); -+ m_list.template get().modify(m_list.template project(oldest), typename CGUIFontCacheEntry::Reassign(key, nowMillis)); -+ m_list.template get().relocate(m_list.template get().end(), oldest); - } - else - { - /* We need a new entry instead */ - /* Yes, this causes the creation an destruction of a temporary entry, but - * this code ought to only be used infrequently, when the cache needs to grow */ -- m_list.get().push_back(CGUIFontCacheEntry(*this, key, nowMillis)); -+ m_list.template get().push_back(CGUIFontCacheEntry(*this, key, nowMillis)); - } - dirtyCache = true; -- return (--m_list.get().end())->m_value; -+ return (--m_list.template get().end())->m_value; - } - else - { -@@ -90,7 +90,7 @@ Value &CGUIFontCache::Lookup(Position &pos, - pos.UpdateWithOffsets(i->m_key.m_pos, scrolling); - /* Update time in entry and move to the back of the list */ - i->m_lastUsedMillis = nowMillis; -- m_list.get().relocate(m_list.get().end(), m_list.project(i)); -+ m_list.template get().relocate(m_list.template get().end(), m_list.template project(i)); - dirtyCache = false; - return i->m_value; - } -@@ -99,7 +99,7 @@ Value &CGUIFontCache::Lookup(Position &pos, - template - void CGUIFontCache::Flush() - { -- m_list.get().clear(); -+ m_list.template get().clear(); - } - - template void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry); --- -1.9.3 - - -From 54348adfcc7842d56e3e981c8935d2ae56dd3540 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 4 Feb 2014 18:52:14 +0000 -Subject: [PATCH 21/82] Fix header to hopefully permit iOS builds to work - again. GUIShader.cpp added #include windowing/egl/WinSystemEGL.h inside a but - also need the header windowing/osx/WinSystemIOS.h instead. The only thing - GUIShader.cpp needed was g_windowing.GetViewPort, which is provided by the - common base class CRenderSystemGLES of g_windowing in both cases, so I think - it should be sufficient to use windowing/WindowingFactory.h instead, which is - abstracted away from the other header files. - ---- - xbmc/guilib/GUIShader.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/guilib/GUIShader.cpp b/xbmc/guilib/GUIShader.cpp -index 53bce09..86330cc 100644 ---- a/xbmc/guilib/GUIShader.cpp -+++ b/xbmc/guilib/GUIShader.cpp -@@ -26,7 +26,7 @@ - #include "GUIShader.h" - #include "MatrixGLES.h" - #include "utils/log.h" --#include "windowing/egl/WinSystemEGL.h" -+#include "windowing/WindowingFactory.h" - #include "guilib/GraphicContext.h" - - CGUIShader::CGUIShader( const char *shader ) : CGLSLShaderProgram("guishader_vert.glsl", shader) --- -1.9.3 - - -From b8a96321efe1da06cac9129e545bc4aafff4457f Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Tue, 8 Apr 2014 18:14:55 +0100 -Subject: [PATCH 22/82] Fix font display in stereoscopic modes - CGUIFontTTFGL::LastEnd was previously using the relatively high-level - CGraphicContext::SetScissors function to enforce hardware clipping. However, - the coordinates it passed in already contained the stereoscopic offset, so - the CGraphicContext::SetScissors effectively ended up double-applying the - offset, with the effect that clip rectangles were always off-screen. Changed - to call the low-level SetScissors call instead (using g_Windowing to select - the correct implementation, e.g. CRenderSystemGLES::SetScissors). This also - skips the intersection of the scissors with the screen limits, but that does - not appear to matter in practice. - ---- - xbmc/guilib/GUIFontTTFGL.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp -index d476409..8466a81 100644 ---- a/xbmc/guilib/GUIFontTTFGL.cpp -+++ b/xbmc/guilib/GUIFontTTFGL.cpp -@@ -194,7 +194,7 @@ void CGUIFontTTFGL::LastEnd() - { - // Apply the clip rectangle - CRect clip = g_Windowing.ClipRectToScissorRect(m_vertexTrans[i].clip); -- g_graphicsContext.SetScissors(clip); -+ g_Windowing.SetScissors(clip); - - // Apply the translation to the currently active (top-of-stack) model view matrix - g_matrices.MatrixMode(MM_MODELVIEW); -@@ -224,7 +224,7 @@ void CGUIFontTTFGL::LastEnd() - g_matrices.PopMatrix(); - } - // Restore the original scissor rectangle -- g_graphicsContext.ResetScissors(); -+ g_Windowing.ResetScissors(); - // Restore the original model view matrix - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); - // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER --- -1.9.3 - - -From 65fb9cd6861394a8eac22722213e434dc1b55007 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 10 Jan 2014 12:10:43 +0000 -Subject: [PATCH 23/82] [rbp] Don't override dvdplayer with omxplayer. - -Using dvdplayer can be useful on the Pi. We can actually play sd (up to 640x480 MPEG-4 video) video in real time. -This is useful for codec variants like DivX3 which we don't currently play. - -This may expose bugs where dvdplayer is incorrectly used as the default player which will need to be fixed ---- - xbmc/cores/playercorefactory/PlayerCoreConfig.h | 7 ------- - 1 file changed, 7 deletions(-) - -diff --git a/xbmc/cores/playercorefactory/PlayerCoreConfig.h b/xbmc/cores/playercorefactory/PlayerCoreConfig.h -index 27f0bec..fc12bb7 100644 ---- a/xbmc/cores/playercorefactory/PlayerCoreConfig.h -+++ b/xbmc/cores/playercorefactory/PlayerCoreConfig.h -@@ -88,14 +88,7 @@ friend class CPlayerCoreFactory; - { - case EPC_MPLAYER: - // TODO: this hack needs removal until we have a better player selection --#if defined(HAS_OMXPLAYER) -- case EPC_DVDPLAYER: -- pPlayer = new COMXPlayer(callback); -- CLog::Log(LOGINFO, "Created player %s for core %d / OMXPlayer forced as DVDPlayer", "OMXPlayer", m_eCore); -- break; --#else - case EPC_DVDPLAYER: pPlayer = new CDVDPlayer(callback); break; --#endif - case EPC_PAPLAYER: pPlayer = new PAPlayer(callback); break; - case EPC_EXTPLAYER: pPlayer = new CExternalPlayer(callback); break; - #if defined(HAS_OMXPLAYER) --- -1.9.3 - - -From b4cc530053b9329b3641faf31e39873fb6962a4a Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 10 Jan 2014 15:37:41 +0000 -Subject: [PATCH 24/82] [players] Use default players rather than hard coded - DVDPlayer/PAPlayer - ---- - system/playercorefactory.xml | 23 ++++++++++++----------- - 1 file changed, 12 insertions(+), 11 deletions(-) - -diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml -index 57dfcdd..7be9799 100644 ---- a/system/playercorefactory.xml -+++ b/system/playercorefactory.xml -@@ -11,31 +11,32 @@ - - - -- -- -- -+ -+ -+ - - - -- -+ - - - -- -- -+ -+ - - - -- -- -+ -+ -+ - - -- -+ - - -- -+ - - -- -+ - - --- -1.9.3 - - -From bb81bc7ab31a99c134f4710c681dd8c652caae1f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 11 Jan 2014 18:23:42 +0000 -Subject: [PATCH 25/82] [rbp] Don't force dvdplayer for airplay - ---- - xbmc/network/AirPlayServer.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp -index 472463d..9f86eb7 100644 ---- a/xbmc/network/AirPlayServer.cpp -+++ b/xbmc/network/AirPlayServer.cpp -@@ -906,9 +906,11 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, - CFileItem fileToPlay(location, false); - fileToPlay.SetProperty("StartPercent", position*100.0f); - ServerInstance->AnnounceToClients(EVENT_LOADING); -+#ifndef TARGET_RASPBERRY_PI - // froce to internal dvdplayer cause it is the only - // one who will work well with airplay - g_application.m_eForcedNextPlayer = EPC_DVDPLAYER; -+#endif - CApplicationMessenger::Get().MediaPlay(fileToPlay); - } - } --- -1.9.3 - - -From a8da5af90041ba129025e0047a73030e8c4bb30d Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Jan 2014 13:11:06 +0000 -Subject: [PATCH 26/82] [rbp] Give plugins omxplayer when they request - dvdplayer on pi - ---- - xbmc/interfaces/legacy/ModuleXbmc.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp -index cf6693c..1170189 100644 ---- a/xbmc/interfaces/legacy/ModuleXbmc.cpp -+++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp -@@ -530,7 +530,11 @@ namespace XBMCAddon - int getPLAYLIST_MUSIC() { return PLAYLIST_MUSIC; } - int getPLAYLIST_VIDEO() { return PLAYLIST_VIDEO; } - int getPLAYER_CORE_AUTO() { return EPC_NONE; } -+#ifdef TARGET_RASPBERRY_PI -+ int getPLAYER_CORE_DVDPLAYER() { return EPC_OMXPLAYER; } -+#else - int getPLAYER_CORE_DVDPLAYER() { return EPC_DVDPLAYER; } -+#endif - int getPLAYER_CORE_MPLAYER() { return EPC_MPLAYER; } - int getPLAYER_CORE_PAPLAYER() { return EPC_PAPLAYER; } - int getTRAY_OPEN() { return TRAY_OPEN; } --- -1.9.3 - - -From 2decce910e8af54e880810ec18e8aa473ef39d36 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 14 Jan 2014 18:04:07 +0000 -Subject: [PATCH 27/82] [rbp] Allow ALSA to be chosen in addition to Pi sink - -Needs --enable-alsa in ./configure step and alsa support on platform ---- - configure.in | 1 - - tools/depends/target/Makefile | 5 +++-- - xbmc/cores/AudioEngine/AESinkFactory.cpp | 15 ++++++++++++++- - 3 files changed, 17 insertions(+), 4 deletions(-) - -diff --git a/configure.in b/configure.in -index 1766ce1..cb4728b 100644 ---- a/configure.in -+++ b/configure.in -@@ -705,7 +705,6 @@ case $use_platform in - use_arch="arm" - use_cpu=arm1176jzf-s - use_hardcoded_tables="yes" -- use_alsa="no" - ARCH="arm" - AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) - USE_OMXLIB=1; AC_DEFINE([HAVE_OMXLIB],[1],["Define to 1 if OMX libs is enabled"]) -diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile -index 3e02fc0..eea2a06 100644 ---- a/tools/depends/target/Makefile -+++ b/tools/depends/target/Makefile -@@ -57,10 +57,11 @@ LINUX_SYSTEM_LIBS= - ifeq ($(OS),linux) - #not for raspberry pi - ifneq ($(TARGET_PLATFORM),raspberry-pi) -- DEPENDS += alsa-lib libsdl linux-system-libs -- ALSA_LIB = alsa-lib -+ DEPENDS += libsdl linux-system-libs - LINUX_SYSTEM_LIBS = linux-system-libs - endif -+ DEPENDS += alsa-lib -+ ALSA_LIB = alsa-lib - FFMPEG_DEPENDS = gnutls - endif - -diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp -index e42d973..715b4f1 100644 ---- a/xbmc/cores/AudioEngine/AESinkFactory.cpp -+++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp -@@ -27,6 +27,7 @@ - #include "Sinks/AESinkAUDIOTRACK.h" - #elif defined(TARGET_RASPBERRY_PI) - #include "Sinks/AESinkPi.h" -+ #include "Sinks/AESinkALSA.h" - #elif defined(TARGET_DARWIN_IOS) - #include "Sinks/AESinkDARWINIOS.h" - #elif defined(TARGET_DARWIN_OSX) -@@ -66,6 +67,7 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver) - driver == "AUDIOTRACK" || - #elif defined(TARGET_RASPBERRY_PI) - driver == "PI" || -+ driver == "ALSA" || - #elif defined(TARGET_DARWIN_IOS) - driver == "DARWINIOS" || - #elif defined(TARGET_DARWIN_OSX) -@@ -105,7 +107,12 @@ IAESink *CAESinkFactory::TrySink(std::string &driver, std::string &device, AEAud - #elif defined(TARGET_ANDROID) - sink = new CAESinkAUDIOTRACK(); - #elif defined(TARGET_RASPBERRY_PI) -+ if (driver == "PI") - sink = new CAESinkPi(); -+ #if defined(HAS_ALSA) -+ if (driver == "ALSA") -+ sink = new CAESinkALSA(); -+ #endif - #elif defined(TARGET_DARWIN_IOS) - sink = new CAESinkDARWINIOS(); - #elif defined(TARGET_DARWIN_OSX) -@@ -196,7 +203,13 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force) - CAESinkPi::EnumerateDevicesEx(info.m_deviceInfoList, force); - if(!info.m_deviceInfoList.empty()) - list.push_back(info); -- -+ #if defined(HAS_ALSA) -+ info.m_deviceInfoList.clear(); -+ info.m_sinkName = "ALSA"; -+ CAESinkALSA::EnumerateDevicesEx(info.m_deviceInfoList, force); -+ if(!info.m_deviceInfoList.empty()) -+ list.push_back(info); -+ #endif - #elif defined(TARGET_DARWIN_IOS) - - info.m_deviceInfoList.clear(); --- -1.9.3 - - -From 04d854f558aacb7c65bdc094da6c7451d4bd1502 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 16 Jan 2014 01:39:29 +0000 -Subject: [PATCH 28/82] [omxcodec] Add hardware decode to dvdplayer for Pi - -Hijack the abandoned OpenMaxVideo codec ---- - configure.in | 21 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 12 +- - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 6 +- - xbmc/cores/VideoRenderers/RenderManager.cpp | 2 +- - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 7 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 7 +- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 295 +--- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 34 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 1 - - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp | 269 ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h | 116 -- - .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 1418 ++++++++++---------- - .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 120 +- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 21 +- - xbmc/linux/OMXCore.cpp | 45 +- - xbmc/linux/OMXCore.h | 2 +- - 17 files changed, 894 insertions(+), 1484 deletions(-) - delete mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp - delete mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h - -diff --git a/configure.in b/configure.in -index cb4728b..66ddeb9 100644 ---- a/configure.in -+++ b/configure.in -@@ -1947,9 +1947,24 @@ if test "$host_vendor" = "apple" ; then - USE_OPENMAX=0 - AC_MSG_NOTICE($openmax_disabled) - elif test "$target_platform" = "target_raspberry_pi"; then -- use_openmax="no" -- USE_OPENMAX=0 -- AC_MSG_NOTICE($openmax_disabled) -+ if test "$use_gles" = "yes" && test "$use_openmax" = "auto"; then -+ use_openmax="yes" -+ USE_OPENMAX=1 -+ HAVE_LIBOPENMAX=1 -+ AC_DEFINE([HAVE_LIBOPENMAX], [1], [Define to 1 if you have the 'LIBOPENMAX' library.]) -+ AC_DEFINE([OMX_SKIP64BIT], [1], [Define to 1 if you have the 'LIBOPENMAX' library.]) -+ AC_MSG_NOTICE($openmax_enabled) -+ elif test "$use_gles" = "yes" && test "$use_openmax" = "yes"; then -+ use_openmax="yes" -+ USE_OPENMAX=1 -+ HAVE_LIBOPENMAX=1 -+ AC_DEFINE([HAVE_LIBOPENMAX], [1], [Define to 1 if you have the 'LIBOPENMAX' library.]) -+ AC_MSG_NOTICE($openmax_enabled) -+ else -+ AC_MSG_NOTICE($openmax_disabled) -+ use_openmax=no -+ USE_OPENMAX=0 -+ fi - else - if test "$use_gles" = "yes" && test "$use_openmax" = "auto"; then - PKG_CHECK_MODULES([OPENMAX], [libomxil-bellagio], -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 72eb725..2e0d0ca 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -44,7 +44,7 @@ - #include "VideoShaders/VideoFilterShader.h" - #include "windowing/WindowingFactory.h" - #include "guilib/Texture.h" --#include "../dvdplayer/DVDCodecs/Video/OpenMaxVideo.h" -+#include "DVDCodecs/Video/OpenMaxVideo.h" - #include "threads/SingleLock.h" - #include "RenderCapture.h" - #include "RenderFormats.h" -@@ -1328,6 +1328,10 @@ void CLinuxRendererGLES::RenderOpenMax(int index, int field) - glActiveTexture(GL_TEXTURE0); - glBindTexture(m_textureTarget, textureId); - -+ GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); -+ - g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); - - GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip -@@ -2674,10 +2678,12 @@ unsigned int CLinuxRendererGLES::GetProcessorSize() - } - - #ifdef HAVE_LIBOPENMAX --void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index) -+void CLinuxRendererGLES::AddProcessor(COpenMaxVideoBuffer *openMaxBuffer, int index) - { - YUVBUFFER &buf = m_buffers[index]; -- buf.openMaxBuffer = picture->openMaxBuffer; -+ COpenMaxVideoBuffer *pic = openMaxBuffer->Acquire(); -+ SAFE_RELEASE(buf.openMaxBuffer); -+ buf.openMaxBuffer = pic; - } - #endif - #ifdef HAVE_VIDEOTOOLBOXDECODER -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -index 642cded..5a6a2be 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h -@@ -39,7 +39,7 @@ class CRenderCapture; - class CBaseTexture; - namespace Shaders { class BaseYUV2RGBShader; } - namespace Shaders { class BaseVideoFilterShader; } --class COpenMaxVideo; -+class COpenMaxVideoBuffer; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; - typedef std::vector Features; -@@ -158,7 +158,7 @@ class CLinuxRendererGLES : public CBaseRenderer - virtual std::vector SupportedFormats() { return m_formats; } - - #ifdef HAVE_LIBOPENMAX -- virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index); -+ virtual void AddProcessor(COpenMaxVideoBuffer *openMaxVideoBuffer, int index); - #endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index); -@@ -272,7 +272,7 @@ class CLinuxRendererGLES : public CBaseRenderer - unsigned flipindex; /* used to decide if this has been uploaded */ - - #ifdef HAVE_LIBOPENMAX -- OpenMaxVideoBuffer *openMaxBuffer; -+ COpenMaxVideoBuffer *openMaxBuffer; - #endif - #ifdef HAVE_VIDEOTOOLBOXDECODER - struct __CVBuffer *cvBufferRef; -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 6832721..3503988 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -912,7 +912,7 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - #endif - #ifdef HAVE_LIBOPENMAX - else if(pic.format == RENDER_FMT_OMXEGL) -- m_pRenderer->AddProcessor(pic.openMax, &pic, index); -+ m_pRenderer->AddProcessor(pic.openMaxBuffer, index); - #endif - #ifdef TARGET_DARWIN - else if(pic.format == RENDER_FMT_CVBREF) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index f77ac40..5d37395 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -268,9 +268,12 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - #endif - - #if defined(HAVE_LIBOPENMAX) -- if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software ) -+ if (!hint.software && CSettings::Get().GetBool("videoplayer.useomx")) - { -- if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1) -+ if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_H263 || hint.codec == AV_CODEC_ID_MPEG4 || -+ hint.codec == AV_CODEC_ID_MPEG1VIDEO || hint.codec == AV_CODEC_ID_MPEG2VIDEO || -+ hint.codec == AV_CODEC_ID_VP6 || hint.codec == AV_CODEC_ID_VP6F || hint.codec == AV_CODEC_ID_VP6A || hint.codec == AV_CODEC_ID_VP8 || -+ hint.codec == AV_CODEC_ID_THEORA || hint.codec == AV_CODEC_ID_MJPEG || hint.codec == AV_CODEC_ID_MJPEGB || hint.codec == AV_CODEC_ID_VC1 || hint.codec == AV_CODEC_ID_WMV3) - { - if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec; - } -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index 741017d..7daed00 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -48,9 +48,7 @@ struct DVDCodecAvailableType - namespace DXVA { class CSurfaceContext; } - namespace VAAPI { struct CHolder; } - namespace VDPAU { class CVdpauRenderPicture; } --class COpenMax; --class COpenMaxVideo; --struct OpenMaxVideoBuffer; -+class COpenMaxVideoBuffer; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; - typedef void* EGLImageKHR; -@@ -79,8 +77,7 @@ struct DVDVideoPicture - }; - - struct { -- COpenMax *openMax; -- OpenMaxVideoBuffer *openMaxBuffer; -+ COpenMaxVideoBuffer *openMaxBuffer; - }; - - struct { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -index b2e7816..7d33192 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -@@ -29,113 +29,43 @@ - #include "DVDStreamInfo.h" - #include "DVDVideoCodecOpenMax.h" - #include "OpenMaxVideo.h" -+#include "settings/Settings.h" - #include "utils/log.h" - --#define CLASSNAME "COpenMax" -+#define CLASSNAME "CDVDVideoCodecOpenMax" - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// --CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() : CDVDVideoCodec() -+CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() - { - m_omx_decoder = NULL; -- m_pFormatName = "omx-xxxx"; -- -- m_convert_bitstream = false; -- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); -+ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); - } - - CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax() - { -+ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); - Dispose(); - } - - bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - { -- // we always qualify even if DVDFactoryCodec does this too. -- if (CSettings::Get().GetBool("videoplayer.useomx") && !hints.software) -- { -- m_convert_bitstream = false; -- -- switch (hints.codec) -- { -- case AV_CODEC_ID_H264: -- { -- m_pFormatName = "omx-h264"; -- if (hints.extrasize < 7 || hints.extradata == NULL) -- { -- CLog::Log(LOGNOTICE, -- "%s::%s - avcC data too small or missing", CLASSNAME, __func__); -- return false; -- } -- // valid avcC data (bitstream) always starts with the value 1 (version) -- if ( *(char*)hints.extradata == 1 ) -- m_convert_bitstream = bitstream_convert_init(hints.extradata, hints.extrasize); -- } -- break; -- case AV_CODEC_ID_MPEG4: -- m_pFormatName = "omx-mpeg4"; -- break; -- case AV_CODEC_ID_MPEG2VIDEO: -- m_pFormatName = "omx-mpeg2"; -- break; -- case AV_CODEC_ID_VC1: -- m_pFormatName = "omx-vc1"; -- break; -- default: -- return false; -- break; -- } -- -- m_omx_decoder = new COpenMaxVideo; -- if (!m_omx_decoder->Open(hints)) -- { -- CLog::Log(LOGERROR, -- "%s::%s - failed to open, codec(%d), profile(%d), level(%d)", -- CLASSNAME, __func__, hints.codec, hints.profile, hints.level); -- return false; -- } -- -- // allocate a YV12 DVDVideoPicture buffer. -- // first make sure all properties are reset. -- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); -- -- m_videobuffer.dts = DVD_NOPTS_VALUE; -- m_videobuffer.pts = DVD_NOPTS_VALUE; -- //m_videobuffer.format = RENDER_FMT_YUV420P; -- m_videobuffer.format = RENDER_FMT_OMXEGL; -- m_videobuffer.color_range = 0; -- m_videobuffer.color_matrix = 4; -- m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; -- m_videobuffer.iWidth = hints.width; -- m_videobuffer.iHeight = hints.height; -- m_videobuffer.iDisplayWidth = hints.width; -- m_videobuffer.iDisplayHeight = hints.height; -- -- return true; -- } -+ m_omx_decoder = new COpenMaxVideo; -+ return m_omx_decoder->Open(hints, options); -+} - -- return false; -+const char* CDVDVideoCodecOpenMax::GetName(void) -+{ -+ return m_omx_decoder ? m_omx_decoder->GetName() : "omx-xxx"; - } - - void CDVDVideoCodecOpenMax::Dispose() - { - if (m_omx_decoder) - { -- m_omx_decoder->Close(); -+ m_omx_decoder->Dispose(); - delete m_omx_decoder; - m_omx_decoder = NULL; - } -- if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED) -- { -- m_videobuffer.iFlags = 0; -- } -- if (m_convert_bitstream) -- { -- if (m_sps_pps_context.sps_pps_data) -- { -- free(m_sps_pps_context.sps_pps_data); -- m_sps_pps_context.sps_pps_data = NULL; -- } -- } - } - - void CDVDVideoCodecOpenMax::SetDropState(bool bDrop) -@@ -145,37 +75,12 @@ void CDVDVideoCodecOpenMax::SetDropState(bool bDrop) - - int CDVDVideoCodecOpenMax::Decode(uint8_t* pData, int iSize, double dts, double pts) - { -- if (pData) -- { -- int rtn; -- int demuxer_bytes = iSize; -- uint8_t *demuxer_content = pData; -- bool bitstream_convered = false; -- -- if (m_convert_bitstream) -- { -- // convert demuxer packet from bitstream to bytestream (AnnexB) -- int bytestream_size = 0; -- uint8_t *bytestream_buff = NULL; -- -- bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size); -- if (bytestream_buff && (bytestream_size > 0)) -- { -- bitstream_convered = true; -- demuxer_bytes = bytestream_size; -- demuxer_content = bytestream_buff; -- } -- } -- -- rtn = m_omx_decoder->Decode(demuxer_content, demuxer_bytes, dts, pts); -- -- if (bitstream_convered) -- free(demuxer_content); -+ return m_omx_decoder->Decode(pData, iSize, dts, pts); -+} - -- return rtn; -- } -- -- return VC_BUFFER; -+unsigned CDVDVideoCodecOpenMax::GetAllowedReferences() -+{ -+ return m_omx_decoder->GetAllowedReferences(); - } - - void CDVDVideoCodecOpenMax::Reset(void) -@@ -185,172 +90,12 @@ void CDVDVideoCodecOpenMax::Reset(void) - - bool CDVDVideoCodecOpenMax::GetPicture(DVDVideoPicture* pDvdVideoPicture) - { -- m_omx_decoder->GetPicture(&m_videobuffer); -- *pDvdVideoPicture = m_videobuffer; -- -- return VC_PICTURE | VC_BUFFER; --} -- --//////////////////////////////////////////////////////////////////////////////////////////// --bool CDVDVideoCodecOpenMax::bitstream_convert_init(void *in_extradata, int in_extrasize) --{ -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- m_sps_pps_size = 0; -- m_sps_pps_context.sps_pps_data = NULL; -- -- // nothing to filter -- if (!in_extradata || in_extrasize < 6) -- return false; -- -- uint16_t unit_size; -- uint32_t total_size = 0; -- uint8_t *out = NULL, unit_nb, sps_done = 0; -- const uint8_t *extradata = (uint8_t*)in_extradata + 4; -- static const uint8_t nalu_header[4] = {0, 0, 0, 1}; -- -- // retrieve length coded size -- m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; -- if (m_sps_pps_context.length_size == 3) -- return false; -- -- // retrieve sps and pps unit(s) -- unit_nb = *extradata++ & 0x1f; // number of sps unit(s) -- if (!unit_nb) -- { -- unit_nb = *extradata++; // number of pps unit(s) -- sps_done++; -- } -- while (unit_nb--) -- { -- unit_size = extradata[0] << 8 | extradata[1]; -- total_size += unit_size + 4; -- if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) ) -- { -- free(out); -- return false; -- } -- uint8_t* new_out = (uint8_t*)realloc(out, total_size); -- if (new_out) -- { -- out = new_out; -- } -- else -- { -- CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__); -- free(out); -- return false; -- } -- -- memcpy(out + total_size - unit_size - 4, nalu_header, 4); -- memcpy(out + total_size - unit_size, extradata + 2, unit_size); -- extradata += 2 + unit_size; -- -- if (!unit_nb && !sps_done++) -- unit_nb = *extradata++; // number of pps unit(s) -- } -- -- m_sps_pps_context.sps_pps_data = out; -- m_sps_pps_context.size = total_size; -- m_sps_pps_context.first_idr = 1; -- -- return true; --} -- --bool CDVDVideoCodecOpenMax::bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) --{ -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- uint8_t *buf = pData; -- uint32_t buf_size = iSize; -- uint8_t unit_type; -- int32_t nal_size; -- uint32_t cumul_size = 0; -- const uint8_t *buf_end = buf + buf_size; -- -- do -- { -- if (buf + m_sps_pps_context.length_size > buf_end) -- goto fail; -- -- if (m_sps_pps_context.length_size == 1) -- nal_size = buf[0]; -- else if (m_sps_pps_context.length_size == 2) -- nal_size = buf[0] << 8 | buf[1]; -- else -- nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -- -- buf += m_sps_pps_context.length_size; -- unit_type = *buf & 0x1f; -- -- if (buf + nal_size > buf_end || nal_size < 0) -- goto fail; -- -- // prepend only to the first type 5 NAL unit of an IDR picture -- if (m_sps_pps_context.first_idr && unit_type == 5) -- { -- bitstream_alloc_and_copy(poutbuf, poutbuf_size, -- m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); -- m_sps_pps_context.first_idr = 0; -- } -- else -- { -- bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); -- if (!m_sps_pps_context.first_idr && unit_type == 1) -- m_sps_pps_context.first_idr = 1; -- } -- -- buf += nal_size; -- cumul_size += nal_size + m_sps_pps_context.length_size; -- } while (cumul_size < buf_size); -- -- return true; -- --fail: -- free(*poutbuf); -- *poutbuf = NULL; -- *poutbuf_size = 0; -- return false; -+ return m_omx_decoder->GetPicture(pDvdVideoPicture); - } - --void CDVDVideoCodecOpenMax::bitstream_alloc_and_copy( -- uint8_t **poutbuf, int *poutbuf_size, -- const uint8_t *sps_pps, uint32_t sps_pps_size, -- const uint8_t *in, uint32_t in_size) -+bool CDVDVideoCodecOpenMax::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - { -- // based on h264_mp4toannexb_bsf.c (ffmpeg) -- // which is Copyright (c) 2007 Benoit Fouet -- // and Licensed GPL 2.1 or greater -- -- #define CHD_WB32(p, d) { \ -- ((uint8_t*)(p))[3] = (d); \ -- ((uint8_t*)(p))[2] = (d) >> 8; \ -- ((uint8_t*)(p))[1] = (d) >> 16; \ -- ((uint8_t*)(p))[0] = (d) >> 24; } -- -- uint32_t offset = *poutbuf_size; -- uint8_t nal_header_size = offset ? 3 : 4; -- -- *poutbuf_size += sps_pps_size + in_size + nal_header_size; -- *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size); -- if (sps_pps) -- memcpy(*poutbuf + offset, sps_pps, sps_pps_size); -- -- memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); -- if (!offset) -- { -- CHD_WB32(*poutbuf + sps_pps_size, 1); -- } -- else -- { -- (*poutbuf + offset + sps_pps_size)[0] = 0; -- (*poutbuf + offset + sps_pps_size)[1] = 0; -- (*poutbuf + offset + sps_pps_size)[2] = 1; -- } -+ return m_omx_decoder->ClearPicture(pDvdVideoPicture); - } - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -index fb80d02..67cc235 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -@@ -23,7 +23,7 @@ - - #include "DVDVideoCodec.h" - --class COpenVideoMax; -+class COpenMaxVideo; - class CDVDVideoCodecOpenMax : public CDVDVideoCodec - { - public: -@@ -36,39 +36,13 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec - virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); - virtual void Reset(void); - virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); -+ virtual unsigned GetAllowedReferences(); - virtual void SetDropState(bool bDrop); -- virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ virtual const char* GetName(void); - - protected: -- const char *m_pFormatName; - COpenMaxVideo *m_omx_decoder; -- DVDVideoPicture m_videobuffer; -- -- // bitstream to bytestream (Annex B) conversion support. -- bool bitstream_convert_init(void *in_extradata, int in_extrasize); -- bool bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size); -- static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size, -- const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size); -- -- typedef struct omx_bitstream_ctx { -- uint8_t length_size; -- uint8_t first_idr; -- uint8_t *sps_pps_data; -- uint32_t size; -- -- omx_bitstream_ctx() -- { -- length_size = 0; -- first_idr = 0; -- sps_pps_data = NULL; -- size = 0; -- } -- -- } omx_bitstream_ctx; -- -- uint32_t m_sps_pps_size; -- omx_bitstream_ctx m_sps_pps_context; -- bool m_convert_bitstream; - }; - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 8a97889..ebf7123 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -20,7 +20,6 @@ SRCS += DVDVideoCodecVDA.cpp - SRCS += VDA.cpp - endif - ifeq (@USE_OPENMAX@,1) --SRCS += OpenMax.cpp - SRCS += OpenMaxVideo.cpp - SRCS += DVDVideoCodecOpenMax.cpp - endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp -deleted file mode 100644 -index 7b0a0c2ef..0000000 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp -+++ /dev/null -@@ -1,269 +0,0 @@ --/* -- * 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 -- * . -- * -- */ -- --#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) -- #include "config.h" --#elif defined(TARGET_WINDOWS) --#include "system.h" --#endif -- --#if defined(HAVE_LIBOPENMAX) --#include "OpenMax.h" --#include "DynamicDll.h" --#include "DVDClock.h" --#include "DVDStreamInfo.h" --#include "windowing/WindowingFactory.h" --#include "DVDVideoCodec.h" --#include "utils/log.h" --#include "utils/TimeUtils.h" --#include "ApplicationMessenger.h" --#include "Application.h" -- --#include --#include --#include --#include -- --#define CLASSNAME "COpenMax" -- -- --//////////////////////////////////////////////////////////////////////////////////////////// --class DllLibOpenMaxInterface --{ --public: -- virtual ~DllLibOpenMaxInterface() {} -- -- virtual OMX_ERRORTYPE OMX_Init(void) = 0; -- virtual OMX_ERRORTYPE OMX_Deinit(void) = 0; -- virtual OMX_ERRORTYPE OMX_GetHandle( -- OMX_HANDLETYPE *pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE *pCallBacks) = 0; -- virtual OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent) = 0; -- virtual OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_STRING role, OMX_U32 *pNumComps, OMX_U8 **compNames) = 0; -- virtual OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_STRING compName, OMX_U32 *pNumRoles, OMX_U8 **roles) = 0; -- virtual OMX_ERRORTYPE OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex) = 0; --}; -- --class DllLibOpenMax : public DllDynamic, DllLibOpenMaxInterface --{ -- DECLARE_DLL_WRAPPER(DllLibOpenMax, "/usr/lib/libnvomx.so") -- -- DEFINE_METHOD0(OMX_ERRORTYPE, OMX_Init) -- DEFINE_METHOD0(OMX_ERRORTYPE, OMX_Deinit) -- DEFINE_METHOD4(OMX_ERRORTYPE, OMX_GetHandle, (OMX_HANDLETYPE *p1, OMX_STRING p2, OMX_PTR p3, OMX_CALLBACKTYPE *p4)) -- DEFINE_METHOD1(OMX_ERRORTYPE, OMX_FreeHandle, (OMX_HANDLETYPE p1)) -- DEFINE_METHOD3(OMX_ERRORTYPE, OMX_GetComponentsOfRole, (OMX_STRING p1, OMX_U32 *p2, OMX_U8 **p3)) -- DEFINE_METHOD3(OMX_ERRORTYPE, OMX_GetRolesOfComponent, (OMX_STRING p1, OMX_U32 *p2, OMX_U8 **p3)) -- DEFINE_METHOD3(OMX_ERRORTYPE, OMX_ComponentNameEnum, (OMX_STRING p1, OMX_U32 p2, OMX_U32 p3)) -- BEGIN_METHOD_RESOLVE() -- RESOLVE_METHOD(OMX_Init) -- RESOLVE_METHOD(OMX_Deinit) -- RESOLVE_METHOD(OMX_GetHandle) -- RESOLVE_METHOD(OMX_FreeHandle) -- RESOLVE_METHOD(OMX_GetComponentsOfRole) -- RESOLVE_METHOD(OMX_GetRolesOfComponent) -- RESOLVE_METHOD(OMX_ComponentNameEnum) -- END_METHOD_RESOLVE() --}; -- --//////////////////////////////////////////////////////////////////////////////////////////// --#define OMX_INIT_STRUCTURE(a) \ -- memset(&(a), 0, sizeof(a)); \ -- (a).nSize = sizeof(a); \ -- (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \ -- (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \ -- (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \ -- (a).nVersion.s.nStep = OMX_VERSION_STEP -- --//////////////////////////////////////////////////////////////////////////////////////////// --//////////////////////////////////////////////////////////////////////////////////////////// --COpenMax::COpenMax() --{ -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif -- m_dll = new DllLibOpenMax; -- m_dll->Load(); -- m_is_open = false; -- -- m_omx_decoder = NULL; -- m_omx_client_state = DEAD; -- m_omx_decoder_state = 0; -- sem_init(m_omx_decoder_state_change, 0, 0); -- /* -- m_omx_flush_input = (sem_t*)malloc(sizeof(sem_t)); -- sem_init(m_omx_flush_input, 0, 0); -- m_omx_flush_output = (sem_t*)malloc(sizeof(sem_t)); -- sem_init(m_omx_flush_output, 0, 0); -- */ --} -- --COpenMax::~COpenMax() --{ -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif -- /* -- sem_destroy(m_omx_flush_input); -- free(m_omx_flush_input); -- sem_destroy(m_omx_flush_output); -- free(m_omx_flush_output); -- */ -- delete m_dll; --} -- -- -- -- --//////////////////////////////////////////////////////////////////////////////////////////// --// DecoderEventHandler -- OMX event callback --OMX_ERRORTYPE COpenMax::DecoderEventHandlerCallback( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, -- OMX_U32 nData1, -- OMX_U32 nData2, -- OMX_PTR pEventData) --{ -- COpenMax *ctx = (COpenMax*)pAppData; -- return ctx->DecoderEventHandler(hComponent, pAppData, eEvent, nData1, nData2, pEventData); --} -- --// DecoderEmptyBufferDone -- OpenMax input buffer has been emptied --OMX_ERRORTYPE COpenMax::DecoderEmptyBufferDoneCallback( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_BUFFERHEADERTYPE* pBuffer) --{ -- COpenMax *ctx = (COpenMax*)pAppData; -- return ctx->DecoderEmptyBufferDone( hComponent, pAppData, pBuffer); --} -- --// DecoderFillBufferDone -- OpenMax output buffer has been filled --OMX_ERRORTYPE COpenMax::DecoderFillBufferDoneCallback( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_BUFFERHEADERTYPE* pBuffer) --{ -- COpenMax *ctx = (COpenMax*)pAppData; -- return ctx->DecoderFillBufferDone(hComponent, pAppData, pBuffer); --} -- -- -- --// Wait for a component to transition to the specified state --OMX_ERRORTYPE COpenMax::WaitForState(OMX_STATETYPE state) --{ -- OMX_STATETYPE test_state; -- int tries = 0; -- struct timespec timeout; -- OMX_ERRORTYPE omx_error = OMX_GetState(m_omx_decoder, &test_state); -- -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - waiting for state(%d)\n", CLASSNAME, __func__, state); -- #endif -- while ((omx_error == OMX_ErrorNone) && (test_state != state)) -- { -- clock_gettime(CLOCK_REALTIME, &timeout); -- timeout.tv_sec += 1; -- sem_timedwait(m_omx_decoder_state_change, &timeout); -- if (errno == ETIMEDOUT) -- tries++; -- if (tries > 5) -- return OMX_ErrorUndefined; -- -- omx_error = OMX_GetState(m_omx_decoder, &test_state); -- } -- -- return omx_error; --} -- --// SetStateForAllComponents --// Blocks until all state changes have completed --OMX_ERRORTYPE COpenMax::SetStateForComponent(OMX_STATETYPE state) --{ -- OMX_ERRORTYPE omx_err; -- -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - state(%d)\n", CLASSNAME, __func__, state); -- #endif -- omx_err = OMX_SendCommand(m_omx_decoder, OMX_CommandStateSet, state, 0); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_CommandStateSet failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- else -- omx_err = WaitForState(state); -- -- return omx_err; --} -- --bool COpenMax::Initialize( const CStdString &decoder_name) --{ -- OMX_ERRORTYPE omx_err = m_dll->OMX_Init(); -- if (omx_err) -- { -- CLog::Log(LOGERROR, -- "%s::%s - OpenMax failed to init, status(%d), ", // codec(%d), profile(%d), level(%d) -- CLASSNAME, __func__, omx_err );//, hints.codec, hints.profile, hints.level); -- return false; -- } -- -- // Get video decoder handle setting up callbacks, component is in loaded state on return. -- static OMX_CALLBACKTYPE decoder_callbacks = { -- &DecoderEventHandlerCallback, &DecoderEmptyBufferDoneCallback, &DecoderFillBufferDoneCallback }; -- omx_err = m_dll->OMX_GetHandle(&m_omx_decoder, (char*)decoder_name.c_str(), this, &decoder_callbacks); -- if (omx_err) -- { -- CLog::Log(LOGERROR, -- "%s::%s - could not get decoder handle\n", CLASSNAME, __func__); -- m_dll->OMX_Deinit(); -- return false; -- } -- -- return true; --} -- --void COpenMax::Deinitialize() --{ -- CLog::Log(LOGERROR, -- "%s::%s - failed to get component port parameter\n", CLASSNAME, __func__); -- m_dll->OMX_FreeHandle(m_omx_decoder); -- m_omx_decoder = NULL; -- m_dll->OMX_Deinit(); --} -- --// OpenMax decoder callback routines. --OMX_ERRORTYPE COpenMax::DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData) --{ -- return OMX_ErrorNone; --} -- --OMX_ERRORTYPE COpenMax::DecoderEmptyBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer) --{ -- return OMX_ErrorNone; --} -- --OMX_ERRORTYPE COpenMax::DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader) --{ -- return OMX_ErrorNone; --} -- --#endif -- -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h -deleted file mode 100644 -index 0d9ff18..0000000 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h -+++ /dev/null -@@ -1,116 +0,0 @@ --#pragma once --/* -- * 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 -- * . -- * -- */ -- --#if defined(HAVE_LIBOPENMAX) -- --#include "cores/dvdplayer/DVDStreamInfo.h" --#include "DVDVideoCodec.h" --#include "threads/Event.h" -- --#include --#include --#include -- --//////////////////////////////////////////////////////////////////////////////////////////// --// debug spew defines --#if 0 --#define OMX_DEBUG_VERBOSE --#define OMX_DEBUG_EVENTHANDLER --#define OMX_DEBUG_FILLBUFFERDONE --#define OMX_DEBUG_EMPTYBUFFERDONE --#endif -- --typedef struct omx_codec_capability { -- // level is OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE, -- // or OMX_VIDEO_MPEG4PROFILETYPE depending on context. -- OMX_U32 level; -- // level is OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE, -- // or OMX_VIDEO_MPEG4PROFILETYPE depending on context. -- OMX_U32 profile; --} omx_codec_capability; -- --typedef struct omx_demux_packet { -- OMX_U8 *buff; -- int size; -- double dts; -- double pts; --} omx_demux_packet; -- --class DllLibOpenMax; --class COpenMax --{ --public: -- COpenMax(); -- virtual ~COpenMax(); -- --protected: -- enum OMX_CLIENT_STATE { -- DEAD, -- LOADED, -- LOADED_TO_IDLE, -- IDLE_TO_EXECUTING, -- EXECUTING, -- EXECUTING_TO_IDLE, -- IDLE_TO_LOADED, -- RECONFIGURING, -- ERROR -- }; -- -- // initialize OpenMax and get decoder component -- bool Initialize( const CStdString &decoder_name); -- void Deinitialize(); -- -- // OpenMax Decoder delegate callback routines. -- static OMX_ERRORTYPE DecoderEventHandlerCallback(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData); -- static OMX_ERRORTYPE DecoderEmptyBufferDoneCallback( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer); -- static OMX_ERRORTYPE DecoderFillBufferDoneCallback( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader); -- -- // OpenMax decoder callback routines. -- virtual OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData); -- virtual OMX_ERRORTYPE DecoderEmptyBufferDone( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer); -- virtual OMX_ERRORTYPE DecoderFillBufferDone( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader); -- -- // OpenMax helper routines -- OMX_ERRORTYPE WaitForState(OMX_STATETYPE state); -- OMX_ERRORTYPE SetStateForComponent(OMX_STATETYPE state); -- -- DllLibOpenMax *m_dll; -- bool m_is_open; -- OMX_HANDLETYPE m_omx_decoder; // openmax decoder component reference -- -- // OpenMax state tracking -- OMX_CLIENT_STATE m_omx_client_state; -- volatile int m_omx_decoder_state; -- sem_t *m_omx_decoder_state_change; -- std::vector m_omx_decoder_capabilities; -- --private: -- COpenMax(const COpenMax& other); -- COpenMax& operator=(const COpenMax&); --}; -- --#endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index dcbdb1e..aca2e0d 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -32,673 +32,891 @@ - #include "DVDVideoCodec.h" - #include "utils/log.h" - #include "utils/TimeUtils.h" -+#include "settings/Settings.h" - #include "ApplicationMessenger.h" - #include "Application.h" -+#include "threads/Atomics.h" - --#include --#include --#include --#include -+#include -+#include -+#include -+#include - -+#include "cores/omxplayer/OMXImage.h" -+ -+#define DTS_QUEUE -+ -+#define DEFAULT_TIMEOUT 1000 -+#ifdef _DEBUG -+#define OMX_DEBUG_VERBOSE -+#endif - - #define CLASSNAME "COpenMaxVideo" - --// TODO: These are Nvidia Tegra2 dependent, need to dynamiclly find the --// right codec matched to video format. --#define OMX_H264BASE_DECODER "OMX.Nvidia.h264.decode" --// OMX.Nvidia.h264ext.decode segfaults, not sure why. --//#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264ext.decode" --#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264.decode" --#define OMX_H264HIGH_DECODER "OMX.Nvidia.h264ext.decode" --#define OMX_MPEG4_DECODER "OMX.Nvidia.mp4.decode" --#define OMX_MPEG4EXT_DECODER "OMX.Nvidia.mp4ext.decode" --#define OMX_MPEG2V_DECODER "OMX.Nvidia.mpeg2v.decode" --#define OMX_VC1_DECODER "OMX.Nvidia.vc1.decode" -- --// EGL extension functions --static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; --static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; --#define GETEXTENSION(type, ext) \ --do \ --{ \ -- ext = (type) eglGetProcAddress(#ext); \ -- if (!ext) \ -- { \ -- CLog::Log(LOGERROR, "%s::%s - ERROR getting proc addr of " #ext "\n", CLASSNAME, __func__); \ -- } \ --} while (0); -- --#define OMX_INIT_STRUCTURE(a) \ -- memset(&(a), 0, sizeof(a)); \ -- (a).nSize = sizeof(a); \ -- (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \ -- (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \ -- (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \ -- (a).nVersion.s.nStep = OMX_VERSION_STEP -+COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv) -+ : m_omv(omv), m_refs(0) -+{ -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+ omx_buffer = NULL; -+ width = 0; -+ height = 0; -+ index = 0; -+ egl_image = 0; -+ texture_id = 0; -+} -+ -+COpenMaxVideoBuffer::~COpenMaxVideoBuffer() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+} - - --COpenMaxVideo::COpenMaxVideo() -+// DecoderFillBufferDone -- OpenMax output buffer has been filled -+static OMX_ERRORTYPE DecoderFillBufferDoneCallback( -+ OMX_HANDLETYPE hComponent, -+ OMX_PTR pAppData, -+ OMX_BUFFERHEADERTYPE* pBuffer) -+{ -+ COpenMaxVideoBuffer *pic = static_cast(pBuffer->pAppPrivate); -+ COpenMaxVideo *ctx = pic->m_omv; -+ return ctx->DecoderFillBufferDone(hComponent, pBuffer); -+} -+ -+ -+COpenMaxVideoBuffer* COpenMaxVideoBuffer::Acquire() -+{ -+ long count = AtomicIncrement(&m_refs); -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p ref:%ld", CLASSNAME, __func__, this, count); -+ #endif -+ (void)count; -+ return this; -+} -+ -+long COpenMaxVideoBuffer::Release() - { -- m_portChanging = false; -+ long count = AtomicDecrement(&m_refs); -+ if (count == 0) -+ { -+ m_omv->ReleaseOpenMaxBuffer(this); -+ } -+ -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p ref:%ld", CLASSNAME, __func__, this, count); -+ #endif -+ return count; -+} - -- pthread_mutex_init(&m_omx_input_mutex, NULL); -+void COpenMaxVideoBuffer::Sync() -+{ -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p ref:%ld", CLASSNAME, __func__, this, m_refs); -+ #endif -+ Release(); -+} -+ -+COpenMaxVideo::COpenMaxVideo() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); - pthread_mutex_init(&m_omx_output_mutex, NULL); - -- m_omx_decoder_state_change = (sem_t*)malloc(sizeof(sem_t)); -- sem_init(m_omx_decoder_state_change, 0, 0); -- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); - m_drop_state = false; - m_decoded_width = 0; - m_decoded_height = 0; -- m_omx_input_eos = false; -- m_omx_input_port = 0; -- m_omx_output_eos = false; -- m_omx_output_port = 0; -- m_videoplayback_done = false; -+ m_egl_buffer_count = 0; -+ -+ m_port_settings_changed = false; -+ m_pFormatName = "omx-xxxx"; - } - - COpenMaxVideo::~COpenMaxVideo() - { - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); - #endif -- if (m_is_open) -- Close(); -- pthread_mutex_destroy(&m_omx_input_mutex); -+ if (m_omx_decoder.IsInitialized()) -+ { -+ if (m_omx_tunnel.IsInitialized()) -+ m_omx_tunnel.Deestablish(); -+ -+ StopDecoder(); -+ -+ if (m_omx_egl_render.IsInitialized()) -+ m_omx_egl_render.Deinitialize(); -+ if (m_omx_decoder.IsInitialized()) -+ m_omx_decoder.Deinitialize(); -+ } - pthread_mutex_destroy(&m_omx_output_mutex); -- sem_destroy(m_omx_decoder_state_change); -- free(m_omx_decoder_state_change); - } - --bool COpenMaxVideo::Open(CDVDStreamInfo &hints) -+bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - { - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif - -+ // we always qualify even if DVDFactoryCodec does this too. -+ if (!CSettings::Get().GetBool("videoplayer.useomx") || hints.software) -+ return false; -+ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- std::string decoder_name; - - m_decoded_width = hints.width; - m_decoded_height = hints.height; - -+ m_egl_display = g_Windowing.GetEGLDisplay(); -+ m_egl_context = g_Windowing.GetEGLContext(); -+ m_egl_buffer_count = 4; -+ -+ m_codingType = OMX_VIDEO_CodingUnused; -+ - switch (hints.codec) - { - case AV_CODEC_ID_H264: -- { -- switch(hints.profile) -- { -- case FF_PROFILE_H264_BASELINE: -- // (role name) video_decoder.avc -- // H.264 Baseline profile -- decoder_name = OMX_H264BASE_DECODER; -- break; -- case FF_PROFILE_H264_MAIN: -- // (role name) video_decoder.avc -- // H.264 Main profile -- decoder_name = OMX_H264MAIN_DECODER; -- break; -- case FF_PROFILE_H264_HIGH: -- // (role name) video_decoder.avc -- // H.264 Main profile -- decoder_name = OMX_H264HIGH_DECODER; -- break; -- default: -- return false; -- break; -- } -- } -+ // H.264 -+ m_codingType = OMX_VIDEO_CodingAVC; -+ m_pFormatName = "omx-h264"; - break; -+ case AV_CODEC_ID_H263: - case AV_CODEC_ID_MPEG4: -- // (role name) video_decoder.mpeg4 -- // MPEG-4, DivX 4/5 and Xvid compatible -- decoder_name = OMX_MPEG4_DECODER; -- break; -- /* -- TODO: what mpeg4 formats are "ext" ???? -- case NvxStreamType_MPEG4Ext: -- // (role name) video_decoder.mpeg4 - // MPEG-4, DivX 4/5 and Xvid compatible -- decoder_name = OMX_MPEG4EXT_DECODER; -+ m_codingType = OMX_VIDEO_CodingMPEG4; - m_pFormatName = "omx-mpeg4"; - break; -- */ -+ case AV_CODEC_ID_MPEG1VIDEO: - case AV_CODEC_ID_MPEG2VIDEO: -- // (role name) video_decoder.mpeg2 - // MPEG-2 -- decoder_name = OMX_MPEG2V_DECODER; -+ m_codingType = OMX_VIDEO_CodingMPEG2; -+ m_pFormatName = "omx-mpeg2"; -+ break; -+ case AV_CODEC_ID_VP6: -+ // this form is encoded upside down -+ // fall through -+ case AV_CODEC_ID_VP6F: -+ case AV_CODEC_ID_VP6A: -+ // VP6 -+ m_codingType = OMX_VIDEO_CodingVP6; -+ m_pFormatName = "omx-vp6"; -+ break; -+ case AV_CODEC_ID_VP8: -+ // VP8 -+ m_codingType = OMX_VIDEO_CodingVP8; -+ m_pFormatName = "omx-vp8"; -+ break; -+ case AV_CODEC_ID_THEORA: -+ // theora -+ m_codingType = OMX_VIDEO_CodingTheora; -+ m_pFormatName = "omx-theora"; -+ break; -+ case AV_CODEC_ID_MJPEG: -+ case AV_CODEC_ID_MJPEGB: -+ // mjpg -+ m_codingType = OMX_VIDEO_CodingMJPEG; -+ m_pFormatName = "omx-mjpg"; - break; - case AV_CODEC_ID_VC1: -- // (role name) video_decoder.vc1 -+ case AV_CODEC_ID_WMV3: - // VC-1, WMV9 -- decoder_name = OMX_VC1_DECODER; -- break; -+ m_codingType = OMX_VIDEO_CodingWMV; -+ m_pFormatName = "omx-vc1"; -+ break; - default: -+ CLog::Log(LOGERROR, "%s::%s : Video codec unknown: %x", CLASSNAME, __func__, hints.codec); - return false; - break; - } - - // initialize OpenMAX. -- if (!Initialize(decoder_name)) -+ if (!m_omx_decoder.Initialize("OMX.broadcom.video_decode", OMX_IndexParamVideoInit)) - { -+ CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize", CLASSNAME, __func__); - return false; - } - -- // TODO: Find component from role name. -- // Get the port information. This will obtain information about the -- // number of ports and index of the first port. -- OMX_PORT_PARAM_TYPE port_param; -- OMX_INIT_STRUCTURE(port_param); -- omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamVideoInit, &port_param); -- if (omx_err) -+ omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); -+ if (omx_err != OMX_ErrorNone) - { -- Deinitialize(); -+ CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - return false; - } -- m_omx_input_port = port_param.nStartPortNumber; -- m_omx_output_port = m_omx_input_port + 1; -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x)\n", -- CLASSNAME, __func__, m_omx_decoder, m_omx_input_port, m_omx_output_port); -- #endif - -- // TODO: Set role for the component because components could have multiple roles. -- //QueryCodec(); -+ OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; -+ OMX_INIT_STRUCTURE(formatType); -+ formatType.nPortIndex = m_omx_decoder.GetInputPort(); -+ formatType.eCompressionFormat = m_codingType; -+ -+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ OMX_PARAM_PORTDEFINITIONTYPE portParam; -+ OMX_INIT_STRUCTURE(portParam); -+ portParam.nPortIndex = m_omx_decoder.GetInputPort(); -+ -+ omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s error OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ portParam.nPortIndex = m_omx_decoder.GetInputPort(); -+ portParam.nBufferCountActual = 20; -+ portParam.format.video.nFrameWidth = m_decoded_width; -+ portParam.format.video.nFrameHeight = m_decoded_height; -+ -+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s error OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ // request portsettingschanged on aspect ratio change -+ OMX_CONFIG_REQUESTCALLBACKTYPE notifications; -+ OMX_INIT_STRUCTURE(notifications); -+ notifications.nPortIndex = m_omx_decoder.GetOutputPort(); -+ notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio; -+ notifications.bEnable = OMX_TRUE; -+ -+ omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, ¬ifications); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s OMX_IndexConfigRequestCallback error (0%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ if (NaluFormatStartCodes(hints.codec, (uint8_t *)hints.extradata, hints.extrasize)) -+ { -+ OMX_NALSTREAMFORMATTYPE nalStreamFormat; -+ OMX_INIT_STRUCTURE(nalStreamFormat); -+ nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); -+ nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; -+ -+ omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s OMX_IndexParamNalStreamFormatSelect error (0%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ } - -- // Component will be in OMX_StateLoaded now so we can alloc omx input/output buffers. -- // we can only alloc them in OMX_StateLoaded state or if the component port is disabled - // Alloc buffers for the omx input port. -- omx_err = AllocOMXInputBuffers(); -- if (omx_err) -+ omx_err = m_omx_decoder.AllocInputBuffers(); -+ if (omx_err != OMX_ErrorNone) - { -- Deinitialize(); -+ CLog::Log(LOGERROR, "%s::%s AllocInputBuffers error (0%08x)", CLASSNAME, __func__, omx_err); - return false; - } -- // Alloc buffers for the omx output port. -- m_egl_display = g_Windowing.GetEGLDisplay(); -- m_egl_context = g_Windowing.GetEGLContext(); -- omx_err = AllocOMXOutputBuffers(); -- if (omx_err) -+ -+ omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); -+ if (omx_err != OMX_ErrorNone) - { -- FreeOMXInputBuffers(false); -- Deinitialize(); -+ CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.SetStateForComponent error (0%08x)", CLASSNAME, __func__, omx_err); - return false; - } - -- m_is_open = true; -- m_drop_state = false; -- m_videoplayback_done = false; -+ if (!SendDecoderConfig((uint8_t *)hints.extradata, hints.extrasize)) -+ return false; - -- // crank it up. -- StartDecoder(); -+ m_drop_state = false; - - return true; - } - --void COpenMaxVideo::Close() -+void COpenMaxVideo::Dispose() - { - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif -- if (m_omx_decoder) -- { -- if (m_omx_decoder_state != OMX_StateLoaded) -- StopDecoder(); -- Deinitialize(); -- } -- m_is_open = false; - } - - void COpenMaxVideo::SetDropState(bool bDrop) - { -+#if defined(OMX_DEBUG_VERBOSE) -+ if (m_drop_state != bDrop) -+ CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)", -+ CLASSNAME, __func__, bDrop); -+#endif - m_drop_state = bDrop; -+} - -- if (m_drop_state) -+bool COpenMaxVideo::SendDecoderConfig(uint8_t *extradata, int extrasize) -+{ -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; -+ -+ /* send decoder config */ -+ if (extrasize > 0 && extradata != NULL) - { -- OMX_ERRORTYPE omx_err; -+ OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(); - -- // blow all but the last ready video frame -- pthread_mutex_lock(&m_omx_output_mutex); -- while (m_omx_output_ready.size() > 1) -+ if (omx_buffer == NULL) - { -- m_dts_queue.pop(); -- OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_output_ready.front()->omx_buffer; -- m_omx_output_ready.pop(); -- // return the omx buffer back to OpenMax to fill. -- omx_err = OMX_FillThisBuffer(m_omx_decoder, omx_buffer); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -+ CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err); -+ return false; - } -- pthread_mutex_unlock(&m_omx_output_mutex); - -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)\n", -- CLASSNAME, __func__, m_drop_state); -- #endif -+ omx_buffer->nOffset = 0; -+ omx_buffer->nFilledLen = extrasize; -+ if (omx_buffer->nFilledLen > omx_buffer->nAllocLen) -+ { -+ CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__); -+ return false; -+ } -+ -+ memcpy((unsigned char *)omx_buffer->pBuffer, extradata, omx_buffer->nFilledLen); -+ omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; -+ -+//CLog::Log(LOGINFO, "%s::%s - Empty(%d,%x)", CLASSNAME, __func__, omx_buffer->nFilledLen, omx_buffer->nFlags); CLog::MemDump((char *)omx_buffer->pBuffer, std::min(64U, omx_buffer->nFilledLen)); -+ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } - } -+ return true; - } - --int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) -+bool COpenMaxVideo::NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize) -+{ -+ switch(codec) -+ { -+ case AV_CODEC_ID_H264: -+ if (extrasize < 7 || extradata == NULL) -+ return true; -+ // valid avcC atom data always starts with the value 1 (version), otherwise annexb -+ else if ( *extradata != 1 ) -+ return true; -+ default: break; -+ } -+ return false; -+} -+ -+bool COpenMaxVideo::PortSettingsChanged() - { -- if (pData) -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; -+ -+ if (m_port_settings_changed) -+ { -+ m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true); -+ } -+ -+ OMX_PARAM_PORTDEFINITIONTYPE port_def; -+ OMX_INIT_STRUCTURE(port_def); -+ port_def.nPortIndex = m_omx_decoder.GetOutputPort(); -+ omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ OMX_CONFIG_POINTTYPE pixel_aspect; -+ OMX_INIT_STRUCTURE(pixel_aspect); -+ pixel_aspect.nPortIndex = m_omx_decoder.GetOutputPort(); -+ omx_err = m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio, &pixel_aspect); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ if (m_port_settings_changed) - { -- int demuxer_bytes = iSize; -- uint8_t *demuxer_content = pData; -+ m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true); -+ return true; -+ } -+ -+ // convert in stripes -+ port_def.format.video.nSliceHeight = 16; -+ port_def.format.video.nStride = 0; -+ -+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter result(0x%x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ OMX_CALLBACKTYPE callbacks = { NULL, NULL, DecoderFillBufferDoneCallback }; -+ if (!m_omx_egl_render.Initialize("OMX.broadcom.egl_render", OMX_IndexParamVideoInit, &callbacks)) -+ { -+ CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.Initialize", CLASSNAME, __func__); -+ return false; -+ } -+ -+ OMX_CONFIG_PORTBOOLEANTYPE discardMode; -+ OMX_INIT_STRUCTURE(discardMode); -+ discardMode.nPortIndex = m_omx_egl_render.GetInputPort(); -+ discardMode.bEnabled = OMX_FALSE; -+ omx_err = m_omx_egl_render.SetParameter(OMX_IndexParamBrcmVideoEGLRenderDiscardMode, &discardMode); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - error m_omx_egl_render.SetParameter(OMX_IndexParamBrcmVideoEGLRenderDiscardMode) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ m_omx_egl_render.ResetEos(); -+ -+ CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__, -+ port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight, -+ port_def.format.video.xFramerate / (float)(1<<16), 0,0); -+ -+ m_omx_tunnel.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort()); -+ -+ omx_err = m_omx_tunnel.Establish(); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ // Obtain the information about the output port. -+ OMX_PARAM_PORTDEFINITIONTYPE port_format; -+ OMX_INIT_STRUCTURE(port_format); -+ port_format.nPortIndex = m_omx_egl_render.GetOutputPort(); -+ omx_err = m_omx_egl_render.GetParameter(OMX_IndexParamPortDefinition, &port_format); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.GetParameter OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ port_format.nBufferCountActual = m_egl_buffer_count; -+ omx_err = m_omx_egl_render.SetParameter(OMX_IndexParamPortDefinition, &port_format); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.SetParameter OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, -+ "%s::%s (1) - oport(%d), nFrameWidth(%u), nFrameHeight(%u), nStride(%x), nBufferCountMin(%u), nBufferCountActual(%u), nBufferSize(%u)", -+ CLASSNAME, __func__, m_omx_egl_render.GetOutputPort(), -+ port_format.format.video.nFrameWidth, port_format.format.video.nFrameHeight,port_format.format.video.nStride, -+ port_format.nBufferCountMin, port_format.nBufferCountActual, port_format.nBufferSize); -+ #endif -+ - -- // we need to queue then de-queue the demux packet, seems silly but -- // omx might not have a omx input buffer avaliable when we are called -- // and we must store the demuxer packet and try again later. -+ omx_err = m_omx_egl_render.EnablePort(m_omx_egl_render.GetOutputPort(), false); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.EnablePort omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ if (!AllocOMXOutputBuffers()) -+ { -+ CLog::Log(LOGERROR, "%s::%s - AllocOMXOutputBuffers failed", CLASSNAME, __func__); -+ return false; -+ } -+ -+ omx_err = m_omx_egl_render.WaitForCommand(OMX_CommandPortEnable, m_omx_egl_render.GetOutputPort()); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.WaitForCommand(OMX_CommandPortEnable) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ assert(m_omx_output_busy.empty()); -+ assert(m_omx_output_ready.empty()); -+ -+ omx_err = m_omx_egl_render.SetStateForComponent(OMX_StateExecuting); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ omx_err = PrimeFillBuffers(); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.PrimeFillBuffers omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ m_port_settings_changed = true; -+ return true; -+} -+ -+ -+int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) -+{ -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f demux_queue(%d) dts_queue(%d) ready_queue(%d) busy_queue(%d)", -+ CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_demux_queue.size(), m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy.size()); -+ #endif -+ -+ OMX_ERRORTYPE omx_err; -+ unsigned int demuxer_bytes = 0; -+ uint8_t *demuxer_content = NULL; -+ -+ // we need to queue then de-queue the demux packet, seems silly but -+ // omx might not have a omx input buffer available when we are called -+ // and we must store the demuxer packet and try again later. -+ if (pData && m_demux_queue.empty() && m_omx_decoder.GetInputBufferSpace() >= (unsigned int)iSize) -+ { -+ demuxer_bytes = iSize; -+ demuxer_content = pData; -+ } -+ else if (pData && iSize) -+ { - omx_demux_packet demux_packet; - demux_packet.dts = dts; - demux_packet.pts = pts; -- -- demux_packet.size = demuxer_bytes; -- demux_packet.buff = new OMX_U8[demuxer_bytes]; -- memcpy(demux_packet.buff, demuxer_content, demuxer_bytes); -+ demux_packet.size = iSize; -+ demux_packet.buff = new OMX_U8[iSize]; -+ memcpy(demux_packet.buff, pData, iSize); - m_demux_queue.push(demux_packet); -+ } - -- // we can look at m_omx_input_avaliable.empty without needing to lock/unlock -+ OMX_U8 *buffer_to_free = NULL; -+ while (1) -+ { - // try to send any/all demux packets to omx decoder. -- while (!m_omx_input_avaliable.empty() && !m_demux_queue.empty() ) -+ if (!demuxer_bytes && !m_demux_queue.empty()) - { -- OMX_ERRORTYPE omx_err; -- OMX_BUFFERHEADERTYPE* omx_buffer; -- -- demux_packet = m_demux_queue.front(); -- m_demux_queue.pop(); -- // need to lock here to retreve an input buffer and pop the queue -- pthread_mutex_lock(&m_omx_input_mutex); -- omx_buffer = m_omx_input_avaliable.front(); -- m_omx_input_avaliable.pop(); -- pthread_mutex_unlock(&m_omx_input_mutex); -- -- // delete the previous demuxer buffer -- delete [] omx_buffer->pBuffer; -- // setup a new omx_buffer. -- omx_buffer->nFlags = m_omx_input_eos ? OMX_BUFFERFLAG_EOS : 0; -+ omx_demux_packet &demux_packet = m_demux_queue.front(); -+ if (m_omx_decoder.GetInputBufferSpace() >= (unsigned int)demux_packet.size) -+ { -+ // need to lock here to retrieve an input buffer and pop the queue -+ m_demux_queue.pop(); -+ demuxer_bytes = (unsigned int)demux_packet.size; -+ demuxer_content = demux_packet.buff; -+ buffer_to_free = demux_packet.buff; -+ dts = demux_packet.dts; -+ pts = demux_packet.pts; -+ } -+ } -+ -+ if (demuxer_content) -+ { -+ // 500ms timeout -+ OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(500); -+ if (omx_buffer == NULL) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_decoder.GetInputBuffer timeout", CLASSNAME, __func__); -+ return VC_ERROR; -+ } -+ #if defined(OMX_DEBUG_VERBOSE) -+ //CLog::Log(LOGDEBUG, "%s::%s - omx_buffer=%p", CLASSNAME, __func__, omx_buffer); -+ #endif -+ omx_buffer->nFlags = 0; - omx_buffer->nOffset = 0; -- omx_buffer->pBuffer = demux_packet.buff; -- omx_buffer->nAllocLen = demux_packet.size; -- omx_buffer->nFilledLen = demux_packet.size; -- omx_buffer->nTimeStamp = (demux_packet.pts == DVD_NOPTS_VALUE) ? 0 : demux_packet.pts * 1000.0; // in microseconds; -+ -+ omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; -+ omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); - omx_buffer->pAppPrivate = omx_buffer; -- omx_buffer->nInputPortIndex = m_omx_input_port; -+ memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); - -- #if defined(OMX_DEBUG_EMPTYBUFFERDONE) -- CLog::Log(LOGDEBUG, -- "%s::%s - feeding decoder, omx_buffer->pBuffer(0x%p), demuxer_bytes(%d)\n", -- CLASSNAME, __func__, omx_buffer->pBuffer, demuxer_bytes); -- #endif -- // Give this omx_buffer to OpenMax to be decoded. -- omx_err = OMX_EmptyThisBuffer(m_omx_decoder, omx_buffer); -- if (omx_err) -+ demuxer_bytes -= omx_buffer->nFilledLen; -+ demuxer_content += omx_buffer->nFilledLen; -+ -+ if (demuxer_bytes == 0) -+ omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; -+ if (pts == DVD_NOPTS_VALUE) -+ omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; -+ if (m_drop_state) // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored) -+ omx_buffer->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; -+ -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x", -+ CLASSNAME, __func__, omx_buffer->nFilledLen, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, omx_buffer->nFlags); -+#endif -+ -+ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); -+ if (omx_err != OMX_ErrorNone) - { -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", -- CLASSNAME, __func__, omx_err); -+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err); - return VC_ERROR; - } -- // only push if we are successful with feeding OMX_EmptyThisBuffer -- m_dts_queue.push(demux_packet.dts); -- -- // if m_omx_input_avaliable and/or demux_queue are now empty, -- // wait up to 20ms for OpenMax to consume a demux packet -- if (m_omx_input_avaliable.empty() || m_demux_queue.empty()) -- m_input_consumed_event.WaitMSec(1); -+ if (demuxer_bytes == 0) -+ { -+#ifdef DTS_QUEUE -+ // only push if we are successful with feeding OMX_EmptyThisBuffer -+ m_dts_queue.push(dts); -+ assert(m_dts_queue.size() < 32); -+#endif -+ if (buffer_to_free) -+ { -+ delete [] buffer_to_free; -+ buffer_to_free = NULL; -+ demuxer_content = NULL; -+ continue; -+ } -+ } -+ } -+ omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); -+ if (omx_err == OMX_ErrorNone) -+ { -+ if (!PortSettingsChanged()) -+ { -+ CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return VC_ERROR; -+ } -+ } -+ else if (omx_err != OMX_ErrorTimeout) -+ { -+ CLog::Log(LOGERROR, "%s::%s - video not supported omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return VC_ERROR; - } -- if (m_omx_input_avaliable.empty() && !m_demux_queue.empty()) -- m_input_consumed_event.WaitMSec(1); -- -- #if defined(OMX_DEBUG_VERBOSE) -- if (m_omx_input_avaliable.empty()) -- CLog::Log(LOGDEBUG, -- "%s::%s - buffering demux, m_demux_queue_size(%d), demuxer_bytes(%d)\n", -- CLASSNAME, __func__, m_demux_queue.size(), demuxer_bytes); -- #endif -+ omx_err = m_omx_decoder.WaitForEvent(OMX_EventParamOrConfigChanged, 0); -+ if (omx_err == OMX_ErrorNone) -+ { -+ if (!PortSettingsChanged()) -+ { -+ CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged (EventParamOrConfigChanged) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return VC_ERROR; -+ } -+ } -+ else if (omx_err == OMX_ErrorStreamCorrupt) -+ { -+ CLog::Log(LOGERROR, "%s::%s - video not supported 2 omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return VC_ERROR; -+ } -+ if (!demuxer_bytes) -+ break; - } - -+#if defined(OMX_DEBUG_VERBOSE) -+ if (!m_omx_decoder.GetInputBufferSpace()) -+ CLog::Log(LOGDEBUG, -+ "%s::%s - buffering demux, m_demux_queue_size(%d), demuxer_bytes(%d) m_dts_queue.size(%d)", -+ CLASSNAME, __func__, m_demux_queue.size(), demuxer_bytes, m_dts_queue.size()); -+ #endif -+ - if (m_omx_output_ready.empty()) -+ { -+ //CLog::Log(LOGDEBUG, "%s::%s - empty: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size()); - return VC_BUFFER; -+ } - -- return VC_PICTURE | VC_BUFFER; -+ //CLog::Log(LOGDEBUG, "%s::%s - full: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size()); -+ return VC_PICTURE; - } - - void COpenMaxVideo::Reset(void) - { - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif --/* -- // only reset OpenMax decoder if it's running -- if (m_omx_decoder_state == OMX_StateExecuting) -+ m_omx_egl_render.FlushAll(); -+ m_omx_decoder.FlushAll(); -+ // blow all ready video frames -+ while (!m_omx_output_ready.empty()) - { -- OMX_ERRORTYPE omx_err; -- -- omx_err = StopDecoder(); -- // Alloc OpenMax input buffers. -- omx_err = AllocOMXInputBuffers(); -- // Alloc OpenMax output buffers. -- omx_err = AllocOMXOutputBuffers(); -- -- omx_err = StartDecoder(); -+ pthread_mutex_lock(&m_omx_output_mutex); -+ COpenMaxVideoBuffer *pic = m_omx_output_ready.front(); -+ m_omx_output_ready.pop(); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ // return the omx buffer back to OpenMax to fill. -+ ReturnOpenMaxBuffer(pic); - } --*/ -- ::Sleep(100); -+#ifdef DTS_QUEUE -+ while (!m_dts_queue.empty()) -+ m_dts_queue.pop(); -+#endif -+ -+ while (!m_demux_queue.empty()) -+ m_demux_queue.pop(); - } - --bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+ -+OMX_ERRORTYPE COpenMaxVideo::ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer) - { -- while (m_omx_output_busy.size() > 1) -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_omx_output_busy.size()); -+#endif -+ bool done = buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_EOS; -+ if (!done) - { -- // fetch a output buffer and pop it off the busy list -- pthread_mutex_lock(&m_omx_output_mutex); -- OpenMaxVideoBuffer *buffer = m_omx_output_busy.front(); -- m_omx_output_busy.pop(); -- pthread_mutex_unlock(&m_omx_output_mutex); -+ // return the omx buffer back to OpenMax to fill. -+ buffer->omx_buffer->nFlags = 0; -+ buffer->omx_buffer->nFilledLen = 0; - -- bool done = buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_EOS; -- if (!done) -- { -- // return the omx buffer back to OpenMax to fill. -- OMX_ERRORTYPE omx_err = OMX_FillThisBuffer(m_omx_decoder, buffer->omx_buffer); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- } -+ assert(buffer->omx_buffer->nOutputPortIndex == m_omx_egl_render.GetOutputPort()); -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s FillThisBuffer(%p) %p->%ld", CLASSNAME, __func__, buffer, buffer->omx_buffer, buffer->m_refs); -+#endif -+ OMX_ERRORTYPE omx_err = m_omx_egl_render.FillThisBuffer(buffer->omx_buffer); -+ -+ if (omx_err) -+ CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)", CLASSNAME, __func__, omx_err); - } -+ return omx_err; -+} -+ -+void COpenMaxVideo::ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer) -+{ -+ // remove from busy list -+ pthread_mutex_lock(&m_omx_output_mutex); -+ m_omx_output_busy.erase(std::remove(m_omx_output_busy.begin(), m_omx_output_busy.end(), buffer), m_omx_output_busy.end()); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ ReturnOpenMaxBuffer(buffer); -+} -+ -+bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ //CLog::Log(LOGDEBUG, "%s::%s - m_omx_output_busy.size()=%d m_omx_output_ready.size()=%d", CLASSNAME, __func__, m_omx_output_busy.size(), m_omx_output_ready.size()); -+ //CLog::Log(LOGDEBUG, "%s::%s - full: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size()); - - if (!m_omx_output_ready.empty()) - { -- OpenMaxVideoBuffer *buffer; -+ COpenMaxVideoBuffer *buffer; - // fetch a output buffer and pop it off the ready list - pthread_mutex_lock(&m_omx_output_mutex); - buffer = m_omx_output_ready.front(); - m_omx_output_ready.pop(); -- m_omx_output_busy.push(buffer); -+ m_omx_output_busy.push_back(buffer); - pthread_mutex_unlock(&m_omx_output_mutex); - -+ memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); - pDvdVideoPicture->dts = DVD_NOPTS_VALUE; - pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - pDvdVideoPicture->format = RENDER_FMT_OMXEGL; -- pDvdVideoPicture->openMax = this; - pDvdVideoPicture->openMaxBuffer = buffer; -- -+ pDvdVideoPicture->color_range = 0; -+ pDvdVideoPicture->color_matrix = 4; -+ pDvdVideoPicture->iWidth = m_decoded_width; -+ pDvdVideoPicture->iHeight = m_decoded_height; -+ pDvdVideoPicture->iDisplayWidth = m_decoded_width; -+ pDvdVideoPicture->iDisplayHeight = m_decoded_height; -+ -+#ifdef DTS_QUEUE - if (!m_dts_queue.empty()) - { - pDvdVideoPicture->dts = m_dts_queue.front(); - m_dts_queue.pop(); - } -+#endif - // nTimeStamp is in microseconds -- pDvdVideoPicture->pts = (buffer->omx_buffer->nTimeStamp == 0) ? DVD_NOPTS_VALUE : (double)buffer->omx_buffer->nTimeStamp / 1000.0; -+ double ts = FromOMXTime(buffer->omx_buffer->nTimeStamp); -+ pDvdVideoPicture->pts = (ts == 0) ? DVD_NOPTS_VALUE : ts; -+ pDvdVideoPicture->openMaxBuffer->Acquire(); -+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -+ if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) -+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__, -+ pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6, -+ pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id); -+#endif - } -- #if defined(OMX_DEBUG_VERBOSE) - else - { -- CLog::Log(LOGDEBUG, "%s::%s - called but m_omx_output_ready is empty\n", -- CLASSNAME, __func__); -+ CLog::Log(LOGERROR, "%s::%s - called but m_omx_output_ready is empty", CLASSNAME, __func__); -+ return false; - } -- #endif -- -- pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -- pDvdVideoPicture->iFlags |= m_drop_state ? DVP_FLAG_DROPPED : 0; -- - return true; - } - -- --// DecoderEmptyBufferDone -- OpenMax input buffer has been emptied --OMX_ERRORTYPE COpenMaxVideo::DecoderEmptyBufferDone( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_BUFFERHEADERTYPE* pBuffer) -+bool COpenMaxVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - { -- COpenMaxVideo *ctx = static_cast(pAppData); --/* -- #if defined(OMX_DEBUG_EMPTYBUFFERDONE) -- CLog::Log(LOGDEBUG, "%s::%s - buffer_size(%lu), timestamp(%f)\n", -- CLASSNAME, __func__, pBuffer->nFilledLen, (double)pBuffer->nTimeStamp / 1000.0); -- #endif --*/ -- // queue free input buffer to avaliable list. -- pthread_mutex_lock(&ctx->m_omx_input_mutex); -- ctx->m_omx_input_avaliable.push(pBuffer); -- ctx->m_input_consumed_event.Set(); -- pthread_mutex_unlock(&ctx->m_omx_input_mutex); -- -- return OMX_ErrorNone; -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p", CLASSNAME, __func__, pDvdVideoPicture->openMaxBuffer); -+#endif -+ if (pDvdVideoPicture->format == RENDER_FMT_OMXEGL) -+ pDvdVideoPicture->openMaxBuffer->Release(); -+ memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); -+ return true; - } - --// DecoderFillBufferDone -- OpenMax output buffer has been filled -+ // DecoderFillBufferDone -- OpenMax output buffer has been filled - OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone( - OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, - OMX_BUFFERHEADERTYPE* pBuffer) - { -- COpenMaxVideo *ctx = static_cast(pAppData); -- OpenMaxVideoBuffer *buffer = (OpenMaxVideoBuffer*)pBuffer->pAppPrivate; -+ COpenMaxVideoBuffer *buffer = (COpenMaxVideoBuffer*)pBuffer->pAppPrivate; - -- #if defined(OMX_DEBUG_FILLBUFFERDONE) -- CLog::Log(LOGDEBUG, "%s::%s - buffer_size(%lu), timestamp(%f)\n", -- CLASSNAME, __func__, pBuffer->nFilledLen, (double)pBuffer->nTimeStamp / 1000.0); -+ #if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f", -+ CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6); - #endif - -- if (!ctx->m_portChanging) -- { -- // queue output omx buffer to ready list. -- pthread_mutex_lock(&ctx->m_omx_output_mutex); -- ctx->m_omx_output_ready.push(buffer); -- pthread_mutex_unlock(&ctx->m_omx_output_mutex); -- } -+ // queue output omx buffer to ready list. -+ pthread_mutex_lock(&m_omx_output_mutex); -+ m_omx_output_ready.push(buffer); -+ pthread_mutex_unlock(&m_omx_output_mutex); - - return OMX_ErrorNone; - } - --void COpenMaxVideo::QueryCodec(void) --{ -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- OMX_VIDEO_PARAM_PROFILELEVELTYPE port_param; -- OMX_INIT_STRUCTURE(port_param); -- -- port_param.nPortIndex = m_omx_input_port; -- -- for (port_param.nProfileIndex = 0;; port_param.nProfileIndex++) -- { -- omx_err = OMX_GetParameter(m_omx_decoder, -- OMX_IndexParamVideoProfileLevelQuerySupported, &port_param); -- if (omx_err) -- break; -- -- omx_codec_capability omx_capability; -- omx_capability.level = port_param.eLevel; -- omx_capability.profile = port_param.eProfile; -- m_omx_decoder_capabilities.push_back(omx_capability); -- } --} -- - OMX_ERRORTYPE COpenMaxVideo::PrimeFillBuffers(void) - { - OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- OpenMaxVideoBuffer *buffer; -+ COpenMaxVideoBuffer *buffer; - - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif - // tell OpenMax to start filling output buffers - for (size_t i = 0; i < m_omx_output_buffers.size(); i++) - { - buffer = m_omx_output_buffers[i]; - // always set the port index. -- buffer->omx_buffer->nOutputPortIndex = m_omx_output_port; -- // Need to clear the EOS flag. -- buffer->omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; -+ buffer->omx_buffer->nOutputPortIndex = m_omx_egl_render.GetOutputPort(); - buffer->omx_buffer->pAppPrivate = buffer; -- -- omx_err = OMX_FillThisBuffer(m_omx_decoder, buffer->omx_buffer); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -+ omx_err = ReturnOpenMaxBuffer(buffer); - } -- - return omx_err; - } - --OMX_ERRORTYPE COpenMaxVideo::AllocOMXInputBuffers(void) --{ -- OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- -- // Obtain the information about the decoder input port. -- OMX_PARAM_PORTDEFINITIONTYPE port_format; -- OMX_INIT_STRUCTURE(port_format); -- port_format.nPortIndex = m_omx_input_port; -- OMX_GetParameter(m_omx_decoder, OMX_IndexParamPortDefinition, &port_format); -- -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "%s::%s - iport(%d), nBufferCountMin(%lu), nBufferSize(%lu)\n", -- CLASSNAME, __func__, m_omx_input_port, port_format.nBufferCountMin, port_format.nBufferSize); -- #endif -- for (size_t i = 0; i < port_format.nBufferCountMin; i++) -- { -- OMX_BUFFERHEADERTYPE *buffer = NULL; -- // use an external buffer that's sized according to actual demux -- // packet size, start at internal's buffer size, will get deleted when -- // we start pulling demuxer packets and using demux packet sized buffers. -- OMX_U8* data = new OMX_U8[port_format.nBufferSize]; -- omx_err = OMX_UseBuffer(m_omx_decoder, &buffer, m_omx_input_port, NULL, port_format.nBufferSize, data); -- if (omx_err) -- { -- CLog::Log(LOGERROR, "%s::%s - OMX_UseBuffer failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return(omx_err); -- } -- m_omx_input_buffers.push_back(buffer); -- // don't have to lock/unlock here, we are not decoding -- m_omx_input_avaliable.push(buffer); -- } -- m_omx_input_eos = false; -- -- return(omx_err); --} --OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(bool wait) -+OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(void) - { - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - -- /* -- omx_err = OMX_SendCommand(m_omx_decoder, OMX_CommandFlush, m_omx_input_port, 0); -- if (omx_err) -- CLog::Log(LOGERROR, "%s::%s - OMX_CommandFlush failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- else if (wait) -- sem_wait(m_omx_flush_input); -- */ -- -- // free omx input port buffers. -- for (size_t i = 0; i < m_omx_input_buffers.size(); i++) -- { -- // using external buffers (OMX_UseBuffer), free our external buffers -- // before calling OMX_FreeBuffer which frees the omx buffer. -- delete [] m_omx_input_buffers[i]->pBuffer; -- m_omx_input_buffers[i]->pBuffer = NULL; -- omx_err = OMX_FreeBuffer(m_omx_decoder, m_omx_input_port, m_omx_input_buffers[i]); -- } -- m_omx_input_buffers.clear(); -- - // empty input buffer queue. not decoding so don't need lock/unlock. -- while (!m_omx_input_avaliable.empty()) -- m_omx_input_avaliable.pop(); - while (!m_demux_queue.empty()) - m_demux_queue.pop(); -+#ifdef DTS_QUEUE - while (!m_dts_queue.empty()) - m_dts_queue.pop(); -- -+#endif - return(omx_err); - } - --void COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata) -+bool COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata) - { - COpenMaxVideo *omx = static_cast(userdata); -- omx->AllocOMXOutputEGLTextures(); -+ return omx->AllocOMXOutputEGLTextures() == OMX_ErrorNone; - } - --void COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata) -+bool COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata) - { - COpenMaxVideo *omx = static_cast(userdata); -- omx->FreeOMXOutputEGLTextures(true); -+ return omx->FreeOMXOutputEGLTextures() == OMX_ErrorNone; - } - --OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputBuffers(void) -+bool COpenMaxVideo::AllocOMXOutputBuffers(void) - { -- OMX_ERRORTYPE omx_err; -- -- if ( g_application.IsCurrentThread() ) -- { -- omx_err = AllocOMXOutputEGLTextures(); -- } -- else -- { -- ThreadMessageCallback callbackData; -- callbackData.callback = &CallbackAllocOMXEGLTextures; -- callbackData.userptr = (void *)this; -- -- ThreadMessage tMsg; -- tMsg.dwMessage = TMSG_CALLBACK; -- tMsg.lpVoid = (void*)&callbackData; -- -- g_application.getApplicationMessenger().SendMessage(tMsg, true); -- -- omx_err = OMX_ErrorNone; -- } -- -- return omx_err; -+ return g_OMXImage.SendMessage(CallbackAllocOMXEGLTextures, (void *)this); - } - --OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputBuffers(bool wait) -+bool COpenMaxVideo::FreeOMXOutputBuffers(void) - { -- OMX_ERRORTYPE omx_err = FreeOMXOutputEGLTextures(wait); -- -- return omx_err; -+ return g_OMXImage.SendMessage(CallbackFreeOMXEGLTextures, (void *)this); - } - - OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - { -- OMX_ERRORTYPE omx_err; -- -- if (!eglCreateImageKHR) -- { -- GETEXTENSION(PFNEGLCREATEIMAGEKHRPROC, eglCreateImageKHR); -- } -- -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; - EGLint attrib = EGL_NONE; -- OpenMaxVideoBuffer *egl_buffer; -- -- // Obtain the information about the output port. -- OMX_PARAM_PORTDEFINITIONTYPE port_format; -- OMX_INIT_STRUCTURE(port_format); -- port_format.nPortIndex = m_omx_output_port; -- omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamPortDefinition, &port_format); -- -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "%s::%s (1) - oport(%d), nFrameWidth(%lu), nFrameHeight(%lu), nStride(%lx), nBufferCountMin(%lu), nBufferSize(%lu)\n", -- CLASSNAME, __func__, m_omx_output_port, -- port_format.format.video.nFrameWidth, port_format.format.video.nFrameHeight,port_format.format.video.nStride, -- port_format.nBufferCountMin, port_format.nBufferSize); -- #endif -+ COpenMaxVideoBuffer *egl_buffer; - - glActiveTexture(GL_TEXTURE0); - -- for (size_t i = 0; i < port_format.nBufferCountMin; i++) -+ for (size_t i = 0; i < m_egl_buffer_count; i++) - { -- egl_buffer = new OpenMaxVideoBuffer; -- memset(egl_buffer, 0, sizeof(*egl_buffer)); -+ egl_buffer = new COpenMaxVideoBuffer(this); - egl_buffer->width = m_decoded_width; - egl_buffer->height = m_decoded_height; - - glGenTextures(1, &egl_buffer->texture_id); - glBindTexture(GL_TEXTURE_2D, egl_buffer->texture_id); - -+ // no mipmaps -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -+ - // create space for buffer with a texture - glTexImage2D( - GL_TEXTURE_2D, // target -@@ -710,8 +928,6 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - GL_RGBA, // format - GL_UNSIGNED_BYTE, // type - NULL); // pixels -- will be provided later -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - // create EGLImage from texture - egl_buffer->egl_image = eglCreateImageKHR( -@@ -722,49 +938,40 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - &attrib); - if (!egl_buffer->egl_image) - { -- CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage\n", CLASSNAME, __func__); -+ CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage", CLASSNAME, __func__); - return(OMX_ErrorUndefined); - } - egl_buffer->index = i; - - // tell decoder output port that it will be using EGLImage -- omx_err = OMX_UseEGLImage( -- m_omx_decoder, &egl_buffer->omx_buffer, m_omx_output_port, egl_buffer, egl_buffer->egl_image); -+ omx_err = m_omx_egl_render.UseEGLImage( -+ &egl_buffer->omx_buffer, m_omx_egl_render.GetOutputPort(), egl_buffer, egl_buffer->egl_image); - if (omx_err) - { -- CLog::Log(LOGERROR, "%s::%s - OMX_UseEGLImage failed with omx_err(0x%x)\n", -+ CLog::Log(LOGERROR, "%s::%s - OMX_UseEGLImage failed with omx_err(0x%x)", - CLASSNAME, __func__, omx_err); - return(omx_err); - } - m_omx_output_buffers.push_back(egl_buffer); - -- CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d\n", -+ CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d", - CLASSNAME, __func__, egl_buffer->egl_image, egl_buffer->width, egl_buffer->height); - } -- m_omx_output_eos = false; -- while (!m_omx_output_busy.empty()) -- m_omx_output_busy.pop(); -- while (!m_omx_output_ready.empty()) -- m_omx_output_ready.pop(); -- - return omx_err; - } - --OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(bool wait) -+OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(void) - { - OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- OpenMaxVideoBuffer *egl_buffer; -- -- if (!eglDestroyImageKHR) -- { -- GETEXTENSION(PFNEGLDESTROYIMAGEKHRPROC, eglDestroyImageKHR); -- } -+ COpenMaxVideoBuffer *egl_buffer; - - for (size_t i = 0; i < m_omx_output_buffers.size(); i++) - { - egl_buffer = m_omx_output_buffers[i]; - // tell decoder output port to stop using the EGLImage -- omx_err = OMX_FreeBuffer(m_omx_decoder, m_omx_output_port, egl_buffer->omx_buffer); -+ omx_err = m_omx_egl_render.FreeOutputBuffer(egl_buffer->omx_buffer); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.FreeOutputBuffer(%p) omx_err(0x%08x)", CLASSNAME, __func__, egl_buffer->omx_buffer, omx_err); - // destroy egl_image - eglDestroyImageKHR(m_egl_display, egl_buffer->egl_image); - // free texture -@@ -777,274 +984,45 @@ OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(bool wait) - } - - --//////////////////////////////////////////////////////////////////////////////////////////// --// DecoderEventHandler -- OMX event callback --OMX_ERRORTYPE COpenMaxVideo::DecoderEventHandler( -- OMX_HANDLETYPE hComponent, -- OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, -- OMX_U32 nData1, -- OMX_U32 nData2, -- OMX_PTR pEventData) --{ -- OMX_ERRORTYPE omx_err; -- COpenMaxVideo *ctx = static_cast(pAppData); -- --/* -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, -- "COpenMax::%s - hComponent(0x%p), eEvent(0x%x), nData1(0x%lx), nData2(0x%lx), pEventData(0x%p)\n", -- __func__, hComponent, eEvent, nData1, nData2, pEventData); -- #endif --*/ -- -- switch (eEvent) -- { -- case OMX_EventCmdComplete: -- switch(nData1) -- { -- case OMX_CommandStateSet: -- ctx->m_omx_decoder_state = (int)nData2; -- switch (ctx->m_omx_decoder_state) -- { -- case OMX_StateInvalid: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateInvalid\n", CLASSNAME, __func__); -- break; -- case OMX_StateLoaded: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateLoaded\n", CLASSNAME, __func__); -- break; -- case OMX_StateIdle: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateIdle\n", CLASSNAME, __func__); -- break; -- case OMX_StateExecuting: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateExecuting\n", CLASSNAME, __func__); -- break; -- case OMX_StatePause: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StatePause\n", CLASSNAME, __func__); -- break; -- case OMX_StateWaitForResources: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_StateWaitForResources\n", CLASSNAME, __func__); -- break; -- default: -- CLog::Log(LOGDEBUG, -- "%s::%s - Unknown OMX_Statexxxxx, state(%d)\n", -- CLASSNAME, __func__, ctx->m_omx_decoder_state); -- break; -- } -- sem_post(ctx->m_omx_decoder_state_change); -- break; -- case OMX_CommandFlush: -- /* -- if (OMX_ALL == (int)nData2) -- { -- sem_post(ctx->m_omx_flush_input); -- sem_post(ctx->m_omx_flush_output); -- CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush input/output\n",__func__); -- } -- else if (ctx->m_omx_input_port == (int)nData2) -- { -- sem_post(ctx->m_omx_flush_input); -- CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush input\n",__func__); -- } -- else if (ctx->m_omx_output_port == (int)nData2) -- { -- sem_post(ctx->m_omx_flush_output); -- CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush ouput\n",__func__); -- } -- else -- */ -- { -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandFlush, nData2(0x%lx)\n", -- CLASSNAME, __func__, nData2); -- #endif -- } -- break; -- case OMX_CommandPortDisable: -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandPortDisable, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- #endif -- if (ctx->m_omx_output_port == (int)nData2) -- { -- // Got OMX_CommandPortDisable event, alloc new buffers for the output port. -- ctx->AllocOMXOutputBuffers(); -- omx_err = OMX_SendCommand(ctx->m_omx_decoder, OMX_CommandPortEnable, ctx->m_omx_output_port, NULL); -- } -- break; -- case OMX_CommandPortEnable: -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandPortEnable, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- #endif -- if (ctx->m_omx_output_port == (int)nData2) -- { -- // Got OMX_CommandPortEnable event. -- // OMX_CommandPortDisable will have re-alloced new ones so re-prime -- ctx->PrimeFillBuffers(); -- } -- ctx->m_portChanging = false; -- break; -- #if defined(OMX_DEBUG_EVENTHANDLER) -- case OMX_CommandMarkBuffer: -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_CommandMarkBuffer, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- break; -- #endif -- } -- break; -- case OMX_EventBufferFlag: -- if (ctx->m_omx_decoder == hComponent && (nData2 & OMX_BUFFERFLAG_EOS)) { -- #if defined(OMX_DEBUG_EVENTHANDLER) -- if(ctx->m_omx_input_port == (int)nData1) -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventBufferFlag(input)\n", -- CLASSNAME, __func__); -- #endif -- if(ctx->m_omx_output_port == (int)nData1) -- { -- ctx->m_videoplayback_done = true; -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventBufferFlag(output)\n", -- CLASSNAME, __func__); -- #endif -- } -- } -- break; -- case OMX_EventPortSettingsChanged: -- #if defined(OMX_DEBUG_EVENTHANDLER) -- CLog::Log(LOGDEBUG, -- "%s::%s - OMX_EventPortSettingsChanged(output)\n", CLASSNAME, __func__); -- #endif -- // not sure nData2 is the input/output ports in this call, docs don't say -- if (ctx->m_omx_output_port == (int)nData2) -- { -- // free the current OpenMax output buffers, you must do this before sending -- // OMX_CommandPortDisable to component as it expects output buffers -- // to be freed before it will issue a OMX_CommandPortDisable event. -- ctx->m_portChanging = true; -- OMX_SendCommand(ctx->m_omx_decoder, OMX_CommandPortDisable, ctx->m_omx_output_port, NULL); -- omx_err = ctx->FreeOMXOutputBuffers(false); -- } -- break; -- #if defined(OMX_DEBUG_EVENTHANDLER) -- case OMX_EventMark: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventMark\n", CLASSNAME, __func__); -- break; -- case OMX_EventResourcesAcquired: -- CLog::Log(LOGDEBUG, "%s::%s - OMX_EventResourcesAcquired\n", CLASSNAME, __func__); -- break; -- #endif -- case OMX_EventError: -- switch((OMX_S32)nData1) -- { -- case OMX_ErrorInsufficientResources: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError, insufficient resources\n", -- CLASSNAME, __func__); -- // we are so frack'ed -- //exit(0); -- break; -- case OMX_ErrorFormatNotDetected: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError, cannot parse input stream\n", -- CLASSNAME, __func__); -- break; -- case OMX_ErrorPortUnpopulated: -- // silently ignore these. We can get them when setting OMX_CommandPortDisable -- // on the output port and the component flushes the output buffers. -- break; -- case OMX_ErrorStreamCorrupt: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError, Bitstream corrupt\n", -- CLASSNAME, __func__); -- ctx->m_videoplayback_done = true; -- break; -- default: -- CLog::Log(LOGERROR, "%s::%s - OMX_EventError detected, nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, nData1, nData2); -- break; -- } -- // do this so we don't hang on errors -- /* -- sem_post(ctx->m_omx_flush_input); -- sem_post(ctx->m_omx_flush_output); -- */ -- sem_post(ctx->m_omx_decoder_state_change); -- break; -- default: -- CLog::Log(LOGWARNING, -- "%s::%s - Unknown eEvent(0x%x), nData1(0x%lx), nData2(0x%lx)\n", -- CLASSNAME, __func__, eEvent, nData1, nData2); -- break; -- } -- -- return OMX_ErrorNone; --} -- --// StartPlayback -- Kick off video playback. --OMX_ERRORTYPE COpenMaxVideo::StartDecoder(void) --{ -- OMX_ERRORTYPE omx_err; -- -- #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -- #endif -- -- // transition decoder component to IDLE state -- omx_err = SetStateForComponent(OMX_StateIdle); -- if (omx_err) -- { -- CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return omx_err; -- } -- -- // transition decoder component to executing state -- omx_err = SetStateForComponent(OMX_StateExecuting); -- if (omx_err) -- { -- CLog::Log(LOGERROR, "%s::%s - setting OMX_StateExecuting failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return omx_err; -- } -- -- //prime the omx output buffers. -- PrimeFillBuffers(); -- -- return omx_err; --} -- - // StopPlayback -- Stop video playback - OMX_ERRORTYPE COpenMaxVideo::StopDecoder(void) - { -- OMX_ERRORTYPE omx_err; -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif -+ - // transition decoder component from executing to idle -- omx_err = SetStateForComponent(OMX_StateIdle); -- if (omx_err) -+ if (m_omx_decoder.IsInitialized()) - { -- CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -- return omx_err; -+ omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle); -+ if (omx_err) -+ CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)", -+ CLASSNAME, __func__, omx_err); - } - - // we can free our allocated port buffers in OMX_StateIdle state. - // free OpenMax input buffers. -- FreeOMXInputBuffers(true); -- // free OpenMax output buffers. -- FreeOMXOutputBuffers(true); -+ FreeOMXInputBuffers(); -+ -+ if (m_omx_egl_render.IsInitialized()) -+ { -+ omx_err = m_omx_egl_render.SetStateForComponent(OMX_StateIdle); -+ if (omx_err) -+ CLog::Log(LOGERROR, "%s::%s - setting egl OMX_StateIdle failed with omx_err(0x%x)", -+ CLASSNAME, __func__, omx_err); -+ // free OpenMax output buffers. -+ omx_err = m_omx_egl_render.DisablePort(m_omx_egl_render.GetOutputPort(), false); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.DisablePort(%d) omx_err(0x%08x)", CLASSNAME, __func__, m_omx_egl_render.GetOutputPort(), omx_err); - -- // transition decoder component from idle to loaded -- omx_err = SetStateForComponent(OMX_StateLoaded); -- if (omx_err) -- CLog::Log(LOGERROR, -- "%s::%s - setting OMX_StateLoaded failed with omx_err(0x%x)\n", -- CLASSNAME, __func__, omx_err); -+ FreeOMXOutputBuffers(); - -+ omx_err = m_omx_egl_render.WaitForCommand(OMX_CommandPortDisable, m_omx_egl_render.GetOutputPort()); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s WaitForCommand:OMX_CommandPortDisable omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ } - return omx_err; - } - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index e06c41d..9079c13 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -21,12 +21,35 @@ - - #if defined(HAVE_LIBOPENMAX) - --#include "OpenMax.h" -+#include "system_gl.h" - #include - #include - -+#include "linux/OMXCore.h" -+#include "linux/OMXClock.h" -+ -+#include "cores/dvdplayer/DVDStreamInfo.h" -+#include "DVDVideoCodec.h" -+#include "threads/Event.h" -+ -+#include -+#include -+ -+typedef struct omx_demux_packet { -+ OMX_U8 *buff; -+ int size; -+ double dts; -+ double pts; -+} omx_demux_packet; -+ -+class COpenMaxVideo; - // an omx egl video frame --typedef struct OpenMaxVideoBuffer { -+class COpenMaxVideoBuffer -+{ -+public: -+ COpenMaxVideoBuffer(COpenMaxVideo *omv); -+ virtual ~COpenMaxVideoBuffer(); -+ - OMX_BUFFERHEADERTYPE *omx_buffer; - int width; - int height; -@@ -35,79 +58,86 @@ typedef struct OpenMaxVideoBuffer { - // used for egl based rendering if active - EGLImageKHR egl_image; - GLuint texture_id; --} OpenMaxVideoBuffer; -+ // reference counting -+ COpenMaxVideoBuffer* Acquire(); -+ long Release(); -+ void Sync(); -+ -+ COpenMaxVideo *m_omv; -+ long m_refs; -+private: -+}; - --class COpenMaxVideo : public COpenMax -+class COpenMaxVideo - { - public: - COpenMaxVideo(); - virtual ~COpenMaxVideo(); - - // Required overrides -- bool Open(CDVDStreamInfo &hints); -- void Close(void); -- int Decode(uint8_t *pData, int iSize, double dts, double pts); -- void Reset(void); -- bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -- void SetDropState(bool bDrop); -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -+ virtual void Dispose(void); -+ virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); -+ virtual void Reset(void); -+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); -+ virtual unsigned GetAllowedReferences() { return 2; } -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ -+ // OpenMax decoder callback routines. -+ OMX_ERRORTYPE DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer); -+ void ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer); -+ - protected: - void QueryCodec(void); - OMX_ERRORTYPE PrimeFillBuffers(void); - OMX_ERRORTYPE AllocOMXInputBuffers(void); -- OMX_ERRORTYPE FreeOMXInputBuffers(bool wait); -- OMX_ERRORTYPE AllocOMXOutputBuffers(void); -- OMX_ERRORTYPE FreeOMXOutputBuffers(bool wait); -- static void CallbackAllocOMXEGLTextures(void*); -+ OMX_ERRORTYPE FreeOMXInputBuffers(void); -+ bool AllocOMXOutputBuffers(void); -+ bool FreeOMXOutputBuffers(void); -+ static bool CallbackAllocOMXEGLTextures(void*); - OMX_ERRORTYPE AllocOMXOutputEGLTextures(void); -- static void CallbackFreeOMXEGLTextures(void*); -- OMX_ERRORTYPE FreeOMXOutputEGLTextures(bool wait); -- -- // TODO Those should move into the base class. After start actions can be executed by callbacks. -- OMX_ERRORTYPE StartDecoder(void); -+ static bool CallbackFreeOMXEGLTextures(void*); -+ OMX_ERRORTYPE FreeOMXOutputEGLTextures(void); - OMX_ERRORTYPE StopDecoder(void); -- -- // OpenMax decoder callback routines. -- virtual OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, -- OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData); -- virtual OMX_ERRORTYPE DecoderEmptyBufferDone( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer); -- virtual OMX_ERRORTYPE DecoderFillBufferDone( -- OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader); -+ OMX_ERRORTYPE ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer); - - // EGL Resources - EGLDisplay m_egl_display; - EGLContext m_egl_context; - - // Video format -- DVDVideoPicture m_videobuffer; - bool m_drop_state; - int m_decoded_width; - int m_decoded_height; -+ unsigned int m_egl_buffer_count; -+ -+ bool m_port_settings_changed; -+ const char *m_pFormatName; - - std::queue m_dts_queue; - std::queue m_demux_queue; - -- // OpenMax input buffers (demuxer packets) -- pthread_mutex_t m_omx_input_mutex; -- std::queue m_omx_input_avaliable; -- std::vector m_omx_input_buffers; -- bool m_omx_input_eos; -- int m_omx_input_port; -- //sem_t *m_omx_flush_input; -- CEvent m_input_consumed_event; -- - // OpenMax output buffers (video frames) - pthread_mutex_t m_omx_output_mutex; -- std::queue m_omx_output_busy; -- std::queue m_omx_output_ready; -- std::vector m_omx_output_buffers; -- bool m_omx_output_eos; -- int m_omx_output_port; -- //sem_t *m_omx_flush_output; -+ std::vector m_omx_output_busy; -+ std::queue m_omx_output_ready; -+ std::vector m_omx_output_buffers; -+ -+ // initialize OpenMax and get decoder component -+ bool Initialize( const CStdString &decoder_name); -+ -+ // Components -+ COMXCoreComponent m_omx_decoder; -+ COMXCoreComponent m_omx_egl_render; - -- bool m_portChanging; -+ COMXCoreTunel m_omx_tunnel; -+ OMX_VIDEO_CODINGTYPE m_codingType; - -- volatile bool m_videoplayback_done; -+ bool PortSettingsChanged(); -+ bool SendDecoderConfig(uint8_t *extradata, int extrasize); -+ bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize); - }; - - // defined(HAVE_LIBOPENMAX) -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 4093974..0634880 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -2981,7 +2981,9 @@ bool CDVDPlayer::OpenVideoStream(CDVDStreamInfo& hint, bool reset) - hint.aspect = aspect; - hint.forced_aspect = true; - } -+#ifndef TARGET_RASPBERRY_PI - hint.software = true; -+#endif - } - - CDVDInputStream::IMenus* pMenus = dynamic_cast(m_pInputStream); -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 633e333..c6350cd 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -324,6 +324,9 @@ void CDVDPlayerVideo::Process() - - while (!m_bStop) - { -+ DemuxPacket staticPacket = {}; -+ DemuxPacket* pPacket = NULL; -+ bool bPacketDrop = false; - int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000; - int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0; - -@@ -360,8 +363,10 @@ void CDVDPlayerVideo::Process() - OutputPicture(&picture, pts); - pts+= frametime; - } -- -- continue; -+ pPacket = &staticPacket; -+ bPacketDrop = false; -+ goto submit_empty_packet; -+ //continue; - } - - if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) -@@ -490,9 +495,12 @@ void CDVDPlayerVideo::Process() - - if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) - { -- DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); -- bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); -- -+ pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); -+ bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); -+ } -+submit_empty_packet: -+ if (ret == MSGQ_TIMEOUT || pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) -+ { - if (m_stalled) - { - CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe left, switching to normal playback"); -@@ -750,7 +758,8 @@ void CDVDPlayerVideo::Process() - } - - // all data is used by the decoder, we can safely free it now -- pMsg->Release(); -+ if (ret != MSGQ_TIMEOUT) -+ pMsg->Release(); - } - - // we need to let decoder release any picture retained resources. -diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp -index 6e7d9a9..99e407a 100644 ---- a/xbmc/linux/OMXCore.cpp -+++ b/xbmc/linux/OMXCore.cpp -@@ -460,7 +460,12 @@ void COMXCoreComponent::FlushInput() - CLog::Log(LOGERROR, "COMXCoreComponent::FlushInput - Error on component %s omx_err(0x%08x)", - m_componentName.c_str(), (int)omx_err); - } -- WaitForCommand(OMX_CommandFlush, m_input_port); -+ omx_err = WaitForCommand(OMX_CommandFlush, m_input_port); -+ if(omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "COMXCoreComponent::FlushInput - %s WaitForCommand omx_err(0x%08x)", -+ m_componentName.c_str(), (int)omx_err); -+ } - } - - void COMXCoreComponent::FlushOutput() -@@ -477,7 +482,12 @@ void COMXCoreComponent::FlushOutput() - CLog::Log(LOGERROR, "COMXCoreComponent::FlushOutput - Error on component %s omx_err(0x%08x)", - m_componentName.c_str(), (int)omx_err); - } -- WaitForCommand(OMX_CommandFlush, m_output_port); -+ omx_err = WaitForCommand(OMX_CommandFlush, m_output_port); -+ if(omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "COMXCoreComponent::FlushOutput - %s WaitForCommand omx_err(0x%08x)", -+ m_componentName.c_str(), (int)omx_err); -+ } - } - - // timeout in milliseconds -@@ -1149,7 +1159,12 @@ OMX_STATETYPE COMXCoreComponent::GetState() - - OMX_STATETYPE state; - -- OMX_GetState(m_handle, &state); -+ OMX_ERRORTYPE omx_err = OMX_GetState(m_handle, &state); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "COMXCoreComponent::GetState - %s failed with omx_err(0x%x)\n", -+ m_componentName.c_str(), omx_err); -+ } - return state; - } - -@@ -1307,6 +1322,8 @@ OMX_ERRORTYPE COMXCoreComponent::DisablePort(unsigned int port, bool wait) - - OMX_ERRORTYPE COMXCoreComponent::UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, void* eglImage) - { -+if (m_callbacks.FillBufferDone == &COMXCoreComponent::DecoderFillBufferDoneCallback) -+{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle) -@@ -1383,8 +1400,21 @@ OMX_ERRORTYPE COMXCoreComponent::UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, - - return omx_err; - } -+else -+{ -+ OMX_ERRORTYPE omx_err; -+ omx_err = OMX_UseEGLImage(m_handle, ppBufferHdr, nPortIndex, pAppPrivate, eglImage); -+ if(omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - %s failed with omx_err(0x%x)\n", -+ CLASSNAME, __func__, m_componentName.c_str(), omx_err); -+ return omx_err; -+ } -+ return omx_err; -+} -+} - --bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEXTYPE index) -+bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEXTYPE index, OMX_CALLBACKTYPE *callbacks) - { - OMX_ERRORTYPE omx_err; - -@@ -1419,6 +1449,13 @@ bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEX - m_callbacks.EmptyBufferDone = &COMXCoreComponent::DecoderEmptyBufferDoneCallback; - m_callbacks.FillBufferDone = &COMXCoreComponent::DecoderFillBufferDoneCallback; - -+ if (callbacks && callbacks->EventHandler) -+ m_callbacks.EventHandler = callbacks->EventHandler; -+ if (callbacks && callbacks->EmptyBufferDone) -+ m_callbacks.EmptyBufferDone = callbacks->EmptyBufferDone; -+ if (callbacks && callbacks->FillBufferDone) -+ m_callbacks.FillBufferDone = callbacks->FillBufferDone; -+ - // Get video component handle setting up callbacks, component is in loaded state on return. - if(!m_handle) - { -diff --git a/xbmc/linux/OMXCore.h b/xbmc/linux/OMXCore.h -index 1efb313..b4c8626 100644 ---- a/xbmc/linux/OMXCore.h -+++ b/xbmc/linux/OMXCore.h -@@ -107,7 +107,7 @@ class COMXCoreComponent - OMX_ERRORTYPE DisablePort(unsigned int port, bool wait = true); - OMX_ERRORTYPE UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, void* eglImage); - -- bool Initialize( const std::string &component_name, OMX_INDEXTYPE index); -+ bool Initialize( const std::string &component_name, OMX_INDEXTYPE index, OMX_CALLBACKTYPE *callbacks = NULL); - bool IsInitialized(); - bool Deinitialize(); - --- -1.9.3 - - -From ff14d4f702b268f92b6267a4691f32e799f4bfcf Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 20 Jan 2014 16:03:40 +0000 -Subject: [PATCH 29/82] [omxcodec] Enable for dvd menus - ---- - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index 5d37395..6d1810f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -192,6 +192,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - - CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); - -+#if defined(HAVE_LIBOPENMAX) -+ // libopenmax can handle dvd playback including stills -+ if (!CSettings::Get().GetBool("videoplayer.useomx")) -+#endif - if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO)) - { - // If dvd is an mpeg2 and hint.stills --- -1.9.3 - - -From 98c9b16254ae852ffe20af8767654ae31eaa65af Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 3 Feb 2014 22:27:44 +0000 -Subject: [PATCH 30/82] [omxcodec] Add omx specific texture - create/upload/delete functions - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 33 +++++++++++++++++++++++++ - xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 +++ - 2 files changed, 37 insertions(+) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 2e0d0ca..b8af8d0 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -803,6 +803,12 @@ void CLinuxRendererGLES::LoadShaders(int field) - m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture; - m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture; - } -+ else if (m_format == RENDER_FMT_OMXEGL) -+ { -+ m_textureUpload = &CLinuxRendererGLES::UploadOMXEGLTexture; -+ m_textureCreate = &CLinuxRendererGLES::CreateOMXEGLTexture; -+ m_textureDelete = &CLinuxRendererGLES::DeleteOMXEGLTexture; -+ } - else - { - // default to YV12 texture handlers -@@ -2485,6 +2491,33 @@ bool CLinuxRendererGLES::CreateSurfaceTexture(int index) - return true; - } - -+//******************************************************************************************************** -+// SurfaceTexture creation, deletion, copying + clearing -+//******************************************************************************************************** -+void CLinuxRendererGLES::UploadOMXEGLTexture(int index) -+{ -+#ifdef HAVE_LIBOPENMAX -+ YUVBUFFER &buf = m_buffers[index]; -+ if (buf.openMaxBuffer) -+ { -+ //buf.openMaxBuffer->Sync(); -+ } -+#endif -+} -+void CLinuxRendererGLES::DeleteOMXEGLTexture(int index) -+{ -+#ifdef HAVE_LIBOPENMAX -+ YUVBUFFER &buf = m_buffers[index]; -+ if (buf.openMaxBuffer) -+ SAFE_RELEASE(buf.openMaxBuffer); -+#endif -+} -+bool CLinuxRendererGLES::CreateOMXEGLTexture(int index) -+{ -+ DeleteOMXEGLTexture(index); -+ return true; -+} -+ - void CLinuxRendererGLES::SetTextureFilter(GLenum method) - { - for (int i = 0 ; i -Date: Mon, 3 Feb 2014 22:50:43 +0000 -Subject: [PATCH 31/82] [omxcodec] Add shared pointer to delay shutdown of - codec until buffers are returned - ---- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 13 +++---------- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 3 ++- - .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 21 ++++++++++++++++++++- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 5 ++++- - 4 files changed, 29 insertions(+), 13 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -index 7d33192..ef10555 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -@@ -28,7 +28,6 @@ - #include "DVDClock.h" - #include "DVDStreamInfo.h" - #include "DVDVideoCodecOpenMax.h" --#include "OpenMaxVideo.h" - #include "settings/Settings.h" - #include "utils/log.h" - -@@ -36,8 +35,8 @@ - //////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////// - CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() -+ : m_omx_decoder( new COpenMaxVideo ) - { -- m_omx_decoder = NULL; - CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); - } - -@@ -49,8 +48,7 @@ CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax() - - bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - { -- m_omx_decoder = new COpenMaxVideo; -- return m_omx_decoder->Open(hints, options); -+ return m_omx_decoder->Open(hints, options, m_omx_decoder); - } - - const char* CDVDVideoCodecOpenMax::GetName(void) -@@ -60,12 +58,7 @@ const char* CDVDVideoCodecOpenMax::GetName(void) - - void CDVDVideoCodecOpenMax::Dispose() - { -- if (m_omx_decoder) -- { -- m_omx_decoder->Dispose(); -- delete m_omx_decoder; -- m_omx_decoder = NULL; -- } -+ m_omx_decoder->Dispose(); - } - - void CDVDVideoCodecOpenMax::SetDropState(bool bDrop) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -index 67cc235..b7c0c1b 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -@@ -22,6 +22,7 @@ - #if defined(HAVE_LIBOPENMAX) - - #include "DVDVideoCodec.h" -+#include "OpenMaxVideo.h" - - class COpenMaxVideo; - class CDVDVideoCodecOpenMax : public CDVDVideoCodec -@@ -42,7 +43,7 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec - virtual const char* GetName(void); - - protected: -- COpenMaxVideo *m_omx_decoder; -+ OpenMaxVideoPtr m_omx_decoder; - }; - - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index aca2e0d..29b5bb9 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -126,6 +126,7 @@ COpenMaxVideo::COpenMaxVideo() - m_egl_buffer_count = 0; - - m_port_settings_changed = false; -+ m_finished = false; - m_pFormatName = "omx-xxxx"; - } - -@@ -134,6 +135,7 @@ COpenMaxVideo::~COpenMaxVideo() - #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); - #endif -+ assert(m_finished); - if (m_omx_decoder.IsInitialized()) - { - if (m_omx_tunnel.IsInitialized()) -@@ -149,7 +151,7 @@ COpenMaxVideo::~COpenMaxVideo() - pthread_mutex_destroy(&m_omx_output_mutex); - } - --bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) -+bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself) - { - #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -@@ -161,6 +163,7 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - -+ m_myself = myself; - m_decoded_width = hints.width; - m_decoded_height = hints.height; - -@@ -331,6 +334,15 @@ void COpenMaxVideo::Dispose() - #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif -+ // we are happy to exit, but let last shared pointer being deleted trigger the destructor -+ bool done = false; -+ pthread_mutex_lock(&m_omx_output_mutex); -+ if (m_omx_output_busy.empty()) -+ done = true; -+ m_finished = true; -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ if (done) -+ m_myself.reset(); - } - - void COpenMaxVideo::SetDropState(bool bDrop) -@@ -752,6 +764,13 @@ void COpenMaxVideo::ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer) - m_omx_output_busy.erase(std::remove(m_omx_output_busy.begin(), m_omx_output_busy.end(), buffer), m_omx_output_busy.end()); - pthread_mutex_unlock(&m_omx_output_mutex); - ReturnOpenMaxBuffer(buffer); -+ bool done = false; -+ pthread_mutex_lock(&m_omx_output_mutex); -+ if (m_finished && m_omx_output_busy.empty()) -+ done = true; -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ if (done) -+ m_myself.reset(); - } - - bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index 9079c13..0975e8a 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -43,6 +43,7 @@ typedef struct omx_demux_packet { - } omx_demux_packet; - - class COpenMaxVideo; -+typedef boost::shared_ptr OpenMaxVideoPtr; - // an omx egl video frame - class COpenMaxVideoBuffer - { -@@ -75,7 +76,7 @@ class COpenMaxVideo - virtual ~COpenMaxVideo(); - - // Required overrides -- virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself); - virtual void Dispose(void); - virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); - virtual void Reset(void); -@@ -112,9 +113,11 @@ class COpenMaxVideo - int m_decoded_width; - int m_decoded_height; - unsigned int m_egl_buffer_count; -+ bool m_finished; - - bool m_port_settings_changed; - const char *m_pFormatName; -+ OpenMaxVideoPtr m_myself; - - std::queue m_dts_queue; - std::queue m_demux_queue; --- -1.9.3 - - -From 4b5259e36cdf7d007c866f862e7275d1e9334b5f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 3 Feb 2014 23:11:31 +0000 -Subject: [PATCH 32/82] [omxcodec] Fix for aspect ratio in non-square pixel - modes - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 17 +++++++++++++++++ - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 3 +++ - 2 files changed, 20 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index 29b5bb9..7e23c87 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -63,6 +63,7 @@ COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv) - index = 0; - egl_image = 0; - texture_id = 0; -+ m_aspect_ratio = 0.0f; - } - - COpenMaxVideoBuffer::~COpenMaxVideoBuffer() -@@ -166,6 +167,8 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM - m_myself = myself; - m_decoded_width = hints.width; - m_decoded_height = hints.height; -+ m_forced_aspect_ratio = hints.forced_aspect; -+ m_aspect_ratio = hints.aspect; - - m_egl_display = g_Windowing.GetEGLDisplay(); - m_egl_context = g_Windowing.GetEGLContext(); -@@ -435,6 +438,9 @@ bool COpenMaxVideo::PortSettingsChanged() - CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - return false; - } -+ if (!m_forced_aspect_ratio && pixel_aspect.nX && pixel_aspect.nY) -+ m_aspect_ratio = (float)pixel_aspect.nX * port_def.format.video.nFrameWidth / -+ ((float)pixel_aspect.nY * port_def.format.video.nFrameHeight); - - if (m_port_settings_changed) - { -@@ -800,6 +806,16 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) - pDvdVideoPicture->iDisplayWidth = m_decoded_width; - pDvdVideoPicture->iDisplayHeight = m_decoded_height; - -+ if (buffer->m_aspect_ratio > 0.0 && !m_forced_aspect_ratio) -+ { -+ pDvdVideoPicture->iDisplayWidth = ((int)lrint(pDvdVideoPicture->iHeight * buffer->m_aspect_ratio)) & -3; -+ if (pDvdVideoPicture->iDisplayWidth > pDvdVideoPicture->iWidth) -+ { -+ pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; -+ pDvdVideoPicture->iDisplayHeight = ((int)lrint(pDvdVideoPicture->iWidth / buffer->m_aspect_ratio)) & -3; -+ } -+ } -+ - #ifdef DTS_QUEUE - if (!m_dts_queue.empty()) - { -@@ -853,6 +869,7 @@ OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone( - - // queue output omx buffer to ready list. - pthread_mutex_lock(&m_omx_output_mutex); -+ buffer->m_aspect_ratio = m_aspect_ratio; - m_omx_output_ready.push(buffer); - pthread_mutex_unlock(&m_omx_output_mutex); - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index 0975e8a..9138a20 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -54,6 +54,7 @@ class COpenMaxVideoBuffer - OMX_BUFFERHEADERTYPE *omx_buffer; - int width; - int height; -+ float m_aspect_ratio; - int index; - - // used for egl based rendering if active -@@ -114,6 +115,8 @@ class COpenMaxVideo - int m_decoded_height; - unsigned int m_egl_buffer_count; - bool m_finished; -+ float m_aspect_ratio; -+ bool m_forced_aspect_ratio; - - bool m_port_settings_changed; - const char *m_pFormatName; --- -1.9.3 - - -From 88238401f7bd76f30e629975c72a0e1e27941c28 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 3 Feb 2014 23:19:22 +0000 -Subject: [PATCH 33/82] [omxcodec] Report error when codec not enabled - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index 7e23c87..2ae722b 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -43,6 +43,7 @@ - #include - - #include "cores/omxplayer/OMXImage.h" -+#include "linux/RBP.h" - - #define DTS_QUEUE - -@@ -155,7 +156,7 @@ COpenMaxVideo::~COpenMaxVideo() - bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself) - { - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ CLog::Log(LOGDEBUG, "%s::%s useomx:%d software:%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.useomx"), hints.software); - #endif - - // we always qualify even if DVDFactoryCodec does this too. -@@ -232,6 +233,13 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM - break; - } - -+ if ( (m_codingType == OMX_VIDEO_CodingMPEG2 && !g_RBP.GetCodecMpg2() ) || -+ (m_codingType == OMX_VIDEO_CodingWMV && !g_RBP.GetCodecWvc1() ) ) -+ { -+ CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported\n", CLASSNAME, __func__, m_pFormatName); -+ return false; -+ } -+ - // initialize OpenMAX. - if (!m_omx_decoder.Initialize("OMX.broadcom.video_decode", OMX_IndexParamVideoInit)) - { --- -1.9.3 - - -From a58f2444e59b8a7cf642ae0b459a93ad55c32e23 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 4 Feb 2014 17:29:37 +0000 -Subject: [PATCH 34/82] [omxcodec] Add deinterlace support - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 +- - .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 106 ++++++++++++++++++--- - .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 9 +- - 3 files changed, 103 insertions(+), 14 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index b8af8d0..51f56aa 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -2605,7 +2605,7 @@ bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode) - return true; - - if(m_renderMethod & RENDER_OMXEGL) -- return false; -+ return true; - - if(m_renderMethod & RENDER_EGLIMG) - return false; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index 2ae722b..fbf1458 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -33,6 +33,7 @@ - #include "utils/log.h" - #include "utils/TimeUtils.h" - #include "settings/Settings.h" -+#include "settings/MediaSettings.h" - #include "ApplicationMessenger.h" - #include "Application.h" - #include "threads/Atomics.h" -@@ -130,6 +131,10 @@ COpenMaxVideo::COpenMaxVideo() - m_port_settings_changed = false; - m_finished = false; - m_pFormatName = "omx-xxxx"; -+ -+ m_deinterlace = false; -+ m_deinterlace_request = VS_DEINTERLACEMODE_OFF; -+ m_deinterlace_second_field = false; - } - - COpenMaxVideo::~COpenMaxVideo() -@@ -140,13 +145,17 @@ COpenMaxVideo::~COpenMaxVideo() - assert(m_finished); - if (m_omx_decoder.IsInitialized()) - { -- if (m_omx_tunnel.IsInitialized()) -- m_omx_tunnel.Deestablish(); -+ if (m_omx_tunnel_decoder.IsInitialized()) -+ m_omx_tunnel_decoder.Deestablish(); -+ if (m_omx_tunnel_image_fx.IsInitialized()) -+ m_omx_tunnel_image_fx.Deestablish(); - - StopDecoder(); - - if (m_omx_egl_render.IsInitialized()) - m_omx_egl_render.Deinitialize(); -+ if (m_omx_image_fx.IsInitialized()) -+ m_omx_image_fx.Deinitialize(); - if (m_omx_decoder.IsInitialized()) - m_omx_decoder.Deinitialize(); - } -@@ -165,6 +174,8 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - -+ m_deinterlace_request = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ - m_myself = myself; - m_decoded_width = hints.width; - m_decoded_height = hints.height; -@@ -467,6 +478,49 @@ bool COpenMaxVideo::PortSettingsChanged() - return false; - } - -+ OMX_CONFIG_INTERLACETYPE interlace; -+ OMX_INIT_STRUCTURE(interlace); -+ interlace.nPortIndex = m_omx_decoder.GetOutputPort(); -+ omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigCommonInterlace, &interlace); -+ -+ if (m_deinterlace_request == VS_DEINTERLACEMODE_FORCE) -+ m_deinterlace = true; -+ else if (m_deinterlace_request == VS_DEINTERLACEMODE_OFF) -+ m_deinterlace = false; -+ else -+ m_deinterlace = interlace.eMode != OMX_InterlaceProgressive; -+ -+ CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", -+ CLASSNAME, __func__, port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight, port_def.format.video.xFramerate / (float) (1 << 16), -+ interlace.eMode, m_deinterlace); -+ -+ if (m_deinterlace) -+ { -+ if (!m_omx_image_fx.Initialize("OMX.broadcom.image_fx", OMX_IndexParamImageInit)) -+ { -+ CLog::Log(LOGERROR, "%s::%s error m_omx_image_fx.Initialize", CLASSNAME, __func__); -+ return false; -+ } -+ } -+ -+ if (m_deinterlace) -+ { -+ OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; -+ OMX_INIT_STRUCTURE(image_filter); -+ -+ image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); -+ image_filter.nNumParams = 1; -+ image_filter.nParams[0] = 3; -+ image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; -+ -+ omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ } -+ - OMX_CALLBACKTYPE callbacks = { NULL, NULL, DecoderFillBufferDoneCallback }; - if (!m_omx_egl_render.Initialize("OMX.broadcom.egl_render", OMX_IndexParamVideoInit, &callbacks)) - { -@@ -487,19 +541,40 @@ bool COpenMaxVideo::PortSettingsChanged() - - m_omx_egl_render.ResetEos(); - -- CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__, -- port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight, -- port_def.format.video.xFramerate / (float)(1<<16), 0,0); -- -- m_omx_tunnel.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort()); -+ if (m_deinterlace) -+ { -+ m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); -+ m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort()); -+ } -+ else -+ { -+ m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort()); -+ } - -- omx_err = m_omx_tunnel.Establish(); -+ omx_err = m_omx_tunnel_decoder.Establish(); - if (omx_err != OMX_ErrorNone) - { -- CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - return false; - } - -+ if (m_deinterlace) -+ { -+ omx_err = m_omx_tunnel_image_fx.Establish(); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_image_fx.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - m_omx_image_fx.SetStateForComponent omx_err(0x%08x)", -+ CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ } -+ - // Obtain the information about the output port. - OMX_PARAM_PORTDEFINITIONTYPE port_format; - OMX_INIT_STRUCTURE(port_format); -@@ -724,8 +799,12 @@ void COpenMaxVideo::Reset(void) - #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - #endif -- m_omx_egl_render.FlushAll(); -- m_omx_decoder.FlushAll(); -+ if (m_omx_egl_render.IsInitialized()) -+ m_omx_egl_render.FlushAll(); -+ if (m_omx_image_fx.IsInitialized()) -+ m_omx_image_fx.FlushAll(); -+ if (m_omx_decoder.IsInitialized()) -+ m_omx_decoder.FlushAll(); - // blow all ready video frames - while (!m_omx_output_ready.empty()) - { -@@ -825,11 +904,14 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) - } - - #ifdef DTS_QUEUE -- if (!m_dts_queue.empty()) -+ if (!m_deinterlace_second_field) - { -+ assert(!m_dts_queue.empty()); - pDvdVideoPicture->dts = m_dts_queue.front(); - m_dts_queue.pop(); - } -+ if (m_deinterlace) -+ m_deinterlace_second_field = !m_deinterlace_second_field; - #endif - // nTimeStamp is in microseconds - double ts = FromOMXTime(buffer->omx_buffer->nTimeStamp); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index 9138a20..c8ad4d8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -31,6 +31,7 @@ - #include "cores/dvdplayer/DVDStreamInfo.h" - #include "DVDVideoCodec.h" - #include "threads/Event.h" -+#include "xbmc/settings/VideoSettings.h" - - #include - #include -@@ -136,11 +137,17 @@ class COpenMaxVideo - - // Components - COMXCoreComponent m_omx_decoder; -+ COMXCoreComponent m_omx_image_fx; - COMXCoreComponent m_omx_egl_render; - -- COMXCoreTunel m_omx_tunnel; -+ COMXCoreTunel m_omx_tunnel_decoder; -+ COMXCoreTunel m_omx_tunnel_image_fx; - OMX_VIDEO_CODINGTYPE m_codingType; - -+ bool m_deinterlace; -+ EDEINTERLACEMODE m_deinterlace_request; -+ bool m_deinterlace_second_field; -+ - bool PortSettingsChanged(); - bool SendDecoderConfig(uint8_t *extradata, int extrasize); - bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize); --- -1.9.3 - - -From de38627cc8686c8044545342b1816cfc182676a9 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 5 Feb 2014 11:46:33 +0000 -Subject: [PATCH 35/82] [rbp/settings] Allow av sync type to be enabled - -It works for dvdplayer ---- - system/settings/rbp.xml | 7 ------- - 1 file changed, 7 deletions(-) - -diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index 2b7d0a6..1429256 100644 ---- a/system/settings/rbp.xml -+++ b/system/settings/rbp.xml -@@ -1,13 +1,6 @@ - - -
-- -- -- -- false -- -- -- - - - false --- -1.9.3 - - -From 33222c103c68a49c3e6a9326a0413cbfdca12b80 Mon Sep 17 00:00:00 2001 -From: Ben Avison -Date: Thu, 1 May 2014 16:28:39 +0100 -Subject: [PATCH 36/82] Improved file buffering in CArchive - -Even though memcpy is typically inlined by the compiler into byte/word loads -and stores (at least for release builds), the frequency with which 1, 2 and 4 -byte loads/stores are encountered in cases where the size is *not* -determinable at compile time is still high enough that it's worth handling -these specially. On the ARM1176JZF-S in the Raspberry Pi, this improves the -total time to open a library (in the case where it's fetched from a CArchive) -by around 4%. - -It should be noted that this code uses 16-bit and 32-bit word loads and -stores that are not necessarily aligned to their respective widths. It is -possible that there are some architectures out there which do not support -this, although all ARMs since ARMv6 have supported it (and ARMs earlier than -that are probably not powerful enough to be good targets for XBMC). ---- - xbmc/utils/Archive.h | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h -index 6ed0f8f..8506d95 100644 ---- a/xbmc/utils/Archive.h -+++ b/xbmc/utils/Archive.h -@@ -154,9 +154,17 @@ class CArchive - * than waiting until we attempt to put more data into an already full buffer */ - if (m_BufferRemain > size) - { -+ switch (size) -+ { -+ case 1: *m_BufferPos++ = *ptr; m_BufferRemain--; break; -+ case 2: *(uint16_t *) m_BufferPos = *(const uint16_t *) ptr; m_BufferPos += 2; m_BufferRemain -= 2; break; -+ case 4: *(uint32_t *) m_BufferPos = *(const uint32_t *) ptr; m_BufferPos += 4; m_BufferRemain -= 4; break; -+ default: - memcpy(m_BufferPos, ptr, size); - m_BufferPos += size; - m_BufferRemain -= size; -+ break; -+ } - return *this; - } - else -@@ -171,9 +179,17 @@ class CArchive - /* Note, refilling the buffer is deferred until we know we need to read more from it */ - if (m_BufferRemain >= size) - { -+ switch (size) -+ { -+ case 1: *ptr = *m_BufferPos++; m_BufferRemain--; break; -+ case 2: *(uint16_t *) ptr = *(const uint16_t *) m_BufferPos; m_BufferPos += 2; m_BufferRemain -= 2; break; -+ case 4: *(uint32_t *) ptr = *(const uint32_t *) m_BufferPos; m_BufferPos += 4; m_BufferRemain -= 4; break; -+ default: - memcpy(ptr, m_BufferPos, size); - m_BufferPos += size; - m_BufferRemain -= size; -+ break; -+ } - return *this; - } - else --- -1.9.3 - - -From 8751a0a0f51afa2ddf14e04f3742512aef1069f3 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 16 Feb 2014 17:38:05 +0000 -Subject: [PATCH 37/82] [omxcodec] Only do essential calls in texture thread - [omxcodec] Fix for files with no valid pts values. [omxcodec] Fix stall on - seek/trickplay - need to reset start flag [omxcodec] Make sure we have a - valid context when video decode starts before first fanart is decoded - [omxcodec] More care with dropping frames quickly - ---- - .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 127 ++++++++++++++------- - .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 14 +-- - 2 files changed, 89 insertions(+), 52 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index fbf1458..71d19af 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -55,6 +55,9 @@ - - #define CLASSNAME "COpenMaxVideo" - -+#define OMX_BUFFERFLAG_PTS_INVALID (1<<28) -+#define OMX_BUFFERFLAG_DROPPED (1<<29) -+ - COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv) - : m_omv(omv), m_refs(0) - { -@@ -120,7 +123,9 @@ void COpenMaxVideoBuffer::Sync() - - COpenMaxVideo::COpenMaxVideo() - { -+ #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+ #endif - pthread_mutex_init(&m_omx_output_mutex, NULL); - - m_drop_state = false; -@@ -135,6 +140,7 @@ COpenMaxVideo::COpenMaxVideo() - m_deinterlace = false; - m_deinterlace_request = VS_DEINTERLACEMODE_OFF; - m_deinterlace_second_field = false; -+ m_startframe = false; - } - - COpenMaxVideo::~COpenMaxVideo() -@@ -182,8 +188,6 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM - m_forced_aspect_ratio = hints.forced_aspect; - m_aspect_ratio = hints.aspect; - -- m_egl_display = g_Windowing.GetEGLDisplay(); -- m_egl_context = g_Windowing.GetEGLContext(); - m_egl_buffer_count = 4; - - m_codingType = OMX_VIDEO_CodingUnused; -@@ -347,6 +351,7 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM - return false; - - m_drop_state = false; -+ m_startframe = false; - - return true; - } -@@ -375,6 +380,25 @@ void COpenMaxVideo::SetDropState(bool bDrop) - CLASSNAME, __func__, bDrop); - #endif - m_drop_state = bDrop; -+ if (m_drop_state) -+ { -+ while (1) -+ { -+ COpenMaxVideoBuffer *buffer = NULL; -+ pthread_mutex_lock(&m_omx_output_mutex); -+ // fetch a output buffer and pop it off the ready list -+ if (!m_omx_output_ready.empty()) -+ { -+ buffer = m_omx_output_ready.front(); -+ m_omx_output_ready.pop(); -+ } -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ if (buffer) -+ ReturnOpenMaxBuffer(buffer); -+ else -+ break; -+ } -+ } - } - - bool COpenMaxVideo::SendDecoderConfig(uint8_t *extradata, int extrasize) -@@ -713,10 +737,13 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - - if (demuxer_bytes == 0) - omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; -- if (pts == DVD_NOPTS_VALUE) -+ // openmax doesn't like an unknown timestamp as first frame -+ if (pts == DVD_NOPTS_VALUE && m_startframe) - omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; -+ if (pts == DVD_NOPTS_VALUE) // hijack an omx flag to indicate there wasn't a real timestamp - it will be returned with the picture (but otherwise ignored) -+ omx_buffer->nFlags |= OMX_BUFFERFLAG_PTS_INVALID; - if (m_drop_state) // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored) -- omx_buffer->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; -+ omx_buffer->nFlags |= OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED; - - #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x", -@@ -731,10 +758,14 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - } - if (demuxer_bytes == 0) - { -+ m_startframe = true; - #ifdef DTS_QUEUE -- // only push if we are successful with feeding OMX_EmptyThisBuffer -- m_dts_queue.push(dts); -- assert(m_dts_queue.size() < 32); -+ if (!m_drop_state) -+ { -+ // only push if we are successful with feeding OMX_EmptyThisBuffer -+ m_dts_queue.push(dts); -+ assert(m_dts_queue.size() < 32); -+ } - #endif - if (buffer_to_free) - { -@@ -806,15 +837,8 @@ void COpenMaxVideo::Reset(void) - if (m_omx_decoder.IsInitialized()) - m_omx_decoder.FlushAll(); - // blow all ready video frames -- while (!m_omx_output_ready.empty()) -- { -- pthread_mutex_lock(&m_omx_output_mutex); -- COpenMaxVideoBuffer *pic = m_omx_output_ready.front(); -- m_omx_output_ready.pop(); -- pthread_mutex_unlock(&m_omx_output_mutex); -- // return the omx buffer back to OpenMax to fill. -- ReturnOpenMaxBuffer(pic); -- } -+ SetDropState(true); -+ SetDropState(false); - #ifdef DTS_QUEUE - while (!m_dts_queue.empty()) - m_dts_queue.pop(); -@@ -822,6 +846,7 @@ void COpenMaxVideo::Reset(void) - - while (!m_demux_queue.empty()) - m_demux_queue.pop(); -+ m_startframe = false; - } - - -@@ -914,17 +939,17 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) - m_deinterlace_second_field = !m_deinterlace_second_field; - #endif - // nTimeStamp is in microseconds -- double ts = FromOMXTime(buffer->omx_buffer->nTimeStamp); -- pDvdVideoPicture->pts = (ts == 0) ? DVD_NOPTS_VALUE : ts; -+ pDvdVideoPicture->pts = FromOMXTime(buffer->omx_buffer->nTimeStamp); - pDvdVideoPicture->openMaxBuffer->Acquire(); - pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -- if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) -- pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; -+ if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_PTS_INVALID) -+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - #if defined(OMX_DEBUG_VERBOSE) - CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__, - pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6, - pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id); - #endif -+ assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED))); - } - else - { -@@ -953,10 +978,11 @@ OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone( - COpenMaxVideoBuffer *buffer = (COpenMaxVideoBuffer*)pBuffer->pAppPrivate; - - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f", -- CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6); -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f flags:%x", -+ CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6, buffer->omx_buffer->nFlags); - #endif - -+ assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED))); - // queue output omx buffer to ready list. - pthread_mutex_lock(&m_omx_output_mutex); - buffer->m_aspect_ratio = m_aspect_ratio; -@@ -1000,41 +1026,60 @@ OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(void) - return(omx_err); - } - --bool COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata) -+bool COpenMaxVideo::CallbackAllocOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void *userdata) - { - COpenMaxVideo *omx = static_cast(userdata); -- return omx->AllocOMXOutputEGLTextures() == OMX_ErrorNone; -+ return omx->AllocOMXOutputEGLTextures(egl_display, egl_context) == OMX_ErrorNone; - } - --bool COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata) -+bool COpenMaxVideo::CallbackFreeOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void *userdata) - { - COpenMaxVideo *omx = static_cast(userdata); -- return omx->FreeOMXOutputEGLTextures() == OMX_ErrorNone; -+ return omx->FreeOMXOutputEGLTextures(egl_display, egl_context) == OMX_ErrorNone; - } - - bool COpenMaxVideo::AllocOMXOutputBuffers(void) - { -- return g_OMXImage.SendMessage(CallbackAllocOMXEGLTextures, (void *)this); -+ pthread_mutex_lock(&m_omx_output_mutex); -+ for (size_t i = 0; i < m_egl_buffer_count; i++) -+ { -+ COpenMaxVideoBuffer *egl_buffer = new COpenMaxVideoBuffer(this); -+ egl_buffer->width = m_decoded_width; -+ egl_buffer->height = m_decoded_height; -+ egl_buffer->index = i; -+ m_omx_output_buffers.push_back(egl_buffer); -+ } -+ bool ret = g_OMXImage.SendMessage(CallbackAllocOMXEGLTextures, (void *)this); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ return ret; - } - - bool COpenMaxVideo::FreeOMXOutputBuffers(void) - { -- return g_OMXImage.SendMessage(CallbackFreeOMXEGLTextures, (void *)this); -+ pthread_mutex_lock(&m_omx_output_mutex); -+ bool ret = g_OMXImage.SendMessage(CallbackFreeOMXEGLTextures, (void *)this); -+ -+ for (size_t i = 0; i < m_omx_output_buffers.size(); i++) -+ { -+ COpenMaxVideoBuffer *egl_buffer = m_omx_output_buffers[i]; -+ delete egl_buffer; -+ } -+ -+ m_omx_output_buffers.clear(); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ return ret; - } - --OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) -+OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context) - { - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - EGLint attrib = EGL_NONE; -- COpenMaxVideoBuffer *egl_buffer; - - glActiveTexture(GL_TEXTURE0); - - for (size_t i = 0; i < m_egl_buffer_count; i++) - { -- egl_buffer = new COpenMaxVideoBuffer(this); -- egl_buffer->width = m_decoded_width; -- egl_buffer->height = m_decoded_height; -+ COpenMaxVideoBuffer *egl_buffer = m_omx_output_buffers[i]; - - glGenTextures(1, &egl_buffer->texture_id); - glBindTexture(GL_TEXTURE_2D, egl_buffer->texture_id); -@@ -1057,8 +1102,8 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - - // create EGLImage from texture - egl_buffer->egl_image = eglCreateImageKHR( -- m_egl_display, -- m_egl_context, -+ egl_display, -+ egl_context, - EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer)(egl_buffer->texture_id), - &attrib); -@@ -1067,7 +1112,6 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage", CLASSNAME, __func__); - return(OMX_ErrorUndefined); - } -- egl_buffer->index = i; - - // tell decoder output port that it will be using EGLImage - omx_err = m_omx_egl_render.UseEGLImage( -@@ -1078,7 +1122,6 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - CLASSNAME, __func__, omx_err); - return(omx_err); - } -- m_omx_output_buffers.push_back(egl_buffer); - - CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d", - CLASSNAME, __func__, egl_buffer->egl_image, egl_buffer->width, egl_buffer->height); -@@ -1086,26 +1129,22 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void) - return omx_err; - } - --OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(void) -+OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context) - { - OMX_ERRORTYPE omx_err = OMX_ErrorNone; -- COpenMaxVideoBuffer *egl_buffer; - - for (size_t i = 0; i < m_omx_output_buffers.size(); i++) - { -- egl_buffer = m_omx_output_buffers[i]; -+ COpenMaxVideoBuffer *egl_buffer = m_omx_output_buffers[i]; - // tell decoder output port to stop using the EGLImage - omx_err = m_omx_egl_render.FreeOutputBuffer(egl_buffer->omx_buffer); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.FreeOutputBuffer(%p) omx_err(0x%08x)", CLASSNAME, __func__, egl_buffer->omx_buffer, omx_err); - // destroy egl_image -- eglDestroyImageKHR(m_egl_display, egl_buffer->egl_image); -+ eglDestroyImageKHR(egl_display, egl_buffer->egl_image); - // free texture - glDeleteTextures(1, &egl_buffer->texture_id); -- delete egl_buffer; - } -- m_omx_output_buffers.clear(); -- - return omx_err; - } - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index c8ad4d8..f234f6d 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -99,17 +99,13 @@ class COpenMaxVideo - OMX_ERRORTYPE FreeOMXInputBuffers(void); - bool AllocOMXOutputBuffers(void); - bool FreeOMXOutputBuffers(void); -- static bool CallbackAllocOMXEGLTextures(void*); -- OMX_ERRORTYPE AllocOMXOutputEGLTextures(void); -- static bool CallbackFreeOMXEGLTextures(void*); -- OMX_ERRORTYPE FreeOMXOutputEGLTextures(void); -+ static bool CallbackAllocOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void*); -+ OMX_ERRORTYPE AllocOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context); -+ static bool CallbackFreeOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void*); -+ OMX_ERRORTYPE FreeOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context); - OMX_ERRORTYPE StopDecoder(void); - OMX_ERRORTYPE ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer); - -- // EGL Resources -- EGLDisplay m_egl_display; -- EGLContext m_egl_context; -- - // Video format - bool m_drop_state; - int m_decoded_width; -@@ -148,6 +144,8 @@ class COpenMaxVideo - EDEINTERLACEMODE m_deinterlace_request; - bool m_deinterlace_second_field; - -+ bool m_startframe; -+ - bool PortSettingsChanged(); - bool SendDecoderConfig(uint8_t *extradata, int extrasize); - bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize); --- -1.9.3 - - -From 5031e939e8df53f54e2534c6b08cf01d799d59cd Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 8 Mar 2014 15:36:06 +0000 -Subject: [PATCH 38/82] [hifiberry] Hack: force it to be recognised as IEC958 - capable to enable passthrough options - ---- - xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -index 8cbf6e5..a8ad933 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp -@@ -932,6 +932,10 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev - if (snd_card_get_name(cardNr, &cardName) == 0) - info.m_displayName = cardName; - -+ // hack: hifiberry digi doesn't correctly report as iec958 device. Needs fixing in kernel driver -+ if (info.m_displayName == "snd_rpi_hifiberry_digi") -+ info.m_deviceType = AE_DEVTYPE_IEC958; -+ - if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 && - info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") - { --- -1.9.3 - - -From 3ec3d6ea28dadd7cefec19e5c4e9d30af2478382 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 11 Mar 2014 18:50:23 +0000 -Subject: [PATCH 39/82] [dvdplayer] Use inexact seeking like omxplayer - ---- - xbmc/cores/dvdplayer/DVDPlayer.cpp | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 0634880..768f51f 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayer.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -1898,7 +1898,11 @@ void CDVDPlayer::CheckAutoSceneSkip() - /* - * Seeking is NOT flushed so any content up to the demux point is retained when playing forwards. - */ -+#ifdef TARGET_RASPBERRY_PI -+ m_messenger.Put(new CDVDMsgPlayerSeek((int)seek, true, true, true, false, true)); -+#else - m_messenger.Put(new CDVDMsgPlayerSeek((int)seek, true, false, true, false, true)); -+#endif - /* - * Seek doesn't always work reliably. Last physical seek time is recorded to prevent looping - * if there was an error with seeking and it landed somewhere unexpected, perhaps back in the -@@ -1916,7 +1920,11 @@ void CDVDPlayer::CheckAutoSceneSkip() - /* - * Seeking is NOT flushed so any content up to the demux point is retained when playing forwards. - */ -+#ifdef TARGET_RASPBERRY_PI -+ m_messenger.Put(new CDVDMsgPlayerSeek(cut.end + 1, true, false, true, false, true)); -+#else - m_messenger.Put(new CDVDMsgPlayerSeek(cut.end + 1, true, false, true, false, true)); -+#endif - /* - * Each commercial break is only skipped once so poorly detected commercial breaks can be - * manually re-entered. Start and end are recorded to prevent looping and to allow seeking back -@@ -3119,9 +3127,12 @@ void CDVDPlayer::UpdateClockMaster() - void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) - { - double startpts; -+#ifndef TARGET_RASPBERRY_PI -+ /* for now, ignore accurate flag as it discards keyframes and causes corrupt frames */ - if(accurate) - startpts = pts; - else -+#endif - startpts = DVD_NOPTS_VALUE; - - /* call with demuxer pts */ --- -1.9.3 - - -From f451883f443aad6156fe67621bb029e444480eac Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 13 Mar 2014 16:08:46 +0000 -Subject: [PATCH 40/82] [omxplayer] Make use of TrueHD fastpath when downmixing - -The TrueHD codec actually works in 3 stages. -It decodes the downmixed stereo. -It then decodes the differences required to produce 5.1. -It then decodes the differences required to produce 7.1. - -Many users end up downmixing this 7.1 stream back to 2.0. -Much better to tell the codec we only need the 2.0 stream. -It saves about 50% of the CPU required ---- - xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp -index bb3bea4..dab9f27 100644 ---- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp -+++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp -@@ -25,6 +25,7 @@ - #include "utils/log.h" - - #include "cores/AudioEngine/Utils/AEUtil.h" -+#include "settings/Settings.h" - - // the size of the audio_render output port buffers - #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024) -@@ -86,6 +87,16 @@ bool COMXAudioCodecOMX::Open(CDVDStreamInfo &hints) - m_pCodecContext->block_align = hints.blockalign; - m_pCodecContext->bit_rate = hints.bitrate; - m_pCodecContext->bits_per_coded_sample = hints.bitspersample; -+ enum AEStdChLayout layout = (enum AEStdChLayout)CSettings::Get().GetInt("audiooutput.channels"); -+ if (hints.codec == AV_CODEC_ID_TRUEHD) -+ { -+ if (layout == AE_CH_LAYOUT_2_0) -+ m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_STEREO; -+ else if (layout <= AE_CH_LAYOUT_5_1) -+ m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_5POINT1; -+ } -+ if (m_pCodecContext->request_channel_layout) -+ CLog::Log(LOGNOTICE,"COMXAudioCodecOMX::Open() Requesting channel layout of %d", (unsigned)m_pCodecContext->request_channel_layout); - - // vorbis has variable sized planar output, so skip concatenation - if (hints.codec == AV_CODEC_ID_VORBIS) --- -1.9.3 - - -From 881f62fcbc398b75eaae7516a04d47cd5bb27b57 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 7 Apr 2014 18:19:32 +0100 -Subject: [PATCH 41/82] [rbp/omxplayer] When opening a stream don't try to - update gui so often - ---- - xbmc/dialogs/GUIDialogBusy.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/xbmc/dialogs/GUIDialogBusy.cpp b/xbmc/dialogs/GUIDialogBusy.cpp -index e9ba7d3..0fdc3c2 100644 ---- a/xbmc/dialogs/GUIDialogBusy.cpp -+++ b/xbmc/dialogs/GUIDialogBusy.cpp -@@ -64,7 +64,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10 - if (dialog) - { - dialog->Show(); -+#ifdef TARGET_RASPBERRY_PI -+ while(!event.WaitMSec(100)) -+#else - while(!event.WaitMSec(1)) -+#endif - { - g_windowManager.ProcessRenderLoop(false); - if (allowCancel && dialog->IsCanceled()) --- -1.9.3 - - -From 6ff163cde8381e808ef65ffe6fc88f2d94fd2108 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 7 Apr 2014 15:28:57 +0100 -Subject: [PATCH 42/82] [omxcodec] Clamp video texture at edges to avoid image - wrapping - ---- - xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -index 51f56aa..2929a37 100644 ---- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp -@@ -1337,6 +1337,8 @@ void CLinuxRendererGLES::RenderOpenMax(int index, int field) - GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; - glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA); - --- -1.9.3 - - -From f67916b281a03d25e57a325983446317e412dff3 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 30 Mar 2014 15:54:34 +0100 -Subject: [PATCH 43/82] [omxplayer] Make the sharpness control act as a - sharpness control. - -This fixes scaling kernel as Mitchell Netravali, and varies sharpness over range B=[5/3,0] C=[-1/3,1/2] ---- - xbmc/cores/omxplayer/OMXPlayer.cpp | 338 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 338 insertions(+) - -diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp -index 49e0fed..12e887e 100644 ---- a/xbmc/cores/omxplayer/OMXPlayer.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayer.cpp -@@ -1051,6 +1051,334 @@ bool COMXPlayer::IsBetterStream(COMXCurrentStream& current, CDemuxStream* stream - return false; - } - -+static void SetSharpness(float sharpness) -+{ -+ const int16_t mitchells[][32] = -+ { -+ { // B=1.66667 C=-0.33333 -+ 0, 3, 8, 15, 24, 35, 49, 55, 70, 92,100,107,109,113,113,114,114,113,113,109,107,100, 92, 70, 55, 49, 35, 24, 15, 8, 3, 0, -+ }, -+ { // B=1.64000 C=-0.32000 -+ 0, 3, 7, 14, 24, 34, 48, 54, 69, 91,100,107,111,114,116,116,116,116,114,111,107,100, 91, 69, 54, 48, 34, 24, 14, 7, 3, 0, -+ }, -+ { // B=1.61333 C=-0.30667 -+ 0, 3, 7, 14, 23, 34, 47, 53, 68, 90, 99,107,112,115,118,118,118,118,115,112,107, 99, 90, 68, 53, 47, 34, 23, 14, 7, 3, 0, -+ }, -+ { // B=1.58667 C=-0.29333 -+ 0, 2, 7, 14, 22, 33, 46, 52, 67, 89, 99,107,113,117,119,121,121,119,117,113,107, 99, 89, 67, 52, 46, 33, 22, 14, 7, 2, 0, -+ }, -+ { // B=1.56000 C=-0.28000 -+ 0, 2, 7, 13, 22, 32, 45, 51, 66, 88, 98,107,114,119,121,123,123,121,119,114,107, 98, 88, 66, 51, 45, 32, 22, 13, 7, 2, 0, -+ }, -+ { // B=1.53333 C=-0.26667 -+ 0, 2, 7, 12, 21, 31, 44, 50, 65, 87, 98,108,114,120,123,125,125,123,120,114,108, 98, 87, 65, 50, 44, 31, 21, 12, 7, 2, 0, -+ }, -+ { // B=1.50667 C=-0.25333 -+ 0, 2, 6, 12, 20, 30, 43, 49, 64, 86, 98,108,116,122,125,127,127,125,122,116,108, 98, 86, 64, 49, 43, 30, 20, 12, 6, 2, 0, -+ }, -+ { // B=1.48000 C=-0.24000 -+ 0, 2, 6, 12, 19, 29, 42, 47, 63, 85, 98,108,117,123,127,130,130,127,123,117,108, 98, 85, 63, 47, 42, 29, 19, 12, 6, 2, 0, -+ }, -+ { // B=1.45333 C=-0.22667 -+ 0, 2, 6, 11, 19, 28, 41, 46, 62, 85, 97,108,118,125,129,132,132,129,125,118,108, 97, 85, 62, 46, 41, 28, 19, 11, 6, 2, 0, -+ }, -+ { // B=1.42667 C=-0.21333 -+ 0, 2, 5, 11, 18, 28, 40, 45, 61, 84, 97,108,119,126,131,134,134,131,126,119,108, 97, 84, 61, 45, 40, 28, 18, 11, 5, 2, 0, -+ }, -+ { // B=1.40000 C=-0.20000 -+ 0, 2, 5, 10, 18, 27, 39, 44, 60, 84, 96,109,119,127,134,136,136,134,127,119,109, 96, 84, 60, 44, 39, 27, 18, 10, 5, 2, 0, -+ }, -+ { // B=1.37333 C=-0.18667 -+ 0, 1, 5, 10, 17, 26, 38, 43, 58, 82, 96,109,120,129,135,139,139,135,129,120,109, 96, 82, 58, 43, 38, 26, 17, 10, 5, 1, 0, -+ }, -+ { // B=1.34667 C=-0.17333 -+ 0, 2, 4, 10, 16, 25, 37, 42, 57, 81, 96,109,121,131,137,141,141,137,131,121,109, 96, 81, 57, 42, 37, 25, 16, 10, 4, 2, 0, -+ }, -+ { // B=1.32000 C=-0.16000 -+ 0, 1, 4, 9, 15, 24, 36, 41, 56, 81, 95,110,122,132,139,143,143,139,132,122,110, 95, 81, 56, 41, 36, 24, 15, 9, 4, 1, 0, -+ }, -+ { // B=1.29333 C=-0.14667 -+ 0, 1, 4, 8, 15, 23, 35, 40, 55, 80, 95,110,123,133,141,146,146,141,133,123,110, 95, 80, 55, 40, 35, 23, 15, 8, 4, 1, 0, -+ }, -+ { // B=1.26667 C=-0.13333 -+ 0, 1, 4, 8, 14, 22, 33, 38, 54, 79, 95,110,124,135,143,148,148,143,135,124,110, 95, 79, 54, 38, 33, 22, 14, 8, 4, 1, 0, -+ }, -+ { // B=1.24000 C=-0.12000 -+ 0, 1, 4, 7, 14, 21, 33, 37, 53, 78, 94,110,125,136,145,150,150,145,136,125,110, 94, 78, 53, 37, 33, 21, 14, 7, 4, 1, 0, -+ }, -+ { // B=1.21333 C=-0.10667 -+ 0, 1, 3, 7, 13, 20, 32, 36, 52, 77, 94,110,127,138,147,152,152,147,138,127,110, 94, 77, 52, 36, 32, 20, 13, 7, 3, 1, 0, -+ }, -+ { // B=1.18667 C=-0.09333 -+ 0, 1, 3, 7, 12, 20, 30, 35, 51, 77, 93,111,125,140,149,155,155,149,140,125,111, 93, 77, 51, 35, 30, 20, 12, 7, 3, 1, 0, -+ }, -+ { // B=1.16000 C=-0.08000 -+ 0, 1, 3, 6, 11, 19, 29, 34, 50, 76, 93,111,128,141,151,157,157,151,141,128,111, 93, 76, 50, 34, 29, 19, 11, 6, 3, 1, 0, -+ }, -+ { // B=1.13333 C=-0.06667 -+ 0, 1, 3, 5, 11, 18, 28, 33, 49, 75, 93,111,129,143,153,159,159,153,143,129,111, 93, 75, 49, 33, 28, 18, 11, 5, 3, 1, 0, -+ }, -+ { // B=1.10667 C=-0.05333 -+ 0, 1, 2, 5, 10, 17, 27, 32, 48, 74, 93,111,130,144,155,161,161,155,144,130,111, 93, 74, 48, 32, 27, 17, 10, 5, 2, 1, 0, -+ }, -+ { // B=1.08000 C=-0.04000 -+ 0, 1, 2, 5, 9, 16, 26, 31, 46, 73, 92,112,130,145,157,164,164,157,145,130,112, 92, 73, 46, 31, 26, 16, 9, 5, 2, 1, 0, -+ }, -+ { // B=1.05333 C=-0.02667 -+ 0, 0, 2, 4, 9, 15, 25, 29, 45, 72, 92,112,131,147,159,166,166,159,147,131,112, 92, 72, 45, 29, 25, 15, 9, 4, 2, 0, 0, -+ }, -+ { // B=1.02667 C=-0.01333 -+ 0, 0, 1, 4, 8, 14, 24, 28, 44, 72, 92,112,132,148,161,168,168,161,148,132,112, 92, 72, 44, 28, 24, 14, 8, 4, 1, 0, 0, -+ }, -+ { // B=1.00000 C=0.00000 -+ 0, 0, 1, 4, 7, 14, 23, 27, 43, 71, 91,112,133,150,163,170,170,163,150,133,112, 91, 71, 43, 27, 23, 14, 7, 4, 1, 0, 0, -+ }, -+ { // B=0.97333 C=0.01333 -+ 0, 0, 1, 3, 7, 12, 22, 26, 42, 70, 91,113,133,152,165,173,173,165,152,133,113, 91, 70, 42, 26, 22, 12, 7, 3, 1, 0, 0, -+ }, -+ { // B=0.94667 C=0.02667 -+ 0, 0, 1, 2, 6, 12, 21, 25, 41, 69, 90,113,135,153,167,175,175,167,153,135,113, 90, 69, 41, 25, 21, 12, 6, 2, 1, 0, 0, -+ }, -+ { // B=0.92000 C=0.04000 -+ 0, 0, 0, 2, 5, 11, 20, 24, 40, 68, 90,113,136,154,169,177,177,169,154,136,113, 90, 68, 40, 24, 20, 11, 5, 2, 0, 0, 0, -+ }, -+ { // B=0.89333 C=0.05333 -+ 0, 0, 0, 1, 5, 10, 19, 23, 39, 67, 90,114,136,156,171,179,179,171,156,136,114, 90, 67, 39, 23, 19, 10, 5, 1, 0, 0, 0, -+ }, -+ { // B=0.86667 C=0.06667 -+ 0, 0, 0, 1, 4, 9, 18, 22, 38, 66, 89,114,137,157,173,182,182,173,157,137,114, 89, 66, 38, 22, 18, 9, 4, 1, 0, 0, 0, -+ }, -+ { // B=0.84000 C=0.08000 -+ 0, 0, -1, 1, 3, 9, 17, 21, 37, 65, 89,114,138,159,175,184,184,175,159,138,114, 89, 65, 37, 21, 17, 9, 3, 1, -1, 0, 0, -+ }, -+ { // B=0.81333 C=0.09333 -+ 0, 0, -1, 0, 3, 7, 16, 19, 36, 65, 89,114,139,160,177,186,186,177,160,139,114, 89, 65, 36, 19, 16, 7, 3, 0, -1, 0, 0, -+ }, -+ { // B=0.78667 C=0.10667 -+ 0, -1, -1, 0, 2, 6, 15, 18, 35, 64, 88,115,139,162,179,188,188,179,162,139,115, 88, 64, 35, 18, 15, 6, 2, 0, -1, -1, 0, -+ }, -+ { // B=0.76000 C=0.12000 -+ 0, -1, -1, -1, 1, 6, 14, 17, 33, 63, 88,115,141,163,181,191,191,181,163,141,115, 88, 63, 33, 17, 14, 6, 1, -1, -1, -1, 0, -+ }, -+ { // B=0.73333 C=0.13333 -+ 0, -1, -1, -1, 0, 5, 13, 16, 32, 62, 87,115,142,165,183,193,193,183,165,142,115, 87, 62, 32, 16, 13, 5, 0, -1, -1, -1, 0, -+ }, -+ { // B=0.70667 C=0.14667 -+ 0, -1, -1, -2, 0, 4, 12, 15, 31, 61, 87,115,143,166,185,195,195,185,166,143,115, 87, 61, 31, 15, 12, 4, 0, -2, -1, -1, 0, -+ }, -+ { // B=0.68000 C=0.16000 -+ 0, -1, -2, -2, -1, 3, 11, 14, 30, 61, 87,116,142,168,187,197,197,187,168,142,116, 87, 61, 30, 14, 11, 3, -1, -2, -2, -1, 0, -+ }, -+ { // B=0.65333 C=0.17333 -+ 0, -1, -2, -3, -1, 2, 10, 13, 29, 60, 86,116,144,169,189,200,200,189,169,144,116, 86, 60, 29, 13, 10, 2, -1, -3, -2, -1, 0, -+ }, -+ { // B=0.62667 C=0.18667 -+ 0, -1, -3, -3, -2, 1, 9, 12, 28, 59, 86,116,145,171,191,202,202,191,171,145,116, 86, 59, 28, 12, 9, 1, -2, -3, -3, -1, 0, -+ }, -+ { // B=0.60000 C=0.20000 -+ 0, -1, -3, -3, -3, 0, 8, 10, 27, 58, 86,116,146,172,193,204,204,193,172,146,116, 86, 58, 27, 10, 8, 0, -3, -3, -3, -1, 0, -+ }, -+ { // B=0.57333 C=0.21333 -+ 0, -1, -3, -4, -3, -1, 7, 9, 26, 57, 86,116,147,174,194,207,207,194,174,147,116, 86, 57, 26, 9, 7, -1, -3, -4, -3, -1, 0, -+ }, -+ { // B=0.54667 C=0.22667 -+ 0, -2, -3, -5, -4, -1, 5, 8, 25, 57, 85,117,148,176,196,209,209,196,176,148,117, 85, 57, 25, 8, 5, -1, -4, -5, -3, -2, 0, -+ }, -+ { // B=0.52000 C=0.24000 -+ 0, -1, -4, -5, -5, -2, 4, 7, 24, 55, 85,117,149,177,199,211,211,199,177,149,117, 85, 55, 24, 7, 4, -2, -5, -5, -4, -1, 0, -+ }, -+ { // B=0.49333 C=0.25333 -+ 0, -2, -4, -5, -6, -3, 3, 6, 23, 55, 84,117,150,178,200,214,214,200,178,150,117, 84, 55, 23, 6, 3, -3, -6, -5, -4, -2, 0, -+ }, -+ { // B=0.46667 C=0.26667 -+ 0, -2, -4, -6, -6, -4, 2, 6, 22, 54, 84,118,150,180,202,216,216,202,180,150,118, 84, 54, 22, 6, 2, -4, -6, -6, -4, -2, 0, -+ }, -+ { // B=0.44000 C=0.28000 -+ 0, -2, -4, -6, -7, -5, 2, 5, 21, 53, 83,118,150,181,205,218,218,205,181,150,118, 83, 53, 21, 5, 2, -5, -7, -6, -4, -2, 0, -+ }, -+ { // B=0.41333 C=0.29333 -+ 0, -2, -4, -7, -7, -6, 0, 5, 20, 53, 83,118,152,183,207,220,220,207,183,152,118, 83, 53, 20, 5, 0, -6, -7, -7, -4, -2, 0, -+ }, -+ { // B=0.38667 C=0.30667 -+ 0, -2, -5, -7, -8, -7, -1, 4, 19, 52, 83,118,153,185,208,223,223,208,185,153,118, 83, 52, 19, 4, -1, -7, -8, -7, -5, -2, 0, -+ }, -+ { // B=0.36000 C=0.32000 -+ 0, -2, -5, -8, -8, -8, -2, 3, 19, 51, 83,118,155,186,210,225,225,210,186,155,118, 83, 51, 19, 3, -2, -8, -8, -8, -5, -2, 0, -+ }, -+ { // B=0.33333 C=0.33333 -+ 0, -2, -6, -8,-10, -8, -3, 2, 18, 50, 82,119,155,187,213,227,227,213,187,155,119, 82, 50, 18, 2, -3, -8,-10, -8, -6, -2, 0, -+ }, -+ { // B=0.32667 C=0.33667 -+ 0, -2, -6, -8,-10, -8, -3, 2, 18, 49, 82,119,155,188,213,228,228,213,188,155,119, 82, 49, 18, 2, -3, -8,-10, -8, -6, -2, 0, -+ }, -+ { // B=0.32000 C=0.34000 -+ 0, -2, -6, -8,-10, -9, -3, 2, 18, 49, 82,119,155,188,214,228,228,214,188,155,119, 82, 49, 18, 2, -3, -9,-10, -8, -6, -2, 0, -+ }, -+ { // B=0.31333 C=0.34333 -+ 0, -2, -6, -8,-10, -9, -4, 1, 18, 49, 82,119,155,188,214,229,229,214,188,155,119, 82, 49, 18, 1, -4, -9,-10, -8, -6, -2, 0, -+ }, -+ { // B=0.30667 C=0.34667 -+ 0, -2, -6, -9,-10, -9, -4, 1, 18, 49, 82,119,156,189,214,229,229,214,189,156,119, 82, 49, 18, 1, -4, -9,-10, -9, -6, -2, 0, -+ }, -+ { // B=0.30000 C=0.35000 -+ 0, -3, -5, -9,-10,-10, -4, 1, 18, 49, 82,119,156,189,215,230,230,215,189,156,119, 82, 49, 18, 1, -4,-10,-10, -9, -5, -3, 0, -+ }, -+ { // B=0.29333 C=0.35333 -+ 0, -2, -6, -9,-10,-10, -4, 1, 17, 48, 82,119,156,190,215,231,231,215,190,156,119, 82, 48, 17, 1, -4,-10,-10, -9, -6, -2, 0, -+ }, -+ { // B=0.28667 C=0.35667 -+ 0, -2, -6, -9,-11,-10, -5, 1, 17, 48, 82,119,157,190,216,231,231,216,190,157,119, 82, 48, 17, 1, -5,-10,-11, -9, -6, -2, 0, -+ }, -+ { // B=0.28000 C=0.36000 -+ 0, -3, -6, -9,-11,-10, -5, 0, 17, 48, 82,119,157,190,217,231,231,217,190,157,119, 82, 48, 17, 0, -5,-10,-11, -9, -6, -3, 0, -+ }, -+ { // B=0.27333 C=0.36333 -+ 0, -3, -6, -9,-11,-11, -5, 0, 17, 48, 82,119,157,191,217,232,232,217,191,157,119, 82, 48, 17, 0, -5,-11,-11, -9, -6, -3, 0, -+ }, -+ { // B=0.26667 C=0.36667 -+ 0, -3, -6, -9,-11,-11, -5, 0, 17, 48, 81,119,157,191,217,233,233,217,191,157,119, 81, 48, 17, 0, -5,-11,-11, -9, -6, -3, 0, -+ }, -+ { // B=0.26000 C=0.37000 -+ 0, -3, -6,-10,-11,-11, -5, 0, 16, 47, 81,120,156,191,218,233,233,218,191,156,120, 81, 47, 16, 0, -5,-11,-11,-10, -6, -3, 0, -+ }, -+ { // B=0.25333 C=0.37333 -+ 0, -3, -6, -9,-12,-11, -6, 0, 16, 47, 81,119,158,192,218,234,234,218,192,158,119, 81, 47, 16, 0, -6,-11,-12, -9, -6, -3, 0, -+ }, -+ { // B=0.24667 C=0.37667 -+ 0, -3, -6,-10,-12,-11, -6, 0, 16, 47, 81,120,157,192,219,234,234,219,192,157,120, 81, 47, 16, 0, -6,-11,-12,-10, -6, -3, 0, -+ }, -+ { // B=0.24000 C=0.38000 -+ 0, -3, -6,-10,-12,-12, -6, -1, 16, 47, 81,120,158,193,219,235,235,219,193,158,120, 81, 47, 16, -1, -6,-12,-12,-10, -6, -3, 0, -+ }, -+ { // B=0.23333 C=0.38333 -+ 0, -3, -6,-10,-12,-12, -6, -1, 16, 46, 81,120,158,193,220,236,236,220,193,158,120, 81, 46, 16, -1, -6,-12,-12,-10, -6, -3, 0, -+ }, -+ { // B=0.22667 C=0.38667 -+ 0, -3, -6,-10,-12,-12, -7, -1, 15, 47, 80,120,158,194,220,236,236,220,194,158,120, 80, 47, 15, -1, -7,-12,-12,-10, -6, -3, 0, -+ }, -+ { // B=0.22000 C=0.39000 -+ 0, -3, -6,-10,-13,-12, -7, -1, 15, 46, 80,120,159,194,221,237,237,221,194,159,120, 80, 46, 15, -1, -7,-12,-13,-10, -6, -3, 0, -+ }, -+ { // B=0.21333 C=0.39333 -+ 0, -3, -6,-10,-13,-12, -8, -1, 15, 46, 80,120,159,194,221,237,237,221,194,159,120, 80, 46, 15, -1, -8,-12,-13,-10, -6, -3, 0, -+ }, -+ { // B=0.20667 C=0.39667 -+ 0, -3, -7,-10,-13,-12, -8, -2, 15, 46, 80,120,159,194,222,238,238,222,194,159,120, 80, 46, 15, -2, -8,-12,-13,-10, -7, -3, 0, -+ }, -+ { // B=0.20000 C=0.40000 -+ 0, -3, -7,-10,-13,-13, -8, -2, 15, 45, 81,120,159,195,222,238,238,222,195,159,120, 81, 45, 15, -2, -8,-13,-13,-10, -7, -3, 0, -+ }, -+ { // B=0.19333 C=0.40333 -+ 0, -3, -7,-11,-13,-13, -8, -2, 15, 45, 81,120,160,195,223,239,239,223,195,160,120, 81, 45, 15, -2, -8,-13,-13,-11, -7, -3, 0, -+ }, -+ { // B=0.18667 C=0.40667 -+ 0, -3, -7,-10,-14,-13, -9, -2, 14, 45, 80,120,160,196,223,240,240,223,196,160,120, 80, 45, 14, -2, -9,-13,-14,-10, -7, -3, 0, -+ }, -+ { // B=0.18000 C=0.41000 -+ 0, -3, -7,-11,-13,-13, -9, -2, 14, 45, 80,120,160,196,224,240,240,224,196,160,120, 80, 45, 14, -2, -9,-13,-13,-11, -7, -3, 0, -+ }, -+ { // B=0.17333 C=0.41333 -+ 0, -3, -7,-11,-13,-14, -9, -3, 14, 45, 80,120,160,196,225,240,240,225,196,160,120, 80, 45, 14, -3, -9,-14,-13,-11, -7, -3, 0, -+ }, -+ { // B=0.16667 C=0.41667 -+ 0, -3, -7,-11,-14,-14, -9, -3, 14, 44, 80,120,161,197,225,241,241,225,197,161,120, 80, 44, 14, -3, -9,-14,-14,-11, -7, -3, 0, -+ }, -+ { // B=0.16000 C=0.42000 -+ 0, -3, -7,-11,-14,-14,-10, -3, 14, 44, 80,120,161,197,225,242,242,225,197,161,120, 80, 44, 14, -3,-10,-14,-14,-11, -7, -3, 0, -+ }, -+ { // B=0.15333 C=0.42333 -+ 0, -3, -7,-11,-14,-14,-10, -3, 13, 44, 80,120,161,197,226,242,242,226,197,161,120, 80, 44, 13, -3,-10,-14,-14,-11, -7, -3, 0, -+ }, -+ { // B=0.14667 C=0.42667 -+ 0, -3, -7,-11,-15,-14,-10, -4, 14, 43, 80,120,163,198,226,243,243,226,198,163,120, 80, 43, 14, -4,-10,-14,-15,-11, -7, -3, 0, -+ }, -+ { // B=0.14000 C=0.43000 -+ 0, -3, -7,-12,-14,-15,-10, -4, 14, 43, 80,120,163,198,227,243,243,227,198,163,120, 80, 43, 14, -4,-10,-15,-14,-12, -7, -3, 0, -+ }, -+ { // B=0.13333 C=0.43333 -+ 0, -3, -7,-12,-14,-15,-11, -4, 13, 43, 79,121,161,199,227,244,244,227,199,161,121, 79, 43, 13, -4,-11,-15,-14,-12, -7, -3, 0, -+ }, -+ { // B=0.12667 C=0.43667 -+ 0, -3, -7,-12,-14,-15,-11, -4, 13, 43, 79,120,163,199,228,245,245,228,199,163,120, 79, 43, 13, -4,-11,-15,-14,-12, -7, -3, 0, -+ }, -+ { // B=0.12000 C=0.44000 -+ 0, -3, -7,-12,-15,-15,-12, -5, 13, 43, 79,121,162,199,228,245,245,228,199,162,121, 79, 43, 13, -5,-12,-15,-15,-12, -7, -3, 0, -+ }, -+ { // B=0.11333 C=0.44333 -+ 0, -3, -7,-12,-15,-16,-11, -5, 13, 42, 79,121,162,200,229,246,246,229,200,162,121, 79, 42, 13, -5,-11,-16,-15,-12, -7, -3, 0, -+ }, -+ { // B=0.10667 C=0.44667 -+ 0, -3, -8,-12,-15,-16,-12, -5, 13, 42, 79,121,162,200,229,246,246,229,200,162,121, 79, 42, 13, -5,-12,-16,-15,-12, -8, -3, 0, -+ }, -+ { // B=0.10000 C=0.45000 -+ 0, -3, -8,-12,-16,-16,-12, -6, 13, 42, 79,121,163,200,230,247,247,230,200,163,121, 79, 42, 13, -6,-12,-16,-16,-12, -8, -3, 0, -+ }, -+ { // B=0.09333 C=0.45333 -+ 0, -3, -8,-12,-16,-16,-13, -5, 12, 42, 79,121,163,201,230,248,248,230,201,163,121, 79, 42, 12, -5,-13,-16,-16,-12, -8, -3, 0, -+ }, -+ { // B=0.08667 C=0.45667 -+ 0, -3, -8,-12,-16,-16,-13, -5, 12, 41, 79,121,163,201,231,248,248,231,201,163,121, 79, 41, 12, -5,-13,-16,-16,-12, -8, -3, 0, -+ }, -+ { // B=0.08000 C=0.46000 -+ 0, -3, -8,-12,-16,-17,-13, -6, 12, 41, 79,121,163,201,232,248,248,232,201,163,121, 79, 41, 12, -6,-13,-17,-16,-12, -8, -3, 0, -+ }, -+ { // B=0.07333 C=0.46333 -+ 0, -3, -8,-13,-16,-17,-13, -6, 12, 41, 79,121,164,202,232,249,249,232,202,164,121, 79, 41, 12, -6,-13,-17,-16,-13, -8, -3, 0, -+ }, -+ { // B=0.06667 C=0.46667 -+ 0, -3, -8,-13,-16,-17,-14, -6, 11, 41, 79,121,164,202,233,249,249,233,202,164,121, 79, 41, 11, -6,-14,-17,-16,-13, -8, -3, 0, -+ }, -+ { // B=0.06000 C=0.47000 -+ 0, -3, -8,-13,-16,-18,-14, -6, 11, 40, 79,121,164,203,233,250,250,233,203,164,121, 79, 40, 11, -6,-14,-18,-16,-13, -8, -3, 0, -+ }, -+ { // B=0.05333 C=0.47333 -+ 0, -3, -8,-13,-17,-18,-14, -6, 11, 40, 79,121,165,203,233,251,251,233,203,165,121, 79, 40, 11, -6,-14,-18,-17,-13, -8, -3, 0, -+ }, -+ { // B=0.04667 C=0.47667 -+ 0, -4, -8,-13,-17,-18,-14, -7, 11, 40, 79,121,166,203,234,251,251,234,203,166,121, 79, 40, 11, -7,-14,-18,-17,-13, -8, -4, 0, -+ }, -+ { // B=0.04000 C=0.48000 -+ 0, -4, -8,-13,-17,-18,-14, -7, 11, 40, 78,121,166,204,234,251,251,234,204,166,121, 78, 40, 11, -7,-14,-18,-17,-13, -8, -4, 0, -+ }, -+ { // B=0.03333 C=0.48333 -+ 0, -4, -8,-14,-17,-18,-15, -7, 11, 40, 78,122,164,204,235,252,252,235,204,164,122, 78, 40, 11, -7,-15,-18,-17,-14, -8, -4, 0, -+ }, -+ { // B=0.02667 C=0.48667 -+ 0, -4, -8,-14,-17,-19,-15, -7, 10, 40, 78,122,164,205,235,253,253,235,205,164,122, 78, 40, 10, -7,-15,-19,-17,-14, -8, -4, 0, -+ }, -+ { // B=0.02000 C=0.49000 -+ 0, -4, -8,-14,-17,-19,-15, -7, 10, 39, 78,122,164,205,236,253,253,236,205,164,122, 78, 39, 10, -7,-15,-19,-17,-14, -8, -4, 0, -+ }, -+ { // B=0.01333 C=0.49333 -+ 0, -4, -8,-14,-18,-19,-16, -7, 9, 40, 78,122,165,205,236,254,254,236,205,165,122, 78, 40, 9, -7,-16,-19,-18,-14, -8, -4, 0, -+ }, -+ { // B=0.00667 C=0.49667 -+ 0, -4, -9,-14,-18,-19,-15, -8, 10, 39, 78,122,166,206,236,254,254,236,206,166,122, 78, 39, 10, -8,-15,-19,-18,-14, -9, -4, 0, -+ }, -+ { // B=0.00000 C=0.50000 -+ 0, -4, -8,-14,-18,-19,-16, -8, 9, 39, 77,122,166,206,237,255,255,237,206,166,122, 77, 39, 9, -8,-16,-19,-18,-14, -8, -4, 0, -+ }, -+ }; -+ int index = (sharpness + 1.0f) * 50.0f + 0.5f; -+ if (index >=0 && index <= 100) -+ { -+ const int16_t *coef = mitchells[index]; -+ -+ char command[33*12]; -+ char response[33*12]; -+ unsigned int len = sprintf(command, "scaling_kernel "); -+ for (int i=0; i < 32; i++) { -+ if (len + 12 < sizeof command) -+ len += sprintf(command+len, "%d ", coef[i]); -+ } -+ // no interpolate flag -+ if (len + 12 < sizeof command) -+ len += sprintf(command+len, " %d", 0); -+ //printf("%i: %s\n", index, command); -+ vc_gencmd(response, sizeof response, command); -+ } -+} -+ - void COMXPlayer::Process() - { - bool bOmxWaitVideo = false; -@@ -1183,6 +1511,8 @@ void COMXPlayer::Process() - SetCaching(CACHESTATE_FLUSH); - - EDEINTERLACEMODE current_deinterlace = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ float current_sharpness = CMediaSettings::Get().GetCurrentVideoSettings().m_Sharpness; -+ SetSharpness(current_sharpness); - - while (!m_bAbortRequest) - { -@@ -1214,6 +1544,13 @@ void COMXPlayer::Process() - current_deinterlace = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; - } - -+ // if sharpness setting has changed, we should update it -+ if (current_sharpness != CMediaSettings::Get().GetCurrentVideoSettings().m_Sharpness) -+ { -+ current_sharpness = CMediaSettings::Get().GetCurrentVideoSettings().m_Sharpness; -+ SetSharpness(current_sharpness); -+ } -+ - m_video_fifo = (int)(100.0*(m_omxPlayerVideo.GetDecoderBufferSize()-m_omxPlayerVideo.GetDecoderFreeSpace())/m_omxPlayerVideo.GetDecoderBufferSize()); - m_audio_fifo = (int)(100.0*audio_fifo/m_omxPlayerAudio.GetCacheTotal()); - -@@ -4577,6 +4914,7 @@ void COMXPlayer::GetRenderFeatures(std::vector &renderFeatures) - renderFeatures.push_back(RENDERFEATURE_CROP); - renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO); - renderFeatures.push_back(RENDERFEATURE_ZOOM); -+ renderFeatures.push_back(RENDERFEATURE_SHARPNESS); - } - - void COMXPlayer::GetDeinterlaceMethods(std::vector &deinterlaceMethods) --- -1.9.3 - - -From 35048ec10fafe1316ca5937401b0f9eee4d92ccf Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 16 Apr 2014 21:18:06 +0100 -Subject: [PATCH 44/82] [omxplayer] Don't propagate 3d flags based on supported - 3d modes - ---- - xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 29 ++++------------------------- - 1 file changed, 4 insertions(+), 25 deletions(-) - -diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -index 2fdbe18..e6bf2d0 100644 ---- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -@@ -746,36 +746,15 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f - unsigned flags = 0; - ERenderFormat format = RENDER_FMT_BYPASS; - -+ /* figure out steremode expected based on user settings and hints */ -+ unsigned int stereo_flags = GetStereoModeFlags(GetStereoMode()); -+ - if(m_bAllowFullscreen) - { - flags |= CONF_FLAGS_FULLSCREEN; - m_bAllowFullscreen = false; // only allow on first configure - } -- -- flags |= GetStereoModeFlags(GetStereoMode()); -- -- if(flags & CONF_FLAGS_STEREO_MODE_SBS) -- { -- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS)) -- CLog::Log(LOGNOTICE, "3DSBS movie found"); -- else -- { -- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); -- CLog::Log(LOGNOTICE, "3DSBS movie found but not supported"); -- } -- } -- else if(flags & CONF_FLAGS_STEREO_MODE_TAB) -- { -- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB)) -- CLog::Log(LOGNOTICE, "3DTB movie found"); -- else -- { -- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); -- CLog::Log(LOGNOTICE, "3DTB movie found but not supported"); -- } -- } -- else -- CLog::Log(LOGNOTICE, "not a 3D movie"); -+ flags |= stereo_flags; - - unsigned int iDisplayWidth = width; - unsigned int iDisplayHeight = height; --- -1.9.3 - - -From 0f0e8c2566ecd3140c381a52cc0196fffccec9a8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 17 Apr 2014 13:00:52 +0100 -Subject: [PATCH 45/82] [graphics] Don't set stereo mode based on resolution - -The resolution change should follow stereo mode ---- - xbmc/guilib/GraphicContext.cpp | 22 ---------------------- - 1 file changed, 22 deletions(-) - -diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp -index 5bffdf5..7e4fdd4 100644 ---- a/xbmc/guilib/GraphicContext.cpp -+++ b/xbmc/guilib/GraphicContext.cpp -@@ -418,28 +418,6 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate) - Lock(); - - RESOLUTION_INFO info_org = CDisplaySettings::Get().GetResolutionInfo(res); -- RESOLUTION_INFO info_last = CDisplaySettings::Get().GetResolutionInfo(lastRes); -- -- RENDER_STEREO_MODE stereo_mode = m_stereoMode; -- -- // if the new mode is an actual stereo mode, switch to that -- // if the old mode was an actual stereo mode, switch to no 3d mode -- if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DTB) -- stereo_mode = RENDER_STEREO_MODE_SPLIT_HORIZONTAL; -- else if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DSBS) -- stereo_mode = RENDER_STEREO_MODE_SPLIT_VERTICAL; -- else if ((info_last.dwFlags & D3DPRESENTFLAG_MODE3DSBS) != 0 -- || (info_last.dwFlags & D3DPRESENTFLAG_MODE3DTB) != 0) -- stereo_mode = RENDER_STEREO_MODE_OFF; -- -- if(stereo_mode != m_stereoMode) -- { -- m_stereoView = RENDER_STEREO_VIEW_OFF; -- m_stereoMode = stereo_mode; -- m_nextStereoMode = stereo_mode; -- CSettings::Get().SetInt("videoscreen.stereoscopicmode", (int)m_stereoMode); -- } -- - RESOLUTION_INFO info_mod = GetResInfo(res); - - m_iScreenWidth = info_mod.iWidth; --- -1.9.3 - - -From b9f95119543d59f7d3b0f80696215d0c66d4fe91 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 17 Apr 2014 13:01:51 +0100 -Subject: [PATCH 46/82] [graphics] Allow switching to a more suitable 3D - resolution - ---- - xbmc/guilib/GraphicContext.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- - xbmc/guilib/GraphicContext.h | 1 + - 2 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp -index 7e4fdd4..886b612 100644 ---- a/xbmc/guilib/GraphicContext.cpp -+++ b/xbmc/guilib/GraphicContext.cpp -@@ -35,6 +35,7 @@ - #include "utils/JobManager.h" - #include "video/VideoReferenceClock.h" - #include "cores/IPlayer.h" -+#include - - using namespace std; - -@@ -459,6 +460,44 @@ RESOLUTION CGraphicContext::GetVideoResolution() const - return m_Resolution; - } - -+RESOLUTION CGraphicContext::Get3DVideoResolution(RENDER_STEREO_MODE mode) const -+{ -+ RESOLUTION best = m_Resolution; -+ RESOLUTION_INFO curr = CDisplaySettings::Get().GetResolutionInfo(best); -+ -+ // Find closest refresh rate -+ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) -+ { -+ const RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo((RESOLUTION)i); -+ -+ //discard resolutions that are not the same width and height (and interlaced/3D flags) -+ //or have a too low refreshrate -+ if (info.iScreenWidth != curr.iScreenWidth -+ || info.iScreenHeight != curr.iScreenHeight -+ || info.iScreen != curr.iScreen -+ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED) -+ || fabs(info.fRefreshRate - curr.fRefreshRate) >= FLT_EPSILON) -+ continue; -+ -+ if (mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) -+ { -+ best = (RESOLUTION)i; -+ break; -+ } -+ else if (mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && info.dwFlags & D3DPRESENTFLAG_MODE3DTB) -+ { -+ best = (RESOLUTION)i; -+ break; -+ } -+ else if ((mode == RENDER_STEREO_MODE_OFF || mode == RENDER_STEREO_MODE_MONO) && !(info.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))) -+ { -+ best = (RESOLUTION)i; -+ break; -+ } -+ } -+ return best; -+} -+ - void CGraphicContext::ResetOverscan(RESOLUTION_INFO &res) - { - res.Overscan.left = 0; -@@ -996,7 +1035,7 @@ void CGraphicContext::Flip(const CDirtyRegionList& dirty) - if(m_stereoMode != m_nextStereoMode) - { - m_stereoMode = m_nextStereoMode; -- SetVideoResolution(GetVideoResolution(), true); -+ SetVideoResolution(Get3DVideoResolution(m_stereoMode), true); - g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET); - } - } -diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h -index 0a27643..df55e92 100644 ---- a/xbmc/guilib/GraphicContext.h -+++ b/xbmc/guilib/GraphicContext.h -@@ -108,6 +108,7 @@ class CGraphicContext : public CCriticalSection, - bool IsValidResolution(RESOLUTION res); - void SetVideoResolution(RESOLUTION res, bool forceUpdate = false); - RESOLUTION GetVideoResolution() const; -+ RESOLUTION Get3DVideoResolution(RENDER_STEREO_MODE mode) const; - void ResetOverscan(RESOLUTION res, OVERSCAN &overscan); - void ResetOverscan(RESOLUTION_INFO &resinfo); - void ResetScreenParameters(RESOLUTION res); --- -1.9.3 - - -From 17042a6427baa1152d593b23edf0340127390529 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 17 Apr 2014 13:38:55 +0100 -Subject: [PATCH 47/82] [3D] Support switching to 3D resolutions - -Include matching 3D flags (SBS/TAB) in the score of a resolution to switch to, to enable switching to 3d modes. -Also remove the old code that treated 3D modes differently when assigning a score. ---- - xbmc/cores/VideoRenderers/BaseRenderer.cpp | 47 +++++++++++------------------- - 1 file changed, 17 insertions(+), 30 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp -index 83c3adb..8076e76 100644 ---- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp -@@ -222,10 +222,14 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) - RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight) - { - RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current); -+ RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode(); - - float fRefreshRate = fps; - -- float last_diff = fRefreshRate; -+ int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); -+ if (!(stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) || -+ !(stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DTB)) -+ c_weight += 1000; - - // Find closest refresh rate - for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) -@@ -241,40 +245,23 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES - || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) - continue; - -- // For 3D choose the closest refresh rate -- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) -- { -- float diff = (info.fRefreshRate - fRefreshRate); -- if(diff < 0) -- diff *= -1.0f; -+ int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); - -- if(diff < last_diff) -- { -- last_diff = diff; -- current = (RESOLUTION)i; -- curr = info; -- } -- } -- else -- { -- int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); -- int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); -+ if (!(stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) || -+ !(stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DTB)) -+ i_weight += 1000; - -- // Closer the better, prefer higher refresh rate if the same -- if ((i_weight < c_weight) -- || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) -- { -- current = (RESOLUTION)i; -- curr = info; -- } -+ // Closer the better, prefer higher refresh rate if the same -+ if ((i_weight < c_weight) -+ || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) -+ { -+ current = (RESOLUTION)i; -+ curr = info; -+ c_weight = i_weight; - } - } - -- // For 3D overwrite weight -- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) -- weight = 0; -- else -- weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); -+ weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); - - return current; - } --- -1.9.3 - - -From 52e2bf4a422d1210622f69b411ff69f585d7d1de Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 23 Apr 2014 00:05:07 +0100 -Subject: [PATCH 48/82] [graphics] Make pixel ratio for 3d modes consistent - -Note: Use the stored stereo flags from lists of resolutions. -Use current stereo mode for current resolution. ---- - xbmc/cores/VideoRenderers/BaseRenderer.cpp | 10 ++++---- - xbmc/guilib/GraphicContext.cpp | 32 ++++++++++--------------- - xbmc/guilib/GraphicContext.h | 4 ++-- - xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 8 ------- - 4 files changed, 19 insertions(+), 35 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp -index 8076e76..beda4e9 100644 ---- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp -@@ -119,7 +119,7 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa - - for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++) - { -- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j); -+ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j, false); - - if (info.iScreenWidth == curr.iScreenWidth - && info.iScreenHeight == curr.iScreenHeight -@@ -179,7 +179,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) - //get the resolution with the refreshrate closest to 60 hertz - for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) - { -- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); -+ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, false); - - if (MathUtils::round_int(info.fRefreshRate) == 60 - && info.iScreenWidth == curr.iScreenWidth -@@ -200,7 +200,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) - CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest"); - for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) - { -- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); -+ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, false); - - if (info.fRefreshRate > curr.fRefreshRate - && info.iScreenWidth == curr.iScreenWidth -@@ -234,14 +234,14 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES - // Find closest refresh rate - for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) - { -- const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); -+ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, false); - - //discard resolutions that are not the same width and height (and interlaced/3D flags) - //or have a too low refreshrate - if (info.iScreenWidth != curr.iScreenWidth - || info.iScreenHeight != curr.iScreenHeight - || info.iScreen != curr.iScreen -- || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK) -+ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED) - || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) - continue; - -diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp -index 886b612..40a6362 100644 ---- a/xbmc/guilib/GraphicContext.cpp -+++ b/xbmc/guilib/GraphicContext.cpp -@@ -707,32 +707,26 @@ void CGraphicContext::ApplyStateBlock() - g_Windowing.ApplyStateBlock(); - } - --const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const -+const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res, bool use_current_3d /*= true*/) const - { - RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res); - -- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) -+ if(use_current_3d ? m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL : (info.dwFlags & D3DPRESENTFLAG_MODE3DTB)) - { -- if((info.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) -- { -- info.fPixelRatio /= 2; -- info.iBlanking = 0; -- info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; -- } -+ info.fPixelRatio /= 2; -+ info.iBlanking = 0; -+ info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; - info.iHeight = (info.iHeight - info.iBlanking) / 2; - info.Overscan.top /= 2; - info.Overscan.bottom = (info.Overscan.bottom - info.iBlanking) / 2; - info.iSubtitles = (info.iSubtitles - info.iBlanking) / 2; - } - -- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) -+ if(use_current_3d ? m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL : (info.dwFlags & D3DPRESENTFLAG_MODE3DSBS)) - { -- if((info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) -- { -- info.fPixelRatio *= 2; -- info.iBlanking = 0; -- info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; -- } -+ info.fPixelRatio *= 2; -+ info.iBlanking = 0; -+ info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; - info.iWidth = (info.iWidth - info.iBlanking) / 2; - info.Overscan.left /= 2; - info.Overscan.right = (info.Overscan.right - info.iBlanking) / 2; -@@ -740,7 +734,7 @@ const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const - return info; - } - --void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info) -+void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info, bool use_current_3d /*= true*/) - { - RESOLUTION_INFO& curr = CDisplaySettings::Get().GetResolutionInfo(res); - curr.Overscan = info.Overscan; -@@ -750,16 +744,14 @@ void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info) - if(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) - { - curr.Overscan.right = info.Overscan.right * 2 + info.iBlanking; -- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) -- curr.fPixelRatio /= 2.0; -+ curr.fPixelRatio /= 2.0; - } - - if(info.dwFlags & D3DPRESENTFLAG_MODE3DTB) - { - curr.Overscan.bottom = info.Overscan.bottom * 2 + info.iBlanking; - curr.iSubtitles = info.iSubtitles * 2 + info.iBlanking; -- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) -- curr.fPixelRatio *= 2.0; -+ curr.fPixelRatio *= 2.0; - } - } - -diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h -index df55e92..c77f2ff 100644 ---- a/xbmc/guilib/GraphicContext.h -+++ b/xbmc/guilib/GraphicContext.h -@@ -124,8 +124,8 @@ class CGraphicContext : public CCriticalSection, - { - return GetResInfo(m_Resolution); - } -- const RESOLUTION_INFO GetResInfo(RESOLUTION res) const; -- void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info); -+ const RESOLUTION_INFO GetResInfo(RESOLUTION res, bool use_current_3d = true) const; -+ void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info, bool use_current_3d = true); - - /* \brief Get UI scaling information from a given resolution to the screen resolution. - Takes account of overscan and UI zooming. -diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -index 90b57e1..5b26b20 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -@@ -448,15 +448,9 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r - m_desktopRes.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); - // Also add 3D flags - if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) -- { - m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; -- m_desktopRes.fPixelRatio *= 2.0; -- } - else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF) -- { - m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB; -- m_desktopRes.fPixelRatio *= 0.5; -- } - HDMI_PROPERTY_PARAM_T property; - property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; - vc_tv_hdmi_get_property(&property); -@@ -602,7 +596,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v - RESOLUTION_INFO res2 = res; - res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; - res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); -- res2.fPixelRatio *= 2.0f; - CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio); - - res2.iSubtitles = (int)(0.965 * res2.iHeight); -@@ -619,7 +612,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v - RESOLUTION_INFO res2 = res; - res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB; - res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); -- res2.fPixelRatio *= 0.5f; - CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio); - - res2.iSubtitles = (int)(0.965 * res2.iHeight); --- -1.9.3 - - -From cacb2609b8e021320d4c5bb949da71ec6a8ad726 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 23 Apr 2014 21:07:51 +0100 -Subject: [PATCH 49/82] [PiSink] More attempts to reduce underrun audio - glitches with multichannl and high samplerate - ---- - xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 73 ++++++++++++------------------- - 1 file changed, 27 insertions(+), 46 deletions(-) - -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -index 811ea0d..7c04919 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -@@ -186,7 +186,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) - unsigned int sample_size = CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3; - format.m_frameSize = sample_size * channels; - format.m_sampleRate = std::max(8000U, std::min(192000U, format.m_sampleRate)); -- format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER; -+ format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; - format.m_frameSamples = format.m_frames * channels; - - SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough)); -@@ -232,7 +232,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) - CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)NUM_OMX_BUFFERS); -- port_param.nBufferSize = m_format.m_frameSize * m_format.m_frames / port_param.nBufferCountActual; -+ port_param.nBufferSize = m_format.m_frameSize * m_format.m_frames; - - omx_err = m_omx_render.SetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) -@@ -308,59 +308,40 @@ double CAESinkPi::GetCacheTotal() - - unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) - { -- unsigned int sent = 0; - uint8_t *buffer = data[0]+offset*m_format.m_frameSize; - -- if (!m_Initialized) -+ if (!m_Initialized || !frames) - return frames; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_BUFFERHEADERTYPE *omx_buffer = NULL; -- while (sent < frames) -+ -+ double delay = GetDelay(); -+ if (delay <= 0.0 && m_submitted) -+ CLog::Log(LOGNOTICE, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames); -+ -+ omx_buffer = m_omx_render.GetInputBuffer(1000); -+ if (omx_buffer == NULL) - { -- double delay = GetDelay(); -- double ideal_submission_time = AUDIO_PLAYBUFFER - delay; -- // ideal amount of audio we'd like submit (to make delay match AUDIO_PLAYBUFFER) -- int timeout = 1000; -- int ideal_submission_samples = ideal_submission_time / (m_sinkbuffer_sec_per_byte * m_format.m_frameSize); -- // if we are almost full then sleep (to avoid repeatedly sending a few samples) -- bool too_laggy = ideal_submission_time < 0.25 * AUDIO_PLAYBUFFER; -- int sleeptime = (int)(AUDIO_PLAYBUFFER * 0.25 * 1000.0); -- if (too_laggy) -- { -- Sleep(sleeptime); -- continue; -- } -- omx_buffer = m_omx_render.GetInputBuffer(timeout); -- if (omx_buffer == NULL) -- { -- CLog::Log(LOGERROR, "COMXAudio::Decode timeout"); -- break; -- } -- -- unsigned int space = omx_buffer->nAllocLen / m_format.m_frameSize; -- unsigned int samples = std::min(std::min(space, (unsigned int)ideal_submission_samples), frames - sent); -- -- omx_buffer->nFilledLen = samples * m_format.m_frameSize; -- omx_buffer->nTimeStamp = ToOMXTime(0); -- omx_buffer->nFlags = 0; -- memcpy(omx_buffer->pBuffer, (uint8_t *)buffer + sent * m_format.m_frameSize, omx_buffer->nFilledLen); -- -- sent += samples; -- -- if (sent == frames) -- omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; -- -- if (delay <= 0.0 && m_submitted) -- CLog::Log(LOGNOTICE, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames); -- -- omx_err = m_omx_render.EmptyThisBuffer(omx_buffer); -- if (omx_err != OMX_ErrorNone) -- CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err); -- m_submitted++; -+ CLog::Log(LOGERROR, "CAESinkPi::AddPackets timeout"); -+ return 0; - } - -- return sent; -+ omx_buffer->nFilledLen = frames * m_format.m_frameSize; -+ // must be true -+ assert(omx_buffer->nFilledLen <= omx_buffer->nAllocLen); -+ omx_buffer->nTimeStamp = ToOMXTime(0); -+ omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; -+ memcpy(omx_buffer->pBuffer, buffer, omx_buffer->nFilledLen); -+ -+ omx_err = m_omx_render.EmptyThisBuffer(omx_buffer); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err); -+ m_submitted++; -+ delay = GetDelay(); -+ if (delay > AUDIO_PLAYBUFFER) -+ Sleep((int)(1000.0f * (delay - AUDIO_PLAYBUFFER))); -+ return frames; - } - - void CAESinkPi::Drain() --- -1.9.3 - - -From 6b5217b28809feb2c8edce446c6a8ba129938bb1 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 22 Apr 2014 12:23:23 +0100 -Subject: [PATCH 50/82] [omxplayer] Make dvdplayer the default for dvd images - ---- - xbmc/cores/omxplayer/omxplayer_advancedsettings.xml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml b/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml -index 77c6a15..51c0daf 100644 ---- a/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml -+++ b/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml -@@ -2,6 +2,6 @@ - - - --- -1.9.3 - - -From eeafafa8332a89f51aea392c9721d6b889074bd3 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 26 Apr 2014 17:27:52 +0100 -Subject: [PATCH 51/82] [cec] Don't suspend pi on tv switch off - it can't wake - up - ---- - system/peripherals.xml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/system/peripherals.xml b/system/peripherals.xml -index a906628..9b5271a 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -16,7 +16,7 @@ - - - -- -+ - - - --- -1.9.3 - - -From f9e7b3b8bbc34c23b8379c248ea14842c1b11570 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 27 Jun 2013 01:25:57 +0100 -Subject: [PATCH 53/82] [rbp/omxplayer] Do we need discontinuity handling? - -So far I've not seen what this is needed for and it does cause problems for some files. ---- - xbmc/cores/omxplayer/OMXPlayer.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp -index 12e887e..a811169 100644 ---- a/xbmc/cores/omxplayer/OMXPlayer.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayer.cpp -@@ -2395,6 +2395,7 @@ static void UpdateLimits(double& minimum, double& maximum, double dts) - - void COMXPlayer::CheckContinuity(COMXCurrentStream& current, DemuxPacket* pPacket) - { -+return; - if (m_playSpeed < DVD_PLAYSPEED_PAUSE) - return; - --- -1.9.3 - - -From 2d38d635a6c27c8c2bdffc7ce24e7d511e2c7c18 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Thu, 24 Oct 2013 00:53:26 +0100 -Subject: [PATCH 54/82] [rbp/omxplayer] Avoid marking non-monotonic timestamps - as unknown - -Following a single spurious timestamp that is in the future, -all subsequent timestamps will be marked unknown causing out of sync. ---- - xbmc/cores/omxplayer/OMXAudio.cpp | 16 ++-------------- - 1 file changed, 2 insertions(+), 14 deletions(-) - -diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp -index 77731a9..5f9d028 100644 ---- a/xbmc/cores/omxplayer/OMXAudio.cpp -+++ b/xbmc/cores/omxplayer/OMXAudio.cpp -@@ -1210,22 +1210,10 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt - } - else - { -- if(pts == DVD_NOPTS_VALUE) -- { -+ if(pts == DVD_NOPTS_VALUE || pts == m_last_pts) - omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; -+ else - m_last_pts = pts; -- } -- else if (m_last_pts != pts) -- { -- if(pts > m_last_pts) -- m_last_pts = pts; -- else -- omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;; -- } -- else if (m_last_pts == pts) -- { -- omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; -- } - } - - omx_buffer->nTimeStamp = ToOMXTime(val); --- -1.9.3 - - -From 8080b6e1199e3fb90e4ff2115831b706a50403a5 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 13 Dec 2013 16:25:23 +0000 -Subject: [PATCH 56/82] Add time taken to resample to log - ---- - xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 7 +++++++ - xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h | 2 +- - 2 files changed, 8 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -index 2f71051..ce74b9d 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -@@ -2586,7 +2586,14 @@ void CActiveAE::ResampleSounds() - { - if (!(*it)->IsConverted()) - { -+ struct timespec now; -+ clock_gettime(CLOCK_MONOTONIC, &now); -+ uint64_t Start = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; -+ - ResampleSound(*it); -+ clock_gettime(CLOCK_MONOTONIC, &now); -+ uint64_t End = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; -+ CLog::Log(LOGNOTICE, "ActiveAE::%s - resample %s took %.0fms", __FUNCTION__, (*it)->m_filename.c_str(), (End-Start)*1e-6); - // only do one sound, then yield to main loop - break; - } -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h -index 9324e1e..4405f66 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h -@@ -58,8 +58,8 @@ class CActiveAESound : public IAESound - static int Read(void *h, uint8_t* buf, int size); - static int64_t Seek(void *h, int64_t pos, int whence); - --protected: - std::string m_filename; -+protected: - XFILE::CFile *m_pFile; - bool m_isSeekPosible; - int m_fileSize; --- -1.9.3 - - -From 0d756bfa2225ef9e050cfd4c048ff73506893a1b Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 14 Dec 2013 16:55:05 +0000 -Subject: [PATCH 57/82] logging: Add microsecond timer to log messages - ---- - xbmc/utils/log.cpp | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp -index 6d7c6c8..45f68bc 100644 ---- a/xbmc/utils/log.cpp -+++ b/xbmc/utils/log.cpp -@@ -32,6 +32,7 @@ - #elif defined(TARGET_WINDOWS) - #include "win32/WIN32Util.h" - #endif -+#include "utils/TimeUtils.cpp" - - #define critSec XBMC_GLOBAL_USE(CLog::CLogGlobals).critSec - #define m_file XBMC_GLOBAL_USE(CLog::CLogGlobals).m_file -@@ -64,7 +65,7 @@ void CLog::Close() - - void CLog::Log(int loglevel, const char *format, ... ) - { -- static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%"PRIu64" %7s: "; -+ static const char* prefixFormat = "%02.2d:%02.2d:%02.2d %10.6f T:%"PRIu64" %7s: "; - CSingleLock waitLock(critSec); - int extras = (loglevel >> LOGMASKBIT) << LOGMASKBIT; - loglevel = loglevel & LOGMASK; -@@ -90,6 +91,11 @@ void CLog::Log(int loglevel, const char *format, ... ) - strData = StringUtils::FormatV(format,va); - va_end(va); - -+ -+ struct timespec now; -+ clock_gettime(CLOCK_MONOTONIC, &now); -+ float Now = now.tv_sec + now.tv_nsec * 1e-9; -+ - if (m_repeatLogLevel == loglevel && m_repeatLine == strData) - { - m_repeatCount++; -@@ -100,7 +106,7 @@ void CLog::Log(int loglevel, const char *format, ... ) - strPrefix = StringUtils::Format(prefixFormat, - time.wHour, - time.wMinute, -- time.wSecond, -+ time.wSecond, Now, - (uint64_t)CThread::GetCurrentThreadId(), - levelNames[m_repeatLogLevel]); - -@@ -129,7 +135,7 @@ void CLog::Log(int loglevel, const char *format, ... ) - strPrefix = StringUtils::Format(prefixFormat, - time.wHour, - time.wMinute, -- time.wSecond, -+ time.wSecond, Now, - (uint64_t)CThread::GetCurrentThreadId(), - levelNames[loglevel]); - --- -1.9.3 - - -From ffeee013ca4f3e7476247e06765cb69bd2150ebf Mon Sep 17 00:00:00 2001 -From: Jonathan Marshall -Date: Sat, 2 Nov 2013 23:49:17 +1300 -Subject: [PATCH 58/82] adds GetTvShowSeasons - ---- - xbmc/video/VideoDatabase.cpp | 30 ++++++++++++++++++++++++------ - xbmc/video/VideoDatabase.h | 1 + - 2 files changed, 25 insertions(+), 6 deletions(-) - -diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp -index 927e8ff..b759970 100644 ---- a/xbmc/video/VideoDatabase.cpp -+++ b/xbmc/video/VideoDatabase.cpp -@@ -4031,7 +4031,7 @@ bool CVideoDatabase::RemoveArtForItem(int mediaId, const MediaType &mediaType, c - return result; - } - --bool CVideoDatabase::GetTvShowSeasonArt(int showId, map > &seasonArt) -+bool CVideoDatabase::GetTvShowSeasons(int showId, map &seasons) - { - try - { -@@ -4042,19 +4042,37 @@ bool CVideoDatabase::GetTvShowSeasonArt(int showId, map - CStdString sql = PrepareSQL("select idSeason,season from seasons where idShow=%i", showId); - m_pDS2->query(sql.c_str()); - -- vector< pair > seasons; -+ seasons.clear(); - while (!m_pDS2->eof()) - { -- seasons.push_back(make_pair(m_pDS2->fv(0).get_asInt(), m_pDS2->fv(1).get_asInt())); -+ seasons.insert(make_pair(m_pDS2->fv(1).get_asInt(), m_pDS2->fv(0).get_asInt())); - m_pDS2->next(); - } - m_pDS2->close(); -+ return true; -+ } -+ catch (...) -+ { -+ CLog::Log(LOGERROR, "%s(%d) failed", __FUNCTION__, showId); -+ } -+ return false; -+} -+ -+bool CVideoDatabase::GetTvShowSeasonArt(int showId, map > &seasonArt) -+{ -+ try -+ { -+ if (NULL == m_pDB.get()) return false; -+ if (NULL == m_pDS2.get()) return false; // using dataset 2 as we're likely called in loops on dataset 1 -+ -+ map seasons; -+ GetTvShowSeasons(showId, seasons); - -- for (vector< pair >::const_iterator i = seasons.begin(); i != seasons.end(); ++i) -+ for (map::const_iterator i = seasons.begin(); i != seasons.end(); ++i) - { - map art; -- GetArtForItem(i->first, MediaTypeSeason, art); -- seasonArt.insert(make_pair(i->second,art)); -+ GetArtForItem(i->second, MediaTypeSeason, art); -+ seasonArt.insert(make_pair(i->first,art)); - } - return true; - } -diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h -index 7bf6d85..80334c6 100644 ---- a/xbmc/video/VideoDatabase.h -+++ b/xbmc/video/VideoDatabase.h -@@ -720,6 +720,7 @@ class CVideoDatabase : public CDatabase - std::string GetArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType); - bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType); - bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::set &artTypes); -+ bool GetTvShowSeasons(int showId, std::map &seasons); - bool GetTvShowSeasonArt(int mediaId, std::map > &seasonArt); - bool GetArtTypes(const MediaType &mediaType, std::vector &artTypes); - --- -1.9.3 - - -From 9460558427955f172fd4476db0f8ab49ef8bd8c8 Mon Sep 17 00:00:00 2001 -From: Jonathan Marshall -Date: Sat, 2 Nov 2013 23:50:10 +1300 -Subject: [PATCH 59/82] move AddSeason() public. - ---- - xbmc/video/VideoDatabase.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h -index 80334c6..a519620 100644 ---- a/xbmc/video/VideoDatabase.h -+++ b/xbmc/video/VideoDatabase.h -@@ -731,6 +731,7 @@ class CVideoDatabase : public CDatabase - - virtual bool GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription &sorting); - -+ int AddSeason(int showID, int season); - int AddSet(const CStdString& strSet); - void ClearMovieSet(int idMovie); - void SetMovieSet(int idMovie, int idSet); -@@ -761,7 +762,6 @@ class CVideoDatabase : public CDatabase - - int AddTvShow(const CStdString& strPath); - int AddMusicVideo(const CStdString& strFilenameAndPath); -- int AddSeason(int showID, int season); - - // link functions - these two do all the work - void AddLinkToActor(const char *table, int actorID, const char *secondField, int secondID, const CStdString &role, int order); --- -1.9.3 - - -From f2b89ac91ae42e69619d19596248e12e987c1842 Mon Sep 17 00:00:00 2001 -From: Jonathan Marshall -Date: Sat, 2 Nov 2013 23:48:24 +1300 -Subject: [PATCH 60/82] adds GetArt function to (video) scraper, allowing art - to be fetched given the video identifier. - ---- - xbmc/addons/Scraper.cpp | 38 ++++++++++++++++++++++++++++++++++++++ - xbmc/addons/Scraper.h | 3 +++ - xbmc/video/VideoInfoDownloader.cpp | 5 +++++ - xbmc/video/VideoInfoDownloader.h | 7 +++++++ - 4 files changed, 53 insertions(+) - -diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp -index 44f6693..a67b243 100644 ---- a/xbmc/addons/Scraper.cpp -+++ b/xbmc/addons/Scraper.cpp -@@ -925,6 +925,44 @@ EPISODELIST CScraper::GetEpisodeList(XFILE::CCurlFile &fcurl, const CScraperUrl - return vcep; - } - -+// takes URL; returns true and populates art XML details on success, false otherwise -+bool CScraper::GetArt(XFILE::CCurlFile &fcurl, const std::string &id, CVideoInfoTag &video) -+{ -+ CLog::Log(LOGDEBUG, "%s: Reading art for '%s' using %s scraper " -+ "(file: '%s', content: '%s', version: '%s')", __FUNCTION__, id.c_str(), Name().c_str(), Path().c_str(), -+ ADDON::TranslateContent(Content()).c_str(), Version().asString().c_str()); -+ -+ video.Reset(); -+ vector vcsIn; -+ CScraperUrl scurl; -+ vcsIn.push_back(id); -+ vector vcsOut = RunNoThrow("GetArt", scurl, fcurl, &vcsIn); -+ -+ // parse XML output -+ bool fRet(false); -+ for (CStdStringArray::const_iterator i = vcsOut.begin(); i != vcsOut.end(); ++i) -+ { -+ CXBMCTinyXML doc; -+ doc.Parse(*i, TIXML_ENCODING_UTF8); -+ if (!doc.RootElement()) -+ { -+ CLog::Log(LOGERROR, "%s: Unable to parse XML", __FUNCTION__); -+ continue; -+ } -+ -+ TiXmlHandle xhDoc(&doc); -+ TiXmlElement *pxeDetails = xhDoc.FirstChild("details").Element(); -+ if (!pxeDetails) -+ { -+ CLog::Log(LOGERROR, "%s: Invalid XML file (want
)", __FUNCTION__); -+ continue; -+ } -+ video.Load(pxeDetails, true/*fChain*/); -+ fRet = true; // but don't exit in case of chaining -+ } -+ return fRet; -+} -+ - // takes URL; returns true and populates video details on success, false otherwise - bool CScraper::GetVideoDetails(XFILE::CCurlFile &fcurl, const CScraperUrl &scurl, - bool fMovie/*else episode*/, CVideoInfoTag &video) -diff --git a/xbmc/addons/Scraper.h b/xbmc/addons/Scraper.h -index 40a90e5..b7e431c 100644 ---- a/xbmc/addons/Scraper.h -+++ b/xbmc/addons/Scraper.h -@@ -18,6 +18,8 @@ - * . - * - */ -+ -+#include - #include "addons/Addon.h" - #include "XBDateTime.h" - #include "utils/ScraperUrl.h" -@@ -146,6 +148,7 @@ class CScraper : public CAddon - CAlbum &album); - bool GetArtistDetails(XFILE::CCurlFile &fcurl, const CScraperUrl &scurl, - const CStdString &sSearch, CArtist &artist); -+ bool GetArt(XFILE::CCurlFile &fcurl, const std::string &id, CVideoInfoTag &video); - - private: - CScraper(const CScraper &rhs); -diff --git a/xbmc/video/VideoInfoDownloader.cpp b/xbmc/video/VideoInfoDownloader.cpp -index f33ac8a..5d84734 100644 ---- a/xbmc/video/VideoInfoDownloader.cpp -+++ b/xbmc/video/VideoInfoDownloader.cpp -@@ -191,6 +191,11 @@ bool CVideoInfoDownloader::GetDetails(const CScraperUrl &url, - return m_info->GetVideoDetails(*m_http, url, true/*fMovie*/, movieDetails); - } - -+bool CVideoInfoDownloader::GetArt(const std::string &id, CVideoInfoTag &details) -+{ -+ return m_info->GetArt(*m_http, id, details); -+} -+ - bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url, - CVideoInfoTag &movieDetails, - CGUIDialogProgress *pProgress /* = NULL */) -diff --git a/xbmc/video/VideoInfoDownloader.h b/xbmc/video/VideoInfoDownloader.h -index 22ac229..75bc341 100644 ---- a/xbmc/video/VideoInfoDownloader.h -+++ b/xbmc/video/VideoInfoDownloader.h -@@ -59,6 +59,13 @@ class CVideoInfoDownloader : public CThread - - static void ShowErrorDialog(const ADDON::CScraperError &sce); - -+ /*! \brief Grab art URLs for an item with the scraper -+ \param id the unique identifier used by the scraper to describe the item. -+ \param details [out] the video info tag structure to fill with art. -+ \return true on success, false on failure. -+ */ -+ bool GetArt(const std::string &id, CVideoInfoTag &details); -+ - protected: - enum LOOKUP_STATE { DO_NOTHING = 0, - FIND_MOVIE = 1, --- -1.9.3 - - -From 911317ea7f8d20a8960fe7d651eaea451525c690 Mon Sep 17 00:00:00 2001 -From: Jonathan Marshall -Date: Sat, 2 Nov 2013 23:53:14 +1300 -Subject: [PATCH 61/82] refresh season art if a new season is found that isn't - recorded in the database yet. Fixes #14339 - ---- - xbmc/video/VideoInfoScanner.cpp | 33 ++++++++++++++++++++++++++++++++- - xbmc/video/VideoInfoScanner.h | 2 ++ - 2 files changed, 34 insertions(+), 1 deletion(-) - -diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp -index 3f1d2e8..bc4d47c 100644 ---- a/xbmc/video/VideoInfoScanner.cpp -+++ b/xbmc/video/VideoInfoScanner.cpp -@@ -1342,6 +1342,10 @@ namespace VIDEO - pDlgProgress->Progress(); - } - -+ bool updateSeasons = false; -+ map seasons; -+ m_database.GetTvShowSeasons(showInfo.m_iDbId, seasons); -+ - EPISODELIST episodes; - bool hasEpisodeGuide = false; - -@@ -1390,6 +1394,8 @@ namespace VIDEO - } - if (AddVideo(&item, CONTENT_TVSHOWS, file->isFolder, true, &showInfo) < 0) - return INFO_ERROR; -+ if (seasons.find(item.GetVideoInfoTag()->m_iSeason) == seasons.end()) -+ updateSeasons = true; - continue; - } - -@@ -1519,6 +1525,8 @@ namespace VIDEO - - if (AddVideo(&item, CONTENT_TVSHOWS, file->isFolder, useLocal, &showInfo) < 0) - return INFO_ERROR; -+ if (seasons.find(item.GetVideoInfoTag()->m_iSeason) == seasons.end()) -+ updateSeasons = true; - } - else - { -@@ -1527,9 +1535,27 @@ namespace VIDEO - file->cDate.GetAsLocalizedDate().c_str(), file->strTitle.c_str()); - } - } -+ if (updateSeasons) -+ UpdateSeasons(showInfo, scraper, useLocal); - return INFO_ADDED; - } - -+ void CVideoInfoScanner::UpdateSeasons(const CVideoInfoTag &showInfo, const ADDON::ScraperPtr &scraper, bool useLocal) -+ { -+ map > seasonArt; -+ m_database.GetTvShowSeasonArt(showInfo.m_iDbId, seasonArt); -+ CVideoInfoTag details; -+ CVideoInfoDownloader loader(scraper); -+ loader.GetArt(showInfo.m_strIMDBNumber, details); -+ details.m_strPath = showInfo.m_strPath; -+ GetSeasonThumbs(details, seasonArt, CVideoThumbLoader::GetArtTypes("season"), useLocal); -+ for (map >::iterator i = seasonArt.begin(); i != seasonArt.end(); ++i) -+ { -+ int seasonID = m_database.AddSeason(showInfo.m_iDbId, i->first); -+ m_database.SetArtForItem(seasonID, "season", i->second); -+ } -+ } -+ - CStdString CVideoInfoScanner::GetnfoFile(CFileItem *item, bool bGrabAny) const - { - CStdString nfoFile; -@@ -1798,6 +1824,11 @@ namespace VIDEO - } - for (int season = -1; season <= maxSeasons; season++) - { -+ // skip if we already have some art -+ map >::const_iterator i = seasonArt.find(season); -+ if (i != seasonArt.end() && !i->second.empty()) -+ continue; -+ - map art; - if (useLocal) - { -@@ -1851,7 +1882,7 @@ namespace VIDEO - art.insert(make_pair(artTypes.front(), image)); - } - -- seasonArt.insert(make_pair(season, art)); -+ seasonArt[season] = art; - } - } - -diff --git a/xbmc/video/VideoInfoScanner.h b/xbmc/video/VideoInfoScanner.h -index b7f657a..841309d 100644 ---- a/xbmc/video/VideoInfoScanner.h -+++ b/xbmc/video/VideoInfoScanner.h -@@ -228,6 +228,8 @@ namespace VIDEO - */ - INFO_RET OnProcessSeriesFolder(EPISODELIST& files, const ADDON::ScraperPtr &scraper, bool useLocal, const CVideoInfoTag& showInfo, CGUIDialogProgress* pDlgProgress = NULL); - -+ void UpdateSeasons(const CVideoInfoTag &showInfo, const ADDON::ScraperPtr &scraper, bool useLocal); -+ - bool EnumerateSeriesFolder(CFileItem* item, EPISODELIST& episodeList); - bool EnumerateEpisodeItem(const CFileItem *item, EPISODELIST& episodeList); - bool ProcessItemByVideoInfoTag(const CFileItem *item, EPISODELIST &episodeList); --- -1.9.3 - - -From cfa00408a9c8d09cbdbb27e9ee12a17ac327d3a7 Mon Sep 17 00:00:00 2001 -From: Jonathan Marshall -Date: Sat, 2 Nov 2013 23:53:34 +1300 -Subject: [PATCH 62/82] REMOVEME: updated thetvdb.com scraper to support art - updates - ---- - addons/metadata.tvdb.com/tvdb.xml | 59 +++++++++++++++++++++++++-------------- - 1 file changed, 38 insertions(+), 21 deletions(-) - -diff --git a/addons/metadata.tvdb.com/tvdb.xml b/addons/metadata.tvdb.com/tvdb.xml -index 39e604d..60a0e96 100644 ---- a/addons/metadata.tvdb.com/tvdb.xml -+++ b/addons/metadata.tvdb.com/tvdb.xml -@@ -99,57 +99,74 @@ - - <Actor>.*?<Image>([^<]*)</Image>.*?<Name>([^<]*)</Name>.*?<Role>([^<]*) - -- -+ -+ -+ -+ -+ .*/(.*).zip -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>series</BannerType>[^<]*<BannerType2>graphical</BannerType2>[^<]*<Language>$INFO[language]</Language> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>series</BannerType>[^<]*<BannerType2>graphical</BannerType2>[^<]*<Language>((?!$INFO[language])[a-z])*</Language> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>series</BannerType>[^<]*<BannerType2>text</BannerType2>[^<]*<Language>$INFO[language]</Language> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>series</BannerType>[^<]*<BannerType2>text</BannerType2>[^<]*<Language>((?!$INFO[language])[a-z])*</Language> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>series</BannerType>[^<]*<BannerType2>blank</BannerType2>[^<]*<Language></Language> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>season</BannerType>[^<]*<BannerType2>season</BannerType2>[^<]*<Language>$INFO[language]</Language>[^<]*[^S]*Season>([0-9]+)</Season> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>season</BannerType>[^<]*<BannerType2>season</BannerType2>[^<]*<Language>((?!$INFO[language])[a-z])*</Language>[^<]*[^S]*Season>([0-9]+)</Season> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>season</BannerType>[^<]*<BannerType2>seasonwide</BannerType2>[^<]*<Language>$INFO[language]</Language>[^<]*[^S]*Season>([0-9]+)</Season> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>season</BannerType>[^<]*<BannerType2>seasonwide</BannerType2>[^<]*<Language>((?!$INFO[language])[a-z])*</Language>[^<]*[^S]*Season>([0-9]+)</Season> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>poster</BannerType> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>poster</BannerType> - -- -- -+ -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>fanart</BannerType>[^<]*<BannerType2>([^<]*)</BannerType2>[^<]*<Colors>([^<]*)</Colors>[^<]*<Language>$INFO[language]</Language> - -- -+ - <BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>fanart</BannerType>[^<]*<BannerType2>([^<]*)</BannerType2>[^<]*<Colors>([^<]*)</Colors>[^<]*<Language>((?!$INFO[language])[a-z])*</Language> - - - -- -- .*/(.*).zip -- -- -- -- - - -- -+ - - - --- -1.9.3 - - -From 5d66491fd31e2ae838a8b59da165c8982273a2d3 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 22 Mar 2014 16:40:01 +0000 -Subject: [PATCH 63/82] Enable PYTHONOPTIMIZE for Pi - ---- - xbmc/interfaces/python/XBPython.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp -index 0d6dabc..c3fd0f1 100644 ---- a/xbmc/interfaces/python/XBPython.cpp -+++ b/xbmc/interfaces/python/XBPython.cpp -@@ -462,6 +462,10 @@ bool XBPython::InitializeEngine() - } - #endif - -+// Lets enable for Pi -+#if defined(TARGET_RASPBERRY_PI) -+ setenv("PYTHONOPTIMIZE", "1", 1); -+#endif - - // Darwin packs .pyo files, we need PYTHONOPTIMIZE on in order to load them. - #if defined(TARGET_DARWIN) --- -1.9.3 - - -From c23f5a8f3a9a6e7d28936b018d88434a8890d172 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 28 Apr 2014 18:07:45 +0100 -Subject: [PATCH 64/82] [rpi] Make ActiveAE thread higher priority to make - audio underrun less likely - ---- - xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -index ce74b9d..ddd9b62 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp -@@ -2144,6 +2144,12 @@ void CActiveAE::LoadSettings() - bool CActiveAE::Initialize() - { - Create(); -+ -+#ifdef TARGET_RASPBERRY_PI -+ /* audio normally won't consume full cpu, so let it have prio */ -+ SetPriority(GetPriority()+1); -+#endif -+ - Message *reply; - if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::INIT, - &reply, --- -1.9.3 - - -From 6e2092ce8cf8356a6584b1cb5442317dbd24f7d0 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 29 Apr 2014 15:23:22 +0100 -Subject: [PATCH 65/82] [ffmpeg] Speed up wtv index creation - -The index creation is O(N^2) with number of entries (typically thousands). -On a Pi this can take more than 60 seconds to execute for a recording of a few hours. - -By replacing with an O(N) loop, this takes virtually zero time ---- - tools/depends/target/ffmpeg/Makefile | 3 +- - .../ffmpeg_Speed_up_wtv_index_creation.patch | 47 ++++++++++++++++++++++ - 2 files changed, 49 insertions(+), 1 deletion(-) - create mode 100644 tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch - -diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile -index 51e1918..f514ae6 100644 ---- a/tools/depends/target/ffmpeg/Makefile -+++ b/tools/depends/target/ffmpeg/Makefile -@@ -1,6 +1,6 @@ - include ../../Makefile.include - include FFMPEG-VERSION --DEPS= ../../Makefile.include FFMPEG-VERSION Makefile -+DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch - - # set to "yes" to enable patching - # we don't apply patches until we move to a vanilla ffmpeg tarball -@@ -63,6 +63,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) - rm -rf $(PLATFORM); mkdir -p $(PLATFORM) - cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) - cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig\npkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure -+ cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch - cd $(PLATFORM);\ - CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ - ./configure $(ffmpg_config) -diff --git a/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch -new file mode 100644 -index 0000000..8f5f989 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch -@@ -0,0 +1,47 @@ -+commit 0e7427498cb1131671f6fe9d054245ae7e5a36f5 -+Author: popcornmix -+Date: Tue Mar 25 19:43:07 2014 +0000 -+ -+ [ffmpeg] Speed up wtv index creation -+ -+ The index creation is O(N^2) with number of entries (typically thousands). -+ On a Pi this can take more than 60 seconds to execute for a recording of a few hours. -+ -+ By replacing with an O(N) loop, this takes virtually zero time -+ -+diff --git a/lib/ffmpeg/libavformat/wtvdec.c b/lib/ffmpeg/libavformat/wtvdec.c -+index e423370..70898bd 100644 -+--- a/lib/ffmpeg/libavformat/wtvdec.c -++++ b/lib/ffmpeg/libavformat/wtvdec.c -+@@ -980,21 +980,23 @@ static int read_header(AVFormatContext *s) -+ pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16); -+ if (pb) { -+ int i; -++ AVIndexEntry *e = wtv->index_entries; -++ AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1; -++ uint64_t last_position = 0; -+ while (1) { -+ uint64_t frame_nb = avio_rl64(pb); -+ uint64_t position = avio_rl64(pb); -++ while (frame_nb > e->size && e <= e_end) { -++ e->pos = last_position; -++ e++; -++ } -+ if (url_feof(pb)) -+ break; -+- for (i = wtv->nb_index_entries - 1; i >= 0; i--) { -+- AVIndexEntry *e = wtv->index_entries + i; -+- if (frame_nb > e->size) -+- break; -+- if (position > e->pos) -+- e->pos = position; -+- } -++ last_position = position; -+ } -++ e_end->pos = last_position; -+ wtvfile_close(pb); -+- st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp; -++ st->duration = e_end->timestamp; -+ } -+ } -+ } --- -1.9.3 - - -From 7955c0cb26e663ed12e6798fcfb696f391aadf77 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 29 Apr 2014 15:55:28 +0100 -Subject: [PATCH 66/82] [ffmpeg] vc-1: Optimise parser (with special attention - to ARM) - -Backport from upstream ffmpeg ---- - ...earch-code-search-functions-into-separate.patch | 752 +++++++++++++++++++++ - ...atform-specific-start-code-search-routine.patch | 143 ++++ - ...mise-parser-with-special-attention-to-ARM.patch | 401 +++++++++++ - tools/depends/target/ffmpeg/Makefile | 8 +- - 4 files changed, 1303 insertions(+), 1 deletion(-) - create mode 100644 tools/depends/target/ffmpeg/0001-h264-Move-search-code-search-functions-into-separate.patch - create mode 100644 tools/depends/target/ffmpeg/0002-vc-1-Add-platform-specific-start-code-search-routine.patch - create mode 100644 tools/depends/target/ffmpeg/0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch - -diff --git a/tools/depends/target/ffmpeg/0001-h264-Move-search-code-search-functions-into-separate.patch b/tools/depends/target/ffmpeg/0001-h264-Move-search-code-search-functions-into-separate.patch -new file mode 100644 -index 0000000..62e473d ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0001-h264-Move-search-code-search-functions-into-separate.patch -@@ -0,0 +1,752 @@ -+From 8cdb3bf2837a3fb4fff3c6586316f81ae5f7b6cd Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Wed, 16 Apr 2014 01:51:31 +0100 -+Subject: [PATCH 1/3] h264: Move search code search functions into separate -+ source files. -+ -+This permits re-use with parsers for codecs which use similar start codes. -+ -+Signed-off-by: Michael Niedermayer -+--- -+ libavcodec/Makefile | 2 +- -+ libavcodec/arm/Makefile | 2 +- -+ libavcodec/arm/h264dsp_armv6.S | 253 -------------------------------------- -+ libavcodec/arm/h264dsp_init_arm.c | 4 +- -+ libavcodec/arm/startcode_armv6.S | 253 ++++++++++++++++++++++++++++++++++++++ -+ libavcodec/h264dsp.c | 31 +---- -+ libavcodec/startcode.c | 57 +++++++++ -+ libavcodec/startcode.h | 35 ++++++ -+ 8 files changed, 351 insertions(+), 286 deletions(-) -+ delete mode 100644 libavcodec/arm/h264dsp_armv6.S -+ create mode 100644 libavcodec/arm/startcode_armv6.S -+ create mode 100644 libavcodec/startcode.c -+ create mode 100644 libavcodec/startcode.h -+ -+diff --git a/libavcodec/Makefile b/libavcodec/Makefile -+index b56ecd1..19caf11 100644 -+--- a/libavcodec/Makefile -++++ b/libavcodec/Makefile -+@@ -49,7 +49,7 @@ OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.o \ -+ OBJS-$(CONFIG_GOLOMB) += golomb.o -+ OBJS-$(CONFIG_H263DSP) += h263dsp.o -+ OBJS-$(CONFIG_H264CHROMA) += h264chroma.o -+-OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o -++OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o startcode.o -+ OBJS-$(CONFIG_H264PRED) += h264pred.o -+ OBJS-$(CONFIG_H264QPEL) += h264qpel.o -+ OBJS-$(CONFIG_HPELDSP) += hpeldsp.o -+diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile -+index a8446b2..b6410b2 100644 -+--- a/libavcodec/arm/Makefile -++++ b/libavcodec/arm/Makefile -+@@ -47,7 +47,7 @@ ARMV6-OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_armv6.o \ -+ arm/simple_idct_armv6.o \ -+ -+ ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o -+-ARMV6-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_armv6.o -++ARMV6-OBJS-$(CONFIG_H264DSP) += arm/startcode_armv6.o -+ ARMV6-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_armv6.o \ -+ arm/hpeldsp_armv6.o -+ ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o -+diff --git a/libavcodec/arm/h264dsp_armv6.S b/libavcodec/arm/h264dsp_armv6.S -+deleted file mode 100644 -+index 2758262..0000000 -+--- a/libavcodec/arm/h264dsp_armv6.S -++++ /dev/null -+@@ -1,253 +0,0 @@ -+-/* -+- * Copyright (c) 2013 RISC OS Open Ltd -+- * Author: Ben Avison -+- * -+- * This file is part of FFmpeg. -+- * -+- * FFmpeg is free software; you can redistribute it and/or -+- * modify it under the terms of the GNU Lesser General Public -+- * License as published by the Free Software Foundation; either -+- * version 2.1 of the License, or (at your option) any later version. -+- * -+- * FFmpeg is distributed in the hope that it will be useful, -+- * but WITHOUT ANY WARRANTY; without even the implied warranty of -+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+- * Lesser General Public License for more details. -+- * -+- * You should have received a copy of the GNU Lesser General Public -+- * License along with FFmpeg; if not, write to the Free Software -+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+- */ -+- -+-#include "libavutil/arm/asm.S" -+- -+-RESULT .req a1 -+-BUF .req a1 -+-SIZE .req a2 -+-PATTERN .req a3 -+-PTR .req a4 -+-DAT0 .req v1 -+-DAT1 .req v2 -+-DAT2 .req v3 -+-DAT3 .req v4 -+-TMP0 .req v5 -+-TMP1 .req v6 -+-TMP2 .req ip -+-TMP3 .req lr -+- -+-#define PRELOAD_DISTANCE 4 -+- -+-.macro innerloop4 -+- ldr DAT0, [PTR], #4 -+- subs SIZE, SIZE, #4 @ C flag survives rest of macro -+- sub TMP0, DAT0, PATTERN, lsr #14 -+- bic TMP0, TMP0, DAT0 -+- ands TMP0, TMP0, PATTERN -+-.endm -+- -+-.macro innerloop16 decrement, do_preload -+- ldmia PTR!, {DAT0,DAT1,DAT2,DAT3} -+- .ifnc "\do_preload","" -+- pld [PTR, #PRELOAD_DISTANCE*32] -+- .endif -+- .ifnc "\decrement","" -+- subs SIZE, SIZE, #\decrement @ C flag survives rest of macro -+- .endif -+- sub TMP0, DAT0, PATTERN, lsr #14 -+- sub TMP1, DAT1, PATTERN, lsr #14 -+- bic TMP0, TMP0, DAT0 -+- bic TMP1, TMP1, DAT1 -+- sub TMP2, DAT2, PATTERN, lsr #14 -+- sub TMP3, DAT3, PATTERN, lsr #14 -+- ands TMP0, TMP0, PATTERN -+- bic TMP2, TMP2, DAT2 -+- it eq -+- andseq TMP1, TMP1, PATTERN -+- bic TMP3, TMP3, DAT3 -+- itt eq -+- andseq TMP2, TMP2, PATTERN -+- andseq TMP3, TMP3, PATTERN -+-.endm -+- -+-/* int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size) */ -+-function ff_h264_find_start_code_candidate_armv6, export=1 -+- push {v1-v6,lr} -+- mov PTR, BUF -+- @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go -+- @ before using code that does preloads -+- cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1 -+- blo 60f -+- -+- @ Get to word-alignment, 1 byte at a time -+- tst PTR, #3 -+- beq 2f -+-1: ldrb DAT0, [PTR], #1 -+- sub SIZE, SIZE, #1 -+- teq DAT0, #0 -+- beq 90f -+- tst PTR, #3 -+- bne 1b -+-2: @ Get to 4-word alignment, 1 word at a time -+- ldr PATTERN, =0x80008000 -+- setend be -+- tst PTR, #12 -+- beq 4f -+-3: innerloop4 -+- bne 91f -+- tst PTR, #12 -+- bne 3b -+-4: @ Get to cacheline (8-word) alignment -+- tst PTR, #16 -+- beq 5f -+- innerloop16 16 -+- bne 93f -+-5: @ Check complete cachelines, with preloading -+- @ We need to stop when there are still (PRELOAD_DISTANCE+1) -+- @ complete cachelines to go -+- sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 -+-6: innerloop16 , do_preload -+- bne 93f -+- innerloop16 32 -+- bne 93f -+- bcs 6b -+- @ Preload trailing part-cacheline, if any -+- tst SIZE, #31 -+- beq 7f -+- pld [PTR, #(PRELOAD_DISTANCE+1)*32] -+- @ Check remaining data without doing any more preloads. First -+- @ do in chunks of 4 words: -+-7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16 -+- bmi 9f -+-8: innerloop16 16 -+- bne 93f -+- bcs 8b -+- @ Then in words: -+-9: adds SIZE, SIZE, #16 - 4 -+- bmi 11f -+-10: innerloop4 -+- bne 91f -+- bcs 10b -+-11: setend le -+- @ Check second byte of final halfword -+- ldrb DAT0, [PTR, #-1] -+- teq DAT0, #0 -+- beq 90f -+- @ Check any remaining bytes -+- tst SIZE, #3 -+- beq 13f -+-12: ldrb DAT0, [PTR], #1 -+- sub SIZE, SIZE, #1 -+- teq DAT0, #0 -+- beq 90f -+- tst SIZE, #3 -+- bne 12b -+- @ No candidate found -+-13: sub RESULT, PTR, BUF -+- b 99f -+- -+-60: @ Small buffer - simply check by looping over bytes -+- subs SIZE, SIZE, #1 -+- bcc 99f -+-61: ldrb DAT0, [PTR], #1 -+- subs SIZE, SIZE, #1 -+- teq DAT0, #0 -+- beq 90f -+- bcs 61b -+- @ No candidate found -+- sub RESULT, PTR, BUF -+- b 99f -+- -+-90: @ Found a candidate at the preceding byte -+- sub RESULT, PTR, BUF -+- sub RESULT, RESULT, #1 -+- b 99f -+- -+-91: @ Found a candidate somewhere in the preceding 4 bytes -+- sub RESULT, PTR, BUF -+- sub RESULT, RESULT, #4 -+- sub TMP0, DAT0, #0x20000 -+- bics TMP0, TMP0, DAT0 -+- itt pl -+- ldrbpl DAT0, [PTR, #-3] -+- addpl RESULT, RESULT, #2 -+- bpl 92f -+- teq RESULT, #0 -+- beq 98f @ don't look back a byte if found at first byte in buffer -+- ldrb DAT0, [PTR, #-5] -+-92: teq DAT0, #0 -+- it eq -+- subeq RESULT, RESULT, #1 -+- b 98f -+- -+-93: @ Found a candidate somewhere in the preceding 16 bytes -+- sub RESULT, PTR, BUF -+- sub RESULT, RESULT, #16 -+- teq TMP0, #0 -+- beq 95f @ not in first 4 bytes -+- sub TMP0, DAT0, #0x20000 -+- bics TMP0, TMP0, DAT0 -+- itt pl -+- ldrbpl DAT0, [PTR, #-15] -+- addpl RESULT, RESULT, #2 -+- bpl 94f -+- teq RESULT, #0 -+- beq 98f @ don't look back a byte if found at first byte in buffer -+- ldrb DAT0, [PTR, #-17] -+-94: teq DAT0, #0 -+- it eq -+- subeq RESULT, RESULT, #1 -+- b 98f -+-95: add RESULT, RESULT, #4 -+- teq TMP1, #0 -+- beq 96f @ not in next 4 bytes -+- sub TMP1, DAT1, #0x20000 -+- bics TMP1, TMP1, DAT1 -+- itee mi -+- ldrbmi DAT0, [PTR, #-13] -+- ldrbpl DAT0, [PTR, #-11] -+- addpl RESULT, RESULT, #2 -+- teq DAT0, #0 -+- it eq -+- subeq RESULT, RESULT, #1 -+- b 98f -+-96: add RESULT, RESULT, #4 -+- teq TMP2, #0 -+- beq 97f @ not in next 4 bytes -+- sub TMP2, DAT2, #0x20000 -+- bics TMP2, TMP2, DAT2 -+- itee mi -+- ldrbmi DAT0, [PTR, #-9] -+- ldrbpl DAT0, [PTR, #-7] -+- addpl RESULT, RESULT, #2 -+- teq DAT0, #0 -+- it eq -+- subeq RESULT, RESULT, #1 -+- b 98f -+-97: add RESULT, RESULT, #4 -+- sub TMP3, DAT3, #0x20000 -+- bics TMP3, TMP3, DAT3 -+- itee mi -+- ldrbmi DAT0, [PTR, #-5] -+- ldrbpl DAT0, [PTR, #-3] -+- addpl RESULT, RESULT, #2 -+- teq DAT0, #0 -+- it eq -+- subeq RESULT, RESULT, #1 -+- @ drop through to 98f -+-98: setend le -+-99: pop {v1-v6,pc} -+-endfunc -+- -+- .unreq RESULT -+- .unreq BUF -+- .unreq SIZE -+- .unreq PATTERN -+- .unreq PTR -+- .unreq DAT0 -+- .unreq DAT1 -+- .unreq DAT2 -+- .unreq DAT3 -+- .unreq TMP0 -+- .unreq TMP1 -+- .unreq TMP2 -+- .unreq TMP3 -+diff --git a/libavcodec/arm/h264dsp_init_arm.c b/libavcodec/arm/h264dsp_init_arm.c -+index a0418fd..eb6c514 100644 -+--- a/libavcodec/arm/h264dsp_init_arm.c -++++ b/libavcodec/arm/h264dsp_init_arm.c -+@@ -24,7 +24,7 @@ -+ #include "libavutil/arm/cpu.h" -+ #include "libavcodec/h264dsp.h" -+ -+-int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size); -++int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size); -+ -+ void ff_h264_v_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha, -+ int beta, int8_t *tc0); -+@@ -109,7 +109,7 @@ av_cold void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth, -+ int cpu_flags = av_get_cpu_flags(); -+ -+ if (have_armv6(cpu_flags)) -+- c->h264_find_start_code_candidate = ff_h264_find_start_code_candidate_armv6; -++ c->h264_find_start_code_candidate = ff_startcode_find_candidate_armv6; -+ if (have_neon(cpu_flags)) -+ h264dsp_init_neon(c, bit_depth, chroma_format_idc); -+ } -+diff --git a/libavcodec/arm/startcode_armv6.S b/libavcodec/arm/startcode_armv6.S -+new file mode 100644 -+index 0000000..a46f009 -+--- /dev/null -++++ b/libavcodec/arm/startcode_armv6.S -+@@ -0,0 +1,253 @@ -++/* -++ * Copyright (c) 2013 RISC OS Open Ltd -++ * Author: Ben Avison -++ * -++ * This file is part of FFmpeg. -++ * -++ * FFmpeg is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU Lesser General Public -++ * License as published by the Free Software Foundation; either -++ * version 2.1 of the License, or (at your option) any later version. -++ * -++ * FFmpeg is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * Lesser General Public License for more details. -++ * -++ * You should have received a copy of the GNU Lesser General Public -++ * License along with FFmpeg; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++#include "libavutil/arm/asm.S" -++ -++RESULT .req a1 -++BUF .req a1 -++SIZE .req a2 -++PATTERN .req a3 -++PTR .req a4 -++DAT0 .req v1 -++DAT1 .req v2 -++DAT2 .req v3 -++DAT3 .req v4 -++TMP0 .req v5 -++TMP1 .req v6 -++TMP2 .req ip -++TMP3 .req lr -++ -++#define PRELOAD_DISTANCE 4 -++ -++.macro innerloop4 -++ ldr DAT0, [PTR], #4 -++ subs SIZE, SIZE, #4 @ C flag survives rest of macro -++ sub TMP0, DAT0, PATTERN, lsr #14 -++ bic TMP0, TMP0, DAT0 -++ ands TMP0, TMP0, PATTERN -++.endm -++ -++.macro innerloop16 decrement, do_preload -++ ldmia PTR!, {DAT0,DAT1,DAT2,DAT3} -++ .ifnc "\do_preload","" -++ pld [PTR, #PRELOAD_DISTANCE*32] -++ .endif -++ .ifnc "\decrement","" -++ subs SIZE, SIZE, #\decrement @ C flag survives rest of macro -++ .endif -++ sub TMP0, DAT0, PATTERN, lsr #14 -++ sub TMP1, DAT1, PATTERN, lsr #14 -++ bic TMP0, TMP0, DAT0 -++ bic TMP1, TMP1, DAT1 -++ sub TMP2, DAT2, PATTERN, lsr #14 -++ sub TMP3, DAT3, PATTERN, lsr #14 -++ ands TMP0, TMP0, PATTERN -++ bic TMP2, TMP2, DAT2 -++ it eq -++ andseq TMP1, TMP1, PATTERN -++ bic TMP3, TMP3, DAT3 -++ itt eq -++ andseq TMP2, TMP2, PATTERN -++ andseq TMP3, TMP3, PATTERN -++.endm -++ -++/* int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size) */ -++function ff_startcode_find_candidate_armv6, export=1 -++ push {v1-v6,lr} -++ mov PTR, BUF -++ @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go -++ @ before using code that does preloads -++ cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1 -++ blo 60f -++ -++ @ Get to word-alignment, 1 byte at a time -++ tst PTR, #3 -++ beq 2f -++1: ldrb DAT0, [PTR], #1 -++ sub SIZE, SIZE, #1 -++ teq DAT0, #0 -++ beq 90f -++ tst PTR, #3 -++ bne 1b -++2: @ Get to 4-word alignment, 1 word at a time -++ ldr PATTERN, =0x80008000 -++ setend be -++ tst PTR, #12 -++ beq 4f -++3: innerloop4 -++ bne 91f -++ tst PTR, #12 -++ bne 3b -++4: @ Get to cacheline (8-word) alignment -++ tst PTR, #16 -++ beq 5f -++ innerloop16 16 -++ bne 93f -++5: @ Check complete cachelines, with preloading -++ @ We need to stop when there are still (PRELOAD_DISTANCE+1) -++ @ complete cachelines to go -++ sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 -++6: innerloop16 , do_preload -++ bne 93f -++ innerloop16 32 -++ bne 93f -++ bcs 6b -++ @ Preload trailing part-cacheline, if any -++ tst SIZE, #31 -++ beq 7f -++ pld [PTR, #(PRELOAD_DISTANCE+1)*32] -++ @ Check remaining data without doing any more preloads. First -++ @ do in chunks of 4 words: -++7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16 -++ bmi 9f -++8: innerloop16 16 -++ bne 93f -++ bcs 8b -++ @ Then in words: -++9: adds SIZE, SIZE, #16 - 4 -++ bmi 11f -++10: innerloop4 -++ bne 91f -++ bcs 10b -++11: setend le -++ @ Check second byte of final halfword -++ ldrb DAT0, [PTR, #-1] -++ teq DAT0, #0 -++ beq 90f -++ @ Check any remaining bytes -++ tst SIZE, #3 -++ beq 13f -++12: ldrb DAT0, [PTR], #1 -++ sub SIZE, SIZE, #1 -++ teq DAT0, #0 -++ beq 90f -++ tst SIZE, #3 -++ bne 12b -++ @ No candidate found -++13: sub RESULT, PTR, BUF -++ b 99f -++ -++60: @ Small buffer - simply check by looping over bytes -++ subs SIZE, SIZE, #1 -++ bcc 99f -++61: ldrb DAT0, [PTR], #1 -++ subs SIZE, SIZE, #1 -++ teq DAT0, #0 -++ beq 90f -++ bcs 61b -++ @ No candidate found -++ sub RESULT, PTR, BUF -++ b 99f -++ -++90: @ Found a candidate at the preceding byte -++ sub RESULT, PTR, BUF -++ sub RESULT, RESULT, #1 -++ b 99f -++ -++91: @ Found a candidate somewhere in the preceding 4 bytes -++ sub RESULT, PTR, BUF -++ sub RESULT, RESULT, #4 -++ sub TMP0, DAT0, #0x20000 -++ bics TMP0, TMP0, DAT0 -++ itt pl -++ ldrbpl DAT0, [PTR, #-3] -++ addpl RESULT, RESULT, #2 -++ bpl 92f -++ teq RESULT, #0 -++ beq 98f @ don't look back a byte if found at first byte in buffer -++ ldrb DAT0, [PTR, #-5] -++92: teq DAT0, #0 -++ it eq -++ subeq RESULT, RESULT, #1 -++ b 98f -++ -++93: @ Found a candidate somewhere in the preceding 16 bytes -++ sub RESULT, PTR, BUF -++ sub RESULT, RESULT, #16 -++ teq TMP0, #0 -++ beq 95f @ not in first 4 bytes -++ sub TMP0, DAT0, #0x20000 -++ bics TMP0, TMP0, DAT0 -++ itt pl -++ ldrbpl DAT0, [PTR, #-15] -++ addpl RESULT, RESULT, #2 -++ bpl 94f -++ teq RESULT, #0 -++ beq 98f @ don't look back a byte if found at first byte in buffer -++ ldrb DAT0, [PTR, #-17] -++94: teq DAT0, #0 -++ it eq -++ subeq RESULT, RESULT, #1 -++ b 98f -++95: add RESULT, RESULT, #4 -++ teq TMP1, #0 -++ beq 96f @ not in next 4 bytes -++ sub TMP1, DAT1, #0x20000 -++ bics TMP1, TMP1, DAT1 -++ itee mi -++ ldrbmi DAT0, [PTR, #-13] -++ ldrbpl DAT0, [PTR, #-11] -++ addpl RESULT, RESULT, #2 -++ teq DAT0, #0 -++ it eq -++ subeq RESULT, RESULT, #1 -++ b 98f -++96: add RESULT, RESULT, #4 -++ teq TMP2, #0 -++ beq 97f @ not in next 4 bytes -++ sub TMP2, DAT2, #0x20000 -++ bics TMP2, TMP2, DAT2 -++ itee mi -++ ldrbmi DAT0, [PTR, #-9] -++ ldrbpl DAT0, [PTR, #-7] -++ addpl RESULT, RESULT, #2 -++ teq DAT0, #0 -++ it eq -++ subeq RESULT, RESULT, #1 -++ b 98f -++97: add RESULT, RESULT, #4 -++ sub TMP3, DAT3, #0x20000 -++ bics TMP3, TMP3, DAT3 -++ itee mi -++ ldrbmi DAT0, [PTR, #-5] -++ ldrbpl DAT0, [PTR, #-3] -++ addpl RESULT, RESULT, #2 -++ teq DAT0, #0 -++ it eq -++ subeq RESULT, RESULT, #1 -++ @ drop through to 98f -++98: setend le -++99: pop {v1-v6,pc} -++endfunc -++ -++ .unreq RESULT -++ .unreq BUF -++ .unreq SIZE -++ .unreq PATTERN -++ .unreq PTR -++ .unreq DAT0 -++ .unreq DAT1 -++ .unreq DAT2 -++ .unreq DAT3 -++ .unreq TMP0 -++ .unreq TMP1 -++ .unreq TMP2 -++ .unreq TMP3 -+diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c -+index a2a4aba..a4da776 100644 -+--- a/libavcodec/h264dsp.c -++++ b/libavcodec/h264dsp.c -+@@ -33,6 +33,7 @@ -+ #include "avcodec.h" -+ #include "h264dsp.h" -+ #include "h264idct.h" -++#include "startcode.h" -+ #include "libavutil/common.h" -+ -+ #define BIT_DEPTH 8 -+@@ -63,34 +64,6 @@ -+ #include "h264addpx_template.c" -+ #undef BIT_DEPTH -+ -+-static int h264_find_start_code_candidate_c(const uint8_t *buf, int size) -+-{ -+- int i = 0; -+-#if HAVE_FAST_UNALIGNED -+- /* we check i < size instead of i + 3 / 7 because it is -+- * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE -+- * bytes at the end. -+- */ -+-# if HAVE_FAST_64BIT -+- while (i < size && -+- !((~*(const uint64_t *)(buf + i) & -+- (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) & -+- 0x8080808080808080ULL)) -+- i += 8; -+-# else -+- while (i < size && -+- !((~*(const uint32_t *)(buf + i) & -+- (*(const uint32_t *)(buf + i) - 0x01010101U)) & -+- 0x80808080U)) -+- i += 4; -+-# endif -+-#endif -+- for (; i < size; i++) -+- if (!buf[i]) -+- break; -+- return i; -+-} -+- -+ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, -+ const int chroma_format_idc) -+ { -+@@ -178,7 +151,7 @@ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, -+ H264_DSP(8); -+ break; -+ } -+- c->h264_find_start_code_candidate = h264_find_start_code_candidate_c; -++ c->h264_find_start_code_candidate = ff_startcode_find_candidate_c; -+ -+ if (ARCH_AARCH64) ff_h264dsp_init_aarch64(c, bit_depth, chroma_format_idc); -+ if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc); -+diff --git a/libavcodec/startcode.c b/libavcodec/startcode.c -+new file mode 100644 -+index 0000000..5df7695 -+--- /dev/null -++++ b/libavcodec/startcode.c -+@@ -0,0 +1,57 @@ -++/* -++ * Copyright (c) 2003-2010 Michael Niedermayer -++ * -++ * This file is part of FFmpeg. -++ * -++ * FFmpeg is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU Lesser General Public -++ * License as published by the Free Software Foundation; either -++ * version 2.1 of the License, or (at your option) any later version. -++ * -++ * FFmpeg is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * Lesser General Public License for more details. -++ * -++ * You should have received a copy of the GNU Lesser General Public -++ * License along with FFmpeg; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++/** -++ * @file -++ * Accelerated start code search function for start codes common to -++ * MPEG-1/2/4 video, VC-1, H.264/5 -++ * @author Michael Niedermayer -++ */ -++ -++#include "startcode.h" -++#include "config.h" -++ -++int ff_startcode_find_candidate_c(const uint8_t *buf, int size) -++{ -++ int i = 0; -++#if HAVE_FAST_UNALIGNED -++ /* we check i < size instead of i + 3 / 7 because it is -++ * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE -++ * bytes at the end. -++ */ -++# if HAVE_FAST_64BIT -++ while (i < size && -++ !((~*(const uint64_t *)(buf + i) & -++ (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) & -++ 0x8080808080808080ULL)) -++ i += 8; -++# else -++ while (i < size && -++ !((~*(const uint32_t *)(buf + i) & -++ (*(const uint32_t *)(buf + i) - 0x01010101U)) & -++ 0x80808080U)) -++ i += 4; -++# endif -++#endif -++ for (; i < size; i++) -++ if (!buf[i]) -++ break; -++ return i; -++} -+diff --git a/libavcodec/startcode.h b/libavcodec/startcode.h -+new file mode 100644 -+index 0000000..cc55d5f -+--- /dev/null -++++ b/libavcodec/startcode.h -+@@ -0,0 +1,35 @@ -++/* -++ * Copyright (c) 2003-2010 Michael Niedermayer -++ * -++ * This file is part of FFmpeg. -++ * -++ * FFmpeg is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU Lesser General Public -++ * License as published by the Free Software Foundation; either -++ * version 2.1 of the License, or (at your option) any later version. -++ * -++ * FFmpeg is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * Lesser General Public License for more details. -++ * -++ * You should have received a copy of the GNU Lesser General Public -++ * License along with FFmpeg; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++/** -++ * @file -++ * Accelerated start code search function for start codes common to -++ * MPEG-1/2/4 video, VC-1, H.264/5 -++ * @author Michael Niedermayer -++ */ -++ -++#ifndef AVCODEC_STARTCODE_H -++#define AVCODEC_STARTCODE_H -++ -++#include -++ -++int ff_startcode_find_candidate_c(const uint8_t *buf, int size); -++ -++#endif /* AVCODEC_STARTCODE_H */ -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0002-vc-1-Add-platform-specific-start-code-search-routine.patch b/tools/depends/target/ffmpeg/0002-vc-1-Add-platform-specific-start-code-search-routine.patch -new file mode 100644 -index 0000000..e84ace6 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0002-vc-1-Add-platform-specific-start-code-search-routine.patch -@@ -0,0 +1,143 @@ -+From a60747132a1a6652ac0d18f3f110a20ea637ac30 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Wed, 16 Apr 2014 01:51:32 +0100 -+Subject: [PATCH 2/3] vc-1: Add platform-specific start code search routine to -+ VC1DSPContext. -+ -+Initialise VC1DSPContext for parser as well as for decoder. -+Note, the VC-1 code doesn't actually use the function pointer yet. -+ -+Signed-off-by: Michael Niedermayer -+--- -+ libavcodec/Makefile | 6 +++--- -+ libavcodec/arm/Makefile | 2 ++ -+ libavcodec/arm/vc1dsp_init_arm.c | 4 ++++ -+ libavcodec/vc1.c | 2 ++ -+ libavcodec/vc1dec.c | 1 - -+ libavcodec/vc1dsp.c | 3 +++ -+ libavcodec/vc1dsp.h | 8 ++++++++ -+ 7 files changed, 22 insertions(+), 4 deletions(-) -+ -+diff --git a/libavcodec/Makefile b/libavcodec/Makefile -+index 19caf11..120f85a 100644 -+--- a/libavcodec/Makefile -++++ b/libavcodec/Makefile -+@@ -458,7 +458,7 @@ OBJS-$(CONFIG_VB_DECODER) += vb.o -+ OBJS-$(CONFIG_VBLE_DECODER) += vble.o -+ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \ -+ msmpeg4dec.o msmpeg4.o msmpeg4data.o \ -+- wmv2dsp.o -++ wmv2dsp.o startcode.o -+ OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o -+ OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o -+ OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o -+@@ -783,9 +783,9 @@ OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o -+ OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o -+ OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o -+ OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o -+-OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ -++OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o vc1dsp.o \ -+ msmpeg4.o msmpeg4data.o mpeg4video.o \ -+- h263.o -++ h263.o startcode.o -+ OBJS-$(CONFIG_VORBIS_PARSER) += vorbis_parser.o xiph.o -+ OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o -+ OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o -+diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile -+index b6410b2..fa2b18e 100644 -+--- a/libavcodec/arm/Makefile -++++ b/libavcodec/arm/Makefile -+@@ -51,6 +51,8 @@ ARMV6-OBJS-$(CONFIG_H264DSP) += arm/startcode_armv6.o -+ ARMV6-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_armv6.o \ -+ arm/hpeldsp_armv6.o -+ ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o -++ARMV6-OBJS-$(CONFIG_VC1_DECODER) += arm/startcode_armv6.o -++ARMV6-OBJS-$(CONFIG_VC1_PARSER) += arm/startcode_armv6.o -+ ARMV6-OBJS-$(CONFIG_VP8_DECODER) += arm/vp8_armv6.o \ -+ arm/vp8dsp_init_armv6.o \ -+ arm/vp8dsp_armv6.o -+diff --git a/libavcodec/arm/vc1dsp_init_arm.c b/libavcodec/arm/vc1dsp_init_arm.c -+index 47d4126..4a84848 100644 -+--- a/libavcodec/arm/vc1dsp_init_arm.c -++++ b/libavcodec/arm/vc1dsp_init_arm.c -+@@ -23,10 +23,14 @@ -+ #include "libavcodec/vc1dsp.h" -+ #include "vc1dsp.h" -+ -++int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size); -++ -+ av_cold void ff_vc1dsp_init_arm(VC1DSPContext *dsp) -+ { -+ int cpu_flags = av_get_cpu_flags(); -+ -++ if (have_armv6(cpu_flags)) -++ dsp->vc1_find_start_code_candidate = ff_startcode_find_candidate_armv6; -+ if (have_neon(cpu_flags)) -+ ff_vc1dsp_init_neon(dsp); -+ } -+diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c -+index 49d4885..cb941dd 100644 -+--- a/libavcodec/vc1.c -++++ b/libavcodec/vc1.c -+@@ -1706,5 +1706,7 @@ av_cold int ff_vc1_init_common(VC1Context *v) -+ v->pq = -1; -+ v->mvrange = 0; /* 7.1.1.18, p80 */ -+ -++ ff_vc1dsp_init(&v->vc1dsp); -++ -+ return 0; -+ } -+diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c -+index 30fee47..67cda42 100644 -+--- a/libavcodec/vc1dec.c -++++ b/libavcodec/vc1dec.c -+@@ -5631,7 +5631,6 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) -+ ff_vc1_decode_end(avctx); -+ -+ ff_h264chroma_init(&v->h264chroma, 8); -+- ff_vc1dsp_init(&v->vc1dsp); -+ -+ if (avctx->codec_id == AV_CODEC_ID_WMV3 || avctx->codec_id == AV_CODEC_ID_WMV3IMAGE) { -+ int count = 0; -+diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c -+index ec9c17b..09a9006 100644 -+--- a/libavcodec/vc1dsp.c -++++ b/libavcodec/vc1dsp.c -+@@ -30,6 +30,7 @@ -+ #include "h264chroma.h" -+ #include "rnd_avg.h" -+ #include "vc1dsp.h" -++#include "startcode.h" -+ -+ /* Apply overlap transform to horizontal edge */ -+ static void vc1_v_overlap_c(uint8_t *src, int stride) -+@@ -947,6 +948,8 @@ av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) -+ dsp->sprite_v_double_twoscale = sprite_v_double_twoscale_c; -+ #endif /* CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER */ -+ -++ dsp->vc1_find_start_code_candidate = ff_startcode_find_candidate_c; -++ -+ if (ARCH_AARCH64) -+ ff_vc1dsp_init_aarch64(dsp); -+ if (ARCH_ARM) -+diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h -+index 990fbc3..6a90eed 100644 -+--- a/libavcodec/vc1dsp.h -++++ b/libavcodec/vc1dsp.h -+@@ -74,6 +74,14 @@ typedef struct VC1DSPContext { -+ void (*sprite_v_double_twoscale)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, -+ const uint8_t *src2a, const uint8_t *src2b, int offset2, -+ int alpha, int width); -++ -++ /** -++ * Search buf from the start for up to size bytes. Return the index -++ * of a zero byte, or >= size if not found. Ideally, use lookahead -++ * to filter out any zero bytes that are known to not be followed by -++ * one or more further zero bytes and a one byte. -++ */ -++ int (*vc1_find_start_code_candidate)(const uint8_t *buf, int size); -+ } VC1DSPContext; -+ -+ void ff_vc1dsp_init(VC1DSPContext* c); -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch b/tools/depends/target/ffmpeg/0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch -new file mode 100644 -index 0000000..1f0cf40 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch -@@ -0,0 +1,401 @@ -+From c39df43eae03768427243668c040de8437c4f79c Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Wed, 23 Apr 2014 01:41:04 +0100 -+Subject: [PATCH 3/3] vc-1: Optimise parser (with special attention to ARM) -+ -+The previous implementation of the parser made four passes over each input -+buffer (reduced to two if the container format already guaranteed the input -+buffer corresponded to frames, such as with MKV). But these buffers are -+often 200K in size, certainly enough to flush the data out of L1 cache, and -+for many CPUs, all the way out to main memory. The passes were: -+ -+1) locate frame boundaries (not needed for MKV etc) -+2) copy the data into a contiguous block (not needed for MKV etc) -+3) locate the start codes within each frame -+4) unescape the data between start codes -+ -+After this, the unescaped data was parsed to extract certain header fields, -+but because the unescape operation was so large, this was usually also -+effectively operating on uncached memory. Most of the unescaped data was -+simply thrown away and never processed further. Only step 2 - because it -+used memcpy - was using prefetch, making things even worse. -+ -+This patch reorganises these steps so that, aside from the copying, the -+operations are performed in parallel, maximising cache utilisation. No more -+than the worst-case number of bytes needed for header parsing is unescaped. -+Most of the data is, in practice, only read in order to search for a start -+code, for which optimised implementations already existed in the H264 codec -+(notably the ARM version uses prefetch, so we end up doing both remaining -+passes at maximum speed). For MKV files, we know when we've found the last -+start code of interest in a given frame, so we are able to avoid doing even -+that one remaining pass for most of the buffer. -+ -+In some use-cases (such as the Raspberry Pi) video decode is handled by the -+GPU, but the entire elementary stream is still fed through the parser to -+pick out certain elements of the header which are necessary to manage the -+decode process. As you might expect, in these cases, the performance of the -+parser is significant. -+ -+To measure parser performance, I used the same VC-1 elementary stream in -+either an MPEG-2 transport stream or a MKV file, and fed it through ffmpeg -+with -c:v copy -c:a copy -f null. These are the gperftools counts for -+those streams, both filtered to only include vc1_parse() and its callees, -+and unfiltered (to include the whole binary). Lower numbers are better: -+ -+ Before After -+File Filtered Mean StdDev Mean StdDev Confidence Change -+M2TS No 861.7 8.2 650.5 8.1 100.0% +32.5% -+MKV No 868.9 7.4 731.7 9.0 100.0% +18.8% -+M2TS Yes 250.0 11.2 27.2 3.4 100.0% +817.9% -+MKV Yes 149.0 12.8 1.7 0.8 100.0% +8526.3% -+ -+Yes, that last case shows vc1_parse() running 86 times faster! The M2TS -+case does show a larger absolute improvement though, since it was worse -+to begin with. -+ -+This patch has been tested with the FATE suite (albeit on x86 for speed). -+ -+Signed-off-by: Michael Niedermayer -+--- -+ libavcodec/vc1_parser.c | 284 ++++++++++++++++++++++++++++++------------------ -+ 1 file changed, 180 insertions(+), 104 deletions(-) -+ -+diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c -+index cc29ce1..4ed14bc 100644 -+--- a/libavcodec/vc1_parser.c -++++ b/libavcodec/vc1_parser.c -+@@ -30,122 +30,88 @@ -+ #include "vc1.h" -+ #include "get_bits.h" -+ -++/** The maximum number of bytes of a sequence, entry point or -++ * frame header whose values we pay any attention to */ -++#define UNESCAPED_THRESHOLD 37 -++ -++/** The maximum number of bytes of a sequence, entry point or -++ * frame header which must be valid memory (because they are -++ * used to update the bitstream cache in skip_bits() calls) -++ */ -++#define UNESCAPED_LIMIT 144 -++ -++typedef enum { -++ NO_MATCH, -++ ONE_ZERO, -++ TWO_ZEROS, -++ ONE -++} VC1ParseSearchState; -++ -+ typedef struct { -+ ParseContext pc; -+ VC1Context v; -++ uint8_t prev_start_code; -++ size_t bytes_to_skip; -++ uint8_t unesc_buffer[UNESCAPED_LIMIT]; -++ size_t unesc_index; -++ VC1ParseSearchState search_state; -+ } VC1ParseContext; -+ -+-static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, -+- const uint8_t *buf, int buf_size) -++static void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx, -++ const uint8_t *buf, int buf_size) -+ { -++ /* Parse the header we just finished unescaping */ -+ VC1ParseContext *vpc = s->priv_data; -+ GetBitContext gb; -+- const uint8_t *start, *end, *next; -+- uint8_t *buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); -+- -++ int ret; -+ vpc->v.s.avctx = avctx; -+ vpc->v.parse_only = 1; -+- vpc->v.first_pic_header_flag = 1; -+- next = buf; -+- s->repeat_pict = 0; -+- -+- for(start = buf, end = buf + buf_size; next < end; start = next){ -+- int buf2_size, size; -+- int ret; -+- -+- next = find_next_marker(start + 4, end); -+- size = next - start - 4; -+- buf2_size = vc1_unescape_buffer(start + 4, size, buf2); -+- init_get_bits(&gb, buf2, buf2_size * 8); -+- if(size <= 0) continue; -+- switch(AV_RB32(start)){ -+- case VC1_CODE_SEQHDR: -+- ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb); -+- break; -+- case VC1_CODE_ENTRYPOINT: -+- ff_vc1_decode_entry_point(avctx, &vpc->v, &gb); -+- break; -+- case VC1_CODE_FRAME: -+- if(vpc->v.profile < PROFILE_ADVANCED) -+- ret = ff_vc1_parse_frame_header (&vpc->v, &gb); -+- else -+- ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb); -+- -+- if (ret < 0) -+- break; -+- -+- /* keep AV_PICTURE_TYPE_BI internal to VC1 */ -+- if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI) -+- s->pict_type = AV_PICTURE_TYPE_B; -+- else -+- s->pict_type = vpc->v.s.pict_type; -+- -+- if (avctx->ticks_per_frame > 1){ -+- // process pulldown flags -+- s->repeat_pict = 1; -+- // Pulldown flags are only valid when 'broadcast' has been set. -+- // So ticks_per_frame will be 2 -+- if (vpc->v.rff){ -+- // repeat field -+- s->repeat_pict = 2; -+- }else if (vpc->v.rptfrm){ -+- // repeat frames -+- s->repeat_pict = vpc->v.rptfrm * 2 + 1; -+- } -+- } -+- -+- if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf) -+- s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB; -+- else -+- s->field_order = AV_FIELD_PROGRESSIVE; -++ init_get_bits(&gb, buf, buf_size * 8); -++ switch (vpc->prev_start_code) { -++ case VC1_CODE_SEQHDR & 0xFF: -++ ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb); -++ break; -++ case VC1_CODE_ENTRYPOINT & 0xFF: -++ ff_vc1_decode_entry_point(avctx, &vpc->v, &gb); -++ break; -++ case VC1_CODE_FRAME & 0xFF: -++ if(vpc->v.profile < PROFILE_ADVANCED) -++ ret = ff_vc1_parse_frame_header (&vpc->v, &gb); -++ else -++ ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb); -+ -++ if (ret < 0) -+ break; -+- } -+- } -+ -+- av_free(buf2); -+-} -++ /* keep AV_PICTURE_TYPE_BI internal to VC1 */ -++ if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI) -++ s->pict_type = AV_PICTURE_TYPE_B; -++ else -++ s->pict_type = vpc->v.s.pict_type; -+ -+-/** -+- * Find the end of the current frame in the bitstream. -+- * @return the position of the first byte of the next frame, or -1 -+- */ -+-static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf, -+- int buf_size) { -+- int pic_found, i; -+- uint32_t state; -+- -+- pic_found= pc->frame_start_found; -+- state= pc->state; -+- -+- i=0; -+- if(!pic_found){ -+- for(i=0; iticks_per_frame > 1){ -++ // process pulldown flags -++ s->repeat_pict = 1; -++ // Pulldown flags are only valid when 'broadcast' has been set. -++ // So ticks_per_frame will be 2 -++ if (vpc->v.rff){ -++ // repeat field -++ s->repeat_pict = 2; -++ }else if (vpc->v.rptfrm){ -++ // repeat frames -++ s->repeat_pict = vpc->v.rptfrm * 2 + 1; -+ } -++ }else{ -++ s->repeat_pict = 0; -+ } -+- } -+ -+- if(pic_found){ -+- /* EOF considered as end of frame */ -+- if (buf_size == 0) -+- return 0; -+- for(; iframe_start_found=0; -+- pc->state=-1; -+- return i-3; -+- } -+- } -++ if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf) -++ s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB; -++ else -++ s->field_order = AV_FIELD_PROGRESSIVE; -++ -++ break; -+ } -+- pc->frame_start_found= pic_found; -+- pc->state= state; -+- return END_NOT_FOUND; -+ } -+ -+ static int vc1_parse(AVCodecParserContext *s, -+@@ -153,22 +119,127 @@ static int vc1_parse(AVCodecParserContext *s, -+ const uint8_t **poutbuf, int *poutbuf_size, -+ const uint8_t *buf, int buf_size) -+ { -++ /* Here we do the searching for frame boundaries and headers at -++ * the same time. Only a minimal amount at the start of each -++ * header is unescaped. */ -+ VC1ParseContext *vpc = s->priv_data; -+- int next; -++ int pic_found = vpc->pc.frame_start_found; -++ uint8_t *unesc_buffer = vpc->unesc_buffer; -++ size_t unesc_index = vpc->unesc_index; -++ VC1ParseSearchState search_state = vpc->search_state; -++ int next = END_NOT_FOUND; -++ int i = vpc->bytes_to_skip; -++ -++ if (pic_found && buf_size == 0) { -++ /* EOF considered as end of frame */ -++ memset(unesc_buffer + unesc_index, 0, UNESCAPED_THRESHOLD - unesc_index); -++ vc1_extract_header(s, avctx, unesc_buffer, unesc_index); -++ next = 0; -++ } -++ while (i < buf_size) { -++ int start_code_found = 0; -++ uint8_t b; -++ while (i < buf_size && unesc_index < UNESCAPED_THRESHOLD) { -++ b = buf[i++]; -++ unesc_buffer[unesc_index++] = b; -++ if (search_state <= ONE_ZERO) -++ search_state = b ? NO_MATCH : search_state + 1; -++ else if (search_state == TWO_ZEROS) { -++ if (b == 1) -++ search_state = ONE; -++ else if (b > 1) { -++ if (b == 3) -++ unesc_index--; // swallow emulation prevention byte -++ search_state = NO_MATCH; -++ } -++ } -++ else { // search_state == ONE -++ // Header unescaping terminates early due to detection of next start code -++ search_state = NO_MATCH; -++ start_code_found = 1; -++ break; -++ } -++ } -++ if ((s->flags & PARSER_FLAG_COMPLETE_FRAMES) && -++ unesc_index >= UNESCAPED_THRESHOLD && -++ vpc->prev_start_code == (VC1_CODE_FRAME & 0xFF)) -++ { -++ // No need to keep scanning the rest of the buffer for -++ // start codes if we know it contains a complete frame and -++ // we've already unescaped all we need of the frame header -++ vc1_extract_header(s, avctx, unesc_buffer, unesc_index); -++ break; -++ } -++ if (unesc_index >= UNESCAPED_THRESHOLD && !start_code_found) { -++ while (i < buf_size) { -++ if (search_state == NO_MATCH) { -++ i += vpc->v.vc1dsp.vc1_find_start_code_candidate(buf + i, buf_size - i); -++ if (i < buf_size) { -++ search_state = ONE_ZERO; -++ } -++ i++; -++ } else { -++ b = buf[i++]; -++ if (search_state == ONE_ZERO) -++ search_state = b ? NO_MATCH : TWO_ZEROS; -++ else if (search_state == TWO_ZEROS) { -++ if (b >= 1) -++ search_state = b == 1 ? ONE : NO_MATCH; -++ } -++ else { // search_state == ONE -++ search_state = NO_MATCH; -++ start_code_found = 1; -++ break; -++ } -++ } -++ } -++ } -++ if (start_code_found) { -++ vc1_extract_header(s, avctx, unesc_buffer, unesc_index); -++ -++ vpc->prev_start_code = b; -++ unesc_index = 0; -++ -++ if (!(s->flags & PARSER_FLAG_COMPLETE_FRAMES)) { -++ if (!pic_found && (b == (VC1_CODE_FRAME & 0xFF) || b == (VC1_CODE_FIELD & 0xFF))) { -++ pic_found = 1; -++ } -++ else if (pic_found && b != (VC1_CODE_FIELD & 0xFF) && b != (VC1_CODE_SLICE & 0xFF)) { -++ next = i - 4; -++ pic_found = b == (VC1_CODE_FRAME & 0xFF); -++ break; -++ } -++ } -++ } -++ } -+ -+- if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ -+- next= buf_size; -+- }else{ -+- next= vc1_find_frame_end(&vpc->pc, buf, buf_size); -++ vpc->pc.frame_start_found = pic_found; -++ vpc->unesc_index = unesc_index; -++ vpc->search_state = search_state; -+ -++ if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { -++ next = buf_size; -++ } else { -+ if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) { -++ vpc->bytes_to_skip = 0; -+ *poutbuf = NULL; -+ *poutbuf_size = 0; -+ return buf_size; -+ } -+ } -+ -+- vc1_extract_headers(s, avctx, buf, buf_size); -++ vpc->v.first_pic_header_flag = 1; -++ -++ /* If we return with a valid pointer to a combined frame buffer -++ * then on the next call then we'll have been unhelpfully rewound -++ * by up to 4 bytes (depending upon whether the start code -++ * overlapped the input buffer, and if so by how much). We don't -++ * want this: it will either cause spurious second detections of -++ * the start code we've already seen, or cause extra bytes to be -++ * inserted at the start of the unescaped buffer. */ -++ vpc->bytes_to_skip = 4; -++ if (next < 0) -++ vpc->bytes_to_skip += next; -+ -+ *poutbuf = buf; -+ *poutbuf_size = buf_size; -+@@ -199,6 +270,11 @@ static av_cold int vc1_parse_init(AVCodecParserContext *s) -+ { -+ VC1ParseContext *vpc = s->priv_data; -+ vpc->v.s.slice_context_count = 1; -++ vpc->v.first_pic_header_flag = 1; -++ vpc->prev_start_code = 0; -++ vpc->bytes_to_skip = 0; -++ vpc->unesc_index = 0; -++ vpc->search_state = NO_MATCH; -+ return ff_vc1_init_common(&vpc->v); -+ } -+ -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile -index f514ae6..863ee41 100644 ---- a/tools/depends/target/ffmpeg/Makefile -+++ b/tools/depends/target/ffmpeg/Makefile -@@ -1,6 +1,9 @@ - include ../../Makefile.include - include FFMPEG-VERSION --DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch -+DEPS= ../../Makefile.include FFMPEG-VERSION Makefile \ -+ ffmpeg_Speed_up_wtv_index_creation.patch 0001-h264-Move-search-code-search-functions-into-separate.patch \ -+ 0002-vc-1-Add-platform-specific-start-code-search-routine.patch 0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch -+ - - # set to "yes" to enable patching - # we don't apply patches until we move to a vanilla ffmpeg tarball -@@ -64,6 +67,9 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) - cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) - cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig\npkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure - cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch -+ cd $(PLATFORM); patch -p1 < ../0001-h264-Move-search-code-search-functions-into-separate.patch -+ cd $(PLATFORM); patch -p1 < ../0002-vc-1-Add-platform-specific-start-code-search-routine.patch -+ cd $(PLATFORM); patch -p1 < ../0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch - cd $(PLATFORM);\ - CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ - ./configure $(ffmpg_config) --- -1.9.3 - - -From e3ac86b34ef35e0463c6475c03e653da70cdc3da Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 29 Apr 2014 16:53:32 +0100 -Subject: [PATCH 67/82] [ffmpeg] truehd: Optimise with special attention to ARM - -Backport from upstream ffmpeg ---- - .../0001-truehd-tune-VLC-decoding-for-ARM.patch | 65 ++ - ...hand-scheduled-ARM-asm-version-of-mlp_fil.patch | 557 +++++++++++++++++ - ...k-out-part-of-rematrix_channels-into-plat.patch | 158 +++++ - ...hand-scheduled-ARM-asm-version-of-ff_mlp_.patch | 285 +++++++++ - ...k-out-part-of-output_data-into-platform-s.patch | 197 ++++++ - ...hand-scheduled-ARM-asm-version-of-ff_mlp_.patch | 689 +++++++++++++++++++++ - tools/depends/target/ffmpeg/Makefile | 13 +- - 7 files changed, 1962 insertions(+), 2 deletions(-) - create mode 100644 tools/depends/target/ffmpeg/0001-truehd-tune-VLC-decoding-for-ARM.patch - create mode 100644 tools/depends/target/ffmpeg/0002-truehd-add-hand-scheduled-ARM-asm-version-of-mlp_fil.patch - create mode 100644 tools/depends/target/ffmpeg/0003-truehd-break-out-part-of-rematrix_channels-into-plat.patch - create mode 100644 tools/depends/target/ffmpeg/0004-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch - create mode 100644 tools/depends/target/ffmpeg/0005-truehd-break-out-part-of-output_data-into-platform-s.patch - create mode 100644 tools/depends/target/ffmpeg/0006-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch - -diff --git a/tools/depends/target/ffmpeg/0001-truehd-tune-VLC-decoding-for-ARM.patch b/tools/depends/target/ffmpeg/0001-truehd-tune-VLC-decoding-for-ARM.patch -new file mode 100644 -index 0000000..2950843 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0001-truehd-tune-VLC-decoding-for-ARM.patch -@@ -0,0 +1,65 @@ -+From 425d69b993d25489e4830766507d9d8f6c819802 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Wed, 19 Mar 2014 17:26:19 +0000 -+Subject: [PATCH 1/6] truehd: tune VLC decoding for ARM. -+ -+Profiling on a Raspberry Pi revealed the best performance to correspond -+with VLC_BITS = 5. Results for overall audio decode and the get_vlc2 function -+in particular are as follows: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+6:2 total 348.8 20.1 339.6 15.1 88.8% +2.7% (insignificant) -+6:2 function 38.1 8.1 26.4 4.1 100.0% +44.5% -+8:2 total 339.1 15.4 324.5 15.5 99.4% +4.5% -+8:2 function 33.8 7.0 27.3 5.6 99.7% +23.6% -+6:6 total 604.6 20.8 572.8 20.6 100.0% +5.6% -+6:6 function 95.8 8.4 68.9 8.2 100.0% +39.1% -+8:8 total 766.4 17.6 741.5 21.2 100.0% +3.4% -+8:8 function 106.0 11.4 86.1 9.9 100.0% +23.1% -+ -+Signed-off-by: Michael Niedermayer -+--- -+ libavcodec/mlpdec.c | 13 ++++++++++--- -+ 1 file changed, 10 insertions(+), 3 deletions(-) -+ -+diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c -+index 93ed552..cbd9000 100644 -+--- a/libavcodec/mlpdec.c -++++ b/libavcodec/mlpdec.c -+@@ -37,9 +37,16 @@ -+ #include "mlp_parser.h" -+ #include "mlpdsp.h" -+ #include "mlp.h" -++#include "config.h" -+ -+ /** number of bits used for VLC lookup - longest Huffman code is 9 */ -++#if ARCH_ARM == 1 -++#define VLC_BITS 5 -++#define VLC_STATIC_SIZE 64 -++#else -+ #define VLC_BITS 9 -++#define VLC_STATIC_SIZE 512 -++#endif -+ -+ typedef struct SubStream { -+ /// Set if a valid restart header has been read. Otherwise the substream cannot be decoded. -+@@ -193,13 +200,13 @@ static av_cold void init_static(void) -+ if (!huff_vlc[0].bits) { -+ INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18, -+ &ff_mlp_huffman_tables[0][0][1], 2, 1, -+- &ff_mlp_huffman_tables[0][0][0], 2, 1, 512); -++ &ff_mlp_huffman_tables[0][0][0], 2, 1, VLC_STATIC_SIZE); -+ INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16, -+ &ff_mlp_huffman_tables[1][0][1], 2, 1, -+- &ff_mlp_huffman_tables[1][0][0], 2, 1, 512); -++ &ff_mlp_huffman_tables[1][0][0], 2, 1, VLC_STATIC_SIZE); -+ INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15, -+ &ff_mlp_huffman_tables[2][0][1], 2, 1, -+- &ff_mlp_huffman_tables[2][0][0], 2, 1, 512); -++ &ff_mlp_huffman_tables[2][0][0], 2, 1, VLC_STATIC_SIZE); -+ } -+ -+ ff_mlp_init_crc(); -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0002-truehd-add-hand-scheduled-ARM-asm-version-of-mlp_fil.patch b/tools/depends/target/ffmpeg/0002-truehd-add-hand-scheduled-ARM-asm-version-of-mlp_fil.patch -new file mode 100644 -index 0000000..4aea35f ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0002-truehd-add-hand-scheduled-ARM-asm-version-of-mlp_fil.patch -@@ -0,0 +1,557 @@ -+From bfe3d8c8e4e046163dc314aa16207413e377283f Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Mon, 3 Mar 2014 19:44:23 +0000 -+Subject: [PATCH 2/6] truehd: add hand-scheduled ARM asm version of -+ mlp_filter_channel. -+ -+Profiling results for overall audio decode and the mlp_filter_channel(_arm) -+function in particular are as follows: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+6:2 total 380.4 22.0 370.8 17.0 87.4% +2.6% (insignificant) -+6:2 function 60.7 7.2 36.6 8.1 100.0% +65.8% -+8:2 total 357.0 17.5 343.2 19.0 97.8% +4.0% (insignificant) -+8:2 function 60.3 8.8 37.3 3.8 100.0% +61.8% -+6:6 total 717.2 23.2 658.4 15.7 100.0% +8.9% -+6:6 function 140.4 12.9 81.5 9.2 100.0% +72.4% -+8:8 total 981.9 16.2 896.2 24.5 100.0% +9.6% -+8:8 function 193.4 15.0 103.3 11.5 100.0% +87.2% -+ -+Experiments with adding preload instructions to this function yielded no -+useful benefit, so these have not been included. -+ -+The assembly version has also been tested with a fuzz tester to ensure that -+any combinations of inputs not exercised by my available test streams still -+generate mathematically identical results to the C version. -+--- -+ libavcodec/arm/Makefile | 2 + -+ libavcodec/arm/mlpdsp_arm.S | 433 +++++++++++++++++++++++++++++++++++++++ -+ libavcodec/arm/mlpdsp_init_arm.c | 36 ++++ -+ libavcodec/mlpdsp.c | 2 + -+ libavcodec/mlpdsp.h | 1 + -+ 5 files changed, 474 insertions(+) -+ create mode 100644 libavcodec/arm/mlpdsp_arm.S -+ create mode 100644 libavcodec/arm/mlpdsp_init_arm.c -+ -+diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile -+index a8446b2..ba673b1 100644 -+--- a/libavcodec/arm/Makefile -++++ b/libavcodec/arm/Makefile -+@@ -22,6 +22,8 @@ OBJS-$(CONFIG_H264PRED) += arm/h264pred_init_arm.o -+ OBJS-$(CONFIG_H264QPEL) += arm/h264qpel_init_arm.o -+ OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_arm.o \ -+ arm/hpeldsp_arm.o -++OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o \ -++ arm/mlpdsp_arm.o -+ OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_init_arm.o -+ OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_arm.o -+ OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o -+diff --git a/libavcodec/arm/mlpdsp_arm.S b/libavcodec/arm/mlpdsp_arm.S -+new file mode 100644 -+index 0000000..615819d -+--- /dev/null -++++ b/libavcodec/arm/mlpdsp_arm.S -+@@ -0,0 +1,433 @@ -++/* -++ * Copyright (c) 2014 RISC OS Open Ltd -++ * Author: Ben Avison -++ * -++ * This file is part of FFmpeg. -++ * -++ * FFmpeg is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU Lesser General Public -++ * License as published by the Free Software Foundation; either -++ * version 2.1 of the License, or (at your option) any later version. -++ * -++ * FFmpeg is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * Lesser General Public License for more details. -++ * -++ * You should have received a copy of the GNU Lesser General Public -++ * License along with FFmpeg; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++#include "libavutil/arm/asm.S" -++ -++#define MAX_CHANNELS 8 -++#define MAX_FIR_ORDER 8 -++#define MAX_IIR_ORDER 4 -++#define MAX_RATEFACTOR 4 -++#define MAX_BLOCKSIZE (40 * MAX_RATEFACTOR) -++ -++PST .req a1 -++PCO .req a2 -++AC0 .req a3 -++AC1 .req a4 -++CO0 .req v1 -++CO1 .req v2 -++CO2 .req v3 -++CO3 .req v4 -++ST0 .req v5 -++ST1 .req v6 -++ST2 .req sl -++ST3 .req fp -++I .req ip -++PSAMP .req lr -++ -++ -++// Some macros that do loads/multiplies where the register number is determined -++// from an assembly-time expression. Boy is GNU assembler's syntax ugly... -++ -++.macro load group, index, base, offset -++ .altmacro -++ load_ \group, %(\index), \base, \offset -++ .noaltmacro -++.endm -++ -++.macro load_ group, index, base, offset -++ ldr \group\index, [\base, #\offset] -++.endm -++ -++.macro loadd group, index, base, offset -++ .altmacro -++ loadd_ \group, %(\index), %(\index+1), \base, \offset -++ .noaltmacro -++.endm -++ -++.macro loadd_ group, index0, index1, base, offset -++A .if offset >= 256 -++A ldr \group\index0, [\base, #\offset] -++A ldr \group\index1, [\base, #(\offset) + 4] -++A .else -++ ldrd \group\index0, \group\index1, [\base, #\offset] -++A .endif -++.endm -++ -++.macro multiply index, accumulate, long -++ .altmacro -++ multiply_ %(\index), \accumulate, \long -++ .noaltmacro -++.endm -++ -++.macro multiply_ index, accumulate, long -++ .if \long -++ .if \accumulate -++ smlal AC0, AC1, CO\index, ST\index -++ .else -++ smull AC0, AC1, CO\index, ST\index -++ .endif -++ .else -++ .if \accumulate -++ mla AC0, CO\index, ST\index, AC0 -++ .else -++ mul AC0, CO\index, ST\index -++ .endif -++ .endif -++.endm -++ -++// A macro to update the load register number and load offsets -++ -++.macro inc howmany -++ .set LOAD_REG, (LOAD_REG + \howmany) & 3 -++ .set OFFSET_CO, OFFSET_CO + 4 * \howmany -++ .set OFFSET_ST, OFFSET_ST + 4 * \howmany -++ .if FIR_REMAIN > 0 -++ .set FIR_REMAIN, FIR_REMAIN - \howmany -++ .if FIR_REMAIN == 0 -++ .set OFFSET_CO, 4 * MAX_FIR_ORDER -++ .set OFFSET_ST, 4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER) -++ .endif -++ .elseif IIR_REMAIN > 0 -++ .set IIR_REMAIN, IIR_REMAIN - \howmany -++ .endif -++.endm -++ -++// Macro to implement the inner loop for one specific combination of parameters -++ -++.macro implement_filter mask_minus1, shift_0, shift_8, iir_taps, fir_taps -++ .set TOTAL_TAPS, \iir_taps + \fir_taps -++ -++ // Deal with register allocation... -++ .set DEFINED_SHIFT, 0 -++ .set DEFINED_MASK, 0 -++ .set SHUFFLE_SHIFT, 0 -++ .set SHUFFLE_MASK, 0 -++ .set SPILL_SHIFT, 0 -++ .set SPILL_MASK, 0 -++ .if TOTAL_TAPS == 0 -++ // Little register pressure in this case - just keep MASK where it was -++ .if !\mask_minus1 -++ MASK .req ST1 -++ .set DEFINED_MASK, 1 -++ .endif -++ .else -++ .if \shift_0 -++ .if !\mask_minus1 -++ // AC1 is unused with shift 0 -++ MASK .req AC1 -++ .set DEFINED_MASK, 1 -++ .set SHUFFLE_MASK, 1 -++ .endif -++ .elseif \shift_8 -++ .if !\mask_minus1 -++ .if TOTAL_TAPS <= 4 -++ // All coefficients are preloaded (so pointer not needed) -++ MASK .req PCO -++ .set DEFINED_MASK, 1 -++ .set SHUFFLE_MASK, 1 -++ .else -++ .set SPILL_MASK, 1 -++ .endif -++ .endif -++ .else // shift not 0 or 8 -++ .if TOTAL_TAPS <= 3 -++ // All coefficients are preloaded, and at least one CO register is unused -++ .if \fir_taps & 1 -++ SHIFT .req CO0 -++ .set DEFINED_SHIFT, 1 -++ .set SHUFFLE_SHIFT, 1 -++ .else -++ SHIFT .req CO3 -++ .set DEFINED_SHIFT, 1 -++ .set SHUFFLE_SHIFT, 1 -++ .endif -++ .if !\mask_minus1 -++ MASK .req PCO -++ .set DEFINED_MASK, 1 -++ .set SHUFFLE_MASK, 1 -++ .endif -++ .elseif TOTAL_TAPS == 4 -++ // All coefficients are preloaded -++ SHIFT .req PCO -++ .set DEFINED_SHIFT, 1 -++ .set SHUFFLE_SHIFT, 1 -++ .if !\mask_minus1 -++ .set SPILL_MASK, 1 -++ .endif -++ .else -++ .set SPILL_SHIFT, 1 -++ .if !\mask_minus1 -++ .set SPILL_MASK, 1 -++ .endif -++ .endif -++ .endif -++ .endif -++ .if SPILL_SHIFT -++ SHIFT .req ST0 -++ .set DEFINED_SHIFT, 1 -++ .endif -++ .if SPILL_MASK -++ MASK .req ST1 -++ .set DEFINED_MASK, 1 -++ .endif -++ -++ // Preload coefficients if possible -++ .if TOTAL_TAPS <= 4 -++ .set OFFSET_CO, 0 -++ .if \fir_taps & 1 -++ .set LOAD_REG, 1 -++ .else -++ .set LOAD_REG, 0 -++ .endif -++ .rept \fir_taps -++ load CO, LOAD_REG, PCO, OFFSET_CO -++ .set LOAD_REG, (LOAD_REG + 1) & 3 -++ .set OFFSET_CO, OFFSET_CO + 4 -++ .endr -++ .set OFFSET_CO, 4 * MAX_FIR_ORDER -++ .rept \iir_taps -++ load CO, LOAD_REG, PCO, OFFSET_CO -++ .set LOAD_REG, (LOAD_REG + 1) & 3 -++ .set OFFSET_CO, OFFSET_CO + 4 -++ .endr -++ .endif -++ -++ // Move mask/shift to final positions if necessary -++ // Need to do this after preloading, because in some cases we -++ // reuse the coefficient pointer register -++ .if SHUFFLE_SHIFT -++ mov SHIFT, ST0 -++ .endif -++ .if SHUFFLE_MASK -++ mov MASK, ST1 -++ .endif -++ -++ // Begin loop -++01: -++ .if TOTAL_TAPS == 0 -++ // Things simplify a lot in this case -++ // In fact this could be pipelined further if it's worth it... -++ ldr ST0, [PSAMP] -++ subs I, I, #1 -++ .if !\mask_minus1 -++ and ST0, ST0, MASK -++ .endif -++ str ST0, [PST, #-4]! -++ str ST0, [PST, #4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)] -++ str ST0, [PSAMP], #4 * MAX_CHANNELS -++ bne 01b -++ .else -++ .if \fir_taps & 1 -++ .set LOAD_REG, 1 -++ .else -++ .set LOAD_REG, 0 -++ .endif -++ .set LOAD_BANK, 0 -++ .set FIR_REMAIN, \fir_taps -++ .set IIR_REMAIN, \iir_taps -++ .if FIR_REMAIN == 0 // only IIR terms -++ .set OFFSET_CO, 4 * MAX_FIR_ORDER -++ .set OFFSET_ST, 4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER) -++ .else -++ .set OFFSET_CO, 0 -++ .set OFFSET_ST, 0 -++ .endif -++ .set MUL_REG, LOAD_REG -++ .set COUNTER, 0 -++ .rept TOTAL_TAPS + 2 -++ // Do load(s) -++ .if FIR_REMAIN != 0 || IIR_REMAIN != 0 -++ .if COUNTER == 0 -++ .if TOTAL_TAPS > 4 -++ load CO, LOAD_REG, PCO, OFFSET_CO -++ .endif -++ load ST, LOAD_REG, PST, OFFSET_ST -++ inc 1 -++ .elseif COUNTER == 1 && (\fir_taps & 1) == 0 -++ .if TOTAL_TAPS > 4 -++ load CO, LOAD_REG, PCO, OFFSET_CO -++ .endif -++ load ST, LOAD_REG, PST, OFFSET_ST -++ inc 1 -++ .elseif LOAD_BANK == 0 -++ .if TOTAL_TAPS > 4 -++ .if FIR_REMAIN == 0 && IIR_REMAIN == 1 -++ load CO, LOAD_REG, PCO, OFFSET_CO -++ .else -++ loadd CO, LOAD_REG, PCO, OFFSET_CO -++ .endif -++ .endif -++ .set LOAD_BANK, 1 -++ .else -++ .if FIR_REMAIN == 0 && IIR_REMAIN == 1 -++ load ST, LOAD_REG, PST, OFFSET_ST -++ inc 1 -++ .else -++ loadd ST, LOAD_REG, PST, OFFSET_ST -++ inc 2 -++ .endif -++ .set LOAD_BANK, 0 -++ .endif -++ .endif -++ -++ // Do interleaved multiplies, slightly delayed -++ .if COUNTER >= 2 -++ multiply MUL_REG, COUNTER > 2, !\shift_0 -++ .set MUL_REG, (MUL_REG + 1) & 3 -++ .endif -++ .set COUNTER, COUNTER + 1 -++ .endr -++ -++ // Post-process the result of the multiplies -++ .if SPILL_SHIFT -++ ldr SHIFT, [sp, #9*4 + 0*4] -++ .endif -++ .if SPILL_MASK -++ ldr MASK, [sp, #9*4 + 1*4] -++ .endif -++ ldr ST2, [PSAMP] -++ subs I, I, #1 -++ .if \shift_8 -++ mov AC0, AC0, lsr #8 -++ orr AC0, AC0, AC1, lsl #24 -++ .elseif !\shift_0 -++ rsb ST3, SHIFT, #32 -++ mov AC0, AC0, lsr SHIFT -++A orr AC0, AC0, AC1, lsl ST3 -++T mov AC1, AC1, lsl ST3 -++T orr AC0, AC0, AC1 -++ .endif -++ .if \mask_minus1 -++ add ST3, ST2, AC0 -++ .else -++ add ST2, ST2, AC0 -++ and ST3, ST2, MASK -++ sub ST2, ST3, AC0 -++ .endif -++ str ST3, [PST, #-4]! -++ str ST2, [PST, #4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)] -++ str ST3, [PSAMP], #4 * MAX_CHANNELS -++ bne 01b -++ .endif -++ b 99f -++ -++ .if DEFINED_SHIFT -++ .unreq SHIFT -++ .endif -++ .if DEFINED_MASK -++ .unreq MASK -++ .endif -++.endm -++ -++.macro switch_on_fir_taps mask_minus1, shift_0, shift_8, iir_taps -++A ldr pc, [pc, a3, LSL #2] // firorder is in range 0-(8-iir_taps) -++T tbh [pc, a3, lsl #1] -++0: -++A .word 0, 70f, 71f, 72f, 73f, 74f -++T .hword (70f - 0b) / 2, (71f - 0b) / 2, (72f - 0b) / 2, (73f - 0b) / 2, (74f - 0b) / 2 -++ .if \iir_taps <= 3 -++A .word 75f -++T .hword (75f - 0b) / 2 -++ .if \iir_taps <= 2 -++A .word 76f -++T .hword (76f - 0b) / 2 -++ .if \iir_taps <= 1 -++A .word 77f -++T .hword (77f - 0b) / 2 -++ .if \iir_taps == 0 -++A .word 78f -++T .hword (78f - 0b) / 2 -++ .endif -++ .endif -++ .endif -++ .endif -++70: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 0 -++71: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 1 -++72: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 2 -++73: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 3 -++74: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 4 -++ .if \iir_taps <= 3 -++75: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 5 -++ .if \iir_taps <= 2 -++76: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 6 -++ .if \iir_taps <= 1 -++77: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 7 -++ .if \iir_taps == 0 -++78: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 8 -++ .endif -++ .endif -++ .endif -++ .endif -++.endm -++ -++.macro switch_on_iir_taps mask_minus1, shift_0, shift_8 -++A ldr pc, [pc, a4, LSL #2] // irorder is in range 0-4 -++T tbh [pc, a4, lsl #1] -++0: -++A .word 0, 60f, 61f, 62f, 63f, 64f -++T .hword (60f - 0b) / 2, (61f - 0b) / 2, (62f - 0b) / 2, (63f - 0b) / 2, (64f - 0b) / 2 -++60: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 0 -++61: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 1 -++62: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 2 -++63: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 3 -++64: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 4 -++.endm -++ -++/* void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff, -++ * int firorder, int iirorder, -++ * unsigned int filter_shift, int32_t mask, -++ * int blocksize, int32_t *sample_buffer); -++ */ -++function ff_mlp_filter_channel_arm, export=1 -++ push {v1-fp,lr} -++ add v1, sp, #9*4 // point at arguments on stack -++ ldm v1, {ST0,ST1,I,PSAMP} -++ cmp ST1, #-1 -++ bne 30f -++ movs ST2, ST0, lsl #29 // shift is in range 0-15; we want to special-case 0 and 8 -++ bne 20f -++ bcs 10f -++ switch_on_iir_taps 1, 1, 0 -++10: switch_on_iir_taps 1, 0, 1 -++20: switch_on_iir_taps 1, 0, 0 -++30: movs ST2, ST0, lsl #29 // shift is in range 0-15; we want to special-case 0 and 8 -++ bne 50f -++ bcs 40f -++ switch_on_iir_taps 0, 1, 0 -++40: switch_on_iir_taps 0, 0, 1 -++50: switch_on_iir_taps 0, 0, 0 -++99: pop {v1-fp,pc} -++endfunc -++ -++ .unreq PST -++ .unreq PCO -++ .unreq AC0 -++ .unreq AC1 -++ .unreq CO0 -++ .unreq CO1 -++ .unreq CO2 -++ .unreq CO3 -++ .unreq ST0 -++ .unreq ST1 -++ .unreq ST2 -++ .unreq ST3 -++ .unreq I -++ .unreq PSAMP -+diff --git a/libavcodec/arm/mlpdsp_init_arm.c b/libavcodec/arm/mlpdsp_init_arm.c -+new file mode 100644 -+index 0000000..9a14815 -+--- /dev/null -++++ b/libavcodec/arm/mlpdsp_init_arm.c -+@@ -0,0 +1,36 @@ -++/* -++ * Copyright (c) 2014 RISC OS Open Ltd -++ * Author: Ben Avison -++ * -++ * This file is part of FFmpeg. -++ * -++ * FFmpeg is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU Lesser General Public -++ * License as published by the Free Software Foundation; either -++ * version 2.1 of the License, or (at your option) any later version. -++ * -++ * FFmpeg is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * Lesser General Public License for more details. -++ * -++ * You should have received a copy of the GNU Lesser General Public -++ * License along with FFmpeg; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++#include -++ -++#include "libavutil/arm/cpu.h" -++#include "libavutil/attributes.h" -++#include "libavcodec/mlpdsp.h" -++ -++void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff, -++ int firorder, int iirorder, -++ unsigned int filter_shift, int32_t mask, -++ int blocksize, int32_t *sample_buffer); -++ -++av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c) -++{ -++ c->mlp_filter_channel = ff_mlp_filter_channel_arm; -++} -+diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c -+index b413e86..4b403b8 100644 -+--- a/libavcodec/mlpdsp.c -++++ b/libavcodec/mlpdsp.c -+@@ -60,6 +60,8 @@ static void mlp_filter_channel(int32_t *state, const int32_t *coeff, -+ av_cold void ff_mlpdsp_init(MLPDSPContext *c) -+ { -+ c->mlp_filter_channel = mlp_filter_channel; -++ if (ARCH_ARM) -++ ff_mlpdsp_init_arm(c); -+ if (ARCH_X86) -+ ff_mlpdsp_init_x86(c); -+ } -+diff --git a/libavcodec/mlpdsp.h b/libavcodec/mlpdsp.h -+index 84a8aa3..129bcfe 100644 -+--- a/libavcodec/mlpdsp.h -++++ b/libavcodec/mlpdsp.h -+@@ -32,6 +32,7 @@ typedef struct MLPDSPContext { -+ } MLPDSPContext; -+ -+ void ff_mlpdsp_init(MLPDSPContext *c); -++void ff_mlpdsp_init_arm(MLPDSPContext *c); -+ void ff_mlpdsp_init_x86(MLPDSPContext *c); -+ -+ #endif /* AVCODEC_MLPDSP_H */ -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0003-truehd-break-out-part-of-rematrix_channels-into-plat.patch b/tools/depends/target/ffmpeg/0003-truehd-break-out-part-of-rematrix_channels-into-plat.patch -new file mode 100644 -index 0000000..9c06f8f ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0003-truehd-break-out-part-of-rematrix_channels-into-plat.patch -@@ -0,0 +1,158 @@ -+From bb74fc44081fb6d7923ce1b7ed3e3e6514695f3e Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Wed, 5 Mar 2014 21:01:28 +0000 -+Subject: [PATCH 3/6] truehd: break out part of rematrix_channels into -+ platform-specific callback. -+ -+Verified with profiling that this doesn't have a measurable effect upon -+overall performance. -+--- -+ libavcodec/mlpdec.c | 37 ++++++++++++------------------------- -+ libavcodec/mlpdsp.c | 33 +++++++++++++++++++++++++++++++++ -+ libavcodec/mlpdsp.h | 23 +++++++++++++++++++++++ -+ 3 files changed, 68 insertions(+), 25 deletions(-) -+ -+diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c -+index cbd9000..01ded5c 100644 -+--- a/libavcodec/mlpdec.c -++++ b/libavcodec/mlpdec.c -+@@ -1024,7 +1024,7 @@ static void fill_noise_buffer(MLPDecodeContext *m, unsigned int substr) -+ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) -+ { -+ SubStream *s = &m->substream[substr]; -+- unsigned int mat, src_ch, i; -++ unsigned int mat; -+ unsigned int maxchan; -+ -+ maxchan = s->max_matrix_channel; -+@@ -1036,31 +1036,18 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) -+ } -+ -+ for (mat = 0; mat < s->num_primitive_matrices; mat++) { -+- int matrix_noise_shift = s->matrix_noise_shift[mat]; -+ unsigned int dest_ch = s->matrix_out_ch[mat]; -+- int32_t mask = MSB_MASK(s->quant_step_size[dest_ch]); -+- int32_t *coeffs = s->matrix_coeff[mat]; -+- int index = s->num_primitive_matrices - mat; -+- int index2 = 2 * index + 1; -+- -+- /* TODO: DSPContext? */ -+- -+- for (i = 0; i < s->blockpos; i++) { -+- int32_t bypassed_lsb = m->bypassed_lsbs[i][mat]; -+- int32_t *samples = m->sample_buffer[i]; -+- int64_t accum = 0; -+- -+- for (src_ch = 0; src_ch <= maxchan; src_ch++) -+- accum += (int64_t) samples[src_ch] * coeffs[src_ch]; -+- -+- if (matrix_noise_shift) { -+- index &= m->access_unit_size_pow2 - 1; -+- accum += m->noise_buffer[index] << (matrix_noise_shift + 7); -+- index += index2; -+- } -+- -+- samples[dest_ch] = ((accum >> 14) & mask) + bypassed_lsb; -+- } -++ m->dsp.mlp_rematrix_channel(&m->sample_buffer[0][0], -++ s->matrix_coeff[mat], -++ &m->bypassed_lsbs[0][mat], -++ m->noise_buffer, -++ s->num_primitive_matrices - mat, -++ dest_ch, -++ s->blockpos, -++ maxchan, -++ s->matrix_noise_shift[mat], -++ m->access_unit_size_pow2, -++ MSB_MASK(s->quant_step_size[dest_ch])); -+ } -+ } -+ -+diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c -+index 4b403b8..7a359b0 100644 -+--- a/libavcodec/mlpdsp.c -++++ b/libavcodec/mlpdsp.c -+@@ -57,9 +57,42 @@ static void mlp_filter_channel(int32_t *state, const int32_t *coeff, -+ } -+ } -+ -++void ff_mlp_rematrix_channel(int32_t *samples, -++ const int32_t *coeffs, -++ const uint8_t *bypassed_lsbs, -++ const int8_t *noise_buffer, -++ int index, -++ unsigned int dest_ch, -++ uint16_t blockpos, -++ unsigned int maxchan, -++ int matrix_noise_shift, -++ int access_unit_size_pow2, -++ int32_t mask) -++{ -++ unsigned int src_ch, i; -++ int index2 = 2 * index + 1; -++ for (i = 0; i < blockpos; i++) { -++ int64_t accum = 0; -++ -++ for (src_ch = 0; src_ch <= maxchan; src_ch++) -++ accum += (int64_t) samples[src_ch] * coeffs[src_ch]; -++ -++ if (matrix_noise_shift) { -++ index &= access_unit_size_pow2 - 1; -++ accum += noise_buffer[index] << (matrix_noise_shift + 7); -++ index += index2; -++ } -++ -++ samples[dest_ch] = ((accum >> 14) & mask) + *bypassed_lsbs; -++ bypassed_lsbs += MAX_CHANNELS; -++ samples += MAX_CHANNELS; -++ } -++} -++ -+ av_cold void ff_mlpdsp_init(MLPDSPContext *c) -+ { -+ c->mlp_filter_channel = mlp_filter_channel; -++ c->mlp_rematrix_channel = ff_mlp_rematrix_channel; -+ if (ARCH_ARM) -+ ff_mlpdsp_init_arm(c); -+ if (ARCH_X86) -+diff --git a/libavcodec/mlpdsp.h b/libavcodec/mlpdsp.h -+index 129bcfe..f98e9be 100644 -+--- a/libavcodec/mlpdsp.h -++++ b/libavcodec/mlpdsp.h -+@@ -24,11 +24,34 @@ -+ -+ #include -+ -++void ff_mlp_rematrix_channel(int32_t *samples, -++ const int32_t *coeffs, -++ const uint8_t *bypassed_lsbs, -++ const int8_t *noise_buffer, -++ int index, -++ unsigned int dest_ch, -++ uint16_t blockpos, -++ unsigned int maxchan, -++ int matrix_noise_shift, -++ int access_unit_size_pow2, -++ int32_t mask); -++ -+ typedef struct MLPDSPContext { -+ void (*mlp_filter_channel)(int32_t *state, const int32_t *coeff, -+ int firorder, int iirorder, -+ unsigned int filter_shift, int32_t mask, -+ int blocksize, int32_t *sample_buffer); -++ void (*mlp_rematrix_channel)(int32_t *samples, -++ const int32_t *coeffs, -++ const uint8_t *bypassed_lsbs, -++ const int8_t *noise_buffer, -++ int index, -++ unsigned int dest_ch, -++ uint16_t blockpos, -++ unsigned int maxchan, -++ int matrix_noise_shift, -++ int access_unit_size_pow2, -++ int32_t mask); -+ } MLPDSPContext; -+ -+ void ff_mlpdsp_init(MLPDSPContext *c); -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0004-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch b/tools/depends/target/ffmpeg/0004-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch -new file mode 100644 -index 0000000..575622e ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0004-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch -@@ -0,0 +1,285 @@ -+From 98428a8cf593587b403076bb54b46cc70ed17ff2 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Mon, 10 Mar 2014 14:42:05 +0000 -+Subject: [PATCH 4/6] truehd: add hand-scheduled ARM asm version of -+ ff_mlp_rematrix_channel. -+ -+Profiling results for overall audio decode and the rematrix_channels function -+in particular are as follows: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+6:2 total 370.8 17.0 348.8 20.1 99.9% +6.3% -+6:2 function 46.4 8.4 45.8 6.6 18.0% +1.2% (insignificant) -+8:2 total 343.2 19.0 339.1 15.4 54.7% +1.2% (insignificant) -+8:2 function 38.9 3.9 40.2 6.9 52.4% -3.2% (insignificant) -+6:6 total 658.4 15.7 604.6 20.8 100.0% +8.9% -+6:6 function 109.0 8.7 59.5 5.4 100.0% +83.3% -+8:8 total 896.2 24.5 766.4 17.6 100.0% +16.9% -+8:8 function 223.4 12.8 93.8 5.0 100.0% +138.3% -+ -+The assembly version has also been tested with a fuzz tester to ensure that -+any combinations of inputs not exercised by my available test streams still -+generate mathematically identical results to the C version. -+--- -+ libavcodec/arm/mlpdsp_arm.S | 222 +++++++++++++++++++++++++++++++++++++++ -+ libavcodec/arm/mlpdsp_init_arm.c | 12 +++ -+ 2 files changed, 234 insertions(+) -+ -+diff --git a/libavcodec/arm/mlpdsp_arm.S b/libavcodec/arm/mlpdsp_arm.S -+index 615819d..9b51d0c 100644 -+--- a/libavcodec/arm/mlpdsp_arm.S -++++ b/libavcodec/arm/mlpdsp_arm.S -+@@ -431,3 +431,225 @@ endfunc -+ .unreq ST3 -+ .unreq I -+ .unreq PSAMP -++ -++/********************************************************************/ -++ -++PSA .req a1 // samples -++PCO .req a2 // coeffs -++PBL .req a3 // bypassed_lsbs -++INDEX .req a4 -++CO0 .req v1 -++CO1 .req v2 -++CO2 .req v3 -++CO3 .req v4 -++SA0 .req v5 -++SA1 .req v6 -++SA2 .req sl -++SA3 .req fp -++AC0 .req ip -++AC1 .req lr -++NOISE .req SA0 -++LSB .req SA1 -++DCH .req SA2 // dest_ch -++MASK .req SA3 -++ -++ // INDEX is used as follows: -++ // bits 0..6 index2 (values up to 17, but wider so that we can -++ // add to index field without needing to mask) -++ // bits 7..14 i (values up to 160) -++ // bit 15 underflow detect for i -++ // bits 25..31 (if access_unit_size_pow2 == 128) \ index -++ // bits 26..31 (if access_unit_size_pow2 == 64) / -++ -++.macro implement_rematrix shift, index_mask, mask_minus1, maxchan -++ .if \maxchan == 1 -++ // We can just leave the coefficients in registers in this case -++ ldrd CO0, CO1, [PCO] -++ .endif -++1: -++ .if \maxchan == 1 -++ ldrd SA0, SA1, [PSA] -++ smull AC0, AC1, CO0, SA0 -++ .elseif \maxchan == 5 -++ ldr CO0, [PCO, #0] -++ ldr SA0, [PSA, #0] -++ ldr CO1, [PCO, #4] -++ ldr SA1, [PSA, #4] -++ ldrd CO2, CO3, [PCO, #8] -++ smull AC0, AC1, CO0, SA0 -++ ldrd SA2, SA3, [PSA, #8] -++ smlal AC0, AC1, CO1, SA1 -++ ldrd CO0, CO1, [PCO, #16] -++ smlal AC0, AC1, CO2, SA2 -++ ldrd SA0, SA1, [PSA, #16] -++ smlal AC0, AC1, CO3, SA3 -++ smlal AC0, AC1, CO0, SA0 -++ .else // \maxchan == 7 -++ ldr CO2, [PCO, #0] -++ ldr SA2, [PSA, #0] -++ ldr CO3, [PCO, #4] -++ ldr SA3, [PSA, #4] -++ ldrd CO0, CO1, [PCO, #8] -++ smull AC0, AC1, CO2, SA2 -++ ldrd SA0, SA1, [PSA, #8] -++ smlal AC0, AC1, CO3, SA3 -++ ldrd CO2, CO3, [PCO, #16] -++ smlal AC0, AC1, CO0, SA0 -++ ldrd SA2, SA3, [PSA, #16] -++ smlal AC0, AC1, CO1, SA1 -++ ldrd CO0, CO1, [PCO, #24] -++ smlal AC0, AC1, CO2, SA2 -++ ldrd SA0, SA1, [PSA, #24] -++ smlal AC0, AC1, CO3, SA3 -++ smlal AC0, AC1, CO0, SA0 -++ .endif -++ ldm sp, {NOISE, DCH, MASK} -++ smlal AC0, AC1, CO1, SA1 -++ .if \shift != 0 -++ .if \index_mask == 63 -++ add NOISE, NOISE, INDEX, lsr #32-6 -++ ldrb LSB, [PBL], #MAX_CHANNELS -++ ldrsb NOISE, [NOISE] -++ add INDEX, INDEX, INDEX, lsl #32-6 -++ .else // \index_mask == 127 -++ add NOISE, NOISE, INDEX, lsr #32-7 -++ ldrb LSB, [PBL], #MAX_CHANNELS -++ ldrsb NOISE, [NOISE] -++ add INDEX, INDEX, INDEX, lsl #32-7 -++ .endif -++ sub INDEX, INDEX, #1<<7 -++ adds AC0, AC0, NOISE, lsl #\shift + 7 -++ adc AC1, AC1, NOISE, asr #31 -++ .else -++ ldrb LSB, [PBL], #MAX_CHANNELS -++ sub INDEX, INDEX, #1<<7 -++ .endif -++ add PSA, PSA, #MAX_CHANNELS*4 -++ mov AC0, AC0, lsr #14 -++ orr AC0, AC0, AC1, lsl #18 -++ .if !\mask_minus1 -++ and AC0, AC0, MASK -++ .endif -++ add AC0, AC0, LSB -++ tst INDEX, #1<<15 -++ str AC0, [PSA, DCH, lsl #2] // DCH is precompensated for the early increment of PSA -++ beq 1b -++ b 98f -++.endm -++ -++.macro switch_on_maxchan shift, index_mask, mask_minus1 -++ cmp v4, #5 -++ blo 51f -++ beq 50f -++ implement_rematrix \shift, \index_mask, \mask_minus1, 7 -++50: implement_rematrix \shift, \index_mask, \mask_minus1, 5 -++51: implement_rematrix \shift, \index_mask, \mask_minus1, 1 -++.endm -++ -++.macro switch_on_mask shift, index_mask -++ cmp sl, #-1 -++ bne 40f -++ switch_on_maxchan \shift, \index_mask, 1 -++40: switch_on_maxchan \shift, \index_mask, 0 -++.endm -++ -++.macro switch_on_au_size shift -++ .if \shift == 0 -++ switch_on_mask \shift, undefined -++ .else -++ teq v6, #64 -++ bne 30f -++ orr INDEX, INDEX, v1, lsl #32-6 -++ switch_on_mask \shift, 63 -++30: orr INDEX, INDEX, v1, lsl #32-7 -++ switch_on_mask \shift, 127 -++ .endif -++.endm -++ -++/* void ff_mlp_rematrix_channel_arm(int32_t *samples, -++ * const int32_t *coeffs, -++ * const uint8_t *bypassed_lsbs, -++ * const int8_t *noise_buffer, -++ * int index, -++ * unsigned int dest_ch, -++ * uint16_t blockpos, -++ * unsigned int maxchan, -++ * int matrix_noise_shift, -++ * int access_unit_size_pow2, -++ * int32_t mask); -++ */ -++function ff_mlp_rematrix_channel_arm, export=1 -++ push {v1-fp,lr} -++ add v1, sp, #9*4 // point at arguments on stack -++ ldm v1, {v1-sl} -++ teq v4, #1 -++ itt ne -++ teqne v4, #5 -++ teqne v4, #7 -++ bne 99f -++ teq v6, #64 -++ it ne -++ teqne v6, #128 -++ bne 99f -++ sub v2, v2, #MAX_CHANNELS -++ push {a4,v2,sl} // initialise NOISE,DCH,MASK; make sp dword-aligned -++ movs INDEX, v3, lsl #7 -++ beq 98f // just in case, do nothing if blockpos = 0 -++ subs INDEX, INDEX, #1<<7 // offset by 1 so we borrow at the right time -++ adc lr, v1, v1 // calculate index2 (C was set by preceding subs) -++ orr INDEX, INDEX, lr -++ // Switch on matrix_noise_shift: values 0 and 1 are -++ // disproportionately common so do those in a form the branch -++ // predictor can accelerate. Values can only go up to 15. -++ cmp v5, #1 -++ beq 11f -++ blo 10f -++A ldr pc, [pc, v5, lsl #2] -++T tbh [pc, v5, lsl #1] -++0: -++A .word 0, 0, 0, 12f, 13f, 14f, 15f, 16f, 17f, 18f, 19f, 20f, 21f, 22f, 23f, 24f, 25f -++T .hword 0, 0, (12f - 0b) / 2, (13f - 0b) / 2, (14f - 0b) / 2, (15f - 0b) / 2 -++T .hword (16f - 0b) / 2, (17f - 0b) / 2, (18f - 0b) / 2, (19f - 0b) / 2 -++T .hword (20f - 0b) / 2, (21f - 0b) / 2, (22f - 0b) / 2, (23f - 0b) / 2, (24f - 0b) / 2, (25f - 0b) / 2 -++10: switch_on_au_size 0 -++11: switch_on_au_size 1 -++12: switch_on_au_size 2 -++13: switch_on_au_size 3 -++14: switch_on_au_size 4 -++15: switch_on_au_size 5 -++16: switch_on_au_size 6 -++17: switch_on_au_size 7 -++18: switch_on_au_size 8 -++19: switch_on_au_size 9 -++20: switch_on_au_size 10 -++21: switch_on_au_size 11 -++22: switch_on_au_size 12 -++23: switch_on_au_size 13 -++24: switch_on_au_size 14 -++25: switch_on_au_size 15 -++ -++98: add sp, sp, #3*4 -++ pop {v1-fp,pc} -++99: // Can't handle these parameters, drop back to C -++ pop {v1-fp,lr} -++ b X(ff_mlp_rematrix_channel) -++endfunc -++ -++ .unreq PSA -++ .unreq PCO -++ .unreq PBL -++ .unreq INDEX -++ .unreq CO0 -++ .unreq CO1 -++ .unreq CO2 -++ .unreq CO3 -++ .unreq SA0 -++ .unreq SA1 -++ .unreq SA2 -++ .unreq SA3 -++ .unreq AC0 -++ .unreq AC1 -++ .unreq NOISE -++ .unreq LSB -++ .unreq DCH -++ .unreq MASK -+diff --git a/libavcodec/arm/mlpdsp_init_arm.c b/libavcodec/arm/mlpdsp_init_arm.c -+index 9a14815..1bb2276 100644 -+--- a/libavcodec/arm/mlpdsp_init_arm.c -++++ b/libavcodec/arm/mlpdsp_init_arm.c -+@@ -29,8 +29,20 @@ void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff, -+ int firorder, int iirorder, -+ unsigned int filter_shift, int32_t mask, -+ int blocksize, int32_t *sample_buffer); -++void ff_mlp_rematrix_channel_arm(int32_t *samples, -++ const int32_t *coeffs, -++ const uint8_t *bypassed_lsbs, -++ const int8_t *noise_buffer, -++ int index, -++ unsigned int dest_ch, -++ uint16_t blockpos, -++ unsigned int maxchan, -++ int matrix_noise_shift, -++ int access_unit_size_pow2, -++ int32_t mask); -+ -+ av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c) -+ { -+ c->mlp_filter_channel = ff_mlp_filter_channel_arm; -++ c->mlp_rematrix_channel = ff_mlp_rematrix_channel_arm; -+ } -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0005-truehd-break-out-part-of-output_data-into-platform-s.patch b/tools/depends/target/ffmpeg/0005-truehd-break-out-part-of-output_data-into-platform-s.patch -new file mode 100644 -index 0000000..c5880e9 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0005-truehd-break-out-part-of-output_data-into-platform-s.patch -@@ -0,0 +1,197 @@ -+From 5bfcb7a691eb63c56f1485b60f399d79ff943799 Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Wed, 12 Mar 2014 18:18:39 +0000 -+Subject: [PATCH 5/6] truehd: break out part of output_data into -+ platform-specific callback. -+ -+Verified with profiling that this doesn't have a measurable effect upon -+overall performance. -+--- -+ libavcodec/mlpdec.c | 40 +++++++++++++++++++++++----------------- -+ libavcodec/mlpdsp.c | 38 ++++++++++++++++++++++++++++++++++++++ -+ libavcodec/mlpdsp.h | 22 ++++++++++++++++++++++ -+ 3 files changed, 83 insertions(+), 17 deletions(-) -+ -+diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c -+index 01ded5c..061dabc 100644 -+--- a/libavcodec/mlpdec.c -++++ b/libavcodec/mlpdec.c -+@@ -363,6 +363,10 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) -+ m->avctx->sample_fmt = AV_SAMPLE_FMT_S32; -+ else -+ m->avctx->sample_fmt = AV_SAMPLE_FMT_S16; -++ m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(m->substream[m->max_decoded_substream].ch_assign, -++ m->substream[m->max_decoded_substream].output_shift, -++ m->substream[m->max_decoded_substream].max_matrix_channel, -++ m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); -+ -+ m->params_valid = 1; -+ for (substr = 0; substr < MAX_SUBSTREAMS; substr++) -+@@ -612,6 +616,10 @@ FF_ENABLE_DEPRECATION_WARNINGS -+ if (substr == m->max_decoded_substream) { -+ m->avctx->channels = s->max_matrix_channel + 1; -+ m->avctx->channel_layout = s->ch_layout; -++ m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, -++ s->output_shift, -++ s->max_matrix_channel, -++ m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); -+ -+ if (m->avctx->codec_id == AV_CODEC_ID_MLP && m->needs_reordering) { -+ if (m->avctx->channel_layout == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) || -+@@ -857,9 +865,15 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, -+ return ret; -+ -+ if (s->param_presence_flags & PARAM_OUTSHIFT) -+- if (get_bits1(gbp)) -++ if (get_bits1(gbp)) { -+ for (ch = 0; ch <= s->max_matrix_channel; ch++) -+ s->output_shift[ch] = get_sbits(gbp, 4); -++ if (substr == m->max_decoded_substream) -++ m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, -++ s->output_shift, -++ s->max_matrix_channel, -++ m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); -++ } -+ -+ if (s->param_presence_flags & PARAM_QUANTSTEP) -+ if (get_bits1(gbp)) -+@@ -1058,9 +1072,6 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, -+ { -+ AVCodecContext *avctx = m->avctx; -+ SubStream *s = &m->substream[substr]; -+- unsigned int i, out_ch = 0; -+- int32_t *data_32; -+- int16_t *data_16; -+ int ret; -+ int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); -+ -+@@ -1078,19 +1089,14 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, -+ frame->nb_samples = s->blockpos; -+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) -+ return ret; -+- data_32 = (int32_t *)frame->data[0]; -+- data_16 = (int16_t *)frame->data[0]; -+- -+- for (i = 0; i < s->blockpos; i++) { -+- for (out_ch = 0; out_ch <= s->max_matrix_channel; out_ch++) { -+- int mat_ch = s->ch_assign[out_ch]; -+- int32_t sample = m->sample_buffer[i][mat_ch] -+- << s->output_shift[mat_ch]; -+- s->lossless_check_data ^= (sample & 0xffffff) << mat_ch; -+- if (is32) *data_32++ = sample << 8; -+- else *data_16++ = sample >> 8; -+- } -+- } -++ s->lossless_check_data = m->dsp.mlp_pack_output(s->lossless_check_data, -++ s->blockpos, -++ m->sample_buffer, -++ frame->data[0], -++ s->ch_assign, -++ s->output_shift, -++ s->max_matrix_channel, -++ is32); -+ -+ /* Update matrix encoding side data */ -+ if ((ret = ff_side_data_update_matrix_encoding(frame, s->matrix_encoding)) < 0) -+diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c -+index 7a359b0..3ae8c37 100644 -+--- a/libavcodec/mlpdsp.c -++++ b/libavcodec/mlpdsp.c -+@@ -89,10 +89,48 @@ void ff_mlp_rematrix_channel(int32_t *samples, -+ } -+ } -+ -++static int32_t (*mlp_select_pack_output(uint8_t *ch_assign, -++ int8_t *output_shift, -++ uint8_t max_matrix_channel, -++ int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) -++{ -++ return ff_mlp_pack_output; -++} -++ -++int32_t ff_mlp_pack_output(int32_t lossless_check_data, -++ uint16_t blockpos, -++ int32_t (*sample_buffer)[MAX_CHANNELS], -++ void *data, -++ uint8_t *ch_assign, -++ int8_t *output_shift, -++ uint8_t max_matrix_channel, -++ int is32) -++{ -++ unsigned int i, out_ch = 0; -++ int32_t *data_32 = data; -++ int16_t *data_16 = data; -++ -++ for (i = 0; i < blockpos; i++) { -++ for (out_ch = 0; out_ch <= max_matrix_channel; out_ch++) { -++ int mat_ch = ch_assign[out_ch]; -++ int32_t sample = sample_buffer[i][mat_ch] -++ << output_shift[mat_ch]; -++ lossless_check_data ^= (sample & 0xffffff) << mat_ch; -++ if (is32) -++ *data_32++ = sample << 8; -++ else -++ *data_16++ = sample >> 8; -++ } -++ } -++ return lossless_check_data; -++} -++ -+ av_cold void ff_mlpdsp_init(MLPDSPContext *c) -+ { -+ c->mlp_filter_channel = mlp_filter_channel; -+ c->mlp_rematrix_channel = ff_mlp_rematrix_channel; -++ c->mlp_select_pack_output = mlp_select_pack_output; -++ c->mlp_pack_output = ff_mlp_pack_output; -+ if (ARCH_ARM) -+ ff_mlpdsp_init_arm(c); -+ if (ARCH_X86) -+diff --git a/libavcodec/mlpdsp.h b/libavcodec/mlpdsp.h -+index f98e9be..a0edeb7 100644 -+--- a/libavcodec/mlpdsp.h -++++ b/libavcodec/mlpdsp.h -+@@ -23,6 +23,7 @@ -+ #define AVCODEC_MLPDSP_H -+ -+ #include -++#include "mlp.h" -+ -+ void ff_mlp_rematrix_channel(int32_t *samples, -+ const int32_t *coeffs, -+@@ -36,6 +37,15 @@ void ff_mlp_rematrix_channel(int32_t *samples, -+ int access_unit_size_pow2, -+ int32_t mask); -+ -++int32_t ff_mlp_pack_output(int32_t lossless_check_data, -++ uint16_t blockpos, -++ int32_t (*sample_buffer)[MAX_CHANNELS], -++ void *data, -++ uint8_t *ch_assign, -++ int8_t *output_shift, -++ uint8_t max_matrix_channel, -++ int is32); -++ -+ typedef struct MLPDSPContext { -+ void (*mlp_filter_channel)(int32_t *state, const int32_t *coeff, -+ int firorder, int iirorder, -+@@ -52,6 +62,18 @@ typedef struct MLPDSPContext { -+ int matrix_noise_shift, -+ int access_unit_size_pow2, -+ int32_t mask); -++ int32_t (*(*mlp_select_pack_output)(uint8_t *ch_assign, -++ int8_t *output_shift, -++ uint8_t max_matrix_channel, -++ int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int); -++ int32_t (*mlp_pack_output)(int32_t lossless_check_data, -++ uint16_t blockpos, -++ int32_t (*sample_buffer)[MAX_CHANNELS], -++ void *data, -++ uint8_t *ch_assign, -++ int8_t *output_shift, -++ uint8_t max_matrix_channel, -++ int is32); -+ } MLPDSPContext; -+ -+ void ff_mlpdsp_init(MLPDSPContext *c); -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/0006-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch b/tools/depends/target/ffmpeg/0006-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch -new file mode 100644 -index 0000000..93add62 ---- /dev/null -+++ b/tools/depends/target/ffmpeg/0006-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch -@@ -0,0 +1,689 @@ -+From c647209386bd811cc1c33b4fc8ec17a00f8c8ded Mon Sep 17 00:00:00 2001 -+From: Ben Avison -+Date: Thu, 13 Mar 2014 00:21:55 +0000 -+Subject: [PATCH 6/6] truehd: add hand-scheduled ARM asm version of -+ ff_mlp_pack_output. -+ -+Profiling results for overall decode and the output_data function in -+particular are as follows: -+ -+ Before After -+ Mean StdDev Mean StdDev Confidence Change -+6:2 total 339.6 15.1 329.3 16.0 95.8% +3.1% (insignificant) -+6:2 function 24.6 6.0 9.9 3.1 100.0% +148.5% -+8:2 total 324.5 15.5 323.6 14.3 15.2% +0.3% (insignificant) -+8:2 function 20.4 3.9 9.9 3.4 100.0% +104.7% -+6:6 total 572.8 20.6 539.9 24.2 100.0% +6.1% -+6:6 function 54.5 5.6 16.0 3.8 100.0% +240.9% -+8:8 total 741.5 21.2 702.5 18.5 100.0% +5.6% -+8:8 function 63.9 7.6 18.4 4.8 100.0% +247.3% -+ -+The assembly version has also been tested with a fuzz tester to ensure that -+any combinations of inputs not exercised by my available test streams still -+generate mathematically identical results to the C version. -+--- -+ libavcodec/arm/Makefile | 1 + -+ libavcodec/arm/mlpdsp_armv6.S | 530 +++++++++++++++++++++++++++++++++++++++ -+ libavcodec/arm/mlpdsp_init_arm.c | 96 +++++++ -+ 3 files changed, 627 insertions(+) -+ create mode 100644 libavcodec/arm/mlpdsp_armv6.S -+ -+diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile -+index ba673b1..7b2f923 100644 -+--- a/libavcodec/arm/Makefile -++++ b/libavcodec/arm/Makefile -+@@ -52,6 +52,7 @@ ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o -+ ARMV6-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_armv6.o -+ ARMV6-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_armv6.o \ -+ arm/hpeldsp_armv6.o -++ARMV6-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv6.o -+ ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o -+ ARMV6-OBJS-$(CONFIG_VP8_DECODER) += arm/vp8_armv6.o \ -+ arm/vp8dsp_init_armv6.o \ -+diff --git a/libavcodec/arm/mlpdsp_armv6.S b/libavcodec/arm/mlpdsp_armv6.S -+new file mode 100644 -+index 0000000..05a2c85 -+--- /dev/null -++++ b/libavcodec/arm/mlpdsp_armv6.S -+@@ -0,0 +1,530 @@ -++/* -++ * Copyright (c) 2014 RISC OS Open Ltd -++ * Author: Ben Avison -++ * -++ * This file is part of FFmpeg. -++ * -++ * FFmpeg is free software; you can redistribute it and/or -++ * modify it under the terms of the GNU Lesser General Public -++ * License as published by the Free Software Foundation; either -++ * version 2.1 of the License, or (at your option) any later version. -++ * -++ * FFmpeg is distributed in the hope that it will be useful, -++ * but WITHOUT ANY WARRANTY; without even the implied warranty of -++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -++ * Lesser General Public License for more details. -++ * -++ * You should have received a copy of the GNU Lesser General Public -++ * License along with FFmpeg; if not, write to the Free Software -++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -++ */ -++ -++#include "libavutil/arm/asm.S" -++ -++.macro loadregoffsh2 group, index, base, offgroup, offindex -++ .altmacro -++ loadregoffsh2_ \group, %(\index), \base, \offgroup, %(\offindex) -++ .noaltmacro -++.endm -++ -++.macro loadregoffsh2_ group, index, base, offgroup, offindex -++ ldr \group\index, [\base, \offgroup\offindex, lsl #2] -++.endm -++ -++.macro eorlslreg check, data, group, index -++ .altmacro -++ eorlslreg_ \check, \data, \group, %(\index) -++ .noaltmacro -++.endm -++ -++.macro eorlslreg_ check, data, group, index -++ eor \check, \check, \data, lsl \group\index -++.endm -++ -++.macro decr_modulo var, by, modulus -++ .set \var, \var - \by -++ .if \var == 0 -++ .set \var, \modulus -++ .endif -++.endm -++ -++ .macro load_group1 size, channels, r0, r1, r2, r3, pointer_dead=0 -++ .if \size == 2 -++ ldrd \r0, \r1, [IN], #(\size + 8 - \channels) * 4 -++ .else // size == 4 -++ .if IDX1 > 4 || \channels==8 -++ ldm IN!, {\r0, \r1, \r2, \r3} -++ .else -++ ldm IN, {\r0, \r1, \r2, \r3} -++ .if !\pointer_dead -++ add IN, IN, #(4 + 8 - \channels) * 4 -++ .endif -++ .endif -++ .endif -++ decr_modulo IDX1, \size, \channels -++ .endm -++ -++ .macro load_group2 size, channels, r0, r1, r2, r3, pointer_dead=0 -++ .if \size == 2 -++ .if IDX1 > 2 -++ ldm IN!, {\r2, \r3} -++ .else -++//A .ifc \r2, ip -++//A .if \pointer_dead -++//A ldm IN, {\r2, \r3} -++//A .else -++//A ldr \r2, [IN], #4 -++//A ldr \r3, [IN], #(\size - 1 + 8 - \channels) * 4 -++//A .endif -++//A .else -++ ldrd \r2, \r3, [IN], #(\size + 8 - \channels) * 4 -++//A .endif -++ .endif -++ .endif -++ decr_modulo IDX1, \size, \channels -++ .endm -++ -++.macro implement_pack inorder, channels, shift -++.if \inorder -++.ifc \shift, mixed -++ -++CHECK .req a1 -++COUNT .req a2 -++IN .req a3 -++OUT .req a4 -++DAT0 .req v1 -++DAT1 .req v2 -++DAT2 .req v3 -++DAT3 .req v4 -++SHIFT0 .req v5 -++SHIFT1 .req v6 -++SHIFT2 .req sl -++SHIFT3 .req fp -++SHIFT4 .req ip -++SHIFT5 .req lr -++ -++ .macro output4words -++ .set SIZE_GROUP1, IDX1 -++ .if SIZE_GROUP1 > 4 -++ .set SIZE_GROUP1, 4 -++ .endif -++ .set SIZE_GROUP2, 4 - SIZE_GROUP1 -++ load_group1 SIZE_GROUP1, \channels, DAT0, DAT1, DAT2, DAT3 -++ load_group2 SIZE_GROUP2, \channels, DAT0, DAT1, DAT2, DAT3 -++ .if \channels == 2 -++ lsl DAT0, SHIFT0 -++ lsl DAT1, SHIFT1 -++ lsl DAT2, SHIFT0 -++ lsl DAT3, SHIFT1 -++ .elseif \channels == 6 -++ .if IDX2 == 6 -++ lsl DAT0, SHIFT0 -++ lsl DAT1, SHIFT1 -++ lsl DAT2, SHIFT2 -++ lsl DAT3, SHIFT3 -++ .elseif IDX2 == 2 -++ lsl DAT0, SHIFT4 -++ lsl DAT1, SHIFT5 -++ lsl DAT2, SHIFT0 -++ lsl DAT3, SHIFT1 -++ .else // IDX2 == 4 -++ lsl DAT0, SHIFT2 -++ lsl DAT1, SHIFT3 -++ lsl DAT2, SHIFT4 -++ lsl DAT3, SHIFT5 -++ .endif -++ .elseif \channels == 8 -++ .if IDX2 == 8 -++ uxtb SHIFT0, SHIFT4, ror #0 -++ uxtb SHIFT1, SHIFT4, ror #8 -++ uxtb SHIFT2, SHIFT4, ror #16 -++ uxtb SHIFT3, SHIFT4, ror #24 -++ .else -++ uxtb SHIFT0, SHIFT5, ror #0 -++ uxtb SHIFT1, SHIFT5, ror #8 -++ uxtb SHIFT2, SHIFT5, ror #16 -++ uxtb SHIFT3, SHIFT5, ror #24 -++ .endif -++ lsl DAT0, SHIFT0 -++ lsl DAT1, SHIFT1 -++ lsl DAT2, SHIFT2 -++ lsl DAT3, SHIFT3 -++ .endif -++ eor CHECK, CHECK, DAT0, lsr #8 - (\channels - IDX2) -++ eor CHECK, CHECK, DAT1, lsr #7 - (\channels - IDX2) -++ decr_modulo IDX2, 2, \channels -++ eor CHECK, CHECK, DAT2, lsr #8 - (\channels - IDX2) -++ eor CHECK, CHECK, DAT3, lsr #7 - (\channels - IDX2) -++ decr_modulo IDX2, 2, \channels -++ stm OUT!, {DAT0 - DAT3} -++ .endm -++ -++ .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 4) -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP * 4 -++ .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels -++ -++function ff_mlp_pack_output_inorder_\channels\()ch_mixedshift_armv6, export=1 -++ .if SAMPLES_PER_LOOP > 1 -++ tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice -++ bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not -++ .endif -++ teq COUNT, #0 -++ it eq -++ bxeq lr -++ push {v1-v6,sl,fp,lr} -++ ldr SHIFT0, [sp, #(9+1)*4] // get output_shift from stack -++ ldr SHIFT1, =0x08080808 -++ ldr SHIFT4, [SHIFT0] -++ .if \channels == 2 -++ uadd8 SHIFT4, SHIFT4, SHIFT1 // increase all shifts by 8 -++ uxtb SHIFT0, SHIFT4, ror #0 -++ uxtb SHIFT1, SHIFT4, ror #8 -++ .else -++ ldr SHIFT5, [SHIFT0, #4] -++ uadd8 SHIFT4, SHIFT4, SHIFT1 // increase all shifts by 8 -++ uadd8 SHIFT5, SHIFT5, SHIFT1 -++ .if \channels == 6 -++ uxtb SHIFT0, SHIFT4, ror #0 -++ uxtb SHIFT1, SHIFT4, ror #8 -++ uxtb SHIFT2, SHIFT4, ror #16 -++ uxtb SHIFT3, SHIFT4, ror #24 -++ uxtb SHIFT4, SHIFT5, ror #0 -++ uxtb SHIFT5, SHIFT5, ror #8 -++ .endif -++ .endif -++ .set IDX1, \channels -++ .set IDX2, \channels -++0: -++ .rept WORDS_PER_LOOP / 4 -++ output4words -++ .endr -++ subs COUNT, COUNT, #SAMPLES_PER_LOOP -++ bne 0b -++ pop {v1-v6,sl,fp,pc} -++ .ltorg -++endfunc -++ .purgem output4words -++ -++ .unreq CHECK -++ .unreq COUNT -++ .unreq IN -++ .unreq OUT -++ .unreq DAT0 -++ .unreq DAT1 -++ .unreq DAT2 -++ .unreq DAT3 -++ .unreq SHIFT0 -++ .unreq SHIFT1 -++ .unreq SHIFT2 -++ .unreq SHIFT3 -++ .unreq SHIFT4 -++ .unreq SHIFT5 -++ -++.else // not mixed -++ -++CHECK .req a1 -++COUNT .req a2 -++IN .req a3 -++OUT .req a4 -++DAT0 .req v1 -++DAT1 .req v2 -++DAT2 .req v3 -++DAT3 .req v4 -++DAT4 .req v5 -++DAT5 .req v6 -++DAT6 .req sl // use these rather than the otherwise unused -++DAT7 .req fp // ip and lr so that we can load them usinf LDRD -++ -++ .macro output4words tail, head, r0, r1, r2, r3, r4, r5, r6, r7, pointer_dead=0 -++ .if \head -++ .set SIZE_GROUP1, IDX1 -++ .if SIZE_GROUP1 > 4 -++ .set SIZE_GROUP1, 4 -++ .endif -++ .set SIZE_GROUP2, 4 - SIZE_GROUP1 -++ load_group1 SIZE_GROUP1, \channels, \r0, \r1, \r2, \r3, \pointer_dead -++ .endif -++ .if \tail -++ eor CHECK, CHECK, \r4, lsr #8 - (\channels - IDX2) -++ eor CHECK, CHECK, \r5, lsr #7 - (\channels - IDX2) -++ decr_modulo IDX2, 2, \channels -++ .endif -++ .if \head -++ load_group2 SIZE_GROUP2, \channels, \r0, \r1, \r2, \r3, \pointer_dead -++ .endif -++ .if \tail -++ eor CHECK, CHECK, \r6, lsr #8 - (\channels - IDX2) -++ eor CHECK, CHECK, \r7, lsr #7 - (\channels - IDX2) -++ decr_modulo IDX2, 2, \channels -++ stm OUT!, {\r4, \r5, \r6, \r7} -++ .endif -++ .if \head -++ lsl \r0, #8 + \shift -++ lsl \r1, #8 + \shift -++ lsl \r2, #8 + \shift -++ lsl \r3, #8 + \shift -++ .endif -++ .endm -++ -++ .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 8) -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP * 8 -++ .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels -++ -++function ff_mlp_pack_output_inorder_\channels\()ch_\shift\()shift_armv6, export=1 -++ .if SAMPLES_PER_LOOP > 1 -++ tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice -++ bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not -++ .endif -++ subs COUNT, COUNT, #SAMPLES_PER_LOOP -++ it lo -++ bxlo lr -++ push {v1-v6,sl,fp,lr} -++ .set IDX1, \channels -++ .set IDX2, \channels -++ output4words 0, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 -++0: beq 1f -++ .rept WORDS_PER_LOOP / 8 -++ output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3 -++ output4words 1, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 -++ .endr -++ subs COUNT, COUNT, #SAMPLES_PER_LOOP -++ bne 0b -++1: -++ .rept WORDS_PER_LOOP / 8 - 1 -++ output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3 -++ output4words 1, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 -++ .endr -++ output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3, pointer_dead=1 -++ output4words 1, 0, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7 -++ pop {v1-v6,sl,fp,pc} -++endfunc -++ .purgem output4words -++ -++ .unreq CHECK -++ .unreq COUNT -++ .unreq IN -++ .unreq OUT -++ .unreq DAT0 -++ .unreq DAT1 -++ .unreq DAT2 -++ .unreq DAT3 -++ .unreq DAT4 -++ .unreq DAT5 -++ .unreq DAT6 -++ .unreq DAT7 -++ -++.endif // mixed -++.else // not inorder -++.ifc \shift, mixed -++ -++// This case not currently handled -++ -++.else // not mixed -++ -++#if !CONFIG_THUMB -++ -++CHECK .req a1 -++COUNT .req a2 -++IN .req a3 -++OUT .req a4 -++DAT0 .req v1 -++DAT1 .req v2 -++DAT2 .req v3 -++DAT3 .req v4 -++CHAN0 .req v5 -++CHAN1 .req v6 -++CHAN2 .req sl -++CHAN3 .req fp -++CHAN4 .req ip -++CHAN5 .req lr -++ -++ .macro output4words -++ .if \channels == 8 -++ .if IDX1 == 8 -++ uxtb CHAN0, CHAN4, ror #0 -++ uxtb CHAN1, CHAN4, ror #8 -++ uxtb CHAN2, CHAN4, ror #16 -++ uxtb CHAN3, CHAN4, ror #24 -++ .else -++ uxtb CHAN0, CHAN5, ror #0 -++ uxtb CHAN1, CHAN5, ror #8 -++ uxtb CHAN2, CHAN5, ror #16 -++ uxtb CHAN3, CHAN5, ror #24 -++ .endif -++ ldr DAT0, [IN, CHAN0, lsl #2] -++ ldr DAT1, [IN, CHAN1, lsl #2] -++ ldr DAT2, [IN, CHAN2, lsl #2] -++ ldr DAT3, [IN, CHAN3, lsl #2] -++ .if IDX1 == 4 -++ add IN, IN, #8*4 -++ .endif -++ decr_modulo IDX1, 4, \channels -++ .else -++ .set SIZE_GROUP1, IDX1 -++ .if SIZE_GROUP1 > 4 -++ .set SIZE_GROUP1, 4 -++ .endif -++ .set SIZE_GROUP2, 4 - SIZE_GROUP1 -++ .if SIZE_GROUP1 == 2 -++ loadregoffsh2 DAT, 0, IN, CHAN, 0 + (\channels - IDX1) -++ loadregoffsh2 DAT, 1, IN, CHAN, 1 + (\channels - IDX1) -++ add IN, IN, #8*4 -++ .else // SIZE_GROUP1 == 4 -++ loadregoffsh2 DAT, 0, IN, CHAN, 0 + (\channels - IDX1) -++ loadregoffsh2 DAT, 1, IN, CHAN, 1 + (\channels - IDX1) -++ loadregoffsh2 DAT, 2, IN, CHAN, 2 + (\channels - IDX1) -++ loadregoffsh2 DAT, 3, IN, CHAN, 3 + (\channels - IDX1) -++ .if IDX1 == 4 -++ add IN, IN, #8*4 -++ .endif -++ .endif -++ decr_modulo IDX1, SIZE_GROUP1, \channels -++ .if SIZE_GROUP2 == 2 -++ loadregoffsh2 DAT, 2, IN, CHAN, 0 + (\channels - IDX1) -++ loadregoffsh2 DAT, 3, IN, CHAN, 1 + (\channels - IDX1) -++ .if IDX1 == 2 -++ add IN, IN, #8*4 -++ .endif -++ .endif -++ decr_modulo IDX1, SIZE_GROUP2, \channels -++ .endif -++ .if \channels == 8 // in this case we can corrupt CHAN0-3 -++ rsb CHAN0, CHAN0, #8 -++ rsb CHAN1, CHAN1, #8 -++ rsb CHAN2, CHAN2, #8 -++ rsb CHAN3, CHAN3, #8 -++ lsl DAT0, #8 + \shift -++ lsl DAT1, #8 + \shift -++ lsl DAT2, #8 + \shift -++ lsl DAT3, #8 + \shift -++ eor CHECK, CHECK, DAT0, lsr CHAN0 -++ eor CHECK, CHECK, DAT1, lsr CHAN1 -++ eor CHECK, CHECK, DAT2, lsr CHAN2 -++ eor CHECK, CHECK, DAT3, lsr CHAN3 -++ .else -++ .if \shift != 0 -++ lsl DAT0, #\shift -++ lsl DAT1, #\shift -++ lsl DAT2, #\shift -++ lsl DAT3, #\shift -++ .endif -++ bic DAT0, DAT0, #0xff000000 -++ bic DAT1, DAT1, #0xff000000 -++ bic DAT2, DAT2, #0xff000000 -++ bic DAT3, DAT3, #0xff000000 -++ eorlslreg CHECK, DAT0, CHAN, 0 + (\channels - IDX2) -++ eorlslreg CHECK, DAT1, CHAN, 1 + (\channels - IDX2) -++ decr_modulo IDX2, 2, \channels -++ eorlslreg CHECK, DAT2, CHAN, 0 + (\channels - IDX2) -++ eorlslreg CHECK, DAT3, CHAN, 1 + (\channels - IDX2) -++ decr_modulo IDX2, 2, \channels -++ lsl DAT0, #8 -++ lsl DAT1, #8 -++ lsl DAT2, #8 -++ lsl DAT3, #8 -++ .endif -++ stm OUT!, {DAT0 - DAT3} -++ .endm -++ -++ .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 4) -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .if (WORDS_PER_LOOP % 2) == 0 -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2 -++ .endif -++ .set WORDS_PER_LOOP, WORDS_PER_LOOP * 4 -++ .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels -++ -++function ff_mlp_pack_output_outoforder_\channels\()ch_\shift\()shift_armv6, export=1 -++ .if SAMPLES_PER_LOOP > 1 -++ tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice -++ bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not -++ .endif -++ teq COUNT, #0 -++ it eq -++ bxeq lr -++ push {v1-v6,sl,fp,lr} -++ ldr CHAN0, [sp, #(9+0)*4] // get ch_assign from stack -++ ldr CHAN4, [CHAN0] -++ .if \channels == 2 -++ uxtb CHAN0, CHAN4, ror #0 -++ uxtb CHAN1, CHAN4, ror #8 -++ .else -++ ldr CHAN5, [CHAN0, #4] -++ .if \channels == 6 -++ uxtb CHAN0, CHAN4, ror #0 -++ uxtb CHAN1, CHAN4, ror #8 -++ uxtb CHAN2, CHAN4, ror #16 -++ uxtb CHAN3, CHAN4, ror #24 -++ uxtb CHAN4, CHAN5, ror #0 -++ uxtb CHAN5, CHAN5, ror #8 -++ .endif -++ .endif -++ .set IDX1, \channels -++ .set IDX2, \channels -++0: -++ .rept WORDS_PER_LOOP / 4 -++ output4words -++ .endr -++ subs COUNT, COUNT, #SAMPLES_PER_LOOP -++ bne 0b -++ pop {v1-v6,sl,fp,pc} -++ .ltorg -++endfunc -++ .purgem output4words -++ -++ .unreq CHECK -++ .unreq COUNT -++ .unreq IN -++ .unreq OUT -++ .unreq DAT0 -++ .unreq DAT1 -++ .unreq DAT2 -++ .unreq DAT3 -++ .unreq CHAN0 -++ .unreq CHAN1 -++ .unreq CHAN2 -++ .unreq CHAN3 -++ .unreq CHAN4 -++ .unreq CHAN5 -++ -++#endif // !CONFIG_THUMB -++ -++.endif // mixed -++.endif // inorder -++.endm // implement_pack -++ -++.macro pack_channels inorder, channels -++ implement_pack \inorder, \channels, 0 -++ implement_pack \inorder, \channels, 1 -++ implement_pack \inorder, \channels, 2 -++ implement_pack \inorder, \channels, 3 -++ implement_pack \inorder, \channels, 4 -++ implement_pack \inorder, \channels, 5 -++ implement_pack \inorder, \channels, mixed -++.endm -++ -++.macro pack_order inorder -++ pack_channels \inorder, 2 -++ pack_channels \inorder, 6 -++ pack_channels \inorder, 8 -++.endm -++ -++ pack_order 0 -++ pack_order 1 -+diff --git a/libavcodec/arm/mlpdsp_init_arm.c b/libavcodec/arm/mlpdsp_init_arm.c -+index 1bb2276..10ec316 100644 -+--- a/libavcodec/arm/mlpdsp_init_arm.c -++++ b/libavcodec/arm/mlpdsp_init_arm.c -+@@ -41,8 +41,104 @@ void ff_mlp_rematrix_channel_arm(int32_t *samples, -+ int access_unit_size_pow2, -+ int32_t mask); -+ -++#define DECLARE_PACK(order,channels,shift) \ -++ int32_t ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_armv6(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int); -++#define ENUMERATE_PACK(order,channels,shift) \ -++ ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_armv6, -++#define PACK_CHANNELS(macro,order,channels) \ -++ macro(order,channels,0) \ -++ macro(order,channels,1) \ -++ macro(order,channels,2) \ -++ macro(order,channels,3) \ -++ macro(order,channels,4) \ -++ macro(order,channels,5) \ -++ macro(order,channels,mixed) -++#define PACK_ORDER(macro,order) \ -++ PACK_CHANNELS(macro,order,2) \ -++ PACK_CHANNELS(macro,order,6) \ -++ PACK_CHANNELS(macro,order,8) -++#define PACK_ALL(macro) \ -++ PACK_ORDER(macro,outof) \ -++ PACK_ORDER(macro,in) -++PACK_ALL(DECLARE_PACK) -++ -++#define ff_mlp_pack_output_outoforder_2ch_mixedshift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_mixedshift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_mixedshift_armv6 0 -++#if CONFIG_THUMB -++#define ff_mlp_pack_output_outoforder_2ch_0shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_2ch_1shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_2ch_2shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_2ch_3shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_2ch_4shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_2ch_5shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_0shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_1shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_2shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_3shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_4shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_6ch_5shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_0shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_1shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_2shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_3shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_4shift_armv6 0 -++#define ff_mlp_pack_output_outoforder_8ch_5shift_armv6 0 -++#endif -++ -++static int32_t (*mlp_select_pack_output_armv6(uint8_t *ch_assign, -++ int8_t *output_shift, -++ uint8_t max_matrix_channel, -++ int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) -++{ -++ int ch_index; -++ int shift = output_shift[0] < 0 || output_shift[0] > 5 ? 6 : output_shift[0]; -++ int inorder = 1; -++ static int32_t (*const routine[2*3*7])(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) = { -++ PACK_ALL(ENUMERATE_PACK) -++ }; -++ int i; -++ -++ if (!is32) // don't support 16-bit output (it's not used by TrueHD) -++ return ff_mlp_pack_output; -++ -++ switch (max_matrix_channel) { -++ case 1: -++ ch_index = 0; -++ break; -++ case 5: -++ ch_index = 1; -++ break; -++ case 7: -++ ch_index = 2; -++ break; -++ default: -++ return ff_mlp_pack_output; -++ } -++ -++ for (i = 0; i <= max_matrix_channel; i++) { -++ if (shift != 6 && output_shift[i] != shift) -++ shift = 6; // indicate mixed shifts -++ if (ch_assign[i] != i) -++ inorder = 0; -++ } -++#if CONFIG_THUMB -++ if (!inorder) -++ return ff_mlp_pack_output; // can't currently handle an order array except in ARM mode -++#else -++ if (shift == 6 && !inorder) -++ return ff_mlp_pack_output; // can't currently handle both an order array and a shift array -++#endif -++ -++ return routine[(inorder*3+ch_index)*7+shift]; -++} -++ -+ av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c) -+ { -++ int cpu_flags = av_get_cpu_flags(); -++ -+ c->mlp_filter_channel = ff_mlp_filter_channel_arm; -+ c->mlp_rematrix_channel = ff_mlp_rematrix_channel_arm; -++ if (cpu_flags & AV_CPU_FLAG_ARMV6) -++ c->mlp_select_pack_output = mlp_select_pack_output_armv6; -+ } -+-- -+1.9.1 -diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile -index 863ee41..b56fbdd 100644 ---- a/tools/depends/target/ffmpeg/Makefile -+++ b/tools/depends/target/ffmpeg/Makefile -@@ -2,8 +2,10 @@ include ../../Makefile.include - include FFMPEG-VERSION - DEPS= ../../Makefile.include FFMPEG-VERSION Makefile \ - ffmpeg_Speed_up_wtv_index_creation.patch 0001-h264-Move-search-code-search-functions-into-separate.patch \ -- 0002-vc-1-Add-platform-specific-start-code-search-routine.patch 0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch -- -+ 0002-vc-1-Add-platform-specific-start-code-search-routine.patch 0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch \ -+ 0001-truehd-tune-VLC-decoding-for-ARM.patch 0002-truehd-add-hand-scheduled-ARM-asm-version-of-mlp_fil.patch \ -+ 0003-truehd-break-out-part-of-rematrix_channels-into-plat.patch 0004-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch \ -+ 0005-truehd-break-out-part-of-output_data-into-platform-s.patch 0006-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch - - # set to "yes" to enable patching - # we don't apply patches until we move to a vanilla ffmpeg tarball -@@ -70,6 +72,13 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) - cd $(PLATFORM); patch -p1 < ../0001-h264-Move-search-code-search-functions-into-separate.patch - cd $(PLATFORM); patch -p1 < ../0002-vc-1-Add-platform-specific-start-code-search-routine.patch - cd $(PLATFORM); patch -p1 < ../0003-vc-1-Optimise-parser-with-special-attention-to-ARM.patch -+ cd $(PLATFORM); patch -p1 < ../0001-truehd-tune-VLC-decoding-for-ARM.patch -+ cd $(PLATFORM); patch -p1 < ../0002-truehd-add-hand-scheduled-ARM-asm-version-of-mlp_fil.patch -+ cd $(PLATFORM); patch -p1 < ../0003-truehd-break-out-part-of-rematrix_channels-into-plat.patch -+ cd $(PLATFORM); patch -p1 < ../0004-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch -+ cd $(PLATFORM); patch -p1 < ../0005-truehd-break-out-part-of-output_data-into-platform-s.patch -+ cd $(PLATFORM); patch -p1 < ../0006-truehd-add-hand-scheduled-ARM-asm-version-of-ff_mlp_.patch -+ - cd $(PLATFORM);\ - CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ - ./configure $(ffmpg_config) --- -1.9.3 - - -From 53d16d23e1b49769b5385646b81dcd0f089b0f4d Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 11 May 2014 16:13:45 +0100 -Subject: [PATCH 68/82] [rbp] Add config.txt settings to log file - ---- - xbmc/linux/RBP.cpp | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp -index 49dcbb8..9a5e9cb 100644 ---- a/xbmc/linux/RBP.cpp -+++ b/xbmc/linux/RBP.cpp -@@ -79,11 +79,17 @@ bool CRBP::Initialize() - - void CRBP::LogFirmwareVerison() - { -- char response[160]; -+ char response[1024]; - m_DllBcmHost->vc_gencmd(response, sizeof response, "version"); - response[sizeof(response) - 1] = '\0'; - CLog::Log(LOGNOTICE, "Raspberry PI firmware version: %s", response); - CLog::Log(LOGNOTICE, "ARM mem: %dMB GPU mem: %dMB MPG2:%d WVC1:%d", m_arm_mem, m_gpu_mem, m_codec_mpg2_enabled, m_codec_wvc1_enabled); -+ m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config int"); -+ response[sizeof(response) - 1] = '\0'; -+ CLog::Log(LOGNOTICE, "Config:\n%s", response); -+ m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config str"); -+ response[sizeof(response) - 1] = '\0'; -+ CLog::Log(LOGNOTICE, "Config:\n%s", response); - } - - void CRBP::GetDisplaySize(int &width, int &height) --- -1.9.3 - - -From 72025619f8b7a33a20028ca959ece3bea2716ec8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 12 May 2014 23:06:43 +0100 -Subject: [PATCH 69/82] [omxcodec] Updates to work better with dropping and - lateness detection - ---- - .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 5 ++ - .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 1 + - .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 97 +++++++++++++++++----- - .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 9 +- - 4 files changed, 86 insertions(+), 26 deletions(-) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -index ef10555..8323497 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp -@@ -91,4 +91,9 @@ bool CDVDVideoCodecOpenMax::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - return m_omx_decoder->ClearPicture(pDvdVideoPicture); - } - -+bool CDVDVideoCodecOpenMax::GetCodecStats(double &pts, int &droppedPics) -+{ -+ return m_omx_decoder->GetCodecStats(pts, droppedPics); -+} -+ - #endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -index b7c0c1b..4f243df 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h -@@ -41,6 +41,7 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec - virtual unsigned GetAllowedReferences(); - virtual void SetDropState(bool bDrop); - virtual const char* GetName(void); -+ virtual bool GetCodecStats(double &pts, int &droppedPics); - - protected: - OpenMaxVideoPtr m_omx_decoder; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index 71d19af..612ae21 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -37,6 +37,7 @@ - #include "ApplicationMessenger.h" - #include "Application.h" - #include "threads/Atomics.h" -+#include "guilib/GUIWindowManager.h" - - #include - #include -@@ -57,6 +58,7 @@ - - #define OMX_BUFFERFLAG_PTS_INVALID (1<<28) - #define OMX_BUFFERFLAG_DROPPED (1<<29) -+#define OMX_BUFFERFLAG_FIRST_FIELD (1<<30) - - COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv) - : m_omv(omv), m_refs(0) -@@ -139,8 +141,11 @@ COpenMaxVideo::COpenMaxVideo() - - m_deinterlace = false; - m_deinterlace_request = VS_DEINTERLACEMODE_OFF; -- m_deinterlace_second_field = false; - m_startframe = false; -+ m_decoderPts = DVD_NOPTS_VALUE; -+ m_droppedPics = 0; -+ m_decode_frame_number = 1; -+ m_skipDeinterlaceFields = false; - } - - COpenMaxVideo::~COpenMaxVideo() -@@ -369,7 +374,10 @@ void COpenMaxVideo::Dispose() - m_finished = true; - pthread_mutex_unlock(&m_omx_output_mutex); - if (done) -+ { -+ assert(m_dts_queue.empty()); - m_myself.reset(); -+ } - } - - void COpenMaxVideo::SetDropState(bool bDrop) -@@ -730,6 +738,7 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; - omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); - omx_buffer->pAppPrivate = omx_buffer; -+ omx_buffer->pMarkData = (OMX_PTR)m_decode_frame_number; - memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); - - demuxer_bytes -= omx_buffer->nFilledLen; -@@ -742,12 +751,18 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; - if (pts == DVD_NOPTS_VALUE) // hijack an omx flag to indicate there wasn't a real timestamp - it will be returned with the picture (but otherwise ignored) - omx_buffer->nFlags |= OMX_BUFFERFLAG_PTS_INVALID; -- if (m_drop_state) // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored) -+ if (m_drop_state) -+ { -+ // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored) - omx_buffer->nFlags |= OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED; -+ m_droppedPics += m_deinterlace ? 2:1; -+ } -+ // always set this flag on input. It won't be set on second field of interlaced video. -+ omx_buffer->nFlags |= OMX_BUFFERFLAG_FIRST_FIELD; - - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x", -- CLASSNAME, __func__, omx_buffer->nFilledLen, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, omx_buffer->nFlags); -+ CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x frame:%d", -+ CLASSNAME, __func__, omx_buffer->nFilledLen, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, omx_buffer->nFlags, (int)omx_buffer->pMarkData); - #endif - - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); -@@ -758,13 +773,16 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) - } - if (demuxer_bytes == 0) - { -+ m_decode_frame_number++; - m_startframe = true; - #ifdef DTS_QUEUE - if (!m_drop_state) - { - // only push if we are successful with feeding OMX_EmptyThisBuffer -+ pthread_mutex_lock(&m_omx_output_mutex); - m_dts_queue.push(dts); - assert(m_dts_queue.size() < 32); -+ pthread_mutex_unlock(&m_omx_output_mutex); - } - #endif - if (buffer_to_free) -@@ -840,13 +858,18 @@ void COpenMaxVideo::Reset(void) - SetDropState(true); - SetDropState(false); - #ifdef DTS_QUEUE -+ pthread_mutex_lock(&m_omx_output_mutex); - while (!m_dts_queue.empty()) - m_dts_queue.pop(); -+ pthread_mutex_unlock(&m_omx_output_mutex); - #endif - - while (!m_demux_queue.empty()) - m_demux_queue.pop(); - m_startframe = false; -+ m_decoderPts = DVD_NOPTS_VALUE; -+ m_droppedPics = 0; -+ m_decode_frame_number = 1; - } - - -@@ -928,26 +951,17 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) - } - } - --#ifdef DTS_QUEUE -- if (!m_deinterlace_second_field) -- { -- assert(!m_dts_queue.empty()); -- pDvdVideoPicture->dts = m_dts_queue.front(); -- m_dts_queue.pop(); -- } -- if (m_deinterlace) -- m_deinterlace_second_field = !m_deinterlace_second_field; --#endif - // nTimeStamp is in microseconds -+ pDvdVideoPicture->dts = buffer->dts; - pDvdVideoPicture->pts = FromOMXTime(buffer->omx_buffer->nTimeStamp); - pDvdVideoPicture->openMaxBuffer->Acquire(); - pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; - if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_PTS_INVALID) - pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__, -+ CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x frame:%d openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__, - pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6, -- pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id); -+ pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, (int)buffer->omx_buffer->pMarkData, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id); - #endif - assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED))); - } -@@ -956,6 +970,12 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) - CLog::Log(LOGERROR, "%s::%s - called but m_omx_output_ready is empty", CLASSNAME, __func__); - return false; - } -+ -+ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) -+ m_decoderPts = pDvdVideoPicture->pts; -+ else -+ m_decoderPts = pDvdVideoPicture->dts; // xxx is DVD_NOPTS_VALUE better? -+ - return true; - } - -@@ -970,25 +990,56 @@ bool COpenMaxVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) - return true; - } - -+bool COpenMaxVideo::GetCodecStats(double &pts, int &droppedPics) -+{ -+ pts = m_decoderPts; -+ droppedPics = m_droppedPics; -+ m_droppedPics = 0; -+#if defined(OMX_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); -+#endif -+ return true; -+} -+ - // DecoderFillBufferDone -- OpenMax output buffer has been filled - OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone( - OMX_HANDLETYPE hComponent, - OMX_BUFFERHEADERTYPE* pBuffer) - { - COpenMaxVideoBuffer *buffer = (COpenMaxVideoBuffer*)pBuffer->pAppPrivate; -+ bool skipDeinterlaceFields = m_skipDeinterlaceFields || g_windowManager.HasDialogOnScreen(); - - #if defined(OMX_DEBUG_VERBOSE) -- CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f flags:%x", -- CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6, buffer->omx_buffer->nFlags); -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f flags:%x frame:%d win:%x", -+ CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6, buffer->omx_buffer->nFlags, (int)buffer->omx_buffer->pMarkData, skipDeinterlaceFields); - #endif - - assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED))); -- // queue output omx buffer to ready list. -- pthread_mutex_lock(&m_omx_output_mutex); -- buffer->m_aspect_ratio = m_aspect_ratio; -- m_omx_output_ready.push(buffer); -- pthread_mutex_unlock(&m_omx_output_mutex); - -+ -+ // flags have OMX_BUFFERFLAG_FIRST_FIELD set if this is a direct result of a submitted frame, -+ // clear for second field of deinterlaced frame. They are zero when frame is returned due to a flush. -+#ifdef DTS_QUEUE -+ if ((!m_deinterlace || (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_FIRST_FIELD)) && buffer->omx_buffer->nFlags) -+ { -+ pthread_mutex_lock(&m_omx_output_mutex); -+ assert(!m_dts_queue.empty()); -+ buffer->dts = m_dts_queue.front(); -+ m_dts_queue.pop(); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ } -+#endif -+ if (m_drop_state || (m_deinterlace && skipDeinterlaceFields && !(buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_FIRST_FIELD))) -+ { -+ ReturnOpenMaxBuffer(buffer); -+ } -+ else -+ { -+ buffer->m_aspect_ratio = m_aspect_ratio; -+ pthread_mutex_lock(&m_omx_output_mutex); -+ m_omx_output_ready.push(buffer); -+ pthread_mutex_unlock(&m_omx_output_mutex); -+ } - return OMX_ErrorNone; - } - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -index f234f6d..adf53b5 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h -@@ -57,6 +57,7 @@ class COpenMaxVideoBuffer - int height; - float m_aspect_ratio; - int index; -+ double dts; - - // used for egl based rendering if active - EGLImageKHR egl_image; -@@ -87,6 +88,7 @@ class COpenMaxVideo - virtual unsigned GetAllowedReferences() { return 2; } - virtual void SetDropState(bool bDrop); - virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ virtual bool GetCodecStats(double &pts, int &droppedPics); - - // OpenMax decoder callback routines. - OMX_ERRORTYPE DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer); -@@ -142,10 +144,11 @@ class COpenMaxVideo - - bool m_deinterlace; - EDEINTERLACEMODE m_deinterlace_request; -- bool m_deinterlace_second_field; -- - bool m_startframe; -- -+ unsigned int m_decode_frame_number; -+ double m_decoderPts; -+ unsigned int m_droppedPics; -+ bool m_skipDeinterlaceFields; - bool PortSettingsChanged(); - bool SendDecoderConfig(uint8_t *extradata, int extrasize); - bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize); --- -1.9.3 - - -From 9a0f4cb20b373b074497192fe3141786c61db81a Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 11 Apr 2014 16:12:27 +0100 -Subject: [PATCH 70/82] [omxplayer] Add ability to log more timestamp info in - extra debug settings - ---- - language/English/strings.po | 5 ++++ - xbmc/commons/ilog.h | 1 + - xbmc/cores/omxplayer/OMXPlayer.cpp | 52 ++++++++++++++++----------------- - xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 8 ++--- - xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 9 +++--- - xbmc/settings/AdvancedSettings.cpp | 3 ++ - 6 files changed, 44 insertions(+), 34 deletions(-) - -diff --git a/language/English/strings.po b/language/English/strings.po -index d386f68..a2c7215 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -2871,6 +2871,11 @@ msgctxt "#679" - msgid "Verbose logging for CEC library" - msgstr "" - -+#: xbmc/settings/AdvancedSettings.cpp -+msgctxt "#697" -+msgid "Verbose logging for OMXPLAYER" -+msgstr "" -+ - #empty strings from id 680 to 699 - - msgctxt "#700" -diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h -index 4bf5d83..3fb7cc3 100644 ---- a/xbmc/commons/ilog.h -+++ b/xbmc/commons/ilog.h -@@ -53,6 +53,7 @@ - #define LOGAIRTUNES (1 << (LOGMASKBIT + 8)) - #define LOGUPNP (1 << (LOGMASKBIT + 9)) - #define LOGCEC (1 << (LOGMASKBIT + 10)) -+#define LOGOMXPLAYER (1 << (LOGMASKBIT+11)) - - #ifdef __GNUC__ - #define ATTRIB_LOG_FORMAT __attribute__((format(printf,3,4))) -diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp -index a811169..d074dbe 100644 ---- a/xbmc/cores/omxplayer/OMXPlayer.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayer.cpp -@@ -1554,27 +1554,28 @@ void COMXPlayer::Process() - m_video_fifo = (int)(100.0*(m_omxPlayerVideo.GetDecoderBufferSize()-m_omxPlayerVideo.GetDecoderFreeSpace())/m_omxPlayerVideo.GetDecoderBufferSize()); - m_audio_fifo = (int)(100.0*audio_fifo/m_omxPlayerAudio.GetCacheTotal()); - -- #ifdef _DEBUG -- static unsigned count; -- if ((count++ & 7) == 0) -+ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) - { -- char response[80]; -- if (m_omxPlayerVideo.GetDecoderBufferSize() && m_omxPlayerAudio.GetCacheTotal()) -- vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", -- m_video_fifo, -- (int)(100.0*video_fifo/m_omxPlayerAudio.GetCacheTotal()), -- 0, 100); -- if (m_omxPlayerAudio.GetCacheTotal()) -- vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", -- m_audio_fifo, -- (int)(100.0*m_omxPlayerAudio.GetDelay()/m_omxPlayerAudio.GetCacheTotal()), -- 0, 100); -- vc_gencmd(response, sizeof response, "render_bar 6 video_queue %d %d %d %d", -- m_omxPlayerVideo.GetLevel(), 0, 0, 100); -- vc_gencmd(response, sizeof response, "render_bar 7 audio_queue %d %d %d %d", -- m_omxPlayerAudio.GetLevel(), 0, 0, 100); -+ static unsigned count; -+ if ((count++ & 7) == 0) -+ { -+ char response[80]; -+ if (m_omxPlayerVideo.GetDecoderBufferSize() && m_omxPlayerAudio.GetCacheTotal()) -+ vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", -+ m_video_fifo, -+ (int)(100.0*video_fifo/m_omxPlayerAudio.GetCacheTotal()), -+ 0, 100); -+ if (m_omxPlayerAudio.GetCacheTotal()) -+ vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", -+ m_audio_fifo, -+ (int)(100.0*m_omxPlayerAudio.GetDelay()/m_omxPlayerAudio.GetCacheTotal()), -+ 0, 100); -+ vc_gencmd(response, sizeof response, "render_bar 6 video_queue %d %d %d %d", -+ m_omxPlayerVideo.GetLevel(), 0, 0, 100); -+ vc_gencmd(response, sizeof response, "render_bar 7 audio_queue %d %d %d %d", -+ m_omxPlayerAudio.GetLevel(), 0, 0, 100); -+ } - } -- #endif - if (audio_pts != DVD_NOPTS_VALUE) - { - audio_fifo_low = m_HasAudio && audio_fifo < threshold; -@@ -1590,13 +1591,12 @@ void COMXPlayer::Process() - if (!m_HasVideo && m_HasAudio) - video_fifo_high = true; - -- #ifdef _DEBUG -- CLog::Log(LOGDEBUG, "%s - M:%.6f-%.6f (A:%.6f V:%.6f) PEF:%d%d%d S:%.2f A:%.2f V:%.2f/T:%.2f (A:%d%d V:%d%d) A:%d%% V:%d%% (%.2f,%.2f)", __FUNCTION__, -- m_stamp*1e-6, m_av_clock.OMXClockAdjustment()*1e-6, audio_pts*1e-6, video_pts*1e-6, m_av_clock.OMXIsPaused(), bOmxSentEOFs, not_accepts_data, m_playSpeed * (1.0f/DVD_PLAYSPEED_NORMAL), -- audio_pts == DVD_NOPTS_VALUE ? 0.0:audio_fifo, video_pts == DVD_NOPTS_VALUE ? 0.0:video_fifo, m_threshold, -- audio_fifo_low, audio_fifo_high, video_fifo_low, video_fifo_high, -- m_omxPlayerAudio.GetLevel(), m_omxPlayerVideo.GetLevel(), m_omxPlayerAudio.GetDelay(), (float)m_omxPlayerAudio.GetCacheTotal()); -- #endif -+ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) -+ CLog::Log(LOGDEBUG, "%s - M:%.6f-%.6f (A:%.6f V:%.6f) PEF:%d%d%d S:%.2f A:%.2f V:%.2f/T:%.2f (A:%d%d V:%d%d) A:%d%% V:%d%% (%.2f,%.2f)", __FUNCTION__, -+ m_stamp*1e-6, m_av_clock.OMXClockAdjustment()*1e-6, audio_pts*1e-6, video_pts*1e-6, m_av_clock.OMXIsPaused(), bOmxSentEOFs, not_accepts_data, m_playSpeed * (1.0f/DVD_PLAYSPEED_NORMAL), -+ audio_pts == DVD_NOPTS_VALUE ? 0.0:audio_fifo, video_pts == DVD_NOPTS_VALUE ? 0.0:video_fifo, m_threshold, -+ audio_fifo_low, audio_fifo_high, video_fifo_low, video_fifo_high, -+ m_omxPlayerAudio.GetLevel(), m_omxPlayerVideo.GetLevel(), m_omxPlayerAudio.GetDelay(), (float)m_omxPlayerAudio.GetCacheTotal()); - - if (TP(m_playSpeed)) - { -diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp -index d3348ec..02dd9be 100644 ---- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp -@@ -364,10 +364,10 @@ void OMXPlayerAudio::Process() - DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); - bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); - -- #ifdef _DEBUG -- CLog::Log(LOGINFO, "Audio: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d,%d", pPacket->dts, pPacket->pts, -- (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, (int)m_omxAudio.GetAudioRenderingLatency(), (int)m_hints_current.samplerate); -- #endif -+ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) -+ CLog::Log(LOGINFO, "Audio: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d,%d", pPacket->dts, pPacket->pts, -+ (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, (int)m_omxAudio.GetAudioRenderingLatency(), (int)m_hints_current.samplerate); -+ - if(Decode(pPacket, m_speed > DVD_PLAYSPEED_NORMAL || m_speed < 0 || bPacketDrop)) - { - // we are not running until something is cached in output device -diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -index e6bf2d0..aa5ea43 100644 ---- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -+++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp -@@ -42,6 +42,7 @@ - #include "DVDOverlayRenderer.h" - #include "settings/DisplaySettings.h" - #include "settings/Settings.h" -+#include "settings/AdvancedSettings.h" - #include "settings/MediaSettings.h" - #include "cores/VideoRenderers/RenderFormats.h" - #include "cores/VideoRenderers/RenderFlags.h" -@@ -451,10 +452,10 @@ void OMXPlayerVideo::Process() - DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); - bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); - -- #ifdef _DEBUG -- CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts, -- (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0); -- #endif -+ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) -+ CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts, -+ (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0); -+ - if (m_messageQueue.GetDataSize() == 0 - || m_speed < 0) - { -diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index edbbcad..b9fc3ae 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -1395,6 +1395,9 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se - #ifdef HAVE_LIBCEC - list.push_back(std::make_pair(g_localizeStrings.Get(679), LOGCEC)); - #endif -+#ifdef TARGET_RASPBERRY_PI -+ list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); -+#endif - } - - void CAdvancedSettings::setExtraLogLevel(const std::vector &components) --- -1.9.3 - - -From d9a51561c7cc6eb38c40b494b7f50fe5a7e85b78 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 7 Apr 2014 23:13:55 +0100 -Subject: [PATCH 71/82] [omxplayer] Add ability to dump out audio/video data - for later debugging - ---- - language/English/strings.po | 10 ++++++++ - xbmc/commons/ilog.h | 2 ++ - xbmc/cores/omxplayer/OMXAudio.cpp | 49 ++++++++++++++++++++++++++++++++++++++ - xbmc/cores/omxplayer/OMXVideo.cpp | 47 ++++++++++++++++++++++++++++++++++++ - xbmc/settings/AdvancedSettings.cpp | 4 ++++ - 5 files changed, 112 insertions(+) - -diff --git a/language/English/strings.po b/language/English/strings.po -index a2c7215..9ba9565 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -2876,6 +2876,16 @@ msgctxt "#697" - msgid "Verbose logging for OMXPLAYER" - msgstr "" - -+#: xbmc/settings/AdvancedSettings.cpp -+msgctxt "#698" -+msgid "Dump video frames to debug file" -+msgstr "" -+ -+#: xbmc/settings/AdvancedSettings.cpp -+msgctxt "#699" -+msgid "Dump audio frames to debug file" -+msgstr "" -+ - #empty strings from id 680 to 699 - - msgctxt "#700" -diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h -index 3fb7cc3..4d722a0 100644 ---- a/xbmc/commons/ilog.h -+++ b/xbmc/commons/ilog.h -@@ -54,6 +54,8 @@ - #define LOGUPNP (1 << (LOGMASKBIT + 9)) - #define LOGCEC (1 << (LOGMASKBIT + 10)) - #define LOGOMXPLAYER (1 << (LOGMASKBIT+11)) -+#define LOGDUMPVIDEO (1 << (LOGMASKBIT+12)) -+#define LOGDUMPAUDIO (1 << (LOGMASKBIT+13)) - - #ifdef __GNUC__ - #define ATTRIB_LOG_FORMAT __attribute__((format(printf,3,4))) -diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp -index 5f9d028..1bcc53e0 100644 ---- a/xbmc/cores/omxplayer/OMXAudio.cpp -+++ b/xbmc/cores/omxplayer/OMXAudio.cpp -@@ -59,6 +59,49 @@ static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0}; - - static const uint16_t DTSFSCod [] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0}; - -+//#define DEBUG_PLAYBACK -+static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) -+{ -+ if (!(g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) -+ return; -+ static FILE *fp; -+ if (!omx_buffer) -+ { -+ if (fp) -+ { -+ fclose(fp); -+ fp = NULL; -+ } -+ return; -+ } -+ if (!fp) -+ { -+ char filename[1024]; -+ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); -+ strcat(filename, "audio.dat"); -+#ifdef DEBUG_PLAYBACK -+ fp = fopen(filename, "rb"); -+#else -+ fp = fopen(filename, "wb"); -+#endif -+ } -+ if (fp) -+ { -+#ifdef DEBUG_PLAYBACK -+ OMX_BUFFERHEADERTYPE omx = {0}; -+ int s = fread(&omx, sizeof omx, 1, fp); -+ omx_buffer->nFilledLen = omx.nFilledLen; -+ omx_buffer->nFlags = omx.nFlags; -+ omx_buffer->nTimeStamp = omx.nTimeStamp; -+ if (s==1) -+ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); -+#else -+ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) -+ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); -+#endif -+ } -+} -+ - ////////////////////////////////////////////////////////////////////// - // Construction/Destruction - ////////////////////////////////////////////////////////////////////// -@@ -866,6 +909,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo - memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); - omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; - -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { -@@ -898,6 +942,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo - memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); - omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; - -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { -@@ -934,6 +979,8 @@ bool COMXAudio::Deinitialize() - { - CSingleLock lock (m_critSection); - -+ dump_omx_buffer(NULL); -+ - if ( m_omx_tunnel_clock_analog.IsInitialized() ) - m_omx_tunnel_clock_analog.Deestablish(); - if ( m_omx_tunnel_clock_hdmi.IsInitialized() ) -@@ -1226,6 +1273,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt - int nRetry = 0; - while(true) - { -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err == OMX_ErrorNone) - { -@@ -1492,6 +1540,7 @@ void COMXAudio::SubmitEOS() - - omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; - -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { -diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp -index 820ea44..6639804 100644 ---- a/xbmc/cores/omxplayer/OMXVideo.cpp -+++ b/xbmc/cores/omxplayer/OMXVideo.cpp -@@ -63,6 +63,49 @@ - - #define MAX_TEXT_LENGTH 1024 - -+//#define DEBUG_PLAYBACK -+static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) -+{ -+ if (!(g_advancedSettings.CanLogComponent(LOGDUMPVIDEO))) -+ return; -+ static FILE *fp; -+ if (!omx_buffer) -+ { -+ if (fp) -+ { -+ fclose(fp); -+ fp = NULL; -+ } -+ return; -+ } -+ if (!fp) -+ { -+ char filename[1024]; -+ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); -+ strcat(filename, "video.dat"); -+#ifdef DEBUG_PLAYBACK -+ fp = fopen(filename, "rb"); -+#else -+ fp = fopen(filename, "wb"); -+#endif -+ } -+ if (fp) -+ { -+#ifdef DEBUG_PLAYBACK -+ OMX_BUFFERHEADERTYPE omx = {0}; -+ int s = fread(&omx, sizeof omx, 1, fp); -+ omx_buffer->nFilledLen = omx.nFilledLen; -+ omx_buffer->nFlags = omx.nFlags; -+ omx_buffer->nTimeStamp = omx.nTimeStamp; -+ if (s==1) -+ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); -+#else -+ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) -+ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); -+#endif -+ } -+} -+ - COMXVideo::COMXVideo() : m_video_codec_name("") - { - m_is_open = false; -@@ -118,6 +161,7 @@ bool COMXVideo::SendDecoderConfig() - memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); - omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; - -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { -@@ -687,6 +731,7 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de - void COMXVideo::Close() - { - CSingleLock lock (m_critSection); -+ dump_omx_buffer(NULL); - m_omx_tunnel_clock.Deestablish(); - m_omx_tunnel_decoder.Deestablish(); - if(m_deinterlace) -@@ -781,6 +826,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) - int nRetry = 0; - while(true) - { -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err == OMX_ErrorNone) - { -@@ -910,6 +956,7 @@ void COMXVideo::SubmitEOS() - - omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; - -+ dump_omx_buffer(omx_buffer); - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { -diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp -index b9fc3ae..4c9aea4 100644 ---- a/xbmc/settings/AdvancedSettings.cpp -+++ b/xbmc/settings/AdvancedSettings.cpp -@@ -1398,6 +1398,10 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se - #ifdef TARGET_RASPBERRY_PI - list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); - #endif -+#ifdef TARGET_RASPBERRY_PI -+ list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); -+ list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); -+#endif - } - - void CAdvancedSettings::setExtraLogLevel(const std::vector &components) --- -1.9.3 - - -From f98b36b22f3c7152e218ae22dacb3e7ac8024a52 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 28 May 2014 18:30:51 +0100 -Subject: [PATCH 72/82] [omxcodec] Reduce GPU memory use by 2 video frames - ---- - xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -index 612ae21..494fdf5 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp -@@ -308,6 +308,20 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM - return false; - } - -+ { -+ // as we aren't tunnelled to display, we can save memory by setting extrabuffers to 0 -+ OMX_PARAM_U32TYPE extra_buffers; -+ OMX_INIT_STRUCTURE(extra_buffers); -+ extra_buffers.nU32 = 0; -+ -+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); -+ if(omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmExtraBuffers omx_err(0x%08x)\n", omx_err); -+ return false; -+ } -+ } -+ - // request portsettingschanged on aspect ratio change - OMX_CONFIG_REQUESTCALLBACKTYPE notifications; - OMX_INIT_STRUCTURE(notifications); --- -1.9.3 - - -From 100cd97b3ef5c514f012e6ee0d688775a471e66f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 30 May 2014 14:15:10 +0100 -Subject: [PATCH 73/82] [pi] Fix for logged resolutions - ---- - xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 15 +++++---------- - 1 file changed, 5 insertions(+), 10 deletions(-) - -diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -index 5b26b20..a3edf0e 100644 ---- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -+++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp -@@ -483,10 +483,8 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r - - if(resolutions.size() == 0) - { -- RESOLUTION_INFO res; -- CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags); -- - AddUniqueResolution(m_desktopRes, resolutions); -+ CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags); - } - - if(resolutions.size() < 2) -@@ -576,13 +574,12 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v - res.iScreenWidth = tv->width; - res.iScreenHeight = tv->height; - res.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res.iScreenWidth / (float)res.iScreenHeight); -+ res.iSubtitles = (int)(0.965 * res.iHeight); - -+ AddUniqueResolution(res, resolutions); - CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f) %s%s:%x\n", i, res.strMode.c_str(), res.fPixelRatio, - tv->native ? "N" : "", tv->scan_mode ? "I" : "", tv->code); - -- res.iSubtitles = (int)(0.965 * res.iHeight); -- -- AddUniqueResolution(res, resolutions); - if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60) - { - RESOLUTION_INFO res2 = res; -@@ -596,11 +593,10 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v - RESOLUTION_INFO res2 = res; - res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; - res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); -- CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio); -- - res2.iSubtitles = (int)(0.965 * res2.iHeight); - - AddUniqueResolution(res2, resolutions); -+ CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio); - if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60) - { - res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f); -@@ -612,11 +608,10 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v - RESOLUTION_INFO res2 = res; - res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB; - res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); -- CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio); -- - res2.iSubtitles = (int)(0.965 * res2.iHeight); - - AddUniqueResolution(res2, resolutions); -+ CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio); - if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60) - { - res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f); --- -1.9.3 - - -From d3c05867d1ae056fbc53249a858b6787525b993d Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 30 May 2014 14:58:43 +0100 -Subject: [PATCH 74/82] [settings] Experiment: Report DESKTOP resolution in - video settings - ---- - xbmc/settings/DisplaySettings.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp -index 246a047..0204839 100644 ---- a/xbmc/settings/DisplaySettings.cpp -+++ b/xbmc/settings/DisplaySettings.cpp -@@ -650,6 +650,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, - vector resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate); - for (vector::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution) - { -+if (resolution->ResInfo_Index == RES_DESKTOP) -+ list.push_back(make_pair(StringUtils::Format("DESKTOP"), resolution->ResInfo_Index)); -+else - list.push_back(make_pair( - StringUtils::Format("%dx%d%s", resolution->width, resolution->height, - ModeFlagsToString(resolution->flags, false).c_str()), --- -1.9.3 - - -From c02792997861e0dff7d1f7cc81180f8eb46384c8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 7 Jun 2014 16:55:41 +0100 -Subject: [PATCH 75/82] [omx] Remove logging for texture jobs - -This causes a lot of log spam which hasn't proved useful so far. ---- - xbmc/cores/omxplayer/OMXImage.cpp | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp -index 262a004..d529b20 100644 ---- a/xbmc/cores/omxplayer/OMXImage.cpp -+++ b/xbmc/cores/omxplayer/OMXImage.cpp -@@ -210,13 +210,11 @@ bool COMXImage::SendMessage(bool (*callback)(EGLDisplay egl_display, EGLContext - mess.sync.Reset(); - { - CSingleLock lock(m_texqueue_lock); -- CLog::Log(LOGDEBUG, "%s: texture job: %p:%p", __func__, &mess, mess.callback); - m_texqueue.push(&mess); - m_texqueue_cond.notifyAll(); - } - // wait for function to have finished (in texture thread) - mess.sync.Wait(); -- CLog::Log(LOGDEBUG, "%s: texture job done: %p:%p = %d", __func__, &mess, mess.callback, mess.result); - // need to ensure texture thread has returned from mess.sync.Set() before we exit and free tex - CSingleLock lock(m_texqueue_lock); - return mess.result; -@@ -429,15 +427,12 @@ void COMXImage::Process() - struct callbackinfo *mess = m_texqueue.front(); - m_texqueue.pop(); - lock.Leave(); -- CLog::Log(LOGDEBUG, "%s: texture job: %p:%p:%p", __func__, mess, mess->callback, mess->cookie); - - mess->result = mess->callback(g_Windowing.GetEGLDisplay(), GetEGLContext(), mess->cookie); -- CLog::Log(LOGDEBUG, "%s: texture job about to Set: %p:%p:%p", __func__, mess, mess->callback, mess->cookie); - { - CSingleLock lock(m_texqueue_lock); - mess->sync.Set(); - } -- CLog::Log(LOGDEBUG, "%s: texture job: %p done", __func__, mess); - } - } - } --- -1.9.3 - - -From 8ecc8fbdc4aedff11b0c930078ba6519f26b5d20 Mon Sep 17 00:00:00 2001 -From: Matthias Kortstiege -Date: Sun, 1 Jun 2014 18:47:20 +0200 -Subject: [PATCH 76/82] changed: avoid useless filesytem io while searching for - subtitles - ---- - xbmc/Util.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp -index 82cbf4b..4340700 100644 ---- a/xbmc/Util.cpp -+++ b/xbmc/Util.cpp -@@ -1983,7 +1983,7 @@ void CUtil::ScanForExternalSubtitles(const CStdString& strMovie, std::vector -Date: Wed, 4 Jun 2014 19:10:27 +0100 -Subject: [PATCH 77/82] [pisink] Support planar formats - ---- - xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 35 ++++++++++++++++++++++++++----- - 1 file changed, 30 insertions(+), 5 deletions(-) - -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -index 7c04919..bf9cb7a 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -@@ -180,7 +180,9 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) - format.m_channelLayout = AE_CH_LAYOUT_2_0; - - // setup for a 50ms sink feed from SoftAE -- if (format.m_dataFormat != AE_FMT_FLOAT && format.m_dataFormat != AE_FMT_S32LE) -+ if (format.m_dataFormat != AE_FMT_FLOATP && format.m_dataFormat != AE_FMT_FLOAT && -+ format.m_dataFormat != AE_FMT_S32NE && format.m_dataFormat != AE_FMT_S32NEP && format.m_dataFormat != AE_FMT_S32LE && -+ format.m_dataFormat != AE_FMT_S16NE && format.m_dataFormat != AE_FMT_S16NEP && format.m_dataFormat != AE_FMT_S16LE) - format.m_dataFormat = AE_FMT_S16LE; - unsigned int channels = format.m_channelLayout.Count(); - unsigned int sample_size = CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3; -@@ -210,7 +212,13 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) - m_pcm_input.eEndian = OMX_EndianLittle; - m_pcm_input.bInterleaved = OMX_TRUE; - m_pcm_input.nBitPerSample = sample_size * 8; -- m_pcm_input.ePCMMode = m_format.m_dataFormat == AE_FMT_FLOAT ? (OMX_AUDIO_PCMMODETYPE)0x8000 : OMX_AUDIO_PCMModeLinear; -+ // 0x8000 = float, 0x10000 = planar -+ uint32_t flags = 0; -+ if (m_format.m_dataFormat == AE_FMT_FLOAT || m_format.m_dataFormat == AE_FMT_FLOATP) -+ flags |= 0x8000; -+ if (AE_IS_PLANAR(m_format.m_dataFormat)) -+ flags |= 0x10000; -+ m_pcm_input.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; - m_pcm_input.nChannels = channels; - m_pcm_input.nSamplingRate = m_format.m_sampleRate; - -@@ -308,14 +316,18 @@ double CAESinkPi::GetCacheTotal() - - unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) - { -- uint8_t *buffer = data[0]+offset*m_format.m_frameSize; -- - if (!m_Initialized || !frames) - return frames; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_BUFFERHEADERTYPE *omx_buffer = NULL; - -+ unsigned int channels = m_format.m_channelLayout.Count(); -+ unsigned int sample_size = CAEUtil::DataFormatToBits(m_format.m_dataFormat) >> 3; -+ const int planes = AE_IS_PLANAR(m_format.m_dataFormat) ? channels : 1; -+ const int chans = AE_IS_PLANAR(m_format.m_dataFormat) ? 1 : channels; -+ const int pitch = chans * sample_size; -+ - double delay = GetDelay(); - if (delay <= 0.0 && m_submitted) - CLog::Log(LOGNOTICE, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames); -@@ -332,8 +344,13 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned - assert(omx_buffer->nFilledLen <= omx_buffer->nAllocLen); - omx_buffer->nTimeStamp = ToOMXTime(0); - omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; -- memcpy(omx_buffer->pBuffer, buffer, omx_buffer->nFilledLen); - -+ if (omx_buffer->nFilledLen) -+ { -+ int planesize = omx_buffer->nFilledLen / planes; -+ for (int i=0; i < planes; i++) -+ memcpy((uint8_t *)omx_buffer->pBuffer + i * planesize, data[i] + offset * pitch, planesize); -+ } - omx_err = m_omx_render.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err); -@@ -367,8 +384,13 @@ void CAESinkPi::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) - for (unsigned int i=0; i -Date: Mon, 30 Dec 2013 12:02:14 +0000 -Subject: [PATCH 78/82] [rbp] Hardware accelerated resampling - -This replaces the format conversion, up/down mixing and resampling code from ActiveAE with a GPU accelerated version. -Should significantly reduce CPU when using paplayer or dvdplayer. - -Requires updated firmware ---- - .../Engines/ActiveAE/ActiveAEResample.cpp | 5 + - .../Engines/ActiveAE/ActiveAEResample.h | 8 + - .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 601 +++++++++++++++++++++ - .../Engines/ActiveAE/ActiveAEResamplePi.h | 62 +++ - xbmc/cores/AudioEngine/Makefile.in | 1 + - xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 14 +- - xbmc/linux/OMXCore.cpp | 4 +- - 7 files changed, 686 insertions(+), 9 deletions(-) - create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp - create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h - -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -index 8250eef..972e1be 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -@@ -18,6 +18,10 @@ - * - */ - -+#include "system.h" -+ -+#if !defined(TARGET_RASPBERRY_PI) -+ - #include "ActiveAEResample.h" - #include "utils/log.h" - -@@ -359,3 +363,4 @@ int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layo - { - return av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel)); - } -+#endif -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h -index a471e02..5d37cc7 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h -@@ -19,6 +19,8 @@ - * - */ - -+#include "system.h" -+ - #include "cores/AudioEngine/Utils/AEChannelInfo.h" - #include "cores/AudioEngine/Utils/AEAudioFormat.h" - #include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" -@@ -29,6 +31,10 @@ extern "C" { - #include "libswresample/swresample.h" - } - -+#if defined(TARGET_RASPBERRY_PI) -+#include "ActiveAEResamplePi.h" -+#else -+ - namespace ActiveAE - { - -@@ -63,3 +69,5 @@ class CActiveAEResample - }; - - } -+ -+#endif -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -new file mode 100644 -index 0000000..9a1e549 ---- /dev/null -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -@@ -0,0 +1,601 @@ -+/* -+ * 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 -+ * . -+ * -+ */ -+ -+#include "system.h" -+ -+#if defined(TARGET_RASPBERRY_PI) -+ -+#include "ActiveAEResample.h" -+#include "linux/RBP.h" -+#include "settings/Settings.h" -+#include "utils/log.h" -+ -+extern "C" { -+#include "libavutil/channel_layout.h" -+#include "libavutil/opt.h" -+#include "libswresample/swresample.h" -+} -+ -+//#define DEBUG_VERBOSE -+ -+#define CLASSNAME "CActiveAEResamplePi" -+ -+#define BUFFERSIZE (32*1024*2*8) -+ -+//#define BENCHMARKING -+#ifdef BENCHMARKING -+#define LOGTIMEINIT(f) \ -+ struct timespec now; \ -+ uint64_t Start, End; \ -+ clock_gettime(CLOCK_MONOTONIC, &now); \ -+ Start = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \ -+ const char *_filename = f; -+ -+#define LOGTIME(n) \ -+ clock_gettime(CLOCK_MONOTONIC, &now); \ -+ End = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \ -+ CLog::Log(LOGNOTICE, "ActiveAE::%s %d - resample %s took %.0fms", __FUNCTION__, n, _filename, (End-Start)*1e-6); \ -+ Start=End; -+#else -+#define LOGTIMEINIT(f) -+#define LOGTIME(n) -+#endif -+ -+using namespace ActiveAE; -+ -+CActiveAEResample::CActiveAEResample() -+{ -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ -+ m_Initialized = false; -+ m_last_src_fmt = AV_SAMPLE_FMT_NONE; -+ m_last_dst_fmt = AV_SAMPLE_FMT_NONE; -+ m_last_src_channels = 0; -+ m_last_dst_channels = 0; -+} -+ -+CActiveAEResample::~CActiveAEResample() -+{ -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ DeInit(); -+} -+ -+void CActiveAEResample::DeInit() -+{ -+ CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); -+ if (m_Initialized) -+ { -+ m_omx_mixer.FlushAll(); -+ m_omx_mixer.Deinitialize(); -+ m_Initialized = false; -+ } -+} -+ -+bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) -+{ -+ LOGTIMEINIT("x"); -+ -+ CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d rate:%d->%d format:%d->%d bits:%d->%d norm:%d upmix:%d", CLASSNAME, __func__, remapLayout, src_channels, dst_channels, src_rate, dst_rate, src_fmt, dst_fmt, src_bits, dst_bits, normalize, upmix); -+ -+ if (src_bits == 0) -+ { -+ if (src_fmt == AV_SAMPLE_FMT_U8) src_bits = 8; -+ else if (src_fmt == AV_SAMPLE_FMT_S16) src_bits = 16; -+ else if (src_fmt == AV_SAMPLE_FMT_S32) src_bits = 32; -+ else if (src_fmt == AV_SAMPLE_FMT_FLT) src_bits = 32; -+ } -+ assert(src_bits && dst_bits); -+ -+ m_dst_chan_layout = dst_chan_layout; -+ m_dst_channels = dst_channels; -+ m_dst_rate = dst_rate; -+ m_dst_fmt = dst_fmt; -+ m_dst_bits = dst_bits; -+ m_src_chan_layout = src_chan_layout; -+ m_src_channels = src_channels; -+ m_src_rate = src_rate; -+ m_src_fmt = src_fmt; -+ m_src_bits = src_bits; -+ -+ if (m_dst_chan_layout == 0) -+ m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels); -+ if (m_src_chan_layout == 0) -+ m_src_chan_layout = av_get_default_channel_layout(m_src_channels); -+ -+ OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix; -+ OMX_INIT_STRUCTURE(mix); -+ -+ assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64); -+ -+ LOGTIME(1); -+// this code is just uses ffmpeg to produce the 8x8 mixing matrix -+{ -+ // dummy sample rate and format, as we only care about channel mapping -+ SwrContext *m_pContext = swr_alloc_set_opts(NULL, m_dst_chan_layout, AV_SAMPLE_FMT_FLT, 48000, -+ m_src_chan_layout, AV_SAMPLE_FMT_FLT, 48000, 0, NULL); -+ if (!m_pContext) -+ { -+ CLog::Log(LOGERROR, "CActiveAEResample::Init - create context failed"); -+ return false; -+ } -+ // tell resampler to clamp float values -+ // not required for sink stage (remapLayout == true) -+ if (!remapLayout && normalize) -+ { -+ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); -+ } -+ -+ if (remapLayout) -+ { -+ // one-to-one mapping of channels -+ // remapLayout is the layout of the sink, if the channel is in our src layout -+ // the channel is mapped by setting coef 1.0 -+ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; -+ memset(m_rematrix, 0, sizeof(m_rematrix)); -+ m_dst_chan_layout = 0; -+ for (unsigned int out=0; outCount(); out++) -+ { -+ m_dst_chan_layout += (uint64_t) (1 << out); -+ int idx = GetAVChannelIndex((*remapLayout)[out], m_src_chan_layout); -+ if (idx >= 0) -+ { -+ m_rematrix[out][idx] = 1.0; -+ } -+ } -+ -+ av_opt_set_int(m_pContext, "out_channel_count", m_dst_channels, 0); -+ av_opt_set_int(m_pContext, "out_channel_layout", m_dst_chan_layout, 0); -+ -+ if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) -+ { -+ CLog::Log(LOGERROR, "CActiveAEResample::Init - setting channel matrix failed"); -+ return false; -+ } -+ } -+ // stereo upmix -+ else if (upmix && m_src_channels == 2 && m_dst_channels > 2) -+ { -+ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; -+ memset(m_rematrix, 0, sizeof(m_rematrix)); -+ for (int out=0; out%d (%.2f)", CLASSNAME, __func__, src_samples, dst_samples, ratio); -+ #endif -+ if (!m_Initialized) -+ return 0; -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; -+ -+ const int s_pitch = m_pcm_input.nChannels * m_src_bits >> 3; -+ const int d_pitch = m_pcm_output.nChannels * m_dst_bits >> 3; -+ int sent = 0; -+ int received = 0; -+ while (sent < src_samples) -+ { -+ OMX_BUFFERHEADERTYPE *omx_buffer = NULL; -+ OMX_BUFFERHEADERTYPE *m_encoded_buffer = NULL; -+ -+ omx_buffer = m_omx_mixer.GetInputBuffer(1000); -+ if (omx_buffer == NULL) -+ return false; -+ -+ const int max_src_samples = BUFFERSIZE / s_pitch; -+ const int max_dst_samples = (long long)(BUFFERSIZE/d_pitch) * m_src_rate / (m_dst_rate + m_src_rate-1); -+ int send = std::min(std::min(max_dst_samples, max_src_samples), src_samples - sent); -+ -+ omx_buffer->nOffset = 0; -+ omx_buffer->nFlags = OMX_BUFFERFLAG_EOS; -+ omx_buffer->nFilledLen = send * s_pitch; -+ -+ assert(omx_buffer->nFilledLen > 0 && omx_buffer->nFilledLen <= omx_buffer->nAllocLen); -+ -+ if (omx_buffer->nFilledLen) -+ { -+ memcpy(omx_buffer->pBuffer, src_buffer[0] + sent * s_pitch, omx_buffer->nFilledLen); -+ sent += send; -+ } -+ -+ omx_err = m_omx_mixer.EmptyThisBuffer(omx_buffer); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ m_encoded_buffer = m_omx_mixer.GetOutputBuffer(); -+ -+ if (!m_encoded_buffer) -+ { -+ CLog::Log(LOGERROR, "%s::%s no output buffer", CLASSNAME, __func__); -+ return false; -+ } -+ -+ omx_err = m_omx_mixer.FillThisBuffer(m_encoded_buffer); -+ if (omx_err != OMX_ErrorNone) -+ return false; -+ -+ omx_err = m_omx_mixer.WaitForOutputDone(1000); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_mixer.WaitForOutputDone result(0x%x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ assert(m_encoded_buffer->nFilledLen > 0 && m_encoded_buffer->nFilledLen <= m_encoded_buffer->nAllocLen); -+ -+ if (m_omx_mixer.BadState()) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_mixer.BadState", CLASSNAME, __func__); -+ return false; -+ } -+ -+ if (m_encoded_buffer->nFilledLen) -+ { -+ memcpy(dst_buffer[0] + received * d_pitch, m_encoded_buffer->pBuffer, m_encoded_buffer->nFilledLen); -+ received += m_encoded_buffer->nFilledLen / d_pitch; -+ } -+ } -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s format:%d->%d rate:%d->%d chan:%d->%d samples %d->%d (%f) %d =%d", CLASSNAME, __func__, -+ (int)m_src_fmt, (int)m_dst_fmt, m_src_rate, m_dst_rate, m_src_channels, m_dst_channels, src_samples, dst_samples, ratio, m_Initialized, received); -+ #endif -+ return received; -+} -+ -+int64_t CActiveAEResample::GetDelay(int64_t base) -+{ -+ int ret = 0; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::GetBufferedSamples() -+{ -+ int ret = 0; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) -+{ -+ int ret = ((long long)src_samples * dst_rate + src_rate-1) / src_rate; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::GetSrcBufferSize(int samples) -+{ -+ int ret = 0; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::GetDstBufferSize(int samples) -+{ -+ int ret = CalcDstSampleCount(samples, m_dst_rate, m_src_rate); -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+uint64_t CActiveAEResample::GetAVChannelLayout(CAEChannelInfo &info) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ uint64_t channelLayout = 0; -+ if (info.HasChannel(AE_CH_FL)) channelLayout |= AV_CH_FRONT_LEFT; -+ if (info.HasChannel(AE_CH_FR)) channelLayout |= AV_CH_FRONT_RIGHT; -+ if (info.HasChannel(AE_CH_FC)) channelLayout |= AV_CH_FRONT_CENTER; -+ if (info.HasChannel(AE_CH_LFE)) channelLayout |= AV_CH_LOW_FREQUENCY; -+ if (info.HasChannel(AE_CH_BL)) channelLayout |= AV_CH_BACK_LEFT; -+ if (info.HasChannel(AE_CH_BR)) channelLayout |= AV_CH_BACK_RIGHT; -+ if (info.HasChannel(AE_CH_FLOC)) channelLayout |= AV_CH_FRONT_LEFT_OF_CENTER; -+ if (info.HasChannel(AE_CH_FROC)) channelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER; -+ if (info.HasChannel(AE_CH_BC)) channelLayout |= AV_CH_BACK_CENTER; -+ if (info.HasChannel(AE_CH_SL)) channelLayout |= AV_CH_SIDE_LEFT; -+ if (info.HasChannel(AE_CH_SR)) channelLayout |= AV_CH_SIDE_RIGHT; -+ if (info.HasChannel(AE_CH_TC)) channelLayout |= AV_CH_TOP_CENTER; -+ if (info.HasChannel(AE_CH_TFL)) channelLayout |= AV_CH_TOP_FRONT_LEFT; -+ if (info.HasChannel(AE_CH_TFC)) channelLayout |= AV_CH_TOP_FRONT_CENTER; -+ if (info.HasChannel(AE_CH_TFR)) channelLayout |= AV_CH_TOP_FRONT_RIGHT; -+ if (info.HasChannel(AE_CH_TBL)) channelLayout |= AV_CH_TOP_BACK_LEFT; -+ if (info.HasChannel(AE_CH_TBC)) channelLayout |= AV_CH_TOP_BACK_CENTER; -+ if (info.HasChannel(AE_CH_TBR)) channelLayout |= AV_CH_TOP_BACK_RIGHT; -+ -+ return channelLayout; -+} -+ -+AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ 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_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_FLOATP) return AV_SAMPLE_FMT_FLTP; -+ else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; -+ -+ if (AE_IS_PLANAR(format)) -+ return AV_SAMPLE_FMT_FLTP; -+ else -+ return AV_SAMPLE_FMT_FLT; -+} -+ -+AEDataFormat CActiveAEResample::GetAESampleFormat(AVSampleFormat format, int bits) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ 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_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_FLTP) return AE_FMT_FLOATP; -+ else if (format == AV_SAMPLE_FMT_DBLP) return AE_FMT_DOUBLEP; -+ -+ CLog::Log(LOGERROR, "CActiveAEResample::GetAESampleFormat - format not supported"); -+ return AE_FMT_INVALID; -+} -+ -+uint64_t CActiveAEResample::GetAVChannel(enum AEChannel aechannel) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ switch (aechannel) -+ { -+ case AE_CH_FL: return AV_CH_FRONT_LEFT; -+ case AE_CH_FR: return AV_CH_FRONT_RIGHT; -+ case AE_CH_FC: return AV_CH_FRONT_CENTER; -+ case AE_CH_LFE: return AV_CH_LOW_FREQUENCY; -+ case AE_CH_BL: return AV_CH_BACK_LEFT; -+ case AE_CH_BR: return AV_CH_BACK_RIGHT; -+ case AE_CH_FLOC: return AV_CH_FRONT_LEFT_OF_CENTER; -+ case AE_CH_FROC: return AV_CH_FRONT_RIGHT_OF_CENTER; -+ case AE_CH_BC: return AV_CH_BACK_CENTER; -+ case AE_CH_SL: return AV_CH_SIDE_LEFT; -+ case AE_CH_SR: return AV_CH_SIDE_RIGHT; -+ case AE_CH_TC: return AV_CH_TOP_CENTER; -+ case AE_CH_TFL: return AV_CH_TOP_FRONT_LEFT; -+ case AE_CH_TFC: return AV_CH_TOP_FRONT_CENTER; -+ case AE_CH_TFR: return AV_CH_TOP_FRONT_RIGHT; -+ case AE_CH_TBL: return AV_CH_TOP_BACK_LEFT; -+ case AE_CH_TBC: return AV_CH_TOP_BACK_CENTER; -+ case AE_CH_TBR: return AV_CH_TOP_BACK_RIGHT; -+ default: -+ return 0; -+ } -+} -+ -+int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ return av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel)); -+} -+ -+#endif -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h -new file mode 100644 -index 0000000..47a9e08 ---- /dev/null -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h -@@ -0,0 +1,62 @@ -+#pragma once -+/* -+ * 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 -+ * . -+ * -+ */ -+ -+#include "linux/OMXCore.h" -+ -+namespace ActiveAE -+{ -+ -+class CActiveAEResample -+{ -+public: -+ CActiveAEResample(); -+ virtual ~CActiveAEResample(); -+ bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality); -+ int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio); -+ int64_t GetDelay(int64_t base); -+ int GetBufferedSamples(); -+ int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate); -+ int GetSrcBufferSize(int samples); -+ int GetDstBufferSize(int samples); -+ static uint64_t GetAVChannelLayout(CAEChannelInfo &info); -+// static CAEChannelInfo GetAEChannelLayout(uint64_t layout); -+ static AVSampleFormat GetAVSampleFormat(AEDataFormat format); -+ static AEDataFormat GetAESampleFormat(AVSampleFormat format, int bits); -+ static uint64_t GetAVChannel(enum AEChannel aechannel); -+ int GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout); -+ -+protected: -+ void DeInit(); -+ uint64_t m_src_chan_layout, m_dst_chan_layout; -+ int m_src_rate, m_dst_rate; -+ int m_src_channels, m_dst_channels; -+ AVSampleFormat m_src_fmt, m_dst_fmt; -+ int m_src_bits, m_dst_bits; -+ -+ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input; -+ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output; -+ COMXCoreComponent m_omx_mixer; -+ bool m_Initialized; -+ AVSampleFormat m_last_src_fmt, m_last_dst_fmt; -+ int m_last_src_channels, m_last_dst_channels; -+}; -+ -+} -diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in -index c27d207..ebc74fa 100644 ---- a/xbmc/cores/AudioEngine/Makefile.in -+++ b/xbmc/cores/AudioEngine/Makefile.in -@@ -31,6 +31,7 @@ SRCS += Engines/ActiveAE/ActiveAESink.cpp - SRCS += Engines/ActiveAE/ActiveAEStream.cpp - SRCS += Engines/ActiveAE/ActiveAESound.cpp - SRCS += Engines/ActiveAE/ActiveAEResample.cpp -+SRCS += Engines/ActiveAE/ActiveAEResamplePi.cpp - SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp - - ifeq (@USE_ANDROID@,1) -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -index bf9cb7a..277f7b9 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -@@ -78,9 +78,9 @@ static void SetAudioProps(bool stream_channels, uint32_t channel_map) - CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map); - } - --static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) -+static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough) - { -- unsigned int channels = format.m_channelLayout.Count(); -+ unsigned int channels = channelLayout.Count(); - uint32_t channel_map = 0; - if (passthrough) - return 0; -@@ -119,12 +119,12 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) - // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels - // but no BR BL channels, we use the wide map in order to open only the num of channels really - // needed. -- if (format.m_channelLayout.HasChannel(AE_CH_BL) && !format.m_channelLayout.HasChannel(AE_CH_SL)) -+ if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL)) - map = map_back; - - for (unsigned int i = 0; i < channels; ++i) - { -- AEChannel c = format.m_channelLayout[i]; -+ AEChannel c = channelLayout[i]; - unsigned int chan = 0; - if ((unsigned int)c < sizeof map_normal / sizeof *map_normal) - chan = map[(unsigned int)c]; -@@ -155,9 +155,9 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) - 0xff, // 7 - 0x13, // 7.1 - }; -- uint8_t cea = format.m_channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; -+ uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; - if (cea == 0xff) -- CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, format.m_channelLayout.HasChannel(AE_CH_LFE), channels); -+ CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels); - - channel_map |= cea << 24; - -@@ -191,7 +191,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) - format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; - format.m_frameSamples = format.m_frames * channels; - -- SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough)); -+ SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough)); - - m_format = format; - m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate); -diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp -index 99e407a..8d3c86a 100644 ---- a/xbmc/linux/OMXCore.cpp -+++ b/xbmc/linux/OMXCore.cpp -@@ -448,7 +448,7 @@ void COMXCoreComponent::FlushAll() - - void COMXCoreComponent::FlushInput() - { -- if(!m_handle) -+ if(!m_handle || m_resource_error) - return; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; -@@ -470,7 +470,7 @@ void COMXCoreComponent::FlushInput() - - void COMXCoreComponent::FlushOutput() - { -- if(!m_handle) -+ if(!m_handle || m_resource_error) - return; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; --- -1.9.3 - - -From baf8fa8c24bfab7ff414b923e4d93740c7d4748a Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 1 Jun 2014 12:15:17 +0100 -Subject: [PATCH 79/82] [resamplepi] Support planar formats - ---- - .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 101 ++++++++++++--------- - 1 file changed, 59 insertions(+), 42 deletions(-) - -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -index 9a1e549..1604030 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -@@ -88,20 +88,36 @@ void CActiveAEResample::DeInit() - } - } - -+static int format_to_bits(AVSampleFormat fmt) -+{ -+ switch (fmt) -+ { -+ case AV_SAMPLE_FMT_U8: -+ case AV_SAMPLE_FMT_U8P: -+ return 8; -+ case AV_SAMPLE_FMT_S16: -+ case AV_SAMPLE_FMT_S16P: -+ return 16; -+ case AV_SAMPLE_FMT_S32: -+ case AV_SAMPLE_FMT_S32P: -+ case AV_SAMPLE_FMT_FLT: -+ case AV_SAMPLE_FMT_FLTP: -+ return 32; -+ default: -+ assert(0); -+ } -+ return 0; -+} -+ - bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) - { - LOGTIMEINIT("x"); - - CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d rate:%d->%d format:%d->%d bits:%d->%d norm:%d upmix:%d", CLASSNAME, __func__, remapLayout, src_channels, dst_channels, src_rate, dst_rate, src_fmt, dst_fmt, src_bits, dst_bits, normalize, upmix); - -- if (src_bits == 0) -- { -- if (src_fmt == AV_SAMPLE_FMT_U8) src_bits = 8; -- else if (src_fmt == AV_SAMPLE_FMT_S16) src_bits = 16; -- else if (src_fmt == AV_SAMPLE_FMT_S32) src_bits = 32; -- else if (src_fmt == AV_SAMPLE_FMT_FLT) src_bits = 32; -- } -- assert(src_bits && dst_bits); -+ // replace passed in number of bits with correct ones -+ src_bits = format_to_bits(src_fmt); -+ dst_bits = format_to_bits(dst_fmt); - - m_dst_chan_layout = dst_chan_layout; - m_dst_channels = dst_channels; -@@ -139,7 +155,7 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst - // not required for sink stage (remapLayout == true) - if (!remapLayout && normalize) - { -- av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); -+ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); - } - - if (remapLayout) -@@ -264,7 +280,13 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst - m_pcm_input.eEndian = OMX_EndianLittle; - m_pcm_input.bInterleaved = OMX_TRUE; - m_pcm_input.nBitPerSample = m_src_bits; -- m_pcm_input.ePCMMode = m_src_fmt == AV_SAMPLE_FMT_FLT ? (OMX_AUDIO_PCMMODETYPE)0x8000 : OMX_AUDIO_PCMModeLinear; -+ // 0x8000 = float, 0x10000 = planar -+ uint32_t flags = 0; -+ if (m_src_fmt == AV_SAMPLE_FMT_FLT || m_src_fmt == AV_SAMPLE_FMT_FLTP) -+ flags |= 0x8000; -+ if (m_src_fmt >= AV_SAMPLE_FMT_U8P) -+ flags |= 0x10000; -+ m_pcm_input.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; - m_pcm_input.nChannels = src_channels; - m_pcm_input.nSamplingRate = src_rate; - -@@ -278,7 +300,12 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst - m_pcm_output.eEndian = OMX_EndianLittle; - m_pcm_output.bInterleaved = OMX_TRUE; - m_pcm_output.nBitPerSample = m_dst_bits; -- m_pcm_output.ePCMMode = m_dst_fmt == AV_SAMPLE_FMT_FLT ? (OMX_AUDIO_PCMMODETYPE)0x8000 : OMX_AUDIO_PCMModeLinear; -+ flags = 0; -+ if (m_dst_fmt == AV_SAMPLE_FMT_FLT || m_dst_fmt == AV_SAMPLE_FMT_FLTP) -+ flags |= 0x8000; -+ if (m_dst_fmt >= AV_SAMPLE_FMT_U8P) -+ flags |= 0x10000; -+ m_pcm_output.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; - m_pcm_output.nChannels = dst_channels; - m_pcm_output.nSamplingRate = dst_rate; - -@@ -364,8 +391,13 @@ int CActiveAEResample::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t * - return 0; - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - -- const int s_pitch = m_pcm_input.nChannels * m_src_bits >> 3; -- const int d_pitch = m_pcm_output.nChannels * m_dst_bits >> 3; -+ const int s_planes = m_src_fmt >= AV_SAMPLE_FMT_U8P ? m_src_channels : 1; -+ const int d_planes = m_dst_fmt >= AV_SAMPLE_FMT_U8P ? m_dst_channels : 1; -+ const int s_chans = m_src_fmt >= AV_SAMPLE_FMT_U8P ? 1 : m_src_channels; -+ const int d_chans = m_dst_fmt >= AV_SAMPLE_FMT_U8P ? 1 : m_dst_channels; -+ const int s_pitch = s_chans * m_src_bits >> 3; -+ const int d_pitch = d_chans * m_dst_bits >> 3; -+ - int sent = 0; - int received = 0; - while (sent < src_samples) -@@ -377,19 +409,23 @@ int CActiveAEResample::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t * - if (omx_buffer == NULL) - return false; - -- const int max_src_samples = BUFFERSIZE / s_pitch; -- const int max_dst_samples = (long long)(BUFFERSIZE/d_pitch) * m_src_rate / (m_dst_rate + m_src_rate-1); -+ const int s_samplesize = m_src_channels * m_src_bits >> 3; -+ const int d_samplesize = m_dst_channels * m_dst_bits >> 3; -+ const int max_src_samples = BUFFERSIZE / s_samplesize; -+ const int max_dst_samples = (long long)(BUFFERSIZE / d_samplesize) * m_src_rate / (m_dst_rate + m_src_rate-1); - int send = std::min(std::min(max_dst_samples, max_src_samples), src_samples - sent); - - omx_buffer->nOffset = 0; - omx_buffer->nFlags = OMX_BUFFERFLAG_EOS; -- omx_buffer->nFilledLen = send * s_pitch; -+ omx_buffer->nFilledLen = send * s_samplesize; - - assert(omx_buffer->nFilledLen > 0 && omx_buffer->nFilledLen <= omx_buffer->nAllocLen); - - if (omx_buffer->nFilledLen) - { -- memcpy(omx_buffer->pBuffer, src_buffer[0] + sent * s_pitch, omx_buffer->nFilledLen); -+ int planesize = omx_buffer->nFilledLen / s_planes; -+ for (int i=0; i < s_planes; i++) -+ memcpy((uint8_t *)omx_buffer->pBuffer + i * planesize, src_buffer[i] + sent * s_pitch, planesize); - sent += send; - } - -@@ -428,8 +464,10 @@ int CActiveAEResample::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t * - - if (m_encoded_buffer->nFilledLen) - { -- memcpy(dst_buffer[0] + received * d_pitch, m_encoded_buffer->pBuffer, m_encoded_buffer->nFilledLen); -- received += m_encoded_buffer->nFilledLen / d_pitch; -+ int planesize = m_encoded_buffer->nFilledLen / d_planes; -+ for (int i=0; i < d_planes; i++) -+ memcpy(dst_buffer[i] + received * d_pitch, (uint8_t *)m_encoded_buffer->pBuffer + i * planesize, planesize); -+ received += m_encoded_buffer->nFilledLen / d_samplesize; - } - } - #ifdef DEBUG_VERBOSE -@@ -521,6 +559,7 @@ AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format) - 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_S24NE4MSB)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; - -@@ -528,6 +567,7 @@ AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format) - 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_S24NE4MSB)return AV_SAMPLE_FMT_S32; - else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP; - else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; - -@@ -537,29 +577,6 @@ AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format) - return AV_SAMPLE_FMT_FLT; - } - --AEDataFormat CActiveAEResample::GetAESampleFormat(AVSampleFormat format, int bits) --{ -- #ifdef DEBUG_VERBOSE -- CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -- #endif -- 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_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_FLTP) return AE_FMT_FLOATP; -- else if (format == AV_SAMPLE_FMT_DBLP) return AE_FMT_DOUBLEP; -- -- CLog::Log(LOGERROR, "CActiveAEResample::GetAESampleFormat - format not supported"); -- return AE_FMT_INVALID; --} -- - uint64_t CActiveAEResample::GetAVChannel(enum AEChannel aechannel) - { - #ifdef DEBUG_VERBOSE --- -1.9.3 -