diff options
108 files changed, 98 insertions, 13251 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 0dc08a7caf..a99bc4303b 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -38,7 +38,7 @@ Steps to reproduce the behavior: <!--- Provide a link to a live example, or an unambiguous set of steps to --> <!--- reproduce this bug. Include code to reproduce, if relevant --> <!--- Put your text below this line --> -1. +1. 2. 3. @@ -50,7 +50,7 @@ The debuglog can be found here: -### Screenshots +### Screenshots Here are some links or screenshots to help explain the problem: <!--- Put your text below this line --> @@ -71,7 +71,6 @@ Used Operating system: - [ ] iOS - [ ] Linux - [ ] OSX - - [ ] Raspberry-Pi - [ ] Windows - [ ] Windows UWP @@ -82,4 +81,4 @@ Used Operating system: <!--- End of this issue --> *note: Once the issue is made we require you to update it with new information or Kodi versions should that be required. -Team Kodi will consider your problem report however, we will not make any promises the problem will be solved.*
\ No newline at end of file +Team Kodi will consider your problem report however, we will not make any promises the problem will be solved.* diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 0dc08a7caf..e8b2c85d81 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -71,7 +71,6 @@ Used Operating system: - [ ] iOS - [ ] Linux - [ ] OSX - - [ ] Raspberry-Pi - [ ] Windows - [ ] Windows UWP diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 08b97f739a..f180606dd2 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -9037,29 +9037,7 @@ msgctxt "#16329" msgid "VAAPI - Motion compensated" msgstr "" -#. Description of OSD video settings for deinterlace method with label #16330 -#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -msgctxt "#16330" -msgid "MMAL - Advanced" -msgstr "" - -#. Description of OSD video settings for deinterlace method with label #16331 -#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -msgctxt "#16331" -msgid "MMAL - Advanced (half)" -msgstr "" - -#. Description of OSD video settings for deinterlace method with label #16332 -#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -msgctxt "#16332" -msgid "MMAL - Bob" -msgstr "" - -#. Description of OSD video settings for deinterlace method with label #16333 -#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp -msgctxt "#16333" -msgid "MMAL - Bob (half)" -msgstr "" +#empty strings from id 16330 to 16333 #. Description of OSD video settings for deinterlace method with label #16334 #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp @@ -20100,17 +20078,7 @@ msgctxt "#36433" msgid "When enabled, VAAPI render method is preferred and the CPU has less load. If you experience hangs, disable this option." msgstr "" -#. Description of setting "Enable MMAL hardware decoding of video files" -#: system/settings/settings.xml -msgctxt "#36434" -msgid "Allow hardware acceleration - MMAL" -msgstr "" - -#. Description of setting "Enable MMAL hardware decoding of video files" -#: system/settings/settings.xml -msgctxt "#36435" -msgid "Use VideoPlayer for decoding of video files with MMAL acceleration." -msgstr "" +#empty strings from id 36434 to 36435 #. Description for setting #310: "Keyboard layouts" #: system/settings/settings.xml @@ -20355,15 +20323,7 @@ msgctxt "#36541" msgid "Allows volume control from AirPlay clients." msgstr "" -#: system/settings/rbp.xml -msgctxt "#36542" -msgid "Output to both analogue (headphones) and HDMI" -msgstr "" - -#: system/settings/rbp.xml -msgctxt "#36543" -msgid "Enable this to make dialogue louder compared to background sounds when downmixing multichannel audio" -msgstr "" +#empty strings from id 36542 to 36543 #: system/settings/settings.xml msgctxt "#36544" @@ -20382,16 +20342,7 @@ msgctxt "#36546" msgid "Sets the visual depth of subtitles for stereoscopic 3D videos. The higher the value, the closer the subtitles will appear to the viewer." msgstr "" -#: system/settings/rbp.xml -msgctxt "#36547" -msgid "Use higher quality textures for covers and fanart (uses more memory)" -msgstr "" - -#: system/settings/rbp.xml -#: system/settings/gbm.xml -msgctxt "#36548" -msgid "Limits resolution of GUI to save memory. Does not affect video playback. Requires restart." -msgstr "" +#empty strings from id 36547 to 36548 #. Description of setting with label #1268 "iOS 8 compatibility mode" #: system/settings/settings.xml @@ -21024,28 +20975,7 @@ msgctxt "#37016" msgid "Select this option if your receiver is capable of decoding Dolby Digital Plus (E-AC3) streams." msgstr "" -#: system/settings/rbp.xml -msgctxt "#37017" -msgid "Dual audio output" -msgstr "" - -#: system/settings/rbp.xml -msgctxt "#37018" -msgid "Boost centre channel when downmixing" -msgstr "" - -#empty string with id 37019 - -#: system/settings/rbp.xml -msgctxt "#37020" -msgid "Enable higher colour depth artwork" -msgstr "" - -#: system/settings/rbp.xml -#: system/settings/gbm.xml -msgctxt "#37021" -msgid "Set GUI resolution limit" -msgstr "" +#empty strings from id 37017 to 37021 #: xbmc/network/upnp/UPnPPlayer.cpp msgctxt "#37022" @@ -21057,40 +20987,34 @@ msgctxt "#37023" msgid "Do you wish to stop playback on the remote device?" msgstr "" -#: system/settings/rbp.xml -msgctxt "#37024" -msgid "Select this if the audio out connection only supports multichannel audio as Dolby Digital 5.1 (AC3), this allows multichannel audio such as AAC 5.1 or FLAC 5.1 to be listened to in 5.1 surround sound. Note: Not recommended on Pi as this requires a lot of CPU." -msgstr "" +#empty string id 37024 #: system/settings/settings.xml msgctxt "#37025" msgid "Configure audio encoder settings such as quality and compression level" msgstr "" -#: system/settings/rbp.xml #: system/settings/android.xml msgctxt "#37026" msgid "Auto" msgstr "" -#: system/settings/rbp.xml +#: system/settings/android.xml msgctxt "#37027" msgid "540" msgstr "" -#: system/settings/rbp.xml #: system/settings/android.xml #: system/settings/gbm.xml msgctxt "#37028" msgid "720" msgstr "" -#: system/settings/rbp.xml +#: system/settings/android.xml msgctxt "#37029" msgid "900" msgstr "" -#: system/settings/rbp.xml #: system/settings/android.xml #: system/settings/gbm.xml msgctxt "#37030" @@ -21193,12 +21117,7 @@ msgctxt "#37046" msgid "1080" msgstr "" -#empty strings from id 37047 to 38009 - -#: system/settings/rbp.xml -msgctxt "#38010" -msgid "GPU accelerated" -msgstr "" +#empty strings from id 37047 to 38010 #. Setting #38011 "Show All Items entry" #: system/settings/settings.xml @@ -21279,27 +21198,7 @@ msgctxt "#38026" msgid "Appearances" msgstr "" -#: system/settings/rbp.xml -msgctxt "#38027" -msgid "Decode the stereo stream from 3D files" -msgstr "" - -#. Description of setting with label #38027 "Decode the stereo stream from 3D files" -#: system/settings/rbp.xml -msgctxt "#38028" -msgid "If enabled, videos created in Multiview Video Coding (MVC) format can also be watched in stereoscopic 3D. MVC format is typically found on 3D Blu-rays.[CR]Note: Processing of this data may reduce playback performance, so only enable if you require stereoscopic 3D support." -msgstr "" - -#: system/settings/rbp.xml -msgctxt "#38029" -msgid "Enable Full HD HDMI modes for stereoscopic 3D" -msgstr "" - -#. Description of setting "Enable Full HD HDMI modes for stereoscopic 3D" with label #38029 -#: system/settings/rbp.xml -msgctxt "#38030" -msgid "This option uses frame-packing to output full resolution for 3D through HDMI.[CR]Enabling this improves quality of Multiview Video Coding (MVC) videos, but may not be supported by all displays." -msgstr "" +#empty strings from id 38027 to 38030 #. Label for an option to select the video stream to play if current video has more than one video stream #: xbmc/video/dialogs/GUIDialogVideoSettings.cpp diff --git a/cmake/addons/README.md b/cmake/addons/README.md index 17e6460d75..a723085bd1 100644 --- a/cmake/addons/README.md +++ b/cmake/addons/README.md @@ -18,7 +18,7 @@ where List of platforms to build an add-on for (or *all*). Negating platforms is supported using a leading exclamation mark, e.g. *!windows*. -Available platforms are: linux, windows, osx, ios, android, rbpi and freebsd. +Available platforms are: linux, windows, osx, ios, android and freebsd. #### Attention If no add-on definitions could be found, the buildsystem assumes that the bootstrapping of the add-on definition repositories hasn't been performed yet and automatically executes the add-on bootstrapping buildsystem located in the *bootstrap* sub-directory with the default settings (i.e. *all* add-ons from all pre-defined add-on definition repositories are bootstrapped into the directory pointed to by the *ADDONS_DEFINITION_DIR* option). @@ -44,4 +44,4 @@ Buildsystem will print a warning if you use any of the below-listed variables. F ## Building The buildsystem makes some assumptions about the environment which must be met by whoever uses it: -- Any dependencies of the add-ons must already be built and their include and library files must be present in the path pointed to by `<CMAKE_PREFIX_PATH>` (in *include* and *lib* sub-directories)
\ No newline at end of file +- Any dependencies of the add-ons must already be built and their include and library files must be present in the path pointed to by `<CMAKE_PREFIX_PATH>` (in *include* and *lib* sub-directories) diff --git a/cmake/installdata/rbpi/lirc.txt b/cmake/installdata/rbpi/lirc.txt deleted file mode 120000 index e89ae50094..0000000000 --- a/cmake/installdata/rbpi/lirc.txt +++ /dev/null @@ -1 +0,0 @@ -../linux/lirc.txt
\ No newline at end of file diff --git a/cmake/modules/FindEGL.cmake b/cmake/modules/FindEGL.cmake index 0b73eb80bc..b00fe08a25 100644 --- a/cmake/modules/FindEGL.cmake +++ b/cmake/modules/FindEGL.cmake @@ -14,18 +14,14 @@ # # EGL::EGL - The EGL library -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - set(_brcmprefix brcm) -endif() - if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_EGL ${_brcmprefix}egl QUIET) + pkg_check_modules(PC_EGL egl QUIET) endif() find_path(EGL_INCLUDE_DIR EGL/egl.h PATHS ${PC_EGL_INCLUDEDIR}) -find_library(EGL_LIBRARY NAMES ${_brcmprefix}EGL egl +find_library(EGL_LIBRARY NAMES EGL egl PATHS ${PC_EGL_LIBDIR}) set(EGL_VERSION ${PC_EGL_VERSION}) diff --git a/cmake/modules/FindMMAL.cmake b/cmake/modules/FindMMAL.cmake deleted file mode 100644 index 0b5f5564ec..0000000000 --- a/cmake/modules/FindMMAL.cmake +++ /dev/null @@ -1,55 +0,0 @@ -# - Try to find MMAL -# Once done this will define -# -# MMAL_FOUND - system has MMAL -# MMAL_INCLUDE_DIRS - the MMAL include directory -# MMAL_LIBRARIES - The MMAL libraries - -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_MMAL mmal QUIET) -endif() - - -find_path(MMAL_INCLUDE_DIR NAMES interface/mmal/mmal.h PATHS ${PC_MMAL_INCLUDEDIR}) -find_library(MMAL_LIBRARY NAMES mmal libmmal PATHS ${PC_MMAL_LIBDIR}) -find_library(MMALCORE_LIBRARY NAMES mmal_core libmmal_core PATHS ${PC_MMAL_LIBDIR}) -find_library(MMALUTIL_LIBRARY NAMES mmal_util libmmal_util PATHS ${PC_MMAL_LIBDIR}) -find_library(MMALCLIENT_LIBRARY NAMES mmal_vc_client libmmal_vc_client PATHS ${PC_MMAL_LIBDIR}) -find_library(MMALCOMPONENT_LIBRARY NAMES mmal_components libmmal_components PATHS ${PC_MMAL_LIBDIR}) -find_library(BCM_LIBRARY NAMES bcm_host libbcm_host PATHS ${PC_MMAL_LIBDIR}) -find_library(VCHIQ_LIBRARY NAMES vchiq_arm libvchiq_arm PATHS ${PC_MMAL_LIBDIR}) -find_library(VCHOSTIF_LIBRARY NAMES vchostif libvchostif PATHS ${PC_MMAL_LIBDIR}) -find_library(VCILCS_LIBRARY NAMES vcilcs libvcilcs PATHS ${PC_MMAL_LIBDIR}) -find_library(VCOS_LIBRARY NAMES vcos libvcos PATHS ${PC_MMAL_LIBDIR}) -find_library(VCSM_LIBRARY NAMES vcsm libvcsm PATHS ${PC_MMAL_LIBDIR}) -find_library(CONTAINER_LIBRARY NAMES containers libcontainers PATHS ${PC_MMAL_LIBDIR}) - - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(MMAL REQUIRED_VARS MMAL_INCLUDE_DIR - MMAL_LIBRARY MMALCORE_LIBRARY MMALUTIL_LIBRARY - MMALCLIENT_LIBRARY MMALCOMPONENT_LIBRARY BCM_LIBRARY - VCHIQ_LIBRARY VCOS_LIBRARY VCSM_LIBRARY VCHOSTIF_LIBRARY - VCILCS_LIBRARY CONTAINER_LIBRARY) - - -if(MMAL_FOUND) - set(MMAL_INCLUDE_DIRS ${MMAL_INCLUDE_DIR}) - set(MMAL_LIBRARIES ${MMAL_LIBRARY} ${MMALCORE_LIBRARY} ${MMALUTIL_LIBRARY} - ${MMALCLIENT_LIBRARY} ${MMALCOMPONENT_LIBRARY} - ${BCM_LIBRARY} ${VCHIQ_LIBRARY} ${VCOS_LIBRARY} ${VCSM_LIBRARY} - ${VCHOSTIF_LIBRARY} ${VCILCS_LIBRARY} ${CONTAINER_LIBRARY} - CACHE STRING "mmal libraries" FORCE) - list(APPEND MMAL_DEFINITIONS -DHAVE_MMAL=1 -DHAS_MMAL=1) - - if(NOT TARGET MMAL::MMAL) - add_library(MMAL::MMAL UNKNOWN IMPORTED) - set_target_properties(MMAL::MMAL PROPERTIES - IMPORTED_LOCATION "${MMAL_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${MMAL_INCLUDE_DIR}") - endif() -endif() - -mark_as_advanced(MMAL_INCLUDE_DIRS MMAL_LIBRARIES MMAL_DEFINITIONS - MMAL_LIBRARY MMALCORE_LIBRARY MMALUTIL_LIBRARY MMALCLIENT_LIBRARY MMALCOMPONENT_LIBRARY BCM_LIBRARY - VCHIQ_LIBRARY VCOS_LIBRARY VCSM_LIBRARY VCHOSTIF_LIBRARY VCILCS_LIBRARY CONTAINER_LIBRARY) diff --git a/cmake/modules/FindOpenGLES.cmake b/cmake/modules/FindOpenGLES.cmake index 43a1367a52..3dbaa447fa 100644 --- a/cmake/modules/FindOpenGLES.cmake +++ b/cmake/modules/FindOpenGLES.cmake @@ -10,18 +10,14 @@ # OPENGLES_LIBRARIES - the OpenGLES libraries # OPENGLES_DEFINITIONS - the OpenGLES definitions -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - set(_brcmprefix brcm) -endif() - if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_OPENGLES ${_brcmprefix}glesv2 QUIET) + pkg_check_modules(PC_OPENGLES glesv2 QUIET) endif() if(NOT CORE_SYSTEM_NAME STREQUAL darwin_embedded) find_path(OPENGLES_INCLUDE_DIR GLES2/gl2.h PATHS ${PC_OPENGLES_INCLUDEDIR}) - find_library(OPENGLES_gl_LIBRARY NAMES ${_brcmprefix}GLESv2 + find_library(OPENGLES_gl_LIBRARY NAMES GLESv2 PATHS ${PC_OPENGLES_LIBDIR}) else() find_library(OPENGLES_gl_LIBRARY NAMES OpenGLES diff --git a/cmake/platform/freebsd/rbpi.cmake b/cmake/platform/freebsd/rbpi.cmake deleted file mode 100644 index f0956939b6..0000000000 --- a/cmake/platform/freebsd/rbpi.cmake +++ /dev/null @@ -1 +0,0 @@ -include(cmake/platform/linux/rbpi.cmake) diff --git a/cmake/platform/linux/rbpi.cmake b/cmake/platform/linux/rbpi.cmake deleted file mode 100644 index 3dde57dce5..0000000000 --- a/cmake/platform/linux/rbpi.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(PLATFORM_REQUIRED_DEPS OpenGLES EGL MMAL LibInput Xkbcommon) -set(APP_RENDER_SYSTEM gles) -list(APPEND PLATFORM_DEFINES -D_ARMEL -DTARGET_RASPBERRY_PI) diff --git a/cmake/scripts/linux/ArchSetup.cmake b/cmake/scripts/linux/ArchSetup.cmake index 04fc6e3ffd..b68efe3bd0 100644 --- a/cmake/scripts/linux/ArchSetup.cmake +++ b/cmake/scripts/linux/ArchSetup.cmake @@ -37,16 +37,6 @@ else() endif() endif() -# temp until further cleanup is done -# add Raspberry Pi 2 and 3 specific flags -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - if(CPU MATCHES "cortex-a7") - set(NEON_FLAGS "-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -mvectorize-with-neon-quad") - elseif(CPU MATCHES "cortex-a53") - set(NEON_FLAGS "-fPIC -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mvectorize-with-neon-quad") - endif() -endif() - if((CMAKE_BUILD_TYPE STREQUAL Release OR CMAKE_BUILD_TYPE STREQUAL MinSizeRel) AND CMAKE_COMPILER_IS_GNUCXX) # Make sure we strip binaries in Release build diff --git a/cmake/treedata/common/rbpi/rbpi.txt b/cmake/treedata/common/rbpi/rbpi.txt deleted file mode 100644 index dc268e773c..0000000000 --- a/cmake/treedata/common/rbpi/rbpi.txt +++ /dev/null @@ -1,2 +0,0 @@ -xbmc/cores/omxplayer cores/omxplayer -xbmc/windowing/rpi windowing/rpi diff --git a/cmake/treedata/freebsd/subdirs.txt b/cmake/treedata/freebsd/subdirs.txt index 79e3462cf4..a7433a5a62 100644 --- a/cmake/treedata/freebsd/subdirs.txt +++ b/cmake/treedata/freebsd/subdirs.txt @@ -1,5 +1,3 @@ -xbmc/cores/RetroPlayer/process/rbpi cores/RetroPlayer/process/rbpi -xbmc/cores/VideoPlayer/Process/rbpi cores/VideoPlayer/Process/rbpi xbmc/input/touch input/touch xbmc/input/touch/generic input/touch/generic xbmc/platform/freebsd platform/freebsd diff --git a/cmake/treedata/linux/subdirs.txt b/cmake/treedata/linux/subdirs.txt index 51a7cbd73a..35c8d88c15 100644 --- a/cmake/treedata/linux/subdirs.txt +++ b/cmake/treedata/linux/subdirs.txt @@ -1,5 +1,3 @@ -xbmc/cores/RetroPlayer/process/rbpi cores/RetroPlayer/process/rbpi -xbmc/cores/VideoPlayer/Process/rbpi cores/VideoPlayer/Process/rbpi xbmc/input/touch input/touch xbmc/input/touch/generic input/touch/generic xbmc/platform/linux platform/linux diff --git a/docs/README.RaspberryPi.md b/docs/README.RaspberryPi.md index 4d8ce4f0e6..d5a9141b24 100644 --- a/docs/README.RaspberryPi.md +++ b/docs/README.RaspberryPi.md @@ -1,242 +1,5 @@ ![Kodi Logo](resources/banner_slim.png) # Raspberry Pi build guide -This guide has been tested with Ubuntu 16.04 (Xenial) x86_64 and 18.04 (Bionic). It is meant to cross-compile Kodi for the Raspberry Pi using **[Kodi's unified depends build system](../tools/depends/README.md)**. Please read it in full before you proceed to familiarize yourself with the build procedure. -If you're looking to build Kodi natively using **[Raspbian](https://www.raspberrypi.org/downloads/raspbian/)**, you should follow the **[Ubuntu guide](README.Ubuntu.md)** instead. Several other distributions have **[specific guides](README.md)** and a general **[Linux guide](README.Linux.md)** is also available. - -## Table of Contents -1. **[Document conventions](#1-document-conventions)** -2. **[Install the required packages](#2-install-the-required-packages)** -3. **[Get the source code](#3-get-the-source-code)** - 3.1. **[Get Raspberry Pi tools and firmware](#31-get-raspberry-pi-tools-and-firmware)** -4. **[Build tools and dependencies](#4-build-tools-and-dependencies)** -5. **[Build Kodi](#5-build-kodi)** -6. **[Docker](#6-docker)** -7. **[Troubleshooting](#7-troubleshooting)** - 7.1. **[ImportError: No module named \_sysconfigdata\_nd](#71-importerror-no-module-named-_sysconfigdata_nd)** - 7.2. **[Errors connecting to any internet (TLS) service](#72-errors-connecting-to-any-internet-tls-service)** - -## 1. Document conventions -This guide assumes you are using `terminal`, also known as `console`, `command-line` or simply `cli`. Commands need to be run at the terminal, one at a time and in the provided order. - -This is a comment that provides context: -``` -this is a command -this is another command -and yet another one -``` - -**Example:** Clone Kodi's current master branch: -``` -git clone https://github.com/xbmc/xbmc kodi -``` - -Commands that contain strings enclosed in angle brackets denote something you need to change to suit your needs. -``` -git clone -b <branch-name> https://github.com/xbmc/xbmc kodi -``` - -**Example:** Clone Kodi's current Krypton branch: -``` -git clone -b Krypton https://github.com/xbmc/xbmc kodi -``` - -Several different strategies are used to draw your attention to certain pieces of information. In order of how critical the information is, these items are marked as a note, tip, or warning. For example: - -**NOTE:** Linux is user friendly... It's just very particular about who its friends are. -**TIP:** Algorithm is what developers call code they do not want to explain. -**WARNING:** Developers don't change light bulbs. It's a hardware problem. - -**[back to top](#table-of-contents)** | **[back to section top](#1-document-conventions)** - -## 2. Install the required packages -**NOTE:** Kodi requires a compiler with C++14 support, i.e. gcc >= 4.9 or clang >= 3.4 - -Install build dependencies needed to cross-compile Kodi for the Raspberry Pi: -``` -sudo apt install autoconf bison build-essential curl default-jdk gawk git gperf libcurl4-openssl-dev zlib1g-dev -``` - -**[back to top](#table-of-contents)** - -## 3. Get the source code -Change to your `home` directory: -``` -cd $HOME -``` - -Clone Kodi's current master branch: -``` -git clone https://github.com/xbmc/xbmc kodi -``` - -### 3.1. Get Raspberry Pi tools and firmware -Clone Raspberry Pi tools: -``` -git clone https://github.com/raspberrypi/tools --depth=1 -``` - -Clone Raspberry Pi firmware: -``` -git clone https://github.com/raspberrypi/firmware --depth=1 -``` - -**[back to top](#table-of-contents)** - -## 4. Build tools and dependencies -Create target directory: -``` -mkdir $HOME/kodi-rpi -``` - -Prepare to configure build: -``` -cd $HOME/kodi/tools/depends -./bootstrap -``` - -**TIP:** Look for comments starting with `Or ...` and only execute the command(s) you need. - -Configure build for Raspberry Pi 1: -``` -./configure --host=arm-linux-gnueabihf --prefix=$HOME/kodi-rpi --with-toolchain=$HOME/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf --with-firmware=$HOME/firmware --with-platform=raspberry-pi --disable-debug -``` - -Or configure build for Raspberry Pi 2 and 3: -``` -./configure --host=arm-linux-gnueabihf --prefix=$HOME/kodi-rpi --with-toolchain=$HOME/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf --with-firmware=$HOME/firmware --with-platform=raspberry-pi2 --disable-debug -``` - -Build tools and dependencies: -``` -make -j$(getconf _NPROCESSORS_ONLN) -``` - -**TIP:** By adding `-j<number>` to the make command, you can choose how many concurrent jobs will be used and expedite the build process. It is recommended to use `-j$(getconf _NPROCESSORS_ONLN)` to compile on all available processor cores. The build machine can also be configured to do this automatically by adding `export MAKEFLAGS="-j$(getconf _NPROCESSORS_ONLN)"` to your shell config (e.g. `~/.bashrc`). - -**[back to top](#table-of-contents)** | **[back to section top](#4-build-tools-and-dependencies)** - -## 5. Build Kodi -Configure CMake build: -``` -cd $HOME/kodi -make -C tools/depends/target/cmakebuildsys -``` - -**TIP:** BUILD_DIR can be provided as an argument to cmakebuildsys. This allows you to provide an alternate build location. Change all paths onwards as required if BUILD_DIR option used. -``` -mkdir $HOME/kodi-build -make -C tools/depends/target/cmakebuildsys BUILD_DIR=$HOME/kodi-build -``` - -Build Kodi: -``` -cd $HOME/kodi/build -make -j$(getconf _NPROCESSORS_ONLN) -``` - -Install to target directory: -``` -make install -``` - -After the build process is finished, you can find the files ready to be installed inside `$HOME/kodi-rpi`. Look for a directory called `raspberry-pi-release` or `raspberry-pi2-release`. - -**[back to top](#table-of-contents)** - - -## 6. Docker - -If you encounter issues with the previous instructions, or if you don't have a proper system for cross-compiling Kodi, it's also possible to use a [Docker](https://www.docker.com/) image to perform the build. This method, although it should work just like the build instructions mentioned above, is **not** supported. Therefore, issues related specifically to Docker should **not** be opened. - -Here is an example Dockerfile, summarizing basically all the instructions described above (/!\ may not be up to date with the actual instructions!). **Please read the comments as they describe things you NEED to change and/or consider before building.** - -```Dockerfile -# Change 'latest' to the officially supported version of Ubuntu for cross-compilation -FROM ubuntu:latest - -RUN apt-get update && apt-get upgrade -y -RUN apt-get -y install autoconf bison build-essential curl default-jdk gawk git gperf libcurl4-openssl-dev zlib1g-dev file - -# The 'HOME' variable doesn't really matter - it is only the location of the files within the image -ARG HOME=/home/pi -# This is the location kodi will be built for, that means you will have to put the built files in -# this directory afterwards. It is important because many paths end up hardcoded during the build. -ARG PREFIX=/opt/kodi - -RUN mkdir $PREFIX -WORKDIR $HOME - -# Replace 'master' with whichever branch/tag you wish to build - be careful with nightly builds! -RUN git clone -b master https://github.com/xbmc/xbmc kodi --depth 1 -RUN git clone https://github.com/raspberrypi/tools --depth=1 -RUN git clone https://github.com/raspberrypi/firmware --depth=1 - -WORKDIR $HOME/kodi/tools/depends -RUN ./bootstrap - -# Change this if you're building on a RPi1, as described above -RUN ./configure --host=arm-linux-gnueabihf --prefix=$PREFIX --with-toolchain=$HOME/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf --with-firmware=$HOME/firmware --with-platform=raspberry-pi2 --disable-debug - -RUN make -j$(getconf _NPROCESSORS_ONLN) - -WORKDIR $HOME/kodi -# This step builds all the binary addons. -# Kodi - at its core - works fine without them, however they are used by many other addons. -# Therefore, it is recommended to simply compile all of them. -RUN make -j$(getconf _NPROCESSORS_ONLN) -C tools/depends/target/binary-addons -RUN make -C tools/depends/target/cmakebuildsys - -WORKDIR $HOME/kodi/build -RUN make -j$(getconf _NPROCESSORS_ONLN) - -RUN make install -RUN tar zfc /kodi.tar.gz $PREFIX -``` - -You can then build the image, and afterwards retrieve the build files from a dummy container: - -```bash -docker build -t kodi_build . -docker run --name some-temp-container-name kodi_build /bin/bash -docker cp some-temp-container-name:/kodi.tar.gz ./ -docker rm some-temp-container-name -``` - -You should now have a file `kodi.tar.gz` in your current directory. Now you need to uncompress this file in the `$PREFIX` directory (as mentioned in the Dockerfile) of your Raspberry. Note that the archive contains multiple directories in its root, but only the `raspberry-pi2-release` (or `raspberry-pi-release`) is needed, so you can delete the others safely. If you encounter problems, please take a look at the [Troubleshooting](#7-troubleshooting) section below before filing an issue. - -**[back to top](#table-of-contents)** - -## 7. Troubleshooting - -### 7.1 ImportError: No module named \_sysconfigdata\_nd - -This is caused by an issue with a python package. The solution is to simply add a missing symlink so the library can be found, i.e.: - -```bash -ln -s /usr/lib/python2.7/plat-arm-linux-gnueabihf/_sysconfigdata_nd.py /usr/lib/python2.7/ -``` - -### 7.2 Errors connecting to any internet (TLS) service - -First, you should enable debug logging (instructions [here](https://kodi.wiki/view/Log_file)). Then you need to check the logs and find what the source of your problem is. If, when trying to access TLS services (e.g. when installing an addon), the connection fails and your log contains entries such as: - -```log -# note that those logs appear when enabling component-specific logs -> libcurl -2019-05-19 17:18:39.570 T:1854288832 DEBUG: Curl::Debug - TEXT: SSL certificate problem: unable to get local issuer certificate -2019-05-19 17:18:39.570 T:1854288832 DEBUG: Curl::Debug - TEXT: Closing connection 0 - -# this is part of the regular Kodi logs -2019-05-19 17:18:39.570 T:1854288832 ERROR: CCurlFile::FillBuffer - Failed: Peer certificate cannot be authenticated with given CA certificates(60) -``` - -Then, you need to define the environment variable `SSL_CERT_FILE` so it points to your system's certificate file. Depending on how you start Kodi, putting this line in your in your `.profile` file should fix this issue: - -```bash -export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt -``` - -Note that you need to define this variable *before* starting Kodi. For example, if you start Kodi on startup through a crontab, your `.profile` will *not* be sourced. - -**[back to top](#table-of-contents)** +The Raspberry Pi platform has been merged into the GBM build. See [README.Linux.md](README.Linux.md). diff --git a/docs/README.md b/docs/README.md index 3c033f8435..836f1c39a8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,7 +16,6 @@ Kodi uses CMake as its building system but instructions are highly dependent on <a href="README.Linux.md" title="Linux"><img src="resources/linux.svg" height="78"></a> <a href="README.macOS.md" title="macOS"><img src="resources/macos.svg" height="78"></a> <a href="README.openSUSE.md" title="openSUSE"><img src="resources/opensuse.svg" height="78"></a> - <a href="README.RaspberryPi.md" title="Raspberry Pi"><img src="resources/raspberrypi.svg" height="78"></a> <a href="README.tvOS.md" title="tvOS"><img src="resources/tvos.svg" height="78"></a> <a href="README.Ubuntu.md" title="Ubuntu"><img src="resources/ubuntu.svg" height="78"></a> <a href="README.Windows.md" title="Windows"><img src="resources/windows.svg" height="78"></a> diff --git a/docs/resources/raspberrypi.svg b/docs/resources/raspberrypi.svg deleted file mode 100644 index b1121fb85f..0000000000 --- a/docs/resources/raspberrypi.svg +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg width="100" height="100" version="1.1" viewBox="0 0 26.458333 26.458334" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <metadata>
- <rdf:RDF>
- <cc:Work rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
- <dc:title/>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <rect x="-1.4211e-14" y="8.5449e-6" width="26.458" height="26.458" fill="#c51a4a" stroke-width=".27763"/>
- <path d="m9.9286 3.97c-0.093646 3e-3 -0.19449 0.0375-0.30893 0.12775-0.2802-0.10803-0.55196-0.14559-0.79495 0.0744-0.37521-0.0487-0.49712 0.0518-0.58952 0.16905-0.082373-2e-3 -0.61632-0.0847-0.86123 0.2806-0.61536-0.0728-0.80985 0.36195-0.58947 0.76742-0.12571 0.19454-0.25596 0.38676 0.037957 0.75772-0.10396 0.20656-0.039487 0.43068 0.20542 0.70187-0.06464 0.29046 0.062431 0.49532 0.29034 0.65502-0.042659 0.39742 0.36444 0.6285 0.48596 0.71082 0.046682 0.23154 0.14395 0.4501 0.6089 0.57089 0.076707 0.34512 0.35612 0.40472 0.62675 0.47713-0.89437 0.5199-1.6613 1.2039-1.6561 2.8822l-0.13104 0.2337c-1.0255 0.62363-1.9482 2.6281-0.50534 4.2573 0.094213 0.50999 0.25227 0.8763 0.393 1.2817 0.21046 1.6336 1.5841 2.3986 1.9465 2.4891 0.53089 0.40438 1.0963 0.78809 1.8615 1.0569 0.7213 0.7439 1.5028 1.0274 2.2885 1.027 0.01156 0 1.602-0.28303 2.3233-1.027 0.76515-0.26882 1.3306-0.65253 1.8615-1.0569 0.36229-0.0905 1.7359-0.85546 1.9464-2.4891 0.14072-0.40541 0.29878-0.77172 0.39306-1.2817 1.4427-1.6294 0.52012-3.6339-0.5054-4.2576l-0.13121-0.23369c0.0052-1.6782-0.76175-2.3622-1.6561-2.8822 0.27057-0.0724 0.55004-0.132 0.62669-0.47713 0.46495-0.12084 0.56228-0.33935 0.6089-0.57089 0.12158-0.0823 0.52862-0.3134 0.48602-0.71082 0.22786-0.1597 0.35493-0.36461 0.29029-0.65501 0.24496-0.2712 0.30938-0.49532 0.20542-0.70193 0.29397-0.37073 0.16356-0.56296 0.03801-0.7575 0.22026-0.40546 0.02589-0.84027-0.5897-0.76742-0.2448-0.36529-0.77863-0.28235-0.86123-0.28065-0.09234-0.11722-0.21426-0.21766-0.58947-0.169-0.24298-0.21998-0.51469-0.18247-0.79495-0.0744-0.33278-0.26259-0.55298-0.0521-0.80452 0.0275-0.40286-0.13166-0.49503 0.0487-0.69297 0.12215-0.4394-0.0929-0.57293 0.10928-0.78356 0.32263l-0.24502-5e-3c-0.66272 0.39056-0.99198 1.1858-1.1087 1.5947-0.11676-0.40891-0.44523-1.2042-1.1078-1.5947l-0.24502 5e-3c-0.21092-0.21335-0.34439-0.41549-0.78379-0.32263-0.198-0.0735-0.28983-0.25381-0.69303-0.12215-0.16508-0.0522-0.31691-0.16078-0.49565-0.15522l-4.5488 7.9878" fill="#ffffff" stroke-width=".056652"/>
- <g transform="translate(0,-270.54)" fill="#c51a4a" stroke-width=".056652">
- <path d="m8.6091 276.23c1.7583 0.9065 2.7804 1.6398 3.3405 2.2643-0.28678 1.1494-1.7829 1.2019-2.3299 1.1696 0.112-0.0521 0.20548-0.1146 0.23862-0.21052-0.13727-0.0976-0.62397-0.0103-0.96377-0.20117 0.13053-0.0271 0.1916-0.0534 0.25261-0.14973-0.32099-0.10237-0.6668-0.19064-0.87018-0.36026 0.10974 1e-3 0.21222 0.0246 0.35555-0.0748-0.28751-0.15495-0.59434-0.27777-0.83273-0.51464 0.14866-4e-3 0.30893-1e-3 0.35555-0.0561-0.26315-0.16305-0.48523-0.34433-0.66901-0.54267 0.20803 0.0251 0.2959 4e-3 0.3462-0.0328-0.19896-0.20378-0.45073-0.37583-0.57077-0.62692 0.15443 0.0533 0.29578 0.0736 0.39764-5e-3 -0.067586-0.15251-0.35719-0.24248-0.52398-0.59888 0.16265 0.0158 0.3351 0.0355 0.3696 0-0.075461-0.30751-0.20497-0.48041-0.33198-0.65955 0.34802-5e-3 0.87534 1e-3 0.85149-0.028l-0.21522-0.21987c0.33997-0.0915 0.68782 0.0147 0.94037 0.0935 0.11336-0.0895-0.00204-0.20259-0.14038-0.31811 0.28893 0.0386 0.54998 0.10498 0.786 0.19647 0.12605-0.11381-0.081863-0.22768-0.18248-0.3415 0.44636 0.0846 0.63547 0.20367 0.82339 0.32281 0.13636-0.1307 0.0078-0.2418-0.084185-0.35555 0.33657 0.12463 0.50993 0.28558 0.6924 0.44444 0.06186-0.0835 0.15721-0.14475 0.04209-0.34621 0.23896 0.13772 0.41894 0.30003 0.55208 0.48189 0.14786-0.0942 0.08809-0.22287 0.08889-0.34156 0.24836 0.20202 0.40597 0.41702 0.59887 0.62692 0.03886-0.0283 0.07286-0.12424 0.10294-0.27601 0.59241 0.57474 1.4296 2.0225 0.21516 2.5965-1.0335-0.8524-2.2679-1.472-3.6357-1.9368l3.966e-4 -2.3e-4"/>
- <path d="m17.939 276.23c-1.758 0.90661-2.7802 1.6397-3.3402 2.2643 0.28678 1.1494 1.7828 1.2019 2.3298 1.1696-0.112-0.0521-0.20548-0.1146-0.23856-0.21052 0.13727-0.0976 0.62397-0.0103 0.96371-0.20117-0.13053-0.0271-0.19154-0.0534-0.25261-0.14973 0.32105-0.10237 0.66686-0.19064 0.87018-0.36026-0.10974 1e-3 -0.21222 0.0246-0.35555-0.0748 0.28757-0.15495 0.5944-0.27777 0.83279-0.51464-0.14871-4e-3 -0.30898-1e-3 -0.35555-0.0561 0.26315-0.16305 0.48523-0.34433 0.66901-0.54267-0.20808 0.0251-0.2959 4e-3 -0.3462-0.0328 0.19891-0.20378 0.45073-0.37583 0.57077-0.62692-0.15449 0.0533-0.29584 0.0736-0.3977-5e-3 0.06759-0.15251 0.35725-0.24248 0.52398-0.59888-0.16259 0.0158-0.3351 0.0355-0.3696 0 0.07563-0.30762 0.20514-0.48052 0.33215-0.65966-0.34802-5e-3 -0.87534 1e-3 -0.85149-0.028l0.21522-0.21993c-0.33997-0.0915-0.68782 0.0147-0.94037 0.0936-0.11336-0.0894 2e-3 -0.20259 0.14033-0.3181-0.28887 0.0385-0.54998 0.10498-0.78594 0.19647-0.12611-0.11382 0.08186-0.22769 0.18248-0.3415-0.44636 0.0846-0.63547 0.20366-0.82344 0.3228-0.13636-0.13069-0.0078-0.24179 0.08424-0.35555-0.33657 0.12464-0.50993 0.28559-0.6924 0.44444-0.06192-0.0835-0.15721-0.14474-0.04215-0.3462-0.2389 0.13772-0.41889 0.30003-0.55202 0.48189-0.14786-0.0942-0.08809-0.22293-0.08889-0.34156-0.24836 0.20202-0.40597 0.41696-0.59887 0.62691-0.03886-0.0283-0.07286-0.12423-0.10294-0.27606-0.59241 0.57479-1.4296 2.0226-0.21516 2.5966 1.0329-0.85262 2.2672-1.4721 3.6352-1.9369h-2.26e-4"/>
- <path d="m15.403 287.93c0.0061 1.0726-0.93188 1.9467-2.095 1.9523-1.1632 6e-3 -2.1111-0.85924-2.1172-1.9318-5.6e-5 -7e-3 -5.6e-5 -0.0136 0-0.0204-0.0061-1.0726 0.93182-1.9466 2.095-1.9523 1.1632-6e-3 2.111 0.85925 2.1172 1.9318v0.0205"/>
- <path d="m12.078 282.39c0.87267 0.5718 1.03 1.8678 0.35136 2.8947s-1.9362 1.396-2.8089 0.82423c-0.87267-0.57179-1.0299-1.8678-0.35136-2.8947 0.67864-1.0269 1.9362-1.396 2.8089-0.82424"/>
- <path d="m14.434 282.28c-0.87262 0.57174-1.0299 1.8678-0.35136 2.8947 0.67864 1.0269 1.9362 1.396 2.8089 0.82418 0.87267-0.57174 1.03-1.8677 0.35136-2.8947-0.67858-1.0269-1.9362-1.3959-2.8089-0.82418"/>
- <path d="m7.7169 283.32c0.94219-0.25256 0.3181 3.8979-0.44852 3.5573-0.84327-0.67825-1.1149-2.6645 0.44852-3.5573"/>
- <path d="m18.605 283.27c-0.9423-0.2525-0.3181 3.8981 0.44852 3.5576 0.84327-0.6783 1.1149-2.6648-0.44852-3.5576"/>
- <path d="m15.404 280.18c1.626-0.27454 2.979 0.6915 2.9243 2.4546-0.05348 0.67598-3.5234-2.354-2.9243-2.4546"/>
- <path d="m10.911 280.13c-1.6261-0.2746-2.979 0.69167-2.9243 2.4547 0.05348 0.67592 3.5234-2.354 2.9243-2.4547"/>
- <path d="m13.247 279.71c-0.97046-0.0253-1.9018 0.72023-1.9041 1.1527-0.0027 0.52539 0.7673 1.0634 1.9107 1.077 1.1676 8e-3 1.9127-0.43062 1.9164-0.97284 0.0043-0.61434-1.0619-1.2664-1.9231-1.2569v5e-5"/>
- <path d="m13.306 290.49c0.8461-0.0369 1.9814 0.2725 1.9837 0.68306 0.01405 0.39861-1.0297 1.2993-2.0398 1.2819-1.0461 0.0451-2.0719-0.85693-2.0585-1.1696-0.01569-0.45843 1.2738-0.81636 2.1146-0.79534"/>
- <path d="m10.181 288.06c0.60238 0.72572 0.87704 2.0008 0.3743 2.3766-0.4756 0.28694-1.6306 0.16876-2.4515-1.0106-0.55366-0.98961-0.48234-1.9966-0.09359-2.2924 0.58131-0.35408 1.4795 0.12424 2.1708 0.92638h-5.7e-5"/>
- <path d="m16.311 287.83c-0.65179 0.76339-1.0147 2.1558-0.53927 2.6043 0.45464 0.34841 1.675 0.29969 2.5765-0.95114 0.65456-0.8401 0.43526-2.2431 0.06135-2.6156-0.55542-0.4296-1.3528 0.12022-2.0986 0.9623v2.3e-4"/>
- </g>
-</svg>
diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml deleted file mode 100644 index f6c228253d..0000000000 --- a/system/settings/rbp.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<settings version="1"> - <section id="player"> - <category id="videoplayer"> - <group id="3"> - <setting id="videoplayer.rendermethod"> - <visible>false</visible> - </setting> - <setting id="videoplayer.hqscalers"> - <visible>false</visible> - </setting> - <setting id="videoplayer.usemmal" type="boolean" label="36434" help="36435"> - <level>2</level> - <default>true</default> - <control type="toggle" /> - </setting> - <setting id="videoplayer.limitguiupdate" type="integer" label="38013" help="38014"> - <level>2</level> - <default>10</default> - <constraints> - <minimum label="38015">0</minimum> <!-- Unlimited --> - <step>5</step> - <maximum>25</maximum> - </constraints> - <control type="spinner" format="string"> - <formatlabel>38016</formatlabel> - </control> - <control type="edit" format="integer" /> - </setting> - </group> - <group id="4"> - <setting id="videoplayer.supportmvc" type="boolean" label="38027" help="38028"> - <level>2</level> - <default>true</default> - <control type="toggle" /> - </setting> - </group> - </category> - </section> - <section id="media"> - <category id="video"> - <group id="1"> - <setting id="myvideos.extractchapterthumbs"> - <default>false</default> - </setting> - </group> - </category> - </section> - <section id="system"> - <category id="display"> - <group id="1"> - <setting id="videoscreen.screen"> - <visible>false</visible> - </setting> - <setting id="videoscreen.blankdisplays"> - <visible>false</visible> - </setting> - <setting id="videoscreen.fakefullscreen"> - <visible>false</visible> - </setting> - <setting id="videoscreen.textures32" type="boolean" label="37020" help="36547"> - <level>2</level> - <default>false</default> - <control type="toggle" /> - </setting> - <setting id="videoscreen.limitgui" type="integer" label="37021" help="36548"> - <level>2</level> - <default>0</default> - <constraints> - <options> - <option label="37026">0</option> <!-- auto --> - <option label="37027">540</option> <!-- 540 --> - <option label="37028">720</option> <!-- 720 --> - <option label="37029">900</option> <!-- 900 --> - <option label="37030">1080</option> <!-- unlimited --> - </options> - </constraints> - <control type="spinner" format="string" /> - <control type="edit" format="integer" /> - </setting> - </group> - <group id="2"> - <setting id="videoscreen.framepacking" type="boolean" label="38029" help="38030"> - <level>2</level> - <default>false</default> - <control type="toggle" /> - </setting> - </group> - </category> - <category id="audio"> - <group id="1"> - <setting id="audiooutput.processquality"> - <default>101</default> <!-- AE_QUALITY_GPU --> - </setting> - <setting id="audiooutput.atempothreshold"> - <default>100</default> <!-- disabled --> - </setting> - <setting id="audiooutput.audiodevice"> - <default>PI:HDMI</default> - </setting> - </group> - <group id="3"> - <setting id="audiooutput.ac3transcode" help="37024"> - </setting> - </group> - </category> - <category id="input"> - <group id="4" label="35150"> - <setting id="input.libinputkeyboardlayout" type="string" label="310" help="36436"> - <level>0</level> - <default>us</default> - <visible>true</visible> - <constraints> - <options>libinputkeyboardlayout</options> - </constraints> - <control type="list" format="string"> - <multiselect>false</multiselect> - </control> - </setting> - </group> - </category> - </section> -</settings> diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml deleted file mode 100644 index 44a982453d..0000000000 --- a/system/settings/rbp2.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<settings version="1"> - <section id="system"> - <category id="display"> - <group id="1"> - <setting id="videoscreen.textures32"> - <default>true</default> - </setting> - </group> - </category> - <category id="audio"> - <group id="1"> - <setting id="audiooutput.atempothreshold"> - <default>2</default> <!-- 2% --> - </setting> - </group> - <group id="3"> - <setting id="audiooutput.ac3transcode" help="36429"> - </setting> - </group> - <group id="1"> - <setting id="audiooutput.processquality"> - <default>30</default> <!-- AE_QUALITY_MID --> - </setting> - </group> - </category> - </section> -</settings> diff --git a/tools/buildsteps/defaultenv b/tools/buildsteps/defaultenv index becf6ae8f8..66f0777fb0 100644 --- a/tools/buildsteps/defaultenv +++ b/tools/buildsteps/defaultenv @@ -50,12 +50,6 @@ case $XBMC_PLATFORM_DIR in DEFAULT_CONFIGURATION="Debug" ;; - rbpi) - JENKINS_RBPI_DEVENV=${JENKINS_RBPI_DEVENV:-"/home/jenkins/rbpi-dev"} - DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends - DEFAULT_CONFIGURATION="Debug" - ;; - freebsd) DEFAULT_CONFIGURATION="Debug" ;; diff --git a/tools/buildsteps/rbpi/configure-depends b/tools/buildsteps/rbpi/configure-depends deleted file mode 100755 index 13d5ca27cb..0000000000 --- a/tools/buildsteps/rbpi/configure-depends +++ /dev/null @@ -1,12 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] -then - cd $WORKSPACE/tools/depends; - - ./configure --with-platform=raspberry-pi2 --host=arm-linux-gnueabihf --prefix=$XBMC_DEPENDS_ROOT --with-tarballs=$TARBALLS \ - --with-firmware=$JENKINS_RBPI_DEVENV/firmware --build=i686-linux $DEBUG_SWITCH \ - --with-toolchain=$JENKINS_RBPI_DEVENV/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf -fi diff --git a/tools/buildsteps/rbpi/configure-xbmc b/tools/buildsteps/rbpi/configure-xbmc deleted file mode 100755 index 6dd54bf845..0000000000 --- a/tools/buildsteps/rbpi/configure-xbmc +++ /dev/null @@ -1,5 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -make -C $WORKSPACE/tools/depends/target/cmakebuildsys diff --git a/tools/buildsteps/rbpi/make-binary-addons b/tools/buildsteps/rbpi/make-binary-addons deleted file mode 100755 index 862e7d79e9..0000000000 --- a/tools/buildsteps/rbpi/make-binary-addons +++ /dev/null @@ -1,28 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-native-depends - -#clear the build failed file -rm -f $WORKSPACE/cmake/$FAILED_BUILD_FILENAME - -ALL_BINARY_ADDONS_BUILT="1" -#only build binary addons when requested by env/jenkins -if [ "$BUILD_BINARY_ADDONS" == "true" ] -then - for addon in $BINARY_ADDONS - do - echo "building $addon" - git clean -xffd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon - cd $WORKSPACE/$BINARY_ADDONS_ROOT/$addon;make -j $BUILDTHREADS V=99 VERBOSE=1 || ALL_BINARY_ADDONS_BUILT="0" - done -fi - -if [ "$ALL_BINARY_ADDONS_BUILT" == "1" ] -then - tagSuccessFulBuild $WORKSPACE/cmake -else - #mark the build failure in the filesystem but leave jenkins running - tagFailedBuild $WORKSPACE/cmake -fi diff --git a/tools/buildsteps/rbpi/make-depends b/tools/buildsteps/rbpi/make-depends deleted file mode 100755 index ceeee09234..0000000000 --- a/tools/buildsteps/rbpi/make-depends +++ /dev/null @@ -1,9 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] -then - cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS || make && tagSuccessFulBuild $WORKSPACE/tools/depends -fi - diff --git a/tools/buildsteps/rbpi/make-native-depends b/tools/buildsteps/rbpi/make-native-depends deleted file mode 100755 index d4d9e7dbe1..0000000000 --- a/tools/buildsteps/rbpi/make-native-depends +++ /dev/null @@ -1,9 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] && [ "$BINARY_ADDONS_CLEAN_NATIVETOOLS" != "0" ] -then - git clean -xffd $WORKSPACE/tools/depends/native - cd $WORKSPACE/tools/depends/native;make -j $BUILDTHREADS && tagSuccessFulBuild $WORKSPACE/tools/depends -fi
\ No newline at end of file diff --git a/tools/buildsteps/rbpi/make-xbmc b/tools/buildsteps/rbpi/make-xbmc deleted file mode 100755 index 07cfae21c7..0000000000 --- a/tools/buildsteps/rbpi/make-xbmc +++ /dev/null @@ -1,5 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -cd $WORKSPACE/build;make -j$BUILDTHREADS || make diff --git a/tools/buildsteps/rbpi/package b/tools/buildsteps/rbpi/package deleted file mode 100755 index f3c41a5c96..0000000000 --- a/tools/buildsteps/rbpi/package +++ /dev/null @@ -1,5 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -#nothing for rbpi atm diff --git a/tools/buildsteps/rbpi/prepare-depends b/tools/buildsteps/rbpi/prepare-depends deleted file mode 100755 index c38eb77901..0000000000 --- a/tools/buildsteps/rbpi/prepare-depends +++ /dev/null @@ -1,24 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -#clean without depends for skipping depends build if possible -#also skip binary addons (pvr, audioencoder) as long as they are deployed in tree -cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" ${DEPLOYED_BINARY_ADDONS} - -if [ -d $JENKINS_RBPI_DEVENV/firmware ] -then - cd $JENKINS_RBPI_DEVENV/firmware;git pull origin master -else - cd $JENKINS_RBPI_DEVENV;git clone git://github.com/raspberrypi/firmware.git --depth=1 -b master -fi - -cd $WORKSPACE - -# if depends path has changed - cleanout everything and do a full rebuild -if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] -then - #clean up the rest too - cd $WORKSPACE;git clean -xffd - cd $WORKSPACE/tools/depends/;./bootstrap -fi diff --git a/tools/buildsteps/rbpi/prepare-xbmc b/tools/buildsteps/rbpi/prepare-xbmc deleted file mode 100755 index 3957f5aab7..0000000000 --- a/tools/buildsteps/rbpi/prepare-xbmc +++ /dev/null @@ -1,11 +0,0 @@ -WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} -XBMC_PLATFORM_DIR=rbpi -. $WORKSPACE/tools/buildsteps/defaultenv - -cd $WORKSPACE - -#build binary addons before building xbmc... -#make sure that binary_addons don't clean the native tools -#here -BINARY_ADDONS_CLEAN_NATIVETOOLS="0" -. $WORKSPACE/tools/buildsteps/$XBMC_PLATFORM_DIR/make-binary-addons diff --git a/tools/depends/README.md b/tools/depends/README.md index b4bc0587dd..2e5db17886 100644 --- a/tools/depends/README.md +++ b/tools/depends/README.md @@ -20,25 +20,25 @@ Paths below are examples. If you want to build Kodi, follow our **[build guides] ### All platforms `./bootstrap` ### Darwin -**macOS (x86_64)** +**macOS (x86_64)** `./configure --host=x86_64-apple-darwin` -**iOS (arm64)** +**iOS (arm64)** `./configure --host=aarch64-apple-darwin` -**tvOS** +**tvOS** `./configure --host=aarch64-apple-darwin --with-platform=tvos` **NOTE:** You can target the same `--prefix=` path. Each setup will be done in an isolated directory. The last configure/make you do is the one used for Kodi/Xcode. - + ### Android -**arm** +**arm** `./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=arm-linux-androideabi --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends` -**aarch64** +**aarch64** `./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=aarch64-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends` -**x86** +**x86** `./configure --with-tarballs=$HOME/android-tools/xbmc-tarballs --host=i686-linux-android --with-sdk-path=$HOME/android-tools/android-sdk-linux --with-ndk-path=$HOME/android-tools/android-ndk-r20 --prefix=$HOME/android-tools/xbmc-depends` **x86_64** @@ -47,13 +47,10 @@ Paths below are examples. If you want to build Kodi, follow our **[build guides] > **Note:** Android x86 and x86_64 are not maintained and are not 100% sure that everything works correctly! ### Linux -**ARM (codesourcery/lenaro/etc)** +**ARM (codesourcery/lenaro/etc)** `./configure --with-toolchain=/opt/toolchains/my-example-toolchain/ --prefix=/opt/xbmc-deps --host=arm-linux-gnueabi` -**Raspberry Pi** -`./configure --with-platform=raspberry-pi --host=arm-linux-gnueabihf --prefix=/opt/xbmc-deps --with-tarballs=/opt/xbmc-tarballs --with-toolchain=/opt/rbp-dev/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf --with-firmware=/opt/rbp-dev/firmware --build=i686-linux` - -**Native** +**Native** `./configure --with-toolchain=/usr --prefix=/opt/xbmc-deps --host=x86_64-linux-gnu` Cross compiling is a PITA. diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac index 3ab992a34e..700681e7b3 100644 --- a/tools/depends/configure.ac +++ b/tools/depends/configure.ac @@ -431,30 +431,6 @@ case $use_platform in fi target_platform=$use_platform ;; - raspberry-pi) - target_platform=raspberry-pi - use_cpu=arm1176jzf-s - ffmpeg_options_default="--cpu=arm1176jzf-s" - platform_cflags="-mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp" - platform_cxxflags="-mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp" - platform_ldflags="" - ;; - raspberry-pi2) - target_platform=raspberry-pi - use_cpu=cortex-a7 - ffmpeg_options_default="--cpu=cortex-a7" - platform_cflags="-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -mvectorize-with-neon-quad" - platform_cxxflags="-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -mvectorize-with-neon-quad" - platform_ldflags="-lpthread" - ;; - raspberry-pi3) - target_platform=raspberry-pi - use_cpu=cortex-a53 - ffmpeg_options_default="--cpu=cortex-a53" - platform_cflags="-fPIC -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mvectorize-with-neon-quad" - platform_cxxflags="-fPIC -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mvectorize-with-neon-quad" - platform_ldflags="-lpthread" - ;; tvos) platform_cflags+=" -fembed-bitcode" platform_cxxflags+=" -fembed-bitcode" @@ -468,32 +444,6 @@ case $use_platform in AC_MSG_ERROR(unsupported platform ($use_platform)) esac -if test "$target_platform" = "raspberry-pi" ; then - if test -d "${use_firmware}/opt/vc/include"; then - : - else - AC_MSG_ERROR([Raspberry Pi firmware not found]) - fi - use_arch="arm" - use_hardcoded_tables="yes" - ARCH="arm" - cross_compiling="yes" - use_host="arm-linux-gnueabihf" - deps_dir="$use_platform-$build_type" - platform_cflags+=" -pipe -mabi=aapcs-linux -Wno-psabi \ - -Wa,-mno-warn-deprecated -Wno-deprecated-declarations \ - -isystem${use_firmware}/opt/vc/include \ - -isystem${use_firmware}/opt/vc/include/interface/vcos/pthreads \ - -isystem${use_firmware}/opt/vc/include/interface/vmcs_host/linux" - platform_cxxflags+=" -pipe -mabi=aapcs-linux -Wno-psabi \ - -Wa,-mno-warn-deprecated -Wno-deprecated-declarations \ - -isystem${use_firmware}/opt/vc/include \ - -isystem${use_firmware}/opt/vc/include/interface/vcos/pthreads \ - -isystem${use_firmware}/opt/vc/include/interface/vmcs_host/linux" - platform_ldflags+=" -L${use_firmware}/opt/vc/lib -lEGL -lGLESv2 -lbcm_host -lvcos \ - -lvchiq_arm" -fi - XBMC_SETUP_ARCH_DEFINES() diff --git a/tools/depends/m4/xbmc_arch.m4 b/tools/depends/m4/xbmc_arch.m4 index b4beef8f77..83e42552c7 100644 --- a/tools/depends/m4/xbmc_arch.m4 +++ b/tools/depends/m4/xbmc_arch.m4 @@ -74,7 +74,4 @@ if test "$target_platform" = "target_android" ; then AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -DTARGET_ANDROID") fi -if test "$target_platform" = "target_raspberry_pi" ; then - AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_ARMEL -DTARGET_RASPBERRY_PI") -fi ]) diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile index 405690ceab..afda288e3b 100644 --- a/tools/depends/target/Makefile +++ b/tools/depends/target/Makefile @@ -61,24 +61,19 @@ endif WAYLANDPP_DEPS= ALSA_LIB= ifeq ($(OS),linux) - DEPENDS += dbus libuuid - # not for raspberry pi or gbm - ifeq (,$(filter $(TARGET_PLATFORM),raspberry-pi gbm)) - DEPENDS += linux-system-libs - WAYLANDPP_DEPS += linux-system-libs - endif - DEPENDS += alsa-lib + DEPENDS += dbus libuuid alsa-lib ALSA_LIB = alsa-lib LIBUUID = libuuid - ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),raspberry-pi gbm)) - DEPENDS += libxkbcommon libinput libudev libevdev mtdev - endif + ifeq ($(TARGET_PLATFORM),gbm) - DEPENDS += libdrm mesa + DEPENDS += libxkbcommon libinput libudev libevdev mtdev libdrm mesa ifeq ($(CPU),x86_64) DEPENDS += libva LIBVA = libva endif + else + DEPENDS += linux-system-libs + WAYLANDPP_DEPS += linux-system-libs endif endif diff --git a/tools/depends/target/Toolchain.cmake.in b/tools/depends/target/Toolchain.cmake.in index 7b5ea6ab0e..8786f52f7e 100644 --- a/tools/depends/target/Toolchain.cmake.in +++ b/tools/depends/target/Toolchain.cmake.in @@ -10,14 +10,7 @@ set(PLATFORM "@target_platform@") if(OS STREQUAL linux) set(CMAKE_SYSTEM_NAME Linux) set(CORE_SYSTEM_NAME linux) - if(PLATFORM STREQUAL raspberry-pi) - set(CORE_PLATFORM_NAME rbpi) - # wrapping libdvd fails with gold on rbpi - # todo: revisit after toolchain bump - set(ENABLE_LDGOLD OFF CACHE BOOL "Disabling Gnu Gold Linker" FORCE) - elseif(NOT "@target_platform@" STREQUAL "") - set(CORE_PLATFORM_NAME @target_platform@) - endif() + set(CORE_PLATFORM_NAME @target_platform@) if(NOT "@app_rendersystem@" STREQUAL "") set(X11_RENDER_SYSTEM @app_rendersystem@ CACHE STRING "Render system to use with X11: \"gl\" or \"gles\"") set(WAYLAND_RENDER_SYSTEM @app_rendersystem@ CACHE STRING "Render system to use with Wayland: \"gl\" or \"gles\"") @@ -100,13 +93,6 @@ if(NOT "@use_sdk_path@" STREQUAL "") list(APPEND CMAKE_FIND_ROOT_PATH @use_sdk_path@ @use_sdk_path@/usr) endif() -# add RBPI's firmware directories -if(CORE_PLATFORM_NAME STREQUAL rbpi) - list(APPEND CMAKE_FIND_ROOT_PATH @use_firmware@/opt/vc) - list(APPEND CMAKE_LIBRARY_PATH @use_firmware@/opt/vc/lib) - list(APPEND CMAKE_INCLUDE_PATH @use_firmware@/opt/vc/include) -endif() - # add Android directories and tools if(CORE_SYSTEM_NAME STREQUAL android) set(NDKROOT @use_ndk_path@) diff --git a/tools/depends/target/Toolchain_binaddons.cmake.in b/tools/depends/target/Toolchain_binaddons.cmake.in index 30059d1c6d..27a6dbd3aa 100644 --- a/tools/depends/target/Toolchain_binaddons.cmake.in +++ b/tools/depends/target/Toolchain_binaddons.cmake.in @@ -10,15 +10,7 @@ set(CMAKE_FIND_ROOT_PATH @CMAKE_FIND_ROOT_PATH@) if(OS STREQUAL linux) set(CMAKE_SYSTEM_NAME Linux) set(CORE_SYSTEM_NAME linux) - if(PLATFORM STREQUAL raspberry-pi) - set(CORE_PLATFORM_NAME rbpi) - set(ENABLE_LDGOLD OFF CACHE BOOL "Disabling Gnu Gold Linker" FORCE) - if(NOT APP_RENDER_SYSTEM) - set(APP_RENDER_SYSTEM gles) - endif() - elseif(NOT "@target_platform@" STREQUAL "") - set(CORE_PLATFORM_NAME @target_platform@) - endif() + set(CORE_PLATFORM_NAME @target_platform@) if(NOT APP_RENDER_SYSTEM) set(APP_RENDER_SYSTEM gl) endif() @@ -73,13 +65,6 @@ if(NOT "@use_toolchain@" STREQUAL "") list(APPEND CMAKE_FIND_ROOT_PATH @use_toolchain@/sysroot/usr) endif() -# add RBPI's firmware directories -if(CORE_PLATFORM_NAME STREQUAL rbpi) - list(APPEND CMAKE_FIND_ROOT_PATH @use_firmware@/opt/vc) - list(APPEND CMAKE_LIBRARY_PATH @CMAKE_FIND_ROOT_PATH@/lib:@use_firmware@/opt/vc/lib) - list(APPEND CMAKE_INCLUDE_PATH @CMAKE_FIND_ROOT_PATH@/include:@use_firmware@/opt/vc/include) -endif() - # add Android directories and tools if(CORE_SYSTEM_NAME STREQUAL android) set(NDKROOT @use_ndk_path@) diff --git a/tools/depends/target/ffmpeg/CMakeLists.txt b/tools/depends/target/ffmpeg/CMakeLists.txt index 3ebd65cf13..a0f4ed269b 100644 --- a/tools/depends/target/ffmpeg/CMakeLists.txt +++ b/tools/depends/target/ffmpeg/CMakeLists.txt @@ -39,20 +39,16 @@ if(CMAKE_BUILD_TYPE STREQUAL Release) endif() if(CORE_SYSTEM_NAME STREQUAL linux OR CORE_SYSTEM_NAME STREQUAL freebsd) - if(CORE_PLATFORM_NAME STREQUAL rbpi) - list(APPEND ffmpeg_conf --cpu=${CPU} --disable-vaapi --disable-vdpau) + list(APPEND ffmpeg_conf --enable-pic) + if(ENABLE_VAAPI) + list(APPEND ffmpeg_conf --enable-vaapi) else() - list(APPEND ffmpeg_conf --enable-pic) - if(ENABLE_VAAPI) - list(APPEND ffmpeg_conf --enable-vaapi) - else() - list(APPEND ffmpeg_conf --disable-vaapi) - endif() - if(ENABLE_VDPAU) - list(APPEND ffmpeg_conf --enable-vdpau) - else() - list(APPEND ffmpeg_conf --disable-vdpau) - endif() + list(APPEND ffmpeg_conf --disable-vaapi) + endif() + if(ENABLE_VDPAU) + list(APPEND ffmpeg_conf --enable-vdpau) + else() + list(APPEND ffmpeg_conf --disable-vdpau) endif() elseif(CORE_SYSTEM_NAME STREQUAL android) if(CPU MATCHES arm64) @@ -75,7 +71,7 @@ elseif(CORE_SYSTEM_NAME STREQUAL osx) --disable-securetransport) endif() -if(CPU MATCHES arm OR CORE_PLATFORM_NAME STREQUAL rbpi) +if(CPU MATCHES arm) list(APPEND ffmpeg_conf --enable-pic --disable-armv5te --disable-armv6t2) elseif(CPU MATCHES mips) list(APPEND ffmpeg_conf --disable-mips32r2 --disable-mipsdsp --disable-mipsdspr2) diff --git a/tools/depends/xbmc-addons.include b/tools/depends/xbmc-addons.include index 35399f0e2f..79d7c069b4 100644 --- a/tools/depends/xbmc-addons.include +++ b/tools/depends/xbmc-addons.include @@ -6,11 +6,6 @@ export PKG_CONFIG_LIBDIR = $(ADDON_DEPS_DIR)/lib/pkgconfig ifeq ($(CROSS_COMPILING),yes) DEPS = $(TOOLCHAIN_FILE) $(abs_top_srcdir)/target/config-binaddons.site $(abs_top_srcdir)/target/Toolchain_binaddons.cmake $(CONFIG_SUB) $(CONFIG_GUESS) TOOLCHAIN = -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) - ifeq ($(OS),linux) - ifneq ($(TARGET_PLATFORM),raspberry-pi) - DEPS += linux-system-libs - endif - endif endif ifeq ($(PLATFORM),) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 3ac1680b32..0a1d9b6729 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -451,16 +451,9 @@ bool CApplication::Create(const CAppParamParser ¶ms) #else buildType = "Unknown"; #endif - std::string specialVersion; - //! @todo - move to CPlatformXXX -#if defined(TARGET_RASPBERRY_PI) - specialVersion = " (version for Raspberry Pi)"; -//#elif defined(some_ID) // uncomment for special version/fork -// specialVersion = " (version for XXXX)"; -#endif - CLog::Log(LOGINFO, "Using %s %s x%d build%s", buildType.c_str(), CSysInfo::GetAppName().c_str(), - g_sysinfo.GetXbmcBitness(), specialVersion.c_str()); + CLog::Log(LOGINFO, "Using %s %s x%d", buildType.c_str(), CSysInfo::GetAppName().c_str(), + g_sysinfo.GetXbmcBitness()); CLog::Log( LOGINFO, "%s compiled %s by %s for %s %s %d-bit %s (%s)", CSysInfo::GetAppName().c_str(), CSysInfo::GetBuildDate(), g_sysinfo.GetUsedCompilerNameAndVer().c_str(), @@ -2447,7 +2440,8 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) if (processGUI && m_renderGUI) { m_skipGuiRender = false; -#if defined(TARGET_RASPBERRY_PI) + + /*! @todo look into the possibility to use this for GBM int fps = 0; // This code reduces rendering fps of the GUI layer when playing videos in fullscreen mode @@ -2459,7 +2453,7 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) unsigned int frameTime = now - m_lastRenderTime; if (fps > 0 && frameTime * fps < 1000) m_skipGuiRender = true; -#endif + */ if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiSmartRedraw && m_guiRefreshTimer.IsTimePast()) { diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index aef925d6f9..3015c964ae 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -1164,14 +1164,6 @@ const infomap weather[] = {{ "isfetched", WEATHER_IS_FETCHED }, /// @return **True** if Kodi is running on a linux/unix based computer. /// <p> /// } -/// \table_row3{ <b>`System.Platform.Linux.RaspberryPi`</b>, -/// \anchor System_PlatformLinuxRaspberryPi -/// _boolean_, -/// @return **True** if Kodi is running on a Raspberry Pi. -/// <p><hr> -/// @skinning_v13 **[New Boolean Condition]** \link System_PlatformLinuxRaspberryPi -/// `System.Platform.Linux.RaspberryPi`\endlink <p> -/// } /// \table_row3{ <b>`System.Platform.Windows`</b>, /// \anchor System_PlatformWindows /// _boolean_, @@ -9259,6 +9251,11 @@ const infomap slideshow[] = {{ "ispaused", SLIDESHOW_ISPAUSED /// \page modules__infolabels_boolean_conditions /// \section modules_rm_infolabels_booleans Additional revision history for Infolabels and Boolean Conditions /// <hr> +/// \subsection modules_rm_infolabels_booleans_v19 Kodi v19 (Matrix) +/// @skinning_v19 **[Removed Infolabels]** The following infolabels have been removed: +/// - `System.Platform.Linux.RaspberryPi` - use \link System_Platform_Linux `System.Platform.Linux`\endlink instead +/// +/// <hr> /// \subsection modules_rm_infolabels_booleans_v18 Kodi v18 (Leia) /// /// @skinning_v18 **[Removed Infolabels]** The following infolabels have been removed: @@ -9909,15 +9906,7 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool { //! @todo replace with a single system.platform std::string platform = info[2].name; if (platform == "linux") - { - if (info.size() == 4) - { - std::string device = info[3].name; - if (device == "raspberrypi") - return SYSTEM_PLATFORM_LINUX_RASPBERRY_PI; - } - else return SYSTEM_PLATFORM_LINUX; - } + return SYSTEM_PLATFORM_LINUX; else if (platform == "windows") return SYSTEM_PLATFORM_WINDOWS; else if (platform == "uwp") diff --git a/xbmc/SystemGlobals.cpp b/xbmc/SystemGlobals.cpp index 435b1f5090..6bb854cc42 100644 --- a/xbmc/SystemGlobals.cpp +++ b/xbmc/SystemGlobals.cpp @@ -24,10 +24,6 @@ std::map<std::string, std::string> CSpecialProtocol::m_pathMap; #include "filesystem/ZipManager.h" -#ifdef TARGET_RASPBERRY_PI -#include "platform/linux/RBP.h" -#endif - CLangCodeExpander g_LangCodeExpander; CLocalizeStrings g_localizeStrings; CLocalizeStrings g_localizeStringsTemp; @@ -42,8 +38,4 @@ std::map<std::string, std::string> CSpecialProtocol::m_pathMap; CAlarmClock g_alarmClock; CSectionLoader g_sectionLoader; -#ifdef TARGET_RASPBERRY_PI - CRBP g_RBP; -#endif - CZipManager g_ZipManager; diff --git a/xbmc/TextureCacheJob.cpp b/xbmc/TextureCacheJob.cpp index 7afe6a49ff..f1f3d25ee0 100644 --- a/xbmc/TextureCacheJob.cpp +++ b/xbmc/TextureCacheJob.cpp @@ -22,9 +22,6 @@ #include "FileItem.h" #include "music/MusicThumbLoader.h" #include "music/tags/MusicInfoTag.h" -#if defined(TARGET_RASPBERRY_PI) -#include "cores/omxplayer/OMXImage.h" -#endif #include <inttypes.h> @@ -80,20 +77,6 @@ bool CTextureCacheJob::CacheTexture(CBaseTexture **out_texture) else if (m_details.hash == m_oldHash) return true; -#if defined(TARGET_RASPBERRY_PI) - if (COMXImage::CreateThumb(image, width, height, additional_info, CTextureCache::GetCachedPath(m_cachePath + ".jpg"))) - { - m_details.width = width; - m_details.height = height; - m_details.file = m_cachePath + ".jpg"; - if (out_texture) - *out_texture = LoadImage(CTextureCache::GetCachedPath(m_details.file), width, height, "" /* already flipped */); - CLog::Log(LOGDEBUG, "Fast %s image '%s' to '%s': %p", - m_oldHash.empty() ? "Caching" : "Recaching", CURL::GetRedacted(image), - m_details.file, static_cast<void*>(out_texture)); - return true; - } -#endif CBaseTexture *texture = LoadImage(image, width, height, additional_info, true); if (texture) { diff --git a/xbmc/addons/addoninfo/AddonInfoBuilder.cpp b/xbmc/addons/addoninfo/AddonInfoBuilder.cpp index f36e7e57e0..42b5fc9675 100644 --- a/xbmc/addons/addoninfo/AddonInfoBuilder.cpp +++ b/xbmc/addons/addoninfo/AddonInfoBuilder.cpp @@ -558,9 +558,6 @@ const char* CAddonInfoBuilder::GetPlatformLibraryName(const TiXmlElement* elemen #if defined(TARGET_FREEBSD) libraryName = element->Attribute("library_freebsd"); if (libraryName == nullptr) -#elif defined(TARGET_RASPBERRY_PI) - libraryName = element->Attribute("library_rbpi"); - if (libraryName == nullptr) #endif libraryName = element->Attribute("library_linux"); #elif defined(TARGET_WINDOWS_DESKTOP) diff --git a/xbmc/cores/AudioEngine/AEResampleFactory.cpp b/xbmc/cores/AudioEngine/AEResampleFactory.cpp index 32d13c68da..224910f465 100644 --- a/xbmc/cores/AudioEngine/AEResampleFactory.cpp +++ b/xbmc/cores/AudioEngine/AEResampleFactory.cpp @@ -8,22 +8,12 @@ #include "AEResampleFactory.h" #include "cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h" -#if defined(TARGET_RASPBERRY_PI) - #include "ServiceBroker.h" - #include "settings/Settings.h" -#include "settings/SettingsComponent.h" - #include "cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h" -#endif namespace ActiveAE { IAEResample *CAEResampleFactory::Create(uint32_t flags /* = 0 */) { -#if defined(TARGET_RASPBERRY_PI) - if (!(flags & AERESAMPLEFACTORY_QUICK_RESAMPLE) && CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_AUDIOOUTPUT_PROCESSQUALITY) == AE_QUALITY_GPU) - return new CActiveAEResamplePi(); -#endif return new CActiveAEResampleFFMPEG(); } diff --git a/xbmc/cores/AudioEngine/CMakeLists.txt b/xbmc/cores/AudioEngine/CMakeLists.txt index 3f97e30220..eb34be83a3 100644 --- a/xbmc/cores/AudioEngine/CMakeLists.txt +++ b/xbmc/cores/AudioEngine/CMakeLists.txt @@ -51,7 +51,7 @@ if(ALSA_FOUND) Utils/AEELDParser.cpp) list(APPEND HEADERS Sinks/AESinkALSA.h Utils/AEELDParser.h) - + if(NOT CORE_PLATFORM_NAME_LC STREQUAL x11) list(APPEND SOURCES Sinks/alsa/ALSAHControlMonitor.cpp) list(APPEND HEADERS Sinks/alsa/ALSAHControlMonitor.h) @@ -94,13 +94,6 @@ if(CORE_SYSTEM_NAME MATCHES windows) endif() endif() -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - list(APPEND SOURCES Engines/ActiveAE/ActiveAEResamplePi.cpp - Sinks/AESinkPi.cpp) - list(APPEND HEADERS Engines/ActiveAE/ActiveAEResamplePi.h - Sinks/AESinkPi.h) -endif() - if(CORE_SYSTEM_NAME STREQUAL osx) list(APPEND SOURCES Sinks/AESinkDARWINOSX.cpp Sinks/darwin/CoreAudioHelpers.cpp diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp index a4b62e02fe..d9def8434c 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp @@ -2734,10 +2734,6 @@ bool CActiveAE::SupportsQualityLevel(enum AEQuality level) { if (level == AE_QUALITY_LOW || level == AE_QUALITY_MID || level == AE_QUALITY_HIGH) return true; -#if defined(TARGET_RASPBERRY_PI) - if (level == AE_QUALITY_GPU) - return true; -#endif return false; } diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp deleted file mode 100644 index 00d0ad57a8..0000000000 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include <cassert> - -#include "cores/AudioEngine/Utils/AEUtil.h" -#include "ActiveAEResamplePi.h" -#include "settings/Settings.h" -#include "utils/log.h" -#include "platform/linux/RBP.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(LOGINFO, "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; - -CActiveAEResamplePi::CActiveAEResamplePi() -{ - CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); - - m_Initialized = false; - m_encoded_buffer = NULL; - m_offset = 0; - m_ratio = 0.0; -} - -CActiveAEResamplePi::~CActiveAEResamplePi() -{ - CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); - DeInit(); -} - -void CActiveAEResamplePi::DeInit() -{ - CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); - if (m_Initialized) - { - m_omx_mixer.FlushAll(); - m_omx_mixer.Deinitialize(); - m_Initialized = false; - } -} - -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 CActiveAEResamplePi::Init(SampleConfig dstConfig, SampleConfig srcConfig, bool upmix, bool normalize, double centerMix, - CAEChannelInfo *remapLayout, AEQuality quality, bool force_resample) -{ - LOGTIMEINIT("x"); - - CLog::Log(LOGINFO, - "%s::%s remap:%p chan:%d->%d rate:%d->%d format:%d->%d bits:%d->%d dither:%d->%d " - "norm:%d upmix:%d", - CLASSNAME, __func__, static_cast<void*>(remapLayout), srcConfig.channels, dstConfig.channels, - srcConfig.sample_rate, dstConfig.sample_rate, srcConfig.fmt, dstConfig.fmt, - srcConfig.bits_per_sample, dstConfig.bits_per_sample, srcConfig.dither_bits, dstConfig.dither_bits, - normalize, upmix); - - m_dst_chan_layout = dstConfig.channel_layout; - m_dst_channels = dstConfig.channels; - m_dst_rate = dstConfig.sample_rate; - m_dst_fmt = dstConfig.fmt; - m_dst_bits = dstConfig.bits_per_sample; - m_dst_dither_bits = dstConfig.dither_bits; - m_src_chan_layout = srcConfig.channel_layout; - m_src_channels = srcConfig.channels; - m_src_rate = srcConfig.sample_rate; - m_src_fmt = srcConfig.fmt; - m_src_bits = srcConfig.bits_per_sample; - m_src_dither_bits = srcConfig.dither_bits; - m_offset = 0; - m_src_pitch = format_to_bits(m_src_fmt) >> 3; - m_dst_pitch = format_to_bits(m_dst_fmt) >> 3; - m_force_resample = force_resample; - - // special handling for S24 formats which are carried in S32 (S24NE3) - if ((m_dst_fmt == AV_SAMPLE_FMT_S32 || m_dst_fmt == AV_SAMPLE_FMT_S32P) && m_dst_bits == 24 && m_dst_dither_bits == -8) - m_dst_pitch = 24; - - 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, "CActiveAEResamplePi::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; out<remapLayout->Count(); out++) - { - m_dst_chan_layout += (uint64_t) (1 << out); - int idx = CAEUtil::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, "CActiveAEResamplePi::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<m_dst_channels; out++) - { - uint64_t out_chan = av_channel_layout_extract_channel(m_dst_chan_layout, out); - switch(out_chan) - { - case AV_CH_FRONT_LEFT: - case AV_CH_BACK_LEFT: - case AV_CH_SIDE_LEFT: - m_rematrix[out][0] = 1.0; - break; - case AV_CH_FRONT_RIGHT: - case AV_CH_BACK_RIGHT: - case AV_CH_SIDE_RIGHT: - m_rematrix[out][1] = 1.0; - break; - case AV_CH_FRONT_CENTER: - m_rematrix[out][0] = 0.5; - m_rematrix[out][1] = 0.5; - break; - case AV_CH_LOW_FREQUENCY: - m_rematrix[out][0] = 0.5; - m_rematrix[out][1] = 0.5; - break; - default: - break; - } - } - - if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) - { - CLog::Log(LOGERROR, "CActiveAEResamplePi::Init - setting channel matrix failed"); - return false; - } - } - - if (swr_init(m_pContext) < 0) - { - CLog::Log(LOGERROR, "CActiveAEResamplePi::Init - init resampler failed"); - return false; - } - - const int samples = 8; - uint8_t *output, *input; - av_samples_alloc(&output, NULL, m_dst_channels, samples, AV_SAMPLE_FMT_FLT, 1); - av_samples_alloc(&input , NULL, m_src_channels, samples, AV_SAMPLE_FMT_FLT, 1); - - // Produce "identity" samples - float *f = (float *)input; - for (int j=0; j < samples; j++) - for (int i=0; i < m_src_channels; i++) - *f++ = i == j ? 1.0f : 0.0f; - - int ret = swr_convert(m_pContext, &output, samples, (const uint8_t **)&input, samples); - if (ret < 0) - CLog::Log(LOGERROR, "CActiveAEResamplePi::Resample - resample failed"); - - f = (float *)output; - for (int j=0; j < samples; j++) - for (int i=0; i < m_dst_channels; i++) - mix.coeff[8*i+j] = *f++ * (1<<16); - - for (int j=0; j < 8; j++) - { - char s[128] = {}, *t=s; - for (int i=0; i < 8; i++) - t += sprintf(t, "% 6.2f ", mix.coeff[j*8+i] * (1.0/0x10000)); - CLog::Log(LOGINFO, "%s::%s %s", CLASSNAME, __func__, s); - } - av_freep(&input); - av_freep(&output); - swr_free(&m_pContext); -} - LOGTIME(2); - - // This may be called before Application calls g_RBP.Initialise, so call it here too - g_RBP.Initialize(); - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if (!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit)) - CLog::Log(LOGERROR, "%s::%s - m_omx_mixer.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - LOGTIME(3); - - if (m_force_resample) - { - OMX_PARAM_U32TYPE scaleType; - OMX_INIT_STRUCTURE(scaleType); - - scaleType.nPortIndex = m_omx_mixer.GetInputPort(); - scaleType.nU32 = (1 << 16); - omx_err = m_omx_mixer.SetConfig(OMX_IndexParamBrcmTimeScale, &scaleType); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer Failed to set OMX_IndexParamBrcmTimeScale omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - m_ratio = 1.0; - } - // audio_mixer only supports up to 192kHz, however as long as ratio of samplerates remains the same we can lie - while (srcConfig.sample_rate > 192000 || dstConfig.sample_rate > 192000) - srcConfig.sample_rate >>= 1, dstConfig.sample_rate >>= 1; - - OMX_INIT_STRUCTURE(m_pcm_input); - m_pcm_input.nPortIndex = m_omx_mixer.GetInputPort(); - m_pcm_input.eNumData = OMX_NumericalDataSigned; - m_pcm_input.eEndian = OMX_EndianLittle; - m_pcm_input.bInterleaved = OMX_TRUE; - m_pcm_input.nBitPerSample = m_src_pitch << 3; - // 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 = srcConfig.channels; - m_pcm_input.nSamplingRate = srcConfig.sample_rate; - - omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer in SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - OMX_INIT_STRUCTURE(m_pcm_output); - m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort(); - m_pcm_output.eNumData = OMX_NumericalDataSigned; - m_pcm_output.eEndian = OMX_EndianLittle; - m_pcm_output.bInterleaved = OMX_TRUE; - m_pcm_output.nBitPerSample = m_dst_pitch << 3; - 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; - // shift bits if destination format requires it, swr_resamples aligns to the left - if (m_dst_bits != 32 && (m_dst_dither_bits + m_dst_bits) != 32) - flags |= (32 - m_dst_bits - m_dst_dither_bits) << 8; - - m_pcm_output.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; - m_pcm_output.nChannels = dstConfig.channels; - m_pcm_output.nSamplingRate = dstConfig.sample_rate; - - omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer out SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - LOGTIME(4); - - mix.nPortIndex = m_omx_mixer.GetInputPort(); - omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix); - if (omx_err != OMX_ErrorNone) - { - CLog::Log( - LOGERROR, - "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x", - CLASSNAME, __func__, omx_err); - return false; - } - - // set up the number/size of buffers for decoder input - OMX_PARAM_PORTDEFINITIONTYPE port_param; - OMX_INIT_STRUCTURE(port_param); - port_param.nPortIndex = m_omx_mixer.GetInputPort(); - - omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) - 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)1); - port_param.nBufferSize = BUFFERSIZE; - - omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - LOGTIME(5); - - omx_err = m_omx_mixer.AllocInputBuffers(); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); - - LOGTIME(6); - - // set up the number/size of buffers for decoder output - OMX_INIT_STRUCTURE(port_param); - port_param.nPortIndex = m_omx_mixer.GetOutputPort(); - - omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) - 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)1); - port_param.nBufferSize = BUFFERSIZE; - - omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - LOGTIME(7); - - omx_err = m_omx_mixer.AllocOutputBuffers(); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); - - LOGTIME(8); - - omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - LOGTIME(9); - - m_Initialized = true; - - return true; -} - - -static void copy_planes(uint8_t **dst_buffer, int d_pitch, int d_planes, int d_samplesize, int offset, uint8_t *src_buffer, int src_samples, int planesize) -{ - for (int i=0; i < d_planes; i++) - memcpy(dst_buffer[i] + offset * d_pitch, src_buffer + i * planesize, src_samples * d_samplesize / d_planes); -} - -int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio) -{ - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s samples:%d->%d (%.2f)", CLASSNAME, __func__, src_samples, dst_samples, ratio); - #endif - if (!m_Initialized) - return 0; - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if (m_ratio != 0.0 && ratio != m_ratio) - { - OMX_PARAM_U32TYPE scaleType; - OMX_INIT_STRUCTURE(scaleType); - - scaleType.nPortIndex = m_omx_mixer.GetInputPort(); - scaleType.nU32 = (1 << 16) / ratio; - omx_err = m_omx_mixer.SetConfig(OMX_IndexParamBrcmTimeScale, &scaleType); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer Failed to set OMX_IndexParamBrcmTimeScale omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - m_ratio = ratio; - } - - 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_pitch; - const int d_pitch = d_chans * m_dst_pitch; - - const int s_samplesize = m_src_channels * m_src_pitch; - const int d_samplesize = m_dst_channels * m_dst_pitch; - 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 sent = 0; - int received = 0; - - while (1) - { - if (m_encoded_buffer && m_encoded_buffer->nFilledLen) - { - int samples_available = m_encoded_buffer->nFilledLen / d_samplesize - m_offset; - int samples = std::min(samples_available, dst_samples - received); - copy_planes(dst_buffer, d_pitch, d_planes, d_samplesize, received, (uint8_t *)m_encoded_buffer->pBuffer + m_offset * d_pitch, samples, m_encoded_buffer->nFilledLen / d_planes); - received += samples; - m_offset += samples; - if (m_offset == m_encoded_buffer->nFilledLen / d_samplesize) - { - m_offset = 0; - m_encoded_buffer = NULL; - } - else if (m_offset > m_encoded_buffer->nFilledLen / d_samplesize) assert(0); - else assert(sent == src_samples); - } - - if (sent >= src_samples) - break; - - OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_mixer.GetInputBuffer(1000); - if (omx_buffer == NULL) - { - CLog::Log(LOGERROR, "%s::%s m_omx_mixer.GetInputBuffer failed to get buffer", CLASSNAME, __func__); - return false; - } - 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_samplesize; - - assert(omx_buffer->nFilledLen > 0 && omx_buffer->nFilledLen <= omx_buffer->nAllocLen); - - if (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; - } - - 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); - m_omx_mixer.DecoderEmptyBufferDone(m_omx_mixer.GetComponent(), omx_buffer); - 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) - { - CLog::Log(LOGERROR, "%s::%s m_omx_mixer.FillThisBuffer result(0x%x)", CLASSNAME, __func__, omx_err); - m_omx_mixer.DecoderFillBufferDone(m_omx_mixer.GetComponent(), m_encoded_buffer); - 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 (sent < src_samples) - CLog::Log(LOGERROR, "%s::%s More data to send %d/%d", CLASSNAME, __func__, sent, src_samples); - } - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s format:%d->%d rate:%d->%d chan:%d->%d samples %d->%d (%f) %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, received); - #endif - assert(received <= dst_samples); - return received; -} - -int64_t CActiveAEResamplePi::GetDelay(int64_t base) -{ - int64_t ret = av_rescale_rnd(GetBufferedSamples(), m_dst_rate, base, AV_ROUND_UP); - - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s = %" PRId64, CLASSNAME, __func__, ret); - #endif - return ret; -} - -int CActiveAEResamplePi::GetBufferedSamples() -{ - int samples = 0; - if (m_encoded_buffer) - { - const int d_samplesize = m_dst_channels * m_src_pitch; - samples = m_encoded_buffer->nFilledLen / d_samplesize - m_offset; - } - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, samples); - #endif - return samples; -} - -int CActiveAEResamplePi::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) -{ - int ret = av_rescale_rnd(src_samples, dst_rate, src_rate, AV_ROUND_UP); - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); - #endif - return ret; -} - -int CActiveAEResamplePi::GetSrcBufferSize(int samples) -{ - int ret = av_samples_get_buffer_size(NULL, m_src_channels, samples, m_src_fmt, 1); - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); - #endif - return ret; -} - -int CActiveAEResamplePi::GetDstBufferSize(int samples) -{ - int ret = av_samples_get_buffer_size(NULL, m_dst_channels, samples, m_dst_fmt, 1); - #ifdef DEBUG_VERBOSE - CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); - #endif - return ret; -} diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h deleted file mode 100644 index 8a6ad52ce1..0000000000 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "cores/AudioEngine/Interfaces/AEResample.h" - -#include "platform/linux/OMXCore.h" - -namespace ActiveAE -{ - -class CActiveAEResamplePi : public IAEResample -{ -public: - const char *GetName() { return "ActiveAEResamplePi"; } - CActiveAEResamplePi(); - virtual ~CActiveAEResamplePi(); - bool Init(SampleConfig dstConfig, SampleConfig srcConfig, bool upmix, bool normalize, double centerMix, - CAEChannelInfo *remapLayout, AEQuality quality, bool force_resample); - 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(); - bool WantsNewSamples(int samples) { return GetBufferedSamples() <= samples; } - int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate); - int GetSrcBufferSize(int samples); - int GetDstBufferSize(int samples); - -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; - int m_src_pitch, m_dst_pitch; - int m_src_dither_bits, m_dst_dither_bits; - - OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input; - OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output; - COMXCoreComponent m_omx_mixer; - bool m_Initialized; - bool m_force_resample; - OMX_BUFFERHEADERTYPE *m_encoded_buffer; - unsigned int m_offset; - double m_ratio; -}; - -} diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp deleted file mode 100644 index 7822c91fdb..0000000000 --- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "AESinkPi.h" - -#include "ServiceBroker.h" -#include "cores/AudioEngine/AESinkFactory.h" -#include "cores/AudioEngine/Utils/AEUtil.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "utils/XTimeUtils.h" -#include "utils/log.h" - -#include "platform/linux/RBP.h" - -#include <cassert> -#include <limits.h> -#include <stdint.h> - -#define CLASSNAME "CAESinkPi" - -#define NUM_OMX_BUFFERS 2 -#define AUDIO_PLAYBUFFER (0.1) // 100ms - -#ifdef OMX_SKIP64BIT -static inline OMX_TICKS ToOMXTime(int64_t pts) -{ - OMX_TICKS ticks; - ticks.nLowPart = pts; - ticks.nHighPart = pts >> 32; - return ticks; -} -#else -#define ToOMXTime(x) (x) -#endif - -static const unsigned int PassthroughSampleRates[] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000 }; - -CAEDeviceInfo CAESinkPi::m_info; - -CAESinkPi::CAESinkPi() : - m_sinkbuffer_sec_per_byte(0), - m_Initialized(false), - m_submitted(0), - m_omx_output(NULL), - m_output(AESINKPI_UNKNOWN) -{ -} - -CAESinkPi::~CAESinkPi() -{ -} - -void CAESinkPi::SetAudioDest() -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest; - OMX_INIT_STRUCTURE(audioDest); - if ( m_omx_render.IsInitialized() ) - { - if (m_output == AESINKPI_ANALOGUE) - strncpy(reinterpret_cast<char*>(audioDest.sName), "local", strlen("local") + 1); - else - strncpy(reinterpret_cast<char*>(audioDest.sName), "hdmi", strlen("hdmi") + 1); - omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - m_omx_render.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - if ( m_omx_render_slave.IsInitialized() ) - { - if (m_output != AESINKPI_ANALOGUE) - strncpy(reinterpret_cast<char*>(audioDest.sName), "local", strlen("local") + 1); - else - strncpy(reinterpret_cast<char*>(audioDest.sName), "hdmi", strlen("hdmi") + 1); - omx_err = m_omx_render_slave.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - m_omx_render_slave.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } -} - -static void SetAudioProps(bool stream_channels, uint32_t channel_map) -{ - char command[80], response[80]; - - sprintf(command, "hdmi_stream_channels %d", stream_channels ? 1 : 0); - vc_gencmd(response, sizeof response, command); - - sprintf(command, "hdmi_channel_map 0x%08x", channel_map); - vc_gencmd(response, sizeof response, command); - - CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map); -} - -static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough) -{ - unsigned int channels = channelLayout.Count(); - uint32_t channel_map = 0; - if (passthrough) - return 0; - - static const unsigned char map_normal[] = - { - 0, //AE_CH_RAW , - 1, //AE_CH_FL - 2, //AE_CH_FR - 4, //AE_CH_FC - 3, //AE_CH_LFE - 7, //AE_CH_BL - 8, //AE_CH_BR - 1, //AE_CH_FLOC, - 2, //AE_CH_FROC, - 4, //AE_CH_BC, - 5, //AE_CH_SL - 6, //AE_CH_SR - }; - static const unsigned char map_back[] = - { - 0, //AE_CH_RAW , - 1, //AE_CH_FL - 2, //AE_CH_FR - 4, //AE_CH_FC - 3, //AE_CH_LFE - 5, //AE_CH_BL - 6, //AE_CH_BR - 1, //AE_CH_FLOC, - 2, //AE_CH_FROC, - 4, //AE_CH_BC, - 5, //AE_CH_SL - 6, //AE_CH_SR - }; - const unsigned char *map = map_normal; - // 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 (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL)) - map = map_back; - - for (unsigned int i = 0; i < channels; ++i) - { - AEChannel c = channelLayout[i]; - unsigned int chan = 0; - if ((unsigned int)c < sizeof map_normal / sizeof *map_normal) - chan = map[(unsigned int)c]; - if (chan > 0) - channel_map |= (chan-1) << (3*i); - } - // These numbers are from Table 28 Audio InfoFrame Data byte 4 of CEA 861 - // and describe the speaker layout - static const uint8_t cea_map[] = { - 0xff, // 0 - 0xff, // 1 - 0x00, // 2.0 - 0x02, // 3.0 - 0x08, // 4.0 - 0x0a, // 5.0 - 0xff, // 6 - 0x12, // 7.0 - 0xff, // 8 - }; - static const uint8_t cea_map_lfe[] = { - 0xff, // 0 - 0xff, // 1 - 0xff, // 2 - 0x01, // 2.1 - 0x03, // 3.1 - 0x09, // 4.1 - 0x0b, // 5.1 - 0xff, // 7 - 0x13, // 7.1 - }; - 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__, channelLayout.HasChannel(AE_CH_LFE), channels); - - channel_map |= cea << 24; - - return channel_map; -} - -void CAESinkPi::Register() -{ - AE::AESinkRegEntry reg; - reg.sinkName = "PI"; - reg.createFunc = CAESinkPi::Create; - reg.enumerateFunc = CAESinkPi::EnumerateDevicesEx; - AE::CAESinkFactory::RegisterSink(reg); -} - -IAESink* CAESinkPi::Create(std::string &device, AEAudioFormat &desiredFormat) -{ - IAESink *sink = new CAESinkPi(); - if (sink->Initialize(desiredFormat, device)) - return sink; - - delete sink; - return nullptr; -} - - -bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) -{ - // This may be called before Application calls g_RBP.Initialise, so call it here too - g_RBP.Initialize(); - - /* if we are raw need to let gpu know */ - m_passthrough = format.m_dataFormat == AE_FMT_RAW; - - m_initDevice = device; - m_initFormat = format; - - const std::string audioDevice = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_AUDIOOUTPUT_AUDIODEVICE); - - if (m_passthrough || audioDevice == "PI:HDMI") - m_output = AESINKPI_HDMI; - else if (audioDevice == "PI:Analogue") - m_output = AESINKPI_ANALOGUE; - else if (audioDevice == "PI:Both") - m_output = AESINKPI_BOTH; - else if (audioDevice == "Default") - m_output = AESINKPI_HDMI; - else assert(0); - - // analogue only supports stereo - if (m_output == AESINKPI_ANALOGUE || m_output == AESINKPI_BOTH) - format.m_channelLayout = AE_CH_LAYOUT_2_0; - - // setup for a 50ms sink feed from SoftAE - 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; - 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 / NUM_OMX_BUFFERS; - - m_format = format; - m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate); - - CLog::Log(LOGDEBUG, "%s:%s Format:%d Channels:%d Samplerate:%d framesize:%d bufsize:%d bytes/s=%.2f dest=%s", CLASSNAME, __func__, - m_format.m_dataFormat, channels, m_format.m_sampleRate, m_format.m_frameSize, m_format.m_frameSize * m_format.m_frames, 1.0/m_sinkbuffer_sec_per_byte, - audioDevice.c_str()); - - // magic value used when omxplayer is playing - want sink to be disabled - if (m_passthrough && m_format.m_streamInfo.m_sampleRate == 16000) - return true; - - SetAudioProps(m_passthrough, GetChannelMap(m_format.m_channelLayout, m_passthrough)); - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if (!m_omx_render.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) - CLog::Log(LOGERROR, "%s::%s - m_omx_render.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - if (m_output == AESINKPI_BOTH) - { - if (!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit)) - CLog::Log(LOGERROR, "%s::%s - m_omx_splitter.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - if (!m_omx_render_slave.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) - CLog::Log(LOGERROR, "%s::%s - m_omx_render.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - m_omx_output = &m_omx_splitter; - } - else - m_omx_output = &m_omx_render; - - SetAudioDest(); - - OMX_INIT_STRUCTURE(m_pcm_input); - m_pcm_input.eNumData = OMX_NumericalDataSigned; - m_pcm_input.eEndian = OMX_EndianLittle; - m_pcm_input.bInterleaved = OMX_TRUE; - m_pcm_input.nBitPerSample = sample_size * 8; - // 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; - - if ( m_omx_splitter.IsInitialized() ) - { - m_pcm_input.nPortIndex = m_omx_splitter.GetInputPort(); - omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - m_pcm_input.nPortIndex = m_omx_splitter.GetOutputPort(); - omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); - if(omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - m_pcm_input.nPortIndex = m_omx_splitter.GetOutputPort() + 1; - omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); - if(omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - - if ( m_omx_render_slave.IsInitialized() ) - { - m_pcm_input.nPortIndex = m_omx_render_slave.GetInputPort(); - omx_err = m_omx_render_slave.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_render_slave SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - - if ( m_omx_render.IsInitialized() ) - { - m_pcm_input.nPortIndex = m_omx_render.GetInputPort(); - omx_err = m_omx_render.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s::%s - error m_omx_render SetParameter in omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - - if ( m_omx_output->IsInitialized() ) - { - // set up the number/size of buffers for decoder input - OMX_PARAM_PORTDEFINITIONTYPE port_param; - OMX_INIT_STRUCTURE(port_param); - port_param.nPortIndex = m_omx_output->GetInputPort(); - - omx_err = m_omx_output->GetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) - 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 = ALIGN_UP(m_format.m_frameSize * m_format.m_frames, port_param.nBufferAlignment); - - omx_err = m_omx_output->SetParameter(OMX_IndexParamPortDefinition, &port_param); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - - omx_err = m_omx_output->AllocInputBuffers(); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); - } - - if ( m_omx_splitter.IsInitialized() ) - { - m_omx_tunnel_splitter.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); - omx_err = m_omx_tunnel_splitter.Establish(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter.Establish 0x%08x", omx_err); - return false; - } - - m_omx_tunnel_splitter_slave.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort() + 1, &m_omx_render_slave, m_omx_render_slave.GetInputPort()); - omx_err = m_omx_tunnel_splitter_slave.Establish(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_slave.Establish 0x%08x", omx_err); - return false; - } - } - - if ( m_omx_splitter.IsInitialized() ) - { - omx_err = m_omx_splitter.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - m_omx_splitter OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - if ( m_omx_render.IsInitialized() ) - { - omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - m_omx_render OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - if ( m_omx_render_slave.IsInitialized() ) - { - omx_err = m_omx_render_slave.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - CLog::Log(LOGERROR, "%s:%s - m_omx_render_slave OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); - } - - m_Initialized = true; - return true; -} - - -void CAESinkPi::Deinitialize() -{ - CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); - SetAudioProps(false, 0); - - if ( m_omx_render.IsInitialized() ) - m_omx_render.IgnoreNextError(OMX_ErrorPortUnpopulated); - if ( m_omx_render_slave.IsInitialized() ) - m_omx_render_slave.IgnoreNextError(OMX_ErrorPortUnpopulated); - - if ( m_omx_tunnel_splitter.IsInitialized() ) - m_omx_tunnel_splitter.Deestablish(); - if ( m_omx_tunnel_splitter_slave.IsInitialized() ) - m_omx_tunnel_splitter_slave.Deestablish(); - - if ( m_omx_splitter.IsInitialized() ) - m_omx_splitter.FlushAll(); - if ( m_omx_render.IsInitialized() ) - m_omx_render.FlushAll(); - if ( m_omx_render_slave.IsInitialized() ) - m_omx_render_slave.FlushAll(); - - if ( m_omx_splitter.IsInitialized() ) - m_omx_splitter.Deinitialize(); - if ( m_omx_render.IsInitialized() ) - m_omx_render.Deinitialize(); - if ( m_omx_render_slave.IsInitialized() ) - m_omx_render_slave.Deinitialize(); - - m_Initialized = false; -} - -bool CAESinkPi::IsCompatible(const AEAudioFormat &format, const std::string &device) -{ - bool compatible = - /* compare against the requested format and the real format */ - (m_initFormat.m_sampleRate == format.m_sampleRate || m_format.m_sampleRate == format.m_sampleRate ) && - (m_initFormat.m_dataFormat == format.m_dataFormat || m_format.m_dataFormat == format.m_dataFormat ) && - (m_initFormat.m_channelLayout == format.m_channelLayout || m_format.m_channelLayout == format.m_channelLayout) && - (m_initDevice == device); - CLog::Log(LOGDEBUG, "%s:%s Format:%d Channels:%d Samplerate:%d = %d", CLASSNAME, __func__, format.m_dataFormat, format.m_channelLayout.Count(), format.m_sampleRate, compatible); - return compatible; -} - -void CAESinkPi::GetDelay(AEDelayStatus& status) -{ - OMX_PARAM_U32TYPE param; - OMX_INIT_STRUCTURE(param); - - if (!m_Initialized) - { - status.SetDelay(0); - return; - } - - param.nPortIndex = m_omx_render.GetInputPort(); - - OMX_ERRORTYPE omx_err = m_omx_render.GetConfig(OMX_IndexConfigAudioRenderingLatency, ¶m); - - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x", - CLASSNAME, __func__, omx_err); - } - double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * param.nU32 * m_format.m_frameSize; - status.SetDelay(sinkbuffer_seconds_to_empty); -} - -double CAESinkPi::GetCacheTotal() -{ - return AUDIO_PLAYBUFFER; -} - -unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) -{ - if (!m_Initialized || !m_omx_output || !frames) - { - KODI::TIME::Sleep(10); - 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; - - AEDelayStatus status; - GetDelay(status); - double delay = status.GetDelay(); - if (delay <= 0.0 && m_submitted) - CLog::Log(LOGINFO, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames); - - omx_buffer = m_omx_output->GetInputBuffer(1000); - if (omx_buffer == NULL) - { - CLog::Log(LOGERROR, "CAESinkPi::AddPackets timeout"); - return 0; - } - - 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; - - 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_output->EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err); - m_omx_output->DecoderEmptyBufferDone(m_omx_output->GetComponent(), omx_buffer); - } - m_submitted++; - GetDelay(status); - delay = status.GetDelay(); - if (delay > AUDIO_PLAYBUFFER) - KODI::TIME::Sleep(static_cast<int>(1000.0f * (delay - AUDIO_PLAYBUFFER))); - return frames; -} - -void CAESinkPi::Drain() -{ - AEDelayStatus status; - GetDelay(status); - int delay = (int)(status.GetDelay() * 1000.0); - if (delay) - KODI::TIME::Sleep(delay); - CLog::Log(LOGDEBUG, "%s:%s delay:%dms now:%dms", CLASSNAME, __func__, delay, (int)(status.GetDelay() * 1000.0)); -} - -void CAESinkPi::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) -{ - m_info.m_channels.Reset(); - m_info.m_dataFormats.clear(); - m_info.m_streamTypes.clear(); - m_info.m_sampleRates.clear(); - - m_info.m_deviceType = AE_DEVTYPE_HDMI; - m_info.m_deviceName = "HDMI"; - m_info.m_displayName = "HDMI"; - m_info.m_displayNameExtra = ""; - m_info.m_channels += AE_CH_FL; - m_info.m_channels += AE_CH_FR; - for (unsigned int i=0; i<sizeof PassthroughSampleRates/sizeof *PassthroughSampleRates; i++) - m_info.m_sampleRates.push_back(PassthroughSampleRates[i]); - m_info.m_dataFormats.push_back(AE_FMT_FLOAT); - m_info.m_dataFormats.push_back(AE_FMT_S32NE); - m_info.m_dataFormats.push_back(AE_FMT_S16NE); - m_info.m_dataFormats.push_back(AE_FMT_S32LE); - m_info.m_dataFormats.push_back(AE_FMT_S16LE); - m_info.m_dataFormats.push_back(AE_FMT_FLOATP); - m_info.m_dataFormats.push_back(AE_FMT_S32NEP); - m_info.m_dataFormats.push_back(AE_FMT_S16NEP); - - m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_AC3); - m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_EAC3); - m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTSHD_CORE); - m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTS_2048); - m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTS_1024); - m_info.m_streamTypes.push_back(CAEStreamInfo::STREAM_TYPE_DTS_512); - m_info.m_dataFormats.push_back(AE_FMT_RAW); - - m_info.m_wantsIECPassthrough = true; - list.push_back(m_info); - - m_info.m_channels.Reset(); - m_info.m_dataFormats.clear(); - m_info.m_streamTypes.clear(); - m_info.m_sampleRates.clear(); - - m_info.m_deviceType = AE_DEVTYPE_PCM; - m_info.m_deviceName = "Analogue"; - m_info.m_displayName = "Analogue"; - m_info.m_displayNameExtra = ""; - m_info.m_channels += AE_CH_FL; - m_info.m_channels += AE_CH_FR; - m_info.m_sampleRates.push_back(48000); - m_info.m_dataFormats.push_back(AE_FMT_FLOAT); - m_info.m_dataFormats.push_back(AE_FMT_S32LE); - m_info.m_dataFormats.push_back(AE_FMT_S16LE); - m_info.m_dataFormats.push_back(AE_FMT_FLOATP); - m_info.m_dataFormats.push_back(AE_FMT_S32NEP); - m_info.m_dataFormats.push_back(AE_FMT_S16NEP); - - m_info.m_wantsIECPassthrough = true; - list.push_back(m_info); - - m_info.m_channels.Reset(); - m_info.m_dataFormats.clear(); - m_info.m_streamTypes.clear(); - m_info.m_sampleRates.clear(); - - m_info.m_deviceType = AE_DEVTYPE_PCM; - m_info.m_deviceName = "Both"; - m_info.m_displayName = "HDMI and Analogue"; - m_info.m_displayNameExtra = ""; - m_info.m_channels += AE_CH_FL; - m_info.m_channels += AE_CH_FR; - m_info.m_sampleRates.push_back(48000); - m_info.m_dataFormats.push_back(AE_FMT_FLOAT); - m_info.m_dataFormats.push_back(AE_FMT_S32LE); - m_info.m_dataFormats.push_back(AE_FMT_S16LE); - m_info.m_dataFormats.push_back(AE_FMT_FLOATP); - m_info.m_dataFormats.push_back(AE_FMT_S32NEP); - m_info.m_dataFormats.push_back(AE_FMT_S16NEP); - - m_info.m_wantsIECPassthrough = true; - list.push_back(m_info); -} diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h deleted file mode 100644 index 3003bf90a9..0000000000 --- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "cores/AudioEngine/Interfaces/AESink.h" -#include "cores/AudioEngine/Utils/AEDeviceInfo.h" -#include "utils/XTimeUtils.h" - -#include "platform/linux/OMXCore.h" - -class CAESinkPi : public IAESink -{ -public: - virtual const char *GetName() { return "SinkPi"; } - - CAESinkPi(); - virtual ~CAESinkPi(); - - static void Register(); - static IAESink* Create(std::string &device, AEAudioFormat &desiredFormat); - - virtual bool Initialize(AEAudioFormat &format, std::string &device); - virtual void Deinitialize(); - virtual bool IsCompatible(const AEAudioFormat &format, const std::string &device); - - virtual void GetDelay (AEDelayStatus& status); - virtual double GetCacheTotal (); - virtual unsigned int AddPackets (uint8_t **data, unsigned int frames, unsigned int offset); - virtual void Drain (); - - static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); -private: - void SetAudioDest(); - - std::string m_initDevice; - AEAudioFormat m_initFormat; - AEAudioFormat m_format; - double m_sinkbuffer_sec_per_byte; - static CAEDeviceInfo m_info; - bool m_Initialized; - uint32_t m_submitted; - OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input; - COMXCoreComponent *m_omx_output; - COMXCoreComponent m_omx_splitter; - COMXCoreComponent m_omx_render; - COMXCoreComponent m_omx_render_slave; - bool m_passthrough; - COMXCoreTunnel m_omx_tunnel_splitter; - COMXCoreTunnel m_omx_tunnel_splitter_slave; - enum { AESINKPI_UNKNOWN, AESINKPI_HDMI, AESINKPI_ANALOGUE, AESINKPI_BOTH } m_output; -}; diff --git a/xbmc/cores/RetroPlayer/process/rbpi/CMakeLists.txt b/xbmc/cores/RetroPlayer/process/rbpi/CMakeLists.txt deleted file mode 100644 index 97eb97960f..0000000000 --- a/xbmc/cores/RetroPlayer/process/rbpi/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - set(SOURCES RPProcessInfoPi.cpp) - - set(HEADERS RPProcessInfoPi.h) - - core_add_library(rp-process-pi) -endif() diff --git a/xbmc/cores/RetroPlayer/process/rbpi/RPProcessInfoPi.cpp b/xbmc/cores/RetroPlayer/process/rbpi/RPProcessInfoPi.cpp deleted file mode 100644 index 135172979a..0000000000 --- a/xbmc/cores/RetroPlayer/process/rbpi/RPProcessInfoPi.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2017-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "RPProcessInfoPi.h" - -using namespace KODI; -using namespace RETRO; - -CRPProcessInfoPi::CRPProcessInfoPi() : CRPProcessInfo("RPi") -{ -} - -CRPProcessInfo* CRPProcessInfoPi::Create() -{ - return new CRPProcessInfoPi(); -} - -void CRPProcessInfoPi::Register() -{ - CRPProcessInfo::RegisterProcessControl(CRPProcessInfoPi::Create); -} diff --git a/xbmc/cores/RetroPlayer/process/rbpi/RPProcessInfoPi.h b/xbmc/cores/RetroPlayer/process/rbpi/RPProcessInfoPi.h deleted file mode 100644 index a800f72bbb..0000000000 --- a/xbmc/cores/RetroPlayer/process/rbpi/RPProcessInfoPi.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2017-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "cores/RetroPlayer/process/RPProcessInfo.h" - -namespace KODI -{ -namespace RETRO -{ -class CRPProcessInfoPi : public CRPProcessInfo -{ -public: - CRPProcessInfoPi(); - - static CRPProcessInfo* Create(); - static void Register(); -}; -} // namespace RETRO -} // namespace KODI diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt index f7b5513136..b276581e4c 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt @@ -31,13 +31,6 @@ if(APPLE) list(APPEND HEADERS VTB.h) endif() -if(MMAL_FOUND) - list(APPEND SOURCES MMALCodec.cpp) - list(APPEND HEADERS MMALCodec.h) - list(APPEND SOURCES MMALFFmpeg.cpp) - list(APPEND HEADERS MMALFFmpeg.h) -endif() - if(CORE_SYSTEM_NAME STREQUAL android) list(APPEND SOURCES DVDVideoCodecAndroidMediaCodec.cpp) list(APPEND HEADERS DVDVideoCodecAndroidMediaCodec.h) diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp deleted file mode 100644 index 4fdd733026..0000000000 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp +++ /dev/null @@ -1,860 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#if defined(TARGET_WINDOWS) -#endif - -#include <interface/mmal/util/mmal_util.h> -#include <interface/mmal/util/mmal_default_components.h> -#include <interface/mmal/util/mmal_util_params.h> - -#include "MMALCodec.h" - -#include "ServiceBroker.h" -#include "DVDClock.h" -#include "DVDStreamInfo.h" -#include "cores/VideoPlayer/DVDCodecs/DVDCodecs.h" -#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" -#include "DVDVideoCodec.h" -#include "utils/log.h" -#include "utils/TimeUtils.h" -#include "settings/MediaSettings.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "messaging/ApplicationMessenger.h" -#include "Application.h" -#include "guilib/GUIWindowManager.h" -#include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" -#include "settings/DisplaySettings.h" -#include "settings/SettingsComponent.h" -#include "cores/VideoPlayer/VideoRenderers/RenderManager.h" -#include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" - -#include "platform/linux/RBP.h" - -using namespace KODI::MESSAGING; -using namespace MMAL; - -#define CLASSNAME "CMMALVideoBuffer" - -#define VERBOSE 0 - -CMMALVideoBuffer::CMMALVideoBuffer(int id) : CMMALBuffer(id) -{ -} - -CMMALVideoBuffer::~CMMALVideoBuffer() -{ -} - -#undef CLASSNAME -#define CLASSNAME "CMMALVideo" - -CMMALVideo::CMMALVideo(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo) -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s %p", CLASSNAME, __func__, static_cast<void*>(this)); - - m_decoded_width = 0; - m_decoded_height = 0; - m_decoded_aligned_width = 0; - m_decoded_aligned_height = 0; - - m_finished = false; - m_pFormatName = "mmal-xxxx"; - - m_interlace_mode = MMAL_InterlaceProgressive; - m_decoderPts = DVD_NOPTS_VALUE; - m_demuxerPts = DVD_NOPTS_VALUE; - - m_dec = NULL; - m_dec_input = NULL; - m_dec_output = NULL; - m_dec_input_pool = NULL; - m_pool = nullptr; - - m_codingType = 0; - - m_es_format = mmal_format_alloc(); - m_preroll = true; - m_speed = DVD_PLAYSPEED_NORMAL; - m_fps = 0.0f; - m_num_decoded = 0; - m_codecControlFlags = 0; - m_got_eos = false; - m_packet_num = 0; - m_packet_num_eos = ~0; -} - -CMMALVideo::~CMMALVideo() -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s %p", CLASSNAME, __func__, static_cast<void*>(this)); - if (!m_finished) - Dispose(); - - CSingleLock lock(m_sharedSection); - - if (m_dec && m_dec->control && m_dec->control->is_enabled) - mmal_port_disable(m_dec->control); - - if (m_dec_input && m_dec_input->is_enabled) - mmal_port_disable(m_dec_input); - - m_dec_output = NULL; - - if (m_dec_input_pool) - mmal_port_pool_destroy(m_dec_input, m_dec_input_pool); - m_dec_input_pool = NULL; - m_dec_input = NULL; - - m_dec = NULL; - mmal_format_free(m_es_format); - m_es_format = NULL; -} - -void CMMALVideo::PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CSingleLock lock(m_sharedSection); - MMAL_EVENT_FORMAT_CHANGED_T *fmt = mmal_event_format_changed_get(buffer); - mmal_format_copy(m_es_format, fmt->format); - - if (m_es_format->es->video.crop.width && m_es_format->es->video.crop.height) - { - if (m_es_format->es->video.par.num && m_es_format->es->video.par.den) - m_aspect_ratio = (float)(m_es_format->es->video.par.num * m_es_format->es->video.crop.width) / (m_es_format->es->video.par.den * m_es_format->es->video.crop.height); - m_decoded_width = m_es_format->es->video.crop.width; - m_decoded_height = m_es_format->es->video.crop.height; - m_decoded_aligned_width = m_es_format->es->video.width; - m_decoded_aligned_height = m_es_format->es->video.height; - - m_processInfo.SetVideoDimensions(m_decoded_width, m_decoded_height); - m_processInfo.SetVideoDAR(m_aspect_ratio); - - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s format changed: %dx%d (%dx%d) %.2f", CLASSNAME, __func__, m_decoded_width, m_decoded_height, m_decoded_aligned_width, m_decoded_aligned_height, m_aspect_ratio); - } - else - CLog::Log(LOGERROR, "%s::%s format changed: Unexpected %dx%d (%dx%d)", CLASSNAME, __func__, m_es_format->es->video.crop.width, m_es_format->es->video.crop.height, m_decoded_aligned_width, m_decoded_aligned_height); - - if (!change_dec_output_format()) - CLog::Log(LOGERROR, "%s::%s - change_dec_output_format() failed", CLASSNAME, __func__); -} - -void CMMALVideo::dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - MMAL_STATUS_T status; - - if (buffer->cmd == MMAL_EVENT_ERROR) - { - status = (MMAL_STATUS_T)*(uint32_t *)buffer->data; - CLog::Log(LOGERROR, "%s::%s Error (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - } - else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) - { - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s format changed", CLASSNAME, __func__); - PortSettingsChanged(port, buffer); - } - else - CLog::Log(LOGERROR, "%s::%s other (cmd:%x data:%x)", CLASSNAME, __func__, buffer->cmd, *(uint32_t *)buffer->data); - - mmal_buffer_header_release(buffer); -} - -static void dec_control_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CMMALVideo *mmal = reinterpret_cast<CMMALVideo*>(port->userdata); - mmal->dec_control_port_cb(port, buffer); -} - - -void CMMALVideo::dec_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, - static_cast<void*>(port), static_cast<void*>(buffer), buffer->length, buffer->cmd); - mmal_buffer_header_release(buffer); - CSingleLock output_lock(m_output_mutex); - m_output_cond.notifyAll(); -} - -static void dec_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CMMALVideo *mmal = reinterpret_cast<CMMALVideo*>(port->userdata); - mmal->dec_input_port_cb(port, buffer); -} - - -void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - if (!(buffer->cmd == 0 && buffer->length > 0)) - { - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s port:%p buffer %p, len %d cmd:%x flags:%x", CLASSNAME, - __func__, static_cast<void*>(port), static_cast<void*>(buffer), buffer->length, - buffer->cmd, buffer->flags); - } - - bool kept = false; - CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; - - assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)); - if (buffer->cmd == 0) - { - if (buffer->length > 0) - { - if (buffer->pts != MMAL_TIME_UNKNOWN) - m_decoderPts = buffer->pts; - else if (buffer->dts != MMAL_TIME_UNKNOWN) - m_decoderPts = buffer->dts; - - assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); - assert(omvb); - assert(omvb->mmal_buffer == buffer); - bool wanted = true; - // we don't keep up when running at 60fps in the background so switch to half rate - if (m_fps > 40.0f && !CServiceBroker::GetWinSystem()->GetGfxContext().IsFullScreenVideo() && !(m_num_decoded & 1)) - wanted = false; - if ((buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED)) - wanted = false; - m_num_decoded++; - CLog::Log(LOGDEBUG, LOGVIDEO, - "%s::%s - omvb:%p mmal:%p len:%u dts:%.3f pts:%.3f flags:%x:%x pool:%p %dx%d " - "(%dx%d) %dx%d (%dx%d) enc:%.4s", - CLASSNAME, __func__, static_cast<void*>(buffer), static_cast<void*>(omvb), - buffer->length, buffer->dts * 1e-6, buffer->pts * 1e-6, buffer->flags, - buffer->type->video.flags, static_cast<void*>(m_pool.get()), omvb->Width(), - omvb->Height(), omvb->AlignedWidth(), omvb->AlignedHeight(), m_decoded_width, - m_decoded_height, m_decoded_aligned_width, m_decoded_aligned_height, - (char*)&omvb->Encoding()); - if (wanted) - { - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - if (pool) - pool->Configure(AV_PIX_FMT_NONE, m_decoded_width, m_decoded_height, m_decoded_aligned_width, m_decoded_aligned_height, 128); - omvb->m_aspect_ratio = m_aspect_ratio; - { - CSingleLock output_lock(m_output_mutex); - m_output_ready.push(omvb); - m_output_cond.notifyAll(); - } - kept = true; - } - } - if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS) - { - CSingleLock output_lock(m_output_mutex); - m_got_eos = true; - m_output_cond.notifyAll(); - } - } - else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) - { - PortSettingsChanged(port, buffer); - } - if (!kept) - { - if (omvb) - omvb->Release(); - else - mmal_buffer_header_release(buffer); - } -} - -static void dec_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CMMALVideo *mmal = reinterpret_cast<CMMALVideo*>(port->userdata); - mmal->dec_output_port_cb(port, buffer); -} - -bool CMMALVideo::change_dec_output_format() -{ - CSingleLock lock(m_sharedSection); - MMAL_STATUS_T status; - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s", CLASSNAME, __func__); - - MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type = {{ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE, sizeof( interlace_type )}}; - status = mmal_port_parameter_get( m_dec_output, &interlace_type.hdr ); - - if (status == MMAL_SUCCESS) - { - if (m_interlace_mode != interlace_type.eMode) - { - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s Interlace mode %d->%d", CLASSNAME, __func__, m_interlace_mode, interlace_type.eMode); - m_interlace_mode = interlace_type.eMode; - } - } - else - CLog::Log(LOGERROR, "%s::%s Failed to query interlace type on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); - - mmal_format_copy(m_dec_output->format, m_es_format); - - status = mmal_port_parameter_set_boolean(m_dec_output, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); - - status = mmal_port_format_commit(m_dec_output); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - return true; -} - -bool CMMALVideo::SendCodecConfigData() -{ - CSingleLock lock(m_sharedSection); - MMAL_STATUS_T status; - if (!m_dec_input_pool || !m_hints.extrasize) - return true; - // send code config data - MMAL_BUFFER_HEADER_T *buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500); - if (!buffer) - { - CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); - return false; - } - - mmal_buffer_header_reset(buffer); - buffer->cmd = 0; - buffer->length = std::min(m_hints.extrasize, buffer->alloc_size); - memcpy(buffer->data, m_hints.extradata, buffer->length); - buffer->flags = MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_CONFIG; - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - %-8p %-6d flags:%x", CLASSNAME, __func__, static_cast<void*>(buffer), - buffer->length, buffer->flags); - status = mmal_port_send_buffer(m_dec_input, buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - return true; -} - -bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) -{ - CSingleLock lock(m_sharedSection); - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s usemmal:%d options:%x %dx%d", CLASSNAME, __func__, CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_USEMMAL), hints.codecOptions, hints.width, hints.height); - - // This occurs at start of m2ts files before streams have been fully identified - just ignore - if (!hints.width) - return false; - // we always qualify even if DVDFactoryCodec does this too. - if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_USEMMAL) || (hints.codecOptions & CODEC_FORCE_SOFTWARE)) - return false; - - std::list<EINTERLACEMETHOD> deintMethods; - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_AUTO); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_ADVANCED); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_BOB); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_BOB_HALF); - m_processInfo.UpdateDeinterlacingMethods(deintMethods); - - m_hints = hints; - MMAL_STATUS_T status; - - m_decoded_width = hints.width; - m_decoded_height = hints.height; - - m_decoded_aligned_width = ALIGN_UP(m_decoded_width, 32); - m_decoded_aligned_height = ALIGN_UP(m_decoded_height, 16); - - // use aspect in stream if available - if (m_hints.forced_aspect) - m_aspect_ratio = m_hints.aspect; - else - m_aspect_ratio = 0.0; - - switch (hints.codec) - { - case AV_CODEC_ID_H264: - // H.264 - switch (hints.profile) - { - // Cannot hardware decode Hi10P without artifacts - switch to software on Pi2/Pi3 - case FF_PROFILE_H264_HIGH_10: - case FF_PROFILE_H264_HIGH_10_INTRA: - if (g_RBP.RaspberryPiVersion() > 1) - return false; - } - m_codingType = MMAL_ENCODING_H264; - m_pFormatName = "mmal-h264"; - if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_SUPPORTMVC)) - { - m_codingType = MMAL_ENCODING_MVC; - m_pFormatName= "mmal-mvc"; - } - break; - case AV_CODEC_ID_H263: - case AV_CODEC_ID_MPEG4: - // MPEG-4, DivX 4/5 and Xvid compatible - m_codingType = MMAL_ENCODING_MP4V; - m_pFormatName = "mmal-mpeg4"; - break; - case AV_CODEC_ID_MPEG1VIDEO: - case AV_CODEC_ID_MPEG2VIDEO: - // MPEG-2 - m_codingType = MMAL_ENCODING_MP2V; - m_pFormatName = "mmal-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 = MMAL_ENCODING_VP6; - m_pFormatName = "mmal-vp6"; - break; - case AV_CODEC_ID_VP8: - // VP8 - m_codingType = MMAL_ENCODING_VP8; - m_pFormatName = "mmal-vp8"; - break; - case AV_CODEC_ID_THEORA: - // theora - m_codingType = MMAL_ENCODING_THEORA; - m_pFormatName = "mmal-theora"; - break; - case AV_CODEC_ID_MJPEG: - case AV_CODEC_ID_MJPEGB: - // mjpg - m_codingType = MMAL_ENCODING_MJPEG; - m_pFormatName = "mmal-mjpg"; - break; - case AV_CODEC_ID_VC1: - case AV_CODEC_ID_WMV3: - // VC-1, WMV9 - m_codingType = MMAL_ENCODING_WVC1; - m_pFormatName = "mmal-vc1"; - break; - default: - CLog::Log(LOGERROR, "%s::%s : Video codec unknown: %x", CLASSNAME, __func__, hints.codec); - return false; - break; - } - - if ( (m_codingType == MMAL_ENCODING_MP2V && !g_RBP.GetCodecMpg2() ) || - (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) - { - CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported", CLASSNAME, __func__, m_pFormatName); - return false; - } - - /* Create video component with attached pool */ - m_pool = std::make_shared<CMMALPool>(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, false, MMAL_NUM_OUTPUT_BUFFERS, 128, MMAL_ENCODING_OPAQUE, MMALStateHWDec); - if (!m_pool) - { - CLog::Log(LOGERROR, "%s::%s Failed to create pool for video output", CLASSNAME, __func__); - return false; - } - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - pool->SetProcessInfo(&m_processInfo); - m_dec = pool->GetComponent(); - - m_dec->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; - status = mmal_port_enable(m_dec->control, dec_control_port_cb_static); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable decoder control port %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); - return false; - } - - m_dec_input = m_dec->input[0]; - - m_dec_input->format->type = MMAL_ES_TYPE_VIDEO; - m_dec_input->format->encoding = m_codingType; - if (m_decoded_width && m_decoded_height) - { - m_dec_input->format->es->video.crop.width = m_decoded_width; - m_dec_input->format->es->video.crop.height = m_decoded_height; - - m_dec_input->format->es->video.width = m_decoded_aligned_width; - m_dec_input->format->es->video.height = m_decoded_aligned_width; - } - if (hints.fpsrate > 0 && hints.fpsscale > 0) - { - m_dec_input->format->es->video.frame_rate.num = hints.fpsrate; - m_dec_input->format->es->video.frame_rate.den = hints.fpsscale; - m_fps = hints.fpsrate / hints.fpsscale; - } - else - m_fps = 0.0f; - m_dec_input->format->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; - - status = mmal_port_parameter_set_boolean(m_dec_input, MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT, MMAL_FALSE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to disable error concealment on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - - // we need an extra buffer when seeking as a picture remains on screen from old seek point - status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, GetAllowedReferences() + 1); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - - status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 1); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to disable interpolate timestamps mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - - // limit number of callback structures in video_decode to reduce latency. Too low and video hangs. - // negative numbers have special meaning. -1=size of DPB -2=size of DPB+1 - status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS, -5); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to configure max num callbacks on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - - status = mmal_port_parameter_set_boolean(m_dec_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - - status = mmal_port_format_commit(m_dec_input); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to commit format for decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - return false; - } - // use a small number of large buffers to keep latency under control - m_dec_input->buffer_size = 1024*1024; - m_dec_input->buffer_num = 2; - - m_dec_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; - status = mmal_port_enable(m_dec_input, dec_input_port_cb_static); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); - return false; - } - - m_dec_output = m_dec->output[0]; - - mmal_format_copy(m_es_format, m_dec_output->format); - - status = mmal_port_format_commit(m_dec_output); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - m_dec_output->buffer_size = m_dec_output->buffer_size_min; - m_dec_output->buffer_num = MMAL_NUM_OUTPUT_BUFFERS; - m_dec_output->userdata = (struct MMAL_PORT_USERDATA_T *)this; - status = mmal_port_enable(m_dec_output, dec_output_port_cb_static); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - status = mmal_component_enable(m_dec); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable decoder component %s (status=%x %s)", CLASSNAME, __func__, m_dec->name, status, mmal_status_to_string(status)); - return false; - } - - m_dec_input_pool = mmal_port_pool_create(m_dec_input, m_dec_input->buffer_num, m_dec_input->buffer_size); - if (!m_dec_input_pool) - { - CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - if (!SendCodecConfigData()) - return false; - - if (pool) - pool->Prime(); - m_preroll = !m_hints.stills; - m_speed = DVD_PLAYSPEED_NORMAL; - - m_processInfo.SetVideoDecoderName(m_pFormatName, true); - m_processInfo.SetVideoDimensions(m_decoded_width, m_decoded_height); - m_processInfo.SetVideoDAR(m_aspect_ratio); - - return true; -} - -void CMMALVideo::Dispose() -{ - CSingleLock lock(m_sharedSection); - m_finished = true; - Reset(); -} - -bool CMMALVideo::AddData(const DemuxPacket &packet) -{ - uint8_t* pData = packet.pData; - int iSize = packet.iSize; - CSingleLock lock(m_sharedSection); - //if (CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - // CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f ready_queue(%d)", - // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : packet.dts*1e-6, packet.pts == DVD_NOPTS_VALUE ? 0.0 : packet.pts*1e-6, m_output_ready.size()); - - MMAL_BUFFER_HEADER_T *buffer; - MMAL_STATUS_T status; - assert(pData != nullptr && iSize > 0); // no longer valid - - while (iSize > 0) - { - // 500ms timeout - lock.Leave(); - buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500); - if (!buffer) - { - CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); - return false; - } - lock.Enter(); - - mmal_buffer_header_reset(buffer); - buffer->cmd = 0; - buffer->pts = packet.pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : packet.pts; - buffer->dts = packet.dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : packet.dts; - if (m_hints.ptsinvalid) buffer->pts = MMAL_TIME_UNKNOWN; - buffer->length = (uint32_t)iSize > buffer->alloc_size ? buffer->alloc_size : (uint32_t)iSize; - // set a flag so we can identify primary frames from generated frames (deinterlace) - buffer->flags = 0; - if (m_codecControlFlags & DVD_CODEC_CTRL_DROP_ANY) - buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER3; - - if (pData) - memcpy(buffer->data, pData, buffer->length); - iSize -= buffer->length; - pData += buffer->length; - - if (iSize == 0) - { - m_packet_num++; - buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; - } - CLog::Log(LOGDEBUG, LOGVIDEO, - "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x ready_queue(%d)", CLASSNAME, - __func__, static_cast<void*>(buffer), buffer->length, iSize, - packet.dts == DVD_NOPTS_VALUE ? 0.0 : packet.dts * 1e-6, - packet.pts == DVD_NOPTS_VALUE ? 0.0 : packet.pts * 1e-6, buffer->flags, - m_output_ready.size()); - status = mmal_port_send_buffer(m_dec_input, buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - if (packet.pts != DVD_NOPTS_VALUE) - m_demuxerPts = packet.pts; - else if (packet.dts != DVD_NOPTS_VALUE) - m_demuxerPts = packet.dts; - - if (m_demuxerPts != DVD_NOPTS_VALUE && m_decoderPts == DVD_NOPTS_VALUE) - m_decoderPts = m_demuxerPts; - - return true; -} - -void CMMALVideo::Reset(void) -{ - CSingleLock lock(m_sharedSection); - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s", CLASSNAME, __func__); - - if (m_dec_input && m_dec_input->is_enabled) - mmal_port_disable(m_dec_input); - if (m_dec_output && m_dec_output->is_enabled) - mmal_port_disable(m_dec_output); - if (!m_finished) - { - if (m_dec_input) - mmal_port_enable(m_dec_input, dec_input_port_cb_static); - if (m_dec_output) - mmal_port_enable(m_dec_output, dec_output_port_cb_static); - } - // blow all ready video frames - while (1) - { - CMMALVideoBuffer *buffer = NULL; - { - CSingleLock output_lock(m_output_mutex); - // fetch a output buffer and pop it off the ready list - if (!m_output_ready.empty()) - { - buffer = m_output_ready.front(); - m_output_ready.pop(); - } - m_output_cond.notifyAll(); - } - if (buffer) - buffer->Release(); - else - break; - } - - if (!m_finished) - { - SendCodecConfigData(); - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - if (pool) - pool->Prime(); - } - m_decoderPts = DVD_NOPTS_VALUE; - m_demuxerPts = DVD_NOPTS_VALUE; - m_codecControlFlags = 0; - m_num_decoded = 0; - m_got_eos = false; - m_packet_num = 0; - m_packet_num_eos = ~0; - m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); -} - -void CMMALVideo::SetSpeed(int iSpeed) -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s %d->%d", CLASSNAME, __func__, m_speed, iSpeed); - - m_speed = iSpeed; -} - -CDVDVideoCodec::VCReturn CMMALVideo::GetPicture(VideoPicture* picture) -{ - CSingleLock lock(m_sharedSection); - MMAL_STATUS_T status; - bool drain = (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) ? true : false; - bool send_eos = drain && !m_got_eos && m_packet_num_eos != m_packet_num; - - // we don't get an EOS response if no packets have been sent - if (!drain) - m_got_eos = false; - else if (m_packet_num == 0 && send_eos) - m_got_eos = true; - - if (send_eos && !m_got_eos) - { - MMAL_BUFFER_HEADER_T *buffer; - // 500ms timeout - lock.Leave(); - buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500); - lock.Enter(); - - if (buffer) - { - mmal_buffer_header_reset(buffer); - buffer->cmd = 0; - buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_EOS; - m_packet_num_eos = m_packet_num; - m_got_eos = false; - status = mmal_port_send_buffer(m_dec_input, buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return VC_ERROR; - } - else - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - Send EOS (%d, %d, %d)", CLASSNAME, __func__, m_got_eos, m_packet_num, m_packet_num_eos); - } - else - { - CLog::Log(LOGWARNING, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); - // lets assume decoder has returned all it will - m_got_eos = true; - } - } - - // we've built up quite a lot of data in decoder - try to throttle it - double queued = m_decoderPts != DVD_NOPTS_VALUE && m_demuxerPts != DVD_NOPTS_VALUE ? m_demuxerPts - m_decoderPts : 0.0; - bool full = queued > DVD_MSEC_TO_TIME(1000); - CDVDVideoCodec::VCReturn ret = CDVDVideoCodec::VC_NONE; - - CMMALVideoBuffer *buffer = nullptr; - XbmcThreads::EndTime delay(500); - while (ret == CDVDVideoCodec::VC_NONE && !delay.IsTimePast()) - { - CSingleLock output_lock(m_output_mutex); - unsigned int pics = m_output_ready.size(); - if (m_preroll && (pics >= GetAllowedReferences() || drain)) - m_preroll = false; - if (pics > 0 && !m_preroll) - { - // fetch a output buffer and pop it off the ready list - buffer = m_output_ready.front(); - m_output_ready.pop(); - m_output_cond.notifyAll(); - ret = CDVDVideoCodec::VC_PICTURE; - } - else if (m_got_eos) - ret = CDVDVideoCodec::VC_EOF; - else if ((m_preroll || pics <= 1) && mmal_queue_length(m_dec_input_pool->queue) > 0) - ret = CDVDVideoCodec::VC_BUFFER; - if (ret == CDVDVideoCodec::VC_NONE) - { - // otherwise we busy spin - lock.Leave(); - m_output_cond.wait(output_lock, delay.MillisLeft()); - lock.Enter(); - } - } - - if (ret == CDVDVideoCodec::VC_PICTURE) - { - assert(buffer && buffer->mmal_buffer); - if (picture->videoBuffer) - picture->videoBuffer->Release(); - picture->videoBuffer = dynamic_cast<CVideoBuffer*>(buffer); - assert(picture->videoBuffer); - picture->color_range = 0; - picture->iWidth = buffer->Width() ? buffer->Width() : m_decoded_width; - picture->iHeight = buffer->Height() ? buffer->Height() : m_decoded_height; - picture->iDisplayWidth = picture->iWidth; - picture->iDisplayHeight = picture->iHeight; - //CLog::Log(LOGDEBUG, "%s::%s - %dx%d %dx%d %dx%d %dx%d %f,%f", CLASSNAME, __func__, picture->iWidth, picture->iHeight, picture->iDisplayWidth, picture->iDisplayHeight, m_decoded_width, m_decoded_height, buffer->Width(), buffer->Height(), buffer->m_aspect_ratio, m_hints.aspect); - - if (buffer->m_aspect_ratio > 0.0) - { - picture->iDisplayWidth = ((int)lrint(picture->iHeight * buffer->m_aspect_ratio)) & -3; - if (picture->iDisplayWidth > picture->iWidth) - { - picture->iDisplayWidth = picture->iWidth; - picture->iDisplayHeight = ((int)lrint(picture->iWidth / buffer->m_aspect_ratio)) & -3; - } - } - - // timestamp is in microseconds - picture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts; - picture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts; - picture->iRepeatPicture = 0; - picture->iFlags = 0; - if (buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER3) - picture->iFlags |= DVP_FLAG_DROPPED; - CLog::Log(LOGINFO, LOGVIDEO, - "%s::%s dts:%.3f pts:%.3f flags:%x:%x MMALBuffer:%p mmal_buffer:%p", CLASSNAME, - __func__, picture->dts == DVD_NOPTS_VALUE ? 0.0 : picture->dts * 1e-6, - picture->pts == DVD_NOPTS_VALUE ? 0.0 : picture->pts * 1e-6, picture->iFlags, - buffer->mmal_buffer->flags, static_cast<void*>(buffer), - static_cast<void*>(buffer->mmal_buffer)); - assert(!(buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); - buffer->mmal_buffer->flags &= ~MMAL_BUFFER_HEADER_FLAG_USER3; - buffer->m_stills = m_hints.stills; - } - - if (ret == CDVDVideoCodec::VC_NONE) - CLog::Log(LOGWARNING, "%s::%s - ret(%x) pics(%d) inputs(%d) slept(%2d) queued(%.2f) (%.2f:%.2f) full(%d) flags(%x) preroll(%d) eos(%d %d/%d)", CLASSNAME, __func__, ret, m_output_ready.size(), mmal_queue_length(m_dec_input_pool->queue), 500-delay.MillisLeft(), queued*1e-6, m_demuxerPts*1e-6, m_decoderPts*1e-6, full, m_codecControlFlags, m_preroll, m_got_eos, m_packet_num, m_packet_num_eos); - else - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - ret(%x) pics(%d) inputs(%d) slept(%2d) queued(%.2f) (%.2f:%.2f) full(%d) flags(%x) preroll(%d) eos(%d %d/%d)", CLASSNAME, __func__, ret, m_output_ready.size(), mmal_queue_length(m_dec_input_pool->queue), 500-delay.MillisLeft(), queued*1e-6, m_demuxerPts*1e-6, m_decoderPts*1e-6, full, m_codecControlFlags, m_preroll, m_got_eos, m_packet_num, m_packet_num_eos); - - return ret; -} - -void CMMALVideo::SetCodecControl(int flags) -{ - CSingleLock lock(m_sharedSection); - if (m_codecControlFlags != flags) - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s %x->%x", CLASSNAME, __func__, m_codecControlFlags, flags); - m_codecControlFlags = flags; -} - -CDVDVideoCodec* CMMALVideo::Create(CProcessInfo &processInfo) - { - return new CMMALVideo(processInfo); - } - -void CMMALVideo::Register() -{ - CDVDFactoryCodec::RegisterHWVideoCodec("mmal", CMMALVideo::Create); -} diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h deleted file mode 100644 index 0e5e27ce39..0000000000 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "DVDVideoCodec.h" -#include "cores/VideoPlayer/DVDResource.h" -#include "cores/VideoPlayer/DVDStreamInfo.h" -#include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h" -#include "cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h" -#include "cores/VideoSettings.h" -#include "rendering/RenderSystem.h" -#include "threads/Event.h" -#include "utils/Geometry.h" - -#include <memory> -#include <queue> -#include <string> - -#include <semaphore.h> - -namespace MMAL { - -class CMMALVideo; -class CMMALPool; - -// a mmal video frame -class CMMALVideoBuffer : public CMMALBuffer -{ -public: - CMMALVideoBuffer(int id); - virtual ~CMMALVideoBuffer(); -protected: -}; - -class CMMALVideo : public CDVDVideoCodec -{ -public: - CMMALVideo(CProcessInfo &processInfo); - virtual ~CMMALVideo(); - - // Required overrides - virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) override; - virtual bool AddData(const DemuxPacket &packet) override; - virtual void Reset(void) override; - virtual CDVDVideoCodec::VCReturn GetPicture(VideoPicture *pDvdVideoPicture) override; - virtual unsigned GetAllowedReferences() override { return 4; } - virtual const char* GetName(void) override { return m_pFormatName ? m_pFormatName:"mmal-xxx"; } - virtual void SetCodecControl(int flags) override; - virtual void SetSpeed(int iSpeed) override; - - // MMAL decoder callback routines. - void dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - void dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - void dec_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - static CDVDVideoCodec* Create(CProcessInfo &processInfo); - static void Register(); - -protected: - void QueryCodec(void); - void Dispose(void); - - // Video format - unsigned int m_decoded_width; - unsigned int m_decoded_height; - unsigned int m_decoded_aligned_width; - unsigned int m_decoded_aligned_height; - unsigned int m_egl_buffer_count; - bool m_finished; - float m_aspect_ratio; - const char *m_pFormatName; - - // mmal output buffers (video frames) - CCriticalSection m_output_mutex; - XbmcThreads::ConditionVariable m_output_cond; - std::queue<CMMALVideoBuffer*> m_output_ready; - - // initialize mmal and get decoder component - bool Initialize( const std::string &decoder_name); - void PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - bool SendCodecConfigData(); - - CDVDStreamInfo m_hints; - float m_fps; - unsigned m_num_decoded; - // Components - MMAL_INTERLACETYPE_T m_interlace_mode; - double m_demuxerPts; - double m_decoderPts; - int m_speed; - int m_codecControlFlags; - bool m_preroll; - bool m_got_eos; - uint32_t m_packet_num; - uint32_t m_packet_num_eos; - - CCriticalSection m_sharedSection; - MMAL_COMPONENT_T *m_dec; - MMAL_PORT_T *m_dec_input; - MMAL_PORT_T *m_dec_output; - MMAL_POOL_T *m_dec_input_pool; - std::shared_ptr<CMMALPool> m_pool; - - MMAL_ES_FORMAT_T *m_es_format; - - MMAL_FOURCC_T m_codingType; - VideoPicture* m_lastDvdVideoPicture; - - bool change_dec_output_format(); -}; - -}; diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp deleted file mode 100644 index 28eff23f16..0000000000 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (C) 2016-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include <interface/mmal/util/mmal_default_components.h> - -#include "cores/VideoPlayer/VideoRenderers/RenderManager.h" -#include "../DVDCodecUtils.h" -#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" -#include "MMALFFmpeg.h" -#include "utils/log.h" -#include "utils/StringUtils.h" -#include "platform/linux/RBP.h" -#include "settings/AdvancedSettings.h" - -extern "C" { -#include <libavutil/imgutils.h> -} - -using namespace MMAL; - -//----------------------------------------------------------------------------- -// MMAL Buffers -//----------------------------------------------------------------------------- - -#define CLASSNAME "CMMALYUVBuffer" - -#define VERBOSE 0 - -CMMALYUVBuffer::CMMALYUVBuffer(int id) - : CMMALBuffer(id) -{ -} - -CMMALYUVBuffer::~CMMALYUVBuffer() -{ - delete m_gmem; -} - -uint8_t* CMMALYUVBuffer::GetMemPtr() -{ - if (!m_gmem) - return nullptr; - return static_cast<uint8_t *>(m_gmem->m_arm); -} - -void CMMALYUVBuffer::GetPlanes(uint8_t*(&planes)[YuvImage::MAX_PLANES]) -{ - for (int i = 0; i < YuvImage::MAX_PLANES; i++) - planes[i] = nullptr; - - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - assert(pool); - AVRpiZcFrameGeometry geo = pool->GetGeometry(); - - if (VERBOSE) - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s %dx%d %dx%d (%dx%d %dx%d)", CLASSNAME, __FUNCTION__, geo.getStrideY(), geo.getHeightY(), geo.getStrideC(), geo.getHeightC(), Width(), Height(), AlignedWidth(), AlignedHeight()); - - planes[0] = GetMemPtr(); - if (planes[0] && geo.getPlanesC() >= 1) - planes[1] = planes[0] + geo.getSizeY(); - if (planes[1] && geo.getPlanesC() >= 2) - planes[2] = planes[1] + geo.getSizeC(); -} - -void CMMALYUVBuffer::GetStrides(int(&strides)[YuvImage::MAX_PLANES]) -{ - for (int i = 0; i < YuvImage::MAX_PLANES; i++) - strides[i] = 0; - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - assert(pool); - AVRpiZcFrameGeometry geo = pool->GetGeometry(); - strides[0] = geo.getStrideY(); - strides[1] = geo.getStrideC(); - strides[2] = geo.getStrideC(); -} - -void CMMALYUVBuffer::SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES], const int (&planeOffsets)[YuvImage::MAX_PLANES]) -{ - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - assert(pool); - pool->SetDimensions(width, height, strides, planeOffsets); -} - -void CMMALYUVBuffer::SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES]) -{ - const int (&planeOffsets)[YuvImage::MAX_PLANES] = {}; - SetDimensions(width, height, strides, planeOffsets); -} - -CGPUMEM *CMMALYUVBuffer::Allocate(int size, void *opaque) -{ - m_gmem = new CGPUMEM(size, true); - if (m_gmem && m_gmem->m_vc) - { - m_gmem->m_opaque = opaque; - } - else - { - delete m_gmem; - m_gmem = nullptr; - } - return m_gmem; -} - - -//----------------------------------------------------------------------------- -// MMAL Decoder -//----------------------------------------------------------------------------- - -#undef CLASSNAME -#define CLASSNAME "CDecoder" - -void CDecoder::AlignedSize(AVCodecContext *avctx, int &width, int &height) -{ - if (!avctx) - return; - int w = width, h = height; - AVFrame picture; - int unaligned; - int stride_align[AV_NUM_DATA_POINTERS]; - - avcodec_align_dimensions2(avctx, &w, &h, stride_align); - - do { - // NOTE: do not align linesizes individually, this breaks e.g. assumptions - // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 - av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w); - // increase alignment of w for next try (rhs gives the lowest bit set in w) - w += w & ~(w - 1); - - unaligned = 0; - for (int i = 0; i < 4; i++) - unaligned |= picture.linesize[i] % stride_align[i]; - } while (unaligned); - width = w; - height = h; -} - -CDecoder::CDecoder(CProcessInfo &processInfo, CDVDStreamInfo &hints) : m_processInfo(processInfo), m_hints(hints) -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - create %p", CLASSNAME, __FUNCTION__, static_cast<void*>(this)); - m_avctx = nullptr; - m_pool = nullptr; -} - -CDecoder::~CDecoder() -{ - if (m_renderBuffer) - m_renderBuffer->Release(); - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - destroy %p", CLASSNAME, __FUNCTION__, static_cast<void*>(this)); -} - -long CDecoder::Release() -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - m_refs:%ld", CLASSNAME, __FUNCTION__, m_refs.load()); - return IHardwareDecoder::Release(); -} - -void CDecoder::FFReleaseBuffer(void *opaque, uint8_t *data) -{ - CGPUMEM *gmem = (CGPUMEM *)opaque; - CMMALYUVBuffer *YUVBuffer = (CMMALYUVBuffer *)gmem->m_opaque; - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s buf:%p gmem:%p", CLASSNAME, __FUNCTION__, - static_cast<void*>(YUVBuffer), static_cast<void*>(gmem)); - - YUVBuffer->Release(); -} - -int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *frame, int flags) -{ - ICallbackHWAccel* cb = static_cast<ICallbackHWAccel*>(avctx->opaque); - CDecoder* dec = static_cast<CDecoder*>(cb->GetHWAccel()); - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s %dx%d format:%x:%x flags:%x", CLASSNAME, __FUNCTION__, frame->width, frame->height, frame->format, dec->m_fmt, flags); - - if ((avctx->codec && (avctx->codec->capabilities & AV_CODEC_CAP_DR1) == 0) || frame->format != dec->m_fmt) - { - assert(0); - return avcodec_default_get_buffer2(avctx, frame, flags); - } - - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(dec->m_pool); - if (!pool->IsConfigured()) - { - int aligned_width = frame->width; - int aligned_height = frame->height; - if (pool->Encoding() != MMAL_ENCODING_YUVUV128 && pool->Encoding() != MMAL_ENCODING_YUVUV64_16) - { - // ffmpeg requirements - AlignedSize(dec->m_avctx, aligned_width, aligned_height); - // GPU requirements - aligned_width = ALIGN_UP(aligned_width, 32); - aligned_height = ALIGN_UP(aligned_height, 16); - } - pool->Configure(dec->m_fmt, frame->width, frame->height, aligned_width, aligned_height, 0); - } - CMMALYUVBuffer *YUVBuffer = dynamic_cast<CMMALYUVBuffer *>(pool->Get()); - if (!YUVBuffer) - { - CLog::Log(LOGERROR,"%s::%s Failed to allocated buffer in time", CLASSNAME, __FUNCTION__); - return -1; - } - assert(YUVBuffer->mmal_buffer); - - CGPUMEM *gmem = YUVBuffer->GetMem(); - assert(gmem); - - AVBufferRef *buf = av_buffer_create((uint8_t *)gmem->m_arm, gmem->m_numbytes, CDecoder::FFReleaseBuffer, gmem, AV_BUFFER_FLAG_READONLY); - if (!buf) - { - CLog::Log(LOGERROR, "%s::%s av_buffer_create() failed", CLASSNAME, __FUNCTION__); - YUVBuffer->Release(); - return -1; - } - - uint8_t *planes[YuvImage::MAX_PLANES]; - int strides[YuvImage::MAX_PLANES]; - YUVBuffer->GetPlanes(planes); - YUVBuffer->GetStrides(strides); - - for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) - { - frame->data[i] = i < YuvImage::MAX_PLANES ? planes[i] : nullptr; - frame->linesize[i] = i < YuvImage::MAX_PLANES ? strides[i] : 0; - frame->buf[i] = i == 0 ? buf : nullptr; - } - - frame->extended_data = frame->data; - // Leave extended buf alone - - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s buf:%p mmal:%p gmem:%p avbuf:%p:%p:%p", CLASSNAME, - __FUNCTION__, static_cast<void*>(YUVBuffer), static_cast<void*>(YUVBuffer->mmal_buffer), - static_cast<void*>(gmem), static_cast<void*>(frame->data[0]), - static_cast<void*>(frame->data[1]), static_cast<void*>(frame->data[2])); - - return 0; -} - - -bool CDecoder::Open(AVCodecContext *avctx, AVCodecContext* mainctx, enum AVPixelFormat fmt) -{ - CSingleLock lock(m_section); - - CLog::Log(LOGINFO, "%s::%s - fmt:%d", CLASSNAME, __FUNCTION__, fmt); - - CLog::Log(LOGDEBUG, "%s::%s MMAL - source requires %d references", CLASSNAME, __FUNCTION__, avctx->refs); - - avctx->get_buffer2 = CDecoder::FFGetBuffer; - mainctx->get_buffer2 = CDecoder::FFGetBuffer; - - m_avctx = mainctx; - m_fmt = fmt; - - /* Create dummy component with attached pool */ - m_pool = std::make_shared<CMMALPool>(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, false, MMAL_NUM_OUTPUT_BUFFERS, 0, MMAL_ENCODING_UNKNOWN, MMALStateFFDec); - if (!m_pool) - { - CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder output", CLASSNAME, __func__); - return false; - } - - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - pool->SetProcessInfo(&m_processInfo); - - std::list<EINTERLACEMETHOD> deintMethods; - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_AUTO); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_ADVANCED); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_BOB); - deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_MMAL_BOB_HALF); - m_processInfo.UpdateDeinterlacingMethods(deintMethods); - - return true; -} - -CDVDVideoCodec::VCReturn CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) -{ - CSingleLock lock(m_section); - - if (frame) - { - if ((frame->format != AV_PIX_FMT_YUV420P && frame->format != AV_PIX_FMT_YUV420P10 && frame->format != AV_PIX_FMT_YUV420P12 && frame->format != AV_PIX_FMT_YUV420P14 && frame->format != AV_PIX_FMT_YUV420P16 && - frame->format != AV_PIX_FMT_BGR0 && frame->format != AV_PIX_FMT_RGB565LE) || - frame->buf[1] != nullptr || frame->buf[0] == nullptr) - { - CLog::Log(LOGERROR, "%s::%s frame format invalid format:%d buf:%p,%p", CLASSNAME, __func__, - frame->format, static_cast<void*>(frame->buf[0]), - static_cast<void*>(frame->buf[1])); - return CDVDVideoCodec::VC_ERROR; - } - CVideoBuffer *old = m_renderBuffer; - if (m_renderBuffer) - m_renderBuffer->Release(); - - CGPUMEM *m_gmem = (CGPUMEM *)av_buffer_get_opaque(frame->buf[0]); - assert(m_gmem); - // need to flush ARM cache so GPU can see it - m_gmem->Flush(); - m_renderBuffer = static_cast<CMMALYUVBuffer*>(m_gmem->m_opaque); - assert(m_renderBuffer && m_renderBuffer->mmal_buffer); - if (m_renderBuffer) - { - m_renderBuffer->m_stills = m_hints.stills; - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - mmal:%p buf:%p old:%p gpu:%p %dx%d (%dx%d)", - CLASSNAME, __FUNCTION__, static_cast<void*>(m_renderBuffer->mmal_buffer), - static_cast<void*>(m_renderBuffer), static_cast<void*>(old), - static_cast<void*>(m_renderBuffer->GetMem()), m_renderBuffer->Width(), - m_renderBuffer->Height(), m_renderBuffer->AlignedWidth(), - m_renderBuffer->AlignedHeight()); - m_renderBuffer->Acquire(); - } - } - - CDVDVideoCodec::VCReturn status = Check(avctx); - if (status != CDVDVideoCodec::VC_NONE) - return status; - - if (frame) - return CDVDVideoCodec::VC_PICTURE; - else - return CDVDVideoCodec::VC_BUFFER; -} - -bool CDecoder::GetPicture(AVCodecContext* avctx, VideoPicture* picture) -{ - CSingleLock lock(m_section); - - bool ret = ((ICallbackHWAccel*)avctx->opaque)->GetPictureCommon(picture); - if (!ret || !m_renderBuffer) - return false; - - CVideoBuffer *old = picture->videoBuffer; - if (picture->videoBuffer) - picture->videoBuffer->Release(); - - picture->videoBuffer = m_renderBuffer; - CLog::Log( - LOGDEBUG, LOGVIDEO, "%s::%s - mmal:%p dts:%.3f pts:%.3f buf:%p old:%p gpu:%p %dx%d (%dx%d)", - CLASSNAME, __FUNCTION__, static_cast<void*>(m_renderBuffer->mmal_buffer), 1e-6 * picture->dts, - 1e-6 * picture->pts, static_cast<void*>(m_renderBuffer), static_cast<void*>(old), - static_cast<void*>(m_renderBuffer->GetMem()), m_renderBuffer->Width(), - m_renderBuffer->Height(), m_renderBuffer->AlignedWidth(), m_renderBuffer->AlignedHeight()); - picture->videoBuffer->Acquire(); - - return true; -} - -CDVDVideoCodec::VCReturn CDecoder::Check(AVCodecContext* avctx) -{ - CSingleLock lock(m_section); - return CDVDVideoCodec::VC_NONE; -} - -unsigned CDecoder::GetAllowedReferences() -{ - return 6; -} - -IHardwareDecoder* CDecoder::Create(CDVDStreamInfo &hint, CProcessInfo &processInfo, AVPixelFormat fmt) - { - return new CDecoder(processInfo, hint); - } - -void CDecoder::Register() -{ - CDVDFactoryCodec::RegisterHWAccel("mmalffmpeg", CDecoder::Create); -} diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h deleted file mode 100644 index 74106a770b..0000000000 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2016-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h" -#include "cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h" - -#include <memory> -#include <queue> - -#include <libavcodec/avcodec.h> - -struct MMAL_BUFFER_HEADER_T; -class CGPUMEM; - -namespace MMAL { - -class CDecoder; - -// a mmal video frame -class CMMALYUVBuffer : public CMMALBuffer -{ -public: - CMMALYUVBuffer(int id); - virtual ~CMMALYUVBuffer(); - uint8_t* GetMemPtr() override; - virtual void GetPlanes(uint8_t*(&planes)[YuvImage::MAX_PLANES]) override; - virtual void GetStrides(int(&strides)[YuvImage::MAX_PLANES]) override; - virtual void SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES]) override; - virtual void SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES], const int (&planeOffsets)[YuvImage::MAX_PLANES]) override; - CGPUMEM *Allocate(int size, void *opaque); - CGPUMEM *GetMem() { return m_gmem; } -protected: - CGPUMEM *m_gmem = nullptr; -}; - -class CDecoder - : public IHardwareDecoder -{ -public: - CDecoder(CProcessInfo& processInfo, CDVDStreamInfo &hints); - virtual ~CDecoder(); - virtual bool Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat) override; - virtual CDVDVideoCodec::VCReturn Decode(AVCodecContext* avctx, AVFrame* frame) override; - virtual bool GetPicture(AVCodecContext* avctx, VideoPicture* picture) override; - virtual CDVDVideoCodec::VCReturn Check(AVCodecContext* avctx) override; - virtual const std::string Name() override { return "mmal"; } - virtual unsigned GetAllowedReferences() override; - virtual long Release() override; - - static void AlignedSize(AVCodecContext *avctx, int &width, int &height); - static void FFReleaseBuffer(void *opaque, uint8_t *data); - static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags); - static IHardwareDecoder* Create(CDVDStreamInfo &hint, CProcessInfo &processInfo, AVPixelFormat fmt); - static void Register(); - -protected: - AVCodecContext *m_avctx; - CProcessInfo &m_processInfo; - CCriticalSection m_section; - std::shared_ptr<CMMALPool> m_pool; - enum AVPixelFormat m_fmt; - CDVDStreamInfo m_hints; - CMMALYUVBuffer *m_renderBuffer = nullptr; -}; - -}; diff --git a/xbmc/cores/VideoPlayer/Process/rbpi/CMakeLists.txt b/xbmc/cores/VideoPlayer/Process/rbpi/CMakeLists.txt deleted file mode 100644 index 1a41576405..0000000000 --- a/xbmc/cores/VideoPlayer/Process/rbpi/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - set(SOURCES ProcessInfoPi.cpp) - - set(HEADERS ProcessInfoPi.h) - - core_add_library(processPi) -endif() diff --git a/xbmc/cores/VideoPlayer/Process/rbpi/ProcessInfoPi.cpp b/xbmc/cores/VideoPlayer/Process/rbpi/ProcessInfoPi.cpp deleted file mode 100644 index 79ab42758c..0000000000 --- a/xbmc/cores/VideoPlayer/Process/rbpi/ProcessInfoPi.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "ProcessInfoPi.h" - -#include "cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h" - -#include "platform/linux/RBP.h" - -#include <interface/mmal/util/mmal_default_components.h> - -// Override for platform ports -using namespace MMAL; - -CProcessInfo* CProcessInfoPi::Create() -{ - return new CProcessInfoPi(); -} - -CProcessInfoPi::CProcessInfoPi() -{ - /* Create dummy component with attached pool */ - std::shared_ptr<IVideoBufferPool> pool = std::make_shared<CMMALPool>(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, false, MMAL_NUM_OUTPUT_BUFFERS, 0, MMAL_ENCODING_UNKNOWN, MMALStateFFDec); - m_videoBufferManager.RegisterPool(pool); -} - -void CProcessInfoPi::Register() -{ - CProcessInfo::RegisterProcessControl("rbpi", CProcessInfoPi::Create); -} - -EINTERLACEMETHOD CProcessInfoPi::GetFallbackDeintMethod() -{ - return EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE_HALF; -} - -bool CProcessInfoPi::AllowDTSHDDecode() -{ - if (g_RBP.RaspberryPiVersion() == 1) - return false; - return true; -} diff --git a/xbmc/cores/VideoPlayer/Process/rbpi/ProcessInfoPi.h b/xbmc/cores/VideoPlayer/Process/rbpi/ProcessInfoPi.h deleted file mode 100644 index 24334a43b0..0000000000 --- a/xbmc/cores/VideoPlayer/Process/rbpi/ProcessInfoPi.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "cores/IPlayer.h" -#include "cores/VideoPlayer/Process/ProcessInfo.h" - -namespace MMAL { - class CMMALYUVBuffer; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -class CVideoBufferManagerPi : public CVideoBufferManager -{ -public: - CVideoBufferManagerPi(); - void RegisterPool(std::shared_ptr<IVideoBufferPool> pool); - void ReleasePools(); - CVideoBuffer* Get(AVPixelFormat format, int width, int height); - CVideoBuffer* Get(AVPixelFormat format, int size); - void SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES]); - -protected: -}; - -class CProcessInfoPi : public CProcessInfo -{ -public: - CProcessInfoPi(); - static CProcessInfo* Create(); - static void Register(); - EINTERLACEMETHOD GetFallbackDeintMethod() override; - bool AllowDTSHDDecode() override; - -//protected: -}; diff --git a/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp b/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp index 74aea898c1..f93ca6c2cc 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp @@ -19,9 +19,6 @@ #include "utils/MathUtils.h" #include "cores/AudioEngine/Interfaces/AE.h" #include "cores/AudioEngine/Utils/AEUtil.h" -#ifdef TARGET_RASPBERRY_PI -#include "platform/linux/RBP.h" -#endif #include <sstream> #include <iomanip> diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt index 6184affccf..367c171720 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt @@ -32,11 +32,6 @@ if(CORE_SYSTEM_NAME STREQUAL darwin_embedded) list(APPEND HEADERS RendererVTBGLES.h) endif() -if(MMAL_FOUND) - list(APPEND SOURCES MMALRenderer.cpp) - list(APPEND HEADERS MMALRenderer.h) -endif() - if(CORE_SYSTEM_NAME STREQUAL android) list(APPEND SOURCES RendererMediaCodec.cpp RendererMediaCodecSurface.cpp) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp deleted file mode 100644 index 0c73642887..0000000000 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp +++ /dev/null @@ -1,1570 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include <interface/mmal/util/mmal_util.h> -#include <interface/mmal/util/mmal_default_components.h> -#include <interface/mmal/util/mmal_util_params.h> - -#include "Util.h" -#include "MMALRenderer.h" -#include "ServiceBroker.h" -#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h" -#include "filesystem/File.h" -#include "settings/DisplaySettings.h" -#include "settings/MediaSettings.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "threads/SingleLock.h" -#include "utils/log.h" -#include "utils/MathUtils.h" -#include "cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h" -#include "cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h" -#include "Application.h" -#include "platform/linux/RBP.h" -#include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" -#include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" - -extern "C" { -#include <libavutil/imgutils.h> -} - -#define VERBOSE 0 - -using namespace MMAL; - -#define CLASSNAME "CMMALBuffer" - -CMMALBuffer::CMMALBuffer(int id) : CVideoBuffer(id) -{ - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, static_cast<void*>(this)); -} - -CMMALBuffer::~CMMALBuffer() -{ - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, static_cast<void*>(this)); -} - -void CMMALBuffer::Unref() -{ - if (mmal_buffer) - { - mmal_buffer_header_release(mmal_buffer); - mmal_buffer = nullptr; - } -} - -void CMMALBuffer::Update() -{ - if (mmal_buffer) - { - CMMALYUVBuffer *yuv = dynamic_cast<CMMALYUVBuffer *>(this); - if (yuv) - { - int size = 0; - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - if (pool) - size = pool->Size(); - mmal_buffer->alloc_size = size; - mmal_buffer->length = size; - CGPUMEM *gmem = yuv->GetMem(); - if (gmem) - mmal_buffer->data = (uint8_t *)gmem->m_vc_handle; - } - } -} - -void CMMALBuffer::SetVideoDeintMethod(std::string method) -{ - std::shared_ptr<CMMALPool> pool = std::dynamic_pointer_cast<CMMALPool>(m_pool); - if (pool) - pool->SetVideoDeintMethod(method); -} - - -#undef CLASSNAME -#define CLASSNAME "CMMALPool" - - -void CMMALPool::Return(int id) -{ - CSingleLock lock(m_critSection); - - m_all[id]->Unref(); - auto it = m_used.begin(); - while (it != m_used.end()) - { - if (*it == id) - { - m_used.erase(it); - break; - } - else - ++it; - } - m_free.push_back(id); - Prime(); -} - -CMMALPool::CMMALPool(const char *component_name, bool input, uint32_t num_buffers, uint32_t buffer_size, uint32_t encoding, MMALState state) - : m_mmal_format(encoding), m_state(state), m_input(input) -{ - CSingleLock lock(m_critSection); - MMAL_STATUS_T status; - - status = mmal_component_create(component_name, &m_component); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to create component %s", CLASSNAME, __func__, component_name); - - MMAL_PORT_T *port = m_input ? m_component->input[0] : m_component->output[0]; - - // set up initial decoded frame format - may change from this - port->format->encoding = encoding; - - status = mmal_port_parameter_set_boolean(port, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, port->name, status, mmal_status_to_string(status)); - - status = mmal_port_format_commit(port); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to commit format for %s (status=%x %s)", CLASSNAME, __func__, port->name, status, mmal_status_to_string(status)); - - port->buffer_size = buffer_size; - port->buffer_num = std::max(num_buffers, port->buffer_num_recommended); - - m_mmal_pool = mmal_port_pool_create(port, port->buffer_num, port->buffer_size); - if (!m_mmal_pool) - CLog::Log(LOGERROR, "%s::%s Failed to create pool for port %s", CLASSNAME, __func__, port->name); - else - { - CLog::Log(LOGDEBUG, "%s::%s Created pool %p of size %d x %d for port %s", CLASSNAME, __func__, - static_cast<void*>(m_mmal_pool), num_buffers, buffer_size, port->name); - } -} - -CMMALPool::~CMMALPool() -{ - CSingleLock lock(m_critSection); - MMAL_STATUS_T status; - - MMAL_PORT_T *port = m_input ? m_component->input[0] : m_component->output[0]; - CLog::Log(LOGDEBUG, "%s::%s Destroying pool %p for port %s", CLASSNAME, __func__, - static_cast<void*>(m_mmal_pool), port->name); - - if (port && port->is_enabled) - { - status = mmal_port_disable(port); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to disable port %s (status=%x %s)", CLASSNAME, __func__, port->name, status, mmal_status_to_string(status)); - } - - if (m_component && m_component->is_enabled) - { - status = mmal_component_disable(m_component); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to disable component %s (status=%x %s)", CLASSNAME, __func__, m_component->name, status, mmal_status_to_string(status)); - } - - mmal_port_pool_destroy(port, m_mmal_pool); - - if (m_component) - mmal_component_destroy(m_component); - m_component = nullptr; - - m_mmal_pool = nullptr; - for (auto buf : m_all) - { - delete buf; - } -} - -std::vector<CMMALPool::MMALEncodingTable> CMMALPool::mmal_encoding_table = -{ - { AV_PIX_FMT_YUV420P, MMAL_ENCODING_I420 }, - { AV_PIX_FMT_YUVJ420P, MMAL_ENCODING_I420 }, - { AV_PIX_FMT_YUV420P10,MMAL_ENCODING_I420_16, }, - { AV_PIX_FMT_YUV420P12,MMAL_ENCODING_I420_16, }, - { AV_PIX_FMT_YUV420P14,MMAL_ENCODING_I420_16, }, - { AV_PIX_FMT_YUV420P16,MMAL_ENCODING_I420_16, }, - { AV_PIX_FMT_RGBA, MMAL_ENCODING_RGBA, }, - { AV_PIX_FMT_BGRA, MMAL_ENCODING_BGRA }, - { AV_PIX_FMT_RGB0, MMAL_ENCODING_RGBA }, - { AV_PIX_FMT_BGR0, MMAL_ENCODING_BGRA }, - { AV_PIX_FMT_RGB24, MMAL_ENCODING_RGB24 }, - { AV_PIX_FMT_BGR24, MMAL_ENCODING_BGR24 }, - { AV_PIX_FMT_RGB565, MMAL_ENCODING_RGB16 }, - { AV_PIX_FMT_RGB565LE, MMAL_ENCODING_RGB16 }, - { AV_PIX_FMT_BGR565, MMAL_ENCODING_BGR16 }, - { AV_PIX_FMT_NONE, MMAL_ENCODING_UNKNOWN }, -}; - - -uint32_t CMMALPool::TranslateFormat(AVPixelFormat pixfmt) -{ - for (const auto& entry : mmal_encoding_table) - { - if (entry.pixfmt == pixfmt) - return entry.encoding; - } - assert(0); - return MMAL_ENCODING_UNKNOWN; -} - -void CMMALPool::Configure(AVPixelFormat format, int width, int height, int alignedWidth, int alignedHeight, int size) -{ - CSingleLock lock(m_critSection); - if (format != AV_PIX_FMT_NONE) - m_mmal_format = TranslateFormat(format); - m_width = width; - m_height = height; - m_size = size; - m_software = true; - m_configured = true; - - if (m_mmal_format != MMAL_ENCODING_UNKNOWN) - { - m_geo = g_RBP.GetFrameGeometry(m_mmal_format, alignedWidth, alignedHeight); - if (m_mmal_format != MMAL_ENCODING_YUVUV128 && m_mmal_format != MMAL_ENCODING_YUVUV64_16 ) - { - if (alignedWidth) - { - m_geo.setStrideY(alignedWidth * m_geo.getBytesPerPixel()); - m_geo.setStrideC(alignedWidth * m_geo.getBytesPerPixel() >> 1); - } - if (alignedHeight) - { - m_geo.setHeightY(alignedHeight); - m_geo.setHeightC(alignedHeight >> 1); - } - } - } - if (m_size == 0) - m_size = m_geo.getSize(); - CLog::Log(LOGDEBUG, "%s::%s pool:%p %dx%d (%dx%d) pix:%d size:%d fmt:%.4s", CLASSNAME, __func__, - static_cast<void*>(m_mmal_pool), width, height, alignedWidth, alignedHeight, format, size, - (char*)&m_mmal_format); -} - -void CMMALPool::Configure(AVPixelFormat format, int size) -{ - Configure(format, 0, 0, 0, 0, size); -} - -void CMMALPool::SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES], const int (&planeOffsets)[YuvImage::MAX_PLANES]) -{ - assert(m_geo.getBytesPerPixel()); - int alignedWidth = strides[0] ? strides[0] / m_geo.getBytesPerPixel() : width; - int alignedHeight = planeOffsets[1] ? planeOffsets[1] / strides[0] : height; - Configure(AV_PIX_FMT_NONE, width, height, alignedWidth, alignedHeight, 0); - // libwv side-by-side UV format - if (planeOffsets[2] - planeOffsets[1] == strides[1] >> 1) - m_mmal_format = MMAL_ENCODING_I420_S; -} - -inline bool CMMALPool::IsConfigured() -{ - CSingleLock lock(m_critSection); - return m_configured; -} - -bool CMMALPool::IsCompatible(AVPixelFormat format, int size) -{ - CSingleLock lock(m_critSection); - uint32_t mmal_format = TranslateFormat(format); - if (m_mmal_format == MMAL_ENCODING_I420_S && mmal_format == MMAL_ENCODING_I420) - return true; - if (m_mmal_format == mmal_format && - m_size == size) - return true; - - return false; -} - -CVideoBuffer *CMMALPool::Get() -{ - return GetBuffer(500); -} - -CMMALBuffer *CMMALPool::GetBuffer(uint32_t timeout) -{ - MMAL_BUFFER_HEADER_T *buffer = nullptr; - CMMALBuffer *omvb = nullptr; - int id = -1; - bool newbuf = false; - CGPUMEM *gmem = nullptr; - - if (m_mmal_pool && m_mmal_pool->queue) - buffer = mmal_queue_timedwait(m_mmal_pool->queue, timeout); - CSingleLock lock(m_critSection); - if (buffer) - { - mmal_buffer_header_reset(buffer); - buffer->cmd = 0; - buffer->offset = 0; - buffer->flags = 0; - buffer->user_data = 0; - - if (!m_free.empty()) - { - id = m_free.front(); - m_free.pop_front(); - m_used.push_back(id); - omvb = m_all[id]; - } - else - { - newbuf = true; - id = m_all.size(); - if (!IsSoftware()) - { - CMMALVideoBuffer *vid = new CMMALVideoBuffer(id); - omvb = vid; - } - else - { - CMMALYUVBuffer *yuv = new CMMALYUVBuffer(id); - if (yuv) - { - assert(m_size > 0); - gmem = yuv->Allocate(m_size, (void *)yuv); - if (!gmem) - { - delete yuv; - yuv = nullptr; - } - } - omvb = yuv; - } - if (omvb) - { - m_all.push_back(omvb); - m_used.push_back(id); - } - } - if (omvb) - { - omvb->Acquire(GetPtr()); - omvb->m_rendered = false; - omvb->m_state = m_state; - buffer->user_data = omvb; - omvb->mmal_buffer = buffer; - omvb->Update(); - assert(omvb->Pool() == GetPtr()); - } - } - if (timeout > 0 && !omvb) - { - CLog::Log(LOGERROR, "%s::%s - failed pool:%p omvb:%p mmal:%p timeout:%d", CLASSNAME, - __FUNCTION__, static_cast<void*>(m_mmal_pool), static_cast<void*>(omvb), - static_cast<void*>(buffer), timeout); - } - else if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, - "%s::%s pool:%p omvb:%p mmal:%p gmem:%p new:%d id:%d to:%d %dx%d (%dx%d) size:%d " - "pool:%p:%p enc:%.4s", - CLASSNAME, __FUNCTION__, static_cast<void*>(m_mmal_pool), static_cast<void*>(omvb), - static_cast<void*>(buffer), static_cast<void*>(gmem), newbuf, id, timeout, m_width, - m_height, AlignedWidth(), AlignedHeight(), buffer ? buffer->alloc_size : 0, - omvb ? static_cast<void*>(omvb->Pool().get()) : nullptr, - static_cast<void*>(GetPtr().get()), (char*)&m_mmal_format); - } - return omvb; -} - -void CMMALPool::Prime() -{ - CSingleLock lock(m_critSection); - CMMALBuffer *omvb; - if (!m_mmal_pool || !m_component) - return; - MMAL_PORT_T *port = m_input ? m_component->input[0] : m_component->output[0]; - if (!port->is_enabled) - return; - while (omvb = GetBuffer(0), omvb) - { - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log( - LOGDEBUG, "%s::%s Send omvb:%p mmal:%p from pool %p to %s len:%d cmd:%x flags:%x pool:%p", - CLASSNAME, __func__, static_cast<void*>(omvb), static_cast<void*>(omvb->mmal_buffer), - static_cast<void*>(m_mmal_pool), port->name, omvb->mmal_buffer->length, - omvb->mmal_buffer->cmd, omvb->mmal_buffer->flags, static_cast<void*>(omvb->Pool().get())); - } - MMAL_STATUS_T status = mmal_port_send_buffer(port, omvb->mmal_buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log( - LOGERROR, "%s::%s - Failed to send omvb:%p mmal:%p from pool %p to %s (status=0%x %s)", - CLASSNAME, __func__, static_cast<void*>(omvb), static_cast<void*>(omvb->mmal_buffer), - static_cast<void*>(m_mmal_pool), port->name, status, mmal_status_to_string(status)); - } - } -} - -void CMMALPool::SetVideoDeintMethod(std::string method) -{ - CSingleLock lock(m_critSection); - if (m_processInfo) - m_processInfo->SetVideoDeintMethod(method); -} - -void CMMALPool::Released(CVideoBufferManager &videoBufferManager) -{ - /* Create dummy component with attached pool */ - std::shared_ptr<IVideoBufferPool> pool = std::make_shared<CMMALPool>(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, false, MMAL_NUM_OUTPUT_BUFFERS, 0, MMAL_ENCODING_UNKNOWN, MMALStateFFDec); - videoBufferManager.RegisterPool(pool); -} - -#undef CLASSNAME -#define CLASSNAME "CMMALRenderer" - -CRenderInfo CMMALRenderer::GetRenderInfo() -{ - CSingleLock lock(m_sharedSection); - CRenderInfo info; - - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s opaque:%p", CLASSNAME, __func__, static_cast<void*>(this)); - - info.max_buffer_size = NUM_BUFFERS; - info.optimal_buffer_size = NUM_BUFFERS; - info.opaque_pointer = (void *)this; - - return info; -} - -void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, "%s::%s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x", - CLASSNAME, __func__, static_cast<void*>(buffer->user_data), - static_cast<void*>(buffer), buffer->dts * 1e-6, buffer->pts * 1e-6, buffer->length, - buffer->cmd, buffer->flags); - } - buffer->length = 0; - mmal_queue_put(m_queue_process, buffer); -} - -static void vout_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CMMALRenderer *mmal = reinterpret_cast<CMMALRenderer*>(port->userdata); - mmal->vout_input_port_cb(port, buffer); -} - -bool CMMALRenderer::CheckConfigurationVout(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding) -{ - MMAL_STATUS_T status; - bool sizeChanged = width != m_vout_width || height != m_vout_height || aligned_width != m_vout_aligned_width || aligned_height != m_vout_aligned_height; - bool encodingChanged = !m_vout_input || !m_vout_input->format || encoding != m_vout_input->format->encoding; - - if (!m_vout) - { - /* Create video renderer */ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s CreateRenderer", CLASSNAME, __func__); - - status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout); - if(status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - m_vout_input = m_vout->input[0]; - - status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_NO_IMAGE_PADDING, MMAL_TRUE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable no image padding mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status)); - - status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status)); - - m_vout_input->format->type = MMAL_ES_TYPE_VIDEO; - if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) - m_vout_input->format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; - else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) - m_vout_input->format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; - else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) - m_vout_input->format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; - } - - if (m_vout_input && (sizeChanged || encodingChanged)) - { - assert(m_vout_input != nullptr && m_vout_input->format != nullptr && m_vout_input->format->es != nullptr); - CLog::Log(LOGDEBUG, "%s::%s Changing Vout dimensions from %dx%d (%dx%d) to %dx%d (%dx%d) %.4s", CLASSNAME, __func__, - m_vout_width, m_vout_height, m_vout_aligned_width, m_vout_aligned_height, width, height, aligned_width, aligned_height, (char *)&encoding); - - // we need to disable port when encoding changes, but not if just resolution changes - if (encodingChanged && m_vout_input->is_enabled) - { - status = mmal_port_disable(m_vout_input); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to disable vout input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - - m_vout_width = width; - m_vout_height = height; - m_vout_aligned_width = aligned_width; - m_vout_aligned_height = aligned_height; - - m_vout_input->format->es->video.crop.width = width; - m_vout_input->format->es->video.crop.height = height; - m_vout_input->format->es->video.width = aligned_width; - m_vout_input->format->es->video.height = aligned_height; - m_vout_input->format->encoding = encoding; - - status = mmal_port_format_commit(m_vout_input); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - if (!m_vout_input->is_enabled) - { - m_vout_input->buffer_num = MMAL_NUM_OUTPUT_BUFFERS; - m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; - m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; - - status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable vout input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - } - - if (m_vout && !m_vout->is_enabled) - { - status = mmal_component_enable(m_vout); - if(status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - if (!m_queue_render && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool("videoplayer.usedisplayasclock")) - { - m_queue_render = mmal_queue_create(); - CThread::Create(); - } - } - SetVideoRect(m_cachedSourceRect, m_cachedDestRect); - return true; -} - -CMMALRenderer::CMMALRenderer() : CThread("MMALRenderer"), m_processThread(this, "MMALProcess") -{ - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - m_vout = NULL; - m_vout_input = NULL; - memset(m_buffers, 0, sizeof m_buffers); - m_iFlags = 0; - m_bConfigured = false; - m_queue_render = nullptr; - m_error = 0.0; - m_fps = 0.0; - m_lastPts = DVD_NOPTS_VALUE; - m_frameInterval = 0.0; - m_frameIntervalDiff = 1e5; - m_vsync_count = ~0U; - m_vout_width = 0; - m_vout_height = 0; - m_vout_aligned_width = 0; - m_vout_aligned_height = 0; - m_deint = NULL; - m_deint_input = NULL; - m_deint_output = NULL; - m_deint_width = 0; - m_deint_height = 0; - m_deint_aligned_width = 0; - m_deint_aligned_height = 0; - m_cachedSourceRect.SetRect(0, 0, 0, 0); - m_cachedDestRect.SetRect(0, 0, 0, 0); - m_isPi1 = g_RBP.RaspberryPiVersion() == 1; - - m_queue_process = mmal_queue_create(); - m_processThread.Create(); -} - -CMMALRenderer::~CMMALRenderer() -{ - CSingleLock lock(m_sharedSection); - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - UnInit(); - - if (m_queue_process) - mmal_queue_put(m_queue_process, &m_quitpacket); - - { - // leave the lock to allow other threads to exit - CSingleExit unlock(m_sharedSection); - m_processThread.StopThread(); - } - - mmal_queue_destroy(m_queue_process); - m_queue_process = nullptr; -} - - -void CMMALRenderer::Process() -{ - bool bStop = false; - SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); - CLog::Log(LOGDEBUG, "%s::%s - starting", CLASSNAME, __func__); - while (!bStop) - { - double dfps = CServiceBroker::GetWinSystem()->GetGfxContext().GetFPS(); - double fps = 0.0; - double inc = 1.0; - g_RBP.WaitVsync(); - - CSingleLock lock(m_sharedSection); - // if good enough framerate measure then use it - if (dfps > 0.0 && m_frameInterval > 0.0 && m_frameIntervalDiff * 1e-6 < 1e-3) - { - fps = 1e6 / m_frameInterval; - inc = fps / dfps; - if (fabs(inc - 1.0) < 1e-2) - inc = 1.0; - else if (fabs(inc - 0.5) < 1e-2) - inc = 0.5; - else if (fabs(inc - 24.0/60.0) < 1e-2) - inc = 24.0/60.0; - if (m_deint) - inc *= 2.0; - } - // This algorithm is basically making the decision according to Bresenham's line algorithm. Imagine drawing a line where x-axis is display frames, and y-axis is video frames - m_error += inc; - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - debug vsync:%d queue:%d fps:%.2f/%.2f/%.2f inc:%f diff:%f", CLASSNAME, __func__, g_RBP.LastVsync(), mmal_queue_length(m_queue_render), fps, m_fps, dfps, inc, m_error); - // we may need to discard frames if queue length gets too high or video frame rate is above display frame rate - while (mmal_queue_length(m_queue_render) > 2 || (mmal_queue_length(m_queue_render) > 1 && m_error > 1.0)) - { - if (m_error > 1.0) - m_error -= 1.0; - MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_queue_render); - if (buffer == &m_quitpacket) - bStop = true; - else if (buffer) - { - CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data; - assert(buffer == omvb->mmal_buffer); - omvb->Release(); - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - discard omvb:%p mmal:%p vsync:%d queue:%d diff:%f", - CLASSNAME, __func__, static_cast<void*>(omvb), static_cast<void*>(buffer), - g_RBP.LastVsync(), mmal_queue_length(m_queue_render), m_error); - } - } - // this is case where we would like to display a new frame - if (m_error > 0.0) - { - m_error -= 1.0; - MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_queue_render); - if (buffer == &m_quitpacket) - bStop = true; - else if (buffer) - { - CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data; - assert(buffer == omvb->mmal_buffer); - CheckConfigurationVout(omvb->Width(), omvb->Height(), omvb->AlignedWidth(), omvb->AlignedHeight(), omvb->Encoding()); - MMAL_STATUS_T status = mmal_port_send_buffer(m_vout_input, buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s - Failed to send omvb:%p mmal:%p to %s (status=0%x %s)", - CLASSNAME, __func__, static_cast<void*>(omvb), static_cast<void*>(buffer), - m_vout_input->name, status, mmal_status_to_string(status)); - } - } - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - omvb:%p mmal:%p vsync:%d queue:%d diff:%f", CLASSNAME, - __func__, buffer ? static_cast<void*>(buffer->user_data) : nullptr, - static_cast<void*>(buffer), g_RBP.LastVsync(), mmal_queue_length(m_queue_render), - m_error); - } - } - CLog::Log(LOGDEBUG, "%s::%s - stopping", CLASSNAME, __func__); -} - -void CMMALRenderer::Run() -{ - CLog::Log(LOGDEBUG, "%s::%s - starting", CLASSNAME, __func__); - while (1) - { - MMAL_BUFFER_HEADER_T *buffer = mmal_queue_wait(m_queue_process); - assert(buffer); - if (buffer == &m_quitpacket) - break; - CSingleLock lock(m_sharedSection); - bool kept = false; - - CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data; - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, - "%s::%s %s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x enc:%.4s", - CLASSNAME, __func__, omvb ? omvb->GetStateName() : "", static_cast<void*>(omvb), - static_cast<void*>(buffer), buffer->dts * 1e-6, buffer->pts * 1e-6, buffer->length, - buffer->cmd, buffer->flags, omvb ? (char*)&omvb->Encoding() : ""); - } - - assert(omvb && buffer == omvb->mmal_buffer); - assert(buffer->cmd == 0); - assert(!(buffer->flags & (MMAL_BUFFER_HEADER_FLAG_EOS | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED))); - if (m_bConfigured) - switch (omvb->m_state) - { - case MMALStateHWDec: - case MMALStateFFDec: - { - if (buffer->length > 0) - { - int yuv16 = omvb->Encoding() == MMAL_ENCODING_I420_16 || omvb->Encoding() == MMAL_ENCODING_YUVUV64_16; - EINTERLACEMETHOD last_interlace_method = m_interlace_method; - EINTERLACEMETHOD interlace_method = m_videoSettings.m_InterlaceMethod; - if (interlace_method == VS_INTERLACEMETHOD_AUTO) - { - interlace_method = VS_INTERLACEMETHOD_MMAL_ADVANCED; - // avoid advanced deinterlace when using software decode and HD resolution - if ((omvb->m_state == MMALStateFFDec || m_isPi1) && omvb->Width() * omvb->Height() > 720*576) - interlace_method = VS_INTERLACEMETHOD_MMAL_BOB; - } - bool interlace = (omvb->mmal_buffer->flags & MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED) ? true:false; - - // advanced deinterlace requires 3 frames of context so disable when showing stills - if (omvb->m_stills) - { - if (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED) - interlace_method = VS_INTERLACEMETHOD_MMAL_BOB; - if (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF) - interlace_method = VS_INTERLACEMETHOD_MMAL_BOB_HALF; - } - - // we don't keep up when running at 60fps in the background so switch to half rate - if (!CServiceBroker::GetWinSystem()->GetGfxContext().IsFullScreenVideo()) - { - if (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED) - interlace_method = VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF; - if (interlace_method == VS_INTERLACEMETHOD_MMAL_BOB) - interlace_method = VS_INTERLACEMETHOD_MMAL_BOB_HALF; - } - - if (interlace_method == VS_INTERLACEMETHOD_NONE && !yuv16) - { - if (m_deint_input) - DestroyDeinterlace(); - } - - if (yuv16) - interlace_method = VS_INTERLACEMETHOD_NONE; - - if (yuv16 || (interlace_method != VS_INTERLACEMETHOD_NONE && (m_deint_input || interlace))) - CheckConfigurationDeint(omvb->Width(), omvb->Height(), omvb->AlignedWidth(), omvb->AlignedHeight(), omvb->Encoding(), interlace_method, omvb->BitsPerPixel()); - - if (!m_deint_input) - m_interlace_method = VS_INTERLACEMETHOD_NONE; - - if (last_interlace_method == m_interlace_method) - ; - else if (m_interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED) - omvb->SetVideoDeintMethod("adv(x2)"); - else if (m_interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF) - omvb->SetVideoDeintMethod("adv(x1)"); - else if (m_interlace_method == VS_INTERLACEMETHOD_MMAL_BOB) - omvb->SetVideoDeintMethod("bob(x2)"); - else if (m_interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF) - omvb->SetVideoDeintMethod("bob(x1)"); - else - omvb->SetVideoDeintMethod("none"); - - if (m_deint_input) - { - MMAL_STATUS_T status = mmal_port_send_buffer(m_deint_input, omvb->mmal_buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s - Failed to send omvb:%p mmal:%p to %s (status=0%x %s)", - CLASSNAME, __func__, static_cast<void*>(omvb), - static_cast<void*>(omvb->mmal_buffer), m_deint_input->name, status, - mmal_status_to_string(status)); - } - else - kept = true; - } - else if (m_queue_render) - { - mmal_queue_put(m_queue_render, omvb->mmal_buffer); - kept = true; - } - else - { - CheckConfigurationVout(omvb->Width(), omvb->Height(), omvb->AlignedWidth(), omvb->AlignedHeight(), omvb->Encoding()); - if (m_vout_input) - { - MMAL_STATUS_T status = mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s - Failed to send omvb:%p mmal:%p to %s (status=0%x %s)", - CLASSNAME, __func__, static_cast<void*>(omvb), - static_cast<void*>(omvb->mmal_buffer), m_vout_input->name, status, - mmal_status_to_string(status)); - } - else - kept = true; - } - } - } - break; - } - case MMALStateDeint: - { - if (buffer->length > 0) - { - if (m_queue_render) - { - mmal_queue_put(m_queue_render, buffer); - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s send %p to m_queue_render", CLASSNAME, __func__, static_cast<void*>(omvb)); - kept = true; - } - else - { - CheckConfigurationVout(omvb->Width(), omvb->Height(), omvb->AlignedWidth(), omvb->AlignedHeight(), omvb->Encoding()); - if (m_vout_input) - { - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s send %p to m_vout_input", CLASSNAME, __func__, static_cast<void*>(omvb)); - MMAL_STATUS_T status = mmal_port_send_buffer(m_vout_input, buffer); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s - Failed to send omvb:%p mmal%:p to %s (status=0%x %s)", - CLASSNAME, __func__, static_cast<void*>(omvb), static_cast<void*>(buffer), - m_vout_input->name, status, mmal_status_to_string(status)); - } - else - kept = true; - } - } - } - break; - } - default: assert(0); break; - } - if (!kept) - { - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log( - LOGDEBUG, - "%s::%s %s Not kept: omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x enc:%.4s", - CLASSNAME, __func__, omvb ? omvb->GetStateName() : "", static_cast<void*>(omvb), - static_cast<void*>(buffer), buffer->dts * 1e-6, buffer->pts * 1e-6, buffer->length, - buffer->cmd, buffer->flags, omvb ? (char*)&omvb->Encoding() : ""); - } - if (omvb) - omvb->Release(); - else - { - mmal_buffer_header_reset(buffer); - buffer->cmd = 0; - mmal_buffer_header_release(buffer); - } - } - } - CLog::Log(LOGDEBUG, "%s::%s - stopping", CLASSNAME, __func__); -} - -void CMMALRenderer::UpdateFramerateStats(double pts) -{ - double diff = 0.0; - if (m_lastPts != DVD_NOPTS_VALUE && pts != DVD_NOPTS_VALUE && pts - m_lastPts > 0.0 && pts - m_lastPts < DVD_SEC_TO_TIME(1./20.0)) - { - diff = pts - m_lastPts; - if (m_frameInterval == 0.0) - m_frameInterval = diff; - else if (diff > 0.0) - { - m_frameIntervalDiff = m_frameIntervalDiff * 0.9 + 0.1 * fabs(m_frameInterval - diff); - m_frameInterval = m_frameInterval * 0.9 + diff * 0.1; - } - } - if (pts != DVD_NOPTS_VALUE) - m_lastPts = pts; - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s pts:%.3f diff:%.3f m_frameInterval:%.6f m_frameIntervalDiff:%.6f", CLASSNAME, __func__, pts*1e-6, diff * 1e-6 , m_frameInterval * 1e-6, m_frameIntervalDiff *1e-6); -} - -void CMMALRenderer::AddVideoPicture(const VideoPicture& pic, int id) -{ - CMMALBuffer *buffer = dynamic_cast<CMMALBuffer*>(pic.videoBuffer); - assert(buffer); - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, "%s::%s MMAL - %p (%p) %i", CLASSNAME, __func__, static_cast<void*>(buffer), - static_cast<void*>(buffer->mmal_buffer), id); - } - - assert(!m_buffers[id]); - buffer->Acquire(); - m_buffers[id] = buffer; - UpdateFramerateStats(pic.pts); -} - -bool CMMALRenderer::Configure(const VideoPicture &picture, float fps, unsigned int orientation) -{ - CSingleLock lock(m_sharedSection); - ReleaseBuffers(); - - if (picture.videoBuffer) - m_format = picture.videoBuffer->GetFormat(); - m_sourceWidth = picture.iWidth; - m_sourceHeight = picture.iHeight; - m_renderOrientation = orientation; - - m_iFlags = GetFlagsChromaPosition(picture.chroma_position) | - GetFlagsColorPrimaries(picture.color_primaries) | - GetFlagsStereoMode(picture.stereoMode); - - m_fps = fps; - m_error = 0.0; - m_lastPts = DVD_NOPTS_VALUE; - m_frameInterval = 0.0; - m_frameIntervalDiff = 1e5; - - // cause SetVideoRect to trigger - needed after a hdmi mode change - m_src_rect.SetRect(0, 0, 0, 0); - m_dst_rect.SetRect(0, 0, 0, 0); - - CLog::Log(LOGDEBUG, "%s::%s - %dx%d->%dx%d@%.2f flags:%x format:%d orient:%d", CLASSNAME, __func__, picture.iWidth, picture.iHeight, picture.iDisplayWidth, picture.iDisplayHeight, fps, m_iFlags, m_format, orientation); - - // calculate the input frame aspect ratio - CalculateFrameAspectRatio(picture.iDisplayWidth, picture.iDisplayHeight); - SetViewMode(m_videoSettings.m_ViewMode); - ManageRenderArea(); - - m_bConfigured = true; - return true; -} - -void CMMALRenderer::ReleaseBuffer(int id) -{ - CSingleLock lock(m_sharedSection); - CMMALBuffer *omvb = m_buffers[id]; - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, "%s::%s - MMAL: source:%d omvb:%p mmal:%p", CLASSNAME, __func__, id, - static_cast<void*>(omvb), omvb ? static_cast<void*>(omvb->mmal_buffer) : nullptr); - } - if (m_buffers[id]) - m_buffers[id]->Release(); - m_buffers[id] = nullptr; -} - -bool CMMALRenderer::Flush(bool saveBuffers) -{ - CSingleLock lock(m_sharedSection); - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - if (m_vout_input) - mmal_port_flush(m_vout_input); - ReleaseBuffers(); - - return false; -} - -void CMMALRenderer::Update() -{ - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s", CLASSNAME, __func__); - if (!m_bConfigured) return; - ManageRenderArea(); -} - -void CMMALRenderer::RenderUpdate(int index, int index2, bool clear, unsigned int flags, unsigned int alpha) -{ - CSingleLock lock(m_sharedSection); - CMMALBuffer *omvb = nullptr; - - if (!m_bConfigured) - { - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s - not configured: clear:%d flags:%x alpha:%d source:%d", CLASSNAME, __func__, clear, flags, alpha, index); - goto exit; - } - - omvb = m_buffers[index]; - - if (CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoView() != RENDER_STEREO_VIEW_RIGHT) - { - ManageRenderArea(); - CRect view; - CBaseRenderer::GetVideoRect(m_cachedSourceRect, m_cachedDestRect, view); - } - - // we only want to upload frames once - if (omvb && omvb->m_rendered) - { - CLog::Log( - LOGDEBUG, LOGVIDEO, - "%s::%s - MMAL: clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p mflags:%x skipping", - CLASSNAME, __func__, clear, flags, alpha, index, static_cast<void*>(omvb), - static_cast<void*>(omvb->mmal_buffer), omvb->mmal_buffer->flags); - SetVideoRect(m_cachedSourceRect, m_cachedDestRect); - goto exit; - } - - if (omvb && omvb->m_state == MMALStateBypass) - { - // dummy buffer from omxplayer - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, "%s::%s - OMX: clear:%d flags:%x alpha:%d source:%d omvb:%p", CLASSNAME, - __func__, clear, flags, alpha, index, static_cast<void*>(omvb)); - } - } - else if (omvb && omvb->mmal_buffer) - { - if (flags & RENDER_FLAG_TOP) - omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED | MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST; - else if (flags & RENDER_FLAG_BOT) - omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED; - CLog::Log(LOGDEBUG, LOGVIDEO, - "%s::%s - MMAL: clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p mflags:%x " - "len:%d data:%p enc:%.4s", - CLASSNAME, __func__, clear, flags, alpha, index, static_cast<void*>(omvb), - static_cast<void*>(omvb->mmal_buffer), omvb->mmal_buffer->flags, - omvb->mmal_buffer->length, static_cast<void*>(omvb->mmal_buffer->data), - (char*)&omvb->Encoding()); - assert(omvb->mmal_buffer && omvb->mmal_buffer->data && omvb->mmal_buffer->length); - omvb->Acquire(); - omvb->m_rendered = true; - assert(omvb->mmal_buffer->user_data == omvb); - mmal_queue_put(m_queue_process, omvb->mmal_buffer); - } - else - { - CLog::Log( - LOGDEBUG, - "%s::%s - MMAL: No buffer to update clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p", - CLASSNAME, __func__, clear, flags, alpha, index, static_cast<void*>(omvb), - omvb ? static_cast<void*>(omvb->mmal_buffer) : nullptr); - } - -exit: - lock.Leave(); - uint32_t v = g_RBP.WaitVsync(m_vsync_count); - // allow a frame of slop - if (m_vsync_count == ~0U || !(v == m_vsync_count)) - { - CLog::Log(LOGDEBUG, "%s::%s - vsync %d (+%d)", CLASSNAME, __func__, m_vsync_count, v - m_vsync_count); - m_vsync_count = v + 1; - } - else - m_vsync_count++; -} - -void CMMALRenderer::ReleaseBuffers() -{ - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - for (int i=0; i<NUM_BUFFERS; i++) - ReleaseBuffer(i); -} - -void CMMALRenderer::UnInitMMAL() -{ - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); - - if (m_queue_render) - { - mmal_queue_put(m_queue_render, &m_quitpacket); - { - // leave the lock to allow other threads to exit - CSingleExit unlock(m_sharedSection); - StopThread(true); - } - mmal_queue_destroy(m_queue_render); - m_queue_render = nullptr; - } - - if (m_vout) - { - mmal_component_disable(m_vout); - } - - if (m_vout_input) - { - mmal_port_flush(m_vout_input); - mmal_port_disable(m_vout_input); - } - - ReleaseBuffers(); - - m_vout_input = NULL; - - if (m_vout) - { - mmal_component_release(m_vout); - m_vout = NULL; - } - - m_src_rect.SetRect(0, 0, 0, 0); - m_dst_rect.SetRect(0, 0, 0, 0); - m_video_stereo_mode = RENDER_STEREO_MODE_OFF; - m_display_stereo_mode = RENDER_STEREO_MODE_OFF; - m_StereoInvert = false; - m_vout_width = 0; - m_vout_height = 0; - m_vout_aligned_width = 0; - m_vout_aligned_height = 0; -} - -void CMMALRenderer::UnInit() -{ - CSingleLock lock(m_sharedSection); - m_bConfigured = false; - DestroyDeinterlace(); - UnInitMMAL(); -} - -bool CMMALRenderer::RenderCapture(CRenderCapture* capture) -{ - if (!m_bConfigured) - return false; - - CLog::Log(LOGDEBUG, "%s::%s - %p", CLASSNAME, __func__, static_cast<void*>(capture)); - - capture->BeginRender(); - capture->EndRender(); - - return true; -} - -//******************************************************************************************************** -// YV12 Texture creation, deletion, copying + clearing -//******************************************************************************************************** - -bool CMMALRenderer::Supports(ERENDERFEATURE feature) -{ - if (feature == RENDERFEATURE_STRETCH || - feature == RENDERFEATURE_ZOOM || - feature == RENDERFEATURE_ROTATION || - feature == RENDERFEATURE_VERTICAL_SHIFT || - feature == RENDERFEATURE_PIXEL_RATIO) - return true; - - return false; -} - -bool CMMALRenderer::Supports(ESCALINGMETHOD method) -{ - return false; -} - -void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect) -{ - CSingleLock lock(m_sharedSection); - - if (!m_vout_input) - return; - - CRect SrcRect = InSrcRect, DestRect = InDestRect; - RENDER_STEREO_MODE video_stereo_mode = (m_iFlags & CONF_FLAGS_STEREO_MODE_SBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL : - (m_iFlags & CONF_FLAGS_STEREO_MODE_TAB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL : RENDER_STEREO_MODE_OFF; - bool stereo_invert = (m_iFlags & CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) ? true : false; - RENDER_STEREO_MODE display_stereo_mode = CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode(); - - // ignore video stereo mode when 3D display mode is disabled - if (display_stereo_mode == RENDER_STEREO_MODE_OFF) - video_stereo_mode = RENDER_STEREO_MODE_OFF; - - // fix up transposed video - if (m_renderOrientation == 90 || m_renderOrientation == 270) - { - float newWidth, newHeight; - float aspectRatio = GetAspectRatio(); - // clamp width if too wide - if (DestRect.Height() > DestRect.Width()) - { - newWidth = DestRect.Width(); // clamp to the width of the old dest rect - newHeight = newWidth * aspectRatio; - } - else // else clamp to height - { - newHeight = DestRect.Height(); // clamp to the height of the old dest rect - newWidth = newHeight / aspectRatio; - } - - // calculate the center point of the view and offsets - float centerX = DestRect.x1 + DestRect.Width() * 0.5f; - float centerY = DestRect.y1 + DestRect.Height() * 0.5f; - float diffX = newWidth * 0.5f; - float diffY = newHeight * 0.5f; - - DestRect.x1 = centerX - diffX; - DestRect.x2 = centerX + diffX; - DestRect.y1 = centerY - diffY; - DestRect.y2 = centerY + diffY; - } - - // check if destination rect or video view mode has changed - if (!(m_dst_rect != DestRect) && !(m_src_rect != SrcRect) && m_video_stereo_mode == video_stereo_mode && m_display_stereo_mode == display_stereo_mode && m_StereoInvert == stereo_invert) - return; - - CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d (o:%d v:%d d:%d i:%d)", CLASSNAME, __func__, - (int)SrcRect.x1, (int)SrcRect.y1, (int)SrcRect.x2, (int)SrcRect.y2, - (int)DestRect.x1, (int)DestRect.y1, (int)DestRect.x2, (int)DestRect.y2, - m_renderOrientation, video_stereo_mode, display_stereo_mode, stereo_invert); - - m_src_rect = SrcRect; - m_dst_rect = DestRect; - m_video_stereo_mode = video_stereo_mode; - m_display_stereo_mode = display_stereo_mode; - m_StereoInvert = stereo_invert; - - // might need to scale up m_dst_rect to display size as video decodes - // to separate video plane that is at display size. - RESOLUTION res = CServiceBroker::GetWinSystem()->GetGfxContext().GetVideoResolution(); - CRect gui(0, 0, CDisplaySettings::GetInstance().GetResolutionInfo(res).iWidth, CDisplaySettings::GetInstance().GetResolutionInfo(res).iHeight); - CRect display(0, 0, CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::GetInstance().GetResolutionInfo(res).iScreenHeight); - - if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - { - float width = DestRect.x2 - DestRect.x1; - DestRect.x1 *= 2.0f; - DestRect.x2 = DestRect.x1 + 2.0f * width; - } - else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) - { - float height = DestRect.y2 - DestRect.y1; - DestRect.y1 *= 2.0f; - DestRect.y2 = DestRect.y1 + 2.0f * height; - } - - if (gui != display) - { - float xscale = display.Width() / gui.Width(); - float yscale = display.Height() / gui.Height(); - DestRect.x1 *= xscale; - DestRect.x2 *= xscale; - DestRect.y1 *= yscale; - DestRect.y2 *= yscale; - } - - MMAL_DISPLAYREGION_T region; - memset(®ion, 0, sizeof region); - - region.set = MMAL_DISPLAY_SET_DEST_RECT|MMAL_DISPLAY_SET_SRC_RECT|MMAL_DISPLAY_SET_FULLSCREEN|MMAL_DISPLAY_SET_NOASPECT|MMAL_DISPLAY_SET_MODE|MMAL_DISPLAY_SET_TRANSFORM; - region.dest_rect.x = lrintf(DestRect.x1); - region.dest_rect.y = lrintf(DestRect.y1); - region.dest_rect.width = lrintf(DestRect.Width()); - region.dest_rect.height = lrintf(DestRect.Height()); - - region.src_rect.x = lrintf(SrcRect.x1); - region.src_rect.y = lrintf(SrcRect.y1); - region.src_rect.width = lrintf(SrcRect.Width()); - region.src_rect.height = lrintf(SrcRect.Height()); - - region.fullscreen = MMAL_FALSE; - region.noaspect = MMAL_TRUE; - region.mode = MMAL_DISPLAY_MODE_LETTERBOX; - - if (m_renderOrientation == 90) - region.transform = MMAL_DISPLAY_ROT90; - else if (m_renderOrientation == 180) - region.transform = MMAL_DISPLAY_ROT180; - else if (m_renderOrientation == 270) - region.transform = MMAL_DISPLAY_ROT270; - else - region.transform = MMAL_DISPLAY_ROT0; - - if (m_video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) - region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_TB); - else if (m_video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_SBS); - else - region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_MONO); - - if (m_StereoInvert) - region.transform = (MMAL_DISPLAYTRANSFORM_T)(region.transform | DISPMANX_STEREOSCOPIC_INVERT); - - MMAL_STATUS_T status = mmal_util_set_display_region(m_vout_input, ®ion); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to set display region (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - - CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d t:%x", CLASSNAME, __func__, - region.src_rect.x, region.src_rect.y, region.src_rect.width, region.src_rect.height, - region.dest_rect.x, region.dest_rect.y, region.dest_rect.width, region.dest_rect.height, region.transform); -} - -void CMMALRenderer::deint_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, "%s::%s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x", - CLASSNAME, __func__, static_cast<void*>(buffer->user_data), - static_cast<void*>(buffer), buffer->dts * 1e-6, buffer->pts * 1e-6, buffer->length, - buffer->cmd, buffer->flags); - } - mmal_queue_put(m_queue_process, buffer); -} - -static void deint_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CMMALRenderer *mmal = reinterpret_cast<CMMALRenderer*>(port->userdata); - mmal->deint_input_port_cb(port, buffer); -} - -void CMMALRenderer::deint_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - if (VERBOSE && CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO)) - { - CLog::Log(LOGDEBUG, "%s::%s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x", - CLASSNAME, __func__, static_cast<void*>(buffer->user_data), - static_cast<void*>(buffer), buffer->dts * 1e-6, buffer->pts * 1e-6, buffer->length, - buffer->cmd, buffer->flags); - } - mmal_queue_put(m_queue_process, buffer); -} - -static void deint_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -{ - CMMALRenderer *mmal = reinterpret_cast<CMMALRenderer*>(port->userdata); - mmal->deint_output_port_cb(port, buffer); -} - -void CMMALRenderer::DestroyDeinterlace() -{ - MMAL_STATUS_T status; - - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s", CLASSNAME, __func__); - - // (lazily) destroy pool first so new buffers aren't allocated when flushing - m_deint_output_pool = nullptr; - - if (m_deint_input && m_deint_input->is_enabled) - { - status = mmal_port_disable(m_deint_input); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace input port(status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - } - m_deint_input = nullptr; - if (m_deint_output && m_deint_output->is_enabled) - { - status = mmal_port_disable(m_deint_output); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace output port(status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - } - m_deint_output = nullptr; - m_interlace_method = VS_INTERLACEMETHOD_MAX; - m_deint_width = 0; - m_deint_height = 0; - m_deint_aligned_width = 0; - m_deint_aligned_height = 0; - m_deint = nullptr; -} - -bool CMMALRenderer::CheckConfigurationDeint(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding, EINTERLACEMETHOD interlace_method, int bitsPerPixel) -{ - MMAL_STATUS_T status; - bool sizeChanged = width != m_deint_width || height != m_deint_height || aligned_width != m_deint_aligned_width || aligned_height != m_deint_aligned_height; - bool deinterlaceChanged = interlace_method != m_interlace_method; - bool encodingChanged = !m_deint_input || !m_deint_input->format || m_deint_input->format->encoding != encoding; - bool advanced_deinterlace = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF; - bool half_framerate = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF; - uint32_t output_encoding = advanced_deinterlace ? MMAL_ENCODING_YUVUV128 : MMAL_ENCODING_I420; - const char *component = interlace_method == VS_INTERLACEMETHOD_NONE ? "vc.ril.isp" : "vc.ril.image_fx"; - - if (!m_bConfigured) - { - CLog::Log(LOGDEBUG, "%s::%s Unconfigured", CLASSNAME, __func__); - return false; - } - - if (!m_deint) - { - CLog::Log(LOGDEBUG, LOGVIDEO, "%s::%s CreateDeinterlace", CLASSNAME, __func__); - - /* Create deinterlace component with attached pool */ - m_deint_output_pool = std::make_shared<CMMALPool>(component, false, 3, 0, output_encoding, MMALStateDeint); - if (!m_deint_output_pool) - { - CLog::Log(LOGERROR, "%s::%s Failed to create pool for deint output", CLASSNAME, __func__); - return false; - } - - m_deint = m_deint_output_pool->GetComponent(); - m_deint_output = m_deint->output[0]; - m_deint_input = m_deint->input[0]; - - status = mmal_port_parameter_set_boolean(m_deint_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_deint_input->name, status, mmal_status_to_string(status)); - } - - if (m_deint_input && (sizeChanged || deinterlaceChanged || encodingChanged)) - { - assert(m_deint_input != nullptr && m_deint_input->format != nullptr && m_deint_input->format->es != nullptr); - CLog::Log(LOGDEBUG, "%s::%s Changing Deint dimensions from %dx%d (%dx%d) to %dx%d (%dx%d) %.4s->%.4s mode %d->%d bpp:%d", CLASSNAME, __func__, - m_deint_input->format->es->video.crop.width, m_deint_input->format->es->video.crop.height, - m_deint_input->format->es->video.width, m_deint_input->format->es->video.height, width, height, aligned_width, aligned_height, - (char *)&m_deint_input->format->encoding, (char *)&encoding, m_interlace_method, interlace_method, bitsPerPixel); - - // we need to disable port when parameters change - if (m_deint_input && m_deint_input->is_enabled) - { - status = mmal_port_disable(m_deint_input); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to disable deint input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - } - - if (m_deint_output && (sizeChanged || deinterlaceChanged || encodingChanged)) - { - if (m_deint_output && m_deint_output->is_enabled) - { - status = mmal_port_disable(m_deint_output); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to disable deint output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - } - - if (m_deint_input && (sizeChanged || deinterlaceChanged || encodingChanged)) - { - m_deint_width = width; - m_deint_height = height; - m_deint_aligned_width = aligned_width; - m_deint_aligned_height = aligned_height; - - m_deint_input->format->es->video.crop.width = width; - m_deint_input->format->es->video.crop.height = height; - m_deint_input->format->es->video.width = aligned_width; - m_deint_input->format->es->video.height = aligned_height; - m_deint_input->format->encoding = encoding; - - status = mmal_port_format_commit(m_deint_input); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to commit deint input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - if (!m_deint_input->is_enabled) - { - m_deint_input->buffer_num = MMAL_NUM_OUTPUT_BUFFERS; - m_deint_input->buffer_size = m_deint_input->buffer_size_recommended; - m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; - - status = mmal_port_enable(m_deint_input, deint_input_port_cb_static); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable deint input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - } - - - if (m_deint_output && (sizeChanged || deinterlaceChanged || encodingChanged)) - { - if (interlace_method != VS_INTERLACEMETHOD_NONE) - { - MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, - advanced_deinterlace ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 4, {5, 0, half_framerate, 1 }}; - - status = mmal_port_parameter_set(m_deint_output, &imfx_param.hdr); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - // Image_fx assumed 3 frames of context. simple deinterlace doesn't require this - status = mmal_port_parameter_set_uint32(m_deint_input, MMAL_PARAMETER_EXTRA_BUFFERS, 6 - 5 + advanced_deinterlace ? 2:0); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_deint_input->name, status, mmal_status_to_string(status)); - } - else - { - // We need to scale the YUV to 16-bit - status = mmal_port_parameter_set_int32(m_deint_input, MMAL_PARAMETER_CCM_SHIFT, 16-bitsPerPixel-1); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to configure MMAL_PARAMETER_CCM_SHIFT on %s (status=%x %s)", CLASSNAME, __func__, m_deint_input->name, status, mmal_status_to_string(status)); - status = mmal_port_parameter_set_uint32(m_deint_output, MMAL_PARAMETER_OUTPUT_SHIFT, 1); - if (status != MMAL_SUCCESS) - CLog::Log(LOGERROR, "%s::%s Failed to configure MMAL_PARAMETER_OUTPUT_SHIFT on %s (status=%x %s)", CLASSNAME, __func__, m_deint_output->name, status, mmal_status_to_string(status)); - } - } - - if (m_deint_output && (sizeChanged || deinterlaceChanged || encodingChanged)) - { - m_deint_output->format->es->video.crop.width = width; - m_deint_output->format->es->video.crop.height = height; - m_deint_output->format->es->video.width = ALIGN_UP(width, 32); - m_deint_output->format->es->video.height = ALIGN_UP(height, 16); - m_deint_output->format->encoding = output_encoding; - - status = mmal_port_format_commit(m_deint_output); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - - if (!m_deint_output->is_enabled) - { - m_deint_output->buffer_num = 3; - m_deint_output->buffer_size = m_deint_output->buffer_size_recommended; - m_deint_output->userdata = (struct MMAL_PORT_USERDATA_T *)this; - - status = mmal_port_enable(m_deint_output, deint_output_port_cb_static); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable deint output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); - return false; - } - } - if (m_deint_output_pool) - m_deint_output_pool->Configure(AV_PIX_FMT_NONE, - m_deint_output->format->es->video.crop.width, m_deint_output->format->es->video.crop.height, - m_deint_output->format->es->video.width, m_deint_output->format->es->video.height, m_deint_output->buffer_size); - } - - if (m_deint && !m_deint->is_enabled) - { - status = mmal_component_enable(m_deint); - if (status != MMAL_SUCCESS) - { - CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); - return false; - } - } - m_interlace_method = interlace_method; - - // give buffers to deint - if (m_deint_output_pool) - m_deint_output_pool->Prime(); - return true; -} - -CBaseRenderer* CMMALRenderer::Create(CVideoBuffer *buffer) -{ - return new CMMALRenderer(); -} - -bool CMMALRenderer::Register() -{ - VIDEOPLAYER::CRendererFactory::RegisterRenderer("mmal", CMMALRenderer::Create); - return true; -} diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h deleted file mode 100644 index 4b77f90589..0000000000 --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "../BaseRenderer.h" -#include "../RenderCapture.h" -#include "../RenderFlags.h" -#include "cores/VideoPlayer/DVDStreamInfo.h" -#include "cores/VideoSettings.h" -#include "threads/IRunnable.h" -#include "threads/Thread.h" -#include "utils/Geometry.h" -#include "windowing/GraphicContext.h" - -#include <vector> - -#include <interface/mmal/mmal.h> - -// worst case number of buffers. 12 for decoder. 8 for multi-threading in ffmpeg. NUM_BUFFERS for renderer. -// Note, generally these won't necessarily result in allocated pictures -#define MMAL_NUM_OUTPUT_BUFFERS (12 + 8 + NUM_BUFFERS) - -struct VideoPicture; -class CProcessInfo; - -namespace MMAL { - -class CMMALBuffer; - -enum MMALState { MMALStateNone, MMALStateHWDec, MMALStateFFDec, MMALStateDeint, MMALStateBypass, }; - -class CMMALPool : public IVideoBufferPool -{ -public: - CMMALPool(const char *component_name, bool input, uint32_t num_buffers, uint32_t buffer_size, uint32_t encoding, MMALState state); - ~CMMALPool(); - - virtual CVideoBuffer* Get() override; - virtual void Return(int id) override; - virtual void Configure(AVPixelFormat format, int size) override; - virtual bool IsConfigured() override; - virtual bool IsCompatible(AVPixelFormat format, int size) override; - - void SetDimensions(int width, int height, const int (&strides)[YuvImage::MAX_PLANES], const int (&planeOffsets)[YuvImage::MAX_PLANES]); - MMAL_COMPONENT_T *GetComponent() { return m_component; } - CMMALBuffer *GetBuffer(uint32_t timeout); - void Prime(); - void SetProcessInfo(CProcessInfo *processInfo) { m_processInfo = processInfo; } - void Configure(AVPixelFormat format, int width, int height, int alignedWidth, int alignedHeight, int size); - bool IsSoftware() { return m_software; } - void SetVideoDeintMethod(std::string method); - static uint32_t TranslateFormat(AVPixelFormat pixfmt); - virtual int Width() { return m_width; } - virtual int Height() { return m_height; } - virtual int AlignedWidth() { return m_mmal_format == MMAL_ENCODING_YUVUV128 || m_mmal_format == MMAL_ENCODING_YUVUV64_16 || m_geo.getBytesPerPixel() == 0 ? 0 : m_geo.getStrideY() / m_geo.getBytesPerPixel(); } - virtual int AlignedHeight() { return m_mmal_format == MMAL_ENCODING_YUVUV128 || m_mmal_format == MMAL_ENCODING_YUVUV64_16 ? 0 : m_geo.getHeightY(); } - virtual int BitsPerPixel() { return m_geo.getBitsPerPixel(); } - virtual uint32_t &Encoding() { return m_mmal_format; } - virtual int Size() { return m_size; } - AVRpiZcFrameGeometry &GetGeometry() { return m_geo; } - virtual void Released(CVideoBufferManager &videoBufferManager); - -protected: - int m_width = 0; - int m_height = 0; - bool m_configured = false; - CCriticalSection m_critSection; - - std::vector<CMMALBuffer*> m_all; - std::deque<int> m_used; - std::deque<int> m_free; - - int m_size = 0; - uint32_t m_mmal_format = 0; - bool m_software = false; - CProcessInfo *m_processInfo = nullptr; - MMALState m_state; - bool m_input; - MMAL_POOL_T *m_mmal_pool; - MMAL_COMPONENT_T *m_component; - AVRpiZcFrameGeometry m_geo; - struct MMALEncodingTable - { - AVPixelFormat pixfmt; - uint32_t encoding; - }; - static std::vector<MMALEncodingTable> mmal_encoding_table; -}; - -// a generic mmal video frame. May be overridden as either software or hardware decoded buffer -class CMMALBuffer : public CVideoBuffer -{ -public: - CMMALBuffer(int id); - virtual ~CMMALBuffer(); - MMAL_BUFFER_HEADER_T *mmal_buffer = nullptr; - float m_aspect_ratio = 0.0f; - MMALState m_state = MMALStateNone; - bool m_rendered = false; - bool m_stills = false; - - virtual void Unref(); - virtual std::shared_ptr<CMMALPool> Pool() { return std::dynamic_pointer_cast<CMMALPool>(m_pool); }; - virtual int Width() { return Pool()->Width(); } - virtual int Height() { return Pool()->Height(); } - virtual int AlignedWidth() { return Pool()->AlignedWidth(); } - virtual int AlignedHeight() { return Pool()->AlignedHeight(); } - virtual uint32_t &Encoding() { return Pool()->Encoding(); } - virtual int BitsPerPixel() { return Pool()->BitsPerPixel(); } - virtual void Update(); - - void SetVideoDeintMethod(std::string method); - const char *GetStateName() { - static const char *names[] = { "MMALStateNone", "MMALStateHWDec", "MMALStateFFDec", "MMALStateDeint", "MMALStateBypass", }; - if ((size_t)m_state < vcos_countof(names)) - return names[(size_t)m_state]; - else - return "invalid"; - } -protected: -}; - - -class CMMALRenderer : public CBaseRenderer, public CThread, public IRunnable -{ -public: - CMMALRenderer(); - ~CMMALRenderer(); - - void Process(); - virtual void Update(); - - bool RenderCapture(CRenderCapture* capture); - - // Player functions - virtual bool Configure(const VideoPicture &picture, float fps, unsigned int orientation) override; - virtual void ReleaseBuffer(int idx) override; - virtual void UnInit(); - virtual bool Flush(bool saveBuffers) override; - virtual bool IsConfigured() override { return m_bConfigured; } - virtual void AddVideoPicture(const VideoPicture& pic, int index) override; - virtual bool IsPictureHW(const VideoPicture &picture) override { return false; }; - virtual CRenderInfo GetRenderInfo() override; - - virtual bool SupportsMultiPassRendering() override { return false; }; - virtual bool Supports(ERENDERFEATURE feature) override; - virtual bool Supports(ESCALINGMETHOD method) override; - - virtual void RenderUpdate(int index, int index2, bool clear, unsigned int flags, unsigned int alpha) override; - - virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); - virtual bool IsGuiLayer() override { return false; } - virtual bool ConfigChanged(const VideoPicture &picture) override { return false; } - - void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - void deint_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - void deint_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - - static CBaseRenderer* Create(CVideoBuffer *buffer); - static bool Register(); - -protected: - CMMALBuffer *m_buffers[NUM_BUFFERS]; - bool m_bConfigured; - unsigned int m_extended_format; - int m_neededBuffers; - - CRect m_cachedSourceRect; - CRect m_cachedDestRect; - CRect m_src_rect; - CRect m_dst_rect; - RENDER_STEREO_MODE m_video_stereo_mode; - RENDER_STEREO_MODE m_display_stereo_mode; - bool m_StereoInvert; - bool m_isPi1; - - CCriticalSection m_sharedSection; - MMAL_COMPONENT_T *m_vout; - MMAL_PORT_T *m_vout_input; - MMAL_QUEUE_T *m_queue_render; - MMAL_QUEUE_T *m_queue_process; - CThread m_processThread; - MMAL_BUFFER_HEADER_T m_quitpacket; - double m_error; - double m_lastPts; - double m_frameInterval; - double m_frameIntervalDiff; - uint32_t m_vout_width, m_vout_height, m_vout_aligned_width, m_vout_aligned_height; - // deinterlace - MMAL_COMPONENT_T *m_deint; - MMAL_PORT_T *m_deint_input; - MMAL_PORT_T *m_deint_output; - std::shared_ptr<CMMALPool> m_deint_output_pool; - MMAL_INTERLACETYPE_T m_interlace_mode; - EINTERLACEMETHOD m_interlace_method; - uint32_t m_deint_width, m_deint_height, m_deint_aligned_width, m_deint_aligned_height; - MMAL_FOURCC_T m_deinterlace_out_encoding; - void DestroyDeinterlace(); - bool CheckConfigurationDeint(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding, EINTERLACEMETHOD interlace_method, int bitsPerPixel); - - bool CheckConfigurationVout(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding); - uint32_t m_vsync_count; - void ReleaseBuffers(); - void UnInitMMAL(); - void UpdateFramerateStats(double pts); - virtual void Run() override; -}; - -}; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp index 395bd85bc9..7baa6f1f83 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp @@ -49,45 +49,7 @@ bool CRenderCaptureBase::UseOcclusionQuery() return true; } -#if defined(TARGET_RASPBERRY_PI) - -CRenderCaptureDispmanX::CRenderCaptureDispmanX() -{ - m_pixels = nullptr; -} - -CRenderCaptureDispmanX::~CRenderCaptureDispmanX() -{ - delete[] m_pixels; -} - -int CRenderCaptureDispmanX::GetCaptureFormat() -{ - return CAPTUREFORMAT_BGRA; -} - -void CRenderCaptureDispmanX::BeginRender() -{ -} - -void CRenderCaptureDispmanX::EndRender() -{ - delete[] m_pixels; - m_pixels = g_RBP.CaptureDisplay(m_width, m_height, NULL, true); - - SetState(CAPTURESTATE_DONE); -} - -void* CRenderCaptureDispmanX::GetRenderBuffer() -{ - return m_pixels; -} - -void CRenderCaptureDispmanX::ReadOut() -{ -} - -#elif defined(HAS_GL) || defined(HAS_GLES) +#if defined(HAS_GL) || defined(HAS_GLES) CRenderCaptureGL::CRenderCaptureGL() { diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.h index d371536116..cc1a969fe0 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.h @@ -100,33 +100,7 @@ class CRenderCaptureBase bool m_asyncChecked; }; -#if defined(TARGET_RASPBERRY_PI) -#include "platform/linux/RBP.h" - -class CRenderCaptureDispmanX : public CRenderCaptureBase -{ - public: - CRenderCaptureDispmanX(); - ~CRenderCaptureDispmanX(); - - int GetCaptureFormat(); - - void BeginRender(); - void EndRender(); - void ReadOut(); - - void* GetRenderBuffer(); -}; - -//used instead of typedef CRenderCaptureGL CRenderCapture -//since C++ doesn't allow you to forward declare a typedef -class CRenderCapture : public CRenderCaptureDispmanX -{ - public: - CRenderCapture() {}; -}; - -#elif defined(HAS_GL) || defined(HAS_GLES) +#if defined(HAS_GL) || defined(HAS_GLES) #include "system_gl.h" class CRenderCaptureGL : public CRenderCaptureBase diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h index b366b5d99e..ba5b21c112 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h @@ -29,7 +29,6 @@ class CRenderCapture; struct VideoPicture; class CWinRenderer; -class CMMALRenderer; class CLinuxRenderer; class CLinuxRendererGL; class CLinuxRendererGLES; diff --git a/xbmc/cores/VideoSettings.h b/xbmc/cores/VideoSettings.h index bedeb37dcd..bd9ac62f8e 100644 --- a/xbmc/cores/VideoSettings.h +++ b/xbmc/cores/VideoSettings.h @@ -30,10 +30,6 @@ enum EINTERLACEMETHOD VS_INTERLACEMETHOD_VAAPI_BOB = 22, VS_INTERLACEMETHOD_VAAPI_MADI = 23, VS_INTERLACEMETHOD_VAAPI_MACI = 24, - VS_INTERLACEMETHOD_MMAL_ADVANCED = 25, - VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF = 26, - VS_INTERLACEMETHOD_MMAL_BOB = 27, - VS_INTERLACEMETHOD_MMAL_BOB_HALF = 28, VS_INTERLACEMETHOD_DXVA_AUTO = 32, VS_INTERLACEMETHOD_MAX // do not use and keep as last enum value. }; diff --git a/xbmc/cores/omxplayer/CMakeLists.txt b/xbmc/cores/omxplayer/CMakeLists.txt deleted file mode 100644 index 038274bf71..0000000000 --- a/xbmc/cores/omxplayer/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(SOURCES OMXImage.cpp) - -set(HEADERS OMXImage.h) - -core_add_library(omxplayer) -target_compile_definitions(${CORE_LIBRARY} PRIVATE -D__STDC_FORMAT_MACROS) diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp deleted file mode 100644 index 1c1a258236..0000000000 --- a/xbmc/cores/omxplayer/OMXImage.cpp +++ /dev/null @@ -1,2340 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "OMXImage.h" - -#include "Application.h" -#include "ServiceBroker.h" -#include "URL.h" -#include "settings/AdvancedSettings.h" -#include "settings/DisplaySettings.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "utils/URIUtils.h" -#include "utils/log.h" -#include "windowing/GraphicContext.h" -#include "windowing/WinSystem.h" -#include "windowing/rpi/WinSystemRpiGLESContext.h" - -#include "platform/linux/RBP.h" - -#include <algorithm> -#include <cassert> -#include <inttypes.h> - -#include <sys/time.h> - -#ifdef _DEBUG -#define CheckError() { GLint result = eglGetError(); if (result != EGL_SUCCESS) CLog::Log(LOGERROR, "EGL error in %s: %x", __FUNCTION__, result); } -#else -#define CheckError() -#endif - -#define EXIF_TAG_ORIENTATION 0x0112 - - -// A helper for restricting threads calling GPU functions to limit memory use -// Experimentally, 3 outstanding operations is optimal -static XbmcThreads::ConditionVariable g_count_cond; -static CCriticalSection g_count_lock; -static int g_count_val; - -static void limit_calls_enter() -{ - CSingleLock lock(g_count_lock); - while (g_count_val >= 3) - g_count_cond.wait(lock); - g_count_val++; -} - -static void limit_calls_leave() -{ - CSingleLock lock(g_count_lock); - g_count_val--; - g_count_cond.notifyAll(); -} - - -#ifdef CLASSNAME -#undef CLASSNAME -#endif -#define CLASSNAME "COMXImage" - -using namespace XFILE; - -COMXImage::COMXImage() -: CThread("CRBPWorker") -{ - m_egl_context = EGL_NO_CONTEXT; -} - -COMXImage::~COMXImage() -{ - Deinitialize(); -} - -void COMXImage::Initialize() -{ - Create(); -} - -void COMXImage::Deinitialize() -{ - // wake up thread so it can quit - { - CSingleLock lock(m_texqueue_lock); - m_bStop = true; - m_texqueue_cond.notifyAll(); - } - if (IsRunning()) - StopThread(); -} - -bool COMXImage::CreateThumbnailFromSurface(unsigned char* buffer, unsigned int width, unsigned int height, - unsigned int format, unsigned int pitch, const std::string& destFile) -{ - COMXImageEnc omxImageEnc; - bool ret = omxImageEnc.CreateThumbnailFromSurface(buffer, width, height, format, pitch, destFile); - if (!ret) - CLog::Log(LOGINFO, "%s: unable to create thumbnail %s %dx%d", __func__, destFile.c_str(), width, - height); - return ret; -} - -COMXImageFile *COMXImage::LoadJpeg(const std::string& texturePath) -{ - COMXImageFile *file = new COMXImageFile(); - if (!file->ReadFile(texturePath)) - { - CLog::Log(LOGINFO, "%s: unable to load %s", __func__, CURL::GetRedacted(texturePath).c_str()); - delete file; - file = NULL; - } - return file; -} - -void COMXImage::CloseJpeg(COMXImageFile *file) -{ - delete file; -} - -bool COMXImage::DecodeJpeg(COMXImageFile *file, unsigned int width, unsigned int height, unsigned int stride, void *pixels) -{ - bool ret = false; - COMXImageDec omx_image; - if (omx_image.Decode(file->GetImageBuffer(), file->GetImageSize(), width, height, stride, pixels)) - { - assert(width == omx_image.GetDecodedWidth()); - assert(height == omx_image.GetDecodedHeight()); - assert(stride == omx_image.GetDecodedStride()); - ret = true; - } - else - CLog::Log(LOGINFO, "%s: unable to decode %s %dx%d", __func__, file->GetFilename(), width, - height); - omx_image.Close(); - return ret; -} - -bool COMXImage::ClampLimits(unsigned int &width, unsigned int &height, unsigned int m_width, unsigned int m_height, bool transposed) -{ - RESOLUTION_INFO& res_info = CDisplaySettings::GetInstance().GetResolutionInfo(CServiceBroker::GetWinSystem()->GetGfxContext().GetVideoResolution()); - unsigned int max_width = width; - unsigned int max_height = height; - const unsigned int gui_width = transposed ? res_info.iHeight:res_info.iWidth; - const unsigned int gui_height = transposed ? res_info.iWidth:res_info.iHeight; - const float aspect = (float)m_width / m_height; - bool clamped = false; - - if (max_width == 0 || max_height == 0) - { - const std::shared_ptr<CAdvancedSettings> advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings(); - - max_height = advancedSettings->m_imageRes; - - if (advancedSettings->m_fanartRes > advancedSettings->m_imageRes) - { // 16x9 images larger than the fanart res use that rather than the image res - if (fabsf(aspect / (16.0f/9.0f) - 1.0f) <= 0.01f && m_height >= advancedSettings->m_fanartRes) - { - max_height = advancedSettings->m_fanartRes; - } - } - max_width = max_height * 16/9; - } - - if (gui_width) - max_width = std::min(max_width, gui_width); - if (gui_height) - max_height = std::min(max_height, gui_height); - - max_width = std::min(max_width, 2048U); - max_height = std::min(max_height, 2048U); - - width = m_width; - height = m_height; - if (width > max_width || height > max_height) - { - if ((unsigned int)(max_width / aspect + 0.5f) > max_height) - max_width = (unsigned int)(max_height * aspect + 0.5f); - else - max_height = (unsigned int)(max_width / aspect + 0.5f); - width = max_width; - height = max_height; - clamped = true; - } - - return clamped; -} - -bool COMXImage::CreateThumb(const std::string& srcFile, unsigned int maxHeight, unsigned int maxWidth, std::string &additional_info, const std::string& destFile) -{ - bool okay = false; - COMXImageFile file; - COMXImageReEnc reenc; - void *pDestBuffer; - unsigned int nDestSize; - int orientation = additional_info == "flipped" ? 1:0; - if (URIUtils::HasExtension(srcFile, ".jpg|.tbn") && file.ReadFile(srcFile, orientation) && reenc.ReEncode(file, maxWidth, maxHeight, pDestBuffer, nDestSize)) - { - XFILE::CFile outfile; - if (outfile.OpenForWrite(destFile, true)) - { - outfile.Write(pDestBuffer, nDestSize); - outfile.Close(); - okay = true; - } - else - CLog::Log(LOGERROR, "%s: can't open output file: %s", __func__, destFile.c_str()); - } - return okay; -} - -bool COMXImage::SendMessage(bool (*callback)(EGLDisplay egl_display, EGLContext egl_context, void *cookie), void *cookie) -{ - // we can only call gl functions from the application thread or texture thread - if ( g_application.IsCurrentThread() ) - { - CWinSystemRpiGLESContext *winsystem = static_cast<CWinSystemRpiGLESContext *>(CServiceBroker::GetWinSystem()); - return callback(winsystem->GetEGLDisplay(), GetEGLContext(), cookie); - } - struct callbackinfo mess; - mess.callback = callback; - mess.cookie = cookie; - mess.result = false; - mess.sync.Reset(); - { - CSingleLock lock(m_texqueue_lock); - m_texqueue.push(&mess); - m_texqueue_cond.notifyAll(); - } - // wait for function to have finished (in texture thread) - mess.sync.Wait(); - // 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; -} - - -static bool AllocTextureCallback(EGLDisplay egl_display, EGLContext egl_context, void *cookie) -{ - struct COMXImage::textureinfo *tex = static_cast<struct COMXImage::textureinfo *>(cookie); - COMXImage *img = static_cast<COMXImage*>(tex->parent); - return img->AllocTextureInternal(egl_display, egl_context, tex); -} - -bool COMXImage::AllocTextureInternal(EGLDisplay egl_display, EGLContext egl_context, struct textureinfo *tex) -{ - glGenTextures(1, (GLuint*) &tex->texture); - glBindTexture(GL_TEXTURE_2D, tex->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - GLenum type = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool("videoscreen.textures32") ? GL_UNSIGNED_BYTE:GL_UNSIGNED_SHORT_5_6_5; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex->width, tex->height, 0, GL_RGB, type, 0); - tex->egl_image = eglCreateImageKHR(egl_display, egl_context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)tex->texture, NULL); - if (!tex->egl_image) - CLog::Log(LOGDEBUG, "%s: eglCreateImageKHR failed to allocate", __func__); - CheckError(); - return true; -} - -void COMXImage::GetTexture(void *userdata, GLuint *texture) -{ - struct textureinfo *tex = static_cast<struct textureinfo *>(userdata); - *texture = tex->texture; -} - -static bool DestroyTextureCallback(EGLDisplay egl_display, EGLContext egl_context, void *cookie) -{ - struct COMXImage::textureinfo *tex = static_cast<struct COMXImage::textureinfo *>(cookie); - COMXImage *img = static_cast<COMXImage*>(tex->parent); - return img->DestroyTextureInternal(egl_display, egl_context, tex); -} - -void COMXImage::DestroyTexture(void *userdata) -{ - SendMessage(DestroyTextureCallback, userdata); -} - -bool COMXImage::DestroyTextureInternal(EGLDisplay egl_display, EGLContext egl_context, struct textureinfo *tex) -{ - bool s = true; - if (tex->egl_image) - { - s = eglDestroyImageKHR(egl_display, tex->egl_image); - if (!s) - CLog::Log(LOGINFO, "%s: failed to destroy texture", __func__); - } - if (tex->texture) - glDeleteTextures(1, (GLuint*) &tex->texture); - return s; -} - -bool COMXImage::DecodeJpegToTexture(COMXImageFile *file, unsigned int width, unsigned int height, void **userdata) -{ - bool ret = false; - COMXTexture omx_image; - - struct textureinfo *tex = new struct textureinfo; - if (!tex) - return NULL; - - tex->parent = (void *)this; - tex->width = width; - tex->height = height; - tex->texture = 0; - tex->egl_image = NULL; - - SendMessage(AllocTextureCallback, tex); - - if (tex->egl_image && tex->texture && omx_image.Decode(file->GetImageBuffer(), file->GetImageSize(), width, height, tex->egl_image)) - { - ret = true; - *userdata = tex; - CLog::Log(LOGDEBUG, "%s: decoded %s %dx%d", __func__, file->GetFilename(), width, height); - } - else - { - CLog::Log(LOGINFO, "%s: unable to decode to texture %s %dx%d", __func__, file->GetFilename(), - width, height); - DestroyTexture(tex); - } - return ret; -} - -EGLContext COMXImage::GetEGLContext() -{ - CSingleLock lock(m_texqueue_lock); - CWinSystemRpiGLESContext *winsystem = static_cast<CWinSystemRpiGLESContext *>(CServiceBroker::GetWinSystem()); - if (g_application.IsCurrentThread()) - return winsystem->GetEGLContext(); - if (m_egl_context == EGL_NO_CONTEXT) - CreateContext(); - return m_egl_context; -} - -static bool ChooseConfig(EGLDisplay display, const EGLint *configAttrs, EGLConfig *config) -{ - EGLBoolean eglStatus = true; - EGLint configCount = 0; - EGLConfig* configList = NULL; - // Find out how many configurations suit our needs - eglStatus = eglChooseConfig(display, configAttrs, NULL, 0, &configCount); - CheckError(); - - if (!eglStatus || !configCount) - { - CLog::Log(LOGERROR, "EGL failed to return any matching configurations: %i", configCount); - return false; - } - - // Allocate room for the list of matching configurations - configList = (EGLConfig*)malloc(configCount * sizeof(EGLConfig)); - if (!configList) - { - CLog::Log(LOGERROR, "EGL failure obtaining configuration list"); - return false; - } - - // Obtain the configuration list from EGL - eglStatus = eglChooseConfig(display, configAttrs, configList, configCount, &configCount); - CheckError(); - if (!eglStatus || !configCount) - { - CLog::Log(LOGERROR, "EGL failed to populate configuration list: %d", eglStatus); - return false; - } - - // Select an EGL configuration that matches the native window - *config = configList[0]; - - free(configList); - return true; -} - -void COMXImage::CreateContext() -{ - EGLConfig egl_config; - CWinSystemRpiGLESContext *winsystem = static_cast<CWinSystemRpiGLESContext *>(CServiceBroker::GetWinSystem()); - EGLDisplay egl_display = winsystem->GetEGLDisplay(); - - eglInitialize(egl_display, NULL, NULL); - CheckError(); - eglBindAPI(EGL_OPENGL_ES_API); - CheckError(); - static const EGLint contextAttrs [] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - static const EGLint configAttrs [] = { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_STENCIL_SIZE, 0, - EGL_SAMPLE_BUFFERS, 0, - EGL_SAMPLES, 0, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - bool s = ChooseConfig(egl_display, configAttrs, &egl_config); - CheckError(); - if (!s) - { - CLog::Log(LOGERROR, "%s: Could not find a compatible configuration",__FUNCTION__); - return; - } - m_egl_context = eglCreateContext(egl_display, egl_config, winsystem->GetEGLContext(), contextAttrs); - CheckError(); - if (m_egl_context == EGL_NO_CONTEXT) - { - CLog::Log(LOGERROR, "%s: Could not create a context",__FUNCTION__); - return; - } - EGLSurface egl_surface = eglCreatePbufferSurface(egl_display, egl_config, NULL); - CheckError(); - if (egl_surface == EGL_NO_SURFACE) - { - CLog::Log(LOGERROR, "%s: Could not create a surface",__FUNCTION__); - return; - } - s = eglMakeCurrent(egl_display, egl_surface, egl_surface, m_egl_context); - CheckError(); - if (!s) - { - CLog::Log(LOGERROR, "%s: Could not make current",__FUNCTION__); - return; - } -} - -void COMXImage::Process() -{ - while(!m_bStop) - { - CSingleLock lock(m_texqueue_lock); - if (m_texqueue.empty()) - { - m_texqueue_cond.wait(lock); - } - else - { - struct callbackinfo *mess = m_texqueue.front(); - m_texqueue.pop(); - lock.Leave(); - - CWinSystemRpiGLESContext *winsystem = static_cast<CWinSystemRpiGLESContext *>(CServiceBroker::GetWinSystem()); - mess->result = mess->callback(winsystem->GetEGLDisplay(), GetEGLContext(), mess->cookie); - { - CSingleLock lock(m_texqueue_lock); - mess->sync.Set(); - } - } - } -} - -void COMXImage::OnStartup() -{ -} - -void COMXImage::OnExit() -{ -} - -#ifdef CLASSNAME -#undef CLASSNAME -#endif -#define CLASSNAME "COMXImageFile" - -COMXImageFile::COMXImageFile() -{ - m_image_size = 0; - m_image_buffer = NULL; - m_orientation = 0; - m_width = 0; - m_height = 0; -} - -COMXImageFile::~COMXImageFile() -{ - if(m_image_buffer) - free(m_image_buffer); -} - -typedef enum { /* JPEG marker codes */ - M_SOF0 = 0xc0, - M_SOF1 = 0xc1, - M_SOF2 = 0xc2, - M_SOF3 = 0xc3, - M_SOF5 = 0xc5, - M_SOF6 = 0xc6, - M_SOF7 = 0xc7, - M_JPG = 0xc8, - M_SOF9 = 0xc9, - M_SOF10 = 0xca, - M_SOF11 = 0xcb, - M_SOF13 = 0xcd, - M_SOF14 = 0xce, - M_SOF15 = 0xcf, - - M_DHT = 0xc4, - M_DAC = 0xcc, - - M_RST0 = 0xd0, - M_RST1 = 0xd1, - M_RST2 = 0xd2, - M_RST3 = 0xd3, - M_RST4 = 0xd4, - M_RST5 = 0xd5, - M_RST6 = 0xd6, - M_RST7 = 0xd7, - - M_SOI = 0xd8, - M_EOI = 0xd9, - M_SOS = 0xda, - M_DQT = 0xdb, - M_DNL = 0xdc, - M_DRI = 0xdd, - M_DHP = 0xde, - M_EXP = 0xdf, - - M_APP0 = 0xe0, - M_APP1 = 0xe1, - M_APP2 = 0xe2, - M_APP3 = 0xe3, - M_APP4 = 0xe4, - M_APP5 = 0xe5, - M_APP6 = 0xe6, - M_APP7 = 0xe7, - M_APP8 = 0xe8, - M_APP9 = 0xe9, - M_APP10 = 0xea, - M_APP11 = 0xeb, - M_APP12 = 0xec, - M_APP13 = 0xed, - M_APP14 = 0xee, - M_APP15 = 0xef, - // extensions - M_JPG0 = 0xf0, - M_JPG1 = 0xf1, - M_JPG2 = 0xf2, - M_JPG3 = 0xf3, - M_JPG4 = 0xf4, - M_JPG5 = 0xf5, - M_JPG6 = 0xf6, - M_JPG7 = 0xf7, - M_JPG8 = 0xf8, - M_JPG9 = 0xf9, - M_JPG10 = 0xfa, - M_JPG11 = 0xfb, - M_JPG12 = 0xfc, - M_JPG13 = 0xfd, - M_JPG14 = 0xfe, - M_COM = 0xff, - - M_TEM = 0x01, -} JPEG_MARKER; - -static uint8_t inline READ8(uint8_t * &p) -{ - uint8_t r = p[0]; - p += 1; - return r; -} - -static uint16_t inline READ16(uint8_t * &p) -{ - uint16_t r = (p[0] << 8) | p[1]; - p += 2; - return r; -} - -static uint32_t inline READ32(uint8_t * &p) -{ - uint32_t r = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - p += 4; - return r; -} - -static void inline SKIPN(uint8_t * &p, unsigned int n) -{ - p += n; -} - -OMX_IMAGE_CODINGTYPE COMXImageFile::GetCodingType(unsigned int &width, unsigned int &height, int orientation) -{ - OMX_IMAGE_CODINGTYPE eCompressionFormat = OMX_IMAGE_CodingMax; - bool progressive = false; - int components = 0; - m_orientation = 0; - - if(!m_image_size) - { - CLog::Log(LOGERROR, "%s::%s %s m_image_size unexpected (%lu)", CLASSNAME, __func__, - GetFilename(), m_image_size); - return OMX_IMAGE_CodingMax; - } - - uint8_t *p = m_image_buffer; - uint8_t *q = m_image_buffer + m_image_size; - - /* JPEG Header */ - if(READ16(p) == 0xFFD8) - { - eCompressionFormat = OMX_IMAGE_CodingJPEG; - - READ8(p); - unsigned char marker = READ8(p); - unsigned short block_size = 0; - bool nMarker = false; - - while(p < q && !progressive) - { - switch(marker) - { - case M_DQT: - case M_DNL: - case M_DHP: - case M_EXP: - - case M_DHT: - - case M_SOF0: - case M_SOF1: - case M_SOF2: - case M_SOF3: - - case M_SOF5: - case M_SOF6: - case M_SOF7: - - case M_JPG: - case M_SOF9: - case M_SOF10: - case M_SOF11: - - case M_SOF13: - case M_SOF14: - case M_SOF15: - - case M_APP0: - case M_APP1: - case M_APP2: - case M_APP3: - case M_APP4: - case M_APP5: - case M_APP6: - case M_APP7: - case M_APP8: - case M_APP9: - case M_APP10: - case M_APP11: - case M_APP12: - case M_APP13: - case M_APP14: - case M_APP15: - - case M_JPG0: - case M_JPG1: - case M_JPG2: - case M_JPG3: - case M_JPG4: - case M_JPG5: - case M_JPG6: - case M_JPG7: - case M_JPG8: - case M_JPG9: - case M_JPG10: - case M_JPG11: - case M_JPG12: - case M_JPG13: - case M_JPG14: - case M_COM: - block_size = READ16(p); - nMarker = true; - break; - - case M_SOS: - default: - nMarker = false; - break; - } - - if(!nMarker) - { - break; - } - - if(marker >= M_SOF0 && marker <= M_SOF15 && marker != M_DHT && marker != M_DAC) - { - if(marker == M_SOF2 || marker == M_SOF6 || marker == M_SOF10 || marker == M_SOF14) - { - progressive = true; - } - int readBits = 2; - SKIPN(p, 1); - readBits ++; - height = READ16(p); - readBits += 2; - width = READ16(p); - readBits += 2; - components = READ8(p); - readBits += 1; - SKIPN(p, 1 * (block_size - readBits)); - } - else if(marker == M_APP1) - { - int readBits = 2; - - // Exif header - if(READ32(p) == 0x45786966) - { - bool bMotorola = false; - bool bError = false; - SKIPN(p, 1 * 2); - readBits += 2; - - char o1 = READ8(p); - char o2 = READ8(p); - readBits += 2; - - /* Discover byte order */ - if(o1 == 'M' && o2 == 'M') - bMotorola = true; - else if(o1 == 'I' && o2 == 'I') - bMotorola = false; - else - bError = true; - - SKIPN(p, 1 * 2); - readBits += 2; - - if(!bError) - { - unsigned int offset, a, b, numberOfTags, tagNumber; - - // Get first IFD offset (offset to IFD0) - if(bMotorola) - { - SKIPN(p, 1 * 2); - readBits += 2; - - a = READ8(p); - b = READ8(p); - readBits += 2; - offset = (a << 8) + b; - } - else - { - a = READ8(p); - b = READ8(p); - readBits += 2; - offset = (b << 8) + a; - - SKIPN(p, 1 * 2); - readBits += 2; - } - - offset -= 8; - if(offset > 0) - { - SKIPN(p, 1 * offset); - readBits += offset; - } - - // Get the number of directory entries contained in this IFD - if(bMotorola) - { - a = READ8(p); - b = READ8(p); - numberOfTags = (a << 8) + b; - } - else - { - a = READ8(p); - b = READ8(p); - numberOfTags = (b << 8) + a; - } - readBits += 2; - - while(numberOfTags && p < q) - { - // Get Tag number - if(bMotorola) - { - a = READ8(p); - b = READ8(p); - tagNumber = (a << 8) + b; - readBits += 2; - } - else - { - a = READ8(p); - b = READ8(p); - tagNumber = (b << 8) + a; - readBits += 2; - } - - //found orientation tag - if(tagNumber == EXIF_TAG_ORIENTATION) - { - if(bMotorola) - { - SKIPN(p, 1 * 7); - readBits += 7; - m_orientation = READ8(p)-1; - readBits += 1; - SKIPN(p, 1 * 2); - readBits += 2; - } - else - { - SKIPN(p, 1 * 6); - readBits += 6; - m_orientation = READ8(p)-1; - readBits += 1; - SKIPN(p, 1 * 3); - readBits += 3; - } - break; - } - else - { - SKIPN(p, 1 * 10); - readBits += 10; - } - numberOfTags--; - } - } - } - readBits += 4; - SKIPN(p, 1 * (block_size - readBits)); - } - else - { - SKIPN(p, 1 * (block_size - 2)); - } - - READ8(p); - marker = READ8(p); - - } - } - else - CLog::Log(LOGERROR, "%s::%s error unsupported image format", CLASSNAME, __func__); - - // apply input orientation - m_orientation = m_orientation ^ orientation; - if(m_orientation < 0 || m_orientation >= 8) - m_orientation = 0; - - if(progressive) - { - CLog::Log(LOGWARNING, "%s::%s progressive images not supported by decoder", CLASSNAME, - __func__); - eCompressionFormat = OMX_IMAGE_CodingMax; - } - - if(components > 3) - { - CLog::Log(LOGWARNING, "%s::%s Only YUV images are supported by decoder", CLASSNAME, __func__); - eCompressionFormat = OMX_IMAGE_CodingMax; - } - - return eCompressionFormat; -} - - -bool COMXImageFile::ReadFile(const std::string& inputFile, int orientation) -{ - XFILE::CFile m_pFile; - m_filename = CURL::GetRedacted(inputFile); - if(!m_pFile.Open(inputFile, 0)) - { - CLog::Log(LOGERROR, "%s::%s %s not found", CLASSNAME, __func__, GetFilename()); - return false; - } - - if(m_image_buffer) - free(m_image_buffer); - m_image_buffer = NULL; - - m_image_size = m_pFile.GetLength(); - - if(!m_image_size) - { - CLog::Log(LOGERROR, "%s::%s %s m_image_size zero", CLASSNAME, __func__, GetFilename()); - return false; - } - m_image_buffer = (uint8_t *)malloc(m_image_size); - if(!m_image_buffer) - { - CLog::Log(LOGERROR, "%s::%s %s m_image_buffer null (%lu)", CLASSNAME, __func__, GetFilename(), - m_image_size); - return false; - } - - m_pFile.Read(m_image_buffer, m_image_size); - m_pFile.Close(); - - OMX_IMAGE_CODINGTYPE eCompressionFormat = GetCodingType(m_width, m_height, orientation); - if(eCompressionFormat != OMX_IMAGE_CodingJPEG || m_width < 1 || m_height < 1) - { - CLog::Log(LOGDEBUG, "%s::%s %s GetCodingType=0x%x (%dx%d)", CLASSNAME, __func__, GetFilename(), - eCompressionFormat, m_width, m_height); - return false; - } - - return true; -} - -#ifdef CLASSNAME -#undef CLASSNAME -#endif -#define CLASSNAME "COMXImageDec" - -COMXImageDec::COMXImageDec() -{ - limit_calls_enter(); - m_decoded_buffer = NULL; - OMX_INIT_STRUCTURE(m_decoded_format); - m_success = false; -} - -COMXImageDec::~COMXImageDec() -{ - Close(); - - OMX_INIT_STRUCTURE(m_decoded_format); - m_decoded_buffer = NULL; - limit_calls_leave(); -} - -void COMXImageDec::Close() -{ - CSingleLock lock(m_OMXSection); - - if (!m_success) - { - if(m_omx_decoder.IsInitialized()) - { - m_omx_decoder.SetStateForComponent(OMX_StateIdle); - m_omx_decoder.FlushInput(); - m_omx_decoder.FreeInputBuffers(); - } - if(m_omx_resize.IsInitialized()) - { - m_omx_resize.SetStateForComponent(OMX_StateIdle); - m_omx_resize.FlushOutput(); - m_omx_resize.FreeOutputBuffers(); - } - } - if(m_omx_tunnel_decode.IsInitialized()) - m_omx_tunnel_decode.Deestablish(); - if(m_omx_decoder.IsInitialized()) - m_omx_decoder.Deinitialize(); - if(m_omx_resize.IsInitialized()) - m_omx_resize.Deinitialize(); -} - -bool COMXImageDec::HandlePortSettingChange(unsigned int resize_width, unsigned int resize_height, unsigned int resize_stride) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - // on the first port settings changed event, we create the tunnel and alloc the buffer - if (!m_decoded_buffer) - { - OMX_PARAM_PORTDEFINITIONTYPE port_def; - OMX_INIT_STRUCTURE(port_def); - - port_def.nPortIndex = m_omx_decoder.GetOutputPort(); - m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - port_def.format.image.nSliceHeight = 16; - m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); - - port_def.nPortIndex = m_omx_resize.GetInputPort(); - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort()); - - omx_err = m_omx_tunnel_decode.Establish(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish", CLASSNAME, __func__); - return false; - } - omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForEvent=%x", CLASSNAME, __func__, omx_err); - return false; - } - - port_def.nPortIndex = m_omx_resize.GetOutputPort(); - m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def); - - port_def.nPortIndex = m_omx_resize.GetOutputPort(); - port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; - port_def.format.image.eColorFormat = OMX_COLOR_Format32bitARGB8888; - port_def.format.image.nFrameWidth = resize_width; - port_def.format.image.nFrameHeight = resize_height; - port_def.format.image.nStride = resize_stride; - port_def.format.image.nSliceHeight = 0; - port_def.format.image.bFlagErrorConcealment = OMX_FALSE; - - omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - OMX_INIT_STRUCTURE(m_decoded_format); - m_decoded_format.nPortIndex = m_omx_resize.GetOutputPort(); - omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &m_decoded_format); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - assert(m_decoded_format.nBufferCountActual == 1); - - omx_err = m_omx_resize.AllocOutputBuffers(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.AllocOutputBuffers result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetStateForComponent result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - - m_decoded_buffer = m_omx_resize.GetOutputBuffer(); - - if(!m_decoded_buffer) - { - CLog::Log(LOGERROR, "%s::%s no output buffer", CLASSNAME, __func__); - return false; - } - - omx_err = m_omx_resize.FillThisBuffer(m_decoded_buffer); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize FillThisBuffer result(0x%x)", CLASSNAME, __func__, - omx_err); - m_omx_resize.DecoderFillBufferDone(m_omx_resize.GetComponent(), m_decoded_buffer); - return false; - } - } - // on subsequent port settings changed event, we just copy the port settings - else - { - // a little surprising, make a note - CLog::Log(LOGDEBUG, "%s::%s m_omx_resize second port changed event", CLASSNAME, __func__); - m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true); - m_omx_resize.DisablePort(m_omx_resize.GetInputPort(), true); - - OMX_PARAM_PORTDEFINITIONTYPE port_def; - OMX_INIT_STRUCTURE(port_def); - - port_def.nPortIndex = m_omx_decoder.GetOutputPort(); - m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - port_def.nPortIndex = m_omx_resize.GetInputPort(); - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - - omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForEvent=%x", CLASSNAME, __func__, omx_err); - return false; - } - m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true); - m_omx_resize.EnablePort(m_omx_resize.GetInputPort(), true); - } - return true; -} - -bool COMXImageDec::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes, unsigned width, unsigned height, unsigned stride, void *pixels) -{ - CSingleLock lock(m_OMXSection); - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_BUFFERHEADERTYPE *omx_buffer = NULL; - - if(!demuxer_content || !demuxer_bytes) - { - CLog::Log(LOGERROR, "%s::%s no input buffer", CLASSNAME, __func__); - return false; - } - - if(!m_omx_decoder.Initialize("OMX.broadcom.image_decode", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize", CLASSNAME, __func__); - return false; - } - - if(!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize", CLASSNAME, __func__); - return false; - } - - // set input format - 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 GetParameter:OMX_IndexParamPortDefinition omx_err(0x%08x)", - CLASSNAME, __func__, omx_err); - return false; - } - - portParam.nBufferCountActual = portParam.nBufferCountMin; - portParam.nBufferSize = std::max(portParam.nBufferSize, ALIGN_UP(demuxer_bytes, portParam.nBufferAlignment)); - portParam.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG; - - omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error SetParameter:OMX_IndexParamPortDefinition omx_err(0x%08x)", - CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_decoder.AllocInputBuffers(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_decoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - - while(demuxer_bytes > 0 || !m_decoded_buffer) - { - long timeout = 0; - if (demuxer_bytes) - { - omx_buffer = m_omx_decoder.GetInputBuffer(1000); - if(omx_buffer == NULL) - return false; - - omx_buffer->nOffset = omx_buffer->nFlags = 0; - - omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; - memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); - - demuxer_content += omx_buffer->nFilledLen; - demuxer_bytes -= omx_buffer->nFilledLen; - - if(demuxer_bytes == 0) - omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; - - 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); - m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); - return false; - } - } - if (!demuxer_bytes) - { - // we've submitted all buffers so can wait now - timeout = 1000; - } - omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, timeout); - if(omx_err == OMX_ErrorNone) - { - if (!HandlePortSettingChange(width, height, stride)) - { - CLog::Log(LOGERROR, "%s::%s HandlePortSettingChange() failed", CLASSNAME, __func__); - return false; - } - } - else if(omx_err == OMX_ErrorStreamCorrupt) - { - CLog::Log(LOGERROR, "%s::%s - image not supported", CLASSNAME, __func__); - return false; - } - else if(timeout || omx_err != OMX_ErrorTimeout) - { - CLog::Log(LOGERROR, "%s::%s WaitForEvent:OMX_EventPortSettingsChanged failed (%x)", CLASSNAME, - __func__, omx_err); - return false; - } - } - - omx_err = m_omx_resize.WaitForOutputDone(1000); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForOutputDone result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - if(m_omx_decoder.BadState()) - return false; - - memcpy( (char*)pixels, m_decoded_buffer->pBuffer, stride * height); - - m_success = true; - Close(); - return true; -} - -#ifdef CLASSNAME -#undef CLASSNAME -#endif -#define CLASSNAME "COMXImageEnc" - -COMXImageEnc::COMXImageEnc() -{ - limit_calls_enter(); - CSingleLock lock(m_OMXSection); - OMX_INIT_STRUCTURE(m_encoded_format); - m_encoded_buffer = NULL; - m_success = false; -} - -COMXImageEnc::~COMXImageEnc() -{ - CSingleLock lock(m_OMXSection); - - OMX_INIT_STRUCTURE(m_encoded_format); - m_encoded_buffer = NULL; - if (!m_success) - { - if(m_omx_encoder.IsInitialized()) - { - m_omx_encoder.SetStateForComponent(OMX_StateIdle); - m_omx_encoder.FlushAll(); - m_omx_encoder.FreeInputBuffers(); - m_omx_encoder.FreeOutputBuffers(); - m_omx_encoder.Deinitialize(); - } - } - limit_calls_leave(); -} - -bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsigned height, unsigned int pitch) -{ - CSingleLock lock(m_OMXSection); - - unsigned int demuxer_bytes = 0; - const uint8_t *demuxer_content = NULL; - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_BUFFERHEADERTYPE *omx_buffer = NULL; - OMX_INIT_STRUCTURE(m_encoded_format); - - if (pitch == 0) - pitch = 4 * width; - - if (!buffer || !size) - { - CLog::Log(LOGERROR, "%s::%s error no buffer", CLASSNAME, __func__); - return false; - } - - if(!m_omx_encoder.Initialize("OMX.broadcom.image_encode", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_encoder.Initialize", CLASSNAME, __func__); - return false; - } - - OMX_PARAM_PORTDEFINITIONTYPE port_def; - OMX_INIT_STRUCTURE(port_def); - port_def.nPortIndex = m_omx_encoder.GetInputPort(); - - omx_err = m_omx_encoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused; - port_def.format.image.eColorFormat = OMX_COLOR_Format32bitARGB8888; - port_def.format.image.nFrameWidth = width; - port_def.format.image.nFrameHeight = height; - port_def.format.image.nStride = pitch; - port_def.format.image.nSliceHeight = (height+15) & ~15; - port_def.format.image.bFlagErrorConcealment = OMX_FALSE; - - omx_err = m_omx_encoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - OMX_INIT_STRUCTURE(port_def); - port_def.nPortIndex = m_omx_encoder.GetOutputPort(); - - omx_err = m_omx_encoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG; - port_def.format.image.eColorFormat = OMX_COLOR_FormatUnused; - port_def.format.image.nFrameWidth = width; - port_def.format.image.nFrameHeight = height; - port_def.format.image.nStride = 0; - port_def.format.image.nSliceHeight = 0; - port_def.format.image.bFlagErrorConcealment = OMX_FALSE; - - omx_err = m_omx_encoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - OMX_IMAGE_PARAM_QFACTORTYPE qfactor; - OMX_INIT_STRUCTURE(qfactor); - qfactor.nPortIndex = m_omx_encoder.GetOutputPort(); - qfactor.nQFactor = 16; - - omx_err = m_omx_encoder.SetParameter(OMX_IndexParamQFactor, &qfactor); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetParameter OMX_IndexParamQFactor result(0x%x)", - CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_encoder.AllocInputBuffers(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_encoder.AllocOutputBuffers(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.AllocOutputBuffers result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - omx_err = m_omx_encoder.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetStateForComponent result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - - demuxer_content = buffer; - demuxer_bytes = height * pitch; - - if(!demuxer_bytes || !demuxer_content) - return false; - - while(demuxer_bytes > 0) - { - omx_buffer = m_omx_encoder.GetInputBuffer(1000); - if(omx_buffer == NULL) - { - return false; - } - - omx_buffer->nOffset = omx_buffer->nFlags = 0; - - omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; - memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); - - demuxer_content += omx_buffer->nFilledLen; - demuxer_bytes -= omx_buffer->nFilledLen; - - if(demuxer_bytes == 0) - omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; - - omx_err = m_omx_encoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, - __func__, omx_err); - m_omx_encoder.DecoderEmptyBufferDone(m_omx_encoder.GetComponent(), omx_buffer); - break; - } - } - - m_encoded_buffer = m_omx_encoder.GetOutputBuffer(); - - if(!m_encoded_buffer) - { - CLog::Log(LOGERROR, "%s::%s no output buffer", CLASSNAME, __func__); - return false; - } - - omx_err = m_omx_encoder.FillThisBuffer(m_encoded_buffer); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.FillThisBuffer result(0x%x)", CLASSNAME, __func__, - omx_err); - m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); - return false; - } - omx_err = m_omx_encoder.WaitForOutputDone(2000); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.WaitForOutputDone result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - m_encoded_format.nPortIndex = m_omx_encoder.GetOutputPort(); - omx_err = m_omx_encoder.GetParameter(OMX_IndexParamPortDefinition, &m_encoded_format); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - if(m_omx_encoder.BadState()) - return false; - - return true; -} - -bool COMXImageEnc::CreateThumbnailFromSurface(unsigned char* buffer, unsigned int width, unsigned int height, - unsigned int format, unsigned int pitch, const std::string& destFile) -{ - if(format != XB_FMT_A8R8G8B8 || !buffer) - { - CLog::Log(LOGDEBUG, "%s::%s : %s failed format=0x%x", CLASSNAME, __func__, destFile.c_str(), - format); - return false; - } - - if(!Encode(buffer, height * pitch, width, height, pitch)) - { - CLog::Log(LOGDEBUG, "%s::%s : %s encode failed", CLASSNAME, __func__, destFile.c_str()); - return false; - } - - XFILE::CFile file; - if (file.OpenForWrite(destFile, true)) - { - CLog::Log(LOGDEBUG, "%s::%s : %s width %d height %d", CLASSNAME, __func__, destFile.c_str(), - width, height); - - file.Write(m_encoded_buffer->pBuffer, m_encoded_buffer->nFilledLen); - file.Close(); - return true; - } - - m_success = true; - return false; -} - -#ifdef CLASSNAME -#undef CLASSNAME -#endif -#define CLASSNAME "COMXReEnc" - -COMXImageReEnc::COMXImageReEnc() -{ - limit_calls_enter(); - m_encoded_buffer = NULL; - m_pDestBuffer = NULL; - m_nDestAllocSize = 0; - m_success = false; -} - -COMXImageReEnc::~COMXImageReEnc() -{ - Close(); - if (m_pDestBuffer) - free (m_pDestBuffer); - m_pDestBuffer = NULL; - m_nDestAllocSize = 0; - limit_calls_leave(); -} - -void COMXImageReEnc::Close() -{ - CSingleLock lock(m_OMXSection); - - if (!m_success) - { - if(m_omx_decoder.IsInitialized()) - { - m_omx_decoder.SetStateForComponent(OMX_StateIdle); - m_omx_decoder.FlushInput(); - m_omx_decoder.FreeInputBuffers(); - } - if(m_omx_resize.IsInitialized()) - { - m_omx_resize.SetStateForComponent(OMX_StateIdle); - } - if(m_omx_encoder.IsInitialized()) - { - m_omx_encoder.SetStateForComponent(OMX_StateIdle); - m_omx_encoder.FlushOutput(); - m_omx_encoder.FreeOutputBuffers(); - } - } - if(m_omx_tunnel_decode.IsInitialized()) - m_omx_tunnel_decode.Deestablish(); - if(m_omx_tunnel_resize.IsInitialized()) - m_omx_tunnel_resize.Deestablish(); - if(m_omx_decoder.IsInitialized()) - m_omx_decoder.Deinitialize(); - if(m_omx_resize.IsInitialized()) - m_omx_resize.Deinitialize(); - if(m_omx_encoder.IsInitialized()) - m_omx_encoder.Deinitialize(); -} - - - -bool COMXImageReEnc::HandlePortSettingChange(unsigned int resize_width, unsigned int resize_height, int orientation, bool port_settings_changed) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - // on the first port settings changed event, we create the tunnel and alloc the buffer - if (!port_settings_changed) - { - OMX_PARAM_PORTDEFINITIONTYPE port_def; - OMX_INIT_STRUCTURE(port_def); - - port_def.nPortIndex = m_omx_decoder.GetOutputPort(); - m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_decoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - if (resize_width != port_def.format.image.nFrameWidth || resize_height != port_def.format.image.nFrameHeight || (orientation & 4)) - { - if(!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize", CLASSNAME, __func__); - return false; - } - } - - //! @todo jpeg decoder can decimate by factors of 2 - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; - if (m_omx_resize.IsInitialized()) - port_def.format.image.nSliceHeight = 16; - else - port_def.format.image.nSliceHeight = (resize_height+15) & ~15; - - port_def.format.image.nStride = 0; - - 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; - } - - if (m_omx_resize.IsInitialized()) - { - port_def.nPortIndex = m_omx_resize.GetInputPort(); - - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.nPortIndex = m_omx_resize.GetOutputPort(); - m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; - port_def.format.image.nFrameWidth = resize_width; - port_def.format.image.nFrameHeight = resize_height; - port_def.format.image.nSliceHeight = (resize_height+15) & ~15; - port_def.format.image.nStride = 0; - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - } - - if(!m_omx_encoder.Initialize("OMX.broadcom.image_encode", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_encoder.Initialize", CLASSNAME, __func__); - return false; - } - - port_def.nPortIndex = m_omx_encoder.GetInputPort(); - m_omx_encoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; - port_def.format.image.nFrameWidth = resize_width; - port_def.format.image.nFrameHeight = resize_height; - port_def.format.image.nSliceHeight = (resize_height+15) & ~15; - port_def.format.image.nStride = 0; - m_omx_encoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.nPortIndex = m_omx_encoder.GetOutputPort(); - omx_err = m_omx_encoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG; - port_def.format.image.eColorFormat = OMX_COLOR_FormatUnused; - port_def.format.image.nFrameWidth = resize_width; - port_def.format.image.nFrameHeight = resize_height; - port_def.format.image.nStride = 0; - port_def.format.image.nSliceHeight = 0; - port_def.format.image.bFlagErrorConcealment = OMX_FALSE; - - omx_err = m_omx_encoder.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - OMX_IMAGE_PARAM_QFACTORTYPE qfactor; - OMX_INIT_STRUCTURE(qfactor); - qfactor.nPortIndex = m_omx_encoder.GetOutputPort(); - qfactor.nQFactor = 16; - - omx_err = m_omx_encoder.SetParameter(OMX_IndexParamQFactor, &qfactor); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetParameter OMX_IndexParamQFactor result(0x%x)", - CLASSNAME, __func__, omx_err); - return false; - } - - if (orientation) - { - struct { - // metadata, these two fields need to be together - OMX_CONFIG_METADATAITEMTYPE metadata; - char metadata_space[64]; - } item; - OMX_INIT_STRUCTURE(item.metadata); - - item.metadata.nSize = sizeof(item); - item.metadata.eScopeMode = OMX_MetadataScopePortLevel; - item.metadata.nScopeSpecifier = m_omx_encoder.GetOutputPort(); - item.metadata.nMetadataItemIndex = 0; - item.metadata.eSearchMode = OMX_MetadataSearchValueSizeByIndex; - item.metadata.eKeyCharset = OMX_MetadataCharsetASCII; - strcpy((char *)item.metadata.nKey, "IFD0.Orientation"); - item.metadata.nKeySizeUsed = strlen((char *)item.metadata.nKey); - - item.metadata.eValueCharset = OMX_MetadataCharsetASCII; - item.metadata.sLanguageCountry = 0; - item.metadata.nValueMaxSize = sizeof(item.metadata_space); - sprintf((char *)item.metadata.nValue, "%d", orientation + 1); - item.metadata.nValueSizeUsed = strlen((char *)item.metadata.nValue); - - omx_err = m_omx_encoder.SetParameter(OMX_IndexConfigMetadataItem, &item); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "%s::%s m_omx_encoder.SetParameter:OMX_IndexConfigMetadataItem omx_err(0x%08x)", - CLASSNAME, __func__, omx_err); - return false; - } - } - omx_err = m_omx_encoder.AllocOutputBuffers(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.AllocOutputBuffers result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - - if (m_omx_resize.IsInitialized()) - { - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort()); - - omx_err = m_omx_tunnel_decode.Establish(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish", CLASSNAME, __func__); - return false; - } - - m_omx_tunnel_resize.Initialize(&m_omx_resize, m_omx_resize.GetOutputPort(), &m_omx_encoder, m_omx_encoder.GetInputPort()); - - omx_err = m_omx_tunnel_resize.Establish(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_resize.Establish", CLASSNAME, __func__); - return false; - } - - omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetStateForComponent result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - } - else - { - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_encoder, m_omx_encoder.GetInputPort()); - - omx_err = m_omx_tunnel_decode.Establish(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish", CLASSNAME, __func__); - return false; - } - } - omx_err = m_omx_encoder.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_encoder.SetStateForComponent result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - - if(m_omx_encoder.BadState()) - return false; - } - // on subsequent port settings changed event, we just copy the port settings - else - { - // a little surprising, make a note - CLog::Log(LOGDEBUG, "%s::%s m_omx_resize second port changed event", CLASSNAME, __func__); - m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true); - if (m_omx_resize.IsInitialized()) - { - m_omx_resize.DisablePort(m_omx_resize.GetInputPort(), true); - - OMX_PARAM_PORTDEFINITIONTYPE port_def; - OMX_INIT_STRUCTURE(port_def); - - port_def.nPortIndex = m_omx_decoder.GetOutputPort(); - m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def); - port_def.nPortIndex = m_omx_resize.GetInputPort(); - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - - omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForEvent=%x", CLASSNAME, __func__, omx_err); - return false; - } - m_omx_resize.EnablePort(m_omx_resize.GetInputPort(), true); - } - m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true); - } - return true; -} - -bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, unsigned int maxHeight, void * &pDestBuffer, unsigned int &nDestSize) -{ - CSingleLock lock(m_OMXSection); - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - COMXImage::ClampLimits(maxWidth, maxHeight, srcFile.GetWidth(), srcFile.GetHeight(), srcFile.GetOrientation() & 4); - unsigned int demuxer_bytes = srcFile.GetImageSize(); - unsigned char *demuxer_content = (unsigned char *)srcFile.GetImageBuffer(); - // initial dest buffer size - nDestSize = 0; - - if(!demuxer_content || !demuxer_bytes) - { - CLog::Log(LOGERROR, "%s::%s %s no input buffer", CLASSNAME, __func__, srcFile.GetFilename()); - return false; - } - - if(!m_omx_decoder.Initialize("OMX.broadcom.image_decode", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s %s error m_omx_decoder.Initialize", CLASSNAME, __func__, - srcFile.GetFilename()); - return false; - } - - // set input format - 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 %s error GetParameter:OMX_IndexParamPortDefinition omx_err(0x%08x)", - CLASSNAME, __func__, srcFile.GetFilename(), omx_err); - return false; - } - - portParam.nBufferCountActual = portParam.nBufferCountMin; - portParam.nBufferSize = std::max(portParam.nBufferSize, ALIGN_UP(demuxer_bytes, portParam.nBufferAlignment)); - portParam.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG; - - omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s %s error SetParameter:OMX_IndexParamPortDefinition omx_err(0x%08x)", - CLASSNAME, __func__, srcFile.GetFilename(), omx_err); - return false; - } - - omx_err = m_omx_decoder.AllocInputBuffers(); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s %s m_omx_decoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); - return false; - } - - omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s %s m_omx_decoder.SetStateForComponent result(0x%x)", CLASSNAME, - __func__, srcFile.GetFilename(), omx_err); - return false; - } - - bool port_settings_changed = false, eos = false; - while(demuxer_bytes > 0 || !port_settings_changed || !eos) - { - long timeout = 0; - if (demuxer_bytes) - { - OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(1000); - if(omx_buffer) - { - omx_buffer->nOffset = omx_buffer->nFlags = 0; - - omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; - memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); - - demuxer_content += omx_buffer->nFilledLen; - demuxer_bytes -= omx_buffer->nFilledLen; - if(demuxer_bytes == 0) - omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; - - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s %s OMX_EmptyThisBuffer() failed with result(0x%x)", - CLASSNAME, __func__, srcFile.GetFilename(), omx_err); - m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); - return false; - } - } - } - if (!demuxer_bytes) - { - // we've submitted all buffers so can wait now - timeout = 1000; - } - - omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, timeout); - if(omx_err == OMX_ErrorNone) - { - if (!HandlePortSettingChange(maxWidth, maxHeight, srcFile.GetOrientation(), port_settings_changed)) - { - CLog::Log(LOGERROR, "%s::%s %s HandlePortSettingChange() failed", srcFile.GetFilename(), - CLASSNAME, __func__); - return false; - } - port_settings_changed = true; - } - else if(omx_err == OMX_ErrorStreamCorrupt) - { - CLog::Log(LOGERROR, "%s::%s %s - image not supported", CLASSNAME, __func__, srcFile.GetFilename()); - return false; - } - else if(timeout || omx_err != OMX_ErrorTimeout) - { - CLog::Log(LOGERROR, "%s::%s %s WaitForEvent:OMX_EventPortSettingsChanged failed (%x)", - CLASSNAME, __func__, srcFile.GetFilename(), omx_err); - return false; - } - - if (!m_encoded_buffer && port_settings_changed && demuxer_bytes == 0) - { - m_encoded_buffer = m_omx_encoder.GetOutputBuffer(); - omx_err = m_omx_encoder.FillThisBuffer(m_encoded_buffer); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s %s FillThisBuffer() failed (%x)", CLASSNAME, __func__, - srcFile.GetFilename(), omx_err); - m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); - return false; - } - } - if (m_encoded_buffer) - { - omx_err = m_omx_encoder.WaitForOutputDone(2000); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s %s m_omx_encoder.WaitForOutputDone result(0x%x)", CLASSNAME, - __func__, srcFile.GetFilename(), omx_err); - return false; - } - if (!m_encoded_buffer->nFilledLen) - { - CLog::Log(LOGERROR, "%s::%s %s m_omx_encoder.WaitForOutputDone no data", CLASSNAME, - __func__, srcFile.GetFilename()); - return false; - } - if (m_encoded_buffer->nFlags & OMX_BUFFERFLAG_EOS) - eos = true; - - if (nDestSize + m_encoded_buffer->nFilledLen > m_nDestAllocSize) - { - while (nDestSize + m_encoded_buffer->nFilledLen > m_nDestAllocSize) - m_nDestAllocSize = std::max(1024U*1024U, m_nDestAllocSize*2); - m_pDestBuffer = realloc(m_pDestBuffer, m_nDestAllocSize); - } - memcpy((char *)m_pDestBuffer + nDestSize, m_encoded_buffer->pBuffer, m_encoded_buffer->nFilledLen); - nDestSize += m_encoded_buffer->nFilledLen; - m_encoded_buffer = NULL; - } - } - - if(m_omx_decoder.BadState()) - return false; - - pDestBuffer = m_pDestBuffer; - CLog::Log(LOGDEBUG, "%s::%s : %s %dx%d -> %dx%d", CLASSNAME, __func__, srcFile.GetFilename(), - srcFile.GetWidth(), srcFile.GetHeight(), maxWidth, maxHeight); - - m_success = true; - Close(); - - return true; -} - - -#ifdef CLASSNAME -#undef CLASSNAME -#endif -#define CLASSNAME "COMXTexture" - -COMXTexture::COMXTexture() -{ - limit_calls_enter(); - m_success = false; -} - -COMXTexture::~COMXTexture() -{ - Close(); - limit_calls_leave(); -} - -void COMXTexture::Close() -{ - CSingleLock lock(m_OMXSection); - - if (!m_success) - { - if(m_omx_decoder.IsInitialized()) - { - m_omx_decoder.SetStateForComponent(OMX_StateIdle); - m_omx_decoder.FlushInput(); - m_omx_decoder.FreeInputBuffers(); - } - if(m_omx_egl_render.IsInitialized()) - { - m_omx_egl_render.SetStateForComponent(OMX_StateIdle); - m_omx_egl_render.FlushOutput(); - m_omx_egl_render.FreeOutputBuffers(); - } - } - if (m_omx_tunnel_decode.IsInitialized()) - m_omx_tunnel_decode.Deestablish(); - if (m_omx_tunnel_egl.IsInitialized()) - m_omx_tunnel_egl.Deestablish(); - // delete components - if (m_omx_decoder.IsInitialized()) - m_omx_decoder.Deinitialize(); - if (m_omx_resize.IsInitialized()) - m_omx_resize.Deinitialize(); - if (m_omx_egl_render.IsInitialized()) - m_omx_egl_render.Deinitialize(); -} - -bool COMXTexture::HandlePortSettingChange(unsigned int resize_width, unsigned int resize_height, void *egl_image, bool port_settings_changed) -{ - CWinSystemRpiGLESContext *winsystem = static_cast<CWinSystemRpiGLESContext *>(CServiceBroker::GetWinSystem()); - EGLDisplay egl_display = winsystem->GetEGLDisplay(); - OMX_ERRORTYPE omx_err; - - if (port_settings_changed) - CLog::Log(LOGERROR, "%s::%s Unexpected second port_settings_changed call", CLASSNAME, __func__); - - 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 m_omx_decoder.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - //! @todo jpeg decoder can decimate by factors of 2 - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; - port_def.format.image.nSliceHeight = 16; - port_def.format.image.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; - } - if (resize_width != port_def.format.image.nFrameWidth || resize_height != port_def.format.image.nFrameHeight) - { - if (!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize", CLASSNAME, __func__); - return false; - } - } - if (m_omx_resize.IsInitialized()) - { - port_def.nPortIndex = m_omx_resize.GetInputPort(); - - omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.nPortIndex = m_omx_resize.GetOutputPort(); - omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; - port_def.format.image.nFrameWidth = resize_width; - port_def.format.image.nFrameHeight = resize_height; - port_def.format.image.nSliceHeight = 16; - port_def.format.image.nStride = 0; - omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - } - if (!m_omx_egl_render.Initialize("OMX.broadcom.egl_render", OMX_IndexParamVideoInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.Initialize", CLASSNAME, __func__); - return false; - } - - port_def.nPortIndex = m_omx_egl_render.GetOutputPort(); - omx_err = m_omx_egl_render.GetParameter(OMX_IndexParamPortDefinition, &port_def); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - port_def.nBufferCountActual = 1; - port_def.format.video.pNativeWindow = egl_display; - - omx_err = m_omx_egl_render.SetParameter(OMX_IndexParamPortDefinition, &port_def); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.SetParameter result(0x%x)", CLASSNAME, __func__, - omx_err); - return false; - } - - omx_err = m_omx_egl_render.UseEGLImage(&m_egl_buffer, m_omx_egl_render.GetOutputPort(), NULL, egl_image); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.UseEGLImage (%x)", CLASSNAME, __func__, omx_err); - return false; - } - if (m_omx_resize.IsInitialized()) - { - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort()); - - omx_err = m_omx_tunnel_decode.Establish(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish (%x)", CLASSNAME, __func__, omx_err); - return false; - } - - m_omx_tunnel_egl.Initialize(&m_omx_resize, m_omx_resize.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort()); - - omx_err = m_omx_tunnel_egl.Establish(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_egl.Establish (%x)", CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.GetParameter (%x)", CLASSNAME, __func__, omx_err); - return false; - } - } - else - { - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort()); - - omx_err = m_omx_tunnel_decode.Establish(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish (%x)", CLASSNAME, __func__, omx_err); - return false; - } - } - - omx_err = m_omx_egl_render.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.SetStateForComponent (%x)", CLASSNAME, __func__, omx_err); - return false; - } - - return true; -} - -bool COMXTexture::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes, unsigned int width, unsigned int height, void *egl_image) -{ - CSingleLock lock(m_OMXSection); - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if (!demuxer_content || !demuxer_bytes) - { - CLog::Log(LOGERROR, "%s::%s no input buffer", CLASSNAME, __func__); - return false; - } - - if (!m_omx_decoder.Initialize("OMX.broadcom.image_decode", OMX_IndexParamImageInit)) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize", CLASSNAME, __func__); - return false; - } - - // set input format - 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 GetParameter:OMX_IndexParamPortDefinition omx_err(0x%08x)", - CLASSNAME, __func__, omx_err); - return false; - } - - portParam.nBufferCountActual = portParam.nBufferCountMin; - portParam.nBufferSize = std::max(portParam.nBufferSize, ALIGN_UP(demuxer_bytes, portParam.nBufferAlignment)); - portParam.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG; - - omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error SetParameter:OMX_IndexParamPortDefinition omx_err(0x%08x)", - CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_decoder.AllocInputBuffers(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s - Error alloc buffers (%x)", CLASSNAME, __func__, omx_err); - return false; - } - - omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_sched.SetStateForComponent (%x)", CLASSNAME, __func__, omx_err); - return false; - } - - bool port_settings_changed = false; - bool eos = false; - while(demuxer_bytes > 0 || !port_settings_changed || !eos) - { - long timeout = 0; - if (demuxer_bytes) - { - OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(1000); - if (omx_buffer) - { - omx_buffer->nOffset = omx_buffer->nFlags = 0; - - omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; - memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); - - demuxer_content += omx_buffer->nFilledLen; - demuxer_bytes -= omx_buffer->nFilledLen; - - if (demuxer_bytes == 0) - omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; - - omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s - m_omx_decoder.OMX_EmptyThisBuffer (%x)", CLASSNAME, __func__, omx_err); - m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); - return false; - } - } - } - if (!demuxer_bytes) - { - // we've submitted all buffers so can wait now - timeout = 1000; - } - - omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, timeout); - if (omx_err == OMX_ErrorNone) - { - if (!HandlePortSettingChange(width, height, egl_image, port_settings_changed)) - { - CLog::Log(LOGERROR, "%s::%s - HandlePortSettingChange failed (%x)", CLASSNAME, __func__, omx_err); - return false; - } - port_settings_changed = true; - } - else if (omx_err == OMX_ErrorStreamCorrupt) - { - CLog::Log(LOGERROR, "%s::%s - image not supported", CLASSNAME, __func__); - return false; - } - else if (timeout || omx_err != OMX_ErrorTimeout) - { - CLog::Log(LOGERROR, "%s::%s WaitForEvent:OMX_EventPortSettingsChanged failed (%x)", CLASSNAME, - __func__, omx_err); - return false; - } - - if (port_settings_changed && m_egl_buffer && demuxer_bytes == 0 && !eos) - { - OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_egl_render.GetOutputBuffer(); - if (!omx_buffer) - { - CLog::Log(LOGERROR, "%s::%s GetOutputBuffer failed", CLASSNAME, __func__); - return false; - } - if (omx_buffer != m_egl_buffer) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.GetOutputBuffer (%p,%p)", CLASSNAME, - __func__, static_cast<void*>(omx_buffer), static_cast<void*>(m_egl_buffer)); - return false; - } - - omx_err = m_omx_egl_render.FillThisBuffer(m_egl_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.FillThisBuffer (%x)", CLASSNAME, __func__, omx_err); - m_omx_egl_render.DecoderFillBufferDone(m_omx_egl_render.GetComponent(), m_egl_buffer); - return false; - } - - omx_err = m_omx_egl_render.WaitForOutputDone(2000); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.WaitForOutputDone result(0x%x)", CLASSNAME, - __func__, omx_err); - return false; - } - eos = true; - } - } - m_success = true; - Close(); - return true; -} - -COMXImage g_OMXImage; diff --git a/xbmc/cores/omxplayer/OMXImage.h b/xbmc/cores/omxplayer/OMXImage.h deleted file mode 100644 index 474346c18e..0000000000 --- a/xbmc/cores/omxplayer/OMXImage.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "OMXCore.h" -#include "filesystem/File.h" -#include "guilib/XBTF.h" -#include "threads/Thread.h" - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <IL/OMX_Video.h> - -#include "system_gl.h" - -class COMXImageFile; - -class COMXImage : public CThread -{ - struct callbackinfo { - CEvent sync; - bool (*callback)(EGLDisplay egl_display, EGLContext egl_context, void *cookie); - void *cookie; - bool result; - }; -protected: - virtual void OnStartup(); - virtual void OnExit(); - virtual void Process(); -public: - struct textureinfo { - int width, height; - GLuint texture; - EGLImageKHR egl_image; - void *parent; - }; - COMXImage(); - virtual ~COMXImage(); - void Initialize(); - void Deinitialize(); - static COMXImageFile *LoadJpeg(const std::string& texturePath); - static void CloseJpeg(COMXImageFile *file); - - static bool DecodeJpeg(COMXImageFile *file, unsigned int maxWidth, unsigned int maxHeight, unsigned int stride, void *pixels); - static bool CreateThumbnailFromSurface(unsigned char* buffer, unsigned int width, unsigned int height, - unsigned int format, unsigned int pitch, const std::string& destFile); - static bool ClampLimits(unsigned int &width, unsigned int &height, unsigned int m_width, unsigned int m_height, bool transposed = false); - static bool CreateThumb(const std::string& srcFile, unsigned int width, unsigned int height, std::string &additional_info, const std::string& destFile); - bool SendMessage(bool (*callback)(EGLDisplay egl_display, EGLContext egl_context, void *cookie), void *cookie); - bool DecodeJpegToTexture(COMXImageFile *file, unsigned int width, unsigned int height, void **userdata); - void DestroyTexture(void *userdata); - void GetTexture(void *userdata, GLuint *texture); - bool AllocTextureInternal(EGLDisplay egl_display, EGLContext egl_context, struct textureinfo *tex); - bool DestroyTextureInternal(EGLDisplay egl_display, EGLContext egl_context, struct textureinfo *tex); -private: - EGLContext m_egl_context; - - void CreateContext(); - EGLContext GetEGLContext(); - CCriticalSection m_texqueue_lock; - XbmcThreads::ConditionVariable m_texqueue_cond; - std::queue <struct callbackinfo *> m_texqueue; -}; - -class COMXImageFile -{ -public: - COMXImageFile(); - virtual ~COMXImageFile(); - bool ReadFile(const std::string& inputFile, int orientation = 0); - int GetOrientation() const { return m_orientation; }; - unsigned int GetWidth() const { return m_width; }; - unsigned int GetHeight() const { return m_height; }; - unsigned long GetImageSize() const { return m_image_size; }; - const uint8_t *GetImageBuffer() const { return (const uint8_t *)m_image_buffer; }; - const char *GetFilename() const { return m_filename.c_str(); }; -protected: - OMX_IMAGE_CODINGTYPE GetCodingType(unsigned int &width, unsigned int &height, int orientation); - uint8_t *m_image_buffer; - unsigned long m_image_size; - unsigned int m_width; - unsigned int m_height; - int m_orientation; - std::string m_filename; -}; - -class COMXImageDec -{ -public: - COMXImageDec(); - virtual ~COMXImageDec(); - - // Required overrides - void Close(); - bool Decode(const uint8_t *data, unsigned size, unsigned int width, unsigned int height, unsigned stride, void *pixels); - unsigned int GetDecodedWidth() const { return (unsigned int)m_decoded_format.format.image.nFrameWidth; }; - unsigned int GetDecodedHeight() const { return (unsigned int)m_decoded_format.format.image.nFrameHeight; }; - unsigned int GetDecodedStride() const { return (unsigned int)m_decoded_format.format.image.nStride; }; -protected: - bool HandlePortSettingChange(unsigned int resize_width, unsigned int resize_height, unsigned int resize_stride); - // Components - COMXCoreComponent m_omx_decoder; - COMXCoreComponent m_omx_resize; - COMXCoreTunnel m_omx_tunnel_decode; - OMX_BUFFERHEADERTYPE *m_decoded_buffer; - OMX_PARAM_PORTDEFINITIONTYPE m_decoded_format; - CCriticalSection m_OMXSection; - bool m_success; -}; - -class COMXImageEnc -{ -public: - COMXImageEnc(); - virtual ~COMXImageEnc(); - - // Required overrides - bool CreateThumbnailFromSurface(unsigned char* buffer, unsigned int width, unsigned int height, - unsigned int format, unsigned int pitch, const std::string& destFile); -protected: - bool Encode(unsigned char *buffer, int size, unsigned int width, unsigned int height, unsigned int pitch); - // Components - COMXCoreComponent m_omx_encoder; - OMX_BUFFERHEADERTYPE *m_encoded_buffer; - OMX_PARAM_PORTDEFINITIONTYPE m_encoded_format; - CCriticalSection m_OMXSection; - bool m_success; -}; - -class COMXImageReEnc -{ -public: - COMXImageReEnc(); - virtual ~COMXImageReEnc(); - - // Required overrides - void Close(); - bool ReEncode(COMXImageFile &srcFile, unsigned int width, unsigned int height, void * &pDestBuffer, unsigned int &nDestSize); -protected: - bool HandlePortSettingChange(unsigned int resize_width, unsigned int resize_height, int orientation, bool port_settings_changed); - // Components - COMXCoreComponent m_omx_decoder; - COMXCoreComponent m_omx_resize; - COMXCoreComponent m_omx_encoder; - COMXCoreTunnel m_omx_tunnel_decode; - COMXCoreTunnel m_omx_tunnel_resize; - OMX_BUFFERHEADERTYPE *m_encoded_buffer; - CCriticalSection m_OMXSection; - void *m_pDestBuffer; - unsigned int m_nDestAllocSize; - bool m_success; -}; - -class COMXTexture -{ -public: - COMXTexture(); - virtual ~COMXTexture(); - - // Required overrides - void Close(void); - bool Decode(const uint8_t *data, unsigned size, unsigned int width, unsigned int height, void *egl_image); -protected: - bool HandlePortSettingChange(unsigned int resize_width, unsigned int resize_height, void *egl_image, bool port_settings_changed); - - // Components - COMXCoreComponent m_omx_decoder; - COMXCoreComponent m_omx_resize; - COMXCoreComponent m_omx_egl_render; - - COMXCoreTunnel m_omx_tunnel_decode; - COMXCoreTunnel m_omx_tunnel_egl; - - OMX_BUFFERHEADERTYPE *m_egl_buffer; - CCriticalSection m_OMXSection; - bool m_success; -}; - -extern COMXImage g_OMXImage; diff --git a/xbmc/guilib/CMakeLists.txt b/xbmc/guilib/CMakeLists.txt index 9adceca14c..f64e112d3e 100644 --- a/xbmc/guilib/CMakeLists.txt +++ b/xbmc/guilib/CMakeLists.txt @@ -177,11 +177,6 @@ if(OPENGLES_FOUND) TextureGL.h) endif() -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - list(APPEND SOURCES TexturePi.cpp) - list(APPEND HEADERS TexturePi.h) -endif() - if(CORE_SYSTEM_NAME STREQUAL windows OR CORE_SYSTEM_NAME STREQUAL windowsstore) list(APPEND SOURCES D3DResource.cpp DirectXGraphics.cpp diff --git a/xbmc/guilib/Texture.h b/xbmc/guilib/Texture.h index b33847cadb..084a48bc31 100644 --- a/xbmc/guilib/Texture.h +++ b/xbmc/guilib/Texture.h @@ -133,10 +133,7 @@ protected: bool m_bCacheMemory = false; }; -#if defined(TARGET_RASPBERRY_PI) -#include "TexturePi.h" -#define CTexture CPiTexture -#elif defined(HAS_GL) || defined(HAS_GLES) +#if defined(HAS_GL) || defined(HAS_GLES) #include "TextureGL.h" #define CTexture CGLTexture #elif defined(HAS_DX) diff --git a/xbmc/guilib/TexturePi.cpp b/xbmc/guilib/TexturePi.cpp deleted file mode 100644 index dc7ebdd5c7..0000000000 --- a/xbmc/guilib/TexturePi.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2013-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "Texture.h" -#include "cores/omxplayer/OMXImage.h" -#include "guilib/TextureManager.h" -#include "utils/GLUtils.h" -#include "utils/URIUtils.h" -#include "utils/log.h" - -/************************************************************************/ -/* CPiTexture */ -/************************************************************************/ - -CPiTexture::CPiTexture(unsigned int width, unsigned int height, unsigned int format) -: CGLTexture(width, height, format) -{ - m_egl_image = NULL; -} - -CPiTexture::~CPiTexture() -{ - if (m_egl_image) - { - g_OMXImage.DestroyTexture(m_egl_image); - m_egl_image = NULL; - } -} - -void CPiTexture::Allocate(unsigned int width, unsigned int height, unsigned int format) -{ - if (m_egl_image) - { - m_imageWidth = m_originalWidth = width; - m_imageHeight = m_originalHeight = height; - m_format = format; - m_orientation = 0; - - m_textureWidth = m_imageWidth; - m_textureHeight = m_imageHeight; - return; - } - return CGLTexture::Allocate(width, height, format); -} - -void CPiTexture::CreateTextureObject() -{ - if (m_egl_image && !m_texture) - { - g_OMXImage.GetTexture(m_egl_image, &m_texture); - return; - } - CGLTexture::CreateTextureObject(); -} - -void CPiTexture::LoadToGPU() -{ - if (m_egl_image) - { - if (m_loadedToGPU) - { - // nothing to load - probably same image (no change) - return; - } - if (m_texture == 0) - { - // Have OpenGL generate a texture object handle for us - // this happens only one time - the first time the texture is loaded - CreateTextureObject(); - } - - // Bind the texture object - glBindTexture(GL_TEXTURE_2D, m_texture); - - if (IsMipmapped()) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glGenerateMipmap(GL_TEXTURE_2D); - } - m_loadedToGPU = true; - return; - } - CGLTexture::LoadToGPU(); -} - -void CPiTexture::Update(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU) -{ - if (m_egl_image) - { - if (loadToGPU) - LoadToGPU(); - return; - } - CGLTexture::Update(width, height, pitch, format, pixels, loadToGPU); -} - -bool CPiTexture::LoadFromFileInternal(const std::string& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool requirePixels, const std::string& strMimeType) -{ - if (URIUtils::HasExtension(texturePath, ".jpg|.tbn")) - { - COMXImageFile *file = g_OMXImage.LoadJpeg(texturePath); - if (file) - { - bool okay = false; - int orientation = file->GetOrientation(); - // limit the sizes of jpegs (even if we fail to decode) - g_OMXImage.ClampLimits(maxWidth, maxHeight, file->GetWidth(), file->GetHeight(), orientation & 4); - - if (requirePixels) - { - Allocate(maxWidth, maxHeight, XB_FMT_A8R8G8B8); - if (m_pixels && COMXImage::DecodeJpeg(file, maxWidth, GetRows(), GetPitch(), (void *)m_pixels)) - okay = true; - } - else - { - if (g_OMXImage.DecodeJpegToTexture(file, maxWidth, maxHeight, &m_egl_image) && m_egl_image) - { - Allocate(maxWidth, maxHeight, XB_FMT_A8R8G8B8); - okay = true; - } - } - g_OMXImage.CloseJpeg(file); - if (okay) - { - m_hasAlpha = false; - m_orientation = orientation; - return true; - } - } - } - return CGLTexture::LoadFromFileInternal(texturePath, maxWidth, maxHeight, requirePixels); -} diff --git a/xbmc/guilib/TexturePi.h b/xbmc/guilib/TexturePi.h deleted file mode 100644 index 96ac178474..0000000000 --- a/xbmc/guilib/TexturePi.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "TextureGL.h" - -#include "system_gl.h" - -/************************************************************************/ -/* CGLTexture */ -/************************************************************************/ -class CPiTexture : public CGLTexture -{ -public: - CPiTexture(unsigned int width = 0, unsigned int height = 0, unsigned int format = XB_FMT_A8R8G8B8); - virtual ~CPiTexture(); - void CreateTextureObject(); - void LoadToGPU(); - void Update(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU); - void Allocate(unsigned int width, unsigned int height, unsigned int format); - bool LoadFromFileInternal(const std::string& texturePath, unsigned int maxWidth, unsigned int maxHeight, bool requirePixels, const std::string& strMimeType = ""); - -protected: - -private: - void *m_egl_image; -}; diff --git a/xbmc/guilib/guiinfo/GUIInfoLabels.h b/xbmc/guilib/guiinfo/GUIInfoLabels.h index 683476e604..9d2d2988dd 100644 --- a/xbmc/guilib/guiinfo/GUIInfoLabels.h +++ b/xbmc/guilib/guiinfo/GUIInfoLabels.h @@ -443,7 +443,7 @@ #define SYSTEM_PLATFORM_DARWIN_IOS 745 #define SYSTEM_PLATFORM_UWP 746 #define SYSTEM_PLATFORM_ANDROID 747 -#define SYSTEM_PLATFORM_LINUX_RASPBERRY_PI 748 +// previously used by rpi 748 #define SYSTEM_PLATFORM_WIN10 749 #define SYSTEM_CAN_POWERDOWN 750 diff --git a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp index 8fbe6fefe2..0e1327d683 100644 --- a/xbmc/guilib/guiinfo/SystemGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/SystemGUIInfo.cpp @@ -492,13 +492,6 @@ bool CSystemGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int context value = false; #endif return true; - case SYSTEM_PLATFORM_LINUX_RASPBERRY_PI: -#if defined(TARGET_RASPBERRY_PI) - value = true; -#else - value = false; -#endif - return true; case SYSTEM_MEDIA_DVD: value = CServiceBroker::GetMediaManager().IsDiscInDrive(); return true; diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h index 8a5176601b..82422491d2 100644 --- a/xbmc/peripherals/PeripheralTypes.h +++ b/xbmc/peripherals/PeripheralTypes.h @@ -28,7 +28,6 @@ enum PeripheralBusType PERIPHERAL_BUS_UNKNOWN = 0, PERIPHERAL_BUS_USB, PERIPHERAL_BUS_PCI, - PERIPHERAL_BUS_RPI, PERIPHERAL_BUS_CEC, PERIPHERAL_BUS_ADDON, #ifdef TARGET_ANDROID @@ -183,8 +182,6 @@ public: return "usb"; case PERIPHERAL_BUS_PCI: return "pci"; - case PERIPHERAL_BUS_RPI: - return "rpi"; case PERIPHERAL_BUS_CEC: return "cec"; case PERIPHERAL_BUS_ADDON: @@ -213,8 +210,6 @@ public: return PERIPHERAL_BUS_USB; else if (strTypeLowerCase == "pci") return PERIPHERAL_BUS_PCI; - else if (strTypeLowerCase == "rpi") - return PERIPHERAL_BUS_RPI; else if (strTypeLowerCase == "cec") return PERIPHERAL_BUS_CEC; else if (strTypeLowerCase == "addon") diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp index 0cbcd67785..e119638bc0 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp +++ b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp @@ -45,11 +45,6 @@ bool CPeripheralBusCEC::PerformDeviceScan(PeripheralScanResults& results) case ADAPTERTYPE_P8_DAUGHTERBOARD: result.m_mappedBusType = PERIPHERAL_BUS_USB; break; - case ADAPTERTYPE_RPI: - result.m_mappedBusType = PERIPHERAL_BUS_RPI; - /** the Pi's adapter cannot be removed, no need to rescan */ - m_bNeedsPolling = false; - break; default: break; } diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp index 9816ae6a1d..e24f613dd7 100644 --- a/xbmc/pictures/Picture.cpp +++ b/xbmc/pictures/Picture.cpp @@ -20,9 +20,6 @@ #include "utils/URIUtils.h" #include "guilib/Texture.h" #include "guilib/imagefactory.h" -#if defined(TARGET_RASPBERRY_PI) -#include "cores/omxplayer/OMXImage.h" -#endif extern "C" { #include <libswscale/swscale.h> @@ -58,13 +55,6 @@ bool CPicture::GetThumbnailFromSurface(const unsigned char* buffer, int width, i bool CPicture::CreateThumbnailFromSurface(const unsigned char *buffer, int width, int height, int stride, const std::string &thumbFile) { CLog::Log(LOGDEBUG, "cached image '%s' size %dx%d", CURL::GetRedacted(thumbFile).c_str(), width, height); - if (URIUtils::HasExtension(thumbFile, ".jpg")) - { -#if defined(TARGET_RASPBERRY_PI) - if (COMXImage::CreateThumbnailFromSurface(const_cast<unsigned char*>(buffer), width, height, XB_FMT_A8R8G8B8, stride, thumbFile.c_str())) - return true; -#endif - } unsigned char *thumb = NULL; unsigned int thumbsize=0; diff --git a/xbmc/platform/linux/CMakeLists.txt b/xbmc/platform/linux/CMakeLists.txt index 186c6dc7cc..3f851f521f 100644 --- a/xbmc/platform/linux/CMakeLists.txt +++ b/xbmc/platform/linux/CMakeLists.txt @@ -23,15 +23,4 @@ if(DBUS_FOUND) DBusUtil.h) endif() -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi) - list(APPEND SOURCES RBP.cpp - OMXCore.cpp - ScreenshotSurfaceRBP.cpp) - list(APPEND HEADERS RBP.h - DllBCM.h - DllOMX.h - OMXCore.h - ScreenshotSurfaceRBP.h) -endif() - core_add_library(linuxsupport) diff --git a/xbmc/platform/linux/DllBCM.h b/xbmc/platform/linux/DllBCM.h deleted file mode 100644 index e04bf0e99e..0000000000 --- a/xbmc/platform/linux/DllBCM.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#ifndef __GNUC__ -#pragma warning(push) -#pragma warning(disable:4244) -#endif - -extern "C" { -#include <bcm_host.h> -} - -#include "DynamicDll.h" -#include "utils/log.h" - -#define USE_EXTERNAL_LIBBCM_HOST 1 - -//////////////////////////////////////////////////////////////////////////////////////////// - -class DllBcmHostInterface -{ -public: - virtual ~DllBcmHostInterface() {} - - virtual void bcm_host_init() = 0; - virtual void bcm_host_deinit() = 0; - virtual int32_t graphics_get_display_size( const uint16_t display_number, uint32_t *width, uint32_t *height) = 0; - virtual int vc_tv_power_off() = 0; - virtual int vc_tv_sdtv_power_on(SDTV_MODE_T mode, SDTV_OPTIONS_T *options) = 0; - virtual int vc_tv_hdmi_power_on_preferred() = 0; - virtual int vc_tv_hdmi_power_on_best(uint32_t width, uint32_t height, uint32_t frame_rate, - HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) = 0; - virtual int vc_tv_hdmi_power_on_best_3d(uint32_t width, uint32_t height, uint32_t frame_rate, - HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) = 0; - - virtual int vc_tv_hdmi_get_supported_modes_new(HDMI_RES_GROUP_T group, TV_SUPPORTED_MODE_NEW_T *supported_modes, - uint32_t max_supported_modes, HDMI_RES_GROUP_T *preferred_group, - uint32_t *preferred_mode) = 0; - virtual int vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_T mode, HDMI_RES_GROUP_T group, uint32_t code) = 0; - virtual int vc_tv_hdmi_set_property(const HDMI_PROPERTY_PARAM_T *property) = 0; - virtual int vc_tv_get_display_state(TV_DISPLAY_STATE_T *tvstate) = 0; - virtual int vc_tv_show_info(uint32_t show) = 0; - virtual int vc_gencmd(char *response, int maxlen, const char *string) = 0; - virtual void vc_tv_register_callback(TVSERVICE_CALLBACK_T callback, void *callback_data) = 0; - virtual void vc_tv_unregister_callback(TVSERVICE_CALLBACK_T callback) = 0; - virtual void vc_cec_register_callback(CECSERVICE_CALLBACK_T callback, void *callback_data) = 0; - //virtual void vc_cec_unregister_callback(CECSERVICE_CALLBACK_T callback) = 0; - virtual DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device ) = 0; - virtual DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority ) = 0; - virtual DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display, - int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src, - const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection, - VC_DISPMANX_ALPHA_T *alpha, - DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform ) = 0; - virtual int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update ) = 0; - virtual int vc_dispmanx_update_submit( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg ) = 0; - - virtual int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element ) = 0; - virtual int vc_dispmanx_element_change_attributes( DISPMANX_UPDATE_HANDLE_T update, - DISPMANX_ELEMENT_HANDLE_T element, - uint32_t change_flags, - int32_t layer, - uint8_t opacity, - const VC_RECT_T *dest_rect, - const VC_RECT_T *src_rect, - DISPMANX_RESOURCE_HANDLE_T mask, - DISPMANX_TRANSFORM_T transform ) = 0; - virtual int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display ) = 0; - virtual int vc_dispmanx_display_get_info( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_MODEINFO_T * pinfo ) = 0; - virtual int vc_dispmanx_display_set_background( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display, - uint8_t red, uint8_t green, uint8_t blue ) = 0; - virtual int vc_tv_hdmi_audio_supported(uint32_t audio_format, uint32_t num_channels, - EDID_AudioSampleRate fs, uint32_t bitrate) = 0; -}; - -#if defined(USE_EXTERNAL_LIBBCM_HOST) -class DllBcmHost : public DllDynamic, DllBcmHostInterface -{ -public: - virtual void bcm_host_init() - { return ::bcm_host_init(); }; - virtual void bcm_host_deinit() - { return ::bcm_host_deinit(); }; - virtual int32_t graphics_get_display_size( const uint16_t display_number, uint32_t *width, uint32_t *height) - { return ::graphics_get_display_size(display_number, width, height); }; - virtual int vc_tv_power_off() - { return ::vc_tv_power_off(); } - virtual int vc_tv_sdtv_power_on(SDTV_MODE_T mode, SDTV_OPTIONS_T *options) - { return ::vc_tv_sdtv_power_on(mode, options); } - virtual int vc_tv_hdmi_power_on_preferred() - { return ::vc_tv_hdmi_power_on_preferred(); } - virtual int vc_tv_hdmi_power_on_best(uint32_t width, uint32_t height, uint32_t frame_rate, - HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) - { return ::vc_tv_hdmi_power_on_best(width, height, frame_rate, scan_mode, match_flags); }; - virtual int vc_tv_hdmi_power_on_best_3d(uint32_t width, uint32_t height, uint32_t frame_rate, - HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) - { return ::vc_tv_hdmi_power_on_best_3d(width, height, frame_rate, scan_mode, match_flags); }; - virtual int vc_tv_hdmi_get_supported_modes_new(HDMI_RES_GROUP_T group, TV_SUPPORTED_MODE_NEW_T *supported_modes, - uint32_t max_supported_modes, HDMI_RES_GROUP_T *preferred_group, - uint32_t *preferred_mode) - { return ::vc_tv_hdmi_get_supported_modes_new(group, supported_modes, max_supported_modes, preferred_group, preferred_mode); }; - virtual int vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_T mode, HDMI_RES_GROUP_T group, uint32_t code) - { return ::vc_tv_hdmi_power_on_explicit_new(mode, group, code); }; - virtual int vc_tv_hdmi_set_property(const HDMI_PROPERTY_PARAM_T *property) - { return ::vc_tv_hdmi_set_property(property); }; - virtual int vc_tv_get_display_state(TV_DISPLAY_STATE_T *tvstate) - { return ::vc_tv_get_display_state(tvstate); }; - virtual int vc_tv_show_info(uint32_t show) - { return ::vc_tv_show_info(show); }; - virtual int vc_gencmd(char *response, int maxlen, const char *string) - { return ::vc_gencmd(response, maxlen, string); }; - virtual void vc_tv_register_callback(TVSERVICE_CALLBACK_T callback, void *callback_data) - { ::vc_tv_register_callback(callback, callback_data); }; - virtual void vc_tv_unregister_callback(TVSERVICE_CALLBACK_T callback) - { ::vc_tv_unregister_callback(callback); }; - virtual void vc_cec_register_callback(CECSERVICE_CALLBACK_T callback, void *callback_data) - { ::vc_cec_register_callback(callback, callback_data); }; - //virtual void vc_cec_unregister_callback(CECSERVICE_CALLBACK_T callback) - // { ::vc_cec_unregister_callback(callback); }; - virtual DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device ) - { return ::vc_dispmanx_display_open(device); }; - virtual DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority ) - { return ::vc_dispmanx_update_start(priority); }; - virtual DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display, - int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src, - const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection, - VC_DISPMANX_ALPHA_T *alpha, - DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform ) - { return ::vc_dispmanx_element_add(update, display, layer, dest_rect, src, src_rect, protection, alpha, clamp, transform); }; - virtual int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update ) - { return ::vc_dispmanx_update_submit_sync(update); }; - virtual int vc_dispmanx_update_submit( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg ) - { return ::vc_dispmanx_update_submit(update, cb_func, cb_arg); }; - virtual int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element ) - { return ::vc_dispmanx_element_remove(update, element); }; - virtual int vc_dispmanx_element_change_attributes( DISPMANX_UPDATE_HANDLE_T update, - DISPMANX_ELEMENT_HANDLE_T element, - uint32_t change_flags, - int32_t layer, - uint8_t opacity, - const VC_RECT_T *dest_rect, - const VC_RECT_T *src_rect, - DISPMANX_RESOURCE_HANDLE_T mask, - DISPMANX_TRANSFORM_T transform ) - { return ::vc_dispmanx_element_change_attributes( update, element, change_flags, layer, opacity, dest_rect, src_rect, mask, transform ); }; - virtual int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display ) - { return ::vc_dispmanx_display_close(display); }; - virtual int vc_dispmanx_display_get_info( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_MODEINFO_T *pinfo ) - { return ::vc_dispmanx_display_get_info(display, pinfo); }; - virtual int vc_dispmanx_display_set_background( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display, - uint8_t red, uint8_t green, uint8_t blue ) - { return ::vc_dispmanx_display_set_background(update, display, red, green, blue); }; - virtual int vc_tv_hdmi_audio_supported(uint32_t audio_format, uint32_t num_channels, - EDID_AudioSampleRate fs, uint32_t bitrate) - { return ::vc_tv_hdmi_audio_supported(audio_format, num_channels, fs, bitrate); }; - virtual bool ResolveExports() - { return true; } - virtual bool Load() - { - CLog::Log(LOGDEBUG, "DllBcm: Using omx system library"); - return true; - } - virtual void Unload() {} -}; -#else -class DllBcmHost : public DllDynamic, DllBcmHostInterface -{ - DECLARE_DLL_WRAPPER(DllBcmHost, "/opt/vc/lib/libbcm_host.so") - - DEFINE_METHOD0(void, bcm_host_init) - DEFINE_METHOD0(void, bcm_host_deinit) - DEFINE_METHOD3(int32_t, graphics_get_display_size, (const uint16_t p1, uint32_t *p2, uint32_t *p3)) - DEFINE_METHOD5(int, vc_tv_hdmi_power_on_best, (uint32_t p1, uint32_t p2, uint32_t p3, - HDMI_INTERLACED_T p4, EDID_MODE_MATCH_FLAG_T p5)) - DEFINE_METHOD5(int, vc_tv_hdmi_power_on_best_3d, (uint32_t p1, uint32_t p2, uint32_t p3, - HDMI_INTERLACED_T p4, EDID_MODE_MATCH_FLAG_T p5)) - DEFINE_METHOD5(int, vc_tv_hdmi_get_supported_modes_new, (HDMI_RES_GROUP_T p1, TV_SUPPORTED_MODE_NEW_T *p2, - uint32_t p3, HDMI_RES_GROUP_T *p4, uint32_t *p5)) - DEFINE_METHOD3(int, vc_tv_hdmi_power_on_explicit_new, (HDMI_MODE_T p1, HDMI_RES_GROUP_T p2, uint32_t p3)) - DEFINE_METHOD1(int, vc_tv_hdmi_set_property, (const HDMI_PROPERTY_PARAM_T *property)) - DEFINE_METHOD1(int, vc_tv_get_display_state, (TV_DISPLAY_STATE_T *p1)) - DEFINE_METHOD1(int, vc_tv_show_info, (uint32_t p1)) - DEFINE_METHOD3(int, vc_gencmd, (char *p1, int p2, const char *p3)) - - DEFINE_METHOD2(void, vc_tv_register_callback, (TVSERVICE_CALLBACK_T p1, void *p2)) - DEFINE_METHOD1(void, vc_tv_unregister_callback, (TVSERVICE_CALLBACK_T p1)) - - DEFINE_METHOD2(void, vc_cec_register_callback, (CECSERVICE_CALLBACK_T p1, void *p2)) - //DEFINE_METHOD1(void, vc_cec_unregister_callback, (CECSERVICE_CALLBACK_T p1)) - DEFINE_METHOD1(DISPMANX_DISPLAY_HANDLE_T, vc_dispmanx_display_open, (uint32_t p1 )) - DEFINE_METHOD1(DISPMANX_UPDATE_HANDLE_T, vc_dispmanx_update_start, (int32_t p1 )) - DEFINE_METHOD10(DISPMANX_ELEMENT_HANDLE_T, vc_dispmanx_element_add, (DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_DISPLAY_HANDLE_T p2, - int32_t p3, const VC_RECT_T *p4, DISPMANX_RESOURCE_HANDLE_T p5, - const VC_RECT_T *p6, DISPMANX_PROTECTION_T p7, - VC_DISPMANX_ALPHA_T *p8, - DISPMANX_CLAMP_T *p9, DISPMANX_TRANSFORM_T p10 )) - DEFINE_METHOD1(int, vc_dispmanx_update_submit_sync, (DISPMANX_UPDATE_HANDLE_T p1)) - DEFINE_METHOD3(int, vc_dispmanx_update_submit, (DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_CALLBACK_FUNC_T p2, void *p3)) - DEFINE_METHOD2(int, vc_dispmanx_element_remove, (DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_ELEMENT_HANDLE_T p2)) - DEFINE_METHOD9(int, vc_dispmanx_element_change_attributes, ( DISPMANX_UPDATE_HANDLE_T p1, - DISPMANX_ELEMENT_HANDLE_T p2, - uint32_t p3, - int32_t p4, - uint8_t p5, - const VC_RECT_T *p6, - const VC_RECT_T *p7rect, - DISPMANX_RESOURCE_HANDLE_T p8, - DISPMANX_TRANSFORM_T p9)) - DEFINE_METHOD1(int, vc_dispmanx_display_close, (DISPMANX_DISPLAY_HANDLE_T p1)) - DEFINE_METHOD2(int, vc_dispmanx_display_get_info, (DISPMANX_DISPLAY_HANDLE_T p1, DISPMANX_MODEINFO_T *p2)) - DEFINE_METHOD5(int, vc_dispmanx_display_set_background, ( DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_DISPLAY_HANDLE_T p2, - uint8_t p3, uint8_t p4, uint8_t p5 )) - DEFINE_METHOD4(int, vc_tv_hdmi_audio_supported, (uint32_t p1, uint32_t p2, EDID_AudioSampleRate p3, uint32_t p4)) - - BEGIN_METHOD_RESOLVE() - RESOLVE_METHOD(bcm_host_init) - RESOLVE_METHOD(bcm_host_deinit) - RESOLVE_METHOD(graphics_get_display_size) - RESOLVE_METHOD(vc_tv_hdmi_power_on_best) - RESOLVE_METHOD(vc_tv_hdmi_power_on_best_3d) - RESOLVE_METHOD(vc_tv_hdmi_get_supported_modes_new) - RESOLVE_METHOD(vc_tv_hdmi_power_on_explicit_new) - RESOLVE_METHOD(vc_tv_hdmi_set_property) - RESOLVE_METHOD(vc_tv_get_display_state) - RESOLVE_METHOD(vc_tv_show_info) - RESOLVE_METHOD(vc_gencmd) - RESOLVE_METHOD(vc_tv_register_callback) - RESOLVE_METHOD(vc_tv_unregister_callback) - RESOLVE_METHOD(vc_cec_register_callback) - //RESOLVE_METHOD(vc_cec_unregister_callback) - RESOLVE_METHOD(vc_dispmanx_display_open) - RESOLVE_METHOD(vc_dispmanx_update_start) - RESOLVE_METHOD(vc_dispmanx_element_add) - RESOLVE_METHOD(vc_dispmanx_update_submit_sync) - RESOLVE_METHOD(vc_dispmanx_update_submit) - RESOLVE_METHOD(vc_dispmanx_element_remove) - RESOLVE_METHOD(vc_dispmanx_element_change_attributes) - RESOLVE_METHOD(vc_dispmanx_display_close) - RESOLVE_METHOD(vc_dispmanx_display_get_info) - RESOLVE_METHOD(vc_dispmanx_display_set_background) - RESOLVE_METHOD(vc_tv_hdmi_audio_supported) - END_METHOD_RESOLVE() - -public: - virtual bool Load() - { - return DllDynamic::Load(); - } -}; -#endif diff --git a/xbmc/platform/linux/DllOMX.h b/xbmc/platform/linux/DllOMX.h deleted file mode 100644 index 7643796827..0000000000 --- a/xbmc/platform/linux/DllOMX.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#ifndef __GNUC__ -#pragma warning(push) -#pragma warning(disable:4244) -#endif - -#include "DynamicDll.h" -#include "utils/log.h" - -#include <IL/OMX_Core.h> -#include <IL/OMX_Component.h> -#include <IL/OMX_Index.h> -#include <IL/OMX_Image.h> -#include <IL/OMX_Video.h> -#include <IL/OMX_Broadcom.h> - -//////////////////////////////////////////////////////////////////////////////////////////// - -class DllOMXInterface -{ -public: - virtual ~DllOMXInterface() {} - - 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; - virtual OMX_ERRORTYPE OMX_SetupTunnel(OMX_HANDLETYPE hOutput, OMX_U32 nPortOutput, OMX_HANDLETYPE hInput, OMX_U32 nPortInput) = 0; - -}; - -#if (defined USE_EXTERNAL_OMX) -class DllOMX : public DllDynamic, DllOMXInterface -{ -public: - virtual OMX_ERRORTYPE OMX_Init(void) - { return ::OMX_Init(); }; - virtual OMX_ERRORTYPE OMX_Deinit(void) - { return ::OMX_Deinit(); }; - virtual OMX_ERRORTYPE OMX_GetHandle(OMX_HANDLETYPE *pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE *pCallBacks) - { return ::OMX_GetHandle(pHandle, cComponentName, pAppData, pCallBacks); }; - virtual OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent) - { return ::OMX_FreeHandle(hComponent); }; - virtual OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_STRING role, OMX_U32 *pNumComps, OMX_U8 **compNames) - { return ::OMX_GetComponentsOfRole(role, pNumComps, compNames); }; - virtual OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_STRING compName, OMX_U32 *pNumRoles, OMX_U8 **roles) - { return ::OMX_GetRolesOfComponent(compName, pNumRoles, roles); }; - virtual OMX_ERRORTYPE OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex) - { return ::OMX_ComponentNameEnum(cComponentName, nNameLength, nIndex); }; - virtual OMX_ERRORTYPE OMX_SetupTunnel(OMX_HANDLETYPE hOutput, OMX_U32 nPortOutput, OMX_HANDLETYPE hInput, OMX_U32 nPortInput) - { return ::OMX_SetupTunnel(hOutput, nPortOutput, hInput, nPortInput); }; - virtual bool ResolveExports() - { return true; } - virtual bool Load() - { - CLog::Log(LOGDEBUG, "DllOMX: Using omx system library"); - return true; - } - virtual void Unload() {} -}; -#else -class DllOMX : public DllDynamic, DllOMXInterface -{ - DECLARE_DLL_WRAPPER(DllOMX, "libopenmaxil.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)) - DEFINE_METHOD4(OMX_ERRORTYPE, OMX_SetupTunnel, (OMX_HANDLETYPE p1, OMX_U32 p2, OMX_HANDLETYPE p3, OMX_U32 p4)); - 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) - RESOLVE_METHOD(OMX_SetupTunnel) - END_METHOD_RESOLVE() - -public: - virtual bool Load() - { - return DllDynamic::Load(); - } -}; -#endif diff --git a/xbmc/platform/linux/OMXCore.cpp b/xbmc/platform/linux/OMXCore.cpp deleted file mode 100644 index b2eb3acf45..0000000000 --- a/xbmc/platform/linux/OMXCore.cpp +++ /dev/null @@ -1,1792 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "OMXCore.h" - -#include "utils/log.h" - -#include "platform/linux/RBP.h" - -#include <cassert> -#include <math.h> - -#include <sys/time.h> - -//#define OMX_DEBUG_EVENTS -//#define OMX_DEBUG_EVENTHANDLER - -//////////////////////////////////////////////////////////////////////////////////////////// -#define CLASSNAME "COMXCoreComponent" -//////////////////////////////////////////////////////////////////////////////////////////// - -static void add_timespecs(struct timespec &time, long millisecs) -{ - long long nsec = time.tv_nsec + (long long)millisecs * 1000000; - while (nsec > 1000000000) - { - time.tv_sec += 1; - nsec -= 1000000000; - } - time.tv_nsec = nsec; -} - - -COMXCoreTunnel::COMXCoreTunnel() -{ - m_src_component = NULL; - m_dst_component = NULL; - m_src_port = 0; - m_dst_port = 0; - m_tunnel_set = false; - m_DllOMX = g_RBP.GetDllOMX(); -} - -COMXCoreTunnel::~COMXCoreTunnel() -{ -} - -void COMXCoreTunnel::Initialize(COMXCoreComponent *src_component, unsigned int src_port, COMXCoreComponent *dst_component, unsigned int dst_port) -{ - m_src_component = src_component; - m_src_port = src_port; - m_dst_component = dst_component; - m_dst_port = dst_port; -} - -OMX_ERRORTYPE COMXCoreTunnel::Deestablish(bool noWait) -{ - if(!m_src_component || !m_dst_component || !IsInitialized()) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(m_src_component->GetComponent()) - { - omx_err = m_src_component->DisablePort(m_src_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Deestablish - Error disable port %d on component %s omx_err(0x%08x)", - m_src_port, m_src_component->GetName().c_str(), (int)omx_err); - } - } - - if(m_dst_component->GetComponent()) - { - omx_err = m_dst_component->DisablePort(m_dst_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Deestablish - Error disable port %d on component %s omx_err(0x%08x)", - m_dst_port, m_dst_component->GetName().c_str(), (int)omx_err); - } - } - - if(m_src_component->GetComponent()) - { - omx_err = m_src_component->WaitForCommand(OMX_CommandPortDisable, m_src_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Deestablish - Error WaitForCommand port %d on component %s omx_err(0x%08x)", - m_dst_port, m_src_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_dst_component->GetComponent()) - { - omx_err = m_dst_component->WaitForCommand(OMX_CommandPortDisable, m_dst_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Deestablish - Error WaitForCommand port %d on component %s omx_err(0x%08x)", - m_dst_port, m_dst_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_src_component->GetComponent()) - { - omx_err = m_DllOMX->OMX_SetupTunnel(m_src_component->GetComponent(), m_src_port, NULL, 0); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreTunnel::Deestablish - could not unset tunnel on comp src %s port %d " - "omx_err(0x%08x)", - m_src_component->GetName().c_str(), m_src_port, (int)omx_err); - } - } - - if(m_dst_component->GetComponent()) - { - omx_err = m_DllOMX->OMX_SetupTunnel(m_dst_component->GetComponent(), m_dst_port, NULL, 0); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreTunnel::Deestablish - could not unset tunnel on comp dst %s port %d " - "omx_err(0x%08x)", - m_dst_component->GetName().c_str(), m_dst_port, (int)omx_err); - } - } - - m_tunnel_set = false; - - return OMX_ErrorNone; -} - -OMX_ERRORTYPE COMXCoreTunnel::Establish(bool enable_ports /* = true */, bool disable_ports /* = false */) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_PARAM_U32TYPE param; - OMX_INIT_STRUCTURE(param); - - if(!m_src_component || !m_dst_component) - { - return OMX_ErrorUndefined; - } - - if(m_src_component->GetState() == OMX_StateLoaded) - { - omx_err = m_src_component->SetStateForComponent(OMX_StateIdle); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error setting state to idle %s omx_err(0x%08x)", - m_src_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_src_component->GetComponent() && disable_ports) - { - omx_err = m_src_component->DisablePort(m_src_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error disable port %d on component %s omx_err(0x%08x)", - m_src_port, m_src_component->GetName().c_str(), (int)omx_err); - } - } - - if(m_dst_component->GetComponent() && disable_ports) - { - omx_err = m_dst_component->DisablePort(m_dst_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error disable port %d on component %s omx_err(0x%08x)", - m_dst_port, m_dst_component->GetName().c_str(), (int)omx_err); - } - } - - if(m_src_component->GetComponent() && disable_ports) - { - omx_err = m_src_component->WaitForCommand(OMX_CommandPortDisable, m_src_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error WaitForCommand port %d on component %s omx_err(0x%08x)", - m_dst_port, m_src_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_dst_component->GetComponent() && disable_ports) - { - omx_err = m_dst_component->WaitForCommand(OMX_CommandPortDisable, m_dst_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error WaitForCommand port %d on component %s omx_err(0x%08x)", - m_dst_port, m_dst_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_src_component->GetComponent() && m_dst_component->GetComponent()) - { - omx_err = m_DllOMX->OMX_SetupTunnel(m_src_component->GetComponent(), m_src_port, m_dst_component->GetComponent(), m_dst_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreTunnel::Establish - could not setup tunnel src %s port %d dst %s port %d " - "omx_err(0x%08x)", - m_src_component->GetName().c_str(), m_src_port, m_dst_component->GetName().c_str(), - m_dst_port, (int)omx_err); - return omx_err; - } - } - else - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - could not setup tunnel"); - return OMX_ErrorUndefined; - } - - m_tunnel_set = true; - - if(m_src_component->GetComponent() && enable_ports) - { - omx_err = m_src_component->EnablePort(m_src_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error enable port %d on component %s omx_err(0x%08x)", - m_src_port, m_src_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_dst_component->GetComponent() && enable_ports) - { - omx_err = m_dst_component->EnablePort(m_dst_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreTunnel::Establish - Error enable port %d on component %s omx_err(0x%08x)", - m_dst_port, m_dst_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - - if(m_dst_component->GetComponent() && enable_ports) - { - omx_err = m_dst_component->WaitForCommand(OMX_CommandPortEnable, m_dst_port); - if(omx_err != OMX_ErrorNone) - { - return omx_err; - } - - if(m_dst_component->GetState() == OMX_StateLoaded) - { - omx_err = m_dst_component->SetStateForComponent(OMX_StateIdle); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::Establish - Error setting state to idle %s omx_err(0x%08x)", - m_src_component->GetName().c_str(), (int)omx_err); - return omx_err; - } - } - } - - if(m_src_component->GetComponent() && enable_ports) - { - omx_err = m_src_component->WaitForCommand(OMX_CommandPortEnable, m_src_port); - if(omx_err != OMX_ErrorNone) - { - return omx_err; - } - } - - return OMX_ErrorNone; -} - -//////////////////////////////////////////////////////////////////////////////////////////// - -COMXCoreComponent::COMXCoreComponent() -{ - m_input_port = 0; - m_output_port = 0; - m_handle = NULL; - - m_input_alignment = 0; - m_input_buffer_size = 0; - m_input_buffer_count = 0; - - m_output_alignment = 0; - m_output_buffer_size = 0; - m_output_buffer_count = 0; - m_flush_input = false; - m_flush_output = false; - m_resource_error = false; - - m_eos = false; - - m_exit = false; - - m_omx_events.clear(); - m_ignore_error = OMX_ErrorNone; - - pthread_mutex_init(&m_omx_input_mutex, NULL); - pthread_mutex_init(&m_omx_output_mutex, NULL); - pthread_mutex_init(&m_omx_event_mutex, NULL); - pthread_mutex_init(&m_omx_eos_mutex, NULL); - pthread_cond_init(&m_input_buffer_cond, NULL); - pthread_cond_init(&m_output_buffer_cond, NULL); - pthread_cond_init(&m_omx_event_cond, NULL); - - m_DllOMX = g_RBP.GetDllOMX(); -} - -COMXCoreComponent::~COMXCoreComponent() -{ - Deinitialize(); - - pthread_mutex_destroy(&m_omx_input_mutex); - pthread_mutex_destroy(&m_omx_output_mutex); - pthread_mutex_destroy(&m_omx_event_mutex); - pthread_mutex_destroy(&m_omx_eos_mutex); - pthread_cond_destroy(&m_input_buffer_cond); - pthread_cond_destroy(&m_output_buffer_cond); - pthread_cond_destroy(&m_omx_event_cond); -} - -void COMXCoreComponent::TransitionToStateLoaded() -{ - if(!m_handle) - return; - - if(GetState() != OMX_StateLoaded && GetState() != OMX_StateIdle) - SetStateForComponent(OMX_StateIdle); - - if(GetState() != OMX_StateLoaded) - SetStateForComponent(OMX_StateLoaded); -} - -OMX_ERRORTYPE COMXCoreComponent::EmptyThisBuffer(OMX_BUFFERHEADERTYPE *omx_buffer) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "COMXCoreComponent::EmptyThisBuffer component(%s) %p", - m_componentName.c_str(), omx_buffer); -#endif - if(!m_handle || !omx_buffer) - return OMX_ErrorUndefined; - - omx_err = OMX_EmptyThisBuffer(m_handle, omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::EmptyThisBuffer component(%s) - failed with result(0x%x)", - m_componentName.c_str(), omx_err); - } - - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::FillThisBuffer(OMX_BUFFERHEADERTYPE *omx_buffer) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "COMXCoreComponent::FillThisBuffer component(%s) %p", m_componentName.c_str(), - omx_buffer); -#endif - if(!m_handle || !omx_buffer) - return OMX_ErrorUndefined; - - omx_err = OMX_FillThisBuffer(m_handle, omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::FillThisBuffer component(%s) - failed with result(0x%x)", - m_componentName.c_str(), omx_err); - } - - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::FreeOutputBuffer(OMX_BUFFERHEADERTYPE *omx_buffer) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle || !omx_buffer) - return OMX_ErrorUndefined; - - omx_err = OMX_FreeBuffer(m_handle, m_output_port, omx_buffer); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::FreeOutputBuffer component(%s) - failed with result(0x%x)", - m_componentName.c_str(), omx_err); - } - - return omx_err; -} - -void COMXCoreComponent::FlushAll() -{ - FlushInput(); - FlushOutput(); -} - -void COMXCoreComponent::FlushInput() -{ - if(!m_handle || m_resource_error) - return; - - OMX_ERRORTYPE omx_err = OMX_SendCommand(m_handle, OMX_CommandFlush, m_input_port, NULL); - - if(omx_err != OMX_ErrorNone) - { - 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); -} - -void COMXCoreComponent::FlushOutput() -{ - if(!m_handle || m_resource_error) - return; - - OMX_ERRORTYPE omx_err = OMX_SendCommand(m_handle, OMX_CommandFlush, m_output_port, NULL); - - if(omx_err != OMX_ErrorNone) - { - 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); -} - -// timeout in milliseconds -OMX_BUFFERHEADERTYPE *COMXCoreComponent::GetInputBuffer(long timeout /*=200*/) -{ - OMX_BUFFERHEADERTYPE *omx_input_buffer = NULL; - - if(!m_handle) - return NULL; - - pthread_mutex_lock(&m_omx_input_mutex); - struct timespec endtime; - clock_gettime(CLOCK_REALTIME, &endtime); - add_timespecs(endtime, timeout); - while (!m_flush_input) - { - if (m_resource_error) - break; - if(!m_omx_input_available.empty()) - { - omx_input_buffer = m_omx_input_available.front(); - m_omx_input_available.pop(); - break; - } - - int retcode = pthread_cond_timedwait(&m_input_buffer_cond, &m_omx_input_mutex, &endtime); - if (retcode != 0) { - if (timeout != 0) - CLog::Log(LOGERROR, "COMXCoreComponent::GetInputBuffer %s wait event timeout", - m_componentName.c_str()); - break; - } - } - pthread_mutex_unlock(&m_omx_input_mutex); - return omx_input_buffer; -} - -OMX_BUFFERHEADERTYPE *COMXCoreComponent::GetOutputBuffer(long timeout /*=200*/) -{ - OMX_BUFFERHEADERTYPE *omx_output_buffer = NULL; - - if(!m_handle) - return NULL; - - pthread_mutex_lock(&m_omx_output_mutex); - struct timespec endtime; - clock_gettime(CLOCK_REALTIME, &endtime); - add_timespecs(endtime, timeout); - while (!m_flush_output) - { - if (m_resource_error) - break; - if(!m_omx_output_available.empty()) - { - omx_output_buffer = m_omx_output_available.front(); - m_omx_output_available.pop(); - break; - } - - int retcode = pthread_cond_timedwait(&m_output_buffer_cond, &m_omx_output_mutex, &endtime); - if (retcode != 0) { - CLog::Log(LOGERROR, "COMXCoreComponent::GetOutputBuffer %s wait event timeout", - m_componentName.c_str()); - break; - } - } - pthread_mutex_unlock(&m_omx_output_mutex); - - return omx_output_buffer; -} - - -OMX_ERRORTYPE COMXCoreComponent::WaitForInputDone(long timeout /*=200*/) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - pthread_mutex_lock(&m_omx_input_mutex); - struct timespec endtime; - clock_gettime(CLOCK_REALTIME, &endtime); - add_timespecs(endtime, timeout); - while (m_input_buffer_count != m_omx_input_available.size()) - { - if (m_resource_error) - break; - int retcode = pthread_cond_timedwait(&m_input_buffer_cond, &m_omx_input_mutex, &endtime); - if (retcode != 0) { - if (timeout != 0) - CLog::Log(LOGERROR, "COMXCoreComponent::WaitForInputDone %s wait event timeout", - m_componentName.c_str()); - omx_err = OMX_ErrorTimeout; - break; - } - } - pthread_mutex_unlock(&m_omx_input_mutex); - return omx_err; -} - - -OMX_ERRORTYPE COMXCoreComponent::WaitForOutputDone(long timeout /*=200*/) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - pthread_mutex_lock(&m_omx_output_mutex); - struct timespec endtime; - clock_gettime(CLOCK_REALTIME, &endtime); - add_timespecs(endtime, timeout); - while (m_output_buffer_count != m_omx_output_available.size()) - { - if (m_resource_error) - break; - int retcode = pthread_cond_timedwait(&m_output_buffer_cond, &m_omx_output_mutex, &endtime); - if (retcode != 0) { - if (timeout != 0) - CLog::Log(LOGERROR, "COMXCoreComponent::WaitForOutputDone %s wait event timeout", - m_componentName.c_str()); - omx_err = OMX_ErrorTimeout; - break; - } - } - pthread_mutex_unlock(&m_omx_output_mutex); - return omx_err; -} - - -OMX_ERRORTYPE COMXCoreComponent::AllocInputBuffers() -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_PARAM_PORTDEFINITIONTYPE portFormat; - OMX_INIT_STRUCTURE(portFormat); - portFormat.nPortIndex = m_input_port; - - omx_err = OMX_GetParameter(m_handle, OMX_IndexParamPortDefinition, &portFormat); - if(omx_err != OMX_ErrorNone) - return omx_err; - - if(GetState() != OMX_StateIdle) - { - if(GetState() != OMX_StateLoaded) - SetStateForComponent(OMX_StateLoaded); - - SetStateForComponent(OMX_StateIdle); - } - - omx_err = EnablePort(m_input_port, false); - if(omx_err != OMX_ErrorNone) - return omx_err; - - m_input_alignment = portFormat.nBufferAlignment; - m_input_buffer_count = portFormat.nBufferCountActual; - m_input_buffer_size = portFormat.nBufferSize; - - CLog::Log(LOGDEBUG, - "COMXCoreComponent::AllocInputBuffers component(%s) - port(%d), nBufferCountMin(%u), " - "nBufferCountActual(%u), nBufferSize(%u), nBufferAlignment(%u)", - m_componentName.c_str(), GetInputPort(), portFormat.nBufferCountMin, - portFormat.nBufferCountActual, portFormat.nBufferSize, portFormat.nBufferAlignment); - - for (size_t i = 0; i < portFormat.nBufferCountActual; i++) - { - OMX_BUFFERHEADERTYPE *buffer = NULL; - - omx_err = OMX_AllocateBuffer(m_handle, &buffer, m_input_port, NULL, portFormat.nBufferSize); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::AllocInputBuffers component(%s) - OMX_UseBuffer failed with " - "omx_err(0x%x)", - m_componentName.c_str(), omx_err); - return omx_err; - } - buffer->nInputPortIndex = m_input_port; - buffer->nFilledLen = 0; - buffer->nOffset = 0; - buffer->pAppPrivate = (void*)i; - m_omx_input_buffers.push_back(buffer); - m_omx_input_available.push(buffer); - } - - omx_err = WaitForCommand(OMX_CommandPortEnable, m_input_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::AllocInputBuffers WaitForCommand:OMX_CommandPortEnable failed on " - "%s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - return omx_err; - } - - m_flush_input = false; - - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::AllocOutputBuffers() -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_PARAM_PORTDEFINITIONTYPE portFormat; - OMX_INIT_STRUCTURE(portFormat); - portFormat.nPortIndex = m_output_port; - - omx_err = OMX_GetParameter(m_handle, OMX_IndexParamPortDefinition, &portFormat); - if(omx_err != OMX_ErrorNone) - return omx_err; - - if(GetState() != OMX_StateIdle) - { - if(GetState() != OMX_StateLoaded) - SetStateForComponent(OMX_StateLoaded); - - SetStateForComponent(OMX_StateIdle); - } - - omx_err = EnablePort(m_output_port, false); - if(omx_err != OMX_ErrorNone) - return omx_err; - - m_output_alignment = portFormat.nBufferAlignment; - m_output_buffer_count = portFormat.nBufferCountActual; - m_output_buffer_size = portFormat.nBufferSize; - - CLog::Log(LOGDEBUG, - "COMXCoreComponent::AllocOutputBuffers component(%s) - port(%d), nBufferCountMin(%u), " - "nBufferCountActual(%u), nBufferSize(%u) nBufferAlignment(%u)", - m_componentName.c_str(), m_output_port, portFormat.nBufferCountMin, - portFormat.nBufferCountActual, portFormat.nBufferSize, portFormat.nBufferAlignment); - - for (size_t i = 0; i < portFormat.nBufferCountActual; i++) - { - OMX_BUFFERHEADERTYPE *buffer = NULL; - - omx_err = OMX_AllocateBuffer(m_handle, &buffer, m_output_port, NULL, portFormat.nBufferSize); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::AllocOutputBuffers component(%s) - OMX_UseBuffer failed with " - "omx_err(0x%x)", - m_componentName.c_str(), omx_err); - return omx_err; - } - buffer->nOutputPortIndex = m_output_port; - buffer->nFilledLen = 0; - buffer->nOffset = 0; - buffer->pAppPrivate = (void*)i; - m_omx_output_buffers.push_back(buffer); - m_omx_output_available.push(buffer); - } - - omx_err = WaitForCommand(OMX_CommandPortEnable, m_output_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::AllocOutputBuffers WaitForCommand:OMX_CommandPortEnable failed " - "on %s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - return omx_err; - } - - m_flush_output = false; - - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::FreeInputBuffers() -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle) - return OMX_ErrorUndefined; - - if(m_omx_input_buffers.empty()) - return OMX_ErrorNone; - - m_flush_input = true; - - omx_err = DisablePort(m_input_port, false); - - pthread_mutex_lock(&m_omx_input_mutex); - pthread_cond_broadcast(&m_input_buffer_cond); - - for (size_t i = 0; i < m_omx_input_buffers.size(); i++) - { - omx_err = OMX_FreeBuffer(m_handle, m_input_port, m_omx_input_buffers[i]); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::FreeInputBuffers error deallocate omx input buffer on " - "component %s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - } - } - pthread_mutex_unlock(&m_omx_input_mutex); - - omx_err = WaitForCommand(OMX_CommandPortDisable, m_input_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::FreeInputBuffers WaitForCommand:OMX_CommandPortDisable failed on " - "%s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - } - - WaitForInputDone(1000); - - pthread_mutex_lock(&m_omx_input_mutex); - assert(m_omx_input_buffers.size() == m_omx_input_available.size()); - - m_omx_input_buffers.clear(); - - while (!m_omx_input_available.empty()) - m_omx_input_available.pop(); - - m_input_alignment = 0; - m_input_buffer_size = 0; - m_input_buffer_count = 0; - - pthread_mutex_unlock(&m_omx_input_mutex); - - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::FreeOutputBuffers() -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle) - return OMX_ErrorUndefined; - - if(m_omx_output_buffers.empty()) - return OMX_ErrorNone; - - m_flush_output = true; - - omx_err = DisablePort(m_output_port, false); - - pthread_mutex_lock(&m_omx_output_mutex); - pthread_cond_broadcast(&m_output_buffer_cond); - - for (size_t i = 0; i < m_omx_output_buffers.size(); i++) - { - omx_err = OMX_FreeBuffer(m_handle, m_output_port, m_omx_output_buffers[i]); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::FreeOutputBuffers error deallocate omx output buffer on " - "component %s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - } - } - pthread_mutex_unlock(&m_omx_output_mutex); - - omx_err = WaitForCommand(OMX_CommandPortDisable, m_output_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::FreeOutputBuffers WaitForCommand:OMX_CommandPortDisable failed " - "on %s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - } - - WaitForOutputDone(1000); - - pthread_mutex_lock(&m_omx_output_mutex); - assert(m_omx_output_buffers.size() == m_omx_output_available.size()); - - m_omx_output_buffers.clear(); - - while (!m_omx_output_available.empty()) - m_omx_output_available.pop(); - - m_output_alignment = 0; - m_output_buffer_size = 0; - m_output_buffer_count = 0; - - pthread_mutex_unlock(&m_omx_output_mutex); - - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::DisableAllPorts() -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - OMX_INDEXTYPE idxTypes[] = { - OMX_IndexParamAudioInit, - OMX_IndexParamImageInit, - OMX_IndexParamVideoInit, - OMX_IndexParamOtherInit - }; - - OMX_PORT_PARAM_TYPE ports; - OMX_INIT_STRUCTURE(ports); - - int i; - for(i=0; i < 4; i++) - { - omx_err = OMX_GetParameter(m_handle, idxTypes[i], &ports); - if(omx_err == OMX_ErrorNone) { - - uint32_t j; - for(j=0; j<ports.nPorts; j++) - { - OMX_PARAM_PORTDEFINITIONTYPE portFormat; - OMX_INIT_STRUCTURE(portFormat); - portFormat.nPortIndex = ports.nStartPortNumber+j; - - omx_err = OMX_GetParameter(m_handle, OMX_IndexParamPortDefinition, &portFormat); - if(omx_err != OMX_ErrorNone) - { - if(portFormat.bEnabled == OMX_FALSE) - continue; - } - - omx_err = OMX_SendCommand(m_handle, OMX_CommandPortDisable, ports.nStartPortNumber+j, NULL); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::DisableAllPorts - Error disable port %d on component %s omx_err(0x%08x)", - (int)(ports.nStartPortNumber) + j, m_componentName.c_str(), (int)omx_err); - } - omx_err = WaitForCommand(OMX_CommandPortDisable, ports.nStartPortNumber+j); - if(omx_err != OMX_ErrorNone && omx_err != OMX_ErrorSameState) - return omx_err; - } - } - } - - return OMX_ErrorNone; -} - -void COMXCoreComponent::RemoveEvent(OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2) -{ - for (std::vector<omx_event>::iterator it = m_omx_events.begin(); it != m_omx_events.end(); ) - { - omx_event event = *it; - - if(event.eEvent == eEvent && event.nData1 == nData1 && event.nData2 == nData2) - { - it = m_omx_events.erase(it); - continue; - } - ++it; - } -} - -OMX_ERRORTYPE COMXCoreComponent::AddEvent(OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2) -{ - omx_event event; - - event.eEvent = eEvent; - event.nData1 = nData1; - event.nData2 = nData2; - - pthread_mutex_lock(&m_omx_event_mutex); - RemoveEvent(eEvent, nData1, nData2); - m_omx_events.push_back(event); - // this allows (all) blocked tasks to be awoken - pthread_cond_broadcast(&m_omx_event_cond); - pthread_mutex_unlock(&m_omx_event_mutex); - -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::AddEvent %s add event event.eEvent 0x%08x event.nData1 0x%08x " - "event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - - return OMX_ErrorNone; -} - -// timeout in milliseconds -OMX_ERRORTYPE COMXCoreComponent::WaitForEvent(OMX_EVENTTYPE eventType, long timeout) -{ -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, "COMXCoreComponent::WaitForEvent %s wait event 0x%08x", - m_componentName.c_str(), (int)eventType); -#endif - - pthread_mutex_lock(&m_omx_event_mutex); - struct timespec endtime; - clock_gettime(CLOCK_REALTIME, &endtime); - add_timespecs(endtime, timeout); - while(true) - { - for (std::vector<omx_event>::iterator it = m_omx_events.begin(); it != m_omx_events.end(); ++it) - { - omx_event event = *it; - -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForEvent %s inlist event event.eEvent 0x%08x event.nData1 " - "0x%08x event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - - - if(event.eEvent == OMX_EventError && event.nData1 == (OMX_U32)OMX_ErrorSameState && event.nData2 == 1) - { -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForEvent %s remove event event.eEvent 0x%08x " - "event.nData1 0x%08x event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - m_omx_events.erase(it); - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorNone; - } - else if(event.eEvent == OMX_EventError) - { - m_omx_events.erase(it); - pthread_mutex_unlock(&m_omx_event_mutex); - return (OMX_ERRORTYPE)event.nData1; - } - else if(event.eEvent == eventType) - { -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForEvent %s remove event event.eEvent 0x%08x " - "event.nData1 0x%08x event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - - m_omx_events.erase(it); - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorNone; - } - } - - if (m_resource_error) - break; - int retcode = pthread_cond_timedwait(&m_omx_event_cond, &m_omx_event_mutex, &endtime); - if (retcode != 0) - { - if (timeout > 0) - CLog::Log(LOGERROR, "COMXCoreComponent::WaitForEvent %s wait event 0x%08x timeout %ld", - m_componentName.c_str(), (int)eventType, timeout); - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorTimeout; - } - } - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorNone; -} - -// timeout in milliseconds -OMX_ERRORTYPE COMXCoreComponent::WaitForCommand(OMX_U32 command, OMX_U32 nData2, long timeout) -{ -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForCommand %s wait event.eEvent 0x%08x event.command 0x%08x " - "event.nData2 %d", - m_componentName.c_str(), (int)OMX_EventCmdComplete, (int)command, (int)nData2); -#endif - - pthread_mutex_lock(&m_omx_event_mutex); - struct timespec endtime; - clock_gettime(CLOCK_REALTIME, &endtime); - add_timespecs(endtime, timeout); - while(true) - { - for (std::vector<omx_event>::iterator it = m_omx_events.begin(); it != m_omx_events.end(); ++it) - { - omx_event event = *it; - -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForCommand %s inlist event event.eEvent 0x%08x " - "event.nData1 0x%08x event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - if(event.eEvent == OMX_EventError && event.nData1 == (OMX_U32)OMX_ErrorSameState && event.nData2 == 1) - { -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForCommand %s remove event event.eEvent 0x%08x " - "event.nData1 0x%08x event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - - m_omx_events.erase(it); - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorNone; - } - else if(event.eEvent == OMX_EventError) - { - m_omx_events.erase(it); - pthread_mutex_unlock(&m_omx_event_mutex); - return (OMX_ERRORTYPE)event.nData1; - } - else if(event.eEvent == OMX_EventCmdComplete && event.nData1 == command && event.nData2 == nData2) - { - -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::WaitForCommand %s remove event event.eEvent 0x%08x " - "event.nData1 0x%08x event.nData2 %d", - m_componentName.c_str(), (int)event.eEvent, (int)event.nData1, (int)event.nData2); -#endif - - m_omx_events.erase(it); - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorNone; - } - } - - if (m_resource_error) - break; - int retcode = pthread_cond_timedwait(&m_omx_event_cond, &m_omx_event_mutex, &endtime); - if (retcode != 0) { - CLog::Log(LOGERROR, - "COMXCoreComponent::WaitForCommand %s wait timeout event.eEvent 0x%08x " - "event.command 0x%08x event.nData2 %d", - m_componentName.c_str(), (int)OMX_EventCmdComplete, (int)command, (int)nData2); - - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorTimeout; - } - } - pthread_mutex_unlock(&m_omx_event_mutex); - return OMX_ErrorNone; -} - -OMX_ERRORTYPE COMXCoreComponent::SetStateForComponent(OMX_STATETYPE state) -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - OMX_STATETYPE state_actual = OMX_StateMax; - - if(state == state_actual) - return OMX_ErrorNone; - - omx_err = OMX_SendCommand(m_handle, OMX_CommandStateSet, state, 0); - if (omx_err != OMX_ErrorNone) - { - if(omx_err == OMX_ErrorSameState) - { - CLog::Log(LOGERROR, "COMXCoreComponent::SetStateForComponent - %s same state", - m_componentName.c_str()); - omx_err = OMX_ErrorNone; - } - else - { - CLog::Log(LOGERROR, "COMXCoreComponent::SetStateForComponent - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - } - else - { - omx_err = WaitForCommand(OMX_CommandStateSet, state); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::WaitForCommand - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - } - return omx_err; -} - -OMX_STATETYPE COMXCoreComponent::GetState() const -{ - if(!m_handle) - return (OMX_STATETYPE)0; - - OMX_STATETYPE state; - - OMX_GetState(m_handle, &state); - return state; -} - -OMX_ERRORTYPE COMXCoreComponent::SetParameter(OMX_INDEXTYPE paramIndex, OMX_PTR paramStruct) -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err; - - omx_err = OMX_SetParameter(m_handle, paramIndex, paramStruct); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::SetParameter - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::GetParameter(OMX_INDEXTYPE paramIndex, OMX_PTR paramStruct) const -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err; - - omx_err = OMX_GetParameter(m_handle, paramIndex, paramStruct); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::GetParameter - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::SetConfig(OMX_INDEXTYPE configIndex, OMX_PTR configStruct) -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err; - - omx_err = OMX_SetConfig(m_handle, configIndex, configStruct); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::SetConfig - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::GetConfig(OMX_INDEXTYPE configIndex, OMX_PTR configStruct) const -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err; - - omx_err = OMX_GetConfig(m_handle, configIndex, configStruct); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::GetConfig - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::SendCommand(OMX_COMMANDTYPE cmd, OMX_U32 cmdParam, OMX_PTR cmdParamData) -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_ERRORTYPE omx_err; - - omx_err = OMX_SendCommand(m_handle, cmd, cmdParam, cmdParamData); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::SendCommand - %s failed with omx_err(0x%x)", - m_componentName.c_str(), omx_err); - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::EnablePort(unsigned int port, bool wait) -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_PARAM_PORTDEFINITIONTYPE portFormat; - OMX_INIT_STRUCTURE(portFormat); - portFormat.nPortIndex = port; - - OMX_ERRORTYPE omx_err = OMX_GetParameter(m_handle, OMX_IndexParamPortDefinition, &portFormat); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::EnablePort - Error get port %d status on component %s omx_err(0x%08x)", - port, m_componentName.c_str(), (int)omx_err); - } - - if(portFormat.bEnabled == OMX_FALSE) - { - omx_err = OMX_SendCommand(m_handle, OMX_CommandPortEnable, port, NULL); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::EnablePort - Error enable port %d on component %s omx_err(0x%08x)", - port, m_componentName.c_str(), (int)omx_err); - return omx_err; - } - else - { - if(wait) - omx_err = WaitForCommand(OMX_CommandPortEnable, port); - } - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::DisablePort(unsigned int port, bool wait) -{ - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_PARAM_PORTDEFINITIONTYPE portFormat; - OMX_INIT_STRUCTURE(portFormat); - portFormat.nPortIndex = port; - - OMX_ERRORTYPE omx_err = OMX_GetParameter(m_handle, OMX_IndexParamPortDefinition, &portFormat); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::DisablePort - Error get port %d status on component %s omx_err(0x%08x)", - port, m_componentName.c_str(), (int)omx_err); - } - - if(portFormat.bEnabled == OMX_TRUE) - { - omx_err = OMX_SendCommand(m_handle, OMX_CommandPortDisable, port, NULL); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::DIsablePort - Error disable port %d on component %s omx_err(0x%08x)", - port, m_componentName.c_str(), (int)omx_err); - return omx_err; - } - else - { - if(wait) - omx_err = WaitForCommand(OMX_CommandPortDisable, port); - } - } - return omx_err; -} - -OMX_ERRORTYPE COMXCoreComponent::UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, void* eglImage) -{ - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - - if(!m_handle) - return OMX_ErrorUndefined; - - OMX_PARAM_PORTDEFINITIONTYPE portFormat; - OMX_INIT_STRUCTURE(portFormat); - portFormat.nPortIndex = m_output_port; - - omx_err = OMX_GetParameter(m_handle, OMX_IndexParamPortDefinition, &portFormat); - if(omx_err != OMX_ErrorNone) - return omx_err; - - if(GetState() != OMX_StateIdle) - { - if(GetState() != OMX_StateLoaded) - SetStateForComponent(OMX_StateLoaded); - - SetStateForComponent(OMX_StateIdle); - } - - omx_err = EnablePort(m_output_port, false); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "%s::%s - %s EnablePort failed with omx_err(0x%x)", CLASSNAME, __func__, - m_componentName.c_str(), omx_err); - return omx_err; - } - - m_output_alignment = portFormat.nBufferAlignment; - m_output_buffer_count = portFormat.nBufferCountActual; - m_output_buffer_size = portFormat.nBufferSize; - - if (portFormat.nBufferCountActual != 1) - { - CLog::Log(LOGERROR, "%s::%s - %s nBufferCountActual unexpected %d", CLASSNAME, __func__, - m_componentName.c_str(), portFormat.nBufferCountActual); - return omx_err; - } - - CLog::Log(LOGDEBUG, - "%s::%s component(%s) - port(%d), nBufferCountMin(%u), nBufferCountActual(%u), " - "nBufferSize(%u) nBufferAlignment(%u)", - CLASSNAME, __func__, m_componentName.c_str(), m_output_port, portFormat.nBufferCountMin, - portFormat.nBufferCountActual, portFormat.nBufferSize, portFormat.nBufferAlignment); - - for (size_t i = 0; i < portFormat.nBufferCountActual; i++) - { - 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)", CLASSNAME, __func__, - m_componentName.c_str(), omx_err); - return omx_err; - } - - OMX_BUFFERHEADERTYPE *buffer = *ppBufferHdr; - buffer->nOutputPortIndex = m_output_port; - buffer->nFilledLen = 0; - buffer->nOffset = 0; - buffer->pAppPrivate = (void*)i; - m_omx_output_buffers.push_back(buffer); - m_omx_output_available.push(buffer); - } - - omx_err = WaitForCommand(OMX_CommandPortEnable, m_output_port); - if(omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, " %s::%s - %s EnablePort failed with omx_err(0x%x)", CLASSNAME, __func__, - m_componentName.c_str(), omx_err); - return omx_err; - } - m_flush_output = false; - - return omx_err; -} - -bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEXTYPE index) -{ - OMX_ERRORTYPE omx_err; - - m_input_port = 0; - m_output_port = 0; - m_handle = NULL; - - m_input_alignment = 0; - m_input_buffer_size = 0; - m_input_buffer_count = 0; - - m_output_alignment = 0; - m_output_buffer_size = 0; - m_output_buffer_count = 0; - m_flush_input = false; - m_flush_output = false; - m_resource_error = false; - - m_eos = false; - - m_exit = false; - - m_omx_events.clear(); - m_ignore_error = OMX_ErrorNone; - - m_componentName = component_name; - - m_callbacks.EventHandler = &COMXCoreComponent::DecoderEventHandlerCallback; - m_callbacks.EmptyBufferDone = &COMXCoreComponent::DecoderEmptyBufferDoneCallback; - m_callbacks.FillBufferDone = &COMXCoreComponent::DecoderFillBufferDoneCallback; - - // Get video component handle setting up callbacks, component is in loaded state on return. - if(!m_handle) - { - omx_err = m_DllOMX->OMX_GetHandle(&m_handle, (char*)component_name.c_str(), this, &m_callbacks); - if (!m_handle || omx_err != OMX_ErrorNone) - { - CLog::Log( - LOGERROR, - "COMXCoreComponent::Initialize - could not get component handle for %s omx_err(0x%08x)", - component_name.c_str(), (int)omx_err); - Deinitialize(); - return false; - } - } - - OMX_PORT_PARAM_TYPE port_param; - OMX_INIT_STRUCTURE(port_param); - - omx_err = OMX_GetParameter(m_handle, index, &port_param); - if (omx_err != OMX_ErrorNone) - { - CLog::Log( - LOGERROR, - "COMXCoreComponent::Initialize - could not get port_param for component %s omx_err(0x%08x)", - component_name.c_str(), (int)omx_err); - } - - omx_err = DisableAllPorts(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, - "COMXCoreComponent::Initialize - error disable ports on component %s omx_err(0x%08x)", - component_name.c_str(), (int)omx_err); - } - - m_input_port = port_param.nStartPortNumber; - m_output_port = m_input_port + 1; - - if(m_componentName == "OMX.broadcom.audio_mixer") - { - m_input_port = port_param.nStartPortNumber + 1; - m_output_port = port_param.nStartPortNumber; - } - - if (m_output_port > port_param.nStartPortNumber+port_param.nPorts-1) - m_output_port = port_param.nStartPortNumber+port_param.nPorts-1; - - CLog::Log(LOGDEBUG, "COMXCoreComponent::Initialize %s input port %d output port %d m_handle %p", - m_componentName.c_str(), m_input_port, m_output_port, m_handle); - - m_exit = false; - m_flush_input = false; - m_flush_output = false; - - return true; -} - -void COMXCoreComponent::ResetEos() -{ - pthread_mutex_lock(&m_omx_eos_mutex); - m_eos = false; - pthread_mutex_unlock(&m_omx_eos_mutex); -} - -bool COMXCoreComponent::Deinitialize() -{ - OMX_ERRORTYPE omx_err; - - m_exit = true; - - m_flush_input = true; - m_flush_output = true; - - if(m_handle) - { - FlushAll(); - - FreeOutputBuffers(); - FreeInputBuffers(); - - TransitionToStateLoaded(); - - CLog::Log(LOGDEBUG, "COMXCoreComponent::Deinitialize : %s handle %p", m_componentName.c_str(), - m_handle); - omx_err = m_DllOMX->OMX_FreeHandle(m_handle); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCoreComponent::Deinitialize - failed to free handle for component %s omx_err(0x%08x)", - m_componentName.c_str(), omx_err); - } - m_handle = NULL; - - m_input_port = 0; - m_output_port = 0; - m_componentName = ""; - m_resource_error = false; - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// DecoderEventHandler -- OMX event callback -OMX_ERRORTYPE COMXCoreComponent::DecoderEventHandlerCallback( - OMX_HANDLETYPE hComponent, - OMX_PTR pAppData, - OMX_EVENTTYPE eEvent, - OMX_U32 nData1, - OMX_U32 nData2, - OMX_PTR pEventData) -{ - if(!pAppData) - return OMX_ErrorNone; - - COMXCoreComponent *ctx = static_cast<COMXCoreComponent*>(pAppData); - return ctx->DecoderEventHandler(hComponent, eEvent, nData1, nData2, pEventData); -} - -// DecoderEmptyBufferDone -- OMXCore input buffer has been emptied -OMX_ERRORTYPE COMXCoreComponent::DecoderEmptyBufferDoneCallback( - OMX_HANDLETYPE hComponent, - OMX_PTR pAppData, - OMX_BUFFERHEADERTYPE* pBuffer) -{ - if(!pAppData) - return OMX_ErrorNone; - - COMXCoreComponent *ctx = static_cast<COMXCoreComponent*>(pAppData); - return ctx->DecoderEmptyBufferDone( hComponent, pBuffer); -} - -// DecoderFillBufferDone -- OMXCore output buffer has been filled -OMX_ERRORTYPE COMXCoreComponent::DecoderFillBufferDoneCallback( - OMX_HANDLETYPE hComponent, - OMX_PTR pAppData, - OMX_BUFFERHEADERTYPE* pBuffer) -{ - if(!pAppData) - return OMX_ErrorNone; - - COMXCoreComponent *ctx = static_cast<COMXCoreComponent*>(pAppData); - return ctx->DecoderFillBufferDone(hComponent, pBuffer); -} - -OMX_ERRORTYPE COMXCoreComponent::DecoderEmptyBufferDone(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer) -{ - if(m_exit) - return OMX_ErrorNone; - - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "COMXCoreComponent::DecoderEmptyBufferDone component(%s) %p %d/%d", - m_componentName.c_str(), pBuffer, m_omx_input_available.size(), m_input_buffer_count); -#endif - pthread_mutex_lock(&m_omx_input_mutex); - m_omx_input_available.push(pBuffer); - - // this allows (all) blocked tasks to be awoken - pthread_cond_broadcast(&m_input_buffer_cond); - - pthread_mutex_unlock(&m_omx_input_mutex); - - return OMX_ErrorNone; -} - -OMX_ERRORTYPE COMXCoreComponent::DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer) -{ - if(m_exit) - return OMX_ErrorNone; - - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "COMXCoreComponent::DecoderFillBufferDone component(%s) %p %d/%d", - m_componentName.c_str(), pBuffer, m_omx_output_available.size(), m_output_buffer_count); -#endif - pthread_mutex_lock(&m_omx_output_mutex); - m_omx_output_available.push(pBuffer); - - // this allows (all) blocked tasks to be awoken - pthread_cond_broadcast(&m_output_buffer_cond); - - pthread_mutex_unlock(&m_omx_output_mutex); - - return OMX_ErrorNone; -} - -// DecoderEmptyBufferDone -- OMXCore input buffer has been emptied -//////////////////////////////////////////////////////////////////////////////////////////// -// Component event handler -- OMX event callback -OMX_ERRORTYPE COMXCoreComponent::DecoderEventHandler( - OMX_HANDLETYPE hComponent, - OMX_EVENTTYPE eEvent, - OMX_U32 nData1, - OMX_U32 nData2, - OMX_PTR pEventData) -{ -#ifdef OMX_DEBUG_EVENTS - CLog::Log(LOGDEBUG, - "COMXCoreComponent::%s - %s eEvent(0x%x), nData1(0x%x), nData2(0x%x), pEventData(0x%p)\n", - __func__, GetName().c_str(), eEvent, nData1, nData2, pEventData); -#endif - - // if the error is expected, then we can skip it - if (eEvent == OMX_EventError && (OMX_S32)nData1 == m_ignore_error) - { - CLog::Log(LOGDEBUG, - "COMXCoreComponent::%s - %s Ignoring expected event: eEvent(0x%x), nData1(0x%x), nData2(0x%x), pEventData(0x%p)\n", - __func__, GetName().c_str(), eEvent, nData1, nData2, pEventData); - m_ignore_error = OMX_ErrorNone; - return OMX_ErrorNone; - } - AddEvent(eEvent, nData1, nData2); - - switch (eEvent) - { - case OMX_EventCmdComplete: - - switch(nData1) - { - case OMX_CommandStateSet: - switch ((int)nData2) - { - case OMX_StateInvalid: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_StateInvalid", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - case OMX_StateLoaded: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_StateLoaded", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - case OMX_StateIdle: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_StateIdle", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - case OMX_StateExecuting: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_StateExecuting", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - case OMX_StatePause: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_StatePause", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - case OMX_StateWaitForResources: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_StateWaitForResources", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - default: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, - "%s::%s %s - Unknown OMX_Statexxxxx, state(%d)\n", CLASSNAME, __func__, GetName().c_str(), (int)nData2); - #endif - break; - } - break; - case OMX_CommandFlush: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_CommandFlush, port %d", CLASSNAME, __func__, - GetName().c_str(), (int)nData2); -#endif - break; - case OMX_CommandPortDisable: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_CommandPortDisable, nData1(0x%x), port %d", - CLASSNAME, __func__, GetName().c_str(), nData1, (int)nData2); -#endif - break; - case OMX_CommandPortEnable: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_CommandPortEnable, nData1(0x%x), port %d", CLASSNAME, - __func__, GetName().c_str(), nData1, (int)nData2); -#endif - break; - #if defined(OMX_DEBUG_EVENTHANDLER) - case OMX_CommandMarkBuffer: - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_CommandMarkBuffer, nData1(0x%x), port %d", CLASSNAME, - __func__, GetName().c_str(), nData1, (int)nData2); - break; - #endif - } - break; - case OMX_EventBufferFlag: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_EventBufferFlag(input)", CLASSNAME, __func__, - GetName().c_str()); -#endif - if(nData2 & OMX_BUFFERFLAG_EOS) - { - pthread_mutex_lock(&m_omx_eos_mutex); - m_eos = true; - pthread_mutex_unlock(&m_omx_eos_mutex); - } - break; - case OMX_EventPortSettingsChanged: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_EventPortSettingsChanged(output)", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - case OMX_EventParamOrConfigChanged: - #if defined(OMX_DEBUG_EVENTHANDLER) - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_EventParamOrConfigChanged(output)", CLASSNAME, __func__, - GetName().c_str()); -#endif - break; - #if defined(OMX_DEBUG_EVENTHANDLER) - case OMX_EventMark: - CLog::Log(LOGDEBUG, "%s::%s %s - OMX_EventMark", CLASSNAME, __func__, GetName().c_str()); - break; - case OMX_EventResourcesAcquired: - CLog::Log(LOGDEBUG, "%s::%s %s- OMX_EventResourcesAcquired", CLASSNAME, __func__, - GetName().c_str()); - break; - #endif - case OMX_EventError: - switch((OMX_S32)nData1) - { - case OMX_ErrorSameState: - //#if defined(OMX_DEBUG_EVENTHANDLER) - //CLog::Log(LOGERROR, "%s::%s %s - OMX_ErrorSameState, same state", CLASSNAME, __func__, GetName().c_str()); - //#endif - break; - case OMX_ErrorInsufficientResources: - CLog::Log(LOGERROR, "%s::%s %s - OMX_ErrorInsufficientResources, insufficient resources", - CLASSNAME, __func__, GetName().c_str()); - m_resource_error = true; - break; - case OMX_ErrorFormatNotDetected: - CLog::Log(LOGERROR, "%s::%s %s - OMX_ErrorFormatNotDetected, cannot parse input stream", - CLASSNAME, __func__, GetName().c_str()); - break; - case OMX_ErrorPortUnpopulated: - CLog::Log(LOGWARNING, "%s::%s %s - OMX_ErrorPortUnpopulated port %d", CLASSNAME, __func__, - GetName().c_str(), (int)nData2); - break; - case OMX_ErrorStreamCorrupt: - CLog::Log(LOGERROR, "%s::%s %s - OMX_ErrorStreamCorrupt, Bitstream corrupt", CLASSNAME, - __func__, GetName().c_str()); - m_resource_error = true; - break; - case OMX_ErrorUnsupportedSetting: - CLog::Log(LOGERROR, "%s::%s %s - OMX_ErrorUnsupportedSetting, unsupported setting", - CLASSNAME, __func__, GetName().c_str()); - break; - default: - CLog::Log(LOGERROR, "%s::%s %s - OMX_EventError detected, nData1(0x%x), port %d", - CLASSNAME, __func__, GetName().c_str(), nData1, (int)nData2); - break; - } - // wake things up - if (m_resource_error) - { - pthread_cond_broadcast(&m_output_buffer_cond); - pthread_cond_broadcast(&m_input_buffer_cond); - pthread_cond_broadcast(&m_omx_event_cond); - } - break; - default: - CLog::Log(LOGWARNING, "%s::%s %s - Unknown eEvent(0x%x), nData1(0x%x), port %d", CLASSNAME, - __func__, GetName().c_str(), eEvent, nData1, (int)nData2); - break; - } - - return OMX_ErrorNone; -} - -//////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////// -COMXCore::COMXCore() -{ - m_is_open = false; - - m_DllOMX = new DllOMX(); -} - -COMXCore::~COMXCore() -{ - delete m_DllOMX; -} - -bool COMXCore::Initialize() -{ - if(!m_DllOMX->Load()) - return false; - - OMX_ERRORTYPE omx_err = m_DllOMX->OMX_Init(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCore::Initialize - OMXCore failed to init, omx_err(0x%08x)", omx_err); - return false; - } - - m_is_open = true; - return true; -} - -void COMXCore::Deinitialize() -{ - if(m_is_open) - { - OMX_ERRORTYPE omx_err = m_DllOMX->OMX_Deinit(); - if (omx_err != OMX_ErrorNone) - { - CLog::Log(LOGERROR, "COMXCore::Deinitialize - OMXCore failed to deinit, omx_err(0x%08x)", omx_err); - } - m_DllOMX->Unload(); - } -} diff --git a/xbmc/platform/linux/OMXCore.h b/xbmc/platform/linux/OMXCore.h deleted file mode 100644 index 84d043469b..0000000000 --- a/xbmc/platform/linux/OMXCore.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2010-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include <string> -#include <queue> -#include <vector> - -//! @todo should this be in configure -#ifndef OMX_SKIP64BIT -#define OMX_SKIP64BIT -#endif - -#include "DllOMX.h" - -#include <semaphore.h> - -//////////////////////////////////////////////////////////////////////////////////////////// -// debug spew defines -#if 0 -#define OMX_DEBUG_VERBOSE -#define OMX_DEBUG_EVENTHANDLER -#endif - -#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 - -#define OMX_MAX_PORTS 10 - -typedef struct omx_event { - OMX_EVENTTYPE eEvent; - OMX_U32 nData1; - OMX_U32 nData2; -} omx_event; - -class COMXCore; -class COMXCoreComponent; -class COMXCoreTunnel; -class COMXCoreClock; - -class COMXCoreTunnel -{ -public: - COMXCoreTunnel(); - ~COMXCoreTunnel(); - - void Initialize(COMXCoreComponent *src_component, unsigned int src_port, COMXCoreComponent *dst_component, unsigned int dst_port); - bool IsInitialized() const { return m_tunnel_set; } - OMX_ERRORTYPE Deestablish(bool noWait = false); - OMX_ERRORTYPE Establish(bool enable_ports = true, bool disable_ports = false); -private: - COMXCoreComponent *m_src_component; - COMXCoreComponent *m_dst_component; - unsigned int m_src_port; - unsigned int m_dst_port; - DllOMX *m_DllOMX; - bool m_tunnel_set; -}; - -class COMXCoreComponent -{ -public: - COMXCoreComponent(); - ~COMXCoreComponent(); - - OMX_HANDLETYPE GetComponent() const { return m_handle; } - unsigned int GetInputPort() const { return m_input_port; } - unsigned int GetOutputPort() const { return m_output_port; } - std::string GetName() const { return m_componentName; } - - OMX_ERRORTYPE DisableAllPorts(); - void RemoveEvent(OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2); - OMX_ERRORTYPE AddEvent(OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2); - OMX_ERRORTYPE WaitForEvent(OMX_EVENTTYPE event, long timeout = 300); - OMX_ERRORTYPE WaitForCommand(OMX_U32 command, OMX_U32 nData2, long timeout = 2000); - OMX_ERRORTYPE SetStateForComponent(OMX_STATETYPE state); - OMX_STATETYPE GetState() const; - OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE paramIndex, OMX_PTR paramStruct); - OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE paramIndex, OMX_PTR paramStruct) const; - OMX_ERRORTYPE SetConfig(OMX_INDEXTYPE configIndex, OMX_PTR configStruct); - OMX_ERRORTYPE GetConfig(OMX_INDEXTYPE configIndex, OMX_PTR configStruct) const; - OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE cmd, OMX_U32 cmdParam, OMX_PTR cmdParamData); - OMX_ERRORTYPE EnablePort(unsigned int port, bool wait = true); - 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 IsInitialized() const { return m_handle != NULL; } - bool Deinitialize(); - - // OMXCore 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); - - // OMXCore decoder callback routines. - OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, - OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData); - OMX_ERRORTYPE DecoderEmptyBufferDone( - OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer); - OMX_ERRORTYPE DecoderFillBufferDone( - OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer); - - void TransitionToStateLoaded(); - - OMX_ERRORTYPE EmptyThisBuffer(OMX_BUFFERHEADERTYPE *omx_buffer); - OMX_ERRORTYPE FillThisBuffer(OMX_BUFFERHEADERTYPE *omx_buffer); - OMX_ERRORTYPE FreeOutputBuffer(OMX_BUFFERHEADERTYPE *omx_buffer); - - unsigned int GetInputBufferSize() const { return m_input_buffer_count * m_input_buffer_size; } - unsigned int GetOutputBufferSize() const { return m_output_buffer_count * m_output_buffer_size; } - - unsigned int GetInputBufferSpace() const { return m_omx_input_available.size() * m_input_buffer_size; } - unsigned int GetOutputBufferSpace() const { return m_omx_output_available.size() * m_output_buffer_size; } - - void FlushAll(); - void FlushInput(); - void FlushOutput(); - - OMX_BUFFERHEADERTYPE *GetInputBuffer(long timeout=200); - OMX_BUFFERHEADERTYPE *GetOutputBuffer(long timeout=200); - - OMX_ERRORTYPE AllocInputBuffers(); - OMX_ERRORTYPE AllocOutputBuffers(); - - OMX_ERRORTYPE FreeInputBuffers(); - OMX_ERRORTYPE FreeOutputBuffers(); - - OMX_ERRORTYPE WaitForInputDone(long timeout=200); - OMX_ERRORTYPE WaitForOutputDone(long timeout=200); - - bool IsEOS() const { return m_eos; } - bool BadState() const { return m_resource_error; } - void ResetEos(); - void IgnoreNextError(OMX_S32 error) { m_ignore_error = error; } - -private: - OMX_HANDLETYPE m_handle; - unsigned int m_input_port; - unsigned int m_output_port; - std::string m_componentName; - pthread_mutex_t m_omx_event_mutex; - pthread_mutex_t m_omx_eos_mutex; - std::vector<omx_event> m_omx_events; - OMX_S32 m_ignore_error; - - OMX_CALLBACKTYPE m_callbacks; - - // OMXCore input buffers (demuxer packets) - pthread_mutex_t m_omx_input_mutex; - std::queue<OMX_BUFFERHEADERTYPE*> m_omx_input_available; - std::vector<OMX_BUFFERHEADERTYPE*> m_omx_input_buffers; - unsigned int m_input_alignment; - unsigned int m_input_buffer_size; - unsigned int m_input_buffer_count; - - // OMXCore output buffers (video frames) - pthread_mutex_t m_omx_output_mutex; - std::queue<OMX_BUFFERHEADERTYPE*> m_omx_output_available; - std::vector<OMX_BUFFERHEADERTYPE*> m_omx_output_buffers; - unsigned int m_output_alignment; - unsigned int m_output_buffer_size; - unsigned int m_output_buffer_count; - - bool m_exit; - DllOMX *m_DllOMX; - pthread_cond_t m_input_buffer_cond; - pthread_cond_t m_output_buffer_cond; - pthread_cond_t m_omx_event_cond; - bool m_eos; - bool m_flush_input; - bool m_flush_output; - bool m_resource_error; -}; - -class COMXCore -{ -public: - COMXCore(); - ~COMXCore(); - - // initialize OMXCore and get decoder component - bool Initialize(); - void Deinitialize(); - DllOMX *GetDll() { return m_DllOMX; } - -protected: - bool m_is_open; - DllOMX *m_DllOMX; -}; diff --git a/xbmc/platform/linux/RBP.cpp b/xbmc/platform/linux/RBP.cpp deleted file mode 100644 index f750fa0656..0000000000 --- a/xbmc/platform/linux/RBP.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "RBP.h" - -#include "ServiceBroker.h" -#include "cores/omxplayer/OMXImage.h" -#include "rpi/rpi_user_vcsm.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "utils/TimeUtils.h" -#include "utils/log.h" - -#include <assert.h> - -#include <interface/mmal/mmal.h> -#include <sys/ioctl.h> - -#define MAJOR_NUM 100 -#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) -#define DEVICE_FILE_NAME "/dev/vcio" - -static int mbox_open(); -static void mbox_close(int file_desc); - -typedef struct vc_image_extra_uv_s { - void *u, *v; - int vpitch; -} VC_IMAGE_EXTRA_UV_T; - -typedef union { - VC_IMAGE_EXTRA_UV_T uv; -} VC_IMAGE_EXTRA_T; - -struct VC_IMAGE_T { - unsigned short type; /* should restrict to 16 bits */ - unsigned short info; /* format-specific info; zero for VC02 behaviour */ - unsigned short width; /* width in pixels */ - unsigned short height; /* height in pixels */ - int pitch; /* pitch of image_data array in bytes */ - int size; /* number of bytes available in image_data array */ - void *image_data; /* pixel data */ - VC_IMAGE_EXTRA_T extra; /* extra data like palette pointer */ - void *metadata; /* metadata header for the image */ - void *pool_object; /* nonNULL if image was allocated from a vc_pool */ - uint32_t mem_handle; /* the mem handle for relocatable memory storage */ - int metadata_size; /* size of metadata of each channel in bytes */ - int channel_offset; /* offset of consecutive channels in bytes */ - uint32_t video_timestamp;/* 90000 Hz RTP times domain - derived from audio timestamp */ - uint8_t num_channels; /* number of channels (2 for stereo) */ - uint8_t current_channel;/* the channel this header is currently pointing to */ - uint8_t linked_multichann_flag;/* Indicate the header has the linked-multichannel structure*/ - uint8_t is_channel_linked; /* Track if the above structure is been used to link the header - into a linked-mulitchannel image */ - uint8_t channel_index; /* index of the channel this header represents while - it is being linked. */ - uint8_t _dummy[3]; /* pad struct to 64 bytes */ -}; -typedef int vc_image_t_size_check[(sizeof(VC_IMAGE_T) == 64) * 2 - 1]; - -CRBP::CRBP() -{ - m_initialized = false; - m_omx_initialized = false; - m_DllBcmHost = new DllBcmHost(); - m_OMX = new COMXCore(); - m_display = DISPMANX_NO_HANDLE; - m_mb = mbox_open(); - vcsm_init(); - m_vsync_count = 0; - m_vsync_time = 0; -} - -CRBP::~CRBP() -{ - Deinitialize(); - delete m_OMX; - delete m_DllBcmHost; -} - -bool CRBP::Initialize() -{ - CSingleLock lock(m_critSection); - if (m_initialized) - return true; - - m_initialized = m_DllBcmHost->Load(); - if(!m_initialized) - return false; - - m_DllBcmHost->bcm_host_init(); - - m_omx_initialized = m_OMX->Initialize(); - if(!m_omx_initialized) - return false; - - char response[80] = ""; - m_arm_mem = 0; - m_gpu_mem = 0; - m_codec_mpg2_enabled = false; - m_codec_wvc1_enabled = false; - - if (vc_gencmd(response, sizeof response, "get_mem arm") == 0) - vc_gencmd_number_property(response, "arm", &m_arm_mem); - if (vc_gencmd(response, sizeof response, "get_mem gpu") == 0) - vc_gencmd_number_property(response, "gpu", &m_gpu_mem); - - if (vc_gencmd(response, sizeof response, "codec_enabled MPG2") == 0) - m_codec_mpg2_enabled = strcmp("MPG2=enabled", response) == 0; - if (vc_gencmd(response, sizeof response, "codec_enabled WVC1") == 0) - m_codec_wvc1_enabled = strcmp("WVC1=enabled", response) == 0; - - if (m_gpu_mem < 128) - setenv("V3D_DOUBLE_BUFFER", "1", 1); - - m_gui_resolution_limit = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt("videoscreen.limitgui"); - if (!m_gui_resolution_limit) - m_gui_resolution_limit = m_gpu_mem < 128 ? 720:1080; - - g_OMXImage.Initialize(); - m_omx_image_init = true; - return true; -} - -void CRBP::LogFirmwareVersion() -{ - char response[1024]; - m_DllBcmHost->vc_gencmd(response, sizeof response, "version"); - response[sizeof(response) - 1] = '\0'; - CLog::Log(LOGINFO, "Raspberry PI firmware version: %s", response); - CLog::Log(LOGINFO, "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(LOGINFO, "Config:\n%s", response); - m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config str"); - response[sizeof(response) - 1] = '\0'; - CLog::Log(LOGINFO, "Config:\n%s", response); -} - -static void vsync_callback_static(DISPMANX_UPDATE_HANDLE_T u, void *arg) -{ - CRBP *rbp = reinterpret_cast<CRBP*>(arg); - rbp->VSyncCallback(); -} - -DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) -{ - CSingleLock lock(m_critSection); - if (m_display == DISPMANX_NO_HANDLE) - { - m_display = vc_dispmanx_display_open( 0 /*screen*/ ); - int s = vc_dispmanx_vsync_callback(m_display, vsync_callback_static, (void *)this); - assert(s == 0); - } - return m_display; -} - -void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display) -{ - CSingleLock lock(m_critSection); - assert(display == m_display); - int s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); - assert(s == 0); - vc_dispmanx_display_close(m_display); - m_display = DISPMANX_NO_HANDLE; -} - -void CRBP::GetDisplaySize(int &width, int &height) -{ - CSingleLock lock(m_critSection); - DISPMANX_MODEINFO_T info; - if (m_display != DISPMANX_NO_HANDLE && vc_dispmanx_display_get_info(m_display, &info) == 0) - { - width = info.width; - height = info.height; - } - else - { - width = 0; - height = 0; - } -} - -unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue, bool video_only) -{ - DISPMANX_RESOURCE_HANDLE_T resource; - VC_RECT_T rect; - unsigned char *image = NULL; - uint32_t vc_image_ptr; - int stride; - uint32_t flags = 0; - - if (video_only) - flags |= DISPMANX_SNAPSHOT_NO_RGB|DISPMANX_SNAPSHOT_FILL; - if (swap_red_blue) - flags |= DISPMANX_SNAPSHOT_SWAP_RED_BLUE; - if (!pstride) - flags |= DISPMANX_SNAPSHOT_PACK; - - stride = ((width + 15) & ~15) * 4; - - CSingleLock lock(m_critSection); - if (m_display != DISPMANX_NO_HANDLE) - { - image = new unsigned char [height * stride]; - resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); - - vc_dispmanx_snapshot(m_display, resource, (DISPMANX_TRANSFORM_T)flags); - - vc_dispmanx_rect_set(&rect, 0, 0, width, height); - vc_dispmanx_resource_read_data(resource, &rect, image, stride); - vc_dispmanx_resource_delete( resource ); - } - if (pstride) - *pstride = stride; - return image; -} - -void CRBP::VSyncCallback() -{ - CSingleLock lock(m_vsync_lock); - m_vsync_count++; - m_vsync_time = CurrentHostCounter(); - m_vsync_cond.notifyAll(); -} - -uint32_t CRBP::WaitVsync(uint32_t target) -{ - CSingleLock vlock(m_vsync_lock); - DISPMANX_DISPLAY_HANDLE_T display = m_display; - XbmcThreads::EndTime delay(50); - if (target == ~0U) - target = m_vsync_count+1; - while (!delay.IsTimePast()) - { - if ((signed)(m_vsync_count - target) >= 0) - break; - if (!m_vsync_cond.wait(vlock, delay.MillisLeft())) - break; - } - if ((signed)(m_vsync_count - target) < 0) - CLog::Log(LOGDEBUG, "CRBP::%s no vsync %d/%d display:%x(%x) delay:%d", __FUNCTION__, m_vsync_count, target, m_display, display, delay.MillisLeft()); - - return m_vsync_count; -} - -uint32_t CRBP::LastVsync(int64_t &time) -{ - CSingleLock lock(m_vsync_lock); - time = m_vsync_time; - return m_vsync_count; -} - -uint32_t CRBP::LastVsync() -{ - int64_t time = 0; - return LastVsync(time); -} - -void CRBP::Deinitialize() -{ - if (m_omx_image_init) - g_OMXImage.Deinitialize(); - - if(m_omx_initialized) - m_OMX->Deinitialize(); - - m_DllBcmHost->bcm_host_deinit(); - - if(m_initialized) - m_DllBcmHost->Unload(); - - m_omx_image_init = false; - m_initialized = false; - m_omx_initialized = false; - if (m_mb) - mbox_close(m_mb); - m_mb = 0; - vcsm_exit(); -} - -static int mbox_property(int file_desc, void *buf) -{ - int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); - - if (ret_val < 0) - { - CLog::Log(LOGERROR, "%s: ioctl_set_msg failed:%d", __FUNCTION__, ret_val); - } - return ret_val; -} - -static int mbox_open() -{ - int file_desc; - - // open a char device file used for communicating with kernel mbox driver - file_desc = open(DEVICE_FILE_NAME, 0); - if (file_desc < 0) - CLog::Log(LOGERROR, "%s: Can't open device file: %s (%d)", __FUNCTION__, DEVICE_FILE_NAME, file_desc); - - return file_desc; -} - -static void mbox_close(int file_desc) -{ - close(file_desc); -} - -static unsigned mem_lock(int file_desc, unsigned handle) -{ - int i=0; - unsigned p[32]; - p[i++] = 0; // size - p[i++] = 0x00000000; // process request - - p[i++] = 0x3000d; // (the tag id) - p[i++] = 4; // (size of the buffer) - p[i++] = 4; // (size of the data) - p[i++] = handle; - - p[i++] = 0x00000000; // end tag - p[0] = i*sizeof *p; // actual size - - mbox_property(file_desc, p); - return p[5]; -} - -static unsigned mem_unlock(int file_desc, unsigned handle) -{ - int i=0; - unsigned p[32]; - p[i++] = 0; // size - p[i++] = 0x00000000; // process request - - p[i++] = 0x3000e; // (the tag id) - p[i++] = 4; // (size of the buffer) - p[i++] = 4; // (size of the data) - p[i++] = handle; - - p[i++] = 0x00000000; // end tag - p[0] = i*sizeof *p; // actual size - - mbox_property(file_desc, p); - return p[5]; -} - - -#define GET_VCIMAGE_PARAMS 0x30044 -static int get_image_params(int file_desc, VC_IMAGE_T * img) -{ - uint32_t buf[sizeof(*img) / sizeof(uint32_t) + 32]; - uint32_t * p = buf; - void * rimg; - int rv; - - *p++ = 0; // size - *p++ = 0; // process request - *p++ = GET_VCIMAGE_PARAMS; - *p++ = sizeof(*img); - *p++ = sizeof(*img); - rimg = p; - memcpy(p, img, sizeof(*img)); - p += sizeof(*img) / sizeof(*p); - *p++ = 0; // End tag - buf[0] = (p - buf) * sizeof(*p); - - rv = mbox_property(file_desc, buf); - memcpy(img, rimg, sizeof(*img)); - - return rv; -} - -CGPUMEM::CGPUMEM(unsigned int numbytes, bool cached) -{ - m_numbytes = numbytes; - m_vcsm_handle = vcsm_malloc_cache(numbytes, static_cast<VCSM_CACHE_TYPE_T>(0x80 | static_cast<unsigned>(cached ? VCSM_CACHE_TYPE_HOST : VCSM_CACHE_TYPE_NONE)), const_cast<char*>("CGPUMEM")); - if (m_vcsm_handle) - m_vc_handle = vcsm_vc_hdl_from_hdl(m_vcsm_handle); - if (m_vc_handle) - m_arm = vcsm_lock(m_vcsm_handle); - if (m_arm) - m_vc = mem_lock(g_RBP.GetMBox(), m_vc_handle); -} - -CGPUMEM::~CGPUMEM() -{ - if (m_vc_handle) - mem_unlock(g_RBP.GetMBox(), m_vc_handle); - if (m_arm) - vcsm_unlock_ptr(m_arm); - if (m_vcsm_handle) - vcsm_free(m_vcsm_handle); -} - -// Call this to clean and invalidate a region of memory -void CGPUMEM::Flush() -{ - struct vcsm_user_clean_invalid_s iocache = {}; - iocache.s[0].handle = m_vcsm_handle; - iocache.s[0].cmd = 3; // clean+invalidate - iocache.s[0].addr = (int) m_arm; - iocache.s[0].size = m_numbytes; - vcsm_clean_invalid( &iocache ); -} - -AVRpiZcFrameGeometry CRBP::GetFrameGeometry(uint32_t encoding, unsigned short video_width, unsigned short video_height) -{ - AVRpiZcFrameGeometry geo; - geo.setStripes(1); - geo.setBitsPerPixel(8); - - switch (encoding) - { - case MMAL_ENCODING_RGBA: case MMAL_ENCODING_BGRA: - geo.setBitsPerPixel(32); - geo.setStrideY(video_width * geo.getBytesPerPixel()); - geo.setHeightY(video_height); - break; - case MMAL_ENCODING_RGB24: case MMAL_ENCODING_BGR24: - geo.setBitsPerPixel(32); - geo.setStrideY(video_width * geo.getBytesPerPixel()); - geo.setHeightY(video_height); - break; - case MMAL_ENCODING_RGB16: case MMAL_ENCODING_BGR16: - geo.setBitsPerPixel(16); - geo.setStrideY(video_width * geo.getBytesPerPixel()); - geo.setHeightY(video_height); - break; - case MMAL_ENCODING_I420: - case MMAL_ENCODING_I420_S: - geo.setStrideY((video_width + 31) & ~31); - geo.setStrideC(geo.getStrideY() >> 1); - geo.setHeightY((video_height + 15) & ~15); - geo.setHeightC(geo.getHeightY() >> 1); - geo.setPlanesC(2); - break; - case MMAL_ENCODING_I420_16: - geo.setBitsPerPixel(10); - geo.setStrideY(((video_width + 31) & ~31) * geo.getBytesPerPixel()); - geo.setStrideC(geo.getStrideY() >> 1); - geo.setHeightY((video_height + 15) & ~15); - geo.setHeightC(geo.getHeightY() >> 1); - geo.setPlanesC(2); - break; - case MMAL_ENCODING_OPAQUE: - geo.setStrideY(video_width); - geo.setHeightY(video_height); - break; - case MMAL_ENCODING_YUVUV128: - { - VC_IMAGE_T img = {}; - img.type = VC_IMAGE_YUV_UV; - img.width = video_width; - img.height = video_height; - int rc = get_image_params(GetMBox(), &img); - assert(rc == 0); - const unsigned int stripe_w = 128; - geo.setStrideY(stripe_w); - geo.setStrideC(stripe_w); - geo.setHeightY(((intptr_t)img.extra.uv.u - (intptr_t)img.image_data) / stripe_w); - geo.setHeightC(img.pitch / stripe_w - geo.getHeightY()); - geo.setPlanesC(1); - geo.setStripes((video_width + stripe_w - 1) / stripe_w); - break; - } - case MMAL_ENCODING_YUVUV64_16: - { - VC_IMAGE_T img = {}; - img.type = VC_IMAGE_YUV_UV_16; - img.width = video_width; - img.height = video_height; - int rc = get_image_params(GetMBox(), &img); - assert(rc == 0); - const unsigned int stripe_w = 128; - geo.setBitsPerPixel(10); - geo.setStrideY(stripe_w); - geo.setStrideC(stripe_w); - geo.setHeightY(((intptr_t)img.extra.uv.u - (intptr_t)img.image_data) / stripe_w); - geo.setHeightC(img.pitch / stripe_w - geo.getHeightY()); - geo.setPlanesC(1); - geo.setStripes((video_width * 2 + stripe_w - 1) / stripe_w); - break; - } - default: assert(0); - } - return geo; -} diff --git a/xbmc/platform/linux/RBP.h b/xbmc/platform/linux/RBP.h deleted file mode 100644 index f56e7b5f91..0000000000 --- a/xbmc/platform/linux/RBP.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#ifndef USE_VCHIQ_ARM -#define USE_VCHIQ_ARM -#endif -#ifndef __VIDEOCORE4__ -#define __VIDEOCORE4__ -#endif -#ifndef HAVE_VMCS_CONFIG -#define HAVE_VMCS_CONFIG -#endif - -#include "DllBCM.h" -#include "OMXCore.h" -#include "ServiceBroker.h" -#include "threads/CriticalSection.h" -#include "threads/Event.h" -#include "utils/CPUInfo.h" - -class AVRpiZcFrameGeometry -{ -public: - unsigned int getStrideY() { return stride_y; } - unsigned int getHeightY() { return height_y; } - unsigned int getStrideC() { return stride_c; } - unsigned int getHeightC() { return height_c; } - unsigned int getPlanesC() { return planes_c; } - unsigned int getStripes() { return stripes; } - unsigned int getBitsPerPixel() { return bits_per_pixel; } - unsigned int getBytesPerPixel() { return (bits_per_pixel + 7) >> 3; } - unsigned int getSizeY() { return stride_y * height_y; } - unsigned int getSizeC() { return stride_c * height_c; } - unsigned int getSize() { return (getSizeY() + getSizeC() * getPlanesC()) * getStripes(); } - void setStrideY(unsigned int v) { stride_y = v; } - void setHeightY(unsigned int v) { height_y = v; } - void setStrideC(unsigned int v) { stride_c = v; } - void setHeightC(unsigned int v) { height_c = v; } - void setPlanesC(unsigned int v) { planes_c = v; } - void setStripes(unsigned int v) { stripes = v; } - void setBitsPerPixel(unsigned int v) { bits_per_pixel = v; } - void setBytesPerPixel(unsigned int v) { bits_per_pixel = v * 8; } -private: - unsigned int stride_y = 0; - unsigned int height_y = 0; - unsigned int stride_c = 0; - unsigned int height_c = 0; - unsigned int planes_c = 0; - unsigned int stripes = 0; - unsigned int bits_per_pixel = 0; -}; - -class CGPUMEM -{ -public: - CGPUMEM(unsigned int numbytes, bool cached = true); - ~CGPUMEM(); - void Flush(); - void *m_arm = nullptr; // Pointer to memory mapped on ARM side - int m_vc_handle = 0; // Videocore handle of relocatable memory - int m_vcsm_handle = 0; // Handle for use by VCSM - unsigned int m_vc = 0; // Address for use in GPU code - unsigned int m_numbytes = 0; // Size of memory block - void *m_opaque = nullptr; -}; - -class CRBP -{ -public: - CRBP(); - ~CRBP(); - - bool Initialize(); - void LogFirmwareVersion(); - void Deinitialize(); - int GetArmMem() { return m_arm_mem; } - int GetGpuMem() { return m_gpu_mem; } - bool GetCodecMpg2() { return m_codec_mpg2_enabled; } - int RaspberryPiVersion() { return CServiceBroker::GetCPUInfo()->GetCPUCount() == 1 ? 1 : 2; }; - bool GetCodecWvc1() { return m_codec_wvc1_enabled; } - void GetDisplaySize(int &width, int &height); - DISPMANX_DISPLAY_HANDLE_T OpenDisplay(uint32_t device); - void CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display); - int GetGUIResolutionLimit() { return m_gui_resolution_limit; } - // stride can be null for packed output - unsigned char *CaptureDisplay(int width, int height, int *stride, bool swap_red_blue, bool video_only = true); - DllOMX *GetDllOMX() { return m_OMX ? m_OMX->GetDll() : NULL; } - uint32_t LastVsync(int64_t &time); - uint32_t LastVsync(); - uint32_t WaitVsync(uint32_t target = ~0U); - void VSyncCallback(); - int GetMBox() { return m_mb; } - AVRpiZcFrameGeometry GetFrameGeometry(uint32_t encoding, unsigned short video_width, unsigned short video_height); - -private: - DllBcmHost *m_DllBcmHost; - bool m_initialized; - bool m_omx_initialized; - bool m_omx_image_init; - int m_arm_mem; - int m_gpu_mem; - int m_gui_resolution_limit; - bool m_codec_mpg2_enabled; - bool m_codec_wvc1_enabled; - COMXCore *m_OMX; - DISPMANX_DISPLAY_HANDLE_T m_display; - CCriticalSection m_vsync_lock; - XbmcThreads::ConditionVariable m_vsync_cond; - uint32_t m_vsync_count; - int64_t m_vsync_time; - class DllLibOMXCore; - CCriticalSection m_critSection; - - int m_mb; -}; - -extern CRBP g_RBP; diff --git a/xbmc/platform/linux/input/CMakeLists.txt b/xbmc/platform/linux/input/CMakeLists.txt index bec4224f77..8e69fda1aa 100644 --- a/xbmc/platform/linux/input/CMakeLists.txt +++ b/xbmc/platform/linux/input/CMakeLists.txt @@ -6,7 +6,7 @@ if(LIRCCLIENT_FOUND) list(APPEND HEADERS LIRC.h) endif() -if(CORE_PLATFORM_NAME_LC STREQUAL rbpi OR CORE_PLATFORM_NAME_LC STREQUAL gbm) +if(CORE_PLATFORM_NAME_LC STREQUAL gbm) if(LIBINPUT_FOUND) list(APPEND SOURCES LibInputHandler.cpp LibInputKeyboard.cpp diff --git a/xbmc/platform/linux/rpi/rpi_user_vcsm.h b/xbmc/platform/linux/rpi/rpi_user_vcsm.h deleted file mode 100644 index d967e5ceeb..0000000000 --- a/xbmc/platform/linux/rpi/rpi_user_vcsm.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2015-2016 Raspberry Pi (Trading) Ltd. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -/* VideoCore Shared Memory - user interface library. -** -** This library provides all the necessary abstraction for any application to -** make use of the shared memory service which is distributed across a kernel -** driver and a videocore service. -** -** It is an application design decision to choose or not to use this service. -** -** The logical flow of operations that a user application needs to follow when -** using this service is: -** -** 1) Initialize the service. -** 2) Allocate shared memory blocks. -** 3) Start using the allocated blocks. -** - In order to gain ownership on a block, lock the allocated block, -** locking a block returns a valid address that the user application -** can access. -** - When finished with using the block for the current execution cycle -** or function, and so when giving up the ownership, unlock the block. -** 4) A block can be locked/unlocked as many times required - within or outside -** of - a specific execution context. -** 5) To completely release an allocated block, free it. -** 6) If the service is no longer required, terminate it. -** -** -** Some generic considerations: - -** Allocating memory blocks. -** -** Memory blocks can be allocated in different manners depending on the cache -** behavior desired. A given block can either be: - -** - Allocated in a non cached fashion all the way through host and videocore. -** - Allocated in a cached fashion on host OR videocore. -** - Allocated in a cached fashion on host AND videocore. -** -** It is an application decision to determine how to allocate a block. Evidently -** if the application will be doing substantial read/write accesses to a given block, -** it is recommended to allocate the block at least in a 'host cached' fashion for -** better results. -** -** -** Locking memory blocks. -** -** When the memory block has been allocated in a host cached fashion, locking the -** memory block (and so taking ownership of it) will trigger a cache invalidation. -** -** For the above reason and when using host cached allocation, it is important that -** an application properly implements the lock/unlock mechanism to ensure cache will -** stay coherent, otherwise there is no guarantee it will at all be. -** -** It is possible to dynamically change the host cache behavior (ie cached or non -** cached) of a given allocation without needing to free and re-allocate the block. -** This feature can be useful for such application which requires access to the block -** only at certain times and not otherwise. By changing the cache behavior dynamically -** the application can optimize performances for a given duration of use. -** Such dynamic cache behavior remapping only applies to host cache and not videocore -** cache. If one requires to change the videocore cache behavior, then a new block -** must be created to replace the old one. -** -** On successful locking, a valid pointer is returned that the application can use -** to access to data inside the block. There is no guarantee that the pointer will -** stay valid following the unlock action corresponding to this lock. -** -** -** Unlocking memory blocks. -** -** When the memory block has been allocated in a host cached fashion, unlocking the -** memory block (and so forgiving its ownership) will trigger a cache flush unless -** explicitly asked not to flush the cache for performances reasons. -** -** For the above reason and when using host cached allocation, it is important that -** an application properly implements the lock/unlock mechanism to ensure cache will -** stay coherent, otherwise there is no guarantee it will at all be. -** -** -** A complete API is defined below. -*/ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Different status that can be dumped. -*/ -typedef enum -{ - VCSM_STATUS_VC_WALK_ALLOC = 0, // Walks *all* the allocation on videocore. - // Result of the walk is seen in the videocore - // log. - VCSM_STATUS_HOST_WALK_MAP, // Walks the *full* mapping allocation on host - // driver (ie for all processes). Result of - // the walk is seen in the kernel log. - VCSM_STATUS_HOST_WALK_PID_MAP, // Walks the per process mapping allocation on host - // driver (for current process). Result of - // the walk is seen in the kernel log. - VCSM_STATUS_HOST_WALK_PID_ALLOC, // Walks the per process host allocation on host - // driver (for current process). Result of - // the walk is seen in the kernel log. - VCSM_STATUS_VC_MAP_ALL, // Equivalent to both VCSM_STATUS_VC_WALK_ALLOC and - // VCSM_STATUS_HOST_WALK_MAP. - // - VCSM_STATUS_NONE, // Must be last - invalid. - -} VCSM_STATUS_T; - -/* Different kind of cache behavior. -*/ -typedef enum -{ - VCSM_CACHE_TYPE_NONE = 0, // No caching applies. - VCSM_CACHE_TYPE_HOST, // Allocation is cached on host (user space). - VCSM_CACHE_TYPE_VC, // Allocation is cached on videocore. - VCSM_CACHE_TYPE_HOST_AND_VC, // Allocation is cached on both host and videocore. - -} VCSM_CACHE_TYPE_T; - -/* Initialize the vcsm processing. -** -** Must be called once before attempting to do anything else. -** -** Returns 0 on success, -1 on error. -*/ -int vcsm_init( void ); - - -/* Terminates the vcsm processing. -** -** Must be called vcsm services are no longer needed, it will -** take care of removing any allocation under the current process -** control if deemed necessary. -*/ -void vcsm_exit( void ); - - -/* Queries the status of the the vcsm. -** -** Triggers dump of various kind of information, see the -** different variants specified in VCSM_STATUS_T. -** -** Pid is optional. -*/ -void vcsm_status( VCSM_STATUS_T status, int pid ); - - -/* Allocates a non-cached block of memory of size 'size' via the vcsm memory -** allocator. -** -** Returns: 0 on error -** a non-zero opaque handle on success. -** -** On success, the user must invoke vcsm_lock with the returned opaque -** handle to gain access to the memory associated with the opaque handle. -** When finished using the memory, the user calls vcsm_unlock_xx (see those -** function definition for more details on the one that can be used). -** -** A well behaved application should make every attempt to lock/unlock -** only for the duration it needs to access the memory data associated with -** the opaque handle. -*/ -unsigned int vcsm_malloc( unsigned int size, char *name ); - - -/* Allocates a cached block of memory of size 'size' via the vcsm memory -** allocator, the type of caching requested is passed as argument of the -** function call. -** -** Returns: 0 on error -** a non-zero opaque handle on success. -** -** On success, the user must invoke vcsm_lock with the returned opaque -** handle to gain access to the memory associated with the opaque handle. -** When finished using the memory, the user calls vcsm_unlock_xx (see those -** function definition for more details on the one that can be used). -** -** A well behaved application should make every attempt to lock/unlock -** only for the duration it needs to access the memory data associated with -** the opaque handle. -*/ -unsigned int vcsm_malloc_cache( unsigned int size, VCSM_CACHE_TYPE_T cache, char *name ); - - -/* Shares an allocated block of memory via the vcsm memory allocator. -** -** Returns: 0 on error -** a non-zero opaque handle on success. -** -** On success, the user must invoke vcsm_lock with the returned opaque -** handle to gain access to the memory associated with the opaque handle. -** When finished using the memory, the user calls vcsm_unlock_xx (see those -** function definition for more details on the one that can be used). -** -** A well behaved application should make every attempt to lock/unlock -** only for the duration it needs to access the memory data associated with -** the opaque handle. -*/ -unsigned int vcsm_malloc_share( unsigned int handle ); - - -/* Resizes a block of memory allocated previously by vcsm_alloc. -** -** Returns: 0 on success -** -errno on error. -** -** The handle must be unlocked by user prior to attempting any -** resize action. -** -** On error, the original size allocated against the handle -** remains available the same way it would be following a -** successful vcsm_malloc. -*/ -int vcsm_resize( unsigned int handle, unsigned int new_size ); - - -/* Frees a block of memory that was successfully allocated by -** a prior call the vcms_alloc. -** -** The handle should be considered invalid upon return from this -** call. -** -** Whether any memory is actually freed up or not as the result of -** this call will depends on many factors, if all goes well it will -** be freed. If something goes wrong, the memory will likely end up -** being freed up as part of the vcsm_exit process. In the end the -** memory is guaranteed to be freed one way or another. -*/ -void vcsm_free( unsigned int handle ); - - -/* Retrieves a videocore opaque handle from a mapped user address -** pointer. The videocore handle will correspond to the actual -** memory mapped in videocore. -** -** Returns: 0 on error -** a non-zero opaque handle on success. -** -** Note: the videocore opaque handle is distinct from the user -** opaque handle (allocated via vcsm_malloc) and it is only -** significant for such application which knows what to do -** with it, for the others it is just a number with little -** use since nothing can be done with it (in particular -** for safety reason it cannot be used to map anything). -*/ -unsigned int vcsm_vc_hdl_from_ptr( void *usr_ptr ); - - -/* Retrieves a videocore opaque handle from a opaque handle -** pointer. The videocore handle will correspond to the actual -** memory mapped in videocore. -** -** Returns: 0 on error -** a non-zero opaque handle on success. -** -** Note: the videocore opaque handle is distinct from the user -** opaque handle (allocated via vcsm_malloc) and it is only -** significant for such application which knows what to do -** with it, for the others it is just a number with little -** use since nothing can be done with it (in particular -** for safety reason it cannot be used to map anything). -*/ -unsigned int vcsm_vc_hdl_from_hdl( unsigned int handle ); - - -/* Retrieves a user opaque handle from a mapped user address -** pointer. -** -** Returns: 0 on error -** a non-zero opaque handle on success. -*/ -unsigned int vcsm_usr_handle( void *usr_ptr ); - - -/* Retrieves a mapped user address from an opaque user -** handle. -** -** Returns: 0 on error -** a non-zero address on success. -** -** On success, the address corresponds to the pointer -** which can access the data allocated via the vcsm_malloc -** call. -*/ -void *vcsm_usr_address( unsigned int handle ); - - -/* Locks the memory associated with this opaque handle. -** -** Returns: NULL on error -** a valid pointer on success. -** -** A user MUST lock the handle received from vcsm_malloc -** in order to be able to use the memory associated with it. -** -** On success, the pointer returned is only valid within -** the lock content (ie until a corresponding vcsm_unlock_xx -** is invoked). -*/ -void *vcsm_lock( unsigned int handle ); - - -/* Locks the memory associated with this opaque handle. The lock -** also gives a chance to update the *host* cache behavior of the -** allocated buffer if so desired. The *videocore* cache behavior -** of the allocated buffer cannot be changed by this call and such -** attempt will be ignored. -** -** The system will attempt to honour the cache_update mode request, -** the cache_result mode will provide the final answer on which cache -** mode is really in use. Failing to change the cache mode will not -** result in a failure to lock the buffer as it is an application -** decision to choose what to do if (cache_result != cache_update) -** -** The value returned in cache_result can only be considered valid if -** the returned pointer is non NULL. The cache_result pointer may be -** NULL if the application does not care about the actual outcome of -** its action with regards to the cache behavior change. -** -** Returns: NULL on error -** a valid pointer on success. -** -** A user MUST lock the handle received from vcsm_malloc -** in order to be able to use the memory associated with it. -** -** On success, the pointer returned is only valid within -** the lock content (ie until a corresponding vcsm_unlock_xx -** is invoked). -*/ -void *vcsm_lock_cache( unsigned int handle, - VCSM_CACHE_TYPE_T cache_update, - VCSM_CACHE_TYPE_T *cache_result ); - - -/* Unlocks the memory associated with this user mapped address. -** -** Returns: 0 on success -** -errno on error. -** -** After unlocking a mapped address, the user should no longer -** attempt to reference it. -*/ -int vcsm_unlock_ptr( void *usr_ptr ); - - -/* Unlocks the memory associated with this user mapped address. -** Apply special processing that would override the otherwise -** default behavior. -** -** If 'cache_no_flush' is specified: -** Do not flush cache as the result of the unlock (if cache -** flush was otherwise applicable in this case). -** -** Returns: 0 on success -** -errno on error. -** -** After unlocking a mapped address, the user should no longer -** attempt to reference it. -*/ -int vcsm_unlock_ptr_sp( void *usr_ptr, int cache_no_flush ); - - -/* Unlocks the memory associated with this user opaque handle. -** -** Returns: 0 on success -** -errno on error. -** -** After unlocking an opaque handle, the user should no longer -** attempt to reference the mapped addressed once associated -** with it. -*/ -int vcsm_unlock_hdl( unsigned int handle ); - - -/* Unlocks the memory associated with this user opaque handle. -** Apply special processing that would override the otherwise -** default behavior. -** -** If 'cache_no_flush' is specified: -** Do not flush cache as the result of the unlock (if cache -** flush was otherwise applicable in this case). -** -** Returns: 0 on success -** -errno on error. -** -** After unlocking an opaque handle, the user should no longer -** attempt to reference the mapped addressed once associated -** with it. -*/ -int vcsm_unlock_hdl_sp( unsigned int handle, int cache_no_flush ); - -/* Clean and/or invalidate the memory associated with this user opaque handle -** -** Returns: non-zero on error -** -** structure contains a list of flush/invalidate commands. Commands are: -** 0: nop -** 1: invalidate given virtual range in L1/L2 -** 2: clean given virtual range in L1/L2 -** 3: clean+invalidate given virtual range in L1/L2 -** 4: flush all L1/L2 -*/ -struct vcsm_user_clean_invalid_s { - struct { - unsigned int cmd; - unsigned int handle; - unsigned int addr; - unsigned int size; - } s[8]; -}; - -int vcsm_clean_invalid( struct vcsm_user_clean_invalid_s *s ); - -#ifdef __cplusplus -} -#endif - diff --git a/xbmc/platform/xbmc.cpp b/xbmc/platform/xbmc.cpp index e9f39178ca..b910caf7eb 100644 --- a/xbmc/platform/xbmc.cpp +++ b/xbmc/platform/xbmc.cpp @@ -8,10 +8,6 @@ #include "Application.h" -#ifdef TARGET_RASPBERRY_PI -#include "platform/linux/RBP.h" -#endif - #ifdef TARGET_WINDOWS_DESKTOP #include "platform/win32/IMMNotificationClient.h" #include <mmdeviceapi.h> @@ -36,11 +32,7 @@ extern "C" int XBMC_Run(bool renderGUI, const CAppParamParser ¶ms) return status; } -#ifdef TARGET_RASPBERRY_PI - if(!g_RBP.Initialize()) - return false; - g_RBP.LogFirmwareVersion(); -#elif defined(TARGET_ANDROID) +#if defined(TARGET_ANDROID) CXBMCApp::get()->Initialize(); #endif @@ -82,9 +74,7 @@ extern "C" int XBMC_Run(bool renderGUI, const CAppParamParser ¶ms) } #endif -#ifdef TARGET_RASPBERRY_PI - g_RBP.Deinitialize(); -#elif defined(TARGET_ANDROID) +#if defined(TARGET_ANDROID) CXBMCApp::get()->Deinitialize(); #endif diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index b3905039c3..be337833c2 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -71,8 +71,7 @@ bool CRenderSystemGLES::InitRenderSystem() m_RenderExtensions += " "; -//! @todo remove TARGET_RASPBERRY_PI when Raspberry Pi updates their GL headers -#if defined(GL_KHR_debug) && defined(TARGET_LINUX) && !defined(TARGET_RASPBERRY_PI) +#if defined(GL_KHR_debug) && defined(TARGET_LINUX) if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging) { if (IsExtSupported("GL_KHR_debug")) diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 8680b105ae..8036a90868 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -33,9 +33,6 @@ #if defined(TARGET_DARWIN_EMBEDDED) #include "SettingAddon.h" #endif -#if defined(TARGET_RASPBERRY_PI) -#include "platform/linux/RBP.h" -#endif #include "powermanagement/PowerTypes.h" #include "profiles/ProfileManager.h" #include "ServiceBroker.h" @@ -142,7 +139,6 @@ const std::string CSettings::SETTING_VIDEOPLAYER_USEVDPAUMPEG4 = "videoplayer.us const std::string CSettings::SETTING_VIDEOPLAYER_USEVDPAUVC1 = "videoplayer.usevdpauvc1"; const std::string CSettings::SETTING_VIDEOPLAYER_USEDXVA2 = "videoplayer.usedxva2"; const std::string CSettings::SETTING_VIDEOPLAYER_USEVTB = "videoplayer.usevtb"; -const std::string CSettings::SETTING_VIDEOPLAYER_USEMMAL = "videoplayer.usemmal"; const std::string CSettings::SETTING_VIDEOPLAYER_USEPRIMEDECODER = "videoplayer.useprimedecoder"; const std::string CSettings::SETTING_VIDEOPLAYER_USESTAGEFRIGHT = "videoplayer.usestagefright"; const std::string CSettings::SETTING_VIDEOPLAYER_LIMITGUIUPDATE = "videoplayer.limitguiupdate"; @@ -625,11 +621,6 @@ bool CSettings::InitializeDefinitions() #elif defined(TARGET_ANDROID) if (CFile::Exists(SETTINGS_XML_FOLDER "android.xml") && !Initialize(SETTINGS_XML_FOLDER "android.xml")) CLog::Log(LOGFATAL, "Unable to load android-specific settings definitions"); -#elif defined(TARGET_RASPBERRY_PI) - if (CFile::Exists(SETTINGS_XML_FOLDER "rbp.xml") && !Initialize(SETTINGS_XML_FOLDER "rbp.xml")) - CLog::Log(LOGFATAL, "Unable to load rbp-specific settings definitions"); - if (g_RBP.RaspberryPiVersion() > 1 && CFile::Exists(SETTINGS_XML_FOLDER "rbp2.xml") && !Initialize(SETTINGS_XML_FOLDER "rbp2.xml")) - CLog::Log(LOGFATAL, "Unable to load rbp2-specific settings definitions"); #elif defined(TARGET_FREEBSD) if (CFile::Exists(SETTINGS_XML_FOLDER "freebsd.xml") && !Initialize(SETTINGS_XML_FOLDER "freebsd.xml")) CLog::Log(LOGFATAL, "Unable to load freebsd-specific settings definitions"); diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h index 220bbd716e..518d3c19cc 100644 --- a/xbmc/settings/Settings.h +++ b/xbmc/settings/Settings.h @@ -107,7 +107,6 @@ public: static const std::string SETTING_VIDEOPLAYER_USEVDPAUVC1; static const std::string SETTING_VIDEOPLAYER_USEDXVA2; static const std::string SETTING_VIDEOPLAYER_USEVTB; - static const std::string SETTING_VIDEOPLAYER_USEMMAL; static const std::string SETTING_VIDEOPLAYER_USEPRIMEDECODER; static const std::string SETTING_VIDEOPLAYER_USESTAGEFRIGHT; static const std::string SETTING_VIDEOPLAYER_LIMITGUIUPDATE; diff --git a/xbmc/utils/EGLUtils.cpp b/xbmc/utils/EGLUtils.cpp index 01df4ba7e7..0d7c23891c 100644 --- a/xbmc/utils/EGLUtils.cpp +++ b/xbmc/utils/EGLUtils.cpp @@ -21,19 +21,6 @@ namespace { -//! @todo remove when Raspberry Pi updates their EGL headers -#ifndef EGL_NO_CONFIG_KHR -#define EGL_NO_CONFIG_KHR static_cast<EGLConfig>(0) -#endif -#ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG -#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 -#endif -#ifndef EGL_CONTEXT_PRIORITY_HIGH_IMG -#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 -#endif -#ifndef EGL_CONTEXT_PRIORITY_MEDIUM_IMG -#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 -#endif #define X(VAL) std::make_pair(VAL, #VAL) std::map<EGLint, const char*> eglAttributes = @@ -97,21 +84,21 @@ std::map<EGLenum, const char*> eglErrors = std::map<EGLint, const char*> eglErrorType = { -//! @todo remove when Raspberry Pi updates their EGL headers -#if !defined(TARGET_RASPBERRY_PI) X(EGL_DEBUG_MSG_CRITICAL_KHR), X(EGL_DEBUG_MSG_ERROR_KHR), X(EGL_DEBUG_MSG_WARN_KHR), X(EGL_DEBUG_MSG_INFO_KHR), -#endif }; #undef X } // namespace -//! @todo remove when Raspberry Pi updates their EGL headers -#if !defined(TARGET_RASPBERRY_PI) -void EglErrorCallback(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message) +void EglErrorCallback(EGLenum error, + const char* command, + EGLint messageType, + EGLLabelKHR threadLabel, + EGLLabelKHR objectLabel, + const char* message) { std::string errorStr; std::string typeStr; @@ -130,7 +117,6 @@ void EglErrorCallback(EGLenum error, const char* command, EGLint messageType, EG CLog::Log(LOGDEBUG, "EGL Debugging:\nError: {}\nCommand: {}\nType: {}\nMessage: {}", errorStr, command, typeStr, message); } -#endif std::set<std::string> CEGLUtils::GetClientExtensions() { @@ -185,8 +171,6 @@ void CEGLUtils::Log(int logLevel, const std::string& what) CEGLContextUtils::CEGLContextUtils(EGLenum platform, std::string const& platformExtension) : m_platform{platform} { -//! @todo remove when Raspberry Pi updates their EGL headers -#if !defined(TARGET_RASPBERRY_PI) if (CEGLUtils::HasClientExtension("EGL_KHR_debug")) { auto eglDebugMessageControl = CEGLUtils::GetRequiredProcAddress<PFNEGLDEBUGMESSAGECONTROLKHRPROC>("eglDebugMessageControlKHR"); @@ -199,7 +183,6 @@ CEGLContextUtils::CEGLContextUtils(EGLenum platform, std::string const& platform eglDebugMessageControl(EglErrorCallback, eglDebugAttribs); } -#endif m_platformSupported = CEGLUtils::HasClientExtension("EGL_EXT_platform_base") && CEGLUtils::HasClientExtension(platformExtension); } @@ -414,14 +397,11 @@ bool CEGLContextUtils::CreateContext(CEGLAttributesVec contextAttribs) if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority")) contextAttribs.Add({{EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG}}); -//! @todo remove when Raspberry Pi updates their EGL headers -#if !defined(TARGET_RASPBERRY_PI) if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_create_context") && CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging) { contextAttribs.Add({{EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR}}); } -#endif m_eglContext = eglCreateContext(m_eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs.Get()); diff --git a/xbmc/utils/GLUtils.cpp b/xbmc/utils/GLUtils.cpp index be94eb5a2c..1ef804709f 100644 --- a/xbmc/utils/GLUtils.cpp +++ b/xbmc/utils/GLUtils.cpp @@ -39,41 +39,35 @@ std::map<GLenum, const char*> glErrors = #endif }; -std::map<GLenum, const char*> glErrorSource = -{ -//! @todo remove TARGET_RASPBERRY_PI when Raspberry Pi updates their GL headers -#if defined(HAS_GLES) && defined(TARGET_LINUX) && !defined(TARGET_RASPBERRY_PI) - X(GL_DEBUG_SOURCE_API_KHR), - X(GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR), - X(GL_DEBUG_SOURCE_SHADER_COMPILER_KHR), - X(GL_DEBUG_SOURCE_THIRD_PARTY_KHR), - X(GL_DEBUG_SOURCE_APPLICATION_KHR), - X(GL_DEBUG_SOURCE_OTHER_KHR), +std::map<GLenum, const char*> glErrorSource = { +#if defined(HAS_GLES) && defined(TARGET_LINUX) + X(GL_DEBUG_SOURCE_API_KHR), + X(GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR), + X(GL_DEBUG_SOURCE_SHADER_COMPILER_KHR), + X(GL_DEBUG_SOURCE_THIRD_PARTY_KHR), + X(GL_DEBUG_SOURCE_APPLICATION_KHR), + X(GL_DEBUG_SOURCE_OTHER_KHR), #endif }; -std::map<GLenum, const char*> glErrorType = -{ -//! @todo remove TARGET_RASPBERRY_PI when Raspberry Pi updates their GL headers -#if defined(HAS_GLES) && defined(TARGET_LINUX) && !defined(TARGET_RASPBERRY_PI) - X(GL_DEBUG_TYPE_ERROR_KHR), - X(GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR), - X(GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR), - X(GL_DEBUG_TYPE_PORTABILITY_KHR), - X(GL_DEBUG_TYPE_PERFORMANCE_KHR), - X(GL_DEBUG_TYPE_OTHER_KHR), - X(GL_DEBUG_TYPE_MARKER_KHR), +std::map<GLenum, const char*> glErrorType = { +#if defined(HAS_GLES) && defined(TARGET_LINUX) + X(GL_DEBUG_TYPE_ERROR_KHR), + X(GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR), + X(GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR), + X(GL_DEBUG_TYPE_PORTABILITY_KHR), + X(GL_DEBUG_TYPE_PERFORMANCE_KHR), + X(GL_DEBUG_TYPE_OTHER_KHR), + X(GL_DEBUG_TYPE_MARKER_KHR), #endif }; -std::map<GLenum, const char*> glErrorSeverity = -{ -//! @todo remove TARGET_RASPBERRY_PI when Raspberry Pi updates their GL headers -#if defined(HAS_GLES) && defined(TARGET_LINUX) && !defined(TARGET_RASPBERRY_PI) - X(GL_DEBUG_SEVERITY_HIGH_KHR), - X(GL_DEBUG_SEVERITY_MEDIUM_KHR), - X(GL_DEBUG_SEVERITY_LOW_KHR), - X(GL_DEBUG_SEVERITY_NOTIFICATION_KHR), +std::map<GLenum, const char*> glErrorSeverity = { +#if defined(HAS_GLES) && defined(TARGET_LINUX) + X(GL_DEBUG_SEVERITY_HIGH_KHR), + X(GL_DEBUG_SEVERITY_MEDIUM_KHR), + X(GL_DEBUG_SEVERITY_LOW_KHR), + X(GL_DEBUG_SEVERITY_NOTIFICATION_KHR), #endif }; #undef X diff --git a/xbmc/utils/SystemInfo.cpp b/xbmc/utils/SystemInfo.cpp index a29ece96ce..92d2c19c93 100644 --- a/xbmc/utils/SystemInfo.cpp +++ b/xbmc/utils/SystemInfo.cpp @@ -1176,9 +1176,7 @@ std::string CSysInfo::GetUserAgent() result += " " + linuxOSName + "/" + GetOsVersion(); #endif -#ifdef TARGET_RASPBERRY_PI - result += " HW_RaspberryPi/1.0"; -#elif defined (TARGET_DARWIN_EMBEDDED) +#if defined(TARGET_DARWIN_IOS) std::string iDevVer; if (iDevStrDigit == std::string::npos) iDevVer = "0.0"; diff --git a/xbmc/utils/test/TestSystemInfo.cpp b/xbmc/utils/test/TestSystemInfo.cpp index 1f2b0a10f3..4ee3256362 100644 --- a/xbmc/utils/test/TestSystemInfo.cpp +++ b/xbmc/utils/test/TestSystemInfo.cpp @@ -239,10 +239,6 @@ TEST_F(TestSystemInfo, GetUserAgent) #endif // defined(TARGET_LINUX) #endif // defined(TARGET_POSIX) -#ifdef TARGET_RASPBERRY_PI - EXPECT_NE(std::string::npos, g_sysinfo.GetUserAgent().find(" XBMC_HW_RaspberryPi/")) << "'GetUserAgent()' must contain ' XBMC_HW_RaspberryPi/'"; -#endif // TARGET_RASPBERRY_PI - EXPECT_NE(std::string::npos, g_sysinfo.GetUserAgent().find(" App_Bitness/")) << "'GetUserAgent()' must contain ' App_Bitness/'"; EXPECT_NE(std::string::npos, g_sysinfo.GetUserAgent().find(" Version/")) << "'GetUserAgent()' must contain ' Version/'"; } diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp index 7d3097df82..28d5b6b0b1 100644 --- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp @@ -320,10 +320,6 @@ void CGUIDialogVideoSettings::InitializeSettings() entries.push_back(TranslatableIntegerSettingOption(16327, VS_INTERLACEMETHOD_VAAPI_BOB)); entries.push_back(TranslatableIntegerSettingOption(16328, VS_INTERLACEMETHOD_VAAPI_MADI)); entries.push_back(TranslatableIntegerSettingOption(16329, VS_INTERLACEMETHOD_VAAPI_MACI)); - entries.push_back(TranslatableIntegerSettingOption(16330, VS_INTERLACEMETHOD_MMAL_ADVANCED)); - entries.push_back(TranslatableIntegerSettingOption(16331, VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF)); - entries.push_back(TranslatableIntegerSettingOption(16332, VS_INTERLACEMETHOD_MMAL_BOB)); - entries.push_back(TranslatableIntegerSettingOption(16333, VS_INTERLACEMETHOD_MMAL_BOB_HALF)); entries.push_back(TranslatableIntegerSettingOption(16320, VS_INTERLACEMETHOD_DXVA_AUTO)); /* remove unsupported methods */ diff --git a/xbmc/windowing/rpi/CMakeLists.txt b/xbmc/windowing/rpi/CMakeLists.txt deleted file mode 100644 index f42c6419fc..0000000000 --- a/xbmc/windowing/rpi/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(SOURCES WinSystemRpi.cpp - RPIUtils.cpp - VideoSyncPi.cpp) - -set(HEADERS WinSystemRpi.h - RPIUtils.h - VideoSyncPi.h) - -if(OPENGLES_FOUND) - list(APPEND SOURCES WinSystemRpiGLESContext.cpp) - list(APPEND HEADERS WinSystemRpiGLESContext.h) -endif() - -core_add_library(windowing_Rpi) diff --git a/xbmc/windowing/rpi/RPIUtils.cpp b/xbmc/windowing/rpi/RPIUtils.cpp deleted file mode 100644 index c7a3a719f8..0000000000 --- a/xbmc/windowing/rpi/RPIUtils.cpp +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (C) 2011-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "RPIUtils.h" - -#include "ServiceBroker.h" -#include "guilib/StereoscopicsManager.h" -#include "guilib/gui3d.h" -#include "rendering/RenderSystem.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "utils/StringUtils.h" -#include "utils/log.h" -#include "windowing/GraphicContext.h" - -#include "platform/linux/DllBCM.h" -#include "platform/linux/RBP.h" - -#include <cassert> -#include <math.h> - -#ifndef __VIDEOCORE4__ -#define __VIDEOCORE4__ -#endif - -#define __VCCOREVER__ 0x04000000 - -#define IS_WIDESCREEN(m) ( m == 3 || m == 7 || m == 9 || \ - m == 11 || m == 13 || m == 15 || m == 18 || m == 22 || \ - m == 24 || m == 26 || m == 28 || m == 30 || m == 36 || \ - m == 38 || m == 43 || m == 45 || m == 49 || m == 51 || \ - m == 53 || m == 55 || m == 57 || m == 59) - -#define MAKEFLAGS(group, mode, interlace) \ - ( ( (mode)<<24 ) | ( (group)<<16 ) | \ - ( (interlace) != 0 ? D3DPRESENTFLAG_INTERLACED : D3DPRESENTFLAG_PROGRESSIVE) | \ - ( ((group) == HDMI_RES_GROUP_CEA && IS_WIDESCREEN(mode) ) ? D3DPRESENTFLAG_WIDESCREEN : 0) ) - -#define GETFLAGS_GROUP(f) ( (HDMI_RES_GROUP_T)( ((f) >> 16) & 0xff )) -#define GETFLAGS_MODE(f) ( ( (f) >>24 ) & 0xff ) - -static void SetResolutionString(RESOLUTION_INFO &res); -static SDTV_ASPECT_T get_sdtv_aspect_from_display_aspect(float display_aspect); - -CRPIUtils::CRPIUtils() -{ - m_DllBcmHost = new DllBcmHost; - m_DllBcmHost->Load(); - - m_dispman_element = DISPMANX_NO_HANDLE; - m_dispman_display = DISPMANX_NO_HANDLE; - - m_height = 1280; - m_width = 720; - m_screen_width = 1280; - m_screen_height = 720; - m_shown = false; - - m_initDesktopRes = true; -} - -CRPIUtils::~CRPIUtils() -{ - if(m_DllBcmHost && m_DllBcmHost->IsLoaded()) - { - m_DllBcmHost->Unload(); - } - - delete m_DllBcmHost; - m_DllBcmHost = NULL; -} - -bool CRPIUtils::GetNativeResolution(RESOLUTION_INFO *res) const -{ - *res = m_desktopRes; - - return true; -} - -int CRPIUtils::FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions, bool desktop) -{ - uint32_t mask = desktop ? D3DPRESENTFLAG_MODEMASK : D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB; - for (int i = 0; i < (int)resolutions.size(); i++) - { - if(resolutions[i].iScreenWidth == res.iScreenWidth && resolutions[i].iScreenHeight == res.iScreenHeight && resolutions[i].fRefreshRate == res.fRefreshRate && - (resolutions[i].dwFlags & mask) == (res.dwFlags & mask)) - { - return i; - } - } - return -1; -} - -int CRPIUtils::AddUniqueResolution(RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions, bool desktop /* = false */) -{ - SetResolutionString(res); - int i = FindMatchingResolution(res, resolutions, desktop); - if (i>=0) - { // don't replace a progressive resolution with an interlaced one of same resolution - if (!(res.dwFlags & D3DPRESENTFLAG_INTERLACED)) - resolutions[i] = res; - } - else - { - resolutions.push_back(res); - } - return i; -} - -bool CRPIUtils::SetNativeResolution(const RESOLUTION_INFO res, EGLSurface m_nativeWindow) -{ - if(!m_DllBcmHost || !m_nativeWindow) - return false; - - DestroyDispmanxWindow(); - - RENDER_STEREO_MODE stereo_mode = CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode(); - if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) - { - uint32_t mode3d = HDMI_3D_FORMAT_NONE; - sem_init(&m_tv_synced, 0, 0); - m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this); - - if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL || stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - { - /* inform TV of any 3D settings. Note this property just applies to next hdmi mode change, so no need to call for 2D modes */ - HDMI_PROPERTY_PARAM_T property; - property.property = HDMI_PROPERTY_3D_STRUCTURE; - const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings(); - if (settings->GetBool(CSettings::SETTING_VIDEOSCREEN_FRAMEPACKING) && - settings->GetBool(CSettings::SETTING_VIDEOPLAYER_SUPPORTMVC) && res.fRefreshRate <= 30.0f) - property.param1 = HDMI_3D_FORMAT_FRAME_PACKING; - else if (stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - property.param1 = HDMI_3D_FORMAT_SBS_HALF; - else if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) - property.param1 = HDMI_3D_FORMAT_TB_HALF; - else - property.param1 = HDMI_3D_FORMAT_NONE; - property.param2 = 0; - mode3d = property.param1; - vc_tv_hdmi_set_property(&property); - } - - HDMI_PROPERTY_PARAM_T property; - property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; - // if we are closer to ntsc version of framerate, let gpu know - int iFrameRate = (int)(res.fRefreshRate + 0.5f); - if (fabsf(res.fRefreshRate * (1001.0f / 1000.0f) - iFrameRate) < fabsf(res.fRefreshRate - iFrameRate)) - property.param1 = HDMI_PIXEL_CLOCK_TYPE_NTSC; - else - property.param1 = HDMI_PIXEL_CLOCK_TYPE_PAL; - property.param2 = 0; - vc_tv_hdmi_set_property(&property); - - int success = m_DllBcmHost->vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags)); - - if (success == 0) - { - CLog::Log(LOGDEBUG, "EGL set HDMI mode (%d,%d)=%d %s%s", GETFLAGS_GROUP(res.dwFlags), - GETFLAGS_MODE(res.dwFlags), success, - CStereoscopicsManager::ConvertGuiStereoModeToString(stereo_mode), - mode3d == HDMI_3D_FORMAT_FRAME_PACKING - ? " FP" - : mode3d == HDMI_3D_FORMAT_SBS_HALF - ? " SBS" - : mode3d == HDMI_3D_FORMAT_TB_HALF ? " TB" : ""); - - sem_wait(&m_tv_synced); - } - else - { - CLog::Log(LOGERROR, "EGL failed to set HDMI mode (%d,%d)=%d %s%s", - GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success, - CStereoscopicsManager::ConvertGuiStereoModeToString(stereo_mode), - mode3d == HDMI_3D_FORMAT_FRAME_PACKING - ? " FP" - : mode3d == HDMI_3D_FORMAT_SBS_HALF - ? " SBS" - : mode3d == HDMI_3D_FORMAT_TB_HALF ? " TB" : ""); - } - m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback); - sem_destroy(&m_tv_synced); - - m_desktopRes = res; - } - else if(!GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) - { - sem_init(&m_tv_synced, 0, 0); - m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this); - - SDTV_OPTIONS_T options; - options.aspect = get_sdtv_aspect_from_display_aspect((float)res.iScreenWidth / (float)res.iScreenHeight); - - int success = m_DllBcmHost->vc_tv_sdtv_power_on((SDTV_MODE_T)GETFLAGS_MODE(res.dwFlags), &options); - - if (success == 0) - { - CLog::Log(LOGDEBUG, "EGL set SDTV mode (%d,%d)=%d", GETFLAGS_GROUP(res.dwFlags), - GETFLAGS_MODE(res.dwFlags), success); - - sem_wait(&m_tv_synced); - } - else - { - CLog::Log(LOGERROR, "EGL failed to set SDTV mode (%d,%d)=%d", GETFLAGS_GROUP(res.dwFlags), - GETFLAGS_MODE(res.dwFlags), success); - } - m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback); - sem_destroy(&m_tv_synced); - - m_desktopRes = res; - } - - m_dispman_display = g_RBP.OpenDisplay(0); - - m_width = res.iWidth; - m_height = res.iHeight; - - m_screen_width = res.iScreenWidth; - m_screen_height = res.iScreenHeight; - - VC_RECT_T dst_rect; - VC_RECT_T src_rect; - - dst_rect.x = 0; - dst_rect.y = 0; - dst_rect.width = m_screen_width; - dst_rect.height = m_screen_height; - - src_rect.x = 0; - src_rect.y = 0; - src_rect.width = m_width << 16; - src_rect.height = m_height << 16; - - VC_DISPMANX_ALPHA_T alpha; - memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T)); - alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE; - - DISPMANX_CLAMP_T clamp; - memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T)); - - DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE; - DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0); - - if (stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) - transform = DISPMANX_STEREOSCOPIC_SBS; - else if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) - transform = DISPMANX_STEREOSCOPIC_TB; - else - transform = DISPMANX_STEREOSCOPIC_MONO; - - CLog::Log(LOGDEBUG, "EGL set resolution %dx%d -> %dx%d @ %.2f fps (%d,%d) flags:%x aspect:%.2f", - m_width, m_height, dst_rect.width, dst_rect.height, res.fRefreshRate, - GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), (int)res.dwFlags, - res.fPixelRatio); - - m_dispman_element = m_DllBcmHost->vc_dispmanx_element_add(dispman_update, - m_dispman_display, - 1, // layer - &dst_rect, - (DISPMANX_RESOURCE_HANDLE_T)0, // src - &src_rect, - DISPMANX_PROTECTION_NONE, - &alpha, //alpha - &clamp, //clamp - transform); // transform - - assert(m_dispman_element != DISPMANX_NO_HANDLE); - assert(m_dispman_element != (unsigned)DISPMANX_INVALID); - - memset(m_nativeWindow, 0, sizeof(EGL_DISPMANX_WINDOW_T)); - - EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow; - - nativeWindow->element = m_dispman_element; - nativeWindow->width = m_width; - nativeWindow->height = m_height; - - m_DllBcmHost->vc_dispmanx_display_set_background(dispman_update, m_dispman_display, 0x00, 0x00, 0x00); - m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update); - m_shown = true; - - return true; -} - -static float get_display_aspect_ratio(HDMI_ASPECT_T aspect) -{ - float display_aspect; - switch (aspect) { - case HDMI_ASPECT_4_3: display_aspect = 4.0/3.0; break; - case HDMI_ASPECT_14_9: display_aspect = 14.0/9.0; break; - case HDMI_ASPECT_16_9: display_aspect = 16.0/9.0; break; - case HDMI_ASPECT_5_4: display_aspect = 5.0/4.0; break; - case HDMI_ASPECT_16_10: display_aspect = 16.0/10.0; break; - case HDMI_ASPECT_15_9: display_aspect = 15.0/9.0; break; - case HDMI_ASPECT_64_27: display_aspect = 64.0/27.0; break; - default: display_aspect = 16.0/9.0; break; - } - return display_aspect; -} - -static float get_display_aspect_ratio(SDTV_ASPECT_T aspect) -{ - float display_aspect; - switch (aspect) { - case SDTV_ASPECT_4_3: display_aspect = 4.0/3.0; break; - case SDTV_ASPECT_14_9: display_aspect = 14.0/9.0; break; - case SDTV_ASPECT_16_9: display_aspect = 16.0/9.0; break; - default: display_aspect = 4.0/3.0; break; - } - return display_aspect; -} - -static bool ClampToGUIDisplayLimits(int &width, int &height) -{ - float max_height = (float)g_RBP.GetGUIResolutionLimit(); - float default_ar = 16.0f/9.0f; - if (max_height < 540.0f || max_height > 1080.0f) - max_height = 1080.0f; - - float ar = (float)width/(float)height; - float max_width = max_height * default_ar; - // bigger than maximum, so need to clamp - if (width > max_width || height > max_height) { - // wider than max, so clamp width first - if (ar > default_ar) - { - width = max_width; - height = max_width / ar + 0.5f; - // taller than max, so clamp height first - } else { - height = max_height; - width = max_height * ar + 0.5f; - } - return true; - } - - return false; -} - -static void SetResolutionString(RESOLUTION_INFO &res) -{ - int gui_width = res.iScreenWidth; - int gui_height = res.iScreenHeight; - - ClampToGUIDisplayLimits(gui_width, gui_height); - - res.iWidth = gui_width; - res.iHeight = gui_height; - - res.strMode = StringUtils::Format("%dx%d (%dx%d) @ %.2f%s - Full Screen", res.iScreenWidth, res.iScreenHeight, res.iWidth, res.iHeight, res.fRefreshRate, - res.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); -} - -static SDTV_ASPECT_T get_sdtv_aspect_from_display_aspect(float display_aspect) -{ - SDTV_ASPECT_T aspect; - const float delta = 1e-3; - if(fabs(get_display_aspect_ratio(SDTV_ASPECT_16_9) - display_aspect) < delta) - { - aspect = SDTV_ASPECT_16_9; - } - else if(fabs(get_display_aspect_ratio(SDTV_ASPECT_14_9) - display_aspect) < delta) - { - aspect = SDTV_ASPECT_14_9; - } - else - { - aspect = SDTV_ASPECT_4_3; - } - return aspect; -} - -bool CRPIUtils::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions) -{ - resolutions.clear(); - - if(!m_DllBcmHost) - return false; - - /* read initial desktop resolution before probe resolutions. - * probing will replace the desktop resolution when it finds the same one. - * we replace it because probing will generate more detailed - * resolution flags we don't get with vc_tv_get_state. - */ - - if(m_initDesktopRes) - { - TV_DISPLAY_STATE_T tv_state; - - // get current display settings state - memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); - m_DllBcmHost->vc_tv_get_display_state(&tv_state); - - if ((tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) != 0) // hdtv - { - m_desktopRes.bFullScreen = true; - m_desktopRes.iWidth = tv_state.display.hdmi.width; - m_desktopRes.iHeight = tv_state.display.hdmi.height; - m_desktopRes.iScreenWidth = tv_state.display.hdmi.width; - m_desktopRes.iScreenHeight= tv_state.display.hdmi.height; - m_desktopRes.dwFlags = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode); - m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); - HDMI_PROPERTY_PARAM_T property; - property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; - vc_tv_hdmi_get_property(&property); - m_desktopRes.fRefreshRate = property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? tv_state.display.hdmi.frame_rate * (1000.0f/1001.0f) : tv_state.display.hdmi.frame_rate; - } - else if ((tv_state.state & ( VC_SDTV_NTSC | VC_SDTV_PAL )) != 0) // sdtv - { - m_desktopRes.bFullScreen = true; - m_desktopRes.iWidth = tv_state.display.sdtv.width; - m_desktopRes.iHeight = tv_state.display.sdtv.height; - m_desktopRes.iScreenWidth = tv_state.display.sdtv.width; - m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; - m_desktopRes.dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, tv_state.display.sdtv.mode, 1); - m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; - m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); - } - else if ((tv_state.state & VC_LCD_ATTACHED_DEFAULT) != 0) // lcd - { - m_desktopRes.bFullScreen = true; - m_desktopRes.iWidth = tv_state.display.sdtv.width; - m_desktopRes.iHeight = tv_state.display.sdtv.height; - m_desktopRes.iScreenWidth = tv_state.display.sdtv.width; - m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; - m_desktopRes.dwFlags = MAKEFLAGS(HDMI_RES_GROUP_INVALID, 0, 0); - m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; - m_desktopRes.fPixelRatio = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); - } - - SetResolutionString(m_desktopRes); - - m_initDesktopRes = false; - - m_desktopRes.iSubtitles = (int)(0.965 * m_desktopRes.iHeight); - - CLog::Log(LOGDEBUG, "EGL initial desktop resolution %s (%.2f)", m_desktopRes.strMode.c_str(), - m_desktopRes.fPixelRatio); - } - - if(GETFLAGS_GROUP(m_desktopRes.dwFlags) && GETFLAGS_MODE(m_desktopRes.dwFlags)) - { - GetSupportedModes(HDMI_RES_GROUP_DMT, resolutions); - GetSupportedModes(HDMI_RES_GROUP_CEA, resolutions); - } - { - AddUniqueResolution(m_desktopRes, resolutions, true); - CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x", m_desktopRes.strMode.c_str(), - m_desktopRes.dwFlags); - } - - return true; -} - -void CRPIUtils::DestroyDispmanxWindow() -{ - if(!m_DllBcmHost) - return; - - DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0); - - if (m_dispman_element != DISPMANX_NO_HANDLE) - { - m_DllBcmHost->vc_dispmanx_element_remove(dispman_update, m_dispman_element); - m_dispman_element = DISPMANX_NO_HANDLE; - } - m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update); - - if (m_dispman_display != DISPMANX_NO_HANDLE) - { - g_RBP.CloseDisplay(m_dispman_display); - m_dispman_display = DISPMANX_NO_HANDLE; - } -} - -void CRPIUtils::SetVisible(bool enable) -{ - if(!m_DllBcmHost || m_shown == enable) - return; - - CLog::Log(LOGDEBUG, "CRPIUtils::EnableDispmanxWindow(%d)", enable); - - DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0); - - if (m_dispman_element != DISPMANX_NO_HANDLE) - { - VC_RECT_T dst_rect; - if (enable) - { - dst_rect.x = 0; - dst_rect.y = 0; - dst_rect.width = m_screen_width; - dst_rect.height = m_screen_height; - } - else - { - dst_rect.x = m_screen_width; - dst_rect.y = m_screen_height; - dst_rect.width = m_screen_width; - dst_rect.height = m_screen_height; - } - m_shown = enable; - m_DllBcmHost->vc_dispmanx_element_change_attributes(dispman_update, m_dispman_element, - (1<<2), 0, 0, &dst_rect, nullptr, 0, DISPMANX_NO_ROTATE); - } - m_DllBcmHost->vc_dispmanx_update_submit(dispman_update, nullptr, nullptr); -} - -void CRPIUtils::GetSupportedModes(HDMI_RES_GROUP_T group, std::vector<RESOLUTION_INFO> &resolutions) -{ - if(!m_DllBcmHost) - return; - - //Supported HDMI CEA/DMT resolutions, preferred resolution will be returned - int32_t num_modes = 0; - HDMI_RES_GROUP_T prefer_group; - uint32_t prefer_mode; - int i; - TV_SUPPORTED_MODE_NEW_T *supported_modes = NULL; - // query the number of modes first - int max_supported_modes = m_DllBcmHost->vc_tv_hdmi_get_supported_modes_new(group, NULL, 0, &prefer_group, &prefer_mode); - - if (max_supported_modes > 0) - supported_modes = new TV_SUPPORTED_MODE_NEW_T[max_supported_modes]; - - if (supported_modes) - { - num_modes = m_DllBcmHost->vc_tv_hdmi_get_supported_modes_new(group, - supported_modes, max_supported_modes, &prefer_group, &prefer_mode); - - CLog::Log(LOGDEBUG, "EGL get supported modes (%d) = %d, prefer_group=%x, prefer_mode=%x", group, - num_modes, prefer_group, prefer_mode); - } - - if (num_modes > 0 && prefer_group != HDMI_RES_GROUP_INVALID) - { - TV_SUPPORTED_MODE_NEW_T *tv = supported_modes; - for (i=0; i < num_modes; i++, tv++) - { - RESOLUTION_INFO res; - - res.bFullScreen = true; - res.dwFlags = MAKEFLAGS(group, tv->code, tv->scan_mode); - res.fRefreshRate = (float)tv->frame_rate; - res.iWidth = tv->width; - res.iHeight = tv->height; - 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); - - if (!m_desktopRes.dwFlags && prefer_group == group && prefer_mode == tv->code) - m_desktopRes = res; - - AddUniqueResolution(res, resolutions); - CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f) %s%s:%x", i, res.strMode, res.fPixelRatio, - tv->native ? "N" : "", tv->scan_mode ? "I" : "", int(tv->code)); - - if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 48 || tv->frame_rate == 60 || tv->frame_rate == 72) - { - RESOLUTION_INFO res2 = res; - res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f); - AddUniqueResolution(res2, resolutions); - } - } - } - if (supported_modes) - delete [] supported_modes; -} - -void CRPIUtils::TvServiceCallback(uint32_t reason, uint32_t param1, uint32_t param2) -{ - CLog::Log(LOGDEBUG, "EGL tv_service_callback (%d,%d,%d)", reason, param1, param2); - switch(reason) - { - case VC_HDMI_UNPLUGGED: - break; - case VC_HDMI_STANDBY: - break; - case VC_SDTV_NTSC: - case VC_SDTV_PAL: - case VC_HDMI_HDMI: - case VC_HDMI_DVI: - //Signal we are ready now - sem_post(&m_tv_synced); - break; - default: - break; - } -} - -void CRPIUtils::CallbackTvServiceCallback(void *userdata, uint32_t reason, uint32_t param1, uint32_t param2) -{ - CRPIUtils *callback = static_cast<CRPIUtils*>(userdata); - callback->TvServiceCallback(reason, param1, param2); -} diff --git a/xbmc/windowing/rpi/RPIUtils.h b/xbmc/windowing/rpi/RPIUtils.h deleted file mode 100644 index a90c22397c..0000000000 --- a/xbmc/windowing/rpi/RPIUtils.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "windowing/Resolution.h" - -#include "platform/linux/RBP.h" - -#include <EGL/egl.h> -#include <bcm_host.h> - -class DllBcmHost; -class CRPIUtils -{ -public: - CRPIUtils(); - virtual ~CRPIUtils(); - virtual void DestroyDispmanxWindow(); - virtual void SetVisible(bool enable); - virtual bool GetNativeResolution(RESOLUTION_INFO *res) const; - virtual bool SetNativeResolution(const RESOLUTION_INFO res, EGLSurface m_nativeWindow); - virtual bool ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions); -private: - DllBcmHost *m_DllBcmHost; - DISPMANX_ELEMENT_HANDLE_T m_dispman_display; - DISPMANX_ELEMENT_HANDLE_T m_dispman_element; - TV_GET_STATE_RESP_T m_tv_state; - sem_t m_tv_synced; - RESOLUTION_INFO m_desktopRes; - int m_width; - int m_height; - int m_screen_width; - int m_screen_height; - bool m_shown; - - int m_initDesktopRes; - - void GetSupportedModes(HDMI_RES_GROUP_T group, std::vector<RESOLUTION_INFO> &resolutions); - void TvServiceCallback(uint32_t reason, uint32_t param1, uint32_t param2); - static void CallbackTvServiceCallback(void *userdata, uint32_t reason, uint32_t param1, uint32_t param2); - - int FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions, bool desktop); - int AddUniqueResolution(RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions, bool desktop = false); -}; diff --git a/xbmc/windowing/rpi/VideoSyncPi.cpp b/xbmc/windowing/rpi/VideoSyncPi.cpp deleted file mode 100644 index 04f095d284..0000000000 --- a/xbmc/windowing/rpi/VideoSyncPi.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "VideoSyncPi.h" - -#include "ServiceBroker.h" -#include "threads/Thread.h" -#include "utils/TimeUtils.h" -#include "utils/log.h" -#include "windowing/GraphicContext.h" -#include "windowing/WinSystem.h" - -#include "platform/linux/RBP.h" - -bool CVideoSyncPi::Setup(PUPDATECLOCK func) -{ - UpdateClock = func; - m_abort = false; - CServiceBroker::GetWinSystem()->Register(this); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up RPi"); - return true; -} - -void CVideoSyncPi::Run(CEvent& stopEvent) -{ - CThread* thread = CThread::GetCurrentThread(); - if (thread != nullptr) - { - /* This shouldn't be very busy and timing is important so increase priority */ - thread->SetPriority(thread->GetPriority() + 1); - } - - while (!stopEvent.Signaled() && !m_abort) - { - g_RBP.WaitVsync(); - uint64_t now = CurrentHostCounter(); - UpdateClock(1, now, m_refClock); - } -} - -void CVideoSyncPi::Cleanup() -{ - CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up RPi"); - CServiceBroker::GetWinSystem()->Unregister(this); -} - -float CVideoSyncPi::GetFps() -{ - m_fps = CServiceBroker::GetWinSystem()->GetGfxContext().GetFPS(); - CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.2f", m_fps); - return m_fps; -} - -void CVideoSyncPi::OnResetDisplay() -{ - m_abort = true; -} - -void CVideoSyncPi::RefreshChanged() -{ - if (m_fps != CServiceBroker::GetWinSystem()->GetGfxContext().GetFPS()) - m_abort = true; -} diff --git a/xbmc/windowing/rpi/VideoSyncPi.h b/xbmc/windowing/rpi/VideoSyncPi.h deleted file mode 100644 index b1c41e85b9..0000000000 --- a/xbmc/windowing/rpi/VideoSyncPi.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "guilib/DispResource.h" -#include "windowing/VideoSync.h" - -class CVideoSyncPi : public CVideoSync, IDispResource -{ -public: - CVideoSyncPi(void *clock) : CVideoSync(clock) {}; - virtual bool Setup(PUPDATECLOCK func); - virtual void Run(CEvent& stopEvent); - virtual void Cleanup(); - virtual float GetFps(); - virtual void OnResetDisplay(); - virtual void RefreshChanged(); - -private: - volatile bool m_abort; -}; diff --git a/xbmc/windowing/rpi/WinSystemRpi.cpp b/xbmc/windowing/rpi/WinSystemRpi.cpp deleted file mode 100644 index ed506d6dfe..0000000000 --- a/xbmc/windowing/rpi/WinSystemRpi.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "WinSystemRpi.h" - -#include "ServiceBroker.h" -#include "cores/AudioEngine/AESinkFactory.h" -#include "cores/AudioEngine/Sinks/AESinkPi.h" -#include "guilib/DispResource.h" -#include "settings/DisplaySettings.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "utils/log.h" -#include "windowing/GraphicContext.h" -#include "windowing/Resolution.h" - -#include "platform/linux/DllBCM.h" -#include "platform/linux/RBP.h" -#include "platform/linux/powermanagement/LinuxPowerSyscall.h" - -#include <float.h> -#include <string.h> - -#include <EGL/egl.h> -#include <EGL/eglplatform.h> - -CWinSystemRpi::CWinSystemRpi() : - m_libinput(new CLibInputHandler) -{ - m_nativeDisplay = EGL_NO_DISPLAY; - m_nativeWindow = EGL_NO_SURFACE; - - m_displayWidth = 0; - m_displayHeight = 0; - - m_stereo_mode = RENDER_STEREO_MODE_OFF; - m_delayDispReset = false; - - m_rpi = new CRPIUtils(); - - AE::CAESinkFactory::ClearSinks(); - - CAESinkPi::Register(); - std::string envSink; - if (getenv("KODI_AE_SINK")) - envSink = getenv("KODI_AE_SINK"); - - if (StringUtils::EqualsNoCase(envSink, "PULSE")) - { - OPTIONALS::PulseAudioRegister(); - } - else if (StringUtils::EqualsNoCase(envSink, "ALSA+PULSE")) - { - OPTIONALS::ALSARegister(); - OPTIONALS::PulseAudioRegister(); - } - else - { - OPTIONALS::ALSARegister(); - } - - CLinuxPowerSyscall::Register(); - m_lirc.reset(OPTIONALS::LircRegister()); - m_libinput->Start(); -} - -CWinSystemRpi::~CWinSystemRpi() -{ - if(m_nativeWindow) - { - m_nativeWindow = nullptr; - } - - delete m_rpi; - m_rpi = nullptr; -} - -bool CWinSystemRpi::InitWindowSystem() -{ - m_nativeDisplay = EGL_DEFAULT_DISPLAY; - - return CWinSystemBase::InitWindowSystem(); -} - -bool CWinSystemRpi::DestroyWindowSystem() -{ - return true; -} - -bool CWinSystemRpi::CreateNewWindow(const std::string& name, - bool fullScreen, - RESOLUTION_INFO& res) -{ - RESOLUTION_INFO current_resolution; - current_resolution.iWidth = current_resolution.iHeight = 0; - RENDER_STEREO_MODE stereo_mode = CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode(); - - m_nWidth = res.iWidth; - m_nHeight = res.iHeight; - m_displayWidth = res.iScreenWidth; - m_displayHeight = res.iScreenHeight; - m_fRefreshRate = res.fRefreshRate; - - if ((m_bWindowCreated && m_rpi->GetNativeResolution(¤t_resolution)) && - current_resolution.iWidth == res.iWidth && current_resolution.iHeight == res.iHeight && - current_resolution.iScreenWidth == res.iScreenWidth && current_resolution.iScreenHeight == res.iScreenHeight && - m_bFullScreen == fullScreen && current_resolution.fRefreshRate == res.fRefreshRate && - (current_resolution.dwFlags & D3DPRESENTFLAG_MODEMASK) == (res.dwFlags & D3DPRESENTFLAG_MODEMASK) && - m_stereo_mode == stereo_mode) - { - CLog::Log(LOGDEBUG, "CWinSystemEGL::CreateNewWindow: No need to create a new window"); - return true; - } - - int delay = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt("videoscreen.delayrefreshchange"); - if (delay > 0) - { - m_delayDispReset = true; - m_dispResetTimer.Set(delay * 100); - } - - { - CSingleLock lock(m_resourceSection); - for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) - { - (*i)->OnLostDisplay(); - } - } - - m_stereo_mode = stereo_mode; - m_bFullScreen = fullScreen; - - m_nativeWindow = static_cast<EGLNativeWindowType>(new EGL_DISPMANX_WINDOW_T); - - m_rpi->SetNativeResolution(res, m_nativeWindow); - - if (!m_delayDispReset) - { - CSingleLock lock(m_resourceSection); - // tell any shared resources - for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) - { - (*i)->OnResetDisplay(); - } - } - - return true; -} - -bool CWinSystemRpi::DestroyWindow() -{ - m_rpi->DestroyDispmanxWindow(); - m_nativeWindow = nullptr; - - return true; -} - -void CWinSystemRpi::UpdateResolutions() -{ - CWinSystemBase::UpdateResolutions(); - - RESOLUTION_INFO resDesktop, curDisplay; - std::vector<RESOLUTION_INFO> resolutions; - - if (!m_rpi->ProbeResolutions(resolutions) || resolutions.empty()) - { - CLog::Log(LOGWARNING, "%s: ProbeResolutions failed.",__FUNCTION__); - } - - /* ProbeResolutions includes already all resolutions. - * Only get desktop resolution so we can replace xbmc's desktop res - */ - if (m_rpi->GetNativeResolution(&curDisplay)) - { - resDesktop = curDisplay; - } - - RESOLUTION ResDesktop = RES_INVALID; - RESOLUTION res_index = RES_DESKTOP; - - for (size_t i = 0; i < resolutions.size(); i++) - { - // if this is a new setting, - // create a new empty setting to fill in. - if ((int)CDisplaySettings::GetInstance().ResolutionInfoSize() <= res_index) - { - RESOLUTION_INFO res; - CDisplaySettings::GetInstance().AddResolutionInfo(res); - } - - CServiceBroker::GetWinSystem()->GetGfxContext().ResetOverscan(resolutions[i]); - CDisplaySettings::GetInstance().GetResolutionInfo(res_index) = resolutions[i]; - - CLog::Log(LOGINFO, "Found resolution %d x %d with %d x %d%s @ %f Hz", resolutions[i].iWidth, - resolutions[i].iHeight, resolutions[i].iScreenWidth, resolutions[i].iScreenHeight, - resolutions[i].dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "", - resolutions[i].fRefreshRate); - - if(resDesktop.iWidth == resolutions[i].iWidth && - resDesktop.iHeight == resolutions[i].iHeight && - resDesktop.iScreenWidth == resolutions[i].iScreenWidth && - resDesktop.iScreenHeight == resolutions[i].iScreenHeight && - (resDesktop.dwFlags & D3DPRESENTFLAG_MODEMASK) == (resolutions[i].dwFlags & D3DPRESENTFLAG_MODEMASK) && - fabs(resDesktop.fRefreshRate - resolutions[i].fRefreshRate) < FLT_EPSILON) - { - ResDesktop = res_index; - } - - res_index = (RESOLUTION)((int)res_index + 1); - } - - // set RES_DESKTOP - if (ResDesktop != RES_INVALID) - { - CLog::Log(LOGINFO, "Found (%dx%d%s@%f) at %d, setting to RES_DESKTOP at %d", resDesktop.iWidth, - resDesktop.iHeight, resDesktop.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "", - resDesktop.fRefreshRate, (int)ResDesktop, (int)RES_DESKTOP); - - CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP) = CDisplaySettings::GetInstance().GetResolutionInfo(ResDesktop); - } -} - -bool CWinSystemRpi::Hide() -{ - return false; -} - -bool CWinSystemRpi::Show(bool raise) -{ - return true; -} - -void CWinSystemRpi::SetVisible(bool visible) -{ - m_rpi->SetVisible(visible); -} - -void CWinSystemRpi::Register(IDispResource *resource) -{ - CSingleLock lock(m_resourceSection); - m_resources.push_back(resource); -} - -void CWinSystemRpi::Unregister(IDispResource *resource) -{ - CSingleLock lock(m_resourceSection); - std::vector<IDispResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource); - if (i != m_resources.end()) - m_resources.erase(i); -} diff --git a/xbmc/windowing/rpi/WinSystemRpi.h b/xbmc/windowing/rpi/WinSystemRpi.h deleted file mode 100644 index 3c6f6e7477..0000000000 --- a/xbmc/windowing/rpi/WinSystemRpi.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "RPIUtils.h" -#include "rendering/gles/RenderSystemGLES.h" -#include "threads/CriticalSection.h" -#include "threads/SystemClock.h" -#include "windowing/WinSystem.h" - -#include "platform/freebsd/OptionalsReg.h" -#include "platform/linux/OptionalsReg.h" -#include "platform/linux/input/LibInputHandler.h" - -#include <EGL/egl.h> - -class IDispResource; - -class CWinSystemRpi : public CWinSystemBase -{ -public: - CWinSystemRpi(); - virtual ~CWinSystemRpi(); - - bool InitWindowSystem() override; - bool DestroyWindowSystem() override; - - bool CreateNewWindow(const std::string& name, - bool fullScreen, - RESOLUTION_INFO& res) override; - - bool DestroyWindow() override; - void UpdateResolutions() override; - - bool Hide() override; - bool Show(bool raise = true) override; - void SetVisible(bool visible); - virtual void Register(IDispResource *resource); - virtual void Unregister(IDispResource *resource); -protected: - CRPIUtils *m_rpi; - EGLDisplay m_nativeDisplay; - EGLSurface m_nativeWindow; - - int m_displayWidth; - int m_displayHeight; - - RENDER_STEREO_MODE m_stereo_mode; - - bool m_delayDispReset; - XbmcThreads::EndTime m_dispResetTimer; - - CCriticalSection m_resourceSection; - std::vector<IDispResource*> m_resources; - std::unique_ptr<OPTIONALS::CLircContainer, OPTIONALS::delete_CLircContainer> m_lirc; - std::unique_ptr<CLibInputHandler> m_libinput; -}; diff --git a/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp b/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp deleted file mode 100644 index 7a3c7ee25a..0000000000 --- a/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#include "WinSystemRpiGLESContext.h" - -#include "Application.h" -#include "ServiceBroker.h" -#include "VideoSyncPi.h" -#include "cores/RetroPlayer/process/rbpi/RPProcessInfoPi.h" -#include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h" -#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" -#include "cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h" -#include "cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h" -#include "cores/VideoPlayer/Process/rbpi/ProcessInfoPi.h" -#include "cores/VideoPlayer/VideoRenderers/RenderFactory.h" -#include "guilib/GUIComponent.h" -#include "guilib/GUIWindowManager.h" -#include "rendering/gles/ScreenshotSurfaceGLES.h" -#include "utils/log.h" - -#include "platform/linux/ScreenshotSurfaceRBP.h" - -using namespace KODI; - - -std::unique_ptr<CWinSystemBase> CWinSystemBase::CreateWinSystem() -{ - std::unique_ptr<CWinSystemBase> winSystem(new CWinSystemRpiGLESContext()); - return winSystem; -} - -bool CWinSystemRpiGLESContext::InitWindowSystem() -{ - if (!CWinSystemRpi::InitWindowSystem()) - { - return false; - } - - if (!m_pGLContext.CreateDisplay(m_nativeDisplay)) - { - return false; - } - - if (!m_pGLContext.InitializeDisplay(EGL_OPENGL_ES_API)) - { - return false; - } - - if (!m_pGLContext.ChooseConfig(EGL_OPENGL_ES2_BIT)) - { - return false; - } - - CEGLAttributesVec contextAttribs; - contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); - - if (!m_pGLContext.CreateContext(contextAttribs)) - { - return false; - } - - CProcessInfoPi::Register(); - RETRO::CRPProcessInfoPi::Register(); - RETRO::CRPProcessInfoPi::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES); - CDVDFactoryCodec::ClearHWAccels(); - MMAL::CDecoder::Register(); - CDVDFactoryCodec::ClearHWVideoCodecs(); - MMAL::CMMALVideo::Register(); - VIDEOPLAYER::CRendererFactory::ClearRenderer(); - MMAL::CMMALRenderer::Register(); - CScreenshotSurfaceGLES::Register(); - CScreenshotSurfaceRBP::Register(); - - return true; -} - -bool CWinSystemRpiGLESContext::CreateNewWindow(const std::string& name, - bool fullScreen, - RESOLUTION_INFO& res) -{ - m_pGLContext.DestroySurface(); - - if (!CWinSystemRpi::DestroyWindow()) - { - return false; - } - - if (!CWinSystemRpi::CreateNewWindow(name, fullScreen, res)) - { - return false; - } - - if (!m_pGLContext.CreateSurface(m_nativeWindow)) - { - return false; - } - - if (!m_pGLContext.BindContext()) - { - return false; - } - - if (!m_delayDispReset) - { - CSingleLock lock(m_resourceSection); - // tell any shared resources - for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) - (*i)->OnResetDisplay(); - } - - return true; -} - -bool CWinSystemRpiGLESContext::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) -{ - CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight); - return true; -} - -bool CWinSystemRpiGLESContext::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) -{ - CreateNewWindow("", fullScreen, res); - CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight); - return true; -} - -void CWinSystemRpiGLESContext::SetVSyncImpl(bool enable) -{ - if (!m_pGLContext.SetVSync(enable)) - { - CLog::Log(LOGERROR, "%s,Could not set egl vsync", __FUNCTION__); - } -} - -void CWinSystemRpiGLESContext::PresentRenderImpl(bool rendered) -{ - CGUIComponent *gui = CServiceBroker::GetGUI(); - if (gui) - CWinSystemRpi::SetVisible(gui->GetWindowManager().HasVisibleControls() || g_application.GetAppPlayer().IsRenderingGuiLayer()); - - if (m_delayDispReset && m_dispResetTimer.IsTimePast()) - { - m_delayDispReset = false; - CSingleLock lock(m_resourceSection); - // tell any shared resources - for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); ++i) - (*i)->OnResetDisplay(); - } - if (!rendered) - return; - - if (!m_pGLContext.TrySwapBuffers()) - { - CEGLUtils::Log(LOGERROR, "eglSwapBuffers failed"); - throw std::runtime_error("eglSwapBuffers failed"); - } -} - -EGLDisplay CWinSystemRpiGLESContext::GetEGLDisplay() const -{ - return m_pGLContext.GetEGLDisplay(); -} - -EGLSurface CWinSystemRpiGLESContext::GetEGLSurface() const -{ - return m_pGLContext.GetEGLSurface(); -} - -EGLContext CWinSystemRpiGLESContext::GetEGLContext() const -{ - return m_pGLContext.GetEGLContext(); -} - -EGLConfig CWinSystemRpiGLESContext::GetEGLConfig() const -{ - return m_pGLContext.GetEGLConfig(); -} - -std::unique_ptr<CVideoSync> CWinSystemRpiGLESContext::GetVideoSync(void *clock) -{ - std::unique_ptr<CVideoSync> pVSync(new CVideoSyncPi(clock)); - return pVSync; -} - diff --git a/xbmc/windowing/rpi/WinSystemRpiGLESContext.h b/xbmc/windowing/rpi/WinSystemRpiGLESContext.h deleted file mode 100644 index 0e8ef22a87..0000000000 --- a/xbmc/windowing/rpi/WinSystemRpiGLESContext.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2005-2018 Team Kodi - * This file is part of Kodi - https://kodi.tv - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSES/README.md for more information. - */ - -#pragma once - -#include "WinSystemRpi.h" -#include "rendering/gles/RenderSystemGLES.h" -#include "utils/EGLUtils.h" - -class CWinSystemRpiGLESContext : public CWinSystemRpi, public CRenderSystemGLES -{ -public: - CWinSystemRpiGLESContext() = default; - virtual ~CWinSystemRpiGLESContext() = default; - - // Implementation of CWinSystemBase via CWinSystemRpi - CRenderSystemBase *GetRenderSystem() override { return this; } - bool InitWindowSystem() override; - bool CreateNewWindow(const std::string& name, - bool fullScreen, - RESOLUTION_INFO& res) override; - - bool ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) override; - bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) override; - - virtual std::unique_ptr<CVideoSync> GetVideoSync(void *clock) override; - - EGLDisplay GetEGLDisplay() const; - EGLSurface GetEGLSurface() const; - EGLContext GetEGLContext() const; - EGLConfig GetEGLConfig() const; -protected: - void SetVSyncImpl(bool enable) override; - void PresentRenderImpl(bool rendered) override; - -private: - CEGLContextUtils m_pGLContext; - -}; diff --git a/xbmc/windows/GUIWindowSystemInfo.cpp b/xbmc/windows/GUIWindowSystemInfo.cpp index e73004d0bb..2b0c23f12c 100644 --- a/xbmc/windows/GUIWindowSystemInfo.cpp +++ b/xbmc/windows/GUIWindowSystemInfo.cpp @@ -156,7 +156,7 @@ void CGUIWindowSystemInfo::FrameMove() SET_CONTROL_LABEL(i++, "Serial: " + CServiceBroker::GetCPUInfo()->GetCPUSerial()); #endif SetControlLabel(i++, "%s %s", 22011, SYSTEM_CPU_TEMPERATURE); -#if (!defined(__arm__) && !defined(__aarch64__)) || defined(TARGET_RASPBERRY_PI) +#if (!defined(__arm__) && !defined(__aarch64__)) SetControlLabel(i++, "%s %s", 13284, SYSTEM_CPUFREQUENCY); #endif #if !(defined(__arm__) && defined(TARGET_LINUX)) |