diff --git a/projects/RPi/patches/kodi/kodi-001-isengard-rpb-backports.patch b/projects/RPi/patches/kodi/kodi-001-isengard-rpb-backports.patch new file mode 100644 index 0000000000..6e52cd22ce --- /dev/null +++ b/projects/RPi/patches/kodi/kodi-001-isengard-rpb-backports.patch @@ -0,0 +1,9022 @@ +From a19240c5a911aa272086bc25f7f90b2e010a00c2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 18:19:32 +0100 +Subject: [PATCH 01/95] [rbp/omxplayer] When opening a stream don't try to + update gui so often + +--- + xbmc/dialogs/GUIDialogBusy.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/dialogs/GUIDialogBusy.cpp b/xbmc/dialogs/GUIDialogBusy.cpp +index 2faceea..889d7a2 100644 +--- a/xbmc/dialogs/GUIDialogBusy.cpp ++++ b/xbmc/dialogs/GUIDialogBusy.cpp +@@ -68,7 +68,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10 + if (dialog) + { + dialog->Show(); ++#ifdef TARGET_RASPBERRY_PI ++ while(!event.WaitMSec(100)) ++#else + while(!event.WaitMSec(1)) ++#endif + { + g_windowManager.ProcessRenderLoop(false); + if (allowCancel && dialog->IsCanceled()) + +From 8c71ba5efd5f5cb14dc8e435cace5e755653486c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 29 Apr 2014 15:23:22 +0100 +Subject: [PATCH 02/95] [ffmpeg] Speed up wtv index creation + +The index creation is O(N^2) with number of entries (typically thousands). +On a Pi this can take more than 60 seconds to execute for a recording of a few hours. + +By replacing with an O(N) loop, this takes virtually zero time +--- + tools/depends/target/ffmpeg/Makefile | 3 +- + .../ffmpeg_Speed_up_wtv_index_creation.patch | 47 ++++++++++++++++++++++ + 2 files changed, 49 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch + +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 711182f..6e8364a 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,6 +1,6 @@ + include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -68,6 +68,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure ++ cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) +diff --git a/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch +new file mode 100644 +index 0000000..4ac5636 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch +@@ -0,0 +1,47 @@ ++commit 0e7427498cb1131671f6fe9d054245ae7e5a36f5 ++Author: popcornmix ++Date: Tue Mar 25 19:43:07 2014 +0000 ++ ++ [ffmpeg] Speed up wtv index creation ++ ++ The index creation is O(N^2) with number of entries (typically thousands). ++ On a Pi this can take more than 60 seconds to execute for a recording of a few hours. ++ ++ By replacing with an O(N) loop, this takes virtually zero time ++ ++diff --git a/lib/ffmpeg/libavformat/wtvdec.c b/lib/ffmpeg/libavformat/wtvdec.c ++index e423370..70898bd 100644 ++--- a/lib/ffmpeg/libavformat/wtvdec.c +++++ b/lib/ffmpeg/libavformat/wtvdec.c ++@@ -980,21 +980,23 @@ static int read_header(AVFormatContext *s) ++ pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16); ++ if (pb) { ++ int i; +++ AVIndexEntry *e = wtv->index_entries; +++ AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1; +++ uint64_t last_position = 0; ++ while (1) { ++ uint64_t frame_nb = avio_rl64(pb); ++ uint64_t position = avio_rl64(pb); +++ while (frame_nb > e->size && e <= e_end) { +++ e->pos = last_position; +++ e++; +++ } ++ if (avio_feof(pb)) ++ break; ++- for (i = wtv->nb_index_entries - 1; i >= 0; i--) { ++- AVIndexEntry *e = wtv->index_entries + i; ++- if (frame_nb > e->size) ++- break; ++- if (position > e->pos) ++- e->pos = position; ++- } +++ last_position = position; ++ } +++ e_end->pos = last_position; ++ wtvfile_close(pb); ++- st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp; +++ st->duration = e_end->timestamp; ++ } ++ } ++ } + +From 82a705d6e192fed880a09a76ef015a3a8bf62161 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 2 Aug 2014 17:48:04 +0100 +Subject: [PATCH 03/95] [omx] Report decoded image name + +--- + xbmc/cores/omxplayer/OMXImage.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index 161ec5a..86a683a 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -327,6 +327,7 @@ bool COMXImage::DecodeJpegToTexture(COMXImageFile *file, unsigned int width, uns + { + ret = true; + *userdata = tex; ++ CLog::Log(LOGDEBUG, "%s: decoded %s %dx%d", __func__, file->GetFilename(), width, height); + } + else + { + +From 38048e049fbf6173dd764b6fa578d3fad37099e2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 8 Mar 2014 15:36:06 +0000 +Subject: [PATCH 04/95] [hifiberry] Hack: force it to be recognised as IEC958 + capable to enable passthrough options + +--- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index e22db7a..0120bd5 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -1342,6 +1342,10 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev + if (snd_card_get_name(cardNr, &cardName) == 0) + info.m_displayName = cardName; + ++ // hack: hifiberry digi doesn't correctly report as iec958 device. Needs fixing in kernel driver ++ if (info.m_displayName == "snd_rpi_hifiberry_digi") ++ info.m_deviceType = AE_DEVTYPE_IEC958; ++ + if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 && + info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") + { + +From 20e2e2cd5bd822edb7b39dc9fd95d4d7abebcafc Mon Sep 17 00:00:00 2001 +From: Ben Avison +Date: Thu, 1 May 2014 16:28:39 +0100 +Subject: [PATCH 05/95] Improved file buffering in CArchive + +Even though memcpy is typically inlined by the compiler into byte/word loads +and stores (at least for release builds), the frequency with which 1, 2 and 4 +byte loads/stores are encountered in cases where the size is *not* +determinable at compile time is still high enough that it's worth handling +these specially. On the ARM1176JZF-S in the Raspberry Pi, this improves the +total time to open a library (in the case where it's fetched from a CArchive) +by around 4%. + +It should be noted that this code uses 16-bit and 32-bit word loads and +stores that are not necessarily aligned to their respective widths. It is +possible that there are some architectures out there which do not support +this, although all ARMs since ARMv6 have supported it (and ARMs earlier than +that are probably not powerful enough to be good targets for XBMC). +--- + xbmc/utils/Archive.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h +index 6ed0f8f..8506d95 100644 +--- a/xbmc/utils/Archive.h ++++ b/xbmc/utils/Archive.h +@@ -154,9 +154,17 @@ class CArchive + * than waiting until we attempt to put more data into an already full buffer */ + if (m_BufferRemain > size) + { ++ switch (size) ++ { ++ case 1: *m_BufferPos++ = *ptr; m_BufferRemain--; break; ++ case 2: *(uint16_t *) m_BufferPos = *(const uint16_t *) ptr; m_BufferPos += 2; m_BufferRemain -= 2; break; ++ case 4: *(uint32_t *) m_BufferPos = *(const uint32_t *) ptr; m_BufferPos += 4; m_BufferRemain -= 4; break; ++ default: + memcpy(m_BufferPos, ptr, size); + m_BufferPos += size; + m_BufferRemain -= size; ++ break; ++ } + return *this; + } + else +@@ -171,9 +179,17 @@ class CArchive + /* Note, refilling the buffer is deferred until we know we need to read more from it */ + if (m_BufferRemain >= size) + { ++ switch (size) ++ { ++ case 1: *ptr = *m_BufferPos++; m_BufferRemain--; break; ++ case 2: *(uint16_t *) ptr = *(const uint16_t *) m_BufferPos; m_BufferPos += 2; m_BufferRemain -= 2; break; ++ case 4: *(uint32_t *) ptr = *(const uint32_t *) m_BufferPos; m_BufferPos += 4; m_BufferRemain -= 4; break; ++ default: + memcpy(ptr, m_BufferPos, size); + m_BufferPos += size; + m_BufferRemain -= size; ++ break; ++ } + return *this; + } + else + +From 05fb7f2a00d3922bec218d905b91f4edfe314ece Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 12 Aug 2014 00:31:36 +0100 +Subject: [PATCH 06/95] [omxcodec] Don't force software codec with dvds + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index e976634..f0059fd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3323,7 +3323,9 @@ bool CDVDPlayer::OpenVideoStream(CDVDStreamInfo& hint, bool reset) + hint.aspect = aspect; + hint.forced_aspect = true; + } ++#ifndef TARGET_RASPBERRY_PI + hint.software = true; ++#endif + } + else if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + +From 2a70374217ab2f6f7cd7f0b4c4ae4aee0a7ef83e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 10 Aug 2014 16:45:16 +0100 +Subject: [PATCH 07/95] filesystem: Make support of browsing into archives + optional + +The ability to browse, scan and play content in archives can cause problems on low powered/low memory devices. +It's quite common to see reports of a large rar file that causes xbmc to crash with an out-of-memory error when browsing or scanning. +It also can be slow as any archive in the directory is opened and extracted. + +This causes issues for people who scan library with archives disabled, then subsequently enable it. +The library has the .rar files in which don't play without removing and re-adding. + +We'll let people who don't use archives disable it manually +--- + addons/resource.language.en_gb/resources/strings.po | 9 +++++++++ + system/settings/settings.xml | 5 +++++ + xbmc/filesystem/FileDirectoryFactory.cpp | 4 ++++ + 3 files changed, 18 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index e53d588..a05173d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16519,6 +16519,15 @@ msgstr "" + #: system/settings/rbp.xml + msgctxt "#38010" + msgid "GPU accelerated" ++ ++#: system/settings/settings.xml ++msgctxt "#38020" ++msgid "Support browsing into archives" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38021" ++msgid "Allow viewing and playing files in archives (e.g. zip, rar)" + msgstr "" + + #. Setting #38011 "Videos -> Library -> Show All Items entry" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 921247f..e64b267 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -301,6 +301,11 @@ + false + + ++ ++ 1 ++ true ++ ++ + + + +diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp +index 3a5ba4e..f1f6f79 100644 +--- a/xbmc/filesystem/FileDirectoryFactory.cpp ++++ b/xbmc/filesystem/FileDirectoryFactory.cpp +@@ -41,6 +41,7 @@ + #include "Directory.h" + #include "File.h" + #include "ZipManager.h" ++#include "settings/Settings.h" + #include "settings/AdvancedSettings.h" + #include "FileItem.h" + #include "utils/StringUtils.h" +@@ -115,6 +116,8 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, + return NULL; + } + #endif ++ if (CSettings::Get().GetBool("filelists.browsearchives")) ++ { + if (url.IsFileType("zip")) + { + CURL zipURL = URIUtils::CreateArchivePath("zip", url); +@@ -188,6 +191,7 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, + } + return NULL; + } ++ } + if (url.IsFileType("xsp")) + { // XBMC Smart playlist - just XML renamed to XSP + // read the name of the playlist in + +From 518265fccf644ee67f68395d5ab852cccf9ba304 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 13:06:57 +0000 +Subject: [PATCH 09/95] [rbp] Make cachemembuffersize default depend on memory + size + +--- + xbmc/linux/RBP.cpp | 5 +++++ + xbmc/settings/AdvancedSettings.cpp | 5 +++++ + 2 files changed, 10 insertions(+) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index ba1a3d0..5119949 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -22,6 +22,7 @@ + #if defined(TARGET_RASPBERRY_PI) + + #include "settings/Settings.h" ++#include "settings/AdvancedSettings.h" + #include "utils/log.h" + + #include "cores/omxplayer/OMXImage.h" +@@ -84,6 +85,9 @@ bool CRBP::Initialize() + if (!m_gui_resolution_limit) + m_gui_resolution_limit = m_gpu_mem < 128 ? 720:1080; + ++ if (g_advancedSettings.m_cacheMemBufferSize == ~0U) ++ g_advancedSettings.m_cacheMemBufferSize = m_arm_mem < 256 ? 1024 * 1024 * 2 : 1024 * 1024 * 20; ++ + g_OMXImage.Initialize(); + m_omx_image_init = true; + return true; +@@ -96,6 +100,7 @@ void CRBP::LogFirmwareVerison() + response[sizeof(response) - 1] = '\0'; + CLog::Log(LOGNOTICE, "Raspberry PI firmware version: %s", response); + CLog::Log(LOGNOTICE, "ARM mem: %dMB GPU mem: %dMB MPG2:%d WVC1:%d", m_arm_mem, m_gpu_mem, m_codec_mpg2_enabled, m_codec_wvc1_enabled); ++ CLog::Log(LOGNOTICE, "cacheMemBufferSize: %dMB", g_advancedSettings.m_cacheMemBufferSize >> 20); + m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config int"); + response[sizeof(response) - 1] = '\0'; + CLog::Log(LOGNOTICE, "Config:\n%s", response); +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index ba15502..7797edf 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -352,7 +352,12 @@ void CAdvancedSettings::Initialize() + m_bPVRAutoScanIconsUserSet = false; + m_iPVRNumericChannelSwitchTimeout = 1000; + ++#ifdef TARGET_RASPBERRY_PI ++ // want default to be memory dependent, but interface to gpu not available yet, so set in RBP.cpp ++ m_cacheMemBufferSize = ~0; ++#else + m_cacheMemBufferSize = 1024 * 1024 * 20; ++#endif + m_networkBufferMode = 0; // Default (buffer all internet streams/filesystems) + // the following setting determines the readRate of a player data + // as multiply of the default data read rate + + +From 3f0d3c71caddb7da678557c66556e8aeb2095247 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 30 May 2014 14:58:43 +0100 +Subject: [PATCH 11/95] [settings] Experiment: Report DESKTOP resolution in + video settings + +--- + xbmc/settings/DisplaySettings.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp +index 1fafd9a..e0288aa 100644 +--- a/xbmc/settings/DisplaySettings.cpp ++++ b/xbmc/settings/DisplaySettings.cpp +@@ -674,6 +674,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, + vector resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate); + for (vector::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution) + { ++if (resolution->ResInfo_Index == RES_DESKTOP) ++ list.push_back(make_pair(StringUtils::Format("DESKTOP"), resolution->ResInfo_Index)); ++else + list.push_back(make_pair( + StringUtils::Format("%dx%d%s", resolution->width, resolution->height, + ModeFlagsToString(resolution->flags, false).c_str()), + +From 73cd1a696ea4d3484cb49de949ce6081f600e3fd Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 16 Aug 2014 21:01:42 +0100 +Subject: [PATCH 12/95] omxrender: Hacks to reduce GUI rendering rate when + playing video + +--- + .../resource.language.en_gb/resources/strings.po | 27 ++++++++++++++++++++++ + system/settings/rbp.xml | 16 +++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index a05173d..6e4e8be 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16541,3 +16541,30 @@ msgstr "" + msgctxt "#38012" + msgid "Show "All Items" entry in directory (for example All Albums or All Seasons)" + msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38000" ++msgid "Limit GUI updates when playing video" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38001" ++msgid "This can reduce CPU when playing video by updating the overlays less often" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38002" ++msgid "Off" ++msgstr "" ++ ++msgctxt "#38003" ++msgid "5 fps" ++msgstr "" ++ ++msgctxt "#38004" ++msgid "10 fps" ++msgstr "" ++ ++msgctxt "#38005" ++msgid "24 fps" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index bd3e2ad..ca1a571 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -15,6 +15,22 @@ + + + ++ ++ ++ 2 ++ 10 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + + +From 71e6bae9785ce14a6bf8230d60034e52cec42ad2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 24 Jan 2015 17:33:30 +0000 +Subject: [PATCH 13/95] renderer: Allow gui updates to be skipped when playing + video + +--- + xbmc/Application.cpp | 43 ++++++++++++++++++++++++++-------------- + xbmc/guilib/GUIWindowManager.cpp | 2 -- + xbmc/guilib/GUIWindowManager.h | 3 ++- + 3 files changed, 30 insertions(+), 18 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index f2b47dd..6f9849d 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -1949,27 +1949,41 @@ void CApplication::Render() + if(!g_Windowing.BeginRender()) + return; + +- CDirtyRegionList dirtyRegions = g_windowManager.GetDirty(); +- if(g_graphicsContext.GetStereoMode()) ++ CDirtyRegionList dirtyRegions; ++ ++ // render gui layer ++ int fps = 0; ++ if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); ++ unsigned int now = XbmcThreads::SystemClockMillis(); ++ unsigned int frameTime = now - m_lastRenderTime; ++ if (fps <= 0 || frameTime * fps >= 1000) + { +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); +- if(RenderNoPresent()) +- hasRendered = true; ++ dirtyRegions = g_windowManager.GetDirty(); ++ if (g_graphicsContext.GetStereoMode()) ++ { ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); ++ if (RenderNoPresent()) ++ hasRendered = true; + +- if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO) ++ if (g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO) ++ { ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT); ++ if (RenderNoPresent()) ++ hasRendered = true; ++ } ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); ++ } ++ else + { +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT); +- if(RenderNoPresent()) ++ if (RenderNoPresent()) + hasRendered = true; + } +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); +- } +- else +- { +- if(RenderNoPresent()) +- hasRendered = true; + } + ++ // render video layer ++ g_windowManager.RenderEx(); ++ + g_Windowing.EndRender(); + + // execute post rendering actions (finalize window closing) +@@ -1981,7 +1995,6 @@ void CApplication::Render() + g_infoManager.ResetCache(); + lock.Leave(); + +- unsigned int now = XbmcThreads::SystemClockMillis(); + if (hasRendered) + m_lastRenderTime = now; + +diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp +index 1ae90ae..e795c75 100644 +--- a/xbmc/guilib/GUIWindowManager.cpp ++++ b/xbmc/guilib/GUIWindowManager.cpp +@@ -986,8 +986,6 @@ bool CGUIWindowManager::Render() + CGUITexture::DrawQuad(*i, 0x4c00ff00); + } + +- RenderEx(); +- + return hasRendered; + } + +diff --git a/xbmc/guilib/GUIWindowManager.h b/xbmc/guilib/GUIWindowManager.h +index 09a7b9c..b492534 100644 +--- a/xbmc/guilib/GUIWindowManager.h ++++ b/xbmc/guilib/GUIWindowManager.h +@@ -94,6 +94,8 @@ class CGUIWindowManager + */ + bool Render(); + ++ void RenderEx() const; ++ + /*! \brief Do any post render activities. + */ + void AfterRender(); +@@ -169,7 +171,6 @@ class CGUIWindowManager + #endif + private: + void RenderPass() const; +- void RenderEx() const; + + void LoadNotOnDemandWindows(); + void UnloadNotOnDemandWindows(); + +From 153a026b4e7ec380925c3096b788a3728a16111b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 9 Sep 2014 12:04:26 +0100 +Subject: [PATCH 14/95] egl: Treat unknown display aspect ratio as square pixel + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 749de8d..98072e8 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -447,7 +447,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + 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 = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); ++ 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); + // Also add 3D flags + if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) + { +@@ -474,7 +474,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; + m_desktopRes.dwFlags = D3DPRESENTFLAG_INTERLACED; + m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; +- m_desktopRes.fPixelRatio = get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); ++ 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); + +From 1be64b18c6da636aee9bcc23d804a7921679c957 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 14:24:56 +0100 +Subject: [PATCH 15/95] [omxplayer] Only enable audio clock master when A/V + sync method is set to audio clock + +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 45a35bb..691b9a7 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -247,7 +247,8 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ if((CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) || ++ CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -273,7 +274,7 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock")) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); + +From 74e5c08023c7d7652a7ad179f9ce41758e0f4c71 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 19 Sep 2014 11:54:49 +0100 +Subject: [PATCH 16/95] [dvdplayer/rbp] Add pi specific option to maintain + vsync with pll adjustment + +New A/V sync option in settings/video/playback to do "Adjust PLL". +This uses video clock (so perfect video syncing) but avoids having to resample +or drop/dupe audio packets which is normally required. + +Needed updated firmware + +[dvdplayeraudio] Add advancedsetting for configuring max pll adjustment + +[dvdplayer] Allow pll adjustment to go higher, but tail off more gradually +--- + .../resource.language.en_gb/resources/strings.po | 24 ++++++++++++++- + system/settings/settings.xml | 14 +++++++++ + xbmc/cores/AudioEngine/Utils/AEUtil.h | 3 +- + xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 36 +++++++++++++++++++--- + xbmc/cores/dvdplayer/DVDPlayerAudio.h | 3 ++ + xbmc/linux/RBP.cpp | 14 +++++++++ + xbmc/linux/RBP.h | 1 + + xbmc/settings/AdvancedSettings.cpp | 2 ++ + xbmc/settings/AdvancedSettings.h | 1 + + 9 files changed, 91 insertions(+), 7 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 6e4e8be..5f1d5b1 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -6334,7 +6334,22 @@ msgctxt "#13459" + msgid "Use OMXPlayer for decoding of video files." + msgstr "" + +-#empty strings from id 13460 to 13504 ++#empty strings from id 13460 to 13499 ++ ++#: system/settings/settings.xml ++msgctxt "#13500" ++msgid "A/V sync method" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#13503" ++msgid "Resample audio" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#13504" ++msgid "Adjust PLL" ++msgstr "" + + #: system/settings/settings.xml + msgctxt "#13505" +@@ -16568,3 +16583,10 @@ msgstr "" + msgctxt "#38005" + msgid "24 fps" + msgstr "" ++ ++#. Description of setting "Videos -> Playback -> A/V sync method" with label #13500 ++#: system/settings/settings.xml ++msgctxt "#38006" ++msgid "Audio has to stay in sync, this can either be done by resampling, or adjusting the PLL" ++msgstr "" ++ +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index e64b267..144105b 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -569,6 +569,20 @@ + false + + ++ ++ 2 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ true ++ ++ ++ + + 2 + 0 +diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h +index 782a9ba..3e0390c 100644 +--- a/xbmc/cores/AudioEngine/Utils/AEUtil.h ++++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h +@@ -57,7 +57,8 @@ enum AVSync + { + SYNC_DISCON = 0, + SYNC_SKIPDUP, +- SYNC_RESAMPLE ++ SYNC_RESAMPLE, ++ SYNC_PLLADJUST + }; + + struct AEDelayStatus +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +index 15e6f73..247e44a 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +@@ -25,6 +25,7 @@ + #include "DVDCodecs/DVDCodecs.h" + #include "DVDCodecs/DVDFactoryCodec.h" + #include "settings/Settings.h" ++#include "settings/AdvancedSettings.h" + #include "video/VideoReferenceClock.h" + #include "utils/log.h" + #include "utils/TimeUtils.h" +@@ -113,6 +114,9 @@ CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent) + m_started = false; + m_silence = false; + m_resampleratio = 1.0; ++ m_plladjust = 1.0; ++ m_last_plladjust = 1.0; ++ m_last_error = 0.0; + m_synctype = SYNC_DISCON; + m_setsynctype = SYNC_DISCON; + m_prevsynctype = -1; +@@ -186,11 +190,13 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec ) + m_synctype = SYNC_DISCON; + m_setsynctype = SYNC_DISCON; + if (CSettings::Get().GetBool("videoplayer.usedisplayasclock")) +- m_setsynctype = SYNC_RESAMPLE; ++ m_setsynctype = CSettings::Get().GetInt("videoplayer.synctype"); + m_prevsynctype = -1; + + m_error = 0; + m_errors.Flush(); ++ m_plladjust = 1.0; ++ m_last_plladjust = 1.0; + m_integral = 0; + m_prevskipped = false; + m_syncclock = true; +@@ -233,7 +239,6 @@ void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers) + + // uninit queue + m_messageQueue.End(); +- + CLog::Log(LOGNOTICE, "Deleting audio codec"); + if (m_pAudioCodec) + { +@@ -481,7 +486,11 @@ void CDVDPlayerAudio::UpdatePlayerInfo() + //print the inverse of the resample ratio, since that makes more sense + //if the resample ratio is 0.5, then we're playing twice as fast + if (m_synctype == SYNC_RESAMPLE) +- s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio; ++ s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms"; ++ if (m_synctype == SYNC_SKIPDUP) ++ s << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms"; ++ if (m_synctype == SYNC_PLLADJUST) ++ s << ", pll:" << fixed << setprecision(5) << m_last_plladjust << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms"; + + s << ", att:" << fixed << setprecision(1) << log(GetCurrentAttenuation()) * 20.0f << " dB"; + +@@ -635,8 +644,8 @@ void CDVDPlayerAudio::SetSyncType(bool passthrough) + + if (m_synctype != m_prevsynctype) + { +- const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "invalid"}; +- int synctype = (m_synctype >= 0 && m_synctype <= 2) ? m_synctype : 3; ++ const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "pll adjust", "invalid"}; ++ int synctype = (m_synctype >= 0 && m_synctype <= 3) ? m_synctype : 4; + CLog::Log(LOGDEBUG, "CDVDPlayerAudio:: synctype set to %i: %s", m_synctype, synctypes[synctype]); + m_prevsynctype = m_synctype; + } +@@ -723,7 +732,19 @@ void CDVDPlayerAudio::HandleSyncError(double duration) + proportional = m_error / DVD_TIME_BASE / proportionaldiv; + } + m_resampleratio = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral; ++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s rr:%.5f error:%.3fms", __FUNCTION__, m_resampleratio, m_error * 1e-3); ++ } ++ else if (m_synctype == SYNC_PLLADJUST) ++ { ++#if defined(TARGET_RASPBERRY_PI) ++ double e = std::max(std::min(m_error / DVD_MSEC_TO_TIME(50), 1.0), -1.0); ++ double adjust = g_advancedSettings.m_maxPllAdjust * 1e-6; ++ m_plladjust = 1.0 + e * adjust; ++ m_last_plladjust = g_RBP.AdjustHDMIClock(m_plladjust); ++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.5f (%.5f) error:%.6f e:%.6f a:%f", __FUNCTION__, m_plladjust, m_last_plladjust, m_error, e * adjust, adjust ); ++#endif + } ++ m_last_error = m_error; + } + } + +@@ -748,6 +769,7 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + { + m_dvdAudio.SetPlayingPts(m_audioClock); + } ++ m_plladjust = 1.0; + } + else if (m_synctype == SYNC_DISCON) + { +@@ -782,6 +804,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + m_dvdAudio.SetResampleRatio(m_resampleratio); + m_dvdAudio.AddPackets(audioframe); + } ++ else if (m_synctype == SYNC_PLLADJUST) ++ { ++ m_dvdAudio.AddPackets(audioframe); ++ } + + return true; + } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +index d58c45c..87de5fd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +@@ -231,6 +231,9 @@ class CDVDPlayerAudio : public CThread, public IDVDStreamPlayerAudio + bool m_prevskipped; + double m_maxspeedadjust; + double m_resampleratio; //resample ratio when using SYNC_RESAMPLE, used for the codec info ++ double m_plladjust; // for display using SYNC_PLLADJUST ++ double m_last_error; // for display using SYNC_PLLADJUST ++ double m_last_plladjust; // for display using SYNC_PLLADJUST + + struct SInfo + { +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index 5119949..ce09fce 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -212,4 +212,18 @@ void CRBP::Deinitialize() + m_initialized = false; + m_omx_initialized = false; + } ++ ++double CRBP::AdjustHDMIClock(double adjust) ++{ ++ char response[80]; ++ vc_gencmd(response, sizeof response, "hdmi_adjust_clock %f", adjust); ++ float new_adjust = 1.0f; ++ char *p = strchr(response, '='); ++ if (p) ++ new_adjust = atof(p+1); ++ CLog::Log(LOGDEBUG, "CRBP::%s(%.4f) = %.4f", __func__, adjust, new_adjust); ++ return new_adjust; ++} ++ ++ + #endif +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 4fd18f3..6456657 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -58,6 +58,7 @@ class CRBP + 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; } + void WaitVsync(); ++ double AdjustHDMIClock(double adjust); + + private: + DllBcmHost *m_DllBcmHost; +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 7797edf..59d45c8 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -110,6 +110,7 @@ void CAdvancedSettings::Initialize() + m_audioHeadRoom = 0; + m_ac3Gain = 12.0f; + m_audioApplyDrc = -1.0f; ++ m_maxPllAdjust = 1000; + m_dvdplayerIgnoreDTSinWAV = false; + + //default hold time of 25 ms, this allows a 20 hertz sine to pass undistorted +@@ -468,6 +469,7 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file) + if (pElement) + { + XMLUtils::GetFloat(pElement, "ac3downmixgain", m_ac3Gain, -96.0f, 96.0f); ++ XMLUtils::GetInt(pElement, "maxplladjust", m_maxPllAdjust, 0, 1000000); + XMLUtils::GetInt(pElement, "headroom", m_audioHeadRoom, 0, 12); + XMLUtils::GetString(pElement, "defaultplayer", m_audioDefaultPlayer); + // 101 on purpose - can be used to never automark as watched +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index b0b4df1..5e0b14c 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -141,6 +141,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + + int m_audioHeadRoom; + float m_ac3Gain; ++ int m_maxPllAdjust; + std::string m_audioDefaultPlayer; + float m_audioPlayCountMinimumPercent; + bool m_dvdplayerIgnoreDTSinWAV; + +From 7c19395b346de7b8a0f86059e726d1132cb41811 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 27 Sep 2014 15:32:37 +0100 +Subject: [PATCH 17/95] [dvdplayer] exerimental: don't raise priority of audio + thread + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index f0059fd..eff7d0e 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3308,7 +3308,11 @@ bool CDVDPlayer::OpenAudioStream(CDVDStreamInfo& hint, bool reset) + m_dvdPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); + + /* audio normally won't consume full cpu, so let it have prio */ ++#ifdef TARGET_RASPBERRY_PI ++ m_dvdPlayerAudio->SetPriority(GetPriority()); ++#else + m_dvdPlayerAudio->SetPriority(GetPriority()+1); ++#endif + return true; + } + + +From 1d26af83fec9b740c1fedfb5ac36fba0f3de6910 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 24 Sep 2014 23:13:52 +0100 +Subject: [PATCH 18/95] [audio] Add settings option to boost centre channel + when downmixing + +This allows a dB volume increase to be added to centre channel. +This can help improve dialgue in the presence of background music/effects. +It can go up to 30dB for testing purposes, but value of 6 is probably more reasonable. +It is recommended to ensure "Normalise levels on downmix" is enabled when boosting by large values to avoid clipping. + +Should work with Pi Sink (dvdplayer/paplayer) and omxplayer +--- + addons/resource.language.en_gb/resources/strings.po | 14 ++++++++++++++ + system/settings/settings.xml | 12 ++++++++++++ + .../Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp | 7 +++++++ + .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 ++++++ + xbmc/cores/omxplayer/OMXAudio.cpp | 6 ++++++ + 5 files changed, 45 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 5f1d5b1..7bae69d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16590,3 +16590,17 @@ msgctxt "#38006" + msgid "Audio has to stay in sync, this can either be done by resampling, or adjusting the PLL" + msgstr "" + ++#: system/settings/settings.xml ++msgctxt "#38007" ++msgid "Boost centre channel when downmixing" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38008" ++msgid "Increase this value to make the dialogue louder compared to background sounds when downmixing multichannel audio" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38009" ++msgid "%i dB" ++msgstr "" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 144105b..a40ecb5 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2640,6 +2640,18 @@ + true + + ++ ++ 2 ++ 0 ++ ++ 0 ++ 1 ++ 30 ++ ++ ++ 38009 ++ ++ + + HAS_AE_QUALITY_LEVELS + 2 +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +index e4ddf9e..34d0152 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +@@ -20,6 +20,7 @@ + + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "ActiveAEResampleFFMPEG.h" ++#include "settings/Settings.h" + #include "utils/log.h" + + extern "C" { +@@ -105,6 +106,12 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + if (remapLayout) + { +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +index b037317..fa8112d 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +@@ -164,6 +164,12 @@ bool CActiveAEResamplePi::Init(uint64_t dst_chan_layout, int dst_channels, int d + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + if (remapLayout) + { +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 691b9a7..602d2fa 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -634,6 +634,12 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + // stereo upmix + if (upmix && m_src_channels == 2 && m_dst_channels > 2) + +From 5026e6015ee5dcc99df426a1881dc6fbcf25fce6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:40:06 +0100 +Subject: [PATCH 19/95] [SinkPi] Handle multichannel layout more like OMXAudio + +--- + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 318df3b..3cb6bfb 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -93,9 +93,9 @@ static void SetAudioProps(bool stream_channels, uint32_t channel_map) + CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map); + } + +-static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) ++static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough) + { +- unsigned int channels = format.m_channelLayout.Count(); ++ unsigned int channels = channelLayout.Count(); + uint32_t channel_map = 0; + if (passthrough) + return 0; +@@ -134,12 +134,12 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) + // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels + // but no BR BL channels, we use the wide map in order to open only the num of channels really + // needed. +- if (format.m_channelLayout.HasChannel(AE_CH_BL) && !format.m_channelLayout.HasChannel(AE_CH_SL)) ++ if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL)) + map = map_back; + + for (unsigned int i = 0; i < channels; ++i) + { +- AEChannel c = format.m_channelLayout[i]; ++ AEChannel c = channelLayout[i]; + unsigned int chan = 0; + if ((unsigned int)c < sizeof map_normal / sizeof *map_normal) + chan = map[(unsigned int)c]; +@@ -170,9 +170,9 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) + 0xff, // 7 + 0x13, // 7.1 + }; +- uint8_t cea = format.m_channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; ++ uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; + if (cea == 0xff) +- CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, format.m_channelLayout.HasChannel(AE_CH_LFE), channels); ++ CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels); + + channel_map |= cea << 24; + +@@ -209,7 +209,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; + format.m_frameSamples = format.m_frames * channels; + +- SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough)); ++ SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough)); + + m_format = format; + m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate); + +From 2505e8b351bc7d8bc1a3b8e0c26d1375f7bfc724 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 15:23:51 +0000 +Subject: [PATCH 20/95] [rbp] Default extract thumbnails to false + +It can take 80 seconds for a single file on a Pi. It can cause crashes with out-of-memory errors. +It genereates a lot of support issues. Best to default to disabled and let users enable it if they must +--- + system/settings/rbp.xml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index ca1a571..f7cb75e 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -39,6 +39,16 @@ + + + ++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ + + +
+ +From e6c1438c3f8a9b9ed608219810e686ffdc2487ba Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 15 Nov 2014 12:03:34 +0000 +Subject: [PATCH 24/95] [dvdplayer] Add lock for player creation + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 3 +++ + xbmc/cores/dvdplayer/DVDPlayer.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index eff7d0e..3180fe9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -531,6 +531,7 @@ int CSelectionStreams::CountSource(StreamType type, StreamSource source) const + + void CDVDPlayer::CreatePlayers() + { ++ CSingleLock lock(m_players_lock); + #ifdef HAS_OMXPLAYER + if (m_omxplayer_mode && OMXPlayerUnsuitable(m_HasVideo, m_HasAudio, m_pDemuxer, m_pInputStream, m_SelectionStreams)) + { +@@ -560,6 +561,7 @@ void CDVDPlayer::CreatePlayers() + + void CDVDPlayer::DestroyPlayers() + { ++ CSingleLock lock(m_players_lock); + if (!m_players_created) + return; + delete m_dvdPlayerVideo; +@@ -4150,6 +4152,7 @@ double CDVDPlayer::GetQueueTime() + + void CDVDPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info) + { ++ CSingleLock lock(m_players_lock); + info.bitrate = m_dvdPlayerVideo->GetVideoBitrate(); + + std::string retVal; +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h +index 64c9974..ae5edc9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -557,4 +557,5 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer + // omxplayer variables + struct SOmxPlayerState m_OmxPlayerState; + bool m_omxplayer_mode; // using omxplayer acceleration ++ CCriticalSection m_players_lock; + }; + +From e8a90602e1fab767227e2101a400885d8e12d8c0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 24 Nov 2014 22:07:25 +0000 +Subject: [PATCH 25/95] [dvdplayervideo] Prod decoder when in stills mode + +An asynchronous hardware decoder doesn't only produce output pictures when new packets arrive. +In dvd stills mode give it a chance to return pictures that weren't ready when frame was decoded. +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 46 ++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 69dc501..5832c58 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -323,7 +323,8 @@ void CDVDPlayerVideo::Process() + + while (!m_bStop) + { +- int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000; ++ bool bPictureWaiting = m_hints.stills && (m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE) & VC_PICTURE); ++ int iQueueTimeOut = (int)(bPictureWaiting ? 0 : (m_hints.stills || m_stalled) ? frametime / 4 : frametime * 10) / 1000; + int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0; + + CDVDMsg* pMsg; +@@ -340,27 +341,36 @@ void CDVDPlayerVideo::Process() + if( iPriority ) + continue; + +- //Okey, start rendering at stream fps now instead, we are likely in a stillframe +- if( !m_stalled ) ++ // check for picture waiting ++ if (bPictureWaiting) + { +- if(m_started) +- CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate); +- m_stalled = true; +- pts+= frametime*4; ++ // create a dummy demuxer packet to prod the decode logic ++ pMsg = new CDVDMsgDemuxerPacket(CDVDDemuxUtils::AllocateDemuxPacket(0), false); + } +- +- //Waiting timed out, output last picture +- if( picture.iFlags & DVP_FLAG_ALLOCATED ) ++ else + { +- //Remove interlaced flag before outputting +- //no need to output this as if it was interlaced +- picture.iFlags &= ~DVP_FLAG_INTERLACED; +- picture.iFlags |= DVP_FLAG_NOSKIP; +- OutputPicture(&picture, pts); +- pts+= frametime; +- } ++ //Okey, start rendering at stream fps now instead, we are likely in a stillframe ++ if( !m_stalled ) ++ { ++ if(m_started) ++ CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate); ++ m_stalled = true; ++ pts+= frametime*4; ++ } + +- continue; ++ //Waiting timed out, output last picture ++ if( picture.iFlags & DVP_FLAG_ALLOCATED ) ++ { ++ //Remove interlaced flag before outputting ++ //no need to output this as if it was interlaced ++ picture.iFlags &= ~DVP_FLAG_INTERLACED; ++ picture.iFlags |= DVP_FLAG_NOSKIP; ++ OutputPicture(&picture, pts); ++ pts+= frametime; ++ } ++ ++ continue; ++ } + } + + if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) + +From 9e6dcba2e48b1c0c52882582c45c38371e594077 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 27 Nov 2014 16:31:56 +0000 +Subject: [PATCH 26/95] [languageinvoker] Reduce priority of python threads + +--- + xbmc/interfaces/generic/LanguageInvokerThread.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/xbmc/interfaces/generic/LanguageInvokerThread.cpp b/xbmc/interfaces/generic/LanguageInvokerThread.cpp +index fcdd063..16f0c89 100644 +--- a/xbmc/interfaces/generic/LanguageInvokerThread.cpp ++++ b/xbmc/interfaces/generic/LanguageInvokerThread.cpp +@@ -50,6 +50,11 @@ bool CLanguageInvokerThread::execute(const std::string &script, const std::vecto + m_args = arguments; + + Create(); ++ #ifdef TARGET_RASPBERRY_PI ++ /* low prio */ ++ SetPriority(GetPriority()-1); ++ #endif ++ + return true; + } + + +From 8d105a5da7c724d97dba995fe660e547b25d3e2e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Dec 2013 16:55:05 +0000 +Subject: [PATCH 27/95] logging: Add microsecond timer to log messages + +--- + xbmc/utils/log.cpp | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp +index 3443f12..31c4a99 100644 +--- a/xbmc/utils/log.cpp ++++ b/xbmc/utils/log.cpp +@@ -24,6 +24,7 @@ + #include "threads/Thread.h" + #include "utils/StringUtils.h" + #include "CompileInfo.h" ++#include "utils/TimeUtils.cpp" + + static const char* const levelNames[] = + {"DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "SEVERE", "FATAL", "NONE"}; +@@ -198,19 +199,31 @@ void CLog::PrintDebugString(const std::string& line) + + bool CLog::WriteLogString(int logLevel, const std::string& logString) + { ++#if defined(TARGET_LINUX) ++ static const char* prefixFormat = "%02.2d:%02.2d:%02.2d %10.6f T:%" PRIu64" %7s: "; ++#else + static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%" PRIu64" %7s: "; +- ++#endif + std::string strData(logString); + /* fixup newline alignment, number of spaces should equal prefix length */ + StringUtils::Replace(strData, "\n", "\n "); + + int hour, minute, second; + s_globals.m_platform.GetCurrentLocalTime(hour, minute, second); +- ++ ++#if defined(TARGET_LINUX) ++ struct timespec now; ++ clock_gettime(CLOCK_MONOTONIC, &now); ++ float Now = now.tv_sec + now.tv_nsec * 1e-9; ++#endif ++ + strData = StringUtils::Format(prefixFormat, + hour, + minute, + second, ++#if defined(TARGET_LINUX) ++ Now, ++#endif + (uint64_t)CThread::GetCurrentThreadId(), + levelNames[logLevel]) + strData; + + +From a97d46591a1178899bffc8511d4b82f5b2d50a44 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:24:42 +0200 +Subject: [PATCH 28/95] Added some vc_tv_* functions that were missing in + DllBCM. + +--- + xbmc/linux/DllBCM.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/xbmc/linux/DllBCM.h b/xbmc/linux/DllBCM.h +index b92fdb8..9c7e293 100644 +--- a/xbmc/linux/DllBCM.h ++++ b/xbmc/linux/DllBCM.h +@@ -48,6 +48,9 @@ class 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, +@@ -92,6 +95,12 @@ class DllBcmHost : public DllDynamic, DllBcmHostInterface + { 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); }; + +From c51d5fd32f12c2aec6094a813ef96fb7e037d21d Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:29:03 +0200 +Subject: [PATCH 29/95] Added private utility function to map a float display + aspect, to the respective SDTV_ASPECT_* enum value. + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 98072e8..da36944 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -412,6 +412,25 @@ static void SetResolutionString(RESOLUTION_INFO &res) + res.dwFlags & D3DPRESENTFLAG_MODE3DTB ? " 3DTB" : "", + res.dwFlags & D3DPRESENTFLAG_MODE3DSBS ? " 3DSBS" : ""); + } ++ ++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; ++} + #endif + + bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &resolutions) + +From 71135169f92ecb7e07a275707c33de2288b304de Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:50:58 +0200 +Subject: [PATCH 30/95] Changed SDTV resolutions to be treated similarly to + HDMI resolutions in SetNativeResolution. This means that the SDTV interface + is powered up and set to the right mode. + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 36 ++++++++++++++++++++----- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h | 1 - + 2 files changed, 29 insertions(+), 8 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index da36944..2ebd74c 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -222,7 +222,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + + DestroyDispmaxWindow(); + +- if(!m_fixedMode && GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) ++ if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) + { + sem_init(&m_tv_synced, 0, 0); + m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this); +@@ -276,6 +276,33 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + + 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\n", ++ 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\n", ++ 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 = m_DllBcmHost->vc_dispmanx_display_open(0); + +@@ -441,8 +468,6 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + if(!m_DllBcmHost) + return false; + +- m_fixedMode = false; +- + /* read initial desktop resolution before probe resolutions. + * probing will replace the desktop resolution when it finds the same one. + * we raplace it because probing will generate more detailed +@@ -491,7 +516,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + 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 = D3DPRESENTFLAG_INTERLACED; ++ 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); + } +@@ -514,9 +539,6 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags); + } + +- if(resolutions.size() < 2) +- m_fixedMode = true; +- + DLOG("CEGLNativeTypeRaspberryPI::ProbeResolutions\n"); + return true; + #else +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +index 59401f5..a0acb1a 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +@@ -59,7 +59,6 @@ class CEGLNativeTypeRaspberryPI : public CEGLNativeType + DISPMANX_ELEMENT_HANDLE_T m_dispman_element; + TV_GET_STATE_RESP_T m_tv_state; + sem_t m_tv_synced; +- bool m_fixedMode; + RESOLUTION_INFO m_desktopRes; + int m_width; + int m_height; + +From e655ab07928217b60908342dc9299219598f20e8 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:54:59 +0200 +Subject: [PATCH 31/95] Added methods SuspendVideoOutput() and + ResumeVideoOutput() to CRBP class, which can be used to power down the + Raspberry PI's video interface, and restore it at a later point. + +--- + xbmc/linux/RBP.cpp | 13 +++++++++++++ + xbmc/linux/RBP.h | 3 +++ + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 3 +++ + 3 files changed, 19 insertions(+) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index ce09fce..a18aa49 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -225,5 +225,18 @@ double CRBP::AdjustHDMIClock(double adjust) + return new_adjust; + } + ++void CRBP::SuspendVideoOutput() ++{ ++ CLog::Log(LOGDEBUG, "Raspberry PI suspending video output\n"); ++ char response[80]; ++ m_DllBcmHost->vc_gencmd(response, sizeof response, "display_power 0"); ++} ++ ++void CRBP::ResumeVideoOutput() ++{ ++ char response[80]; ++ m_DllBcmHost->vc_gencmd(response, sizeof response, "display_power 1"); ++ CLog::Log(LOGDEBUG, "Raspberry PI resuming video output\n"); ++} + + #endif +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 6456657..606c24f 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -60,6 +60,9 @@ class CRBP + void WaitVsync(); + double AdjustHDMIClock(double adjust); + ++ void SuspendVideoOutput(); ++ void ResumeVideoOutput(); ++ + private: + DllBcmHost *m_DllBcmHost; + bool m_initialized; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 2ebd74c..335f6d5 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -60,7 +60,10 @@ + # define DLOG(fmt, args...) + #endif + ++#if defined(TARGET_RASPBERRY_PI) + static void SetResolutionString(RESOLUTION_INFO &res); ++static SDTV_ASPECT_T get_sdtv_aspect_from_display_aspect(float display_aspect); ++#endif + + CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI() + { + +From b1c499da61efc2b7f33b478327600151a1ccf359 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Aug 2013 15:03:36 +0100 +Subject: [PATCH 32/95] PowerManager (and its IPowerSyscall instance) now gets + called from CApplication::OnKey() and can process and suppress key presses. + This is a requirement to implement a virtual sleep state. + +--- + xbmc/Application.cpp | 1 - + xbmc/input/InputManager.cpp | 8 ++++++++ + xbmc/powermanagement/IPowerSyscall.h | 7 +++++++ + xbmc/powermanagement/PowerManager.cpp | 6 ++++++ + xbmc/powermanagement/PowerManager.h | 3 +++ + 5 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 6f9849d..9c6f75f 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2037,7 +2037,6 @@ void CApplication::SetStandAlone(bool value) + g_advancedSettings.m_handleMounting = m_bStandalone = value; + } + +- + // OnAppCommand is called in response to a XBMC_APPCOMMAND event. + // This needs to return true if it processed the appcommand or false if it didn't + bool CApplication::OnAppCommand(const CAction &action) +diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp +index c6f62d8..f90fa89 100644 +--- a/xbmc/input/InputManager.cpp ++++ b/xbmc/input/InputManager.cpp +@@ -30,6 +30,7 @@ + #include "guilib/GUIWindow.h" + #include "guilib/GUIWindowManager.h" + #include "guilib/GUIMessage.h" ++#include "powermanagement/PowerManager.h" + + #ifdef HAS_EVENT_SERVER + #include "network/EventServer.h" +@@ -524,6 +525,13 @@ bool CInputManager::OnKey(const CKey& key) + // special handling if the screensaver is active + CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key); + ++ // give the PowerManager a chance to process a keypress, and ++ // suppress further processing. we need this for virtual sleep. ++ if (g_powerManager.ProcessAction(action)) ++ { ++ return true; ++ } ++ + // a key has been pressed. + // reset Idle Timer + g_application.ResetSystemIdleTimer(); +diff --git a/xbmc/powermanagement/IPowerSyscall.h b/xbmc/powermanagement/IPowerSyscall.h +index 7f9e7ed..711abea 100644 +--- a/xbmc/powermanagement/IPowerSyscall.h ++++ b/xbmc/powermanagement/IPowerSyscall.h +@@ -20,6 +20,9 @@ + * + */ + ++// forward declaration ++class CAction; ++ + class IPowerEventsCallback + { + public: +@@ -60,6 +63,10 @@ class IPowerSyscall + \param callback the callback to signal to + */ + virtual bool PumpPowerEvents(IPowerEventsCallback *callback) = 0; ++ ++ // this is an optional part of the interface, so we provide a no-op implementation here. ++ // return true to suppress further processing of the CAction. ++ virtual bool ProcessAction(const CAction& action) { return false; } + }; + + class CPowerSyscallWithoutEvents : public IPowerSyscall +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 5900f98..6e819d9 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -225,6 +225,12 @@ void CPowerManager::ProcessEvents() + nesting--; + } + ++bool CPowerManager::ProcessAction(const CAction& action) ++{ ++ return m_instance->ProcessAction(action); ++} ++ ++ + void CPowerManager::OnSleep() + { + CAnnouncementManager::Get().Announce(System, "xbmc", "OnSleep"); +diff --git a/xbmc/powermanagement/PowerManager.h b/xbmc/powermanagement/PowerManager.h +index 0b1f10a..e42b143 100644 +--- a/xbmc/powermanagement/PowerManager.h ++++ b/xbmc/powermanagement/PowerManager.h +@@ -58,6 +58,8 @@ class CNullPowerSyscall : public IPowerSyscall + + + virtual bool PumpPowerEvents(IPowerEventsCallback *callback) { return false; } ++ ++ virtual bool ProcessAction(const CAction& action) { return false; } + }; + + // This class will wrap and handle PowerSyscalls. +@@ -87,6 +89,7 @@ class CPowerManager : public IPowerEventsCallback + + static void SettingOptionsShutdownStatesFiller(const CSetting *setting, std::vector< std::pair > &list, int ¤t, void *data); + ++ bool ProcessAction(const CAction& action); + private: + void OnSleep(); + void OnWake(); + +From 126a4e7e1333ad47a1c253fa8be68438525eea4a Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:23:01 +0200 +Subject: [PATCH 33/95] Added CPowerSyscallVirtualSleep class, which acts as a + base class for devices that have no native standby mode, and need to fake it + in some way. + +--- + xbmc/powermanagement/Makefile | 1 + + xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 84 +++++++++++++++++++++++ + xbmc/powermanagement/PowerSyscallVirtualSleep.h | 56 +++++++++++++++ + 3 files changed, 141 insertions(+) + create mode 100644 xbmc/powermanagement/PowerSyscallVirtualSleep.cpp + create mode 100644 xbmc/powermanagement/PowerSyscallVirtualSleep.h + +diff --git a/xbmc/powermanagement/Makefile b/xbmc/powermanagement/Makefile +index 0b4c029..16056af 100644 +--- a/xbmc/powermanagement/Makefile ++++ b/xbmc/powermanagement/Makefile +@@ -1,5 +1,6 @@ + SRCS=DPMSSupport.cpp \ + PowerManager.cpp \ ++ PowerSyscallVirtualSleep.cpp \ + + LIB=powermanagement.a + +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +new file mode 100644 +index 0000000..9e6c8e4 +--- /dev/null ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +@@ -0,0 +1,84 @@ ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "PowerSyscallVirtualSleep.h" ++#include "input/Key.h" ++#include "utils/log.h" ++#include "utils/StringUtils.h" ++ ++bool CPowerSyscallVirtualSleep::Suspend() ++{ ++ if (m_virtualSleepState == VIRTUAL_SLEEP_STATE_AWAKE) ++ { ++ if (VirtualSleep()) ++ { ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_WILL_SLEEP; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++bool CPowerSyscallVirtualSleep::PumpPowerEvents(IPowerEventsCallback *callback) ++{ ++ if (m_virtualSleepState == VIRTUAL_SLEEP_STATE_WILL_WAKE) ++ { ++ callback->OnWake(); ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_AWAKE; ++ return true; ++ } ++ else if (m_virtualSleepState == VIRTUAL_SLEEP_STATE_WILL_SLEEP) ++ { ++ callback->OnSleep(); ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_ASLEEP; ++ return true; ++ } ++ ++ return false; ++} ++ ++bool CPowerSyscallVirtualSleep::ProcessAction(const CAction& action) ++{ ++ if (m_virtualSleepState != VIRTUAL_SLEEP_STATE_ASLEEP) ++ return false; ++ ++ // device is in virtual sleep, only one of the power keys will ++ // wake it up again. ++ if (action.GetID() == ACTION_BUILT_IN_FUNCTION) ++ { ++ std::string name = action.GetName(); ++ StringUtils::ToLower(name); ++ if(name.Equals("xbmc.suspend()") || ++ name.Equals("shutdown") || ++ name.Equals("suspend") || ++ name.Equals("hibernate")) ++ { ++ if(VirtualWake()) ++ { ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_WILL_WAKE; ++ return false; ++ } ++ } ++ } ++ ++ // wasn't a power key, suppress this and stay asleep ++ return true; ++} +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.h b/xbmc/powermanagement/PowerSyscallVirtualSleep.h +new file mode 100644 +index 0000000..ef6e682 +--- /dev/null ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#ifndef _POWER_SYSCALL_VIRTUAL_SLEEP_H_ ++#define _POWER_SYSCALL_VIRTUAL_SLEEP_H_ ++#include "IPowerSyscall.h" ++ ++// Systems that have no native standby mode, can base their ++// IPowerSyscall implementation on this class, and need only ++// implement VirtualSleep()/VirtualWake(). ++class CPowerSyscallVirtualSleep : public IPowerSyscall ++{ ++public: ++ CPowerSyscallVirtualSleep() : m_virtualSleepState(VIRTUAL_SLEEP_STATE_AWAKE) {} ++ virtual ~CPowerSyscallVirtualSleep() {} ++ ++ virtual bool CanSuspend() { return true; } ++ virtual bool Suspend(); ++ ++ virtual bool PumpPowerEvents(IPowerEventsCallback *callback); ++ ++ virtual bool ProcessAction(const CAction& action); ++ ++ virtual bool VirtualSleep() = 0; ++ virtual bool VirtualWake() = 0; ++ ++protected: ++ // keep track of virtual sleep state for devices that support it ++ typedef enum { ++ VIRTUAL_SLEEP_STATE_AWAKE = 0, ++ VIRTUAL_SLEEP_STATE_ASLEEP, ++ VIRTUAL_SLEEP_STATE_WILL_WAKE, ++ VIRTUAL_SLEEP_STATE_WILL_SLEEP, ++ } VirtualSleepState; ++ ++ VirtualSleepState m_virtualSleepState; ++}; ++ ++#endif // _POWER_SYSCALL_VIRTUAL_SLEEP_H_ + +From b50d81dd02214ed26210bad3d3102312ab7bab38 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:24:22 +0200 +Subject: [PATCH 34/95] Added power management support for the Raspberry Pi. + Since it doesn't support true standby, we fake it by turning video on or off, + and ignoring remote inputs during the standby phase. + +--- + xbmc/powermanagement/PowerManager.cpp | 4 ++ + xbmc/powermanagement/linux/Makefile | 1 + + .../linux/RaspberryPIPowerSyscall.cpp | 38 +++++++++++++++++ + .../linux/RaspberryPIPowerSyscall.h | 49 ++++++++++++++++++++++ + 4 files changed, 92 insertions(+) + create mode 100644 xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp + create mode 100644 xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h + +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 6e819d9..2d8c750 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -38,6 +38,8 @@ + + #if defined(TARGET_DARWIN) + #include "osx/CocoaPowerSyscall.h" ++#elif defined(TARGET_RASPBERRY_PI) ++#include "linux/RaspberryPIPowerSyscall.h" + #elif defined(TARGET_ANDROID) + #include "android/AndroidPowerSyscall.h" + #elif defined(TARGET_POSIX) +@@ -71,6 +73,8 @@ void CPowerManager::Initialize() + { + #if defined(TARGET_DARWIN) + m_instance = new CCocoaPowerSyscall(); ++#elif defined(TARGET_RASPBERRY_PI) ++ m_instance = new CRaspberryPIPowerSyscall(); + #elif defined(TARGET_ANDROID) + m_instance = new CAndroidPowerSyscall(); + #elif defined(TARGET_POSIX) +diff --git a/xbmc/powermanagement/linux/Makefile b/xbmc/powermanagement/linux/Makefile +index e9d95fb..b130812 100644 +--- a/xbmc/powermanagement/linux/Makefile ++++ b/xbmc/powermanagement/linux/Makefile +@@ -1,5 +1,6 @@ + SRCS=ConsoleDeviceKitPowerSyscall.cpp \ + ConsoleUPowerSyscall.cpp \ ++ RaspberryPIPowerSyscall.cpp \ + UPowerSyscall.cpp \ + LogindUPowerSyscall.cpp + +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +new file mode 100644 +index 0000000..10deeb8 +--- /dev/null ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if defined(TARGET_RASPBERRY_PI) ++ ++#include "RaspberryPIPowerSyscall.h" ++#include "RBP.h" ++ ++bool CRaspberryPIPowerSyscall::VirtualSleep() ++{ ++ g_RBP.SuspendVideoOutput(); ++ return true; ++} ++ ++bool CRaspberryPIPowerSyscall::VirtualWake() ++{ ++ g_RBP.ResumeVideoOutput(); ++ return true; ++} ++ ++#endif +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +new file mode 100644 +index 0000000..fd1d67c +--- /dev/null ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +@@ -0,0 +1,49 @@ ++#pragma once ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#ifndef _RASPBERRY_PI_POWER_SYSCALL_H_ ++#define _RASPBERRY_PI_POWER_SYSCALL_H_ ++ ++#if defined(TARGET_RASPBERRY_PI) ++#include "powermanagement/PowerSyscallVirtualSleep.h" ++ ++class CRaspberryPIPowerSyscall : public CPowerSyscallVirtualSleep ++{ ++public: ++ CRaspberryPIPowerSyscall() : CPowerSyscallVirtualSleep() {} ++ virtual ~CRaspberryPIPowerSyscall() {} ++ ++ virtual bool Powerdown() { return false; } ++ virtual bool Hibernate() { return false; } ++ virtual bool Reboot() { return false; } ++ ++ virtual bool CanPowerdown() { return false; } ++ virtual bool CanHibernate() { return false; } ++ virtual bool CanReboot() { return true; } ++ ++ virtual int BatteryLevel() { return 0; } ++ ++ virtual bool VirtualSleep(); ++ virtual bool VirtualWake(); ++}; ++#endif // TARGET_RASPBERRY_PI ++ ++#endif // _RASPBERRY_PI_POWER_SYSCALL_H_ + +From 55c10c9ffe81121395c6cfbbdc8dec7ec595e9d1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:16:29 +0000 +Subject: [PATCH 35/95] [power] hack - don't kill lirc or cec + +--- + xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 37 +++++++++++++++++++++++ + xbmc/powermanagement/PowerManager.cpp | 4 +-- + 2 files changed, 39 insertions(+), 2 deletions(-) + +diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +index 3d0c07d..ae5583d 100644 +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +@@ -186,12 +186,49 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender, + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) + { ++#if 1 ++ bool bSendStandbyCommands(false); ++ { ++ CSingleLock lock(m_critSection); ++ bSendStandbyCommands = m_iExitCode != EXITCODE_REBOOT && ++ m_iExitCode != EXITCODE_RESTARTAPP && ++ !m_bDeviceRemoved && ++ (!m_bGoingToStandby || GetSettingBool("standby_tv_on_pc_standby")) && ++ GetSettingBool("enabled"); ++ ++ if (m_bGoingToStandby) ++ m_bActiveSourceBeforeStandby = m_cecAdapter->IsLibCECActiveSource(); ++ } ++ ++ if (bSendStandbyCommands) ++ { ++ if (m_cecAdapter->IsLibCECActiveSource()) ++ { ++ if (!m_configuration.powerOffDevices.IsEmpty()) ++ { ++ CLog::Log(LOGDEBUG, "%s - sending standby commands", __FUNCTION__); ++ m_standbySent = CDateTime::GetCurrentDateTime(); ++ m_cecAdapter->StandbyDevices(); ++ } ++ else if (m_configuration.bSendInactiveSource == 1) ++ { ++ CLog::Log(LOGDEBUG, "%s - sending inactive source commands", __FUNCTION__); ++ m_cecAdapter->SetInactiveView(); ++ } ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, "%s - XBMC is not the active source, not sending any standby commands", __FUNCTION__); ++ } ++ } ++#else + // this will also power off devices when we're the active source + { + CSingleLock lock(m_critSection); + m_bGoingToStandby = true; + } + StopThread(); ++#endif + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) + { +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 2d8c750..901f449 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -241,7 +241,7 @@ void CPowerManager::OnSleep() + CLog::Log(LOGNOTICE, "%s: Running sleep jobs", __FUNCTION__); + + // stop lirc +-#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) ++#if 0 //defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) + CLog::Log(LOGNOTICE, "%s: Stopping lirc", __FUNCTION__); + CBuiltins::Execute("LIRC.Stop"); + #endif +@@ -277,7 +277,7 @@ void CPowerManager::OnWake() + #endif + + // restart lirc +-#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) ++#if 0 // defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) + CLog::Log(LOGNOTICE, "%s: Restarting lirc", __FUNCTION__); + CBuiltins::Execute("LIRC.Start"); + #endif + +From f765ae243bf2d5b55733ebb70fd2b1f758a73090 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:47:54 +0000 +Subject: [PATCH 36/95] [power] hack - wake on any action + +--- + xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +index 9e6c8e4..78566ec 100644 +--- a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +@@ -62,14 +62,14 @@ bool CPowerSyscallVirtualSleep::ProcessAction(const CAction& action) + + // device is in virtual sleep, only one of the power keys will + // wake it up again. +- if (action.GetID() == ACTION_BUILT_IN_FUNCTION) ++ //if (action.GetID() == ACTION_BUILT_IN_FUNCTION) + { + std::string name = action.GetName(); + StringUtils::ToLower(name); +- if(name.Equals("xbmc.suspend()") || ++ /*if(name.Equals("system.suspend") || + name.Equals("shutdown") || + name.Equals("suspend") || +- name.Equals("hibernate")) ++ name.Equals("hibernate"))*/ + { + if(VirtualWake()) + { + +From 275567504607bf439caa71cf7fd834d92ea223d8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 17:30:07 +0000 +Subject: [PATCH 37/95] [power] hack - Make suspend toggle suspend state + +--- + xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +index 78566ec..4cffcce 100644 +--- a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +@@ -33,6 +33,11 @@ bool CPowerSyscallVirtualSleep::Suspend() + return true; + } + } ++ else if (VirtualWake()) ++ { ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_WILL_WAKE; ++ return false; ++ } + + return false; + } + +From 196584d35b67d9cb2cec5d4502b98e314a9c8eee Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 4 Mar 2014 19:33:44 +0000 +Subject: [PATCH 38/95] [power] Add back in powerdown and reboot + +--- + .../linux/RaspberryPIPowerSyscall.cpp | 34 ++++++++++++++++++++++ + .../linux/RaspberryPIPowerSyscall.h | 6 ++-- + 2 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +index 10deeb8..220bca9 100644 +--- a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +@@ -20,7 +20,11 @@ + + #if defined(TARGET_RASPBERRY_PI) + ++#include "system.h" + #include "RaspberryPIPowerSyscall.h" ++#if defined(HAS_DBUS) ++#include "LogindUPowerSyscall.h" ++#endif + #include "RBP.h" + + bool CRaspberryPIPowerSyscall::VirtualSleep() +@@ -35,4 +39,34 @@ bool CRaspberryPIPowerSyscall::VirtualWake() + return true; + } + ++bool CRaspberryPIPowerSyscall::Powerdown() ++{ ++ int s = false; ++#if defined(HAS_DBUS) ++ if (CLogindUPowerSyscall::HasLogind()) ++ { ++ IPowerSyscall *m_instance = new CLogindUPowerSyscall; ++ if (m_instance->CanPowerdown()) ++ s = m_instance->Powerdown(); ++ delete m_instance; ++ } ++#endif ++ return s; ++} ++ ++bool CRaspberryPIPowerSyscall::Reboot() ++{ ++ int s = false; ++#if defined(HAS_DBUS) ++ if (CLogindUPowerSyscall::HasLogind()) ++ { ++ IPowerSyscall *m_instance = new CLogindUPowerSyscall; ++ if (m_instance->CanReboot()) ++ s = m_instance->Reboot(); ++ delete m_instance; ++ } ++#endif ++ return s; ++} ++ + #endif +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +index fd1d67c..062132e 100644 +--- a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +@@ -31,11 +31,11 @@ class CRaspberryPIPowerSyscall : public CPowerSyscallVirtualSleep + CRaspberryPIPowerSyscall() : CPowerSyscallVirtualSleep() {} + virtual ~CRaspberryPIPowerSyscall() {} + +- virtual bool Powerdown() { return false; } ++ virtual bool Powerdown(); + virtual bool Hibernate() { return false; } +- virtual bool Reboot() { return false; } ++ virtual bool Reboot(); + +- virtual bool CanPowerdown() { return false; } ++ virtual bool CanPowerdown() { return true; } + virtual bool CanHibernate() { return false; } + virtual bool CanReboot() { return true; } + + +From a7ea5732e9d41ce4c860f7837e1a5c7a903d1322 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 26 Apr 2014 17:27:52 +0100 +Subject: [PATCH 39/95] [cec] Don't suspend pi on tv switch off - it can't wake + up + +--- + system/peripherals.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/system/peripherals.xml b/system/peripherals.xml +index 094a3c1..0b89ee8 100644 +--- a/system/peripherals.xml ++++ b/system/peripherals.xml +@@ -16,7 +16,7 @@ + + + +- ++ + + + + +From 7b9fdacd125a5b43b35eb0ec777927186749a732 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Jun 2014 00:01:05 +0100 +Subject: [PATCH 40/95] [rbp] Resume video output on startup + +--- + xbmc/linux/RBP.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index a18aa49..6514c2d 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -88,6 +88,9 @@ bool CRBP::Initialize() + if (g_advancedSettings.m_cacheMemBufferSize == ~0U) + g_advancedSettings.m_cacheMemBufferSize = m_arm_mem < 256 ? 1024 * 1024 * 2 : 1024 * 1024 * 20; + ++ // in case xbcm was restarted when suspended ++ ResumeVideoOutput(); ++ + g_OMXImage.Initialize(); + m_omx_image_init = true; + return true; + +From 0972c1c22138ef2b047048caac41b661af6740a9 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 11 Apr 2014 16:12:27 +0100 +Subject: [PATCH 41/95] [omxplayer] Add ability to log more timestamp info in + extra debug settings + +--- + addons/resource.language.en_gb/resources/strings.po | 5 +++++ + xbmc/commons/ilog.h | 1 + + xbmc/cores/omxplayer/OMXHelper.cpp | 12 +++++++----- + xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 8 ++++---- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 9 +++++---- + xbmc/settings/AdvancedSettings.cpp | 3 +++ + 6 files changed, 25 insertions(+), 13 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 44e1ef7..3909203 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2908,6 +2908,11 @@ msgctxt "#680" + msgid "Verbose logging for VIDEO component" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#697" ++msgid "Verbose logging for OMXPLAYER" ++msgstr "" ++ + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index de90359..e4ffb5e 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -53,6 +53,7 @@ + #define LOGUPNP (1 << (LOGMASKBIT + 8)) + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) ++#define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXHelper.cpp b/xbmc/cores/omxplayer/OMXHelper.cpp +index be54f31..9739ed0 100644 +--- a/xbmc/cores/omxplayer/OMXHelper.cpp ++++ b/xbmc/cores/omxplayer/OMXHelper.cpp +@@ -23,6 +23,7 @@ + #ifdef HAS_OMXPLAYER + + #include "DVDPlayer.h" ++#include "settings/AdvancedSettings.h" + #include "settings/Settings.h" + #include "settings/MediaSettings.h" + #include "DVDInputStreams/DVDInputStream.h" +@@ -140,7 +141,8 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed, + m_OmxPlayerState.video_fifo = (int)(100.0*(m_dvdPlayerVideo->GetDecoderBufferSize()-m_dvdPlayerVideo->GetDecoderFreeSpace())/m_dvdPlayerVideo->GetDecoderBufferSize()); + m_OmxPlayerState.audio_fifo = (int)(100.0*audio_fifo/m_dvdPlayerAudio->GetCacheTotal()); + +- #ifdef _DEBUG ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ { + static unsigned count; + if ((count++ & 7) == 0) + { +@@ -160,7 +162,7 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed, + vc_gencmd(response, sizeof response, "render_bar 7 audio_queue %d %d %d %d", + m_dvdPlayerAudio->GetLevel(), 0, 0, 100); + } +- #endif ++ } + if (audio_pts != DVD_NOPTS_VALUE) + { + audio_fifo_low = m_HasAudio && audio_fifo < threshold; +@@ -176,15 +178,15 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed, + if (!m_HasVideo && m_HasAudio) + video_fifo_high = true; + +- #ifdef _DEBUG ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ { + CLog::Log(LOGDEBUG, "%s::%s M:%.6f-%.6f (A:%.6f V:%.6f) PEF:%d%d%d S:%.2f A:%.2f V:%.2f/T:%.2f (A:%d%d V:%d%d) A:%d%% V:%d%% (%.2f,%.2f)", "CDVDPlayer", __FUNCTION__, + m_OmxPlayerState.stamp*1e-6, m_OmxPlayerState.av_clock.OMXClockAdjustment()*1e-6, audio_pts*1e-6, video_pts*1e-6, + m_OmxPlayerState.av_clock.OMXIsPaused(), m_OmxPlayerState.bOmxSentEOFs, not_accepts_data, m_playSpeed * (1.0f/DVD_PLAYSPEED_NORMAL), + audio_pts == DVD_NOPTS_VALUE ? 0.0:audio_fifo, video_pts == DVD_NOPTS_VALUE ? 0.0:video_fifo, m_OmxPlayerState.threshold, + audio_fifo_low, audio_fifo_high, video_fifo_low, video_fifo_high, + m_dvdPlayerAudio->GetLevel(), m_dvdPlayerVideo->GetLevel(), m_dvdPlayerAudio->GetDelay(), (float)m_dvdPlayerAudio->GetCacheTotal()); +- #endif +- ++ } + if(!m_Pause && (m_OmxPlayerState.bOmxSentEOFs || not_accepts_data || (audio_fifo_high && video_fifo_high) || m_playSpeed != DVD_PLAYSPEED_NORMAL)) + { + if (m_OmxPlayerState.av_clock.OMXIsPaused()) +diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +index c2da2d2..2f1df45 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +@@ -366,10 +366,10 @@ void OMXPlayerAudio::Process() + DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); + bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); + +- #ifdef _DEBUG +- CLog::Log(LOGINFO, "Audio: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d,%d", pPacket->dts, pPacket->pts, +- (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, (int)m_omxAudio.GetAudioRenderingLatency(), (int)m_hints_current.samplerate); +- #endif ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ CLog::Log(LOGINFO, "Audio: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d,%d", pPacket->dts, pPacket->pts, ++ (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, (int)m_omxAudio.GetAudioRenderingLatency(), (int)m_hints_current.samplerate); ++ + if(Decode(pPacket, m_speed > DVD_PLAYSPEED_NORMAL || m_speed < 0 || bPacketDrop)) + { + // we are not running until something is cached in output device +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index bee7086..4e599e3 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -42,6 +42,7 @@ + #include "DVDOverlayRenderer.h" + #include "settings/DisplaySettings.h" + #include "settings/Settings.h" ++#include "settings/AdvancedSettings.h" + #include "settings/MediaSettings.h" + #include "cores/VideoRenderers/RenderFormats.h" + #include "cores/VideoRenderers/RenderFlags.h" +@@ -461,10 +462,10 @@ void OMXPlayerVideo::Process() + DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); + bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); + +- #ifdef _DEBUG +- CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts, +- (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0); +- #endif ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts, ++ (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0); ++ + if (m_messageQueue.GetDataSize() == 0 + || m_speed < 0) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 59d45c8..e46233a 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1364,6 +1364,9 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef HAVE_LIBCEC + list.push_back(std::make_pair(g_localizeStrings.Get(679), LOGCEC)); + #endif ++#ifdef TARGET_RASPBERRY_PI ++ list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); ++#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 3df8730dedff3efbc594ab5029653fcbcb510c95 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 42/95] [omxplayer] Add ability to dump out audio/video data + for later debugging + +--- + .../resource.language.en_gb/resources/strings.po | 10 +++++ + xbmc/commons/ilog.h | 2 + + xbmc/cores/omxplayer/OMXAudio.cpp | 49 ++++++++++++++++++++++ + xbmc/cores/omxplayer/OMXVideo.cpp | 47 +++++++++++++++++++++ + xbmc/settings/AdvancedSettings.cpp | 4 ++ + 5 files changed, 112 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 3909203..d8563fb 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2913,6 +2913,16 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#698" ++msgid "Dump video frames to debug file" ++msgstr "" ++ ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#699" ++msgid "Dump audio frames to debug file" ++msgstr "" ++ + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index e4ffb5e..4f8926c 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,6 +54,8 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) ++#define LOGDUMPVIDEO (1 << (LOGMASKBIT + 17)) ++#define LOGDUMPAUDIO (1 << (LOGMASKBIT + 18)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 602d2fa..0b8fd69 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -56,6 +56,49 @@ using namespace std; + #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024) + static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3}; + ++//#define DEBUG_PLAYBACK ++static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) ++{ ++ if (!(g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) ++ return; ++ static FILE *fp; ++ if (!omx_buffer) ++ { ++ if (fp) ++ { ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, "audio.dat"); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ OMX_BUFFERHEADERTYPE omx = {0}; ++ int s = fread(&omx, sizeof omx, 1, fp); ++ omx_buffer->nFilledLen = omx.nFilledLen; ++ omx_buffer->nFlags = omx.nFlags; ++ omx_buffer->nTimeStamp = omx.nTimeStamp; ++ if (s==1) ++ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#else ++ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) ++ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#endif ++ } ++} ++ + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// +@@ -868,6 +911,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -900,6 +944,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -936,6 +981,8 @@ bool COMXAudio::Deinitialize() + { + CSingleLock lock (m_critSection); + ++ dump_omx_buffer(NULL); ++ + if ( m_omx_tunnel_clock_analog.IsInitialized() ) + m_omx_tunnel_clock_analog.Deestablish(); + if ( m_omx_tunnel_clock_hdmi.IsInitialized() ) +@@ -1226,6 +1273,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt + int nRetry = 0; + while(true) + { ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -1473,6 +1521,7 @@ void COMXAudio::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 55e16c4..4489546 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -65,6 +65,49 @@ + + #define MAX_TEXT_LENGTH 1024 + ++//#define DEBUG_PLAYBACK ++static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) ++{ ++ if (!(g_advancedSettings.CanLogComponent(LOGDUMPVIDEO))) ++ return; ++ static FILE *fp; ++ if (!omx_buffer) ++ { ++ if (fp) ++ { ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, "video.dat"); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ OMX_BUFFERHEADERTYPE omx = {0}; ++ int s = fread(&omx, sizeof omx, 1, fp); ++ omx_buffer->nFilledLen = omx.nFilledLen; ++ omx_buffer->nFlags = omx.nFlags; ++ omx_buffer->nTimeStamp = omx.nTimeStamp; ++ if (s==1) ++ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#else ++ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) ++ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#endif ++ } ++} ++ + COMXVideo::COMXVideo() : m_video_codec_name("") + { + m_is_open = false; +@@ -120,6 +163,7 @@ bool COMXVideo::SendDecoderConfig() + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -697,6 +741,7 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + void COMXVideo::Close() + { + CSingleLock lock (m_critSection); ++ dump_omx_buffer(NULL); + m_omx_tunnel_clock.Deestablish(); + m_omx_tunnel_decoder.Deestablish(); + if(m_deinterlace) +@@ -815,6 +860,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + int nRetry = 0; + while(true) + { ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -945,6 +991,7 @@ void COMXVideo::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index e46233a..9119877 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1367,6 +1367,10 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef TARGET_RASPBERRY_PI + list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); + #endif ++#ifdef TARGET_RASPBERRY_PI ++ list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); ++ list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); ++#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 4593665a9ce884639f1116b09a6d8f803a23f4b1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 18 Aug 2014 19:09:32 +0100 +Subject: [PATCH 43/95] rbp: Use new dispmanx function for vsync callbacks + +--- + xbmc/linux/RBP.cpp | 86 ++++++++++++++----------- + xbmc/linux/RBP.h | 7 +- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 +- + 3 files changed, 55 insertions(+), 42 deletions(-) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index 6514c2d..fe1df00 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -21,6 +21,7 @@ + #include "RBP.h" + #if defined(TARGET_RASPBERRY_PI) + ++#include + #include "settings/Settings.h" + #include "settings/AdvancedSettings.h" + #include "utils/log.h" +@@ -33,7 +34,7 @@ CRBP::CRBP() + m_omx_initialized = false; + m_DllBcmHost = new DllBcmHost(); + m_OMX = new COMXCore(); +- m_element = 0; ++ m_display = DISPMANX_NO_HANDLE; + } + + CRBP::~CRBP() +@@ -55,8 +56,7 @@ bool CRBP::Initialize() + + m_DllBcmHost->bcm_host_init(); + +- uint32_t vc_image_ptr; +- m_resource = vc_dispmanx_resource_create( VC_IMAGE_RGB565, 1, 1, &vc_image_ptr ); ++ //OpenDisplay(0 /*screen*/); + + m_omx_initialized = m_OMX->Initialize(); + if(!m_omx_initialized) +@@ -112,13 +112,24 @@ void CRBP::LogFirmwareVerison() + CLog::Log(LOGNOTICE, "Config:\n%s", response); + } + ++DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) ++{ ++ if (m_display == DISPMANX_NO_HANDLE) ++ m_display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ return m_display; ++} ++ ++void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display) ++{ ++ assert(display == m_display); ++ vc_dispmanx_display_close(m_display); ++ m_display = DISPMANX_NO_HANDLE; ++} ++ + void CRBP::GetDisplaySize(int &width, int &height) + { +- DISPMANX_DISPLAY_HANDLE_T display; + DISPMANX_MODEINFO_T info; +- +- display = vc_dispmanx_display_open( 0 /*screen*/ ); +- if (vc_dispmanx_display_get_info(display, &info) == 0) ++ if (vc_dispmanx_display_get_info(m_display, &info) == 0) + { + width = info.width; + height = info.height; +@@ -128,12 +139,10 @@ void CRBP::GetDisplaySize(int &width, int &height) + width = 0; + height = 0; + } +- vc_dispmanx_display_close(display ); + } + + unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue, bool video_only) + { +- DISPMANX_DISPLAY_HANDLE_T display; + DISPMANX_RESOURCE_HANDLE_T resource; + VC_RECT_T rect; + unsigned char *image = NULL; +@@ -148,7 +157,6 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw + if (!pstride) + flags |= DISPMANX_SNAPSHOT_PACK; + +- display = vc_dispmanx_display_open( 0 /*screen*/ ); + stride = ((width + 15) & ~15) * 4; + image = new unsigned char [height * stride]; + +@@ -156,45 +164,44 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw + { + resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); + +- vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)flags); ++ assert(m_display != DISPMANX_NO_HANDLE); ++ 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 ); +- vc_dispmanx_display_close(display ); + } + if (pstride) + *pstride = stride; + return image; + } + +-void CRBP::WaitVsync(void) ++ ++static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg) + { +- DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( 0 /*screen*/ ); +- DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); +- +- VC_DISPMANX_ALPHA_T alpha = { (DISPMANX_FLAGS_ALPHA_T)(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS), 120, /*alpha 0->255*/ 0 }; +- VC_RECT_T src_rect; +- VC_RECT_T dst_rect; +- vc_dispmanx_rect_set( &src_rect, 0, 0, 1 << 16, 1 << 16 ); +- vc_dispmanx_rect_set( &dst_rect, 0, 0, 1, 1 ); +- +- if (m_element) +- vc_dispmanx_element_remove( update, m_element ); +- +- m_element = vc_dispmanx_element_add( update, +- display, +- 2000, // layer +- &dst_rect, +- m_resource, +- &src_rect, +- DISPMANX_PROTECTION_NONE, +- &alpha, +- NULL, // clamp +- (DISPMANX_TRANSFORM_T)0 ); +- +- vc_dispmanx_update_submit_sync(update); +- vc_dispmanx_display_close( display ); ++ CEvent *sync = (CEvent *)arg; ++ sync->Set(); ++} ++ ++void CRBP::WaitVsync() ++{ ++ int s; ++ DISPMANX_DISPLAY_HANDLE_T m_display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ if (m_display == DISPMANX_NO_HANDLE) ++ { ++ CLog::Log(LOGDEBUG, "CRBP::%s skipping while display closed", __func__); ++ return; ++ } ++ m_vsync.Reset(); ++ s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); ++ if (s == 0) ++ { ++ m_vsync.Wait(); ++ } ++ else assert(0); ++ s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); ++ assert(s == 0); ++ vc_dispmanx_display_close( m_display ); + } + + +@@ -206,6 +213,9 @@ void CRBP::Deinitialize() + if(m_omx_initialized) + m_OMX->Deinitialize(); + ++ if (m_display) ++ CloseDisplay(m_display); ++ + m_DllBcmHost->bcm_host_deinit(); + + if(m_initialized) +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 606c24f..82146d6 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -38,6 +38,7 @@ + #include "DllBCM.h" + #include "OMXCore.h" + #include "threads/CriticalSection.h" ++#include "threads/Event.h" + + class CRBP + { +@@ -53,6 +54,8 @@ class CRBP + bool GetCodecMpg2() { return m_codec_mpg2_enabled; } + 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); +@@ -74,10 +77,10 @@ class CRBP + bool m_codec_mpg2_enabled; + bool m_codec_wvc1_enabled; + COMXCore *m_OMX; +- DISPMANX_RESOURCE_HANDLE_T m_resource; +- DISPMANX_ELEMENT_HANDLE_T m_element; + class DllLibOMXCore; + CCriticalSection m_critSection; ++ DISPMANX_DISPLAY_HANDLE_T m_display; ++ CEvent m_vsync; + }; + + extern CRBP g_RBP; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 335f6d5..7d9b0d3 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -307,7 +307,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + m_desktopRes = res; + } + +- m_dispman_display = m_DllBcmHost->vc_dispmanx_display_open(0); ++ m_dispman_display = g_RBP.OpenDisplay(0); + + m_width = res.iWidth; + m_height = res.iHeight; +@@ -578,7 +578,7 @@ void CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow() + + if (m_dispman_display != DISPMANX_NO_HANDLE) + { +- m_DllBcmHost->vc_dispmanx_display_close(m_dispman_display); ++ g_RBP.CloseDisplay(m_dispman_display); + m_dispman_display = DISPMANX_NO_HANDLE; + } + DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); + +From 831431010bbb8a673005a4cd503d6f5db5718bc0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Nov 2014 17:16:54 +0000 +Subject: [PATCH 44/95] Revert "[omxplayer] Add ability to dump out audio/video + data for later debugging" + +This reverts commit 417416bd29d00f1b42c77488d06e9e6840b8c4f4. +--- + .../resource.language.en_gb/resources/strings.po | 10 ----- + xbmc/commons/ilog.h | 2 - + xbmc/cores/omxplayer/OMXAudio.cpp | 49 ---------------------- + xbmc/cores/omxplayer/OMXVideo.cpp | 47 --------------------- + xbmc/settings/AdvancedSettings.cpp | 4 -- + 5 files changed, 112 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index d8563fb..3909203 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2913,16 +2913,6 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + +-#: xbmc/settings/AdvancedSettings.cpp +-msgctxt "#698" +-msgid "Dump video frames to debug file" +-msgstr "" +- +-#: xbmc/settings/AdvancedSettings.cpp +-msgctxt "#699" +-msgid "Dump audio frames to debug file" +-msgstr "" +- + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index 4f8926c..e4ffb5e 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,8 +54,6 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) +-#define LOGDUMPVIDEO (1 << (LOGMASKBIT + 17)) +-#define LOGDUMPAUDIO (1 << (LOGMASKBIT + 18)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 0b8fd69..602d2fa 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -56,49 +56,6 @@ using namespace std; + #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024) + static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3}; + +-//#define DEBUG_PLAYBACK +-static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) +-{ +- if (!(g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) +- return; +- static FILE *fp; +- if (!omx_buffer) +- { +- if (fp) +- { +- fclose(fp); +- fp = NULL; +- } +- return; +- } +- if (!fp) +- { +- char filename[1024]; +- strcpy(filename, g_advancedSettings.m_logFolder.c_str()); +- strcat(filename, "audio.dat"); +-#ifdef DEBUG_PLAYBACK +- fp = fopen(filename, "rb"); +-#else +- fp = fopen(filename, "wb"); +-#endif +- } +- if (fp) +- { +-#ifdef DEBUG_PLAYBACK +- OMX_BUFFERHEADERTYPE omx = {0}; +- int s = fread(&omx, sizeof omx, 1, fp); +- omx_buffer->nFilledLen = omx.nFilledLen; +- omx_buffer->nFlags = omx.nFlags; +- omx_buffer->nTimeStamp = omx.nTimeStamp; +- if (s==1) +- fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#else +- if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) +- fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#endif +- } +-} +- + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// +@@ -911,7 +868,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -944,7 +900,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -981,8 +936,6 @@ bool COMXAudio::Deinitialize() + { + CSingleLock lock (m_critSection); + +- dump_omx_buffer(NULL); +- + if ( m_omx_tunnel_clock_analog.IsInitialized() ) + m_omx_tunnel_clock_analog.Deestablish(); + if ( m_omx_tunnel_clock_hdmi.IsInitialized() ) +@@ -1273,7 +1226,6 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt + int nRetry = 0; + while(true) + { +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -1521,7 +1473,6 @@ void COMXAudio::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 4489546..55e16c4 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -65,49 +65,6 @@ + + #define MAX_TEXT_LENGTH 1024 + +-//#define DEBUG_PLAYBACK +-static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) +-{ +- if (!(g_advancedSettings.CanLogComponent(LOGDUMPVIDEO))) +- return; +- static FILE *fp; +- if (!omx_buffer) +- { +- if (fp) +- { +- fclose(fp); +- fp = NULL; +- } +- return; +- } +- if (!fp) +- { +- char filename[1024]; +- strcpy(filename, g_advancedSettings.m_logFolder.c_str()); +- strcat(filename, "video.dat"); +-#ifdef DEBUG_PLAYBACK +- fp = fopen(filename, "rb"); +-#else +- fp = fopen(filename, "wb"); +-#endif +- } +- if (fp) +- { +-#ifdef DEBUG_PLAYBACK +- OMX_BUFFERHEADERTYPE omx = {0}; +- int s = fread(&omx, sizeof omx, 1, fp); +- omx_buffer->nFilledLen = omx.nFilledLen; +- omx_buffer->nFlags = omx.nFlags; +- omx_buffer->nTimeStamp = omx.nTimeStamp; +- if (s==1) +- fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#else +- if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) +- fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#endif +- } +-} +- + COMXVideo::COMXVideo() : m_video_codec_name("") + { + m_is_open = false; +@@ -163,7 +120,6 @@ bool COMXVideo::SendDecoderConfig() + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -741,7 +697,6 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + void COMXVideo::Close() + { + CSingleLock lock (m_critSection); +- dump_omx_buffer(NULL); + m_omx_tunnel_clock.Deestablish(); + m_omx_tunnel_decoder.Deestablish(); + if(m_deinterlace) +@@ -860,7 +815,6 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + int nRetry = 0; + while(true) + { +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -991,7 +945,6 @@ void COMXVideo::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 9119877..e46233a 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1367,10 +1367,6 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef TARGET_RASPBERRY_PI + list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); + #endif +-#ifdef TARGET_RASPBERRY_PI +- list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); +- list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); +-#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 1ff0d9e4bb953f06cf8c1c9c5a28839e1fd3b1b6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 45/95] [omxplayer] Add ability to dump out audio/video data + for later debugging + +--- + .../resource.language.en_gb/resources/strings.po | 10 ++++ + xbmc/commons/ilog.h | 2 + + xbmc/cores/dvdplayer/DVDPlayer.cpp | 63 ++++++++++++++++++++++ + xbmc/settings/AdvancedSettings.cpp | 4 ++ + 4 files changed, 79 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 3909203..d8563fb 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2913,6 +2913,16 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#698" ++msgid "Dump video frames to debug file" ++msgstr "" ++ ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#699" ++msgid "Dump audio frames to debug file" ++msgstr "" ++ + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index e4ffb5e..4f8926c 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,6 +54,8 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) ++#define LOGDUMPVIDEO (1 << (LOGMASKBIT + 17)) ++#define LOGDUMPAUDIO (1 << (LOGMASKBIT + 18)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 3180fe9..25b0b68 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -96,6 +96,61 @@ + using namespace std; + using namespace PVR; + ++//#define DEBUG_PLAYBACK ++static void dump_packet(DemuxPacket *packet, bool video, bool audio) ++{ ++ static CCriticalSection m_section; ++ static FILE *fp_video, *fp_audio; ++ if ((!video || !g_advancedSettings.CanLogComponent(LOGDUMPVIDEO)) && ++ (!audio || !g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) ++ return; ++ const char *fname = video ? "video.dat" : "audio.dat"; ++ FILE *&fp = video ? fp_video : fp_audio; ++ CSingleLock lock(m_section); ++ if (!packet) ++ { ++ if (fp) ++ { ++ CLog::Log(LOGNOTICE, "%s:: Closing file %p", __func__, fp); ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, fname); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ CLog::Log(LOGNOTICE, "%s:: Opening file %s = %p", __func__, filename, fp); ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ DemuxPacket p = {0}; ++ int s = fread(&p, sizeof p, 1, fp); ++ if (s==1) ++ { ++ packet->iSize = p.iSize; ++ packet->dts = p.dts; ++ packet->pts = p.pts; ++ _aligned_free(packet->pData); ++ packet->pData = (uint8_t*)_aligned_malloc(packet->iSize + FF_INPUT_BUFFER_PADDING_SIZE, 16); ++ fread(packet->pData, packet->iSize, 1, fp); ++ } ++#else ++ if (fwrite(packet, sizeof *packet, 1, fp) == 1) ++ fwrite(packet->pData, packet->iSize, 1, fp); ++#endif ++ } ++} ++ ++ + void CSelectionStreams::Clear(StreamType type, StreamSource source) + { + CSingleLock lock(m_section); +@@ -976,6 +1031,12 @@ bool CDVDPlayer::ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream) + return true; + } + ++ if(m_pDemuxer) ++ { ++ stream = m_pDemuxer->GetStream(packet->iStreamId); ++ if (stream) ++ dump_packet(packet, CheckIsCurrent(m_CurrentVideo, stream, packet), CheckIsCurrent(m_CurrentAudio, stream, packet)); ++ } + UpdateCorrection(packet, m_offset_pts); + + if(packet->iStreamId < 0) +@@ -3453,6 +3514,8 @@ bool CDVDPlayer::CloseStream(CCurrentStream& current, bool bWaitForBuffers) + if(bWaitForBuffers) + SetCaching(CACHESTATE_DONE); + ++ dump_packet(NULL, current.player == DVDPLAYER_VIDEO, current.player == DVDPLAYER_AUDIO); ++ + IDVDStreamPlayer* player = GetStreamPlayer(current.player); + if(player) + player->CloseStream(bWaitForBuffers); +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index e46233a..9119877 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1367,6 +1367,10 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef TARGET_RASPBERRY_PI + list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); + #endif ++#ifdef TARGET_RASPBERRY_PI ++ list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); ++ list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); ++#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 42b63f770f1cb1ca505bf37d133faede51e9e64a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 29 Nov 2014 15:25:16 +0000 +Subject: [PATCH 46/95] [rbp] hack: wait for splash to complete before changing + hdmi mode + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 49 +++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 7d9b0d3..d388373 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -217,12 +217,61 @@ int CEGLNativeTypeRaspberryPI::AddUniqueResolution(RESOLUTION_INFO &res, std::ve + } + #endif + ++#include ++ ++pid_t proc_find(const char* name) ++{ ++ DIR* dir; ++ struct dirent* ent; ++ char buf[512]; ++ ++ long pid; ++ char pname[100] = {0,}; ++ char state; ++ FILE *fp=NULL; ++ ++ if (!(dir = opendir("/proc"))) { ++ perror("can't open /proc"); ++ return -1; ++ } ++ ++ while((ent = readdir(dir)) != NULL) { ++ long lpid = atol(ent->d_name); ++ if(lpid < 0) ++ continue; ++ snprintf(buf, sizeof(buf), "/proc/%ld/stat", lpid); ++ fp = fopen(buf, "r"); ++ ++ if (fp) { ++ if ( (fscanf(fp, "%ld (%[^)]) %c", &pid, pname, &state)) != 3 ){ ++ printf("fscanf failed \n"); ++ fclose(fp); ++ closedir(dir); ++ return -1; ++ } ++ if (!strcmp(pname, name)) { ++ fclose(fp); ++ closedir(dir); ++ return (pid_t)lpid; ++ } ++ fclose(fp); ++ } ++ } ++ ++ closedir(dir); ++ return -1; ++} ++ ++ + bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + { + #if defined(TARGET_RASPBERRY_PI) + if(!m_DllBcmHost || !m_nativeWindow) + return false; + ++ while (proc_find("hello_video.bin") >= 0) ++ Sleep(100); ++ + DestroyDispmaxWindow(); + + if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) + +From 43974c9247ca19ed7473ec61c3b4178e3b4d1e18 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 5 Oct 2014 14:05:25 +0100 +Subject: [PATCH 47/95] [PiSink] Allow audio output latency to be set in + settings + +--- + addons/resource.language.en_gb/resources/strings.po | 15 +++++++++++++++ + system/settings/rbp.xml | 12 ++++++++++++ + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 13 ++++++++----- + xbmc/cores/AudioEngine/Sinks/AESinkPi.h | 1 + + 4 files changed, 36 insertions(+), 5 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index d8563fb..7c3aa66 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16634,3 +16634,18 @@ msgstr "" + msgctxt "#38052" + msgid "Remote button press release time (ms)" + msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38100" ++msgid "Audio output latency" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38101" ++msgid "Increase this to protect against underruns, reduce to have lower latency gui sounds" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38102" ++msgid "%i ms" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index f7cb75e..825a2e7 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -90,6 +90,18 @@ + + 101 + ++ ++ 3 ++ 100 ++ ++ 50 ++ 50 ++ 300 ++ ++ ++ 38102 ++ ++ + + + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 3cb6bfb..363b7d5 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -35,7 +35,6 @@ + #define CLASSNAME "CAESinkPi" + + #define NUM_OMX_BUFFERS 2 +-#define AUDIO_PLAYBUFFER (0.1) // 100ms + + static const unsigned int PassthroughSampleRates[] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000 }; + +@@ -43,6 +42,7 @@ CAEDeviceInfo CAESinkPi::m_info; + + CAESinkPi::CAESinkPi() : + m_sinkbuffer_sec_per_byte(0), ++ m_latency(0), + m_Initialized(false), + m_submitted(0), + m_omx_output(NULL) +@@ -190,6 +190,9 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_initDevice = device; + m_initFormat = format; + ++ m_latency = CSettings::Get().GetInt("audiooutput.latency") * 1e-3; ++ m_latency = std::max(m_latency, 50e-3); ++ + // analogue only supports stereo + if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { +@@ -206,7 +209,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + unsigned int sample_size = CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3; + format.m_frameSize = sample_size * channels; + format.m_sampleRate = std::max(8000U, std::min(192000U, format.m_sampleRate)); +- format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; ++ format.m_frames = format.m_sampleRate * m_latency / NUM_OMX_BUFFERS; + format.m_frameSamples = format.m_frames * channels; + + SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough)); +@@ -421,7 +424,7 @@ void CAESinkPi::GetDelay(AEDelayStatus& status) + + double CAESinkPi::GetCacheTotal() + { +- return AUDIO_PLAYBUFFER; ++ return m_latency; + } + + unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) +@@ -469,8 +472,8 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned + m_submitted++; + GetDelay(status); + delay = status.GetDelay(); +- if (delay > AUDIO_PLAYBUFFER) +- Sleep((int)(1000.0f * (delay - AUDIO_PLAYBUFFER))); ++ if (delay > m_latency) ++ Sleep((int)(1000.0f * (delay - m_latency))); + return frames; + } + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +index 5c57999..cac5051 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +@@ -53,6 +53,7 @@ class CAESinkPi : public IAESink + AEAudioFormat m_initFormat; + AEAudioFormat m_format; + double m_sinkbuffer_sec_per_byte; ++ double m_latency; + static CAEDeviceInfo m_info; + bool m_Initialized; + uint32_t m_submitted; + +From bd5e47c61ed2575765502ae884348f57ce0189af Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 11 Dec 2014 17:00:57 +0000 +Subject: [PATCH 48/95] Fix for UI not showing both extractflags and + extractthumb + +--- + addons/resource.language.en_gb/resources/strings.po | 11 ++++++++--- + system/settings/rbp.xml | 4 ---- + system/settings/settings.xml | 10 +++++----- + 3 files changed, 13 insertions(+), 12 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 7c3aa66..af96b08 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -10974,7 +10974,7 @@ msgstr "" + + #: system/settings/settings.xml + msgctxt "#20433" +-msgid "Extract thumbnails and video information" ++msgid "Extract video information from files" + msgstr "" + + #: xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp +@@ -14501,7 +14501,7 @@ msgstr "" + #. Description of setting "Videos -> File lists -> Extract thumbnails and video information" with label #20433 + #: system/settings/settings.xml + msgctxt "#36178" +-msgid "Extract thumbnails and metadata information such as codec and aspect ratio from videos." ++msgid "Extract metadata information such as codec and aspect ratio from videos." + msgstr "" + + #. Description of setting "Videos -> File lists -> Replace file names with library titles" with label #20419 +@@ -14513,7 +14513,7 @@ msgstr "" + #. Description of setting "Videos -> File lists -> Extract thumbnails and video information" with label #20433 + #: system/settings/settings.xml + msgctxt "#36180" +-msgid "Extract thumbnails and information, such as codecs and aspect ratio, to display in Library Mode." ++msgid "Extract thumbnails, to display in Library Mode." + msgstr "" + + #: system/settings/settings.xml +@@ -16649,3 +16649,8 @@ msgstr "" + msgctxt "#38102" + msgid "%i ms" + msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38015" ++msgid "Extract thumbnails from video files" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 825a2e7..a3b6f6f 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -37,10 +37,6 @@ + + false + +- +- +- +- + + false + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index a40ecb5..5a6c12f 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -899,23 +899,23 @@ + + + +- ++ + 1 + true + + +- ++ + 1 + true + + +- ++ + 1 + true + + +- +- 4 ++ ++ 1 + true + + + +From c865ff570615b4059b737a4ca3e5105da7d11f69 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Thu, 11 Sep 2014 21:30:43 +0200 +Subject: [PATCH 49/95] Disable autoscrolling while on screensaver and while + opening streams. + +--- + xbmc/Application.cpp | 10 ++++++++++ + xbmc/Application.h | 2 ++ + xbmc/guilib/GUIFadeLabelControl.cpp | 4 +++- + xbmc/guilib/GUIFont.cpp | 4 ++++ + xbmc/guilib/GUILabel.cpp | 4 +++- + xbmc/guilib/GUITextBox.cpp | 3 ++- + 6 files changed, 24 insertions(+), 3 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 9c6f75f..fb38cd3 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -4930,3 +4930,13 @@ bool CApplication::NotifyActionListeners(const CAction &action) const + + return false; + } ++ ++bool CApplication::ScreenSaverDisablesAutoScrolling() ++{ ++ bool onBlackDimScreenSaver = IsInScreenSaver() && m_screenSaver && ++ (m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || ++ m_screenSaver->ID() == "screensaver.xbmc.builtin.dim"); ++ bool openingStreams = m_pPlayer->IsPlaying() && g_windowManager.IsWindowActive(WINDOW_DIALOG_BUSY); ++ ++ return onBlackDimScreenSaver || openingStreams; ++} +diff --git a/xbmc/Application.h b/xbmc/Application.h +index ec5dfac..1b9a4bf 100644 +--- a/xbmc/Application.h ++++ b/xbmc/Application.h +@@ -389,6 +389,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs + */ + void UnregisterActionListener(IActionListener *listener); + ++ bool ScreenSaverDisablesAutoScrolling(); ++ + protected: + virtual bool OnSettingsSaving() const; + +diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp +index 9eadbe4..b2b5f13 100644 +--- a/xbmc/guilib/GUIFadeLabelControl.cpp ++++ b/xbmc/guilib/GUIFadeLabelControl.cpp +@@ -20,6 +20,8 @@ + + #include "GUIFadeLabelControl.h" + ++#include "Application.h" ++ + using namespace std; + + CGUIFadeLabelControl::CGUIFadeLabelControl(int parentID, int controlID, float posX, float posY, float width, float height, const CLabelInfo& labelInfo, bool scrollOut, unsigned int timeToDelayAtEnd, bool resetOnLabelChange) +@@ -102,7 +104,7 @@ void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &d + m_lastLabel = m_currentLabel; + } + +- if (m_infoLabels.size() > 1 || !m_shortText) ++ if ((m_infoLabels.size() > 1 || !m_shortText) && !g_application.ScreenSaverDisablesAutoScrolling()) + { // have scrolling text + MarkDirtyRegion(); + +diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp +index 7f11089..1192b74 100644 +--- a/xbmc/guilib/GUIFont.cpp ++++ b/xbmc/guilib/GUIFont.cpp +@@ -22,6 +22,7 @@ + #include "GUIFontTTF.h" + #include "GraphicContext.h" + ++#include "Application.h" + #include "threads/SingleLock.h" + #include "utils/TimeUtils.h" + #include "utils/MathUtils.h" +@@ -128,6 +129,9 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo) + // If the string is smaller than the viewport, then it may be plotted even + // more times than that. + // ++ if (g_application.ScreenSaverDisablesAutoScrolling()) ++ return false; ++ + if (scrollInfo.waitTime) + { + scrollInfo.waitTime--; +diff --git a/xbmc/guilib/GUILabel.cpp b/xbmc/guilib/GUILabel.cpp +index 759ac09..bed6ad2 100644 +--- a/xbmc/guilib/GUILabel.cpp ++++ b/xbmc/guilib/GUILabel.cpp +@@ -21,6 +21,8 @@ + #include "GUILabel.h" + #include + ++#include "Application.h" ++ + CGUILabel::CGUILabel(float posX, float posY, float width, float height, const CLabelInfo& labelInfo, CGUILabel::OVER_FLOW overflow) + : m_label(labelInfo) + , m_textLayout(labelInfo.font, overflow == OVER_FLOW_WRAP, height) +@@ -104,7 +106,7 @@ void CGUILabel::Render() + color_t color = GetColor(); + bool renderSolid = (m_color == COLOR_DISABLED); + bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues +- if (overFlows && m_scrolling && !renderSolid) ++ if (overFlows && m_scrolling && !renderSolid && !g_application.ScreenSaverDisablesAutoScrolling()) + m_textLayout.RenderScrolling(m_renderRect.x1, m_renderRect.y1, m_label.angle, color, m_label.shadowColor, 0, m_renderRect.Width(), m_scrollInfo); + else + { +diff --git a/xbmc/guilib/GUITextBox.cpp b/xbmc/guilib/GUITextBox.cpp +index 0d5b3f7..6d23024 100644 +--- a/xbmc/guilib/GUITextBox.cpp ++++ b/xbmc/guilib/GUITextBox.cpp +@@ -23,6 +23,7 @@ + #include "utils/XBMCTinyXML.h" + #include "utils/MathUtils.h" + #include "utils/StringUtils.h" ++#include "Application.h" + + #include + +@@ -134,7 +135,7 @@ void CGUITextBox::Process(unsigned int currentTime, CDirtyRegionList &dirtyregio + // update our auto-scrolling as necessary + if (m_autoScrollTime && m_lines.size() > m_itemsPerPage) + { +- if (!m_autoScrollCondition || m_autoScrollCondition->Get()) ++ if ((!m_autoScrollCondition || m_autoScrollCondition->Get()) && !g_application.ScreenSaverDisablesAutoScrolling()) + { + if (m_lastRenderTime) + m_autoScrollDelayTime += currentTime - m_lastRenderTime; + +From 155e82d4d93530d221a68eafcf8c4940e84cfd95 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 13 Dec 2014 18:35:20 +0000 +Subject: [PATCH 50/95] [demuxer] Avoid memcpy on every demuxer packet + +Avoids an unnecessary memcpy on every demuxer packet which for +high bitrate videos can be significant. +--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 14 +++++++++----- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h | 3 +++ + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp | 7 ++++++- + 3 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 643c219..2f70412 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -742,7 +742,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + { + if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) + { +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0); + break; + } + } +@@ -751,7 +751,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + bReturnEmpty = true; + } + else +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0); + } + else + bReturnEmpty = true; +@@ -793,9 +793,13 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + // copy contents into our own packet + pPacket->iSize = m_pkt.pkt.size; + +- // maybe we can avoid a memcpy here by detecting where pkt.destruct is pointing too? + if (m_pkt.pkt.data) +- memcpy(pPacket->pData, m_pkt.pkt.data, pPacket->iSize); ++ { ++ pPacket->pData = m_pkt.pkt.data; ++ // so we can free AVPacket when DemuxPacket is freed ++ pPacket->pkt = new AVPacket(m_pkt.pkt); ++ } ++ + + pPacket->pts = ConvertTimestamp(m_pkt.pkt.pts, stream->time_base.den, stream->time_base.num); + pPacket->dts = ConvertTimestamp(m_pkt.pkt.dts, stream->time_base.den, stream->time_base.num); +@@ -830,7 +834,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + pPacket->iStreamId = m_pkt.pkt.stream_index; + } + m_pkt.result = -1; +- av_free_packet(&m_pkt.pkt); ++ memset(&m_pkt.pkt, 0, sizeof(AVPacket)); + } + } + } // end of lock scope +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h +index d64fbb3..012a7d1 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h +@@ -23,6 +23,8 @@ + #define DMX_SPECIALID_STREAMINFO -10 + #define DMX_SPECIALID_STREAMCHANGE -11 + ++struct AVPacket; ++ + typedef struct DemuxPacket + { + unsigned char* pData; // data +@@ -33,4 +35,5 @@ + double pts; // pts in DVD_TIME_BASE + double dts; // dts in DVD_TIME_BASE + double duration; // duration in DVD_TIME_BASE if available ++ AVPacket *pkt; // to allow packet to be freed + } DemuxPacket; +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp +index ab298b2..10c5ee0 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp +@@ -34,7 +34,12 @@ void CDVDDemuxUtils::FreeDemuxPacket(DemuxPacket* pPacket) + if (pPacket) + { + try { +- if (pPacket->pData) _aligned_free(pPacket->pData); ++ if (pPacket->pkt) ++ { ++ av_free_packet(pPacket->pkt); ++ delete pPacket->pkt; ++ } ++ else if (pPacket->pData) _aligned_free(pPacket->pData); + delete pPacket; + } + catch(...) { + +From cf6da32e13b18eb76794134436b91ed44358f9a6 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:27:59 +0100 +Subject: [PATCH 51/95] - added setting for allowing to hide watched + movies/episodes/musicvideos in the recently added lists of the home screen + +--- + addons/resource.language.en_gb/resources/strings.po | 16 ++++++++++++++-- + system/settings/settings.xml | 5 +++++ + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index af96b08..a4c078c 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -11142,7 +11142,13 @@ msgctxt "#20469" + msgid "Keep current set (%s)" + msgstr "" + +-#empty strings from id 20470 to 21329 ++#. Label of setting "Videos -> Library -> Hide watched videos in recently added list (home screen)" ++#: system/settings/settings.xml ++msgctxt "#20470" ++msgid "Hide watched videos in recently added list (home screen)" ++msgstr "" ++ ++#empty strings from id 20471 to 21329 + #up to 21329 is reserved for the video db !! ! + + #: system/settings/settings.xml +@@ -15958,7 +15964,13 @@ msgctxt "#36435" + msgid "Use DVDPlayer for decoding of video files with MMAL acceleration." + msgstr "" + +-#empty strings from id 36436 to 36499 ++#. Description of setting "Videos -> Library -> Hide watched videos in recently added list." ++#: system/settings/settings.xml ++msgctxt "#36436" ++msgid "If enabled all watched items in the recently added list on the home screen will be hidden. This includes movies, episodes and musicvideos. The effect depends on the used skin and its settings." ++msgstr "" ++ ++#empty strings from id 36437 to 36499 + #end reservation + + #. label of a setting for the stereoscopic 3D mode of the GUI that is/should be applied +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 5a6c12f..92f767d 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -465,6 +465,11 @@ + false + + ++ ++ 1 ++ true ++ ++ + + + + +From 405d02a63d8819fad8bc026d55c02309a4d824e5 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:28:36 +0100 +Subject: [PATCH 52/95] - evaluate the setting for hiding watched + movies/episodes/musicvideos in recently added job (should influence + homescreen of skins only) + +--- + xbmc/utils/RecentlyAddedJob.cpp | 10 +++++----- + xbmc/video/VideoDatabase.cpp | 27 ++++++++++++++++++++++++--- + xbmc/video/VideoDatabase.h | 6 +++--- + 3 files changed, 32 insertions(+), 11 deletions(-) + +diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp +index 1f8ec36..de45783 100644 +--- a/xbmc/utils/RecentlyAddedJob.cpp ++++ b/xbmc/utils/RecentlyAddedJob.cpp +@@ -31,6 +31,7 @@ + #include "utils/Variant.h" + #include "utils/StringUtils.h" + #include "settings/AdvancedSettings.h" ++#include "settings/Settings.h" + #include "music/MusicThumbLoader.h" + #include "video/VideoThumbLoader.h" + +@@ -57,8 +58,8 @@ bool CRecentlyAddedJob::UpdateVideo() + loader.OnLoaderStart(); + + videodatabase.Open(); +- +- if (videodatabase.GetRecentlyAddedMoviesNav("videodb://recentlyaddedmovies/", items, NUM_ITEMS)) ++ bool hideWatched = CSettings::Get().GetBool("videolibrary.hiderecentlywatchedvideos"); ++ if (videodatabase.GetRecentlyAddedMoviesNav("videodb://recentlyaddedmovies/", items, NUM_ITEMS, hideWatched)) + { + for (; i < items.Size(); ++i) + { +@@ -97,8 +98,7 @@ bool CRecentlyAddedJob::UpdateVideo() + + i = 0; + CFileItemList TVShowItems; +- +- if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://recentlyaddedepisodes/", TVShowItems, NUM_ITEMS)) ++ if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://recentlyaddedepisodes/", TVShowItems, NUM_ITEMS, hideWatched)) + { + for (; i < TVShowItems.Size(); ++i) + { +@@ -151,7 +151,7 @@ bool CRecentlyAddedJob::UpdateVideo() + i = 0; + CFileItemList MusicVideoItems; + +- if (videodatabase.GetRecentlyAddedMusicVideosNav("videodb://recentlyaddedmusicvideos/", MusicVideoItems, NUM_ITEMS)) ++ if (videodatabase.GetRecentlyAddedMusicVideosNav("videodb://recentlyaddedmusicvideos/", MusicVideoItems, NUM_ITEMS, hideWatched)) + { + for (; i < MusicVideoItems.Size(); ++i) + { +diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp +index 96fa5fd..ca6f0f3 100644 +--- a/xbmc/video/VideoDatabase.cpp ++++ b/xbmc/video/VideoDatabase.cpp +@@ -6552,27 +6552,48 @@ bool CVideoDatabase::GetMusicVideosNav(const std::string& strBaseDir, CFileItemL + return GetMusicVideosByWhere(videoUrl.ToString(), filter, items, true, sortDescription); + } + +-bool CVideoDatabase::GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit) ++bool CVideoDatabase::GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit, bool hideWatched) + { + Filter filter; + filter.order = "dateAdded desc, idMovie desc"; + filter.limit = PrepareSQL("%u", limit ? limit : g_advancedSettings.m_iVideoLibraryRecentlyAddedItems); ++ ++ if (hideWatched) ++ { ++ filter.AppendWhere("playCount <= 0");// only query unwatched items ++ filter.AppendWhere("playCount IS NULL", false); ++ } ++ + return GetMoviesByWhere(strBaseDir, filter, items); + } + +-bool CVideoDatabase::GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit) ++bool CVideoDatabase::GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit, bool hideWatched) + { + Filter filter; + filter.order = "dateAdded desc, idEpisode desc"; + filter.limit = PrepareSQL("%u", limit ? limit : g_advancedSettings.m_iVideoLibraryRecentlyAddedItems); ++ ++ if (hideWatched) ++ { ++ filter.AppendWhere("playCount <= 0");// only query unwatched items ++ filter.AppendWhere("playCount IS NULL", false); ++ } ++ + return GetEpisodesByWhere(strBaseDir, filter, items, false); + } + +-bool CVideoDatabase::GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit) ++bool CVideoDatabase::GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit, bool hideWatched) + { + Filter filter; + filter.order = "dateAdded desc, idMVideo desc"; + filter.limit = PrepareSQL("%u", limit ? limit : g_advancedSettings.m_iVideoLibraryRecentlyAddedItems); ++ ++ if (hideWatched) ++ { ++ filter.AppendWhere("playCount <= 0");// only query unwatched items ++ filter.AppendWhere("playCount IS NULL", false); ++ } ++ + return GetMusicVideosByWhere(strBaseDir, filter, items); + } + +diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h +index ca62f23..b905e48 100644 +--- a/xbmc/video/VideoDatabase.h ++++ b/xbmc/video/VideoDatabase.h +@@ -683,9 +683,9 @@ class CVideoDatabase : public CDatabase + bool GetEpisodesNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idShow=-1, int idSeason=-1, const SortDescription &sortDescription = SortDescription()); + bool GetMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idArtist=-1, int idDirector=-1, int idStudio=-1, int idAlbum=-1, int idTag=-1, const SortDescription &sortDescription = SortDescription()); + +- bool GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0); +- bool GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0); +- bool GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0); ++ bool GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, bool hideWatched=false); ++ bool GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, bool hideWatched=false); ++ bool GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, bool hideWatched=false); + + bool HasContent(); + bool HasContent(VIDEODB_CONTENT_TYPE type); + +From 8361c453c28e8ee81a663a0ba071c690863b85f6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Jan 2015 21:48:31 +0000 +Subject: [PATCH 53/95] [omximage] Increase timeout - this is sometimes hit + +--- + xbmc/cores/omxplayer/OMXImage.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index 86a683a..54a52a7 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1885,7 +1885,7 @@ bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, uns + } + if (m_encoded_buffer) + { +- omx_err = m_omx_encoder.WaitForOutputDone(1000); ++ 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)\n", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); + +From 6b349309ea57c3b9d997a3766566e554d9fba658 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 24 Jan 2015 17:34:04 +0000 +Subject: [PATCH 54/95] temp: Some hacks to help profiling + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 5 +++++ + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 4 ++-- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++ + 3 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index 7c68e1c..6a2fee9 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -564,6 +564,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) + CActiveAEStream *stream; + streamMsg = (MsgStreamNew*)msg->data; + stream = CreateStream(streamMsg); ++ CLog::Log(LOGNOTICE, "ActiveAE::%s - NEWSTREAM %p %p", __FUNCTION__, streamMsg, stream); + if(stream) + { + msg->Reply(CActiveAEDataProtocol::ACC, &stream, sizeof(CActiveAEStream*)); +@@ -1228,6 +1229,7 @@ CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg) + } + if (hasRawStream || (hasStream && AE_IS_RAW(streamMsg->format.m_dataFormat))) + { ++ CLog::Log(LOGNOTICE, "CActiveAE::CreateStream - raw"); + return NULL; + } + +@@ -1256,6 +1258,7 @@ CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg) + + m_streams.push_back(stream); + ++ CLog::Log(LOGNOTICE, "CActiveAE::CreateStream - %p", stream); + return stream; + } + +@@ -2750,11 +2753,13 @@ IAEStream *CActiveAE::MakeStream(enum AEDataFormat dataFormat, unsigned int samp + msg.options = options; + + Message *reply; ++ CLog::Log(LOGNOTICE, "ActiveAE::%s - about to create stream", __FUNCTION__); + if (m_dataPort.SendOutMessageSync(CActiveAEDataProtocol::NEWSTREAM, + &reply,10000, + &msg, sizeof(MsgStreamNew))) + { + bool success = reply->signal == CActiveAEControlProtocol::ACC; ++ CLog::Log(LOGNOTICE, "ActiveAE::%s - created stream : %d", __FUNCTION__, success); + if (success) + { + CActiveAEStream *stream = *(CActiveAEStream**)reply->data; +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index a064da5..ebc4458 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -36,7 +36,7 @@ + #define CLASSNAME "CMMALRenderer" + + #ifdef _DEBUG +-#define MMAL_DEBUG_VERBOSE ++//#define MMAL_DEBUG_VERBOSE + #endif + + static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +@@ -372,7 +372,7 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + #endif + omvb->Acquire(); + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); +- } else assert(0); ++ } //else assert(0); + } + else if (m_format == RENDER_FMT_YUV420P) + { +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 5832c58..76c708d 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -162,6 +162,8 @@ CDVDPlayerVideo::CDVDPlayerVideo( CDVDClock* pClock + + CDVDPlayerVideo::~CDVDPlayerVideo() + { ++ CLog::Log(LOGNOTICE, "drop:%d skip:%d", m_iDroppedFrames, g_renderManager.GetSkippedFrames()); ++ + StopThread(); + g_VideoReferenceClock.Stop(); + } + +From 745d0770dda43582b22d82eea82a23157bd2018e Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Wed, 4 Feb 2015 22:32:03 +0100 +Subject: [PATCH 55/95] NFSFile: Chank ChunkSize to 1MB + +--- + xbmc/filesystem/NFSFile.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/filesystem/NFSFile.h b/xbmc/filesystem/NFSFile.h +index 4c01e4e..7afa6b8 100644 +--- a/xbmc/filesystem/NFSFile.h ++++ b/xbmc/filesystem/NFSFile.h +@@ -148,7 +148,7 @@ namespace XFILE + //implement iocontrol for seek_possible for preventing the stat in File class for + //getting this info ... + virtual int IoControl(EIoControl request, void* param){ if(request == IOCTRL_SEEK_POSSIBLE) return 1;return -1;}; +- virtual int GetChunkSize() {return 1;} ++ virtual int GetChunkSize() {return 1024*1024;} + + virtual bool OpenForWrite(const CURL& url, bool bOverWrite = false); + virtual bool Delete(const CURL& url); + +From 86640c251777f7c4cff679270bf00b4f3dde7415 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Feb 2015 00:19:51 +0000 +Subject: [PATCH 58/95] [libnfs] Add streaming cache + +--- + .../libnfs/0001-Sequential-Readahead-Mode.patch | 949 +++++++++++++++++++++ + tools/depends/target/libnfs/Makefile | 1 + + xbmc/filesystem/DllLibNfs.h | 3 + + xbmc/filesystem/NFSFile.cpp | 2 + + 4 files changed, 955 insertions(+) + create mode 100644 tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch + +diff --git a/tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch b/tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch +new file mode 100644 +index 0000000..83b7e11 +--- /dev/null ++++ b/tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch +@@ -0,0 +1,949 @@ ++From ae7ef01ad15ea91f669a59d4fd44aa9c03a3a6fb Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 11:16:38 -0800 ++Subject: [PATCH 1/7] Sequential Readahead Mode ++ ++Add a new api to activate sequential reading of files. ++It is activated by calling nfs_set_streaming_mode(fs,size) ++with a filehandle and a size. ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ include/nfsc/libnfs-raw.h | 9 ++ ++ include/nfsc/libnfs.h | 14 +++ ++ lib/libnfs-sync.c | 12 ++- ++ lib/libnfs-win32.def | 5 + ++ lib/libnfs.c | 258 +++++++++++++++++++++++++++++++++++++++++++++- ++ lib/socket.c | 15 ++- ++ 6 files changed, 308 insertions(+), 5 deletions(-) ++ ++diff --git a/include/nfsc/libnfs-raw.h b/include/nfsc/libnfs-raw.h ++index 3ba9de3..4593cc6 100644 ++--- a/include/nfsc/libnfs-raw.h +++++ b/include/nfsc/libnfs-raw.h ++@@ -44,6 +44,15 @@ int rpc_get_fd(struct rpc_context *rpc); ++ int rpc_which_events(struct rpc_context *rpc); ++ int rpc_service(struct rpc_context *rpc, int revents); ++ char *rpc_get_error(struct rpc_context *rpc); +++ +++/* Return the number of PDUs in the outqueue. +++ * This is the count of PDUs not yet written to the socket. +++ */ +++int rpc_outqueue_length(struct rpc_context *rpc); +++/* Return the number all in flight PDUs. +++ * This includes both the PDUs not yet written to the socket as well as +++ * all PDUs we have sent to the server but not yet received a reply to. +++ */ ++ int rpc_queue_length(struct rpc_context *rpc); ++ ++ /* Utility function to get an RPC context from a NFS context. Useful for doing low level NFSACL ++diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h ++index 2d14113..f84650b 100644 ++--- a/include/nfsc/libnfs.h +++++ b/include/nfsc/libnfs.h ++@@ -83,6 +83,15 @@ struct utimbuf { ++ EXTERN int nfs_get_fd(struct nfs_context *nfs); ++ EXTERN int nfs_which_events(struct nfs_context *nfs); ++ EXTERN int nfs_service(struct nfs_context *nfs, int revents); +++ +++/* Return the number of PDUs in the outqueue. +++ * This is the count of PDUs not yet written to the socket. +++ */ +++EXTERN int nfs_outqueue_length(struct nfs_context *nfs); +++/* Return the number all in flight PDUs. +++ * This includes both the PDUs not yet written to the socket as well as +++ * all PDUs we have sent to the server but not yet received a reply to. +++ */ ++ EXTERN int nfs_queue_length(struct nfs_context *nfs); ++ ++ /* ++@@ -191,6 +200,11 @@ EXTERN void nfs_set_uid(struct nfs_context *nfs, int uid); ++ EXTERN void nfs_set_gid(struct nfs_context *nfs, int gid); ++ EXTERN void nfs_set_readahead(struct nfs_context *nfs, uint32_t v); ++ +++/* Optimize for sequentianl streaming reads. size is the amount +++ * of buffering. +++ */ +++EXTERN int nfs_set_streaming_mode(struct nfsfh *nfsfh, uint32_t size); +++ ++ /* ++ * MOUNT THE EXPORT ++ */ ++diff --git a/lib/libnfs-sync.c b/lib/libnfs-sync.c ++index 59911fc..dc696c3 100644 ++--- a/lib/libnfs-sync.c +++++ b/lib/libnfs-sync.c ++@@ -137,9 +137,14 @@ static void wait_for_reply(struct rpc_context *rpc, struct sync_cb_data *cb_data ++ static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data) ++ { ++ struct pollfd pfd; ++- ++- while (!cb_data->is_finished) { ++- +++ int available; +++ +++ /* loop until the command has completed, and we have written all +++ * queued PDUs to the socket, and we have read and processed all +++ * data in the socket receive buffer. +++ */ +++ ioctl(nfs_get_fd(nfs), FIONREAD, &available); +++ while (!cb_data->is_finished || nfs_outqueue_length(nfs) || available) { ++ pfd.fd = nfs_get_fd(nfs); ++ pfd.events = nfs_which_events(nfs); ++ if (poll(&pfd, 1, -1) < 0) { ++@@ -152,6 +157,7 @@ static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_ ++ cb_data->status = -EIO; ++ break; ++ } +++ ioctl(nfs_get_fd(nfs), FIONREAD, &available); ++ } ++ } ++ ++diff --git a/lib/libnfs-win32.def b/lib/libnfs-win32.def ++index 5a0df03..bdfa737 100644 ++--- a/lib/libnfs-win32.def +++++ b/lib/libnfs-win32.def ++@@ -48,6 +48,7 @@ nfs_open ++ nfs_open_async ++ nfs_opendir ++ nfs_opendir_async +++nfs_outqueue_length ++ nfs_parse_url_full ++ nfs_parse_url_dir ++ nfs_parse_url_incomplete ++@@ -56,6 +57,7 @@ nfs_pread ++ nfs_pread_async ++ nfs_pwrite ++ nfs_pwrite_async +++nfs_queue_length ++ nfs_read ++ nfs_read_async ++ nfs_readdir ++@@ -71,6 +73,7 @@ nfs_set_gid ++ nfs_set_tcp_syncnt ++ nfs_set_uid ++ nfs_set_readahead +++nfs_set_streaming_mode ++ nfs_stat ++ nfs_stat_async ++ nfs_stat64 ++@@ -205,6 +208,8 @@ rpc_nsm1_unmon_async ++ rpc_nsm1_unmonall_async ++ rpc_nsm1_simucrash_async ++ rpc_nsm1_notify_async +++rpc_outqueue_length +++rpc_queue_length ++ rpc_rquota1_null_async ++ rpc_rquota1_getquota_async ++ rpc_rquota1_getactivequota_async ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index f807822..5fc921d 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -108,12 +108,37 @@ struct nfs_readahead { ++ uint32_t cur_ra; ++ }; ++ +++/* Store streaming cache in blocks of this size */ +++#define NFS_STREAM_BUF_SIZE (32768 * 4) +++/* Skip trying to streaming caching for reads greater than this */ +++#define NFS_MAX_STREAMING_SIZE (1024 * 1024) +++ +++#define BSS_UNUSED 0 +++#define BSS_PENDING 1 +++#define BSS_VALID 2 +++struct nfs_streaming_block { +++ int state; +++ unsigned char *ptr; +++}; +++ +++struct nfs_streaming_read { +++ uint64_t next_offset; +++ int num_seq; +++ +++ int num_blocks; /* number of buffer blocks */ +++ uint64_t buf_offset; +++ struct nfs_streaming_block *blocks; +++ unsigned char *buf; +++}; +++ ++ struct nfsfh { ++ struct nfs_fh3 fh; ++ int is_sync; ++ int is_append; ++ uint64_t offset; ++- struct nfs_readahead ra; +++ +++ struct nfs_streaming_read *sr; +++ struct nfs_readahead ra; /* broken? */ ++ }; ++ ++ struct nested_mounts { ++@@ -231,6 +256,11 @@ int nfs_get_fd(struct nfs_context *nfs) ++ return rpc_get_fd(nfs->rpc); ++ } ++ +++int nfs_outqueue_length(struct nfs_context *nfs) +++{ +++ return rpc_outqueue_length(nfs->rpc); +++} +++ ++ int nfs_queue_length(struct nfs_context *nfs) ++ { ++ return rpc_queue_length(nfs->rpc); ++@@ -730,12 +760,52 @@ static void free_nfs_cb_data(struct nfs_cb_data *data) ++ free(data); ++ } ++ +++int nfs_set_streaming_mode(struct nfsfh *nfsfh, uint32_t size) +++{ +++ struct nfs_streaming_read *sr; +++ int i; +++ +++ sr = malloc(sizeof(struct nfs_streaming_read)); +++ if (sr == NULL) { +++ return -1; +++ } +++ memset(sr, 0, sizeof(struct nfs_streaming_read)); +++ sr->num_blocks = size / NFS_STREAM_BUF_SIZE; +++ +++ sr->buf = malloc(sr->num_blocks * NFS_STREAM_BUF_SIZE); +++ if (sr->buf == NULL) { +++ free(sr); +++ return -1; +++ } +++ memset(sr->buf, 0, sr->num_blocks * NFS_STREAM_BUF_SIZE); +++ +++ sr->blocks = malloc(sr->num_blocks * sizeof(struct nfs_streaming_block)) +++; +++ if (sr->blocks == NULL) { +++ free(sr->buf); +++ free(sr); +++ return -1; +++ } +++ for (i = 0; i < sr->num_blocks; i++) { +++ sr->blocks[i].state = BSS_UNUSED; +++ sr->blocks[i].ptr = &sr->buf[i * NFS_STREAM_BUF_SIZE]; +++ } +++ nfsfh->sr = sr; +++ +++ return 0; +++} +++ ++ static void free_nfsfh(struct nfsfh *nfsfh) ++ { ++ if (nfsfh->fh.data.data_val != NULL) { ++ free(nfsfh->fh.data.data_val); ++ nfsfh->fh.data.data_val = NULL; ++ } +++ if (nfsfh->sr != NULL) { +++ free(nfsfh->sr->blocks); +++ free(nfsfh->sr->buf); +++ free(nfsfh->sr); +++ } ++ free(nfsfh->ra.buf); ++ free(nfsfh); ++ } ++@@ -2033,6 +2103,8 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, ++ nfsfh->fh = data->fh; ++ data->fh.data.data_val = NULL; ++ +++ nfs_set_streaming_mode(nfsfh, 200 * NFS_STREAM_BUF_SIZE); +++ ++ data->cb(0, nfs, nfsfh, data->private_data); ++ free_nfs_cb_data(data); ++ } ++@@ -2252,10 +2324,194 @@ static void nfs_ra_invalidate(struct nfsfh *nfsfh) { ++ nfsfh->ra.cur_ra = NFS_BLKSIZE; ++ } ++ +++struct stream_cb_data { +++ uint64_t offset; +++ struct nfsfh *nfsfh; +++}; +++ +++static void nfs_stream_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +++{ +++ struct stream_cb_data *stream_data = private_data; +++ struct nfsfh *nfsfh = stream_data->nfsfh; +++ READ3res *res; +++ int i; +++ +++ assert(rpc->magic == RPC_CONTEXT_MAGIC); +++ +++ if (stream_data->offset < nfsfh->sr->buf_offset) { +++ free(stream_data); +++ return; +++ } +++ if (stream_data->offset >= nfsfh->sr->buf_offset + nfsfh->sr->num_blocks * NFS_STREAM_BUF_SIZE) { +++ free(stream_data); +++ return; +++ } +++ +++ i = (stream_data->offset - nfsfh->sr->buf_offset) / NFS_STREAM_BUF_SIZE; +++ nfsfh->sr->blocks[i].state = BSS_UNUSED; +++ free(stream_data); +++ +++ if (status == RPC_STATUS_ERROR) { +++ return; +++ } +++ if (status == RPC_STATUS_CANCEL) { +++ return; +++ } +++ if (status == RPC_STATUS_SUCCESS) { +++ res = command_data; +++ if (res->status != NFS3_OK) { +++ return; +++ } +++ if (res->READ3res_u.resok.count != NFS_STREAM_BUF_SIZE) { +++ return; +++ } +++ memcpy(nfsfh->sr->blocks[i].ptr, +++ res->READ3res_u.resok.data.data_val, +++ NFS_STREAM_BUF_SIZE); +++ nfsfh->sr->blocks[i].state = BSS_VALID; +++ } +++} +++ +++static void prefetch_streaming_blocks(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t next_offset, int num_blocks) +++{ +++ int i; +++ +++ for (i = 0; i < nfsfh->sr->num_blocks && num_blocks; i++) { +++ struct stream_cb_data *stream_data; +++ READ3args args; +++ +++ if (nfsfh->sr->blocks[i].state != BSS_UNUSED) { +++ continue; +++ } +++ +++ stream_data = malloc(sizeof(struct stream_cb_data)); +++ if (stream_data == NULL) { +++ return; +++ } +++ stream_data->offset = i * NFS_STREAM_BUF_SIZE + nfsfh->sr->buf_offset; +++ stream_data->nfsfh = nfsfh; +++ +++ nfs_fill_READ3args(&args, nfsfh, stream_data->offset, NFS_STREAM_BUF_SIZE); +++ if (rpc_nfs3_read_async(nfs->rpc, nfs_stream_cb, &args, stream_data) != 0) { +++ free(stream_data); +++ return; +++ } +++ +++ nfsfh->sr->blocks[i].state = BSS_PENDING; +++ num_blocks--; +++ } +++} +++ ++ static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data, int update_pos) ++ { ++ struct nfs_cb_data *data; ++ +++ if (nfsfh->sr != NULL && count <= NFS_MAX_STREAMING_SIZE) { +++ int i, len, remaining, first_block, last_block; +++ unsigned char *buf, *pos; +++ +++ /* track sequential access */ +++ if (offset == nfsfh->sr->next_offset) { +++ nfsfh->sr->num_seq++; +++ } else { +++ if (nfsfh->sr->blocks[0].state != BSS_UNUSED) { +++ for (i = 0; i < nfsfh->sr->num_blocks; i++) { +++ nfsfh->sr->blocks[i].state = BSS_UNUSED; +++ } +++ } +++ nfsfh->sr->num_seq = 0; +++ } +++ nfsfh->sr->next_offset = offset + count; +++ +++ if (nfsfh->sr->num_seq < 5) { +++ goto end_of_streaming; +++ } +++ +++ /* If we do not have any cached data yet, reset buffer +++ * offset to point slightly ahead of the current read. +++ */ +++ if (nfsfh->sr->blocks[0].state == BSS_UNUSED) { +++ nfsfh->sr->buf_offset = (offset / NFS_STREAM_BUF_SIZE + 1) * NFS_STREAM_BUF_SIZE ; +++ } +++ +++ /* Prune head blocks we have read past */ +++ while (nfsfh->sr->blocks[0].state != BSS_UNUSED && +++ offset >= (nfsfh->sr->buf_offset + NFS_STREAM_BUF_SIZE)) { +++ unsigned char *ptr; +++ +++ ptr = nfsfh->sr->blocks[0].ptr; +++ memmove(&nfsfh->sr->blocks[0], &nfsfh->sr->blocks[1], +++ (nfsfh->sr->num_blocks - 1) +++ * sizeof(struct nfs_streaming_block)); +++ nfsfh->sr->buf_offset += NFS_STREAM_BUF_SIZE; +++ nfsfh->sr->blocks[nfsfh->sr->num_blocks - 1].state = BSS_UNUSED; +++ nfsfh->sr->blocks[nfsfh->sr->num_blocks - 1].ptr = ptr; +++ } +++ +++ /* try to prefetch four more blocks */ +++ prefetch_streaming_blocks(nfs, nfsfh, offset + count, 4); +++ +++ /* can we service the request straight out of cache ? */ +++ if (offset < nfsfh->sr->buf_offset) { +++ goto end_of_streaming; +++ } +++ first_block = (offset - nfsfh->sr->buf_offset) / NFS_STREAM_BUF_SIZE; +++ if (first_block >= nfsfh->sr->num_blocks) { +++ goto end_of_streaming; +++ } +++ +++ if (offset + count > nfsfh->sr->buf_offset + nfsfh->sr->num_blocks * NFS_STREAM_BUF_SIZE) { +++ goto end_of_streaming; +++ } +++ last_block = (offset + count - nfsfh->sr->buf_offset - 1) / NFS_STREAM_BUF_SIZE; +++ if (last_block >= nfsfh->sr->num_blocks) { +++ goto end_of_streaming; +++ } +++ if (last_block < first_block) { +++ goto end_of_streaming; +++ } +++ for (i = first_block; i <= last_block; i++) { +++ if (nfsfh->sr->blocks[i].state != BSS_VALID) { +++ goto end_of_streaming; +++ } +++ } +++ if (first_block == last_block) { +++ if (update_pos) { +++ nfsfh->offset += count; +++ } +++ cb(count, nfs, &nfsfh->sr->blocks[first_block].ptr[offset % NFS_STREAM_BUF_SIZE], private_data); +++ return 0; +++ } +++ +++ buf = malloc(count); +++ if (buf == NULL) { +++ goto end_of_streaming; +++ } +++ remaining = count; +++ pos = buf; +++ len = NFS_STREAM_BUF_SIZE - offset % NFS_STREAM_BUF_SIZE; +++ if (len > count) { +++ len = count; +++ } +++ memcpy(pos, &nfsfh->sr->blocks[first_block].ptr[offset % NFS_STREAM_BUF_SIZE], len); +++ remaining -= len; +++ pos += len; +++ +++ for (i = first_block + 1; remaining; i++) { +++ len = (remaining >= NFS_STREAM_BUF_SIZE) ? NFS_STREAM_BUF_SIZE : remaining; +++ memcpy(pos, &nfsfh->sr->blocks[i].ptr[0], len); +++ remaining -= len; +++ pos += len; +++ } +++ if (update_pos) { +++ nfsfh->offset += count; +++ } +++ cb(count, nfs, buf, private_data); +++ free(buf); +++ return 0; +++ } +++end_of_streaming: +++ ++ data = malloc(sizeof(struct nfs_cb_data)); ++ if (data == NULL) { ++ rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure"); ++diff --git a/lib/socket.c b/lib/socket.c ++index 3588246..41fb5b2 100644 ++--- a/lib/socket.c +++++ b/lib/socket.c ++@@ -755,7 +755,7 @@ struct sockaddr *rpc_get_recv_sockaddr(struct rpc_context *rpc) ++ return (struct sockaddr *)&rpc->udp_src; ++ } ++ ++-int rpc_queue_length(struct rpc_context *rpc) +++int rpc_outqueue_length(struct rpc_context *rpc) ++ { ++ int i=0; ++ struct rpc_pdu *pdu; ++@@ -767,6 +767,19 @@ int rpc_queue_length(struct rpc_context *rpc) ++ i++; ++ } ++ +++ return i; +++} +++ +++int rpc_queue_length(struct rpc_context *rpc) +++{ +++ int i=0; +++ struct rpc_pdu *pdu; +++ unsigned int n; +++ +++ assert(rpc->magic == RPC_CONTEXT_MAGIC); +++ +++ i = rpc_outqueue_length(rpc); +++ ++ for (n = 0; n < HASHES; n++) { ++ struct rpc_queue *q = &rpc->waitpdu[n]; ++ ++-- ++1.9.1 ++ ++ ++From 6f6832b6c19a26557883af924d7135f5ef87f45d Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 12:43:59 -0800 ++Subject: [PATCH 2/7] nfs-stream.c: a simple test tool to check performance ++ sequential read mode ++ ++./nfs-stream ++ ++This tool is for testing sequential read mode. ++It reads 32kbyte one block at a time using the sync API. ++The idea is that when a nfs_[p]read() command is executed, we will once we ++identify a sequential scan start issuing asynchronous commands in the ++background to populate a readahead cache. ++ ++During read, we try to service the request immediately out of cache ++and return immediately to the application. During read from cache we will also ++process any to previous reads and use it to populate the cache. Also, as the ++file offset grows, we will discard the already read blocks from the cache ++and issue new asynchronous commands at the tail of the cache. ++ ++nfs_read() will when the cache is operating behave like : ++ nfs_read() { ++ ... process any previous reads and populate the cache ... ++ ... send async command to replenish the tail of the cache ... ++ return data from cache straigh back to application ++ } ++ ++The test tool will try to read 32kb chunks at a given rate. ++Once the test tool manages to service from cache the read laency should drop ++to <<1ms and the majority of the time spent will be in the sleep() between calls. ++Once the latency is steady at <<1ms this is an indication that we now ++service all reads out of cache instead of the network. ++If the read latency remains <<1ms continously, without any spikes, it means that ++we have been successfull in maintaining the asycntrhous tasks to replenish the cache. ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ nfs-stream.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 65 insertions(+) ++ create mode 100644 nfs-stream.c ++ ++diff --git a/nfs-stream.c b/nfs-stream.c ++new file mode 100644 ++index 0000000..5570cd6 ++--- /dev/null +++++ b/nfs-stream.c ++@@ -0,0 +1,65 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include "nfsc/libnfs.h" +++ +++int main(int argc, char *argv[]) +++{ +++ struct nfs_context *nfs; +++ struct nfs_url *url; +++ struct nfsfh *nfsfh = NULL; +++ struct nfs_stat_64 st; +++ uint64_t offset; +++ char buf[32768]; +++ struct timeval t1, t2; +++ uint64_t delta, tpc; +++ +++ nfs = nfs_init_context(); +++ url = nfs_parse_url_full(nfs, argv[1]); +++ if (!url) { +++ fprintf(stderr, "Can not parse URL. %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_mount(nfs, url->server, url->path) != 0) { +++ fprintf(stderr, "Failed to mount nfs share : %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { +++ fprintf(stderr, "Failed to open file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_fstat64(nfs, nfsfh, &st)) { +++ fprintf(stderr, "Failed to stat file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ printf("File size:%lld\n", (long long)st.nfs_size); +++ tpc = 1000000 / (strtol(argv[2], NULL, 10) / 32768); +++ printf("Read one 32kb chunk every %d us\n", (int)tpc); +++ for (offset = 0; offset < st.nfs_size; offset += 32768) { +++ gettimeofday(&t1, NULL); +++ nfs_read(nfs, nfsfh, 8192, buf); +++ gettimeofday(&t2, NULL); +++ delta = t2.tv_sec * 1000000LL + t2.tv_usec - +++ t1.tv_sec * 1000000LL - t1.tv_usec; +++ printf("Read latency:%lld us\n", (long long)delta); +++ if (tpc > delta) { +++ printf("Sleep for %d us\n", (int)(tpc - delta)); +++ usleep(tpc - delta); +++ } +++ } +++ +++ nfs_close(nfs, nfsfh); +++ nfs_destroy_context(nfs); +++ nfs_destroy_url(url); +++ return 0; +++} ++-- ++1.9.1 ++ ++ ++From 225e1c47727871c6ca74d6e3fef79ee6234923a1 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 13:31:02 -0800 ++Subject: [PATCH 3/7] streaming: only try refilling 2 blocks at a time instead ++ of 4 ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ lib/libnfs.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index 5fc921d..84e76b6 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -2448,8 +2448,8 @@ static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh ++ nfsfh->sr->blocks[nfsfh->sr->num_blocks - 1].ptr = ptr; ++ } ++ ++- /* try to prefetch four more blocks */ ++- prefetch_streaming_blocks(nfs, nfsfh, offset + count, 4); +++ /* try to prefetch to more blocks */ +++ prefetch_streaming_blocks(nfs, nfsfh, offset + count, 2); ++ ++ /* can we service the request straight out of cache ? */ ++ if (offset < nfsfh->sr->buf_offset) { ++-- ++1.9.1 ++ ++ ++From ceb35bb17425dda7408ae43ae80a997f4e1c1f95 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 16:19:59 -0800 ++Subject: [PATCH 4/7] read 32kb at a time, not 8kb ++ ++crapadoodle, if we measure 32kb blob read speed we should actually read ++a 32kb blob too. not a 8kb one. ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ nfs-stream.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++diff --git a/nfs-stream.c b/nfs-stream.c ++index 5570cd6..dd01218 100644 ++--- a/nfs-stream.c +++++ b/nfs-stream.c ++@@ -47,13 +47,13 @@ int main(int argc, char *argv[]) ++ printf("Read one 32kb chunk every %d us\n", (int)tpc); ++ for (offset = 0; offset < st.nfs_size; offset += 32768) { ++ gettimeofday(&t1, NULL); ++- nfs_read(nfs, nfsfh, 8192, buf); +++ nfs_read(nfs, nfsfh, 32768, buf); ++ gettimeofday(&t2, NULL); ++ delta = t2.tv_sec * 1000000LL + t2.tv_usec - ++ t1.tv_sec * 1000000LL - t1.tv_usec; ++ printf("Read latency:%lld us\n", (long long)delta); ++ if (tpc > delta) { ++- printf("Sleep for %d us\n", (int)(tpc - delta)); +++ //printf("Sleep for %d us\n", (int)(tpc - delta)); ++ usleep(tpc - delta); ++ } ++ } ++-- ++1.9.1 ++ ++ ++From 5f5faa8cfb86057081ccb3e30f987ecdec40fa13 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Mon, 9 Feb 2015 20:46:25 -0800 ++Subject: [PATCH 5/7] prefetch: limit the amount of prefetches we have in ++ flight to 2 ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ lib/libnfs.c | 16 +++++++++++++--- ++ nfs-stream.c | 7 +++++++ ++ 2 files changed, 20 insertions(+), 3 deletions(-) ++ ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index 84e76b6..929d3e0 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -2103,8 +2103,6 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, ++ nfsfh->fh = data->fh; ++ data->fh.data.data_val = NULL; ++ ++- nfs_set_streaming_mode(nfsfh, 200 * NFS_STREAM_BUF_SIZE); ++- ++ data->cb(0, nfs, nfsfh, data->private_data); ++ free_nfs_cb_data(data); ++ } ++@@ -2374,12 +2372,24 @@ static void nfs_stream_cb(struct rpc_context *rpc, int status, void *command_dat ++ ++ static void prefetch_streaming_blocks(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t next_offset, int num_blocks) ++ { ++- int i; +++ int i, num_pending = 0; ++ ++ for (i = 0; i < nfsfh->sr->num_blocks && num_blocks; i++) { ++ struct stream_cb_data *stream_data; ++ READ3args args; ++ +++ /* +++ * BSS_PENDING means we have a request for prefetch in flight. +++ * We don't want an unlimited amount of requests in flight +++ * since it can cause wild latency spikes while initially +++ * filling the prefetch buffer. +++ */ +++ if (nfsfh->sr->blocks[i].state == BSS_PENDING) { +++ num_pending++; +++ } +++ if (num_pending >= num_blocks) { +++ continue; +++ } ++ if (nfsfh->sr->blocks[i].state != BSS_UNUSED) { ++ continue; ++ } ++diff --git a/nfs-stream.c b/nfs-stream.c ++index dd01218..f5a1b0a 100644 ++--- a/nfs-stream.c +++++ b/nfs-stream.c ++@@ -18,6 +18,11 @@ int main(int argc, char *argv[]) ++ struct timeval t1, t2; ++ uint64_t delta, tpc; ++ +++ if (argc != 3) { +++ fprintf(stderr, "Usage: nfs-stream \n"); +++ exit(1); +++ } +++ ++ nfs = nfs_init_context(); ++ url = nfs_parse_url_full(nfs, argv[1]); ++ if (!url) { ++@@ -36,6 +41,8 @@ int main(int argc, char *argv[]) ++ nfs_get_error(nfs)); ++ exit(1); ++ } +++ nfs_set_streaming_mode(nfsfh, 5 * 1024 * 1024); +++ ++ if (nfs_fstat64(nfs, nfsfh, &st)) { ++ fprintf(stderr, "Failed to stat file %s: %s\n", ++ url->file, ++-- ++1.9.1 ++ ++ ++From 503492873f27cefc3bfb368a96c4c7e1c99b303f Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Tue, 10 Feb 2015 16:40:53 -0800 ++Subject: [PATCH 6/7] streaming mode: wait until we have 10 sequential reads ++ before we prefetch ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ lib/libnfs.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index 929d3e0..53b71fd 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -2433,7 +2433,7 @@ static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh ++ } ++ nfsfh->sr->next_offset = offset + count; ++ ++- if (nfsfh->sr->num_seq < 5) { +++ if (nfsfh->sr->num_seq < 10) { ++ goto end_of_streaming; ++ } ++ ++-- ++1.9.1 ++ ++ ++From 55a673ae81514f109553d36b71647e8c334f8d81 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Wed, 11 Feb 2015 01:25:05 -0800 ++Subject: [PATCH 7/7] nfs-stream.c: move this tool to the examples directory ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ examples/nfs-stream.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ ++ nfs-stream.c | 72 --------------------------------------------------- ++ 2 files changed, 72 insertions(+), 72 deletions(-) ++ create mode 100644 examples/nfs-stream.c ++ delete mode 100644 nfs-stream.c ++ ++diff --git a/examples/nfs-stream.c b/examples/nfs-stream.c ++new file mode 100644 ++index 0000000..f5a1b0a ++--- /dev/null +++++ b/examples/nfs-stream.c ++@@ -0,0 +1,72 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include "nfsc/libnfs.h" +++ +++int main(int argc, char *argv[]) +++{ +++ struct nfs_context *nfs; +++ struct nfs_url *url; +++ struct nfsfh *nfsfh = NULL; +++ struct nfs_stat_64 st; +++ uint64_t offset; +++ char buf[32768]; +++ struct timeval t1, t2; +++ uint64_t delta, tpc; +++ +++ if (argc != 3) { +++ fprintf(stderr, "Usage: nfs-stream \n"); +++ exit(1); +++ } +++ +++ nfs = nfs_init_context(); +++ url = nfs_parse_url_full(nfs, argv[1]); +++ if (!url) { +++ fprintf(stderr, "Can not parse URL. %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_mount(nfs, url->server, url->path) != 0) { +++ fprintf(stderr, "Failed to mount nfs share : %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { +++ fprintf(stderr, "Failed to open file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ nfs_set_streaming_mode(nfsfh, 5 * 1024 * 1024); +++ +++ if (nfs_fstat64(nfs, nfsfh, &st)) { +++ fprintf(stderr, "Failed to stat file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ printf("File size:%lld\n", (long long)st.nfs_size); +++ tpc = 1000000 / (strtol(argv[2], NULL, 10) / 32768); +++ printf("Read one 32kb chunk every %d us\n", (int)tpc); +++ for (offset = 0; offset < st.nfs_size; offset += 32768) { +++ gettimeofday(&t1, NULL); +++ nfs_read(nfs, nfsfh, 32768, buf); +++ gettimeofday(&t2, NULL); +++ delta = t2.tv_sec * 1000000LL + t2.tv_usec - +++ t1.tv_sec * 1000000LL - t1.tv_usec; +++ printf("Read latency:%lld us\n", (long long)delta); +++ if (tpc > delta) { +++ //printf("Sleep for %d us\n", (int)(tpc - delta)); +++ usleep(tpc - delta); +++ } +++ } +++ +++ nfs_close(nfs, nfsfh); +++ nfs_destroy_context(nfs); +++ nfs_destroy_url(url); +++ return 0; +++} ++diff --git a/nfs-stream.c b/nfs-stream.c ++deleted file mode 100644 ++index f5a1b0a..0000000 ++--- a/nfs-stream.c +++++ /dev/null ++@@ -1,72 +0,0 @@ ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include "nfsc/libnfs.h" ++- ++-int main(int argc, char *argv[]) ++-{ ++- struct nfs_context *nfs; ++- struct nfs_url *url; ++- struct nfsfh *nfsfh = NULL; ++- struct nfs_stat_64 st; ++- uint64_t offset; ++- char buf[32768]; ++- struct timeval t1, t2; ++- uint64_t delta, tpc; ++- ++- if (argc != 3) { ++- fprintf(stderr, "Usage: nfs-stream \n"); ++- exit(1); ++- } ++- ++- nfs = nfs_init_context(); ++- url = nfs_parse_url_full(nfs, argv[1]); ++- if (!url) { ++- fprintf(stderr, "Can not parse URL. %s\n", ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- if (nfs_mount(nfs, url->server, url->path) != 0) { ++- fprintf(stderr, "Failed to mount nfs share : %s\n", ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { ++- fprintf(stderr, "Failed to open file %s: %s\n", ++- url->file, ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- nfs_set_streaming_mode(nfsfh, 5 * 1024 * 1024); ++- ++- if (nfs_fstat64(nfs, nfsfh, &st)) { ++- fprintf(stderr, "Failed to stat file %s: %s\n", ++- url->file, ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- printf("File size:%lld\n", (long long)st.nfs_size); ++- tpc = 1000000 / (strtol(argv[2], NULL, 10) / 32768); ++- printf("Read one 32kb chunk every %d us\n", (int)tpc); ++- for (offset = 0; offset < st.nfs_size; offset += 32768) { ++- gettimeofday(&t1, NULL); ++- nfs_read(nfs, nfsfh, 32768, buf); ++- gettimeofday(&t2, NULL); ++- delta = t2.tv_sec * 1000000LL + t2.tv_usec - ++- t1.tv_sec * 1000000LL - t1.tv_usec; ++- printf("Read latency:%lld us\n", (long long)delta); ++- if (tpc > delta) { ++- //printf("Sleep for %d us\n", (int)(tpc - delta)); ++- usleep(tpc - delta); ++- } ++- } ++- ++- nfs_close(nfs, nfsfh); ++- nfs_destroy_context(nfs); ++- nfs_destroy_url(url); ++- return 0; ++-} ++-- ++1.9.1 +diff --git a/tools/depends/target/libnfs/Makefile b/tools/depends/target/libnfs/Makefile +index 642fba8..aa6bde1 100644 +--- a/tools/depends/target/libnfs/Makefile ++++ b/tools/depends/target/libnfs/Makefile +@@ -25,6 +25,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); ./bootstrap + cd $(PLATFORM); patch -p0 < ../utils.patch + cd $(PLATFORM); patch -p1 < ../readahead.patch ++ cd $(PLATFORM); patch -p1 < ../0001-Sequential-Readahead-Mode.patch + cd $(PLATFORM); $(CONFIGURE) + + $(LIBDYLIB): $(PLATFORM) +diff --git a/xbmc/filesystem/DllLibNfs.h b/xbmc/filesystem/DllLibNfs.h +index 4b5ba29..9ba8ebc 100644 +--- a/xbmc/filesystem/DllLibNfs.h ++++ b/xbmc/filesystem/DllLibNfs.h +@@ -85,6 +85,7 @@ class DllLibNfsInterface + virtual int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf)=0; + virtual int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf)=0; + virtual int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset)=0; ++ virtual void nfs_set_streaming_mode(struct nfsfh *nfsfh, uint32_t v)=0; + }; + + class DllLibNfs : public DllDynamic, DllLibNfsInterface +@@ -131,6 +132,7 @@ class DllLibNfs : public DllDynamic, DllLibNfsInterface + DEFINE_METHOD5(int, nfs_pread, (struct nfs_context *p1, struct nfsfh *p2, uint64_t p3, uint64_t p4, char *p5)) + DEFINE_METHOD5(int, nfs_pwrite, (struct nfs_context *p1, struct nfsfh *p2, uint64_t p3, uint64_t p4, char *p5)) + DEFINE_METHOD5(int, nfs_lseek, (struct nfs_context *p1, struct nfsfh *p2, uint64_t p3, int p4, uint64_t *p5)) ++ DEFINE_METHOD2(void,nfs_set_streaming_mode, (struct nfsfh *p1, uint32_t p2)) + + + +@@ -176,6 +178,7 @@ class DllLibNfs : public DllDynamic, DllLibNfsInterface + RESOLVE_METHOD_RENAME(nfs_symlink, nfs_symlink) + RESOLVE_METHOD_RENAME(nfs_rename, nfs_rename) + RESOLVE_METHOD_RENAME(nfs_link, nfs_link) ++ RESOLVE_METHOD_RENAME(nfs_set_streaming_mode, nfs_set_streaming_mode) + END_METHOD_RESOLVE() + }; + +diff --git a/xbmc/filesystem/NFSFile.cpp b/xbmc/filesystem/NFSFile.cpp +index 9354fd5..eaa1dd7 100644 +--- a/xbmc/filesystem/NFSFile.cpp ++++ b/xbmc/filesystem/NFSFile.cpp +@@ -562,6 +562,8 @@ bool CNFSFile::Open(const CURL& url) + CLog::Log(LOGDEBUG,"CNFSFile::Open - opened %s",url.GetFileName().c_str()); + m_url=url; + ++ //gNfsConnection.GetImpl()->nfs_set_streaming_mode(m_pFileHandle, 5 * 1024 * 1024); ++ + struct __stat64 tmpBuffer; + + if( Stat(&tmpBuffer) ) + +From e4cca8769b7ccbf8b3eae3cf497804032c15a17b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 14:06:12 +0000 +Subject: [PATCH 59/95] [mmal] Allow mmal codec for dvd stills + +--- + xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +index 0cd267a..9d8de2a 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +@@ -49,6 +49,9 @@ + #include "Video/DVDVideoCodecAndroidMediaCodec.h" + #include "android/activity/AndroidFeatures.h" + #endif ++#if defined(HAS_MMAL) ++#include "linux/RBP.h" ++#endif + #include "Audio/DVDAudioCodecFFmpeg.h" + #include "Audio/DVDAudioCodecPassthrough.h" + #include "Overlay/DVDOverlayCodecSSA.h" +@@ -199,6 +202,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne + #endif + CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); + ++#if defined(HAS_MMAL) ++ // mmal can handle dvd playback including stills ++ if (!CSettings::Get().GetBool("videoplayer.usemmal") || !g_RBP.GetCodecMpg2()) ++#endif + if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO)) + { + // If dvd is an mpeg2 and hint.stills + +From d2e87054304fdf10cb00d1e5441a2e4376d8c335 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 15:29:51 +0000 +Subject: [PATCH 60/95] [rbp] Add Pi 2 specific settings defaults + +Disable omxplayer by default and don't need to warn against using ac3 transcode +--- + system/settings/rbp2.xml | 107 +++++++++++++++++++++++++++++++++++++++++++++ + xbmc/linux/RBP.h | 2 + + xbmc/settings/Settings.cpp | 7 ++- + 3 files changed, 115 insertions(+), 1 deletion(-) + create mode 100644 system/settings/rbp2.xml + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +new file mode 100644 +index 0000000..e118f3a +--- /dev/null ++++ b/system/settings/rbp2.xml +@@ -0,0 +1,107 @@ ++ ++ ++
++ ++ ++ false ++ ++ ++ ++ false ++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ ++ ++ ++ 2 ++ 10 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ false ++ ++ ++ ++
++ ++
++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ false ++ ++ ++ 2 ++ true ++ ++ ++ ++ 2 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 101 ++ ++ ++ 3 ++ 100 ++ ++ 50 ++ 50 ++ 300 ++ ++ ++ 38102 ++ ++ ++ ++ ++
++
+diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 82146d6..4a04183 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -37,6 +37,7 @@ + #if defined(TARGET_RASPBERRY_PI) + #include "DllBCM.h" + #include "OMXCore.h" ++#include "xbmc/utils/CPUInfo.h" + #include "threads/CriticalSection.h" + #include "threads/Event.h" + +@@ -52,6 +53,7 @@ class CRBP + int GetArmMem() { return m_arm_mem; } + int GetGpuMem() { return m_gpu_mem; } + bool GetCodecMpg2() { return m_codec_mpg2_enabled; } ++ int RasberryPiVersion() { return g_cpuInfo.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); +diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp +index a81fa93..519bd30 100644 +--- a/xbmc/settings/Settings.cpp ++++ b/xbmc/settings/Settings.cpp +@@ -49,6 +49,9 @@ + #if defined(TARGET_DARWIN) + #include "osx/DarwinUtils.h" + #endif ++#if defined(TARGET_RASPBERRY_PI) ++#include "linux/RBP.h" ++#endif + #include "peripherals/Peripherals.h" + #include "powermanagement/PowerManager.h" + #include "profiles/ProfilesManager.h" +@@ -454,8 +457,10 @@ bool CSettings::InitializeDefinitions() + 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")) ++ if (g_RBP.RasberryPiVersion() == 1 && 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.RasberryPiVersion() > 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"); + +From 032835dd2e7944ddf049ea986b3698c78c74b3ad Mon Sep 17 00:00:00 2001 +From: Claudio-Sjo +Date: Mon, 16 Feb 2015 14:51:26 +0100 +Subject: [PATCH 61/95] - allow reads < CDIO_CD_FRAMESIZE_RAW by using a buffer + - fixes #15794 + +--- + xbmc/filesystem/CDDAFile.cpp | 120 ++++++++++++++++++++++++++++++++----------- + xbmc/filesystem/CDDAFile.h | 3 ++ + 2 files changed, 92 insertions(+), 31 deletions(-) + +diff --git a/xbmc/filesystem/CDDAFile.cpp b/xbmc/filesystem/CDDAFile.cpp +index 16796f5..066b49f 100644 +--- a/xbmc/filesystem/CDDAFile.cpp ++++ b/xbmc/filesystem/CDDAFile.cpp +@@ -43,10 +43,14 @@ CFileCDDA::CFileCDDA(void) + m_lsnEnd = CDIO_INVALID_LSN; + m_cdio = CLibcdio::GetInstance(); + m_iSectorCount = 52; ++ m_TrackBuf = (uint8_t *) malloc(CDIO_CD_FRAMESIZE_RAW); ++ p_TrackBuf = 0; ++ f_TrackBuf = 0; + } + + CFileCDDA::~CFileCDDA(void) + { ++ free(m_TrackBuf); + Close(); + } + +@@ -54,6 +58,9 @@ bool CFileCDDA::Open(const CURL& url) + { + std::string strURL = url.GetWithoutFilename(); + ++ // Flag TrackBuffer = FALSE, TrackBuffer is empty ++ f_TrackBuf = 0; ++ + if (!g_mediaManager.IsDiscInDrive(strURL) || !IsValidFile(url)) + return false; + +@@ -118,50 +125,98 @@ int CFileCDDA::Stat(const CURL& url, struct __stat64* buffer) + + ssize_t CFileCDDA::Read(void* lpBuf, size_t uiBufSize) + { +- if (!m_pCdIo || !g_mediaManager.IsDiscInDrive()) +- return -1; + +- if (uiBufSize > SSIZE_MAX) +- uiBufSize = SSIZE_MAX; ++ ssize_t returnValue; ++ int iSectorCount; ++ void *destBuf; + +- // limit number of sectors that fits in buffer by m_iSectorCount +- int iSectorCount = std::min((int)uiBufSize / CDIO_CD_FRAMESIZE_RAW, m_iSectorCount); + +- if (iSectorCount <= 0) ++ if (!m_pCdIo || !g_mediaManager.IsDiscInDrive()) ++ { ++ CLog::Log(LOGERROR, "file cdda: Aborted because no disc in drive or no m_pCdIo"); + return -1; ++ } + +- // Are there enough sectors left to read +- if (m_lsnCurrent + iSectorCount > m_lsnEnd) +- iSectorCount = m_lsnEnd - m_lsnCurrent; ++ uiBufSize = std::min( uiBufSize, (size_t)SSIZE_MAX ); + +- // The loop tries to solve read error problem by lowering number of sectors to read (iSectorCount). +- // When problem is solved the proper number of sectors is stored in m_iSectorCount +- int big_iSectorCount = iSectorCount; +- while (iSectorCount > 0) ++ // If we have data in the TrackBuffer, they must be used first ++ if (f_TrackBuf) + { +- int iret = m_cdio->cdio_read_audio_sectors(m_pCdIo, lpBuf, m_lsnCurrent, iSectorCount); ++ // Get at most the remaining data in m_TrackBuf ++ uiBufSize = std::min(uiBufSize, CDIO_CD_FRAMESIZE_RAW - p_TrackBuf); ++ memcpy(lpBuf, m_TrackBuf + p_TrackBuf, uiBufSize); ++ // Update the data offset ++ p_TrackBuf += uiBufSize; ++ // Is m_TrackBuf empty? ++ f_TrackBuf = (CDIO_CD_FRAMESIZE_RAW == p_TrackBuf); ++ // All done, return read bytes ++ return uiBufSize; ++ } ++ ++ // No data left in buffer ++ ++ // Is this a short read? ++ if (uiBufSize < CDIO_CD_FRAMESIZE_RAW) ++ { ++ // short request, buffer one full sector ++ iSectorCount = 1; ++ destBuf = m_TrackBuf; ++ } ++ else // normal request ++ { ++ // limit number of sectors that fits in buffer by m_iSectorCount ++ iSectorCount = std::min((int)uiBufSize / CDIO_CD_FRAMESIZE_RAW, m_iSectorCount); ++ destBuf = lpBuf; ++ } + ++ // Are there enough sectors left to read? ++ iSectorCount = std::min(iSectorCount, m_lsnEnd - m_lsnCurrent); ++ ++ // Have we reached EOF? ++ if (iSectorCount == 0) ++ { ++ CLog::Log(LOGNOTICE, "file cdda: Read EoF"); ++ return 0; // Success, but nothing read ++ } // Reached EoF ++ ++ // At leat one sector to read ++ int retries; ++ int iret; ++ // Try reading a decresing number of sectors, then 3 times with 1 sector ++ for (retries = 3; retries > 0; iSectorCount>1 ? iSectorCount-- : retries--) ++ { ++ iret = m_cdio->cdio_read_audio_sectors(m_pCdIo, destBuf, m_lsnCurrent, iSectorCount); + if (iret == DRIVER_OP_SUCCESS) ++ break; // Get out from the loop ++ else + { +- // If lower iSectorCount solved the problem limit it's value +- if (iSectorCount < big_iSectorCount) +- { +- m_iSectorCount = iSectorCount; +- } +- break; +- } +- +- // iSectorCount is low so it cannot solve read problem +- if (iSectorCount <= 10) +- { +- CLog::Log(LOGERROR, "file cdda: Reading %d sectors of audio data starting at lsn %d failed with error code %i", iSectorCount, m_lsnCurrent, iret); +- return -1; +- } +- +- iSectorCount = 10; ++ CLog::Log(LOGERROR, "file cdda: Read cdio error when reading track "); ++ } // Errors when reading file + } ++ // retries == 0 only if failed reading at least one sector ++ if (retries == 0) ++ { ++ CLog::Log(LOGERROR, "file cdda: Reading %d sectors of audio data starting at lsn %d failed with error code %i", iSectorCount, m_lsnCurrent, iret); ++ return -1; ++ } ++ ++ // Update position in file + m_lsnCurrent += iSectorCount; + ++ // Was it a short request? ++ if (uiBufSize < CDIO_CD_FRAMESIZE_RAW) ++ { ++ // We copy the amount if requested data into the destination buffer ++ memcpy(lpBuf, m_TrackBuf, uiBufSize); ++ // and keep track of the first available data ++ p_TrackBuf = uiBufSize; ++ // Finally, we set the buffer flag as TRUE ++ f_TrackBuf = true; ++ // We will return uiBufSize ++ return uiBufSize; ++ } ++ ++ // Otherwise, just return the size of read data + return iSectorCount*CDIO_CD_FRAMESIZE_RAW; + } + +@@ -195,6 +250,9 @@ int64_t CFileCDDA::Seek(int64_t iFilePosition, int iWhence /*=SEEK_SET*/) + + void CFileCDDA::Close() + { ++ // Flag TrackBuffer = FALSE, TrackBuffer is empty ++ f_TrackBuf = 0; ++ + if (m_pCdIo) + { + m_cdio->cdio_destroy(m_pCdIo); +diff --git a/xbmc/filesystem/CDDAFile.h b/xbmc/filesystem/CDDAFile.h +index 0427af4..e992362 100644 +--- a/xbmc/filesystem/CDDAFile.h ++++ b/xbmc/filesystem/CDDAFile.h +@@ -50,6 +50,9 @@ class CFileCDDA : public IFile + + protected: + CdIo_t* m_pCdIo; ++ uint8_t *m_TrackBuf; ++ size_t p_TrackBuf; ++ int f_TrackBuf; + lsn_t m_lsnStart; // Start of m_iTrack in logical sector number + lsn_t m_lsnCurrent; // Position inside the track in logical sector number + lsn_t m_lsnEnd; // End of m_iTrack in logical sector number + +From c7b9583bbbb32ff28b10517e2eb654764c592a03 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 20 Feb 2015 14:11:57 +0000 +Subject: [PATCH 62/95] libavformat: add mvcC handling in .mov/.mp4 + +--- + ...ibavformat-add-mvcC-handling-in-.mov-.mp4.patch | 57 ++++++++++++++++++++++ + tools/depends/target/ffmpeg/Makefile | 3 +- + 2 files changed, 59 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + +diff --git a/tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch b/tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch +new file mode 100644 +index 0000000..72fbcb9 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch +@@ -0,0 +1,57 @@ ++From 40bca2ae81bb9cd131b90bf262e976674ca6fab8 Mon Sep 17 00:00:00 2001 ++From: Deborah Crook ++Date: Fri, 16 Jan 2015 14:24:17 +0000 ++Subject: [PATCH] libavformat: add mvcC handling in .mov/.mp4 ++ ++--- ++ libavformat/mov.c | 28 ++++++++++++++++++++++++++++ ++ 1 file changed, 28 insertions(+) ++ ++diff --git a/libavformat/mov.c b/libavformat/mov.c ++index 7455e3b..29bfec9 100644 ++--- a/libavformat/mov.c +++++ b/libavformat/mov.c ++@@ -1201,6 +1201,33 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) ++ return 0; ++ } ++ +++static int mov_read_mvcc(MOVContext *c, AVIOContext *pb, MOVAtom atom) +++{ +++ int extradata_size; +++ int ret, i; +++ uint32_t n; +++ AVStream *st; +++ +++ if (c->fc->nb_streams < 1) +++ return 0; +++ st = c->fc->streams[c->fc->nb_streams-1]; +++ extradata_size = st->codec->extradata_size; +++ +++ if ((uint64_t)atom.size > (1<<30)) +++ return AVERROR_INVALIDDATA; +++ +++ if (extradata_size == 0) +++ return 0; +++ if ((ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_H264)) < 0) +++ return ret; +++ for (i = 0, n = 0; i < 4; i++) +++ n = (n << 8) | st->codec->extradata[extradata_size+i]; +++ n -= 4; +++ for (i = 0; i < 4; i++) +++ st->codec->extradata[extradata_size+i] = (n >> ((3 - i) << 3)) & 0xff; +++ return 0; +++} +++ ++ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) ++ { ++ AVStream *st; ++@@ -3383,6 +3410,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { ++ { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 }, ++ { MKTAG('f','r','e','e'), mov_read_free }, ++ { MKTAG('-','-','-','-'), mov_read_custom }, +++{ MKTAG('m','v','c','C'), mov_read_mvcc }, ++ { 0, NULL } ++ }; ++ ++-- ++1.7.10.4 +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 6e8364a..43dc4ff 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,6 +1,6 @@ + include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -69,6 +69,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure + cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch ++ cd $(PLATFORM); patch -p1 < ../0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) + +From 005ffd4613a34a1a3fca74bdb4fda56abe27cdf3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 00:09:19 +0000 +Subject: [PATCH 63/95] [omxplayer] Limit subtitle updates to 10fps to avoid + stuttering with closed captions + +--- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 4e599e3..b32bd7f 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -222,7 +222,7 @@ double OMXPlayerVideo::NextOverlay(double pts) + else if (delta_stop > 0.0 && (min_delta == DVD_NOPTS_VALUE || delta_stop < min_delta)) + min_delta = delta_stop; + } +- return min_delta == DVD_NOPTS_VALUE ? pts+DVD_MSEC_TO_TIME(500) : pts+min_delta; ++ return min_delta == DVD_NOPTS_VALUE ? pts+DVD_MSEC_TO_TIME(500) : pts+std::max(min_delta, DVD_MSEC_TO_TIME(100)); + } + + +@@ -306,9 +306,9 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket) + double subtitle_pts = m_nextOverlay; + double time = subtitle_pts != DVD_NOPTS_VALUE ? subtitle_pts - media_pts : 0.0; + +- m_nextOverlay = NextOverlay(media_pts); ++ m_nextOverlay = NextOverlay(media_pts + preroll); + +- ProcessOverlays(media_pts); ++ ProcessOverlays(media_pts + preroll); + + time += m_av_clock->GetAbsoluteClock(); + g_renderManager.FlipPage(CThread::m_bStop, time/DVD_TIME_BASE); + +From 8b17d6c5a5d574f554e0b6431df3a8066ef33ce6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 15:57:29 +0000 +Subject: [PATCH 64/95] [mmalrenderer] Fix for stereo view modes + +PR6090 (dirty regions for video) meant that RenderUpate is no longer called with the expected stereo view mode. +So, just explicitly set this before calling ManageDisplay to get the desired rectangles +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index ebc4458..b9d9cd9 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -346,7 +346,11 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + + if (!m_bConfigured) return; + ++ if (g_graphicsContext.GetStereoMode()) ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); + ManageDisplay(); ++ if (g_graphicsContext.GetStereoMode()) ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); + + // if running bypass, then the player might need the src/dst rects + // for sizing video playback on a layer other than the gles layer. + +From 769d01896f4538de56d374838775a93f49f89972 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 14:37:27 +0000 +Subject: [PATCH 65/95] ffmpeg: Add some upstream HEVC optimisations + +--- + tools/depends/target/ffmpeg/Makefile | 5 +- + ...hevcdsp_ARM_NEON_optimized_epel_functions.patch | 406 +++++++++++++++++++++ + 2 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch + +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 43dc4ff..757721c 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,6 +1,7 @@ + include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch \ ++ hevcdsp_ARM_NEON_optimized_epel_functions.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -70,6 +71,8 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure + cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch + cd $(PLATFORM); patch -p1 < ../0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch ++ cd $(PLATFORM); patch -p1 < ../hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) +diff --git a/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch b/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch +new file mode 100644 +index 0000000..de95ba6 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch +@@ -0,0 +1,406 @@ ++From 5114c6fb870fe3aea5da05ea218760a47a29ad74 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Thu, 5 Feb 2015 13:32:28 +0000 ++Subject: [PATCH] hevcdsp: ARM NEON optimized epel functions ++ ++--- ++ libavcodec/arm/Makefile | 1 + ++ libavcodec/arm/hevcdsp_epel_neon.S | 334 +++++++++++++++++++++++++++++++++++++ ++ libavcodec/arm/hevcdsp_init_neon.c | 23 +++ ++ 3 files changed, 358 insertions(+) ++ create mode 100644 libavcodec/arm/hevcdsp_epel_neon.S ++ ++diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile ++index 434a2d1..95eb814 100644 ++--- a/libavcodec/arm/Makefile +++++ b/libavcodec/arm/Makefile ++@@ -134,6 +134,7 @@ NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ ++ arm/synth_filter_neon.o ++ NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ ++ arm/hevcdsp_deblock_neon.o \ +++ arm/hevcdsp_epel_neon.o \ ++ arm/hevcdsp_idct_neon.o \ ++ arm/hevcdsp_qpel_neon.o ++ NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o ++diff --git a/libavcodec/arm/hevcdsp_epel_neon.S b/libavcodec/arm/hevcdsp_epel_neon.S ++new file mode 100644 ++index 0000000..424416d ++--- /dev/null +++++ b/libavcodec/arm/hevcdsp_epel_neon.S ++@@ -0,0 +1,334 @@ +++/* +++ * Copyright (c) 2014 - 2015 Seppo Tomperi +++ * +++ * This file is part of FFmpeg. +++ * +++ * FFmpeg is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU Lesser General Public +++ * License as published by the Free Software Foundation; either +++ * version 2.1 of the License, or (at your option) any later version. +++ * +++ * FFmpeg is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ * Lesser General Public License for more details. +++ * +++ * You should have received a copy of the GNU Lesser General Public +++ * License along with FFmpeg; if not, write to the Free Software +++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ */ +++ +++#include "libavutil/arm/asm.S" +++#include "neon.S" +++ +++#define MAX_PB_SIZE #64 +++ +++.macro vextin_d4 +++ vld1.8 {q10}, [r1], r2 +++ vmov d16, d20 +++ vext.8 d17, d20, d21, #1 +++ vext.8 d18, d20, d21, #2 +++ vext.8 d19, d20, d21, #3 +++.endm +++ +++.macro vextin_d4_8 +++ vld1.8 d16, [r1], r2 +++ vext.8 d17, d16, d16, #1 +++ vext.8 d18, d16, d16, #2 +++ vext.8 d19, d16, d16, #3 +++.endm +++ +++.macro load_coeffs_16b coeffs +++ ldr \coeffs, [\coeffs] +++ vdup.i8 d0, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d1, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d2, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d3, \coeffs +++.endm +++ +++.macro epel_filter_16b out=q12 +++ vmull.u8 q3, d16, d0 +++ vmull.u8 q11, d19, d3 +++ vmull.u8 \out, d17, d1 +++ vmull.u8 q10, d18, d2 +++ vadd.s16 q3, q11 +++ vadd.s16 \out, q10 +++ vsub.s16 \out, q3 +++.endm +++ +++.macro load_coeffs_32b coeffs +++ ldr \coeffs, [\coeffs] +++ vmov.i64 d4, #0 +++ vmov.8 d4[0], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[2], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[4], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[6], \coeffs +++.endm +++ +++.macro epel_filter_32b +++ vmull.s16 q3, d24, d4[0] //q12 +++ vmull.s16 q4, d25, d4[0] +++ vmull.s16 q5, d30, d4[3] //q15 +++ vmull.s16 q6, d31, d4[3] +++ +++ vmull.s16 q7, d26, d4[1] // q13 +++ vmull.s16 q8, d27, d4[1] +++ vmull.s16 q9, d28, d4[2] // q14 +++ vmull.s16 q10, d29, d4[2] +++ vadd.s32 q3, q5 +++ vadd.s32 q4, q6 +++ vadd.s32 q7, q9 +++ vadd.s32 q8, q10 +++ vsub.s32 q7, q3 +++ vsub.s32 q8, q4 +++ vqshrn.s32 d6, q7, #6 +++ vqshrn.s32 d7, q8, #6 +++.endm +++ +++.macro epel_filter_32b_4 +++ vmull.s16 q3, d24, d4[0] //q12 +++ vmull.s16 q5, d30, d4[3] //q15 +++ vmull.s16 q7, d26, d4[1] // q13 +++ vmull.s16 q9, d28, d4[2] // q14 +++ vadd.s32 q3, q5 +++ vadd.s32 q7, q9 +++ vsub.s32 q7, q3 +++ vqshrn.s32 d6, q7, #6 +++.endm +++ +++function ff_hevc_put_epel_h_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r7, [sp, #16] // mx +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ add r7, r12 +++ sub r1, #1 +++ lsl r4, #1 +++ load_coeffs_16b r7 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: subs r3, #1 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b +++ vst1.16 {q12}, [r0], r4 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ cmp r5, #4 +++ bgt 8b +++4: subs r3, #1 +++ pld [r1] +++ vextin_d4_8 +++ epel_filter_16b +++ vst1.16 d24, [r0], r4 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++2: subs r3, #1 +++ pld [r1] +++ vextin_d4_8 +++ epel_filter_16b +++ vst1.32 d24[0], [r0], r4 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++function ff_hevc_put_epel_v_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r7, [sp, #20] // my +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ add r7, r12 +++ load_coeffs_16b r7 +++ sub r1, r2 +++ lsl r4, #1 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++0: pld [r1] +++ vld1.8 {d16}, [r1], r2 +++ pld [r1] +++ vld1.8 {d17}, [r1], r2 +++ pld [r1] +++ vld1.8 {d18}, [r1], r2 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.16 {q12}, [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ b 0b +++4: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.16 d24, [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++ b 0b +++2: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.32 d24[0], [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++function ff_hevc_put_epel_hv_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r6, [sp, #16] // mx +++ ldr r7, [sp, #20] // my +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ sub r6, #1 +++ lsl r6, #2 +++ add r6, r12 // mx epel coeff offset +++ add r7, r12 +++ sub r1, #1 +++ sub r1, r2 +++ lsl r4, #1 +++ load_coeffs_16b r6 +++ load_coeffs_32b r7 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++0: pld [r1] +++ vextin_d4 +++ epel_filter_16b q12 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b q13 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b q14 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: pld [r1] +++ vextin_d4 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b +++ vst1.16 {q3}, [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ b 0b +++4: pld [r1] +++ vextin_d4_8 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b_4 +++ vst1.16 d6, [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++ b 0b +++2: pld [r1] +++ vextin_d4_8 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b_4 +++ vst1.32 d6[0], [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++epel_coeffs: +++ .byte 2, 58, 10, 2 +++ .byte 4, 54, 16, 2 +++ .byte 6, 46, 28, 4 +++ .byte 4, 36, 36, 4 +++ .byte 4, 28, 46, 6 +++ .byte 2, 16, 54, 4 +++ .byte 2, 10, 58, 2 ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 61e6462..917abc4 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -57,6 +57,15 @@ PUT_PIXELS(ff_hevc_put_pixels_w32_neon_8); ++ PUT_PIXELS(ff_hevc_put_pixels_w48_neon_8); ++ PUT_PIXELS(ff_hevc_put_pixels_w64_neon_8); ++ #undef PUT_PIXELS +++void ff_hevc_put_epel_h_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); +++void ff_hevc_put_epel_v_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); +++void ff_hevc_put_epel_hv_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); ++ ++ static void (*put_hevc_qpel_neon[4][4])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, ++ int height, int width); ++@@ -201,7 +210,21 @@ static av_cold void hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ c->put_hevc_qpel_bi[x][1][0] = ff_hevc_put_qpel_bi_neon_wrapper; ++ c->put_hevc_qpel_bi[x][0][1] = ff_hevc_put_qpel_bi_neon_wrapper; ++ c->put_hevc_qpel_bi[x][1][1] = ff_hevc_put_qpel_bi_neon_wrapper; +++ c->put_hevc_epel[x][1][0] = ff_hevc_put_epel_v_neon_8; +++ c->put_hevc_epel[x][0][1] = ff_hevc_put_epel_h_neon_8; +++ c->put_hevc_epel[x][1][1] = ff_hevc_put_epel_hv_neon_8; ++ } +++ c->put_hevc_epel[0][0][0] = ff_hevc_put_pixels_w2_neon_8; +++ c->put_hevc_epel[1][0][0] = ff_hevc_put_pixels_w4_neon_8; +++ c->put_hevc_epel[2][0][0] = ff_hevc_put_pixels_w6_neon_8; +++ c->put_hevc_epel[3][0][0] = ff_hevc_put_pixels_w8_neon_8; +++ c->put_hevc_epel[4][0][0] = ff_hevc_put_pixels_w12_neon_8; +++ c->put_hevc_epel[5][0][0] = ff_hevc_put_pixels_w16_neon_8; +++ c->put_hevc_epel[6][0][0] = ff_hevc_put_pixels_w24_neon_8; +++ c->put_hevc_epel[7][0][0] = ff_hevc_put_pixels_w32_neon_8; +++ c->put_hevc_epel[8][0][0] = ff_hevc_put_pixels_w48_neon_8; +++ c->put_hevc_epel[9][0][0] = ff_hevc_put_pixels_w64_neon_8; +++ ++ c->put_hevc_qpel[0][0][0] = ff_hevc_put_pixels_w2_neon_8; ++ c->put_hevc_qpel[1][0][0] = ff_hevc_put_pixels_w4_neon_8; ++ c->put_hevc_qpel[2][0][0] = ff_hevc_put_pixels_w6_neon_8; + +From d137a1d0d7d29115c6764efec13d8ffff66335c1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 19:07:17 +0000 +Subject: [PATCH 66/95] [omxplayer] Attempt to fix missing subtitles after seek + +--- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index b32bd7f..8becff1 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -296,7 +296,7 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket) + const double preroll = DVD_MSEC_TO_TIME(100); + double media_pts = m_av_clock->OMXMediaTime(); + +- if (m_nextOverlay != DVD_NOPTS_VALUE && media_pts + preroll <= m_nextOverlay) ++ if (m_nextOverlay != DVD_NOPTS_VALUE && media_pts != 0.0 && media_pts + preroll <= m_nextOverlay) + return; + + int buffer = g_renderManager.WaitForBuffer(CThread::m_bStop); + +From b5afc5f7e110f8f0e28fb8b634a8bafd01259573 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Wed, 25 Feb 2015 18:22:21 +0100 +Subject: [PATCH 67/95] Load OSD dialogs on startup. + +Fixes skipped frames the first time they're loaded in memory on less powered +devices, like a Raspberry Pi, when using DVDPlayer. +See http://forum.kodi.tv/showthread.php?tid=211501&pid=1938811#pid1938811 +--- + xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp | 1 + + xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp | 1 + + xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp | 4 +++- + xbmc/video/dialogs/GUIDialogSubtitles.cpp | 2 +- + xbmc/video/dialogs/GUIDialogVideoOSD.cpp | 2 +- + xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 4 +++- + 6 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp +index 499f926..9f85783 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp +@@ -50,6 +50,7 @@ CGUIDialogPVRChannelsOSD::CGUIDialogPVRChannelsOSD() : + CGUIDialog(WINDOW_DIALOG_PVR_OSD_CHANNELS, "DialogPVRChannelsOSD.xml"), + Observer() + { ++ m_loadType = LOAD_ON_GUI_INIT; + m_vecItems = new CFileItemList; + } + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp +index 1670190..329a3b8 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp +@@ -35,6 +35,7 @@ using namespace PVR; + CGUIDialogPVRGuideOSD::CGUIDialogPVRGuideOSD() + : CGUIDialog(WINDOW_DIALOG_PVR_OSD_GUIDE, "DialogPVRGuideOSD.xml") + { ++ m_loadType = LOAD_ON_GUI_INIT; + m_vecItems = new CFileItemList; + } + +diff --git a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +index 55a72e9..f5d6ffc 100644 +--- a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp ++++ b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +@@ -62,7 +62,9 @@ using namespace std; + CGUIDialogAudioSubtitleSettings::CGUIDialogAudioSubtitleSettings() + : CGUIDialogSettingsManualBase(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "VideoOSDSettings.xml"), + m_passthrough(false) +-{ } ++{ ++ m_loadType = LOAD_ON_GUI_INIT; ++} + + CGUIDialogAudioSubtitleSettings::~CGUIDialogAudioSubtitleSettings() + { } +diff --git a/xbmc/video/dialogs/GUIDialogSubtitles.cpp b/xbmc/video/dialogs/GUIDialogSubtitles.cpp +index 5da2daa..a7fc7a0 100644 +--- a/xbmc/video/dialogs/GUIDialogSubtitles.cpp ++++ b/xbmc/video/dialogs/GUIDialogSubtitles.cpp +@@ -100,7 +100,7 @@ class CSubtitlesJob: public CJob + CGUIDialogSubtitles::CGUIDialogSubtitles(void) + : CGUIDialog(WINDOW_DIALOG_SUBTITLES, "DialogSubtitles.xml") + { +- m_loadType = KEEP_IN_MEMORY; ++ m_loadType = LOAD_ON_GUI_INIT; + m_subtitles = new CFileItemList; + m_serviceItems = new CFileItemList; + m_pausedOnRun = false; +diff --git a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp +index 8a856e1..18b25fd 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp +@@ -35,7 +35,7 @@ using namespace PVR; + CGUIDialogVideoOSD::CGUIDialogVideoOSD(void) + : CGUIDialog(WINDOW_DIALOG_VIDEO_OSD, "VideoOSD.xml") + { +- m_loadType = KEEP_IN_MEMORY; ++ m_loadType = LOAD_ON_GUI_INIT; + } + + CGUIDialogVideoOSD::~CGUIDialogVideoOSD(void) +diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +index 4940561..f52698c 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +@@ -64,7 +64,9 @@ using namespace std; + CGUIDialogVideoSettings::CGUIDialogVideoSettings() + : CGUIDialogSettingsManualBase(WINDOW_DIALOG_VIDEO_OSD_SETTINGS, "VideoOSDSettings.xml"), + m_viewModeChanged(false) +-{ } ++{ ++ m_loadType = LOAD_ON_GUI_INIT; ++} + + CGUIDialogVideoSettings::~CGUIDialogVideoSettings() + { } + +From 1ace25f5d8722f5df80c23756e52f8d434db589a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 4 Mar 2015 20:15:18 +0000 +Subject: [PATCH 68/95] test: fix for dirty rendering with skipped updates + +--- + xbmc/Application.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index fb38cd3..edb4271 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -1979,6 +1979,8 @@ void CApplication::Render() + if (RenderNoPresent()) + hasRendered = true; + } ++ // execute post rendering actions (finalize window closing) ++ g_windowManager.AfterRender(); + } + + // render video layer +@@ -1986,9 +1988,6 @@ void CApplication::Render() + + g_Windowing.EndRender(); + +- // execute post rendering actions (finalize window closing) +- g_windowManager.AfterRender(); +- + // reset our info cache - we do this at the end of Render so that it is + // fresh for the next process(), or after a windowclose animation (where process() + // isn't called) + +From 09745d35cbd1b89639ba77bf83560558e3f3f784 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 5 Mar 2015 20:00:59 +0000 +Subject: [PATCH 69/95] [ffmpmeg] Discard data before VO/VOL in mpeg-4 over + mpegts + +--- + ...-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch | 69 ++++++++++++++++++++++ + tools/depends/target/ffmpeg/Makefile | 4 +- + 2 files changed, 72 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + +diff --git a/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch b/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch +new file mode 100644 +index 0000000..eef7385 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch +@@ -0,0 +1,69 @@ ++From ff289b3678b3b102f76c0fc0ffc802e3c8026fdb Mon Sep 17 00:00:00 2001 ++From: Deborah Crook ++Date: Thu, 5 Mar 2015 19:48:43 +0000 ++Subject: [PATCH] Discard data before VO/VOL in mpeg-4 over mpegts ++ ++--- ++ libavcodec/mpeg4video_parser.c | 26 ++++++++++++++++++++++---- ++ 1 file changed, 22 insertions(+), 4 deletions(-) ++ ++diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c ++index aa5e87a..0d8b15a 100644 ++--- a/libavcodec/mpeg4video_parser.c +++++ b/libavcodec/mpeg4video_parser.c ++@@ -43,18 +43,32 @@ int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) ++ state = pc->state; ++ ++ i = 0; ++- if (!vop_found) { +++ if (vop_found < 0) { +++ for (i = 0; i < buf_size; i++) { +++ state = (state << 8) | buf[i]; +++ if (state >= 0x100 && state <= 0x12f) { +++ i++; +++ vop_found = 0; +++ break; +++ } +++ } +++ } +++ +++ if (vop_found == 0) +++ vop_found = 1; +++ +++ if (vop_found == 1) { ++ for (i = 0; i < buf_size; i++) { ++ state = (state << 8) | buf[i]; ++ if (state == 0x1B6) { ++ i++; ++- vop_found = 1; +++ vop_found = 2; ++ break; ++ } ++ } ++ } ++ ++- if (vop_found) { +++ if (vop_found == 2) { ++ /* EOF considered as end of frame */ ++ if (buf_size == 0) ++ return 0; ++@@ -133,12 +147,16 @@ static int mpeg4video_parse(AVCodecParserContext *s, ++ ParseContext *pc = s->priv_data; ++ int next; ++ +++ if (pc->frame_start_found == 0 && !avctx->extradata) +++ pc->frame_start_found = -1; +++ ++ if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { ++ next = buf_size; ++ } else { ++ next = ff_mpeg4_find_frame_end(pc, buf, buf_size); ++ ++- if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { +++ if (pc->frame_start_found < 0 || +++ ff_combine_frame(pc, next, &buf, &buf_size) < 0) { ++ *poutbuf = NULL; ++ *poutbuf_size = 0; ++ return buf_size; ++-- ++2.1.4 +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 757721c..fbef09a 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,7 +1,8 @@ + include ../../Makefile.include + include FFMPEG-VERSION + DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch \ +- hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ hevcdsp_ARM_NEON_optimized_epel_functions.patch \ ++ 0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -72,6 +73,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch + cd $(PLATFORM); patch -p1 < ../0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + cd $(PLATFORM); patch -p1 < ../hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ cd $(PLATFORM); patch -p1 < ../0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + +From c5a96aa31d597241d2cf42acaa81761827ab2136 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 7 Mar 2015 22:46:21 +0000 +Subject: [PATCH 70/95] configure: Add raspberry-pi2 platform + +--- + configure.ac | 14 +++++++-- + m4/xbmc_arch.m4 | 8 ++--- + tools/depends/Makefile.include.in | 2 +- + tools/depends/configure.ac | 38 ++++++++++++++++------- + tools/depends/target/Toolchain.cmake.in | 2 +- + tools/depends/target/Toolchain_binaddons.cmake.in | 2 +- + 6 files changed, 44 insertions(+), 22 deletions(-) + +diff --git a/configure.ac b/configure.ac +index fb7c782..129c57a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -746,8 +746,17 @@ case $use_platform in + raspberry-pi) + target_platform=target_raspberry_pi + use_neon=no +- use_arch="arm" + use_cpu=arm1176jzf-s ++ ;; ++ raspberry-pi2) ++ target_platform=target_raspberry_pi ++ use_neon=yes ++ use_cpu=cortex-a7 ++ ;; ++esac ++ ++if test "$target_platform" = "target_raspberry_pi" ; then ++ use_arch="arm" + use_hardcoded_tables="yes" + ARCH="arm" + AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) +@@ -755,8 +764,7 @@ case $use_platform in + USE_MMAL=1; AC_DEFINE([HAS_MMAL],[1],["Define to 1 if MMAL libs is enabled"]) + CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS" +- ;; +-esac ++fi + + XBMC_SETUP_ARCH_DEFINES() + +diff --git a/m4/xbmc_arch.m4 b/m4/xbmc_arch.m4 +index 0b66a82..adb8e97 100644 +--- a/m4/xbmc_arch.m4 ++++ b/m4/xbmc_arch.m4 +@@ -77,9 +77,7 @@ if test "$target_platform" = "target_android" ; then + AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -DTARGET_ANDROID") + fi + +-case $use_platform in +- raspberry-pi) +- AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_ARMEL -DTARGET_RASPBERRY_PI") +- ;; +-esac ++if test "$target_platform" = "target_raspberry_pi" ; then ++ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_ARMEL -DTARGET_RASPBERRY_PI") ++fi + ]) +diff --git a/tools/depends/Makefile.include.in b/tools/depends/Makefile.include.in +index e1ac05c..d60cccf 100644 +--- a/tools/depends/Makefile.include.in ++++ b/tools/depends/Makefile.include.in +@@ -20,7 +20,7 @@ NATIVE_OS=@build_os@ + CROSS_COMPILING=@cross_compiling@ + ARCH_DEFINES=@ARCH_DEFINES@ + NATIVE_ARCH_DEFINES=@NATIVE_ARCH_DEFINES@ +-TARGET_PLATFORM=@use_platform@ ++TARGET_PLATFORM=@target_platform@ + XCODE_VERSION=@use_xcode@ + AAPT=@AAPT@ + DX=@DX@ +diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac +index f21af0b..74060b1 100644 +--- a/tools/depends/configure.ac ++++ b/tools/depends/configure.ac +@@ -17,7 +17,8 @@ AC_ARG_WITH([toolchain], + AC_ARG_WITH([platform], + [AS_HELP_STRING([--with-platform], + [target platform [auto]])], +- [use_platform=$withval]) ++ [use_platform=$withval], ++ [target_platform=$withval]) + + AC_ARG_WITH([firmware], + [AS_HELP_STRING([--with-firmware], +@@ -305,34 +306,49 @@ case $host in + AC_MSG_ERROR(unsupported host ($use_host)) + esac + +-if test "$use_platform" = "raspberry-pi"; then ++case $use_platform in ++ raspberry-pi) ++ target_platform=raspberry_pi ++ use_neon=no ++ use_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_neon=yes ++ use_cpu=cortex-a7 ++ platform_cflags="-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4" ++ platform_cxxflags="-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4" ++ platform_ldflags="-lpthread" ++ ;; ++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_neon=no + use_arch="arm" +- use_cpu="arm1176jzf-s" + use_hardcoded_tables="yes" +- use_alsa="no" + ARCH="arm" + platform_os="linux" + cross_compiling="yes" + use_host="arm-linux-gnueabihf" + deps_dir="$use_host" +- platform_cflags="-pipe -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard \ +- -mfpu=vfp -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated \ +- -Wno-deprecated-declarations -isystem${use_firmware}/opt/vc/include \ ++ 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 -mcpu=arm1176jzf-s -mtune=arm1176jzf-s \ +- -mfloat-abi=hard -mfpu=vfp -mabi=aapcs-linux -Wno-psabi \ ++ 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 \ ++ platform_ldflags+=" -L${use_firmware}/opt/vc/lib -lEGL -lGLESv2 -lbcm_host -lvcos \ + -lvchiq_arm" + fi + +diff --git a/tools/depends/target/Toolchain.cmake.in b/tools/depends/target/Toolchain.cmake.in +index 943be73..59385e8 100644 +--- a/tools/depends/target/Toolchain.cmake.in ++++ b/tools/depends/target/Toolchain.cmake.in +@@ -1,6 +1,6 @@ + SET(OS "@platform_os@") + SET(CPU "@use_cpu@") +-SET(PLATFORM "@use_platform@") ++SET(PLATFORM "@target_platform@") + IF("${OS}" STREQUAL "linux" OR "${OS}" STREQUAL "android") + SET(CMAKE_SYSTEM_NAME Linux) + ENDIF() +diff --git a/tools/depends/target/Toolchain_binaddons.cmake.in b/tools/depends/target/Toolchain_binaddons.cmake.in +index cdc2fe4..379bd1d 100644 +--- a/tools/depends/target/Toolchain_binaddons.cmake.in ++++ b/tools/depends/target/Toolchain_binaddons.cmake.in +@@ -1,7 +1,7 @@ + set(CMAKE_SYSTEM_VERSION 1) + set(OS "@platform_os@") + set(CPU "@use_cpu@") +-set(PLATFORM "@use_platform@") ++set(PLATFORM "@target_platform@") + if("${OS}" STREQUAL "linux" OR "${OS}" STREQUAL "android") + set(CMAKE_SYSTEM_NAME Linux) + endif() + +From f3f95dcbb1a5533babac13a1e76b75d897d3f626 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 16 Apr 2014 21:18:06 +0100 +Subject: [PATCH 71/95] [omxplayer] Don't propagate 3d flags based on supported + 3d modes + +--- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 29 +++-------------------------- + 1 file changed, 3 insertions(+), 26 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 8becff1..86d97bd 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -763,40 +763,17 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f + uint32_t video_width = CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth; + uint32_t video_height = CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight; + +- unsigned flags = 0; + ERenderFormat format = RENDER_FMT_BYPASS; + ++ /* figure out steremode expected based on user settings and hints */ ++ unsigned flags = GetStereoModeFlags(GetStereoMode()); ++ + if(m_bAllowFullscreen) + { + flags |= CONF_FLAGS_FULLSCREEN; + m_bAllowFullscreen = false; // only allow on first configure + } + +- flags |= GetStereoModeFlags(GetStereoMode()); +- +- if(flags & CONF_FLAGS_STEREO_MODE_SBS) +- { +- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS)) +- CLog::Log(LOGNOTICE, "3DSBS movie found"); +- else +- { +- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); +- CLog::Log(LOGNOTICE, "3DSBS movie found but not supported"); +- } +- } +- else if(flags & CONF_FLAGS_STEREO_MODE_TAB) +- { +- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB)) +- CLog::Log(LOGNOTICE, "3DTB movie found"); +- else +- { +- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); +- CLog::Log(LOGNOTICE, "3DTB movie found but not supported"); +- } +- } +- else +- CLog::Log(LOGNOTICE, "not a 3D movie"); +- + unsigned int iDisplayWidth = width; + unsigned int iDisplayHeight = height; + + +From b1b33de65735c6a374a0bafd86c971a8249c42af Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:01:51 +0100 +Subject: [PATCH 72/95] [graphics] Allow switching to a more suitable 3D + resolution + +--- + xbmc/guilib/GraphicContext.cpp | 40 +++++++++++++++++++++++++++++++++++++++- + xbmc/guilib/GraphicContext.h | 1 + + 2 files changed, 40 insertions(+), 1 deletion(-) + +diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp +index 58406f7..a476cd8 100644 +--- a/xbmc/guilib/GraphicContext.cpp ++++ b/xbmc/guilib/GraphicContext.cpp +@@ -35,6 +35,7 @@ + #include "utils/JobManager.h" + #include "video/VideoReferenceClock.h" + #include "cores/IPlayer.h" ++#include + + using namespace std; + +@@ -500,6 +501,43 @@ RESOLUTION CGraphicContext::GetVideoResolution() const + return m_Resolution; + } + ++RESOLUTION CGraphicContext::Get3DVideoResolution(RESOLUTION resolution, RENDER_STEREO_MODE mode) const ++{ ++ RESOLUTION best = resolution; ++ RESOLUTION_INFO curr = CDisplaySettings::Get().GetResolutionInfo(best); ++ // Find closest refresh rate ++ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) ++ { ++ const RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo((RESOLUTION)i); ++ ++ //discard resolutions that are not the same width and height (and interlaced/3D flags) ++ //or have a too low refreshrate ++ if (info.iScreenWidth != curr.iScreenWidth ++ || info.iScreenHeight != curr.iScreenHeight ++ || info.iScreen != curr.iScreen ++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED) ++ || fabs(info.fRefreshRate - curr.fRefreshRate) >= FLT_EPSILON) ++ continue; ++ ++ if (mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ++ { ++ best = (RESOLUTION)i; ++ break; ++ } ++ else if (mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && info.dwFlags & D3DPRESENTFLAG_MODE3DTB) ++ { ++ best = (RESOLUTION)i; ++ break; ++ } ++ else if ((mode == RENDER_STEREO_MODE_OFF || mode == RENDER_STEREO_MODE_MONO) && !(info.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))) ++ { ++ best = (RESOLUTION)i; ++ break; ++ } ++ } ++ return best; ++} ++ + void CGraphicContext::ResetOverscan(RESOLUTION_INFO &res) + { + res.Overscan.left = 0; +@@ -1037,7 +1075,7 @@ void CGraphicContext::Flip(const CDirtyRegionList& dirty) + if(m_stereoMode != m_nextStereoMode) + { + m_stereoMode = m_nextStereoMode; +- SetVideoResolution(GetVideoResolution(), true); ++ SetVideoResolution(Get3DVideoResolution(m_Resolution, m_stereoMode), true); + g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET); + } + } +diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h +index 5c1501a..aba11cd 100644 +--- a/xbmc/guilib/GraphicContext.h ++++ b/xbmc/guilib/GraphicContext.h +@@ -108,6 +108,7 @@ class CGraphicContext : public CCriticalSection, + bool IsValidResolution(RESOLUTION res); + void SetVideoResolution(RESOLUTION res, bool forceUpdate = false); + RESOLUTION GetVideoResolution() const; ++ RESOLUTION Get3DVideoResolution(RESOLUTION resolution, RENDER_STEREO_MODE mode) const; + void ResetOverscan(RESOLUTION res, OVERSCAN &overscan); + void ResetOverscan(RESOLUTION_INFO &resinfo); + void ResetScreenParameters(RESOLUTION res); + +From f1e42a2b7d6056020781ea1291c996aa34721f57 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:38:55 +0100 +Subject: [PATCH 73/95] [3D] Support switching to 3D resolutions + +Include matching 3D flags (SBS/TAB) in the score of a resolution to switch to, to enable switching to 3d modes. +Also remove the old code that treated 3D modes differently when assigning a score. +--- + xbmc/cores/VideoRenderers/BaseRenderer.cpp | 47 +++++++++++------------------- + 1 file changed, 17 insertions(+), 30 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +index 751a61b..ca4eba6 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +@@ -222,10 +222,14 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) + RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight) + { + RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current); ++ unsigned int stereo_mode = CONF_FLAGS_STEREO_MODE_MASK(m_iFlags); + + float fRefreshRate = fps; + +- float last_diff = fRefreshRate; ++ int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); ++ if (!(stereo_mode == CONF_FLAGS_STEREO_MODE_SBS) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) || ++ !(stereo_mode == CONF_FLAGS_STEREO_MODE_TAB) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DTB)) ++ c_weight += 1000; + + // Find closest refresh rate + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) +@@ -241,40 +245,23 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES + || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) + continue; + +- // For 3D choose the closest refresh rate +- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) +- { +- float diff = (info.fRefreshRate - fRefreshRate); +- if(diff < 0) +- diff *= -1.0f; ++ int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); + +- if(diff < last_diff) +- { +- last_diff = diff; +- current = (RESOLUTION)i; +- curr = info; +- } +- } +- else +- { +- int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); +- int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); ++ if (!(stereo_mode == CONF_FLAGS_STEREO_MODE_SBS) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) || ++ !(stereo_mode == CONF_FLAGS_STEREO_MODE_TAB) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DTB)) ++ i_weight += 1000; + +- // Closer the better, prefer higher refresh rate if the same +- if ((i_weight < c_weight) +- || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) +- { +- current = (RESOLUTION)i; +- curr = info; +- } ++ // Closer the better, prefer higher refresh rate if the same ++ if ((i_weight < c_weight) ++ || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) ++ { ++ current = (RESOLUTION)i; ++ curr = info; ++ c_weight = i_weight; + } + } + +- // For 3D overwrite weight +- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) +- weight = 0; +- else +- weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); ++ weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); + + return current; + } + +From 186abff1aefa3a4f085fd4395be1af2cdb998164 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 23 Apr 2014 00:05:07 +0100 +Subject: [PATCH 74/95] [graphics] Make pixel ratio for 3d modes consistent + +Note: Use the stored stereo flags from lists of resolutions. +Use current stereo mode for current resolution. +--- + xbmc/cores/VideoRenderers/BaseRenderer.cpp | 10 +++---- + xbmc/guilib/GraphicContext.cpp | 37 ++++++++++++------------- + xbmc/guilib/GraphicContext.h | 12 ++++++-- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 8 ------ + 4 files changed, 32 insertions(+), 35 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +index ca4eba6..6db7c86 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +@@ -119,7 +119,7 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa + + for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++) + { +- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j); ++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j, g_graphicsContext.GetStereoMode((RESOLUTION)j)); + + if (info.iScreenWidth == curr.iScreenWidth + && info.iScreenHeight == curr.iScreenHeight +@@ -179,7 +179,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) + //get the resolution with the refreshrate closest to 60 hertz + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) + { +- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i)); + + if (MathUtils::round_int(info.fRefreshRate) == 60 + && info.iScreenWidth == curr.iScreenWidth +@@ -200,7 +200,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) + CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest"); + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) + { +- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i)); + + if (info.fRefreshRate > curr.fRefreshRate + && info.iScreenWidth == curr.iScreenWidth +@@ -234,14 +234,14 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES + // Find closest refresh rate + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) + { +- const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i)); + + //discard resolutions that are not the same width and height (and interlaced/3D flags) + //or have a too low refreshrate + if (info.iScreenWidth != curr.iScreenWidth + || info.iScreenHeight != curr.iScreenHeight + || info.iScreen != curr.iScreen +- || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK) ++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED) + || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) + continue; + +diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp +index a476cd8..9882935 100644 +--- a/xbmc/guilib/GraphicContext.cpp ++++ b/xbmc/guilib/GraphicContext.cpp +@@ -747,32 +747,33 @@ void CGraphicContext::ApplyStateBlock() + g_Windowing.ApplyStateBlock(); + } + +-const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const ++RENDER_STEREO_MODE CGraphicContext::GetStereoMode(RESOLUTION res) const + { + RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res); ++ return (info.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL : ++ (info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL : RENDER_STEREO_MODE_OFF; ++} + +- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res, RENDER_STEREO_MODE stereoMode) const ++{ ++ RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res); ++ ++ if(stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) + { +- if((info.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) +- { +- info.fPixelRatio /= 2; +- info.iBlanking = 0; +- info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; +- } ++ info.fPixelRatio /= 2; ++ info.iBlanking = 0; ++ info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + info.iHeight = (info.iHeight - info.iBlanking) / 2; + info.Overscan.top /= 2; + info.Overscan.bottom = (info.Overscan.bottom - info.iBlanking) / 2; + info.iSubtitles = (info.iSubtitles - info.iBlanking) / 2; + } + +- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ if(stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) + { +- if((info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) +- { +- info.fPixelRatio *= 2; +- info.iBlanking = 0; +- info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; +- } ++ info.fPixelRatio *= 2; ++ info.iBlanking = 0; ++ info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; + info.iWidth = (info.iWidth - info.iBlanking) / 2; + info.Overscan.left /= 2; + info.Overscan.right = (info.Overscan.right - info.iBlanking) / 2; +@@ -790,16 +791,14 @@ void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info) + if(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) + { + curr.Overscan.right = info.Overscan.right * 2 + info.iBlanking; +- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) +- curr.fPixelRatio /= 2.0; ++ curr.fPixelRatio /= 2.0; + } + + if(info.dwFlags & D3DPRESENTFLAG_MODE3DTB) + { + curr.Overscan.bottom = info.Overscan.bottom * 2 + info.iBlanking; + curr.iSubtitles = info.iSubtitles * 2 + info.iBlanking; +- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) +- curr.fPixelRatio *= 2.0; ++ curr.fPixelRatio *= 2.0; + } + } + +diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h +index aba11cd..c84aed0 100644 +--- a/xbmc/guilib/GraphicContext.h ++++ b/xbmc/guilib/GraphicContext.h +@@ -120,11 +120,15 @@ class CGraphicContext : public CCriticalSection, + void GetAllowedResolutions(std::vector &res); + + // output scaling ++ const RESOLUTION_INFO GetResInfo(RESOLUTION res) const ++ { ++ return GetResInfo(res, GetStereoMode()); ++ } + const RESOLUTION_INFO GetResInfo() const + { + return GetResInfo(m_Resolution); + } +- const RESOLUTION_INFO GetResInfo(RESOLUTION res) const; ++ const RESOLUTION_INFO GetResInfo(RESOLUTION res, RENDER_STEREO_MODE stereo_mode) const; + void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info); + + /* \brief Get UI scaling information from a given resolution to the screen resolution. +@@ -161,9 +165,11 @@ class CGraphicContext : public CCriticalSection, + void RestoreOrigin(); + void SetCameraPosition(const CPoint &camera); + void SetStereoView(RENDER_STEREO_VIEW view); +- RENDER_STEREO_VIEW GetStereoView() { return m_stereoView; } ++ RENDER_STEREO_VIEW GetStereoView() const { return m_stereoView; } + void SetStereoMode(RENDER_STEREO_MODE mode) { m_nextStereoMode = mode; } +- RENDER_STEREO_MODE GetStereoMode() { return m_stereoMode; } ++ RENDER_STEREO_MODE GetStereoMode() const { return m_stereoMode; } ++ RENDER_STEREO_MODE GetStereoMode(RESOLUTION res) const; ++ + void RestoreCameraPosition(); + /*! \brief Set a region in which to clip all rendering + Anything that is rendered after setting a clip region will be clipped so that no part renders +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index d388373..ba14e40 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -546,15 +546,9 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + 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); + // Also add 3D flags + if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) +- { + m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; +- m_desktopRes.fPixelRatio *= 2.0; +- } + else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF) +- { + m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB; +- m_desktopRes.fPixelRatio *= 0.5; +- } + HDMI_PROPERTY_PARAM_T property; + property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; + vc_tv_hdmi_get_property(&property); +@@ -694,7 +688,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v + RESOLUTION_INFO res2 = res; + res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; + res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); +- res2.fPixelRatio *= 2.0f; + res2.iSubtitles = (int)(0.965 * res2.iHeight); + + AddUniqueResolution(res2, resolutions); +@@ -710,7 +703,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v + RESOLUTION_INFO res2 = res; + res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); +- res2.fPixelRatio *= 0.5f; + res2.iSubtitles = (int)(0.965 * res2.iHeight); + + AddUniqueResolution(res2, resolutions); + +From f27b17812aedc6cd1bfb9e52fbacb39defbfd8fe Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 13 Mar 2015 20:48:37 +0100 +Subject: [PATCH 75/95] renderer: Allow gui updates to be skipped when playing + video + +--- + xbmc/Application.cpp | 23 ++++++++++++++++------- + xbmc/Application.h | 1 + + 2 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index edb4271..87b5d37 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -328,6 +328,7 @@ CApplication::CApplication(void) + m_currentStackPosition = 0; + m_lastFrameTime = 0; + m_lastRenderTime = 0; ++ m_skipGuiRender = false; + m_bTestMode = false; + + m_muted = false; +@@ -1952,12 +1953,7 @@ void CApplication::Render() + CDirtyRegionList dirtyRegions; + + // render gui layer +- int fps = 0; +- if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) +- fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); +- unsigned int now = XbmcThreads::SystemClockMillis(); +- unsigned int frameTime = now - m_lastRenderTime; +- if (fps <= 0 || frameTime * fps >= 1000) ++ if (!m_skipGuiRender) + { + dirtyRegions = g_windowManager.GetDirty(); + if (g_graphicsContext.GetStereoMode()) +@@ -1994,6 +1990,7 @@ void CApplication::Render() + g_infoManager.ResetCache(); + lock.Leave(); + ++ unsigned int now = XbmcThreads::SystemClockMillis(); + if (hasRendered) + m_lastRenderTime = now; + +@@ -2478,8 +2475,20 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) + } + if (processGUI && m_renderGUI) + { ++ m_skipGuiRender = false; ++ int fps = 0; ++ if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); ++ unsigned int now = XbmcThreads::SystemClockMillis(); ++ unsigned int frameTime = now - m_lastRenderTime; ++ if (fps > 0 && frameTime * fps < 1000) ++ m_skipGuiRender = true; ++ + if (!m_bStop) +- g_windowManager.Process(CTimeUtils::GetFrameTime()); ++ { ++ if (!m_skipGuiRender) ++ g_windowManager.Process(CTimeUtils::GetFrameTime()); ++ } + g_windowManager.FrameMove(); + } + } +diff --git a/xbmc/Application.h b/xbmc/Application.h +index 1b9a4bf..cc064c3 100644 +--- a/xbmc/Application.h ++++ b/xbmc/Application.h +@@ -465,6 +465,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs + bool m_bPresentFrame; + unsigned int m_lastFrameTime; + unsigned int m_lastRenderTime; ++ bool m_skipGuiRender; + + bool m_bStandalone; + bool m_bEnableLegacyRes; + +From 31705fdeef0bc8947cbd8951b57a9f7b4e64cb46 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Mar 2015 17:05:18 +0000 +Subject: [PATCH 76/95] [players] Add settings option to enable MVC support + +--- + addons/resource.language.en_gb/resources/strings.po | 10 ++++++++++ + system/settings/rbp.xml | 10 ++++++++++ + system/settings/rbp2.xml | 10 ++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 5 +++++ + xbmc/cores/omxplayer/OMXVideo.cpp | 5 +++++ + 5 files changed, 40 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index a4c078c..58b6424 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16662,6 +16662,16 @@ msgctxt "#38102" + msgid "%i ms" + msgstr "" + ++#: system/settings/rbp.xml ++msgctxt "#38110" ++msgid "Support MVC video (full frame 3D)" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38111" ++msgid "This option decodes frames for both eyes of MVC video. Disabling may improve performance if you don't require 3D" ++msgstr "" ++ + #: system/settings/settings.xml + msgctxt "#38015" + msgid "Extract thumbnails from video files" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index a3b6f6f..384bfdb 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -31,6 +31,16 @@ + +
+
++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index e118f3a..0320f32 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -34,6 +34,16 @@ + +
+ ++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 1bfec44..21282dc 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -534,6 +534,11 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + // H.264 + m_codingType = MMAL_ENCODING_H264; + m_pFormatName = "mmal-h264"; ++ if (CSettings::Get().GetBool("videoplayer.supportmvc")) ++ { ++ m_codingType = MMAL_ENCODING_MVC; ++ m_pFormatName= "mmal-mvc"; ++ } + break; + case AV_CODEC_ID_H263: + case AV_CODEC_ID_MPEG4: +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 55e16c4..5a74c79 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -434,6 +434,11 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + break; + } + } ++ if (CSettings::Get().GetBool("videoplayer.supportmvc")) ++ { ++ m_codingType = OMX_VIDEO_CodingMVC; ++ m_video_codec_name = "omx-mvc"; ++ } + break; + case AV_CODEC_ID_MPEG4: + // (role name) video_decoder.mpeg4 + +From 7bd4b8bdd382d21aa557f1188351e151c02cf652 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Mar 2015 12:38:08 +0000 +Subject: [PATCH 77/95] [mmalrenderer] Switch to using transform flags for 3d + modes + +--- + .../resource.language.en_gb/resources/strings.po | 10 +++ + system/settings/rbp.xml | 8 ++ + system/settings/rbp2.xml | 8 ++ + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 92 ++++++---------------- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 46 ++--------- + xbmc/cores/omxplayer/OMXVideo.cpp | 36 ++++----- + xbmc/cores/omxplayer/OMXVideo.h | 2 +- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 11 ++- + 8 files changed, 83 insertions(+), 130 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 58b6424..97a9c5c 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16672,6 +16672,16 @@ msgctxt "#38111" + msgid "This option decodes frames for both eyes of MVC video. Disabling may improve performance if you don't require 3D" + msgstr "" + ++#: system/settings/rbp.xml ++msgctxt "#38112" ++msgid "Use Full HD HDMI modes for 3D" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38113" ++msgid "This option uses frame-packing to output full resolution for 3D through HDMI" ++msgstr "" ++ + #: system/settings/settings.xml + msgctxt "#38015" + msgid "Extract thumbnails from video files" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 384bfdb..945e981 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -40,6 +40,14 @@ + true + +
++ ++ ++ true ++ ++ 2 ++ true ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index 0320f32..11bd850 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -43,6 +43,14 @@ + true + +
++ ++ ++ true ++ ++ 2 ++ true ++ ++ + + + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index b9d9cd9..f4c59ea 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -346,11 +346,7 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + + if (!m_bConfigured) return; + +- if (g_graphicsContext.GetStereoMode()) +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); + ManageDisplay(); +- if (g_graphicsContext.GetStereoMode()) +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); + + // if running bypass, then the player might need the src/dst rects + // for sizing video playback on a layer other than the gles layer. +@@ -541,9 +537,7 @@ EINTERLACEMETHOD CMMALRenderer::AutoInterlaceMethod() + + void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect) + { +- // we get called twice a frame for left/right. Can ignore the rights. +- if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT) +- return; ++ assert(g_graphicsContext.GetStereoView() != RENDER_STEREO_VIEW_RIGHT); + + if (!m_vout_input) + return; +@@ -585,41 +579,10 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect + CRect gui(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight); + CRect display(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight); + +- if (display_stereo_mode != RENDER_STEREO_MODE_OFF && display_stereo_mode != RENDER_STEREO_MODE_MONO) +- switch (video_stereo_mode) +- { +- case RENDER_STEREO_MODE_SPLIT_VERTICAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert) +- { +- SrcRect.x2 *= 2.0f; +- DestRect.x2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE) +- { +- SrcRect.x2 *= 2.0f; +- } +- break; +- +- case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert) +- { +- SrcRect.y2 *= 2.0f; +- DestRect.y2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE) +- { +- SrcRect.y2 *= 2.0f; +- } +- break; +- +- default: break; +- } ++ if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ DestRect.x2 *= 2.0f; ++ else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++ DestRect.y2 *= 2.0f; + + if (gui != display) + { +@@ -634,7 +597,7 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect + 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; ++ 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()); +@@ -647,35 +610,32 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect + + 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_renderOrientation) +- { +- region.set |= MMAL_DISPLAY_SET_TRANSFORM; +- 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 assert(0); +- } +- +- if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_TOP_TO_TOP; +- else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_TOP_TO_LEFT; +- else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_LEFT_TO_TOP; +- else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_LEFT_TO_LEFT; ++ 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.mode = MMAL_DISPLAY_MODE_LETTERBOX; ++ 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 mode:%d", CLASSNAME, __func__, ++ 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.mode); ++ region.dest_rect.x, region.dest_rect.y, region.dest_rect.width, region.dest_rect.height, region.transform); + } +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 86d97bd..018e65f 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -660,9 +660,7 @@ int OMXPlayerVideo::GetFreeSpace() + + void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRect) + { +- // we get called twice a frame for left/right. Can ignore the rights. +- if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT) +- return; ++ assert(g_graphicsContext.GetStereoView() != RENDER_STEREO_VIEW_RIGHT); + + CRect SrcRect = InSrcRect, DestRect = InDestRect; + unsigned flags = GetStereoModeFlags(GetStereoMode()); +@@ -702,42 +700,10 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec + CRect gui(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight); + CRect display(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight); + +- switch (video_stereo_mode) +- { +- case RENDER_STEREO_MODE_SPLIT_VERTICAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert) +- { +- SrcRect.x2 *= 2.0f; +- DestRect.x2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (stereo_invert) +- { +- SrcRect.x1 += m_hints.width / 2; +- SrcRect.x2 += m_hints.width / 2; +- } +- break; +- +- case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert) +- { +- SrcRect.y2 *= 2.0f; +- DestRect.y2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (stereo_invert) +- { +- SrcRect.y1 += m_hints.height / 2; +- SrcRect.y2 += m_hints.height / 2; +- } +- break; +- +- default: break; +- } ++ if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ DestRect.x2 *= 2.0f; ++ else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++ DestRect.y2 *= 2.0f; + + if (gui != display) + { +@@ -748,7 +714,7 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec + DestRect.y1 *= yscale; + DestRect.y2 *= yscale; + } +- m_omxVideo.SetVideoRect(SrcRect, DestRect, video_stereo_mode, display_stereo_mode); ++ m_omxVideo.SetVideoRect(SrcRect, DestRect, m_video_stereo_mode, m_display_stereo_mode, m_StereoInvert); + } + + void OMXPlayerVideo::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 5a74c79..aa97396 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -224,15 +224,6 @@ bool COMXVideo::PortSettingsChanged() + OMX_INIT_STRUCTURE(configDisplay); + configDisplay.nPortIndex = m_omx_render.GetInputPort(); + +- configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; +- configDisplay.transform = m_transform; +- omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); +- if(omx_err != OMX_ErrorNone) +- { +- CLog::Log(LOGWARNING, "%s::%s - could not set transform : %d", CLASSNAME, __func__, m_transform); +- return false; +- } +- + if(m_hdmi_clock_sync) + { + OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; +@@ -877,7 +868,7 @@ void COMXVideo::Reset(void) + } + + /////////////////////////////////////////////////////////////////////////////////////////// +-void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode) ++void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode, bool stereo_invert) + { + CSingleLock lock (m_critSection); + if(!m_is_open) +@@ -887,7 +878,7 @@ void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER + + OMX_INIT_STRUCTURE(configDisplay); + configDisplay.nPortIndex = m_omx_render.GetInputPort(); +- configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT|OMX_DISPLAY_SET_MODE); ++ configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT|OMX_DISPLAY_SET_MODE|OMX_DISPLAY_SET_TRANSFORM); + configDisplay.dest_rect.x_offset = lrintf(DestRect.x1); + configDisplay.dest_rect.y_offset = lrintf(DestRect.y1); + configDisplay.dest_rect.width = lrintf(DestRect.Width()); +@@ -900,23 +891,24 @@ void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER + + configDisplay.fullscreen = OMX_FALSE; + configDisplay.noaspect = OMX_TRUE; ++ configDisplay.mode = OMX_DISPLAY_MODE_LETTERBOX; ++ configDisplay.transform = m_transform; + +- if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_TOP_TO_TOP; +- else if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_TOP_TO_LEFT; +- else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_LEFT_TO_TOP; +- else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_LEFT_TO_LEFT; ++ if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_TB); ++ else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_SBS); + else +- configDisplay.mode = OMX_DISPLAY_MODE_LETTERBOX; ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_MONO); ++ ++ if (stereo_invert) ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_INVERT); + + m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); + +- CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d mode:%d", CLASSNAME, __func__, ++ CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d t:%x", CLASSNAME, __func__, + configDisplay.src_rect.x_offset, configDisplay.src_rect.y_offset, configDisplay.src_rect.width, configDisplay.src_rect.height, +- configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset, configDisplay.dest_rect.width, configDisplay.dest_rect.height, configDisplay.mode); ++ configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset, configDisplay.dest_rect.width, configDisplay.dest_rect.height, configDisplay.transform); + } + + int COMXVideo::GetInputBufferSize() +diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h +index 9f26427..3ea02dc 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.h ++++ b/xbmc/cores/omxplayer/OMXVideo.h +@@ -59,7 +59,7 @@ class COMXVideo + void Reset(void); + void SetDropState(bool bDrop); + std::string GetDecoderName() { return m_video_codec_name; }; +- void SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode); ++ void SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode, bool stereo_invert); + int GetInputBufferSize(); + bool GetPlayerInfo(double &match, double &phase, double &pll); + void SubmitEOS(); +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index ba14e40..10a0409 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -284,7 +284,9 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + /* 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; +- if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ++ if (CSettings::Get().GetBool("videoplayer.framepacking")) ++ property.param1 = HDMI_3D_FORMAT_FRAME_PACKING; ++ else if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) + property.param1 = HDMI_3D_FORMAT_SBS_HALF; + else if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) + property.param1 = HDMI_3D_FORMAT_TB_HALF; +@@ -384,6 +386,13 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE; + DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0); + ++ if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ++ transform = DISPMANX_STEREOSCOPIC_SBS; ++ else if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) ++ 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\n", + 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); + + +From 247752fc9fd63a9544d93081720bd15ca172e660 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Mon, 16 Mar 2015 19:12:17 +0100 +Subject: [PATCH 78/95] Avoid breaking skins comparing System.StereoscopicMode + after 6345. + +See http://forum.kodi.tv/showthread.php?tid=211501&pid=1956983#pid1956983 +--- + xbmc/rendering/RenderSystem.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h +index 9f1daf4..60c5e4b 100644 +--- a/xbmc/rendering/RenderSystem.h ++++ b/xbmc/rendering/RenderSystem.h +@@ -74,10 +74,10 @@ enum RENDER_STEREO_MODE + RENDER_STEREO_MODE_SPLIT_VERTICAL, + RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN, + RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA, +- RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE, + RENDER_STEREO_MODE_INTERLACED, + RENDER_STEREO_MODE_HARDWAREBASED, + RENDER_STEREO_MODE_MONO, ++ RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE, + RENDER_STEREO_MODE_COUNT, + + // psuevdo modes + +From 88a85cfa522676d95bdcd30fed1e10f0aef5337e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 17 Mar 2015 20:33:54 +0000 +Subject: [PATCH 79/95] alsa: enable-shared is required + +--- + tools/depends/target/alsa-lib/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/depends/target/alsa-lib/Makefile b/tools/depends/target/alsa-lib/Makefile +index b03fc19..a04d933 100644 +--- a/tools/depends/target/alsa-lib/Makefile ++++ b/tools/depends/target/alsa-lib/Makefile +@@ -19,7 +19,7 @@ CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + --with-ctl-plugins=ext \ + --with-pcm-plugins="copy,linear,route,mulaw,alaw,adpcm,rate,plug,multi,file,null,empty,share,meter,hooks,lfloat,ladspa,asym,iec958,softvol,extplug,ioplug,mmap_emul" \ + --disable-resmgr --enable-aload --enable-mixer --enable-pcm --disable-rawmidi --enable-hwdep --disable-seq --disable-alisp --disable-old-symbols --disable-python \ +- --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no --disable-shared \ ++ --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no --enable-shared \ + + LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + + +From 2e6ff5a10adfabb2fbc51e343ea8444452321270 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 21 Mar 2015 21:46:16 +0000 +Subject: [PATCH 80/95] squash: Move m_output_busy into lock + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 21282dc..3d90b92 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -273,7 +273,6 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + else + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); +- m_output_busy++; + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - %p (%p) buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x frame:%d", + CLASSNAME, __func__, buffer, omvb, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); +@@ -285,6 +284,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + omvb->height = m_decoded_height; + omvb->m_aspect_ratio = m_aspect_ratio; + pthread_mutex_lock(&m_output_mutex); ++ m_output_busy++; + m_output_ready.push(omvb); + pthread_mutex_unlock(&m_output_mutex); + kept = true; + +From 1086403e7c84699464d2646d7323989e4ee4481a Mon Sep 17 00:00:00 2001 +From: "Chris \\\"Koying\\\" Browet" +Date: Sun, 28 Dec 2014 19:31:09 +0100 +Subject: [PATCH 81/95] ADD: Handle bitmap subtitles in 3D + +--- + .../DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp | 78 +++++++++++++--------- + 1 file changed, 48 insertions(+), 30 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +index 75fd6bb..c01b09b 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +@@ -26,6 +26,8 @@ + #include "DVDClock.h" + #include "utils/log.h" + #include "utils/EndianSwap.h" ++#include "guilib/GraphicContext.h" ++#include "xbmc/rendering/RenderSystem.h" + + CDVDOverlayCodecFFmpeg::CDVDOverlayCodecFFmpeg() : CDVDOverlayCodec("FFmpeg Subtitle Decoder") + { +@@ -237,10 +239,28 @@ CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() + if(m_Subtitle.rects[m_SubtitleIndex] == NULL) + return NULL; + +- AVSubtitleRect& rect = *m_Subtitle.rects[m_SubtitleIndex]; ++ AVSubtitleRect rect = *m_Subtitle.rects[m_SubtitleIndex]; + if (rect.pict.data[0] == NULL) + return NULL; + ++ m_height = m_pCodecContext->height; ++ m_width = m_pCodecContext->width; ++ ++ RENDER_STEREO_MODE render_stereo_mode = g_graphicsContext.GetStereoMode(); ++ if (render_stereo_mode != RENDER_STEREO_MODE_OFF) ++ { ++ if (rect.h > m_height / 2) ++ { ++ m_height /= 2; ++ rect.h -= m_pCodecContext->height / 2; ++ } ++ else if (rect.w > m_width / 2) ++ { ++ m_width /= 2; ++ rect.w -= m_pCodecContext->width / 2; ++ } ++ } ++ + CDVDOverlayImage* overlay = new CDVDOverlayImage(); + + overlay->iPTSStartTime = m_StartTime; +@@ -259,36 +279,34 @@ CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() + int right = overlay->x + overlay->width; + int bottom = overlay->y + overlay->height; + +- if(m_height == 0 && m_pCodecContext->height) +- m_height = m_pCodecContext->height; +- if(m_width == 0 && m_pCodecContext->width) +- m_width = m_pCodecContext->width; +- +- if(bottom > m_height) +- { +- if (bottom <= 480) +- m_height = 480; +- else if(bottom <= 576) +- m_height = 576; +- else if(bottom <= 720) +- m_height = 720; +- else if(bottom <= 1080) +- m_height = 1080; +- else +- m_height = bottom; +- } +- if(right > m_width) ++ if (render_stereo_mode == RENDER_STEREO_MODE_OFF) + { +- if (right <= 720) +- m_width = 720; +- else if(right <= 1024) +- m_width = 1024; +- else if(right <= 1280) +- m_width = 1280; +- else if(right <= 1920) +- m_width = 1920; +- else +- m_width = right; ++ if(bottom > m_height) ++ { ++ if (bottom <= 480) ++ m_height = 480; ++ else if(bottom <= 576) ++ m_height = 576; ++ else if(bottom <= 720) ++ m_height = 720; ++ else if(bottom <= 1080) ++ m_height = 1080; ++ else ++ m_height = bottom; ++ } ++ if(right > m_width) ++ { ++ if (right <= 720) ++ m_width = 720; ++ else if(right <= 1024) ++ m_width = 1024; ++ else if(right <= 1280) ++ m_width = 1280; ++ else if(right <= 1920) ++ m_width = 1920; ++ else ++ m_width = right; ++ } + } + + overlay->source_width = m_width; + +From e8c4361333aee9a8979e809d76303e70baac9863 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 22 Mar 2015 19:32:36 +0000 +Subject: [PATCH 82/95] [omxplayer] Handle failures from EmptyThisBuffer and + FillThisBuffer + +Avoid leak of buffer as seen in PR6260 +--- + .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 +++- + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 3 ++ + xbmc/cores/omxplayer/OMXAudio.cpp | 42 +++++++--------------- + xbmc/cores/omxplayer/OMXImage.cpp | 28 ++++++++++++--- + xbmc/cores/omxplayer/OMXVideo.cpp | 38 ++++++-------------- + 5 files changed, 55 insertions(+), 62 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +index fa8112d..759ba7b 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +@@ -506,6 +506,7 @@ int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t + 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; + } + +@@ -518,8 +519,11 @@ int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t + } + 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) + { +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 363b7d5..7f4d103 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -468,7 +468,10 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned + } + 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(); +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 602d2fa..2e39224 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -858,12 +858,8 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + } + + omx_buffer->nOffset = 0; +- omx_buffer->nFilledLen = sizeof(m_wave_header); +- if(omx_buffer->nFilledLen > omx_buffer->nAllocLen) +- { +- CLog::Log(LOGERROR, "COMXAudio::Initialize - omx_buffer->nFilledLen > omx_buffer->nAllocLen"); +- return false; +- } ++ omx_buffer->nFilledLen = std::min(sizeof(m_wave_header), omx_buffer->nAllocLen); ++ + memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen); + memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; +@@ -872,6 +868,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -889,12 +886,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + } + + omx_buffer->nOffset = 0; +- omx_buffer->nFilledLen = m_extrasize; +- if(omx_buffer->nFilledLen > omx_buffer->nAllocLen) +- { +- CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__); +- return false; +- } ++ omx_buffer->nFilledLen = std::min((OMX_U32)m_extrasize, omx_buffer->nAllocLen); + + memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen); + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); +@@ -904,6 +896,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -1223,26 +1216,14 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt + if(demuxer_samples_sent == demuxer_samples) + omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + +- int nRetry = 0; +- while(true) ++ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); ++ if (omx_err != OMX_ErrorNone) + { +- omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); +- if (omx_err == OMX_ErrorNone) +- { +- //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len); +- break; +- } +- else +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); +- nRetry++; +- } +- if(nRetry == 5) +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__); +- return 0; +- } ++ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); ++ return 0; + } ++ //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len); + + omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); + if (omx_err == OMX_ErrorNone) +@@ -1477,6 +1458,7 @@ void COMXAudio::SubmitEOS() + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return; + } + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index 54a52a7..e79f41d 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1058,6 +1058,7 @@ bool COMXImageDec::HandlePortSettingChange(unsigned int resize_width, unsigned i + if(omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s m_omx_resize FillThisBuffer result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_resize.DecoderFillBufferDone(m_omx_resize.GetComponent(), m_decoded_buffer); + return false; + } + } +@@ -1174,6 +1175,7 @@ bool COMXImageDec::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -1240,8 +1242,17 @@ COMXImageEnc::~COMXImageEnc() + + OMX_INIT_STRUCTURE(m_encoded_format); + m_encoded_buffer = NULL; +- if(m_omx_encoder.IsInitialized()) +- m_omx_encoder.Deinitialize(); ++ 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(); + } + +@@ -1383,6 +1394,7 @@ bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsig + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_encoder.DecoderEmptyBufferDone(m_omx_encoder.GetComponent(), omx_buffer); + break; + } + } +@@ -1397,12 +1409,15 @@ bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsig + + 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)\n", CLASSNAME, __func__, omx_err); ++ m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); + return false; +- ++ } + omx_err = m_omx_encoder.WaitForOutputDone(1000); + if(omx_err != OMX_ErrorNone) + { +- CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForOutputDone result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ CLog::Log(LOGERROR, "%s::%s m_omx_encoder.WaitForOutputDone result(0x%x)\n", CLASSNAME, __func__, omx_err); + return false; + } + +@@ -1445,6 +1460,7 @@ bool COMXImageEnc::CreateThumbnailFromSurface(unsigned char* buffer, unsigned in + return true; + } + ++ m_success = true; + return false; + } + +@@ -1842,6 +1858,7 @@ bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, uns + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s %s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -1880,6 +1897,7 @@ bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, uns + if(omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s %s FillThisBuffer() failed (%x)\n", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); ++ m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); + return false; + } + } +@@ -2199,6 +2217,7 @@ bool COMXTexture::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes, + 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; + } + } +@@ -2248,6 +2267,7 @@ bool COMXTexture::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes, + 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; + } + +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index aa97396..3f37d44 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -109,12 +109,7 @@ bool COMXVideo::SendDecoderConfig() + } + + omx_buffer->nOffset = 0; +- omx_buffer->nFilledLen = m_extrasize; +- if(omx_buffer->nFilledLen > omx_buffer->nAllocLen) +- { +- CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__); +- return false; +- } ++ omx_buffer->nFilledLen = std::min((OMX_U32)m_extrasize, omx_buffer->nAllocLen); + + memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen); + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); +@@ -124,6 +119,7 @@ bool COMXVideo::SendDecoderConfig() + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -654,8 +650,7 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + return false; + } + +- if(!SendDecoderConfig()) +- return false; ++ SendDecoderConfig(); + + m_is_open = true; + m_drop_state = false; +@@ -799,7 +794,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; + + omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); +- omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; ++ omx_buffer->nFilledLen = std::min((OMX_U32)demuxer_bytes, omx_buffer->nAllocLen); + memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); + + demuxer_bytes -= omx_buffer->nFilledLen; +@@ -808,26 +803,14 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + if(demuxer_bytes == 0) + omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + +- int nRetry = 0; +- while(true) ++ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); ++ if (omx_err != OMX_ErrorNone) + { +- omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); +- if (omx_err == OMX_ErrorNone) +- { +- //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize); +- break; +- } +- else +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); +- nRetry++; +- } +- if(nRetry == 5) +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finally failed\n", CLASSNAME, __func__); +- return false; +- } ++ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); ++ return false; + } ++ //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize); + + omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); + if (omx_err == OMX_ErrorNone) +@@ -946,6 +929,7 @@ void COMXVideo::SubmitEOS() + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return; + } + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); + + +From 055fe2e21ad53d210eb86054a6b1452c07e93fd8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 23 Mar 2015 23:50:50 +0000 +Subject: [PATCH 85/95] [OMXAudio] Make stereoupmix and fixed behave more like + dvdplayer + +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 2e39224..dd5cdb8 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -600,13 +600,12 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") + stdLayout = AE_CH_LAYOUT_2_0; + +- // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix +- if (m_InputChannels <= 2) +- stdLayout = AE_CH_LAYOUT_2_0; +- +- + CAEChannelInfo resolvedMap = channelMap; + resolvedMap.ResolveChannels(stdLayout); ++ ++ if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED || (upmix && channelMap.Count() <= 2)) ++ resolvedMap = stdLayout; ++ + uint64_t m_dst_chan_layout = GetAVChannelLayout(resolvedMap); + uint64_t m_src_chan_layout = GetAVChannelLayout(channelMap); + + +From 2980f063267a39aff75454ec0794b951f06e51b9 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Mar 2015 17:24:27 +0000 +Subject: [PATCH 86/95] [mmal] Explicitly use fast deinterlace for HD and + reduce buffers allocated by 2 + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 3d90b92..03d397f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -361,10 +361,13 @@ bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) + CLog::Log(LOGERROR, "%s::%s Failed to create deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } ++ bool advanced_deinterlace = (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF) && ++ m_decoded_width * m_decoded_height <= 576 * 720; ++ bool half_framerate = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF; ++ + MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, +- interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF ? +- MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, +- 3, {3, 0, interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF }}; ++ advanced_deinterlace ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 3, {3, 0, half_framerate }}; ++ + status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr); + if (status != MMAL_SUCCESS) + { +@@ -375,6 +378,14 @@ bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) + MMAL_PORT_T *m_deint_input = m_deint->input[0]; + m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; + ++ if (!advanced_deinterlace) ++ { ++ // 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, -2); ++ 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)); ++ } ++ + // Now connect the decoder output port to deinterlace input port + status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); + if (status != MMAL_SUCCESS) + +From cbe862cd4ba91370d31a9b015c413eeb2a504864 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:36:48 +0100 +Subject: [PATCH 87/95] [mmalrenderer] Avoid submitting a buffer to renderer + twice + +Bad things happen when submitting a buffer to renderer twice. We were attempting to protect against that with +a flip count. However that was getting reset from AddProcessor, the the sequence: +Decode->AddProcessor->RenderUpdate->AddProcessor->RenderUpdate +could occur. Instead use a bit from the MMAL flags which is unlikely to get out of sync with the MMAL buffer. +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 15 ++++++++++++--- + xbmc/cores/VideoRenderers/MMALRenderer.h | 1 - + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 3 ++- + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index f4c59ea..357d023 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -54,6 +54,7 @@ void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T * + + if (m_format == RENDER_FMT_MMAL) + { ++ buffer->flags &= ~MMAL_BUFFER_HEADER_FLAG_USER2; + mmal_queue_put(m_release_queue, buffer); + } + else if (m_format == RENDER_FMT_YUV420P) +@@ -359,9 +360,6 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + SetVideoRect(m_sourceRect, m_destRect); + + YUVBUFFER *buffer = &m_buffers[source]; +- // we only want to upload frames once +- if (buffer->flipindex++) +- return; + if (m_format == RENDER_FMT_MMAL) + { + CMMALVideoBuffer *omvb = buffer->MMALBuffer; +@@ -370,7 +368,11 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p (%p)", CLASSNAME, __func__, omvb, omvb->mmal_buffer); + #endif ++ // we only want to upload frames once ++ if (omvb->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER1) ++ return; + omvb->Acquire(); ++ omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1 | MMAL_BUFFER_HEADER_FLAG_USER2; + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); + } //else assert(0); + } +@@ -378,7 +380,14 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + { + CLog::Log(LOGDEBUG, "%s::%s - %p %d", CLASSNAME, __func__, buffer->mmal_buffer, source); + if (buffer->mmal_buffer) ++ { ++ // we only want to upload frames once ++ if (buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER1) ++ return; ++ // sanity check it is not on display ++ buffer->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1; + mmal_port_send_buffer(m_vout_input, buffer->mmal_buffer); ++ } + else assert(0); + } + else assert(0); +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h +index 3422e2d..6e8f240 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.h ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.h +@@ -49,7 +49,6 @@ class CMMALRenderer : public CBaseRenderer, public CThread + { + CMMALVideoBuffer *MMALBuffer; // used for hw decoded buffers + MMAL_BUFFER_HEADER_T *mmal_buffer; // used for sw decoded buffers +- unsigned flipindex; /* used to decide if this has been uploaded */ + }; + public: + CMMALRenderer(); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 03d397f..7410c36 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -1007,7 +1007,8 @@ void CMMALVideo::ReturnBuffer(CMMALVideoBuffer *buffer) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_output_busy); +- ++ // sanity check it is not on display ++ assert(!(buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER2)); + mmal_buffer_header_release(buffer->mmal_buffer); + } + + +From 3246e4b15054daaa27afdab80fe55035c174158a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:37:25 +0100 +Subject: [PATCH 88/95] [omximage] Increase timeout on encode + +--- + xbmc/cores/omxplayer/OMXImage.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index e79f41d..d99d719 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1414,7 +1414,7 @@ bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsig + m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); + return false; + } +- omx_err = m_omx_encoder.WaitForOutputDone(1000); ++ omx_err = m_omx_encoder.WaitForOutputDone(2000); + if(omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s m_omx_encoder.WaitForOutputDone result(0x%x)\n", CLASSNAME, __func__, omx_err); + +From f760ec8883cf487ef38ae6729f72b4f880327057 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 01:25:04 +0100 +Subject: [PATCH 89/95] [mmalrenderer] Reset m_buffers on PreInit + +When switching rapidly between different files you sometimes ended up with a stale buffer +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 357d023..82a066b 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -374,7 +374,9 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + omvb->Acquire(); + omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1 | MMAL_BUFFER_HEADER_FLAG_USER2; + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); +- } //else assert(0); ++ } ++ else ++ CLog::Log(LOGDEBUG, "%s::%s - No buffer to update", CLASSNAME, __func__); + } + else if (m_format == RENDER_FMT_YUV420P) + { +@@ -388,7 +390,8 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + buffer->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1; + mmal_port_send_buffer(m_vout_input, buffer->mmal_buffer); + } +- else assert(0); ++ else ++ CLog::Log(LOGDEBUG, "%s::%s - No buffer to update", CLASSNAME, __func__); + } + else assert(0); + } +@@ -423,6 +426,7 @@ unsigned int CMMALRenderer::PreInit() + m_formats.push_back(RENDER_FMT_MMAL); + m_formats.push_back(RENDER_FMT_BYPASS); + ++ memset(m_buffers, 0, sizeof m_buffers); + m_iYV12RenderBuffer = 0; + m_NumYV12Buffers = NUM_BUFFERS; + + +From e9da9c7eec1b031b9735ec665aa6a6d300566074 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:34:00 +0100 +Subject: [PATCH 90/95] [mmalrenderer] Add locking around m_droppedPics + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 7410c36..5018f3e 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -267,6 +267,9 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + + if (m_drop_state) + { ++ pthread_mutex_lock(&m_output_mutex); ++ m_droppedPics++; ++ pthread_mutex_unlock(&m_output_mutex); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); + } +@@ -756,6 +759,7 @@ void CMMALVideo::SetDropState(bool bDrop) + { + buffer = m_output_ready.front(); + m_output_ready.pop(); ++ m_droppedPics++; + } + pthread_mutex_unlock(&m_output_mutex); + if (buffer) +@@ -869,6 +873,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + + if (demuxer_bytes == 0) + { ++ pthread_mutex_lock(&m_output_mutex); + m_decode_frame_number++; + m_startframe = true; + if (m_drop_state) +@@ -878,11 +883,10 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + else + { + // only push if we are successful with feeding mmal +- pthread_mutex_lock(&m_output_mutex); + m_dts_queue.push(dts); + assert(m_dts_queue.size() < 5000); +- pthread_mutex_unlock(&m_output_mutex); + } ++ pthread_mutex_unlock(&m_output_mutex); + if (m_changed_count_dec != m_changed_count) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -981,6 +985,7 @@ void CMMALVideo::Reset(void) + while (!m_demux_queue.empty()) + m_demux_queue.pop(); + m_demux_queue_length = 0; ++ m_droppedPics = 0; + pthread_mutex_unlock(&m_output_mutex); + if (!old_drop_state) + SetDropState(false); +@@ -990,7 +995,6 @@ void CMMALVideo::Reset(void) + + m_startframe = false; + m_decoderPts = DVD_NOPTS_VALUE; +- m_droppedPics = 0; + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + } +@@ -1124,9 +1128,11 @@ bool CMMALVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) + + bool CMMALVideo::GetCodecStats(double &pts, int &droppedPics) + { ++ pthread_mutex_lock(&m_output_mutex); + pts = m_decoderPts; + droppedPics = m_droppedPics; + m_droppedPics = 0; ++ pthread_mutex_unlock(&m_output_mutex); + //if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + // CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); + return true; + +From be542f7a57abb5cc6a0faf94cc9a740721c36af5 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:31:47 +0100 +Subject: [PATCH 91/95] [mmalrenderer] Add SetCodecControl function and prefer + to return pictures when renderer is low (disabled) + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp | 5 +++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h | 1 + + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 12 ++++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 ++ + 4 files changed, 20 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +index 262283d..ee7d6f2 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +@@ -96,6 +96,11 @@ bool CDVDVideoCodecMMAL::GetCodecStats(double &pts, int &droppedPics) + return m_decoder->GetCodecStats(pts, droppedPics); + } + ++void CDVDVideoCodecMMAL::SetCodecControl(int flags) ++{ ++ m_decoder->SetCodecControl(flags); ++} ++ + void CDVDVideoCodecMMAL::SetSpeed(int iSpeed) + { + m_decoder->SetSpeed(iSpeed); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +index a768e70..aa8e87f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +@@ -42,6 +42,7 @@ class CDVDVideoCodecMMAL : public CDVDVideoCodec + virtual void SetDropState(bool bDrop); + virtual const char* GetName(void); + virtual bool GetCodecStats(double &pts, int &droppedPics); ++ virtual void SetCodecControl(int flags); + virtual void SetSpeed(int iSpeed); + + protected: +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 5018f3e..3868342 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -130,6 +130,7 @@ CMMALVideo::CMMALVideo() + m_es_format = mmal_format_alloc(); + m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; ++ m_codecControlFlags = 0; + } + + CMMALVideo::~CMMALVideo() +@@ -945,6 +946,9 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - got output picture:%d", CLASSNAME, __func__, m_output_ready.size()); + ret |= VC_PICTURE; ++ // renderer is low - give priority to returning pictures ++ if (0 && m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) ++ ret &= ~VC_BUFFER; + } + if (!ret) + { +@@ -997,6 +1001,7 @@ void CMMALVideo::Reset(void) + m_decoderPts = DVD_NOPTS_VALUE; + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); ++ m_codecControlFlags = 0; + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -1137,3 +1142,10 @@ bool CMMALVideo::GetCodecStats(double &pts, int &droppedPics) + // CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); + return true; + } ++ ++void CMMALVideo::SetCodecControl(int flags) ++{ ++ m_codecControlFlags = flags; ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "%s::%s flags:%x", CLASSNAME, __func__, flags); ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index ca513f6..ec44b13 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -90,6 +90,7 @@ class CMMALVideo + virtual void SetDropState(bool bDrop); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } + virtual bool GetCodecStats(double &pts, int &droppedPics); ++ virtual void SetCodecControl(int flags); + virtual void SetSpeed(int iSpeed); + + // MMAL decoder callback routines. +@@ -143,6 +144,7 @@ class CMMALVideo + unsigned int m_droppedPics; + int m_speed; + bool m_preroll; ++ int m_codecControlFlags; + + MMAL_COMPONENT_T *m_dec; + MMAL_PORT_T *m_dec_input; + +From 9e4a74b068b7b92187627fd116dc0a1454152dc7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 16:31:37 +0100 +Subject: [PATCH 92/95] [mmalcodec] Limit submitted video frames. Seems to + avoid stutter issues with low bitrate videos + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 3868342..2e23430 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -929,7 +929,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + break; + } + int ret = 0; +- if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length) ++ int fps = m_hints.fpsrate && m_hints.fpsscale ? (float)m_hints.fpsrate / (float)m_hints.fpsscale : 25; ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length && m_dts_queue.size() <= fps/2) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); + +From 1c57cab24d5ee75a1f47ed05110b647335dd8872 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 18:35:01 +0100 +Subject: [PATCH 93/95] [rbp] Disable analogue output of sync when passthrough + is enabled + +The analogue and output of Pi Sink doesn't support passthrough. +This also applies to the 'Both' (HDMI and Analogue) setting. +If passthrough is enabled in GUI you get black screen and errors: +https://discourse.osmc.tv/t/some-streams-are-staying-black/2311 + +We need to either disable passthrough or disable analogue. + +I think the best solution to this is to force HDMI output when passthrough is active. + +This allows a user to use receiver for videos with dts/ac3 and TV for music or lower quality formats. +--- + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 22 ++++++++++++++-------- + xbmc/cores/AudioEngine/Sinks/AESinkPi.h | 1 + + xbmc/cores/omxplayer/OMXAudio.cpp | 21 +++++++++++++++------ + xbmc/cores/omxplayer/OMXAudio.h | 1 + + 4 files changed, 31 insertions(+), 14 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 7f4d103..b69925a 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -45,7 +45,8 @@ CAESinkPi::CAESinkPi() : + m_latency(0), + m_Initialized(false), + m_submitted(0), +- m_omx_output(NULL) ++ m_omx_output(NULL), ++ m_output(AESINKPI_UNKNOWN) + { + } + +@@ -60,7 +61,7 @@ void CAESinkPi::SetAudioDest() + OMX_INIT_STRUCTURE(audioDest); + if ( m_omx_render.IsInitialized() ) + { +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (m_output == AESINKPI_ANALOGUE) + strncpy((char *)audioDest.sName, "local", strlen("local")); + else + strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); +@@ -70,7 +71,7 @@ void CAESinkPi::SetAudioDest() + } + if ( m_omx_render_slave.IsInitialized() ) + { +- if (CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue") ++ if (m_output != AESINKPI_ANALOGUE) + strncpy((char *)audioDest.sName, "local", strlen("local")); + else + strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); +@@ -193,12 +194,17 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_latency = CSettings::Get().GetInt("audiooutput.latency") * 1e-3; + m_latency = std::max(m_latency, 50e-3); + ++ if (m_passthrough || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:HDMI") ++ m_output = AESINKPI_HDMI; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ m_output = AESINKPI_ANALOGUE; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ m_output = AESINKPI_BOTH; ++ else assert(0); ++ + // analogue only supports stereo +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") +- { ++ if (m_output == AESINKPI_ANALOGUE || m_output == AESINKPI_BOTH) + format.m_channelLayout = AE_CH_LAYOUT_2_0; +- m_passthrough = false; +- } + + // setup for a 50ms sink feed from SoftAE + if (format.m_dataFormat != AE_FMT_FLOATP && format.m_dataFormat != AE_FMT_FLOAT && +@@ -226,7 +232,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + 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 (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ 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); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +index cac5051..10b0ec6 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +@@ -65,6 +65,7 @@ class CAESinkPi : public IAESink + bool m_passthrough; + COMXCoreTunel m_omx_tunnel_splitter; + COMXCoreTunel m_omx_tunnel_splitter_slave; ++ enum { AESINKPI_UNKNOWN, AESINKPI_HDMI, AESINKPI_ANALOGUE, AESINKPI_BOTH } m_output; + }; + + #endif +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index dd5cdb8..9d960aa 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -88,7 +88,8 @@ COMXAudio::COMXAudio() : + m_extrasize (0 ), + m_last_pts (DVD_NOPTS_VALUE), + m_submitted_eos (false ), +- m_failed_eos (false ) ++ m_failed_eos (false ), ++ m_output (AESINKPI_UNKNOWN) + { + CAEFactory::Suspend(); + while (!CAEFactory::IsSuspended()) +@@ -119,17 +120,17 @@ bool COMXAudio::PortSettingsChanged() + if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit)) + return false; + } +- if(CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ if(m_output == AESINKPI_BOTH) + { + if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit)) + return false; + } +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (m_output == AESINKPI_BOTH || m_output == AESINKPI_ANALOGUE) + { + if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; + } +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue") ++ if (m_output == AESINKPI_BOTH || m_output != AESINKPI_ANALOGUE) + { + if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; +@@ -248,7 +249,7 @@ bool COMXAudio::PortSettingsChanged() + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync + if((CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) || +- CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ m_output == AESINKPI_BOTH) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -570,6 +571,14 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + } + SetCodingType(format.m_dataFormat); + ++ if (m_Passthrough || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:HDMI") ++ m_output = AESINKPI_HDMI; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ m_output = AESINKPI_ANALOGUE; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ m_output = AESINKPI_BOTH; ++ else assert(0); ++ + if(hints.extrasize > 0 && hints.extradata != NULL) + { + m_extrasize = hints.extrasize; +@@ -597,7 +606,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + CAEChannelInfo stdLayout = (enum AEStdChLayout)CSettings::Get().GetInt("audiooutput.channels"); + + // ignore layout setting for analogue +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (m_output == AESINKPI_ANALOGUE || m_output == AESINKPI_BOTH) + stdLayout = AE_CH_LAYOUT_2_0; + + CAEChannelInfo resolvedMap = channelMap; +diff --git a/xbmc/cores/omxplayer/OMXAudio.h b/xbmc/cores/omxplayer/OMXAudio.h +index 569cb09..c31d25e 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.h ++++ b/xbmc/cores/omxplayer/OMXAudio.h +@@ -124,6 +124,7 @@ class COMXAudio + double m_last_pts; + bool m_submitted_eos; + bool m_failed_eos; ++ enum { AESINKPI_UNKNOWN, AESINKPI_HDMI, AESINKPI_ANALOGUE, AESINKPI_BOTH } m_output; + + typedef struct { + double pts; + +From dcecbf718d05a56d6dad63f451693780eb706fcb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 15:40:22 +0100 +Subject: [PATCH 94/95] [mmalrenderer] Discard corrupt frames later so we can + track the number of discarded frames + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 2e23430..fc4b29f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -274,6 +274,11 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); + } ++ else if (g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED)) ++ { ++ CLog::Log(LOGDEBUG, "%s::%s - %p buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x Corrupted", ++ CLASSNAME, __func__, buffer, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags); ++ } + else + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); +@@ -643,7 +648,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + + error_concealment.hdr.id = MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT; + error_concealment.hdr.size = sizeof(MMAL_PARAMETER_BOOLEAN_T); +- error_concealment.enable = g_advancedSettings.m_omxDecodeStartWithValidFrame; ++ error_concealment.enable = false;; + status = mmal_port_parameter_set(m_dec_input, &error_concealment.hdr); + 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)); + +From 9de11dd235a93e84e64fe033e32c4961b14552ed Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 00:25:26 +0100 +Subject: [PATCH 95/95] [mmalcodec] Allocate more buffers when deinterlacing + +Needed with trickplay with deinterlace. TODO: can this be reduced +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index fc4b29f..342c9cb 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -387,13 +387,10 @@ bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) + MMAL_PORT_T *m_deint_input = m_deint->input[0]; + m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; + +- if (!advanced_deinterlace) +- { +- // 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, -2); +- 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)); +- } ++ // 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, GetAllowedReferences() - 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)); + + // Now connect the decoder output port to deinterlace input port + status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); diff --git a/projects/RPi2/patches/kodi/kodi-001-isengard-rpb-backports.patch b/projects/RPi2/patches/kodi/kodi-001-isengard-rpb-backports.patch new file mode 100644 index 0000000000..6e52cd22ce --- /dev/null +++ b/projects/RPi2/patches/kodi/kodi-001-isengard-rpb-backports.patch @@ -0,0 +1,9022 @@ +From a19240c5a911aa272086bc25f7f90b2e010a00c2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 18:19:32 +0100 +Subject: [PATCH 01/95] [rbp/omxplayer] When opening a stream don't try to + update gui so often + +--- + xbmc/dialogs/GUIDialogBusy.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/dialogs/GUIDialogBusy.cpp b/xbmc/dialogs/GUIDialogBusy.cpp +index 2faceea..889d7a2 100644 +--- a/xbmc/dialogs/GUIDialogBusy.cpp ++++ b/xbmc/dialogs/GUIDialogBusy.cpp +@@ -68,7 +68,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10 + if (dialog) + { + dialog->Show(); ++#ifdef TARGET_RASPBERRY_PI ++ while(!event.WaitMSec(100)) ++#else + while(!event.WaitMSec(1)) ++#endif + { + g_windowManager.ProcessRenderLoop(false); + if (allowCancel && dialog->IsCanceled()) + +From 8c71ba5efd5f5cb14dc8e435cace5e755653486c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 29 Apr 2014 15:23:22 +0100 +Subject: [PATCH 02/95] [ffmpeg] Speed up wtv index creation + +The index creation is O(N^2) with number of entries (typically thousands). +On a Pi this can take more than 60 seconds to execute for a recording of a few hours. + +By replacing with an O(N) loop, this takes virtually zero time +--- + tools/depends/target/ffmpeg/Makefile | 3 +- + .../ffmpeg_Speed_up_wtv_index_creation.patch | 47 ++++++++++++++++++++++ + 2 files changed, 49 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch + +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 711182f..6e8364a 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,6 +1,6 @@ + include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -68,6 +68,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure ++ cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) +diff --git a/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch +new file mode 100644 +index 0000000..4ac5636 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch +@@ -0,0 +1,47 @@ ++commit 0e7427498cb1131671f6fe9d054245ae7e5a36f5 ++Author: popcornmix ++Date: Tue Mar 25 19:43:07 2014 +0000 ++ ++ [ffmpeg] Speed up wtv index creation ++ ++ The index creation is O(N^2) with number of entries (typically thousands). ++ On a Pi this can take more than 60 seconds to execute for a recording of a few hours. ++ ++ By replacing with an O(N) loop, this takes virtually zero time ++ ++diff --git a/lib/ffmpeg/libavformat/wtvdec.c b/lib/ffmpeg/libavformat/wtvdec.c ++index e423370..70898bd 100644 ++--- a/lib/ffmpeg/libavformat/wtvdec.c +++++ b/lib/ffmpeg/libavformat/wtvdec.c ++@@ -980,21 +980,23 @@ static int read_header(AVFormatContext *s) ++ pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16); ++ if (pb) { ++ int i; +++ AVIndexEntry *e = wtv->index_entries; +++ AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1; +++ uint64_t last_position = 0; ++ while (1) { ++ uint64_t frame_nb = avio_rl64(pb); ++ uint64_t position = avio_rl64(pb); +++ while (frame_nb > e->size && e <= e_end) { +++ e->pos = last_position; +++ e++; +++ } ++ if (avio_feof(pb)) ++ break; ++- for (i = wtv->nb_index_entries - 1; i >= 0; i--) { ++- AVIndexEntry *e = wtv->index_entries + i; ++- if (frame_nb > e->size) ++- break; ++- if (position > e->pos) ++- e->pos = position; ++- } +++ last_position = position; ++ } +++ e_end->pos = last_position; ++ wtvfile_close(pb); ++- st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp; +++ st->duration = e_end->timestamp; ++ } ++ } ++ } + +From 82a705d6e192fed880a09a76ef015a3a8bf62161 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 2 Aug 2014 17:48:04 +0100 +Subject: [PATCH 03/95] [omx] Report decoded image name + +--- + xbmc/cores/omxplayer/OMXImage.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index 161ec5a..86a683a 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -327,6 +327,7 @@ bool COMXImage::DecodeJpegToTexture(COMXImageFile *file, unsigned int width, uns + { + ret = true; + *userdata = tex; ++ CLog::Log(LOGDEBUG, "%s: decoded %s %dx%d", __func__, file->GetFilename(), width, height); + } + else + { + +From 38048e049fbf6173dd764b6fa578d3fad37099e2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 8 Mar 2014 15:36:06 +0000 +Subject: [PATCH 04/95] [hifiberry] Hack: force it to be recognised as IEC958 + capable to enable passthrough options + +--- + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +index e22db7a..0120bd5 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +@@ -1342,6 +1342,10 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev + if (snd_card_get_name(cardNr, &cardName) == 0) + info.m_displayName = cardName; + ++ // hack: hifiberry digi doesn't correctly report as iec958 device. Needs fixing in kernel driver ++ if (info.m_displayName == "snd_rpi_hifiberry_digi") ++ info.m_deviceType = AE_DEVTYPE_IEC958; ++ + if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 && + info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") + { + +From 20e2e2cd5bd822edb7b39dc9fd95d4d7abebcafc Mon Sep 17 00:00:00 2001 +From: Ben Avison +Date: Thu, 1 May 2014 16:28:39 +0100 +Subject: [PATCH 05/95] Improved file buffering in CArchive + +Even though memcpy is typically inlined by the compiler into byte/word loads +and stores (at least for release builds), the frequency with which 1, 2 and 4 +byte loads/stores are encountered in cases where the size is *not* +determinable at compile time is still high enough that it's worth handling +these specially. On the ARM1176JZF-S in the Raspberry Pi, this improves the +total time to open a library (in the case where it's fetched from a CArchive) +by around 4%. + +It should be noted that this code uses 16-bit and 32-bit word loads and +stores that are not necessarily aligned to their respective widths. It is +possible that there are some architectures out there which do not support +this, although all ARMs since ARMv6 have supported it (and ARMs earlier than +that are probably not powerful enough to be good targets for XBMC). +--- + xbmc/utils/Archive.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h +index 6ed0f8f..8506d95 100644 +--- a/xbmc/utils/Archive.h ++++ b/xbmc/utils/Archive.h +@@ -154,9 +154,17 @@ class CArchive + * than waiting until we attempt to put more data into an already full buffer */ + if (m_BufferRemain > size) + { ++ switch (size) ++ { ++ case 1: *m_BufferPos++ = *ptr; m_BufferRemain--; break; ++ case 2: *(uint16_t *) m_BufferPos = *(const uint16_t *) ptr; m_BufferPos += 2; m_BufferRemain -= 2; break; ++ case 4: *(uint32_t *) m_BufferPos = *(const uint32_t *) ptr; m_BufferPos += 4; m_BufferRemain -= 4; break; ++ default: + memcpy(m_BufferPos, ptr, size); + m_BufferPos += size; + m_BufferRemain -= size; ++ break; ++ } + return *this; + } + else +@@ -171,9 +179,17 @@ class CArchive + /* Note, refilling the buffer is deferred until we know we need to read more from it */ + if (m_BufferRemain >= size) + { ++ switch (size) ++ { ++ case 1: *ptr = *m_BufferPos++; m_BufferRemain--; break; ++ case 2: *(uint16_t *) ptr = *(const uint16_t *) m_BufferPos; m_BufferPos += 2; m_BufferRemain -= 2; break; ++ case 4: *(uint32_t *) ptr = *(const uint32_t *) m_BufferPos; m_BufferPos += 4; m_BufferRemain -= 4; break; ++ default: + memcpy(ptr, m_BufferPos, size); + m_BufferPos += size; + m_BufferRemain -= size; ++ break; ++ } + return *this; + } + else + +From 05fb7f2a00d3922bec218d905b91f4edfe314ece Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 12 Aug 2014 00:31:36 +0100 +Subject: [PATCH 06/95] [omxcodec] Don't force software codec with dvds + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index e976634..f0059fd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3323,7 +3323,9 @@ bool CDVDPlayer::OpenVideoStream(CDVDStreamInfo& hint, bool reset) + hint.aspect = aspect; + hint.forced_aspect = true; + } ++#ifndef TARGET_RASPBERRY_PI + hint.software = true; ++#endif + } + else if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + +From 2a70374217ab2f6f7cd7f0b4c4ae4aee0a7ef83e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 10 Aug 2014 16:45:16 +0100 +Subject: [PATCH 07/95] filesystem: Make support of browsing into archives + optional + +The ability to browse, scan and play content in archives can cause problems on low powered/low memory devices. +It's quite common to see reports of a large rar file that causes xbmc to crash with an out-of-memory error when browsing or scanning. +It also can be slow as any archive in the directory is opened and extracted. + +This causes issues for people who scan library with archives disabled, then subsequently enable it. +The library has the .rar files in which don't play without removing and re-adding. + +We'll let people who don't use archives disable it manually +--- + addons/resource.language.en_gb/resources/strings.po | 9 +++++++++ + system/settings/settings.xml | 5 +++++ + xbmc/filesystem/FileDirectoryFactory.cpp | 4 ++++ + 3 files changed, 18 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index e53d588..a05173d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16519,6 +16519,15 @@ msgstr "" + #: system/settings/rbp.xml + msgctxt "#38010" + msgid "GPU accelerated" ++ ++#: system/settings/settings.xml ++msgctxt "#38020" ++msgid "Support browsing into archives" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38021" ++msgid "Allow viewing and playing files in archives (e.g. zip, rar)" + msgstr "" + + #. Setting #38011 "Videos -> Library -> Show All Items entry" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 921247f..e64b267 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -301,6 +301,11 @@ + false + +
++ ++ 1 ++ true ++ ++ + + + +diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp +index 3a5ba4e..f1f6f79 100644 +--- a/xbmc/filesystem/FileDirectoryFactory.cpp ++++ b/xbmc/filesystem/FileDirectoryFactory.cpp +@@ -41,6 +41,7 @@ + #include "Directory.h" + #include "File.h" + #include "ZipManager.h" ++#include "settings/Settings.h" + #include "settings/AdvancedSettings.h" + #include "FileItem.h" + #include "utils/StringUtils.h" +@@ -115,6 +116,8 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, + return NULL; + } + #endif ++ if (CSettings::Get().GetBool("filelists.browsearchives")) ++ { + if (url.IsFileType("zip")) + { + CURL zipURL = URIUtils::CreateArchivePath("zip", url); +@@ -188,6 +191,7 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, + } + return NULL; + } ++ } + if (url.IsFileType("xsp")) + { // XBMC Smart playlist - just XML renamed to XSP + // read the name of the playlist in + +From 518265fccf644ee67f68395d5ab852cccf9ba304 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 13:06:57 +0000 +Subject: [PATCH 09/95] [rbp] Make cachemembuffersize default depend on memory + size + +--- + xbmc/linux/RBP.cpp | 5 +++++ + xbmc/settings/AdvancedSettings.cpp | 5 +++++ + 2 files changed, 10 insertions(+) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index ba1a3d0..5119949 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -22,6 +22,7 @@ + #if defined(TARGET_RASPBERRY_PI) + + #include "settings/Settings.h" ++#include "settings/AdvancedSettings.h" + #include "utils/log.h" + + #include "cores/omxplayer/OMXImage.h" +@@ -84,6 +85,9 @@ bool CRBP::Initialize() + if (!m_gui_resolution_limit) + m_gui_resolution_limit = m_gpu_mem < 128 ? 720:1080; + ++ if (g_advancedSettings.m_cacheMemBufferSize == ~0U) ++ g_advancedSettings.m_cacheMemBufferSize = m_arm_mem < 256 ? 1024 * 1024 * 2 : 1024 * 1024 * 20; ++ + g_OMXImage.Initialize(); + m_omx_image_init = true; + return true; +@@ -96,6 +100,7 @@ void CRBP::LogFirmwareVerison() + response[sizeof(response) - 1] = '\0'; + CLog::Log(LOGNOTICE, "Raspberry PI firmware version: %s", response); + CLog::Log(LOGNOTICE, "ARM mem: %dMB GPU mem: %dMB MPG2:%d WVC1:%d", m_arm_mem, m_gpu_mem, m_codec_mpg2_enabled, m_codec_wvc1_enabled); ++ CLog::Log(LOGNOTICE, "cacheMemBufferSize: %dMB", g_advancedSettings.m_cacheMemBufferSize >> 20); + m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config int"); + response[sizeof(response) - 1] = '\0'; + CLog::Log(LOGNOTICE, "Config:\n%s", response); +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index ba15502..7797edf 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -352,7 +352,12 @@ void CAdvancedSettings::Initialize() + m_bPVRAutoScanIconsUserSet = false; + m_iPVRNumericChannelSwitchTimeout = 1000; + ++#ifdef TARGET_RASPBERRY_PI ++ // want default to be memory dependent, but interface to gpu not available yet, so set in RBP.cpp ++ m_cacheMemBufferSize = ~0; ++#else + m_cacheMemBufferSize = 1024 * 1024 * 20; ++#endif + m_networkBufferMode = 0; // Default (buffer all internet streams/filesystems) + // the following setting determines the readRate of a player data + // as multiply of the default data read rate + + +From 3f0d3c71caddb7da678557c66556e8aeb2095247 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 30 May 2014 14:58:43 +0100 +Subject: [PATCH 11/95] [settings] Experiment: Report DESKTOP resolution in + video settings + +--- + xbmc/settings/DisplaySettings.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp +index 1fafd9a..e0288aa 100644 +--- a/xbmc/settings/DisplaySettings.cpp ++++ b/xbmc/settings/DisplaySettings.cpp +@@ -674,6 +674,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, + vector resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate); + for (vector::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution) + { ++if (resolution->ResInfo_Index == RES_DESKTOP) ++ list.push_back(make_pair(StringUtils::Format("DESKTOP"), resolution->ResInfo_Index)); ++else + list.push_back(make_pair( + StringUtils::Format("%dx%d%s", resolution->width, resolution->height, + ModeFlagsToString(resolution->flags, false).c_str()), + +From 73cd1a696ea4d3484cb49de949ce6081f600e3fd Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 16 Aug 2014 21:01:42 +0100 +Subject: [PATCH 12/95] omxrender: Hacks to reduce GUI rendering rate when + playing video + +--- + .../resource.language.en_gb/resources/strings.po | 27 ++++++++++++++++++++++ + system/settings/rbp.xml | 16 +++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index a05173d..6e4e8be 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16541,3 +16541,30 @@ msgstr "" + msgctxt "#38012" + msgid "Show "All Items" entry in directory (for example All Albums or All Seasons)" + msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38000" ++msgid "Limit GUI updates when playing video" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38001" ++msgid "This can reduce CPU when playing video by updating the overlays less often" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38002" ++msgid "Off" ++msgstr "" ++ ++msgctxt "#38003" ++msgid "5 fps" ++msgstr "" ++ ++msgctxt "#38004" ++msgid "10 fps" ++msgstr "" ++ ++msgctxt "#38005" ++msgid "24 fps" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index bd3e2ad..ca1a571 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -15,6 +15,22 @@ + +
+ ++ ++ ++ 2 ++ 10 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + + +From 71e6bae9785ce14a6bf8230d60034e52cec42ad2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 24 Jan 2015 17:33:30 +0000 +Subject: [PATCH 13/95] renderer: Allow gui updates to be skipped when playing + video + +--- + xbmc/Application.cpp | 43 ++++++++++++++++++++++++++-------------- + xbmc/guilib/GUIWindowManager.cpp | 2 -- + xbmc/guilib/GUIWindowManager.h | 3 ++- + 3 files changed, 30 insertions(+), 18 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index f2b47dd..6f9849d 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -1949,27 +1949,41 @@ void CApplication::Render() + if(!g_Windowing.BeginRender()) + return; + +- CDirtyRegionList dirtyRegions = g_windowManager.GetDirty(); +- if(g_graphicsContext.GetStereoMode()) ++ CDirtyRegionList dirtyRegions; ++ ++ // render gui layer ++ int fps = 0; ++ if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); ++ unsigned int now = XbmcThreads::SystemClockMillis(); ++ unsigned int frameTime = now - m_lastRenderTime; ++ if (fps <= 0 || frameTime * fps >= 1000) + { +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); +- if(RenderNoPresent()) +- hasRendered = true; ++ dirtyRegions = g_windowManager.GetDirty(); ++ if (g_graphicsContext.GetStereoMode()) ++ { ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); ++ if (RenderNoPresent()) ++ hasRendered = true; + +- if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO) ++ if (g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO) ++ { ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT); ++ if (RenderNoPresent()) ++ hasRendered = true; ++ } ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); ++ } ++ else + { +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT); +- if(RenderNoPresent()) ++ if (RenderNoPresent()) + hasRendered = true; + } +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); +- } +- else +- { +- if(RenderNoPresent()) +- hasRendered = true; + } + ++ // render video layer ++ g_windowManager.RenderEx(); ++ + g_Windowing.EndRender(); + + // execute post rendering actions (finalize window closing) +@@ -1981,7 +1995,6 @@ void CApplication::Render() + g_infoManager.ResetCache(); + lock.Leave(); + +- unsigned int now = XbmcThreads::SystemClockMillis(); + if (hasRendered) + m_lastRenderTime = now; + +diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp +index 1ae90ae..e795c75 100644 +--- a/xbmc/guilib/GUIWindowManager.cpp ++++ b/xbmc/guilib/GUIWindowManager.cpp +@@ -986,8 +986,6 @@ bool CGUIWindowManager::Render() + CGUITexture::DrawQuad(*i, 0x4c00ff00); + } + +- RenderEx(); +- + return hasRendered; + } + +diff --git a/xbmc/guilib/GUIWindowManager.h b/xbmc/guilib/GUIWindowManager.h +index 09a7b9c..b492534 100644 +--- a/xbmc/guilib/GUIWindowManager.h ++++ b/xbmc/guilib/GUIWindowManager.h +@@ -94,6 +94,8 @@ class CGUIWindowManager + */ + bool Render(); + ++ void RenderEx() const; ++ + /*! \brief Do any post render activities. + */ + void AfterRender(); +@@ -169,7 +171,6 @@ class CGUIWindowManager + #endif + private: + void RenderPass() const; +- void RenderEx() const; + + void LoadNotOnDemandWindows(); + void UnloadNotOnDemandWindows(); + +From 153a026b4e7ec380925c3096b788a3728a16111b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 9 Sep 2014 12:04:26 +0100 +Subject: [PATCH 14/95] egl: Treat unknown display aspect ratio as square pixel + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 749de8d..98072e8 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -447,7 +447,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + 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 = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); ++ 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); + // Also add 3D flags + if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) + { +@@ -474,7 +474,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + m_desktopRes.iScreenHeight= tv_state.display.sdtv.height; + m_desktopRes.dwFlags = D3DPRESENTFLAG_INTERLACED; + m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate; +- m_desktopRes.fPixelRatio = get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight); ++ 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); + +From 1be64b18c6da636aee9bcc23d804a7921679c957 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 14:24:56 +0100 +Subject: [PATCH 15/95] [omxplayer] Only enable audio clock master when A/V + sync method is set to audio clock + +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 45a35bb..691b9a7 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -247,7 +247,8 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ if((CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) || ++ CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -273,7 +274,7 @@ bool COMXAudio::PortSettingsChanged() + { + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync +- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock")) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); + +From 74e5c08023c7d7652a7ad179f9ce41758e0f4c71 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 19 Sep 2014 11:54:49 +0100 +Subject: [PATCH 16/95] [dvdplayer/rbp] Add pi specific option to maintain + vsync with pll adjustment + +New A/V sync option in settings/video/playback to do "Adjust PLL". +This uses video clock (so perfect video syncing) but avoids having to resample +or drop/dupe audio packets which is normally required. + +Needed updated firmware + +[dvdplayeraudio] Add advancedsetting for configuring max pll adjustment + +[dvdplayer] Allow pll adjustment to go higher, but tail off more gradually +--- + .../resource.language.en_gb/resources/strings.po | 24 ++++++++++++++- + system/settings/settings.xml | 14 +++++++++ + xbmc/cores/AudioEngine/Utils/AEUtil.h | 3 +- + xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 36 +++++++++++++++++++--- + xbmc/cores/dvdplayer/DVDPlayerAudio.h | 3 ++ + xbmc/linux/RBP.cpp | 14 +++++++++ + xbmc/linux/RBP.h | 1 + + xbmc/settings/AdvancedSettings.cpp | 2 ++ + xbmc/settings/AdvancedSettings.h | 1 + + 9 files changed, 91 insertions(+), 7 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 6e4e8be..5f1d5b1 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -6334,7 +6334,22 @@ msgctxt "#13459" + msgid "Use OMXPlayer for decoding of video files." + msgstr "" + +-#empty strings from id 13460 to 13504 ++#empty strings from id 13460 to 13499 ++ ++#: system/settings/settings.xml ++msgctxt "#13500" ++msgid "A/V sync method" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#13503" ++msgid "Resample audio" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#13504" ++msgid "Adjust PLL" ++msgstr "" + + #: system/settings/settings.xml + msgctxt "#13505" +@@ -16568,3 +16583,10 @@ msgstr "" + msgctxt "#38005" + msgid "24 fps" + msgstr "" ++ ++#. Description of setting "Videos -> Playback -> A/V sync method" with label #13500 ++#: system/settings/settings.xml ++msgctxt "#38006" ++msgid "Audio has to stay in sync, this can either be done by resampling, or adjusting the PLL" ++msgstr "" ++ +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index e64b267..144105b 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -569,6 +569,20 @@ + false + +
++ ++ 2 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ true ++ ++ ++ + + 2 + 0 +diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h +index 782a9ba..3e0390c 100644 +--- a/xbmc/cores/AudioEngine/Utils/AEUtil.h ++++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h +@@ -57,7 +57,8 @@ enum AVSync + { + SYNC_DISCON = 0, + SYNC_SKIPDUP, +- SYNC_RESAMPLE ++ SYNC_RESAMPLE, ++ SYNC_PLLADJUST + }; + + struct AEDelayStatus +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +index 15e6f73..247e44a 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +@@ -25,6 +25,7 @@ + #include "DVDCodecs/DVDCodecs.h" + #include "DVDCodecs/DVDFactoryCodec.h" + #include "settings/Settings.h" ++#include "settings/AdvancedSettings.h" + #include "video/VideoReferenceClock.h" + #include "utils/log.h" + #include "utils/TimeUtils.h" +@@ -113,6 +114,9 @@ CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent) + m_started = false; + m_silence = false; + m_resampleratio = 1.0; ++ m_plladjust = 1.0; ++ m_last_plladjust = 1.0; ++ m_last_error = 0.0; + m_synctype = SYNC_DISCON; + m_setsynctype = SYNC_DISCON; + m_prevsynctype = -1; +@@ -186,11 +190,13 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec ) + m_synctype = SYNC_DISCON; + m_setsynctype = SYNC_DISCON; + if (CSettings::Get().GetBool("videoplayer.usedisplayasclock")) +- m_setsynctype = SYNC_RESAMPLE; ++ m_setsynctype = CSettings::Get().GetInt("videoplayer.synctype"); + m_prevsynctype = -1; + + m_error = 0; + m_errors.Flush(); ++ m_plladjust = 1.0; ++ m_last_plladjust = 1.0; + m_integral = 0; + m_prevskipped = false; + m_syncclock = true; +@@ -233,7 +239,6 @@ void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers) + + // uninit queue + m_messageQueue.End(); +- + CLog::Log(LOGNOTICE, "Deleting audio codec"); + if (m_pAudioCodec) + { +@@ -481,7 +486,11 @@ void CDVDPlayerAudio::UpdatePlayerInfo() + //print the inverse of the resample ratio, since that makes more sense + //if the resample ratio is 0.5, then we're playing twice as fast + if (m_synctype == SYNC_RESAMPLE) +- s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio; ++ s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms"; ++ if (m_synctype == SYNC_SKIPDUP) ++ s << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms"; ++ if (m_synctype == SYNC_PLLADJUST) ++ s << ", pll:" << fixed << setprecision(5) << m_last_plladjust << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms"; + + s << ", att:" << fixed << setprecision(1) << log(GetCurrentAttenuation()) * 20.0f << " dB"; + +@@ -635,8 +644,8 @@ void CDVDPlayerAudio::SetSyncType(bool passthrough) + + if (m_synctype != m_prevsynctype) + { +- const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "invalid"}; +- int synctype = (m_synctype >= 0 && m_synctype <= 2) ? m_synctype : 3; ++ const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "pll adjust", "invalid"}; ++ int synctype = (m_synctype >= 0 && m_synctype <= 3) ? m_synctype : 4; + CLog::Log(LOGDEBUG, "CDVDPlayerAudio:: synctype set to %i: %s", m_synctype, synctypes[synctype]); + m_prevsynctype = m_synctype; + } +@@ -723,7 +732,19 @@ void CDVDPlayerAudio::HandleSyncError(double duration) + proportional = m_error / DVD_TIME_BASE / proportionaldiv; + } + m_resampleratio = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral; ++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s rr:%.5f error:%.3fms", __FUNCTION__, m_resampleratio, m_error * 1e-3); ++ } ++ else if (m_synctype == SYNC_PLLADJUST) ++ { ++#if defined(TARGET_RASPBERRY_PI) ++ double e = std::max(std::min(m_error / DVD_MSEC_TO_TIME(50), 1.0), -1.0); ++ double adjust = g_advancedSettings.m_maxPllAdjust * 1e-6; ++ m_plladjust = 1.0 + e * adjust; ++ m_last_plladjust = g_RBP.AdjustHDMIClock(m_plladjust); ++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.5f (%.5f) error:%.6f e:%.6f a:%f", __FUNCTION__, m_plladjust, m_last_plladjust, m_error, e * adjust, adjust ); ++#endif + } ++ m_last_error = m_error; + } + } + +@@ -748,6 +769,7 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + { + m_dvdAudio.SetPlayingPts(m_audioClock); + } ++ m_plladjust = 1.0; + } + else if (m_synctype == SYNC_DISCON) + { +@@ -782,6 +804,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + m_dvdAudio.SetResampleRatio(m_resampleratio); + m_dvdAudio.AddPackets(audioframe); + } ++ else if (m_synctype == SYNC_PLLADJUST) ++ { ++ m_dvdAudio.AddPackets(audioframe); ++ } + + return true; + } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +index d58c45c..87de5fd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +@@ -231,6 +231,9 @@ class CDVDPlayerAudio : public CThread, public IDVDStreamPlayerAudio + bool m_prevskipped; + double m_maxspeedadjust; + double m_resampleratio; //resample ratio when using SYNC_RESAMPLE, used for the codec info ++ double m_plladjust; // for display using SYNC_PLLADJUST ++ double m_last_error; // for display using SYNC_PLLADJUST ++ double m_last_plladjust; // for display using SYNC_PLLADJUST + + struct SInfo + { +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index 5119949..ce09fce 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -212,4 +212,18 @@ void CRBP::Deinitialize() + m_initialized = false; + m_omx_initialized = false; + } ++ ++double CRBP::AdjustHDMIClock(double adjust) ++{ ++ char response[80]; ++ vc_gencmd(response, sizeof response, "hdmi_adjust_clock %f", adjust); ++ float new_adjust = 1.0f; ++ char *p = strchr(response, '='); ++ if (p) ++ new_adjust = atof(p+1); ++ CLog::Log(LOGDEBUG, "CRBP::%s(%.4f) = %.4f", __func__, adjust, new_adjust); ++ return new_adjust; ++} ++ ++ + #endif +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 4fd18f3..6456657 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -58,6 +58,7 @@ class CRBP + 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; } + void WaitVsync(); ++ double AdjustHDMIClock(double adjust); + + private: + DllBcmHost *m_DllBcmHost; +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 7797edf..59d45c8 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -110,6 +110,7 @@ void CAdvancedSettings::Initialize() + m_audioHeadRoom = 0; + m_ac3Gain = 12.0f; + m_audioApplyDrc = -1.0f; ++ m_maxPllAdjust = 1000; + m_dvdplayerIgnoreDTSinWAV = false; + + //default hold time of 25 ms, this allows a 20 hertz sine to pass undistorted +@@ -468,6 +469,7 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file) + if (pElement) + { + XMLUtils::GetFloat(pElement, "ac3downmixgain", m_ac3Gain, -96.0f, 96.0f); ++ XMLUtils::GetInt(pElement, "maxplladjust", m_maxPllAdjust, 0, 1000000); + XMLUtils::GetInt(pElement, "headroom", m_audioHeadRoom, 0, 12); + XMLUtils::GetString(pElement, "defaultplayer", m_audioDefaultPlayer); + // 101 on purpose - can be used to never automark as watched +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index b0b4df1..5e0b14c 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -141,6 +141,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + + int m_audioHeadRoom; + float m_ac3Gain; ++ int m_maxPllAdjust; + std::string m_audioDefaultPlayer; + float m_audioPlayCountMinimumPercent; + bool m_dvdplayerIgnoreDTSinWAV; + +From 7c19395b346de7b8a0f86059e726d1132cb41811 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 27 Sep 2014 15:32:37 +0100 +Subject: [PATCH 17/95] [dvdplayer] exerimental: don't raise priority of audio + thread + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index f0059fd..eff7d0e 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3308,7 +3308,11 @@ bool CDVDPlayer::OpenAudioStream(CDVDStreamInfo& hint, bool reset) + m_dvdPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); + + /* audio normally won't consume full cpu, so let it have prio */ ++#ifdef TARGET_RASPBERRY_PI ++ m_dvdPlayerAudio->SetPriority(GetPriority()); ++#else + m_dvdPlayerAudio->SetPriority(GetPriority()+1); ++#endif + return true; + } + + +From 1d26af83fec9b740c1fedfb5ac36fba0f3de6910 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 24 Sep 2014 23:13:52 +0100 +Subject: [PATCH 18/95] [audio] Add settings option to boost centre channel + when downmixing + +This allows a dB volume increase to be added to centre channel. +This can help improve dialgue in the presence of background music/effects. +It can go up to 30dB for testing purposes, but value of 6 is probably more reasonable. +It is recommended to ensure "Normalise levels on downmix" is enabled when boosting by large values to avoid clipping. + +Should work with Pi Sink (dvdplayer/paplayer) and omxplayer +--- + addons/resource.language.en_gb/resources/strings.po | 14 ++++++++++++++ + system/settings/settings.xml | 12 ++++++++++++ + .../Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp | 7 +++++++ + .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 ++++++ + xbmc/cores/omxplayer/OMXAudio.cpp | 6 ++++++ + 5 files changed, 45 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 5f1d5b1..7bae69d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16590,3 +16590,17 @@ msgctxt "#38006" + msgid "Audio has to stay in sync, this can either be done by resampling, or adjusting the PLL" + msgstr "" + ++#: system/settings/settings.xml ++msgctxt "#38007" ++msgid "Boost centre channel when downmixing" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38008" ++msgid "Increase this value to make the dialogue louder compared to background sounds when downmixing multichannel audio" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38009" ++msgid "%i dB" ++msgstr "" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 144105b..a40ecb5 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2640,6 +2640,18 @@ + true + + ++ ++ 2 ++ 0 ++ ++ 0 ++ 1 ++ 30 ++ ++ ++ 38009 ++ ++ + + HAS_AE_QUALITY_LEVELS + 2 +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +index e4ddf9e..34d0152 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +@@ -20,6 +20,7 @@ + + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "ActiveAEResampleFFMPEG.h" ++#include "settings/Settings.h" + #include "utils/log.h" + + extern "C" { +@@ -105,6 +106,12 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + if (remapLayout) + { +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +index b037317..fa8112d 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +@@ -164,6 +164,12 @@ bool CActiveAEResamplePi::Init(uint64_t dst_chan_layout, int dst_channels, int d + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + if (remapLayout) + { +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 691b9a7..602d2fa 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -634,6 +634,12 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + // stereo upmix + if (upmix && m_src_channels == 2 && m_dst_channels > 2) + +From 5026e6015ee5dcc99df426a1881dc6fbcf25fce6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:40:06 +0100 +Subject: [PATCH 19/95] [SinkPi] Handle multichannel layout more like OMXAudio + +--- + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 318df3b..3cb6bfb 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -93,9 +93,9 @@ static void SetAudioProps(bool stream_channels, uint32_t channel_map) + CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map); + } + +-static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) ++static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough) + { +- unsigned int channels = format.m_channelLayout.Count(); ++ unsigned int channels = channelLayout.Count(); + uint32_t channel_map = 0; + if (passthrough) + return 0; +@@ -134,12 +134,12 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) + // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels + // but no BR BL channels, we use the wide map in order to open only the num of channels really + // needed. +- if (format.m_channelLayout.HasChannel(AE_CH_BL) && !format.m_channelLayout.HasChannel(AE_CH_SL)) ++ if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL)) + map = map_back; + + for (unsigned int i = 0; i < channels; ++i) + { +- AEChannel c = format.m_channelLayout[i]; ++ AEChannel c = channelLayout[i]; + unsigned int chan = 0; + if ((unsigned int)c < sizeof map_normal / sizeof *map_normal) + chan = map[(unsigned int)c]; +@@ -170,9 +170,9 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) + 0xff, // 7 + 0x13, // 7.1 + }; +- uint8_t cea = format.m_channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; ++ uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; + if (cea == 0xff) +- CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, format.m_channelLayout.HasChannel(AE_CH_LFE), channels); ++ CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels); + + channel_map |= cea << 24; + +@@ -209,7 +209,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; + format.m_frameSamples = format.m_frames * channels; + +- SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough)); ++ SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough)); + + m_format = format; + m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate); + +From 2505e8b351bc7d8bc1a3b8e0c26d1375f7bfc724 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 15:23:51 +0000 +Subject: [PATCH 20/95] [rbp] Default extract thumbnails to false + +It can take 80 seconds for a single file on a Pi. It can cause crashes with out-of-memory errors. +It genereates a lot of support issues. Best to default to disabled and let users enable it if they must +--- + system/settings/rbp.xml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index ca1a571..f7cb75e 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -39,6 +39,16 @@ + + + ++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ +
+ +
+ +From e6c1438c3f8a9b9ed608219810e686ffdc2487ba Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 15 Nov 2014 12:03:34 +0000 +Subject: [PATCH 24/95] [dvdplayer] Add lock for player creation + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 3 +++ + xbmc/cores/dvdplayer/DVDPlayer.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index eff7d0e..3180fe9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -531,6 +531,7 @@ int CSelectionStreams::CountSource(StreamType type, StreamSource source) const + + void CDVDPlayer::CreatePlayers() + { ++ CSingleLock lock(m_players_lock); + #ifdef HAS_OMXPLAYER + if (m_omxplayer_mode && OMXPlayerUnsuitable(m_HasVideo, m_HasAudio, m_pDemuxer, m_pInputStream, m_SelectionStreams)) + { +@@ -560,6 +561,7 @@ void CDVDPlayer::CreatePlayers() + + void CDVDPlayer::DestroyPlayers() + { ++ CSingleLock lock(m_players_lock); + if (!m_players_created) + return; + delete m_dvdPlayerVideo; +@@ -4150,6 +4152,7 @@ double CDVDPlayer::GetQueueTime() + + void CDVDPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info) + { ++ CSingleLock lock(m_players_lock); + info.bitrate = m_dvdPlayerVideo->GetVideoBitrate(); + + std::string retVal; +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h +index 64c9974..ae5edc9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -557,4 +557,5 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer + // omxplayer variables + struct SOmxPlayerState m_OmxPlayerState; + bool m_omxplayer_mode; // using omxplayer acceleration ++ CCriticalSection m_players_lock; + }; + +From e8a90602e1fab767227e2101a400885d8e12d8c0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 24 Nov 2014 22:07:25 +0000 +Subject: [PATCH 25/95] [dvdplayervideo] Prod decoder when in stills mode + +An asynchronous hardware decoder doesn't only produce output pictures when new packets arrive. +In dvd stills mode give it a chance to return pictures that weren't ready when frame was decoded. +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 46 ++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 69dc501..5832c58 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -323,7 +323,8 @@ void CDVDPlayerVideo::Process() + + while (!m_bStop) + { +- int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000; ++ bool bPictureWaiting = m_hints.stills && (m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE) & VC_PICTURE); ++ int iQueueTimeOut = (int)(bPictureWaiting ? 0 : (m_hints.stills || m_stalled) ? frametime / 4 : frametime * 10) / 1000; + int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0; + + CDVDMsg* pMsg; +@@ -340,27 +341,36 @@ void CDVDPlayerVideo::Process() + if( iPriority ) + continue; + +- //Okey, start rendering at stream fps now instead, we are likely in a stillframe +- if( !m_stalled ) ++ // check for picture waiting ++ if (bPictureWaiting) + { +- if(m_started) +- CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate); +- m_stalled = true; +- pts+= frametime*4; ++ // create a dummy demuxer packet to prod the decode logic ++ pMsg = new CDVDMsgDemuxerPacket(CDVDDemuxUtils::AllocateDemuxPacket(0), false); + } +- +- //Waiting timed out, output last picture +- if( picture.iFlags & DVP_FLAG_ALLOCATED ) ++ else + { +- //Remove interlaced flag before outputting +- //no need to output this as if it was interlaced +- picture.iFlags &= ~DVP_FLAG_INTERLACED; +- picture.iFlags |= DVP_FLAG_NOSKIP; +- OutputPicture(&picture, pts); +- pts+= frametime; +- } ++ //Okey, start rendering at stream fps now instead, we are likely in a stillframe ++ if( !m_stalled ) ++ { ++ if(m_started) ++ CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate); ++ m_stalled = true; ++ pts+= frametime*4; ++ } + +- continue; ++ //Waiting timed out, output last picture ++ if( picture.iFlags & DVP_FLAG_ALLOCATED ) ++ { ++ //Remove interlaced flag before outputting ++ //no need to output this as if it was interlaced ++ picture.iFlags &= ~DVP_FLAG_INTERLACED; ++ picture.iFlags |= DVP_FLAG_NOSKIP; ++ OutputPicture(&picture, pts); ++ pts+= frametime; ++ } ++ ++ continue; ++ } + } + + if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) + +From 9e6dcba2e48b1c0c52882582c45c38371e594077 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 27 Nov 2014 16:31:56 +0000 +Subject: [PATCH 26/95] [languageinvoker] Reduce priority of python threads + +--- + xbmc/interfaces/generic/LanguageInvokerThread.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/xbmc/interfaces/generic/LanguageInvokerThread.cpp b/xbmc/interfaces/generic/LanguageInvokerThread.cpp +index fcdd063..16f0c89 100644 +--- a/xbmc/interfaces/generic/LanguageInvokerThread.cpp ++++ b/xbmc/interfaces/generic/LanguageInvokerThread.cpp +@@ -50,6 +50,11 @@ bool CLanguageInvokerThread::execute(const std::string &script, const std::vecto + m_args = arguments; + + Create(); ++ #ifdef TARGET_RASPBERRY_PI ++ /* low prio */ ++ SetPriority(GetPriority()-1); ++ #endif ++ + return true; + } + + +From 8d105a5da7c724d97dba995fe660e547b25d3e2e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Dec 2013 16:55:05 +0000 +Subject: [PATCH 27/95] logging: Add microsecond timer to log messages + +--- + xbmc/utils/log.cpp | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp +index 3443f12..31c4a99 100644 +--- a/xbmc/utils/log.cpp ++++ b/xbmc/utils/log.cpp +@@ -24,6 +24,7 @@ + #include "threads/Thread.h" + #include "utils/StringUtils.h" + #include "CompileInfo.h" ++#include "utils/TimeUtils.cpp" + + static const char* const levelNames[] = + {"DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "SEVERE", "FATAL", "NONE"}; +@@ -198,19 +199,31 @@ void CLog::PrintDebugString(const std::string& line) + + bool CLog::WriteLogString(int logLevel, const std::string& logString) + { ++#if defined(TARGET_LINUX) ++ static const char* prefixFormat = "%02.2d:%02.2d:%02.2d %10.6f T:%" PRIu64" %7s: "; ++#else + static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%" PRIu64" %7s: "; +- ++#endif + std::string strData(logString); + /* fixup newline alignment, number of spaces should equal prefix length */ + StringUtils::Replace(strData, "\n", "\n "); + + int hour, minute, second; + s_globals.m_platform.GetCurrentLocalTime(hour, minute, second); +- ++ ++#if defined(TARGET_LINUX) ++ struct timespec now; ++ clock_gettime(CLOCK_MONOTONIC, &now); ++ float Now = now.tv_sec + now.tv_nsec * 1e-9; ++#endif ++ + strData = StringUtils::Format(prefixFormat, + hour, + minute, + second, ++#if defined(TARGET_LINUX) ++ Now, ++#endif + (uint64_t)CThread::GetCurrentThreadId(), + levelNames[logLevel]) + strData; + + +From a97d46591a1178899bffc8511d4b82f5b2d50a44 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:24:42 +0200 +Subject: [PATCH 28/95] Added some vc_tv_* functions that were missing in + DllBCM. + +--- + xbmc/linux/DllBCM.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/xbmc/linux/DllBCM.h b/xbmc/linux/DllBCM.h +index b92fdb8..9c7e293 100644 +--- a/xbmc/linux/DllBCM.h ++++ b/xbmc/linux/DllBCM.h +@@ -48,6 +48,9 @@ class 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, +@@ -92,6 +95,12 @@ class DllBcmHost : public DllDynamic, DllBcmHostInterface + { 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); }; + +From c51d5fd32f12c2aec6094a813ef96fb7e037d21d Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:29:03 +0200 +Subject: [PATCH 29/95] Added private utility function to map a float display + aspect, to the respective SDTV_ASPECT_* enum value. + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 98072e8..da36944 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -412,6 +412,25 @@ static void SetResolutionString(RESOLUTION_INFO &res) + res.dwFlags & D3DPRESENTFLAG_MODE3DTB ? " 3DTB" : "", + res.dwFlags & D3DPRESENTFLAG_MODE3DSBS ? " 3DSBS" : ""); + } ++ ++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; ++} + #endif + + bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &resolutions) + +From 71135169f92ecb7e07a275707c33de2288b304de Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:50:58 +0200 +Subject: [PATCH 30/95] Changed SDTV resolutions to be treated similarly to + HDMI resolutions in SetNativeResolution. This means that the SDTV interface + is powered up and set to the right mode. + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 36 ++++++++++++++++++++----- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h | 1 - + 2 files changed, 29 insertions(+), 8 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index da36944..2ebd74c 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -222,7 +222,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + + DestroyDispmaxWindow(); + +- if(!m_fixedMode && GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) ++ if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) + { + sem_init(&m_tv_synced, 0, 0); + m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this); +@@ -276,6 +276,33 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + + 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\n", ++ 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\n", ++ 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 = m_DllBcmHost->vc_dispmanx_display_open(0); + +@@ -441,8 +468,6 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + if(!m_DllBcmHost) + return false; + +- m_fixedMode = false; +- + /* read initial desktop resolution before probe resolutions. + * probing will replace the desktop resolution when it finds the same one. + * we raplace it because probing will generate more detailed +@@ -491,7 +516,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + 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 = D3DPRESENTFLAG_INTERLACED; ++ 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); + } +@@ -514,9 +539,6 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags); + } + +- if(resolutions.size() < 2) +- m_fixedMode = true; +- + DLOG("CEGLNativeTypeRaspberryPI::ProbeResolutions\n"); + return true; + #else +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +index 59401f5..a0acb1a 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h +@@ -59,7 +59,6 @@ class CEGLNativeTypeRaspberryPI : public CEGLNativeType + DISPMANX_ELEMENT_HANDLE_T m_dispman_element; + TV_GET_STATE_RESP_T m_tv_state; + sem_t m_tv_synced; +- bool m_fixedMode; + RESOLUTION_INFO m_desktopRes; + int m_width; + int m_height; + +From e655ab07928217b60908342dc9299219598f20e8 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:54:59 +0200 +Subject: [PATCH 31/95] Added methods SuspendVideoOutput() and + ResumeVideoOutput() to CRBP class, which can be used to power down the + Raspberry PI's video interface, and restore it at a later point. + +--- + xbmc/linux/RBP.cpp | 13 +++++++++++++ + xbmc/linux/RBP.h | 3 +++ + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 3 +++ + 3 files changed, 19 insertions(+) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index ce09fce..a18aa49 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -225,5 +225,18 @@ double CRBP::AdjustHDMIClock(double adjust) + return new_adjust; + } + ++void CRBP::SuspendVideoOutput() ++{ ++ CLog::Log(LOGDEBUG, "Raspberry PI suspending video output\n"); ++ char response[80]; ++ m_DllBcmHost->vc_gencmd(response, sizeof response, "display_power 0"); ++} ++ ++void CRBP::ResumeVideoOutput() ++{ ++ char response[80]; ++ m_DllBcmHost->vc_gencmd(response, sizeof response, "display_power 1"); ++ CLog::Log(LOGDEBUG, "Raspberry PI resuming video output\n"); ++} + + #endif +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 6456657..606c24f 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -60,6 +60,9 @@ class CRBP + void WaitVsync(); + double AdjustHDMIClock(double adjust); + ++ void SuspendVideoOutput(); ++ void ResumeVideoOutput(); ++ + private: + DllBcmHost *m_DllBcmHost; + bool m_initialized; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 2ebd74c..335f6d5 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -60,7 +60,10 @@ + # define DLOG(fmt, args...) + #endif + ++#if defined(TARGET_RASPBERRY_PI) + static void SetResolutionString(RESOLUTION_INFO &res); ++static SDTV_ASPECT_T get_sdtv_aspect_from_display_aspect(float display_aspect); ++#endif + + CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI() + { + +From b1c499da61efc2b7f33b478327600151a1ccf359 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Aug 2013 15:03:36 +0100 +Subject: [PATCH 32/95] PowerManager (and its IPowerSyscall instance) now gets + called from CApplication::OnKey() and can process and suppress key presses. + This is a requirement to implement a virtual sleep state. + +--- + xbmc/Application.cpp | 1 - + xbmc/input/InputManager.cpp | 8 ++++++++ + xbmc/powermanagement/IPowerSyscall.h | 7 +++++++ + xbmc/powermanagement/PowerManager.cpp | 6 ++++++ + xbmc/powermanagement/PowerManager.h | 3 +++ + 5 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 6f9849d..9c6f75f 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2037,7 +2037,6 @@ void CApplication::SetStandAlone(bool value) + g_advancedSettings.m_handleMounting = m_bStandalone = value; + } + +- + // OnAppCommand is called in response to a XBMC_APPCOMMAND event. + // This needs to return true if it processed the appcommand or false if it didn't + bool CApplication::OnAppCommand(const CAction &action) +diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp +index c6f62d8..f90fa89 100644 +--- a/xbmc/input/InputManager.cpp ++++ b/xbmc/input/InputManager.cpp +@@ -30,6 +30,7 @@ + #include "guilib/GUIWindow.h" + #include "guilib/GUIWindowManager.h" + #include "guilib/GUIMessage.h" ++#include "powermanagement/PowerManager.h" + + #ifdef HAS_EVENT_SERVER + #include "network/EventServer.h" +@@ -524,6 +525,13 @@ bool CInputManager::OnKey(const CKey& key) + // special handling if the screensaver is active + CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key); + ++ // give the PowerManager a chance to process a keypress, and ++ // suppress further processing. we need this for virtual sleep. ++ if (g_powerManager.ProcessAction(action)) ++ { ++ return true; ++ } ++ + // a key has been pressed. + // reset Idle Timer + g_application.ResetSystemIdleTimer(); +diff --git a/xbmc/powermanagement/IPowerSyscall.h b/xbmc/powermanagement/IPowerSyscall.h +index 7f9e7ed..711abea 100644 +--- a/xbmc/powermanagement/IPowerSyscall.h ++++ b/xbmc/powermanagement/IPowerSyscall.h +@@ -20,6 +20,9 @@ + * + */ + ++// forward declaration ++class CAction; ++ + class IPowerEventsCallback + { + public: +@@ -60,6 +63,10 @@ class IPowerSyscall + \param callback the callback to signal to + */ + virtual bool PumpPowerEvents(IPowerEventsCallback *callback) = 0; ++ ++ // this is an optional part of the interface, so we provide a no-op implementation here. ++ // return true to suppress further processing of the CAction. ++ virtual bool ProcessAction(const CAction& action) { return false; } + }; + + class CPowerSyscallWithoutEvents : public IPowerSyscall +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 5900f98..6e819d9 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -225,6 +225,12 @@ void CPowerManager::ProcessEvents() + nesting--; + } + ++bool CPowerManager::ProcessAction(const CAction& action) ++{ ++ return m_instance->ProcessAction(action); ++} ++ ++ + void CPowerManager::OnSleep() + { + CAnnouncementManager::Get().Announce(System, "xbmc", "OnSleep"); +diff --git a/xbmc/powermanagement/PowerManager.h b/xbmc/powermanagement/PowerManager.h +index 0b1f10a..e42b143 100644 +--- a/xbmc/powermanagement/PowerManager.h ++++ b/xbmc/powermanagement/PowerManager.h +@@ -58,6 +58,8 @@ class CNullPowerSyscall : public IPowerSyscall + + + virtual bool PumpPowerEvents(IPowerEventsCallback *callback) { return false; } ++ ++ virtual bool ProcessAction(const CAction& action) { return false; } + }; + + // This class will wrap and handle PowerSyscalls. +@@ -87,6 +89,7 @@ class CPowerManager : public IPowerEventsCallback + + static void SettingOptionsShutdownStatesFiller(const CSetting *setting, std::vector< std::pair > &list, int ¤t, void *data); + ++ bool ProcessAction(const CAction& action); + private: + void OnSleep(); + void OnWake(); + +From 126a4e7e1333ad47a1c253fa8be68438525eea4a Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:23:01 +0200 +Subject: [PATCH 33/95] Added CPowerSyscallVirtualSleep class, which acts as a + base class for devices that have no native standby mode, and need to fake it + in some way. + +--- + xbmc/powermanagement/Makefile | 1 + + xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 84 +++++++++++++++++++++++ + xbmc/powermanagement/PowerSyscallVirtualSleep.h | 56 +++++++++++++++ + 3 files changed, 141 insertions(+) + create mode 100644 xbmc/powermanagement/PowerSyscallVirtualSleep.cpp + create mode 100644 xbmc/powermanagement/PowerSyscallVirtualSleep.h + +diff --git a/xbmc/powermanagement/Makefile b/xbmc/powermanagement/Makefile +index 0b4c029..16056af 100644 +--- a/xbmc/powermanagement/Makefile ++++ b/xbmc/powermanagement/Makefile +@@ -1,5 +1,6 @@ + SRCS=DPMSSupport.cpp \ + PowerManager.cpp \ ++ PowerSyscallVirtualSleep.cpp \ + + LIB=powermanagement.a + +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +new file mode 100644 +index 0000000..9e6c8e4 +--- /dev/null ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +@@ -0,0 +1,84 @@ ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "PowerSyscallVirtualSleep.h" ++#include "input/Key.h" ++#include "utils/log.h" ++#include "utils/StringUtils.h" ++ ++bool CPowerSyscallVirtualSleep::Suspend() ++{ ++ if (m_virtualSleepState == VIRTUAL_SLEEP_STATE_AWAKE) ++ { ++ if (VirtualSleep()) ++ { ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_WILL_SLEEP; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++bool CPowerSyscallVirtualSleep::PumpPowerEvents(IPowerEventsCallback *callback) ++{ ++ if (m_virtualSleepState == VIRTUAL_SLEEP_STATE_WILL_WAKE) ++ { ++ callback->OnWake(); ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_AWAKE; ++ return true; ++ } ++ else if (m_virtualSleepState == VIRTUAL_SLEEP_STATE_WILL_SLEEP) ++ { ++ callback->OnSleep(); ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_ASLEEP; ++ return true; ++ } ++ ++ return false; ++} ++ ++bool CPowerSyscallVirtualSleep::ProcessAction(const CAction& action) ++{ ++ if (m_virtualSleepState != VIRTUAL_SLEEP_STATE_ASLEEP) ++ return false; ++ ++ // device is in virtual sleep, only one of the power keys will ++ // wake it up again. ++ if (action.GetID() == ACTION_BUILT_IN_FUNCTION) ++ { ++ std::string name = action.GetName(); ++ StringUtils::ToLower(name); ++ if(name.Equals("xbmc.suspend()") || ++ name.Equals("shutdown") || ++ name.Equals("suspend") || ++ name.Equals("hibernate")) ++ { ++ if(VirtualWake()) ++ { ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_WILL_WAKE; ++ return false; ++ } ++ } ++ } ++ ++ // wasn't a power key, suppress this and stay asleep ++ return true; ++} +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.h b/xbmc/powermanagement/PowerSyscallVirtualSleep.h +new file mode 100644 +index 0000000..ef6e682 +--- /dev/null ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#ifndef _POWER_SYSCALL_VIRTUAL_SLEEP_H_ ++#define _POWER_SYSCALL_VIRTUAL_SLEEP_H_ ++#include "IPowerSyscall.h" ++ ++// Systems that have no native standby mode, can base their ++// IPowerSyscall implementation on this class, and need only ++// implement VirtualSleep()/VirtualWake(). ++class CPowerSyscallVirtualSleep : public IPowerSyscall ++{ ++public: ++ CPowerSyscallVirtualSleep() : m_virtualSleepState(VIRTUAL_SLEEP_STATE_AWAKE) {} ++ virtual ~CPowerSyscallVirtualSleep() {} ++ ++ virtual bool CanSuspend() { return true; } ++ virtual bool Suspend(); ++ ++ virtual bool PumpPowerEvents(IPowerEventsCallback *callback); ++ ++ virtual bool ProcessAction(const CAction& action); ++ ++ virtual bool VirtualSleep() = 0; ++ virtual bool VirtualWake() = 0; ++ ++protected: ++ // keep track of virtual sleep state for devices that support it ++ typedef enum { ++ VIRTUAL_SLEEP_STATE_AWAKE = 0, ++ VIRTUAL_SLEEP_STATE_ASLEEP, ++ VIRTUAL_SLEEP_STATE_WILL_WAKE, ++ VIRTUAL_SLEEP_STATE_WILL_SLEEP, ++ } VirtualSleepState; ++ ++ VirtualSleepState m_virtualSleepState; ++}; ++ ++#endif // _POWER_SYSCALL_VIRTUAL_SLEEP_H_ + +From b50d81dd02214ed26210bad3d3102312ab7bab38 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:24:22 +0200 +Subject: [PATCH 34/95] Added power management support for the Raspberry Pi. + Since it doesn't support true standby, we fake it by turning video on or off, + and ignoring remote inputs during the standby phase. + +--- + xbmc/powermanagement/PowerManager.cpp | 4 ++ + xbmc/powermanagement/linux/Makefile | 1 + + .../linux/RaspberryPIPowerSyscall.cpp | 38 +++++++++++++++++ + .../linux/RaspberryPIPowerSyscall.h | 49 ++++++++++++++++++++++ + 4 files changed, 92 insertions(+) + create mode 100644 xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp + create mode 100644 xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h + +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 6e819d9..2d8c750 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -38,6 +38,8 @@ + + #if defined(TARGET_DARWIN) + #include "osx/CocoaPowerSyscall.h" ++#elif defined(TARGET_RASPBERRY_PI) ++#include "linux/RaspberryPIPowerSyscall.h" + #elif defined(TARGET_ANDROID) + #include "android/AndroidPowerSyscall.h" + #elif defined(TARGET_POSIX) +@@ -71,6 +73,8 @@ void CPowerManager::Initialize() + { + #if defined(TARGET_DARWIN) + m_instance = new CCocoaPowerSyscall(); ++#elif defined(TARGET_RASPBERRY_PI) ++ m_instance = new CRaspberryPIPowerSyscall(); + #elif defined(TARGET_ANDROID) + m_instance = new CAndroidPowerSyscall(); + #elif defined(TARGET_POSIX) +diff --git a/xbmc/powermanagement/linux/Makefile b/xbmc/powermanagement/linux/Makefile +index e9d95fb..b130812 100644 +--- a/xbmc/powermanagement/linux/Makefile ++++ b/xbmc/powermanagement/linux/Makefile +@@ -1,5 +1,6 @@ + SRCS=ConsoleDeviceKitPowerSyscall.cpp \ + ConsoleUPowerSyscall.cpp \ ++ RaspberryPIPowerSyscall.cpp \ + UPowerSyscall.cpp \ + LogindUPowerSyscall.cpp + +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +new file mode 100644 +index 0000000..10deeb8 +--- /dev/null ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if defined(TARGET_RASPBERRY_PI) ++ ++#include "RaspberryPIPowerSyscall.h" ++#include "RBP.h" ++ ++bool CRaspberryPIPowerSyscall::VirtualSleep() ++{ ++ g_RBP.SuspendVideoOutput(); ++ return true; ++} ++ ++bool CRaspberryPIPowerSyscall::VirtualWake() ++{ ++ g_RBP.ResumeVideoOutput(); ++ return true; ++} ++ ++#endif +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +new file mode 100644 +index 0000000..fd1d67c +--- /dev/null ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +@@ -0,0 +1,49 @@ ++#pragma once ++/* ++ * Copyright (C) 2013 Team XBMC ++ * http://www.xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#ifndef _RASPBERRY_PI_POWER_SYSCALL_H_ ++#define _RASPBERRY_PI_POWER_SYSCALL_H_ ++ ++#if defined(TARGET_RASPBERRY_PI) ++#include "powermanagement/PowerSyscallVirtualSleep.h" ++ ++class CRaspberryPIPowerSyscall : public CPowerSyscallVirtualSleep ++{ ++public: ++ CRaspberryPIPowerSyscall() : CPowerSyscallVirtualSleep() {} ++ virtual ~CRaspberryPIPowerSyscall() {} ++ ++ virtual bool Powerdown() { return false; } ++ virtual bool Hibernate() { return false; } ++ virtual bool Reboot() { return false; } ++ ++ virtual bool CanPowerdown() { return false; } ++ virtual bool CanHibernate() { return false; } ++ virtual bool CanReboot() { return true; } ++ ++ virtual int BatteryLevel() { return 0; } ++ ++ virtual bool VirtualSleep(); ++ virtual bool VirtualWake(); ++}; ++#endif // TARGET_RASPBERRY_PI ++ ++#endif // _RASPBERRY_PI_POWER_SYSCALL_H_ + +From 55c10c9ffe81121395c6cfbbdc8dec7ec595e9d1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:16:29 +0000 +Subject: [PATCH 35/95] [power] hack - don't kill lirc or cec + +--- + xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 37 +++++++++++++++++++++++ + xbmc/powermanagement/PowerManager.cpp | 4 +-- + 2 files changed, 39 insertions(+), 2 deletions(-) + +diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +index 3d0c07d..ae5583d 100644 +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +@@ -186,12 +186,49 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender, + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) + { ++#if 1 ++ bool bSendStandbyCommands(false); ++ { ++ CSingleLock lock(m_critSection); ++ bSendStandbyCommands = m_iExitCode != EXITCODE_REBOOT && ++ m_iExitCode != EXITCODE_RESTARTAPP && ++ !m_bDeviceRemoved && ++ (!m_bGoingToStandby || GetSettingBool("standby_tv_on_pc_standby")) && ++ GetSettingBool("enabled"); ++ ++ if (m_bGoingToStandby) ++ m_bActiveSourceBeforeStandby = m_cecAdapter->IsLibCECActiveSource(); ++ } ++ ++ if (bSendStandbyCommands) ++ { ++ if (m_cecAdapter->IsLibCECActiveSource()) ++ { ++ if (!m_configuration.powerOffDevices.IsEmpty()) ++ { ++ CLog::Log(LOGDEBUG, "%s - sending standby commands", __FUNCTION__); ++ m_standbySent = CDateTime::GetCurrentDateTime(); ++ m_cecAdapter->StandbyDevices(); ++ } ++ else if (m_configuration.bSendInactiveSource == 1) ++ { ++ CLog::Log(LOGDEBUG, "%s - sending inactive source commands", __FUNCTION__); ++ m_cecAdapter->SetInactiveView(); ++ } ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, "%s - XBMC is not the active source, not sending any standby commands", __FUNCTION__); ++ } ++ } ++#else + // this will also power off devices when we're the active source + { + CSingleLock lock(m_critSection); + m_bGoingToStandby = true; + } + StopThread(); ++#endif + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) + { +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 2d8c750..901f449 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -241,7 +241,7 @@ void CPowerManager::OnSleep() + CLog::Log(LOGNOTICE, "%s: Running sleep jobs", __FUNCTION__); + + // stop lirc +-#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) ++#if 0 //defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) + CLog::Log(LOGNOTICE, "%s: Stopping lirc", __FUNCTION__); + CBuiltins::Execute("LIRC.Stop"); + #endif +@@ -277,7 +277,7 @@ void CPowerManager::OnWake() + #endif + + // restart lirc +-#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) ++#if 0 // defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) + CLog::Log(LOGNOTICE, "%s: Restarting lirc", __FUNCTION__); + CBuiltins::Execute("LIRC.Start"); + #endif + +From f765ae243bf2d5b55733ebb70fd2b1f758a73090 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:47:54 +0000 +Subject: [PATCH 36/95] [power] hack - wake on any action + +--- + xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +index 9e6c8e4..78566ec 100644 +--- a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +@@ -62,14 +62,14 @@ bool CPowerSyscallVirtualSleep::ProcessAction(const CAction& action) + + // device is in virtual sleep, only one of the power keys will + // wake it up again. +- if (action.GetID() == ACTION_BUILT_IN_FUNCTION) ++ //if (action.GetID() == ACTION_BUILT_IN_FUNCTION) + { + std::string name = action.GetName(); + StringUtils::ToLower(name); +- if(name.Equals("xbmc.suspend()") || ++ /*if(name.Equals("system.suspend") || + name.Equals("shutdown") || + name.Equals("suspend") || +- name.Equals("hibernate")) ++ name.Equals("hibernate"))*/ + { + if(VirtualWake()) + { + +From 275567504607bf439caa71cf7fd834d92ea223d8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 17:30:07 +0000 +Subject: [PATCH 37/95] [power] hack - Make suspend toggle suspend state + +--- + xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +index 78566ec..4cffcce 100644 +--- a/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp ++++ b/xbmc/powermanagement/PowerSyscallVirtualSleep.cpp +@@ -33,6 +33,11 @@ bool CPowerSyscallVirtualSleep::Suspend() + return true; + } + } ++ else if (VirtualWake()) ++ { ++ m_virtualSleepState = VIRTUAL_SLEEP_STATE_WILL_WAKE; ++ return false; ++ } + + return false; + } + +From 196584d35b67d9cb2cec5d4502b98e314a9c8eee Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 4 Mar 2014 19:33:44 +0000 +Subject: [PATCH 38/95] [power] Add back in powerdown and reboot + +--- + .../linux/RaspberryPIPowerSyscall.cpp | 34 ++++++++++++++++++++++ + .../linux/RaspberryPIPowerSyscall.h | 6 ++-- + 2 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +index 10deeb8..220bca9 100644 +--- a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.cpp +@@ -20,7 +20,11 @@ + + #if defined(TARGET_RASPBERRY_PI) + ++#include "system.h" + #include "RaspberryPIPowerSyscall.h" ++#if defined(HAS_DBUS) ++#include "LogindUPowerSyscall.h" ++#endif + #include "RBP.h" + + bool CRaspberryPIPowerSyscall::VirtualSleep() +@@ -35,4 +39,34 @@ bool CRaspberryPIPowerSyscall::VirtualWake() + return true; + } + ++bool CRaspberryPIPowerSyscall::Powerdown() ++{ ++ int s = false; ++#if defined(HAS_DBUS) ++ if (CLogindUPowerSyscall::HasLogind()) ++ { ++ IPowerSyscall *m_instance = new CLogindUPowerSyscall; ++ if (m_instance->CanPowerdown()) ++ s = m_instance->Powerdown(); ++ delete m_instance; ++ } ++#endif ++ return s; ++} ++ ++bool CRaspberryPIPowerSyscall::Reboot() ++{ ++ int s = false; ++#if defined(HAS_DBUS) ++ if (CLogindUPowerSyscall::HasLogind()) ++ { ++ IPowerSyscall *m_instance = new CLogindUPowerSyscall; ++ if (m_instance->CanReboot()) ++ s = m_instance->Reboot(); ++ delete m_instance; ++ } ++#endif ++ return s; ++} ++ + #endif +diff --git a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +index fd1d67c..062132e 100644 +--- a/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h ++++ b/xbmc/powermanagement/linux/RaspberryPIPowerSyscall.h +@@ -31,11 +31,11 @@ class CRaspberryPIPowerSyscall : public CPowerSyscallVirtualSleep + CRaspberryPIPowerSyscall() : CPowerSyscallVirtualSleep() {} + virtual ~CRaspberryPIPowerSyscall() {} + +- virtual bool Powerdown() { return false; } ++ virtual bool Powerdown(); + virtual bool Hibernate() { return false; } +- virtual bool Reboot() { return false; } ++ virtual bool Reboot(); + +- virtual bool CanPowerdown() { return false; } ++ virtual bool CanPowerdown() { return true; } + virtual bool CanHibernate() { return false; } + virtual bool CanReboot() { return true; } + + +From a7ea5732e9d41ce4c860f7837e1a5c7a903d1322 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 26 Apr 2014 17:27:52 +0100 +Subject: [PATCH 39/95] [cec] Don't suspend pi on tv switch off - it can't wake + up + +--- + system/peripherals.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/system/peripherals.xml b/system/peripherals.xml +index 094a3c1..0b89ee8 100644 +--- a/system/peripherals.xml ++++ b/system/peripherals.xml +@@ -16,7 +16,7 @@ + + + +- ++ + + + + +From 7b9fdacd125a5b43b35eb0ec777927186749a732 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Jun 2014 00:01:05 +0100 +Subject: [PATCH 40/95] [rbp] Resume video output on startup + +--- + xbmc/linux/RBP.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index a18aa49..6514c2d 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -88,6 +88,9 @@ bool CRBP::Initialize() + if (g_advancedSettings.m_cacheMemBufferSize == ~0U) + g_advancedSettings.m_cacheMemBufferSize = m_arm_mem < 256 ? 1024 * 1024 * 2 : 1024 * 1024 * 20; + ++ // in case xbcm was restarted when suspended ++ ResumeVideoOutput(); ++ + g_OMXImage.Initialize(); + m_omx_image_init = true; + return true; + +From 0972c1c22138ef2b047048caac41b661af6740a9 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 11 Apr 2014 16:12:27 +0100 +Subject: [PATCH 41/95] [omxplayer] Add ability to log more timestamp info in + extra debug settings + +--- + addons/resource.language.en_gb/resources/strings.po | 5 +++++ + xbmc/commons/ilog.h | 1 + + xbmc/cores/omxplayer/OMXHelper.cpp | 12 +++++++----- + xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 8 ++++---- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 9 +++++---- + xbmc/settings/AdvancedSettings.cpp | 3 +++ + 6 files changed, 25 insertions(+), 13 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 44e1ef7..3909203 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2908,6 +2908,11 @@ msgctxt "#680" + msgid "Verbose logging for VIDEO component" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#697" ++msgid "Verbose logging for OMXPLAYER" ++msgstr "" ++ + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index de90359..e4ffb5e 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -53,6 +53,7 @@ + #define LOGUPNP (1 << (LOGMASKBIT + 8)) + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) ++#define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXHelper.cpp b/xbmc/cores/omxplayer/OMXHelper.cpp +index be54f31..9739ed0 100644 +--- a/xbmc/cores/omxplayer/OMXHelper.cpp ++++ b/xbmc/cores/omxplayer/OMXHelper.cpp +@@ -23,6 +23,7 @@ + #ifdef HAS_OMXPLAYER + + #include "DVDPlayer.h" ++#include "settings/AdvancedSettings.h" + #include "settings/Settings.h" + #include "settings/MediaSettings.h" + #include "DVDInputStreams/DVDInputStream.h" +@@ -140,7 +141,8 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed, + m_OmxPlayerState.video_fifo = (int)(100.0*(m_dvdPlayerVideo->GetDecoderBufferSize()-m_dvdPlayerVideo->GetDecoderFreeSpace())/m_dvdPlayerVideo->GetDecoderBufferSize()); + m_OmxPlayerState.audio_fifo = (int)(100.0*audio_fifo/m_dvdPlayerAudio->GetCacheTotal()); + +- #ifdef _DEBUG ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ { + static unsigned count; + if ((count++ & 7) == 0) + { +@@ -160,7 +162,7 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed, + vc_gencmd(response, sizeof response, "render_bar 7 audio_queue %d %d %d %d", + m_dvdPlayerAudio->GetLevel(), 0, 0, 100); + } +- #endif ++ } + if (audio_pts != DVD_NOPTS_VALUE) + { + audio_fifo_low = m_HasAudio && audio_fifo < threshold; +@@ -176,15 +178,15 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed, + if (!m_HasVideo && m_HasAudio) + video_fifo_high = true; + +- #ifdef _DEBUG ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ { + CLog::Log(LOGDEBUG, "%s::%s M:%.6f-%.6f (A:%.6f V:%.6f) PEF:%d%d%d S:%.2f A:%.2f V:%.2f/T:%.2f (A:%d%d V:%d%d) A:%d%% V:%d%% (%.2f,%.2f)", "CDVDPlayer", __FUNCTION__, + m_OmxPlayerState.stamp*1e-6, m_OmxPlayerState.av_clock.OMXClockAdjustment()*1e-6, audio_pts*1e-6, video_pts*1e-6, + m_OmxPlayerState.av_clock.OMXIsPaused(), m_OmxPlayerState.bOmxSentEOFs, not_accepts_data, m_playSpeed * (1.0f/DVD_PLAYSPEED_NORMAL), + audio_pts == DVD_NOPTS_VALUE ? 0.0:audio_fifo, video_pts == DVD_NOPTS_VALUE ? 0.0:video_fifo, m_OmxPlayerState.threshold, + audio_fifo_low, audio_fifo_high, video_fifo_low, video_fifo_high, + m_dvdPlayerAudio->GetLevel(), m_dvdPlayerVideo->GetLevel(), m_dvdPlayerAudio->GetDelay(), (float)m_dvdPlayerAudio->GetCacheTotal()); +- #endif +- ++ } + if(!m_Pause && (m_OmxPlayerState.bOmxSentEOFs || not_accepts_data || (audio_fifo_high && video_fifo_high) || m_playSpeed != DVD_PLAYSPEED_NORMAL)) + { + if (m_OmxPlayerState.av_clock.OMXIsPaused()) +diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +index c2da2d2..2f1df45 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +@@ -366,10 +366,10 @@ void OMXPlayerAudio::Process() + DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); + bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); + +- #ifdef _DEBUG +- CLog::Log(LOGINFO, "Audio: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d,%d", pPacket->dts, pPacket->pts, +- (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, (int)m_omxAudio.GetAudioRenderingLatency(), (int)m_hints_current.samplerate); +- #endif ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ CLog::Log(LOGINFO, "Audio: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d,%d", pPacket->dts, pPacket->pts, ++ (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, (int)m_omxAudio.GetAudioRenderingLatency(), (int)m_hints_current.samplerate); ++ + if(Decode(pPacket, m_speed > DVD_PLAYSPEED_NORMAL || m_speed < 0 || bPacketDrop)) + { + // we are not running until something is cached in output device +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index bee7086..4e599e3 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -42,6 +42,7 @@ + #include "DVDOverlayRenderer.h" + #include "settings/DisplaySettings.h" + #include "settings/Settings.h" ++#include "settings/AdvancedSettings.h" + #include "settings/MediaSettings.h" + #include "cores/VideoRenderers/RenderFormats.h" + #include "cores/VideoRenderers/RenderFlags.h" +@@ -461,10 +462,10 @@ void OMXPlayerVideo::Process() + DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); + bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); + +- #ifdef _DEBUG +- CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts, +- (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0); +- #endif ++ if (g_advancedSettings.CanLogComponent(LOGOMXPLAYER)) ++ CLog::Log(LOGINFO, "Video: dts:%.0f pts:%.0f size:%d (s:%d f:%d d:%d l:%d) s:%d %d/%d late:%d\n", pPacket->dts, pPacket->pts, ++ (int)pPacket->iSize, m_started, m_flush, bPacketDrop, m_stalled, m_speed, 0, 0, 0); ++ + if (m_messageQueue.GetDataSize() == 0 + || m_speed < 0) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 59d45c8..e46233a 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1364,6 +1364,9 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef HAVE_LIBCEC + list.push_back(std::make_pair(g_localizeStrings.Get(679), LOGCEC)); + #endif ++#ifdef TARGET_RASPBERRY_PI ++ list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); ++#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 3df8730dedff3efbc594ab5029653fcbcb510c95 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 42/95] [omxplayer] Add ability to dump out audio/video data + for later debugging + +--- + .../resource.language.en_gb/resources/strings.po | 10 +++++ + xbmc/commons/ilog.h | 2 + + xbmc/cores/omxplayer/OMXAudio.cpp | 49 ++++++++++++++++++++++ + xbmc/cores/omxplayer/OMXVideo.cpp | 47 +++++++++++++++++++++ + xbmc/settings/AdvancedSettings.cpp | 4 ++ + 5 files changed, 112 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 3909203..d8563fb 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2913,6 +2913,16 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#698" ++msgid "Dump video frames to debug file" ++msgstr "" ++ ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#699" ++msgid "Dump audio frames to debug file" ++msgstr "" ++ + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index e4ffb5e..4f8926c 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,6 +54,8 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) ++#define LOGDUMPVIDEO (1 << (LOGMASKBIT + 17)) ++#define LOGDUMPAUDIO (1 << (LOGMASKBIT + 18)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 602d2fa..0b8fd69 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -56,6 +56,49 @@ using namespace std; + #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024) + static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3}; + ++//#define DEBUG_PLAYBACK ++static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) ++{ ++ if (!(g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) ++ return; ++ static FILE *fp; ++ if (!omx_buffer) ++ { ++ if (fp) ++ { ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, "audio.dat"); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ OMX_BUFFERHEADERTYPE omx = {0}; ++ int s = fread(&omx, sizeof omx, 1, fp); ++ omx_buffer->nFilledLen = omx.nFilledLen; ++ omx_buffer->nFlags = omx.nFlags; ++ omx_buffer->nTimeStamp = omx.nTimeStamp; ++ if (s==1) ++ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#else ++ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) ++ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#endif ++ } ++} ++ + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// +@@ -868,6 +911,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -900,6 +944,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -936,6 +981,8 @@ bool COMXAudio::Deinitialize() + { + CSingleLock lock (m_critSection); + ++ dump_omx_buffer(NULL); ++ + if ( m_omx_tunnel_clock_analog.IsInitialized() ) + m_omx_tunnel_clock_analog.Deestablish(); + if ( m_omx_tunnel_clock_hdmi.IsInitialized() ) +@@ -1226,6 +1273,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt + int nRetry = 0; + while(true) + { ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -1473,6 +1521,7 @@ void COMXAudio::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 55e16c4..4489546 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -65,6 +65,49 @@ + + #define MAX_TEXT_LENGTH 1024 + ++//#define DEBUG_PLAYBACK ++static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) ++{ ++ if (!(g_advancedSettings.CanLogComponent(LOGDUMPVIDEO))) ++ return; ++ static FILE *fp; ++ if (!omx_buffer) ++ { ++ if (fp) ++ { ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, "video.dat"); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ OMX_BUFFERHEADERTYPE omx = {0}; ++ int s = fread(&omx, sizeof omx, 1, fp); ++ omx_buffer->nFilledLen = omx.nFilledLen; ++ omx_buffer->nFlags = omx.nFlags; ++ omx_buffer->nTimeStamp = omx.nTimeStamp; ++ if (s==1) ++ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#else ++ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) ++ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#endif ++ } ++} ++ + COMXVideo::COMXVideo() : m_video_codec_name("") + { + m_is_open = false; +@@ -120,6 +163,7 @@ bool COMXVideo::SendDecoderConfig() + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -697,6 +741,7 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + void COMXVideo::Close() + { + CSingleLock lock (m_critSection); ++ dump_omx_buffer(NULL); + m_omx_tunnel_clock.Deestablish(); + m_omx_tunnel_decoder.Deestablish(); + if(m_deinterlace) +@@ -815,6 +860,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + int nRetry = 0; + while(true) + { ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -945,6 +991,7 @@ void COMXVideo::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index e46233a..9119877 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1367,6 +1367,10 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef TARGET_RASPBERRY_PI + list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); + #endif ++#ifdef TARGET_RASPBERRY_PI ++ list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); ++ list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); ++#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 4593665a9ce884639f1116b09a6d8f803a23f4b1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 18 Aug 2014 19:09:32 +0100 +Subject: [PATCH 43/95] rbp: Use new dispmanx function for vsync callbacks + +--- + xbmc/linux/RBP.cpp | 86 ++++++++++++++----------- + xbmc/linux/RBP.h | 7 +- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 +- + 3 files changed, 55 insertions(+), 42 deletions(-) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index 6514c2d..fe1df00 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -21,6 +21,7 @@ + #include "RBP.h" + #if defined(TARGET_RASPBERRY_PI) + ++#include + #include "settings/Settings.h" + #include "settings/AdvancedSettings.h" + #include "utils/log.h" +@@ -33,7 +34,7 @@ CRBP::CRBP() + m_omx_initialized = false; + m_DllBcmHost = new DllBcmHost(); + m_OMX = new COMXCore(); +- m_element = 0; ++ m_display = DISPMANX_NO_HANDLE; + } + + CRBP::~CRBP() +@@ -55,8 +56,7 @@ bool CRBP::Initialize() + + m_DllBcmHost->bcm_host_init(); + +- uint32_t vc_image_ptr; +- m_resource = vc_dispmanx_resource_create( VC_IMAGE_RGB565, 1, 1, &vc_image_ptr ); ++ //OpenDisplay(0 /*screen*/); + + m_omx_initialized = m_OMX->Initialize(); + if(!m_omx_initialized) +@@ -112,13 +112,24 @@ void CRBP::LogFirmwareVerison() + CLog::Log(LOGNOTICE, "Config:\n%s", response); + } + ++DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) ++{ ++ if (m_display == DISPMANX_NO_HANDLE) ++ m_display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ return m_display; ++} ++ ++void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display) ++{ ++ assert(display == m_display); ++ vc_dispmanx_display_close(m_display); ++ m_display = DISPMANX_NO_HANDLE; ++} ++ + void CRBP::GetDisplaySize(int &width, int &height) + { +- DISPMANX_DISPLAY_HANDLE_T display; + DISPMANX_MODEINFO_T info; +- +- display = vc_dispmanx_display_open( 0 /*screen*/ ); +- if (vc_dispmanx_display_get_info(display, &info) == 0) ++ if (vc_dispmanx_display_get_info(m_display, &info) == 0) + { + width = info.width; + height = info.height; +@@ -128,12 +139,10 @@ void CRBP::GetDisplaySize(int &width, int &height) + width = 0; + height = 0; + } +- vc_dispmanx_display_close(display ); + } + + unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool swap_red_blue, bool video_only) + { +- DISPMANX_DISPLAY_HANDLE_T display; + DISPMANX_RESOURCE_HANDLE_T resource; + VC_RECT_T rect; + unsigned char *image = NULL; +@@ -148,7 +157,6 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw + if (!pstride) + flags |= DISPMANX_SNAPSHOT_PACK; + +- display = vc_dispmanx_display_open( 0 /*screen*/ ); + stride = ((width + 15) & ~15) * 4; + image = new unsigned char [height * stride]; + +@@ -156,45 +164,44 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw + { + resource = vc_dispmanx_resource_create( VC_IMAGE_RGBA32, width, height, &vc_image_ptr ); + +- vc_dispmanx_snapshot(display, resource, (DISPMANX_TRANSFORM_T)flags); ++ assert(m_display != DISPMANX_NO_HANDLE); ++ 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 ); +- vc_dispmanx_display_close(display ); + } + if (pstride) + *pstride = stride; + return image; + } + +-void CRBP::WaitVsync(void) ++ ++static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg) + { +- DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( 0 /*screen*/ ); +- DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); +- +- VC_DISPMANX_ALPHA_T alpha = { (DISPMANX_FLAGS_ALPHA_T)(DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS), 120, /*alpha 0->255*/ 0 }; +- VC_RECT_T src_rect; +- VC_RECT_T dst_rect; +- vc_dispmanx_rect_set( &src_rect, 0, 0, 1 << 16, 1 << 16 ); +- vc_dispmanx_rect_set( &dst_rect, 0, 0, 1, 1 ); +- +- if (m_element) +- vc_dispmanx_element_remove( update, m_element ); +- +- m_element = vc_dispmanx_element_add( update, +- display, +- 2000, // layer +- &dst_rect, +- m_resource, +- &src_rect, +- DISPMANX_PROTECTION_NONE, +- &alpha, +- NULL, // clamp +- (DISPMANX_TRANSFORM_T)0 ); +- +- vc_dispmanx_update_submit_sync(update); +- vc_dispmanx_display_close( display ); ++ CEvent *sync = (CEvent *)arg; ++ sync->Set(); ++} ++ ++void CRBP::WaitVsync() ++{ ++ int s; ++ DISPMANX_DISPLAY_HANDLE_T m_display = vc_dispmanx_display_open( 0 /*screen*/ ); ++ if (m_display == DISPMANX_NO_HANDLE) ++ { ++ CLog::Log(LOGDEBUG, "CRBP::%s skipping while display closed", __func__); ++ return; ++ } ++ m_vsync.Reset(); ++ s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); ++ if (s == 0) ++ { ++ m_vsync.Wait(); ++ } ++ else assert(0); ++ s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); ++ assert(s == 0); ++ vc_dispmanx_display_close( m_display ); + } + + +@@ -206,6 +213,9 @@ void CRBP::Deinitialize() + if(m_omx_initialized) + m_OMX->Deinitialize(); + ++ if (m_display) ++ CloseDisplay(m_display); ++ + m_DllBcmHost->bcm_host_deinit(); + + if(m_initialized) +diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 606c24f..82146d6 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -38,6 +38,7 @@ + #include "DllBCM.h" + #include "OMXCore.h" + #include "threads/CriticalSection.h" ++#include "threads/Event.h" + + class CRBP + { +@@ -53,6 +54,8 @@ class CRBP + bool GetCodecMpg2() { return m_codec_mpg2_enabled; } + 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); +@@ -74,10 +77,10 @@ class CRBP + bool m_codec_mpg2_enabled; + bool m_codec_wvc1_enabled; + COMXCore *m_OMX; +- DISPMANX_RESOURCE_HANDLE_T m_resource; +- DISPMANX_ELEMENT_HANDLE_T m_element; + class DllLibOMXCore; + CCriticalSection m_critSection; ++ DISPMANX_DISPLAY_HANDLE_T m_display; ++ CEvent m_vsync; + }; + + extern CRBP g_RBP; +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 335f6d5..7d9b0d3 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -307,7 +307,7 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + m_desktopRes = res; + } + +- m_dispman_display = m_DllBcmHost->vc_dispmanx_display_open(0); ++ m_dispman_display = g_RBP.OpenDisplay(0); + + m_width = res.iWidth; + m_height = res.iHeight; +@@ -578,7 +578,7 @@ void CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow() + + if (m_dispman_display != DISPMANX_NO_HANDLE) + { +- m_DllBcmHost->vc_dispmanx_display_close(m_dispman_display); ++ g_RBP.CloseDisplay(m_dispman_display); + m_dispman_display = DISPMANX_NO_HANDLE; + } + DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); + +From 831431010bbb8a673005a4cd503d6f5db5718bc0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Nov 2014 17:16:54 +0000 +Subject: [PATCH 44/95] Revert "[omxplayer] Add ability to dump out audio/video + data for later debugging" + +This reverts commit 417416bd29d00f1b42c77488d06e9e6840b8c4f4. +--- + .../resource.language.en_gb/resources/strings.po | 10 ----- + xbmc/commons/ilog.h | 2 - + xbmc/cores/omxplayer/OMXAudio.cpp | 49 ---------------------- + xbmc/cores/omxplayer/OMXVideo.cpp | 47 --------------------- + xbmc/settings/AdvancedSettings.cpp | 4 -- + 5 files changed, 112 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index d8563fb..3909203 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2913,16 +2913,6 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + +-#: xbmc/settings/AdvancedSettings.cpp +-msgctxt "#698" +-msgid "Dump video frames to debug file" +-msgstr "" +- +-#: xbmc/settings/AdvancedSettings.cpp +-msgctxt "#699" +-msgid "Dump audio frames to debug file" +-msgstr "" +- + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index 4f8926c..e4ffb5e 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,8 +54,6 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) +-#define LOGDUMPVIDEO (1 << (LOGMASKBIT + 17)) +-#define LOGDUMPAUDIO (1 << (LOGMASKBIT + 18)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 0b8fd69..602d2fa 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -56,49 +56,6 @@ using namespace std; + #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024) + static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3}; + +-//#define DEBUG_PLAYBACK +-static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) +-{ +- if (!(g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) +- return; +- static FILE *fp; +- if (!omx_buffer) +- { +- if (fp) +- { +- fclose(fp); +- fp = NULL; +- } +- return; +- } +- if (!fp) +- { +- char filename[1024]; +- strcpy(filename, g_advancedSettings.m_logFolder.c_str()); +- strcat(filename, "audio.dat"); +-#ifdef DEBUG_PLAYBACK +- fp = fopen(filename, "rb"); +-#else +- fp = fopen(filename, "wb"); +-#endif +- } +- if (fp) +- { +-#ifdef DEBUG_PLAYBACK +- OMX_BUFFERHEADERTYPE omx = {0}; +- int s = fread(&omx, sizeof omx, 1, fp); +- omx_buffer->nFilledLen = omx.nFilledLen; +- omx_buffer->nFlags = omx.nFlags; +- omx_buffer->nTimeStamp = omx.nTimeStamp; +- if (s==1) +- fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#else +- if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) +- fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#endif +- } +-} +- + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// +@@ -911,7 +868,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -944,7 +900,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -981,8 +936,6 @@ bool COMXAudio::Deinitialize() + { + CSingleLock lock (m_critSection); + +- dump_omx_buffer(NULL); +- + if ( m_omx_tunnel_clock_analog.IsInitialized() ) + m_omx_tunnel_clock_analog.Deestablish(); + if ( m_omx_tunnel_clock_hdmi.IsInitialized() ) +@@ -1273,7 +1226,6 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt + int nRetry = 0; + while(true) + { +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -1521,7 +1473,6 @@ void COMXAudio::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 4489546..55e16c4 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -65,49 +65,6 @@ + + #define MAX_TEXT_LENGTH 1024 + +-//#define DEBUG_PLAYBACK +-static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) +-{ +- if (!(g_advancedSettings.CanLogComponent(LOGDUMPVIDEO))) +- return; +- static FILE *fp; +- if (!omx_buffer) +- { +- if (fp) +- { +- fclose(fp); +- fp = NULL; +- } +- return; +- } +- if (!fp) +- { +- char filename[1024]; +- strcpy(filename, g_advancedSettings.m_logFolder.c_str()); +- strcat(filename, "video.dat"); +-#ifdef DEBUG_PLAYBACK +- fp = fopen(filename, "rb"); +-#else +- fp = fopen(filename, "wb"); +-#endif +- } +- if (fp) +- { +-#ifdef DEBUG_PLAYBACK +- OMX_BUFFERHEADERTYPE omx = {0}; +- int s = fread(&omx, sizeof omx, 1, fp); +- omx_buffer->nFilledLen = omx.nFilledLen; +- omx_buffer->nFlags = omx.nFlags; +- omx_buffer->nTimeStamp = omx.nTimeStamp; +- if (s==1) +- fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#else +- if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) +- fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); +-#endif +- } +-} +- + COMXVideo::COMXVideo() : m_video_codec_name("") + { + m_is_open = false; +@@ -163,7 +120,6 @@ bool COMXVideo::SendDecoderConfig() + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -741,7 +697,6 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + void COMXVideo::Close() + { + CSingleLock lock (m_critSection); +- dump_omx_buffer(NULL); + m_omx_tunnel_clock.Deestablish(); + m_omx_tunnel_decoder.Deestablish(); + if(m_deinterlace) +@@ -860,7 +815,6 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + int nRetry = 0; + while(true) + { +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err == OMX_ErrorNone) + { +@@ -991,7 +945,6 @@ void COMXVideo::SubmitEOS() + + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN; + +- dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 9119877..e46233a 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1367,10 +1367,6 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef TARGET_RASPBERRY_PI + list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); + #endif +-#ifdef TARGET_RASPBERRY_PI +- list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); +- list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); +-#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 1ff0d9e4bb953f06cf8c1c9c5a28839e1fd3b1b6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 45/95] [omxplayer] Add ability to dump out audio/video data + for later debugging + +--- + .../resource.language.en_gb/resources/strings.po | 10 ++++ + xbmc/commons/ilog.h | 2 + + xbmc/cores/dvdplayer/DVDPlayer.cpp | 63 ++++++++++++++++++++++ + xbmc/settings/AdvancedSettings.cpp | 4 ++ + 4 files changed, 79 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 3909203..d8563fb 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -2913,6 +2913,16 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#698" ++msgid "Dump video frames to debug file" ++msgstr "" ++ ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#699" ++msgid "Dump audio frames to debug file" ++msgstr "" ++ + #empty strings from id 681 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index e4ffb5e..4f8926c 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,6 +54,8 @@ + #define LOGCEC (1 << (LOGMASKBIT + 9)) + #define LOGVIDEO (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT + 16)) ++#define LOGDUMPVIDEO (1 << (LOGMASKBIT + 17)) ++#define LOGDUMPAUDIO (1 << (LOGMASKBIT + 18)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 3180fe9..25b0b68 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -96,6 +96,61 @@ + using namespace std; + using namespace PVR; + ++//#define DEBUG_PLAYBACK ++static void dump_packet(DemuxPacket *packet, bool video, bool audio) ++{ ++ static CCriticalSection m_section; ++ static FILE *fp_video, *fp_audio; ++ if ((!video || !g_advancedSettings.CanLogComponent(LOGDUMPVIDEO)) && ++ (!audio || !g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) ++ return; ++ const char *fname = video ? "video.dat" : "audio.dat"; ++ FILE *&fp = video ? fp_video : fp_audio; ++ CSingleLock lock(m_section); ++ if (!packet) ++ { ++ if (fp) ++ { ++ CLog::Log(LOGNOTICE, "%s:: Closing file %p", __func__, fp); ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, fname); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ CLog::Log(LOGNOTICE, "%s:: Opening file %s = %p", __func__, filename, fp); ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ DemuxPacket p = {0}; ++ int s = fread(&p, sizeof p, 1, fp); ++ if (s==1) ++ { ++ packet->iSize = p.iSize; ++ packet->dts = p.dts; ++ packet->pts = p.pts; ++ _aligned_free(packet->pData); ++ packet->pData = (uint8_t*)_aligned_malloc(packet->iSize + FF_INPUT_BUFFER_PADDING_SIZE, 16); ++ fread(packet->pData, packet->iSize, 1, fp); ++ } ++#else ++ if (fwrite(packet, sizeof *packet, 1, fp) == 1) ++ fwrite(packet->pData, packet->iSize, 1, fp); ++#endif ++ } ++} ++ ++ + void CSelectionStreams::Clear(StreamType type, StreamSource source) + { + CSingleLock lock(m_section); +@@ -976,6 +1031,12 @@ bool CDVDPlayer::ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream) + return true; + } + ++ if(m_pDemuxer) ++ { ++ stream = m_pDemuxer->GetStream(packet->iStreamId); ++ if (stream) ++ dump_packet(packet, CheckIsCurrent(m_CurrentVideo, stream, packet), CheckIsCurrent(m_CurrentAudio, stream, packet)); ++ } + UpdateCorrection(packet, m_offset_pts); + + if(packet->iStreamId < 0) +@@ -3453,6 +3514,8 @@ bool CDVDPlayer::CloseStream(CCurrentStream& current, bool bWaitForBuffers) + if(bWaitForBuffers) + SetCaching(CACHESTATE_DONE); + ++ dump_packet(NULL, current.player == DVDPLAYER_VIDEO, current.player == DVDPLAYER_AUDIO); ++ + IDVDStreamPlayer* player = GetStreamPlayer(current.player); + if(player) + player->CloseStream(bWaitForBuffers); +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index e46233a..9119877 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1367,6 +1367,10 @@ void CAdvancedSettings::SettingOptionsLoggingComponentsFiller(const CSetting *se + #ifdef TARGET_RASPBERRY_PI + list.push_back(std::make_pair(g_localizeStrings.Get(697), LOGOMXPLAYER)); + #endif ++#ifdef TARGET_RASPBERRY_PI ++ list.push_back(std::make_pair(g_localizeStrings.Get(698), LOGDUMPVIDEO)); ++ list.push_back(std::make_pair(g_localizeStrings.Get(699), LOGDUMPAUDIO)); ++#endif + } + + void CAdvancedSettings::setExtraLogLevel(const std::vector &components) + +From 42b63f770f1cb1ca505bf37d133faede51e9e64a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 29 Nov 2014 15:25:16 +0000 +Subject: [PATCH 46/95] [rbp] hack: wait for splash to complete before changing + hdmi mode + +--- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 49 +++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index 7d9b0d3..d388373 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -217,12 +217,61 @@ int CEGLNativeTypeRaspberryPI::AddUniqueResolution(RESOLUTION_INFO &res, std::ve + } + #endif + ++#include ++ ++pid_t proc_find(const char* name) ++{ ++ DIR* dir; ++ struct dirent* ent; ++ char buf[512]; ++ ++ long pid; ++ char pname[100] = {0,}; ++ char state; ++ FILE *fp=NULL; ++ ++ if (!(dir = opendir("/proc"))) { ++ perror("can't open /proc"); ++ return -1; ++ } ++ ++ while((ent = readdir(dir)) != NULL) { ++ long lpid = atol(ent->d_name); ++ if(lpid < 0) ++ continue; ++ snprintf(buf, sizeof(buf), "/proc/%ld/stat", lpid); ++ fp = fopen(buf, "r"); ++ ++ if (fp) { ++ if ( (fscanf(fp, "%ld (%[^)]) %c", &pid, pname, &state)) != 3 ){ ++ printf("fscanf failed \n"); ++ fclose(fp); ++ closedir(dir); ++ return -1; ++ } ++ if (!strcmp(pname, name)) { ++ fclose(fp); ++ closedir(dir); ++ return (pid_t)lpid; ++ } ++ fclose(fp); ++ } ++ } ++ ++ closedir(dir); ++ return -1; ++} ++ ++ + bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + { + #if defined(TARGET_RASPBERRY_PI) + if(!m_DllBcmHost || !m_nativeWindow) + return false; + ++ while (proc_find("hello_video.bin") >= 0) ++ Sleep(100); ++ + DestroyDispmaxWindow(); + + if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags)) + +From 43974c9247ca19ed7473ec61c3b4178e3b4d1e18 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 5 Oct 2014 14:05:25 +0100 +Subject: [PATCH 47/95] [PiSink] Allow audio output latency to be set in + settings + +--- + addons/resource.language.en_gb/resources/strings.po | 15 +++++++++++++++ + system/settings/rbp.xml | 12 ++++++++++++ + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 13 ++++++++----- + xbmc/cores/AudioEngine/Sinks/AESinkPi.h | 1 + + 4 files changed, 36 insertions(+), 5 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index d8563fb..7c3aa66 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16634,3 +16634,18 @@ msgstr "" + msgctxt "#38052" + msgid "Remote button press release time (ms)" + msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38100" ++msgid "Audio output latency" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38101" ++msgid "Increase this to protect against underruns, reduce to have lower latency gui sounds" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38102" ++msgid "%i ms" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index f7cb75e..825a2e7 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -90,6 +90,18 @@ + + 101 + ++ ++ 3 ++ 100 ++ ++ 50 ++ 50 ++ 300 ++ ++ ++ 38102 ++ ++ + + + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 3cb6bfb..363b7d5 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -35,7 +35,6 @@ + #define CLASSNAME "CAESinkPi" + + #define NUM_OMX_BUFFERS 2 +-#define AUDIO_PLAYBUFFER (0.1) // 100ms + + static const unsigned int PassthroughSampleRates[] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000 }; + +@@ -43,6 +42,7 @@ CAEDeviceInfo CAESinkPi::m_info; + + CAESinkPi::CAESinkPi() : + m_sinkbuffer_sec_per_byte(0), ++ m_latency(0), + m_Initialized(false), + m_submitted(0), + m_omx_output(NULL) +@@ -190,6 +190,9 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_initDevice = device; + m_initFormat = format; + ++ m_latency = CSettings::Get().GetInt("audiooutput.latency") * 1e-3; ++ m_latency = std::max(m_latency, 50e-3); ++ + // analogue only supports stereo + if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") + { +@@ -206,7 +209,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + unsigned int sample_size = CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3; + format.m_frameSize = sample_size * channels; + format.m_sampleRate = std::max(8000U, std::min(192000U, format.m_sampleRate)); +- format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; ++ format.m_frames = format.m_sampleRate * m_latency / NUM_OMX_BUFFERS; + format.m_frameSamples = format.m_frames * channels; + + SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough)); +@@ -421,7 +424,7 @@ void CAESinkPi::GetDelay(AEDelayStatus& status) + + double CAESinkPi::GetCacheTotal() + { +- return AUDIO_PLAYBUFFER; ++ return m_latency; + } + + unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned int offset) +@@ -469,8 +472,8 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned + m_submitted++; + GetDelay(status); + delay = status.GetDelay(); +- if (delay > AUDIO_PLAYBUFFER) +- Sleep((int)(1000.0f * (delay - AUDIO_PLAYBUFFER))); ++ if (delay > m_latency) ++ Sleep((int)(1000.0f * (delay - m_latency))); + return frames; + } + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +index 5c57999..cac5051 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +@@ -53,6 +53,7 @@ class CAESinkPi : public IAESink + AEAudioFormat m_initFormat; + AEAudioFormat m_format; + double m_sinkbuffer_sec_per_byte; ++ double m_latency; + static CAEDeviceInfo m_info; + bool m_Initialized; + uint32_t m_submitted; + +From bd5e47c61ed2575765502ae884348f57ce0189af Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 11 Dec 2014 17:00:57 +0000 +Subject: [PATCH 48/95] Fix for UI not showing both extractflags and + extractthumb + +--- + addons/resource.language.en_gb/resources/strings.po | 11 ++++++++--- + system/settings/rbp.xml | 4 ---- + system/settings/settings.xml | 10 +++++----- + 3 files changed, 13 insertions(+), 12 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 7c3aa66..af96b08 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -10974,7 +10974,7 @@ msgstr "" + + #: system/settings/settings.xml + msgctxt "#20433" +-msgid "Extract thumbnails and video information" ++msgid "Extract video information from files" + msgstr "" + + #: xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp +@@ -14501,7 +14501,7 @@ msgstr "" + #. Description of setting "Videos -> File lists -> Extract thumbnails and video information" with label #20433 + #: system/settings/settings.xml + msgctxt "#36178" +-msgid "Extract thumbnails and metadata information such as codec and aspect ratio from videos." ++msgid "Extract metadata information such as codec and aspect ratio from videos." + msgstr "" + + #. Description of setting "Videos -> File lists -> Replace file names with library titles" with label #20419 +@@ -14513,7 +14513,7 @@ msgstr "" + #. Description of setting "Videos -> File lists -> Extract thumbnails and video information" with label #20433 + #: system/settings/settings.xml + msgctxt "#36180" +-msgid "Extract thumbnails and information, such as codecs and aspect ratio, to display in Library Mode." ++msgid "Extract thumbnails, to display in Library Mode." + msgstr "" + + #: system/settings/settings.xml +@@ -16649,3 +16649,8 @@ msgstr "" + msgctxt "#38102" + msgid "%i ms" + msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38015" ++msgid "Extract thumbnails from video files" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 825a2e7..a3b6f6f 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -37,10 +37,6 @@ + + false + +- +- +- +- + + false + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index a40ecb5..5a6c12f 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -899,23 +899,23 @@ + + + +- ++ + 1 + true + + +- ++ + 1 + true + + +- ++ + 1 + true + + +- +- 4 ++ ++ 1 + true + + + +From c865ff570615b4059b737a4ca3e5105da7d11f69 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Thu, 11 Sep 2014 21:30:43 +0200 +Subject: [PATCH 49/95] Disable autoscrolling while on screensaver and while + opening streams. + +--- + xbmc/Application.cpp | 10 ++++++++++ + xbmc/Application.h | 2 ++ + xbmc/guilib/GUIFadeLabelControl.cpp | 4 +++- + xbmc/guilib/GUIFont.cpp | 4 ++++ + xbmc/guilib/GUILabel.cpp | 4 +++- + xbmc/guilib/GUITextBox.cpp | 3 ++- + 6 files changed, 24 insertions(+), 3 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 9c6f75f..fb38cd3 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -4930,3 +4930,13 @@ bool CApplication::NotifyActionListeners(const CAction &action) const + + return false; + } ++ ++bool CApplication::ScreenSaverDisablesAutoScrolling() ++{ ++ bool onBlackDimScreenSaver = IsInScreenSaver() && m_screenSaver && ++ (m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || ++ m_screenSaver->ID() == "screensaver.xbmc.builtin.dim"); ++ bool openingStreams = m_pPlayer->IsPlaying() && g_windowManager.IsWindowActive(WINDOW_DIALOG_BUSY); ++ ++ return onBlackDimScreenSaver || openingStreams; ++} +diff --git a/xbmc/Application.h b/xbmc/Application.h +index ec5dfac..1b9a4bf 100644 +--- a/xbmc/Application.h ++++ b/xbmc/Application.h +@@ -389,6 +389,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs + */ + void UnregisterActionListener(IActionListener *listener); + ++ bool ScreenSaverDisablesAutoScrolling(); ++ + protected: + virtual bool OnSettingsSaving() const; + +diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp +index 9eadbe4..b2b5f13 100644 +--- a/xbmc/guilib/GUIFadeLabelControl.cpp ++++ b/xbmc/guilib/GUIFadeLabelControl.cpp +@@ -20,6 +20,8 @@ + + #include "GUIFadeLabelControl.h" + ++#include "Application.h" ++ + using namespace std; + + CGUIFadeLabelControl::CGUIFadeLabelControl(int parentID, int controlID, float posX, float posY, float width, float height, const CLabelInfo& labelInfo, bool scrollOut, unsigned int timeToDelayAtEnd, bool resetOnLabelChange) +@@ -102,7 +104,7 @@ void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &d + m_lastLabel = m_currentLabel; + } + +- if (m_infoLabels.size() > 1 || !m_shortText) ++ if ((m_infoLabels.size() > 1 || !m_shortText) && !g_application.ScreenSaverDisablesAutoScrolling()) + { // have scrolling text + MarkDirtyRegion(); + +diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp +index 7f11089..1192b74 100644 +--- a/xbmc/guilib/GUIFont.cpp ++++ b/xbmc/guilib/GUIFont.cpp +@@ -22,6 +22,7 @@ + #include "GUIFontTTF.h" + #include "GraphicContext.h" + ++#include "Application.h" + #include "threads/SingleLock.h" + #include "utils/TimeUtils.h" + #include "utils/MathUtils.h" +@@ -128,6 +129,9 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo) + // If the string is smaller than the viewport, then it may be plotted even + // more times than that. + // ++ if (g_application.ScreenSaverDisablesAutoScrolling()) ++ return false; ++ + if (scrollInfo.waitTime) + { + scrollInfo.waitTime--; +diff --git a/xbmc/guilib/GUILabel.cpp b/xbmc/guilib/GUILabel.cpp +index 759ac09..bed6ad2 100644 +--- a/xbmc/guilib/GUILabel.cpp ++++ b/xbmc/guilib/GUILabel.cpp +@@ -21,6 +21,8 @@ + #include "GUILabel.h" + #include + ++#include "Application.h" ++ + CGUILabel::CGUILabel(float posX, float posY, float width, float height, const CLabelInfo& labelInfo, CGUILabel::OVER_FLOW overflow) + : m_label(labelInfo) + , m_textLayout(labelInfo.font, overflow == OVER_FLOW_WRAP, height) +@@ -104,7 +106,7 @@ void CGUILabel::Render() + color_t color = GetColor(); + bool renderSolid = (m_color == COLOR_DISABLED); + bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues +- if (overFlows && m_scrolling && !renderSolid) ++ if (overFlows && m_scrolling && !renderSolid && !g_application.ScreenSaverDisablesAutoScrolling()) + m_textLayout.RenderScrolling(m_renderRect.x1, m_renderRect.y1, m_label.angle, color, m_label.shadowColor, 0, m_renderRect.Width(), m_scrollInfo); + else + { +diff --git a/xbmc/guilib/GUITextBox.cpp b/xbmc/guilib/GUITextBox.cpp +index 0d5b3f7..6d23024 100644 +--- a/xbmc/guilib/GUITextBox.cpp ++++ b/xbmc/guilib/GUITextBox.cpp +@@ -23,6 +23,7 @@ + #include "utils/XBMCTinyXML.h" + #include "utils/MathUtils.h" + #include "utils/StringUtils.h" ++#include "Application.h" + + #include + +@@ -134,7 +135,7 @@ void CGUITextBox::Process(unsigned int currentTime, CDirtyRegionList &dirtyregio + // update our auto-scrolling as necessary + if (m_autoScrollTime && m_lines.size() > m_itemsPerPage) + { +- if (!m_autoScrollCondition || m_autoScrollCondition->Get()) ++ if ((!m_autoScrollCondition || m_autoScrollCondition->Get()) && !g_application.ScreenSaverDisablesAutoScrolling()) + { + if (m_lastRenderTime) + m_autoScrollDelayTime += currentTime - m_lastRenderTime; + +From 155e82d4d93530d221a68eafcf8c4940e84cfd95 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 13 Dec 2014 18:35:20 +0000 +Subject: [PATCH 50/95] [demuxer] Avoid memcpy on every demuxer packet + +Avoids an unnecessary memcpy on every demuxer packet which for +high bitrate videos can be significant. +--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 14 +++++++++----- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h | 3 +++ + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp | 7 ++++++- + 3 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 643c219..2f70412 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -742,7 +742,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + { + if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) + { +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0); + break; + } + } +@@ -751,7 +751,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + bReturnEmpty = true; + } + else +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0); + } + else + bReturnEmpty = true; +@@ -793,9 +793,13 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + // copy contents into our own packet + pPacket->iSize = m_pkt.pkt.size; + +- // maybe we can avoid a memcpy here by detecting where pkt.destruct is pointing too? + if (m_pkt.pkt.data) +- memcpy(pPacket->pData, m_pkt.pkt.data, pPacket->iSize); ++ { ++ pPacket->pData = m_pkt.pkt.data; ++ // so we can free AVPacket when DemuxPacket is freed ++ pPacket->pkt = new AVPacket(m_pkt.pkt); ++ } ++ + + pPacket->pts = ConvertTimestamp(m_pkt.pkt.pts, stream->time_base.den, stream->time_base.num); + pPacket->dts = ConvertTimestamp(m_pkt.pkt.dts, stream->time_base.den, stream->time_base.num); +@@ -830,7 +834,7 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + pPacket->iStreamId = m_pkt.pkt.stream_index; + } + m_pkt.result = -1; +- av_free_packet(&m_pkt.pkt); ++ memset(&m_pkt.pkt, 0, sizeof(AVPacket)); + } + } + } // end of lock scope +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h +index d64fbb3..012a7d1 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h +@@ -23,6 +23,8 @@ + #define DMX_SPECIALID_STREAMINFO -10 + #define DMX_SPECIALID_STREAMCHANGE -11 + ++struct AVPacket; ++ + typedef struct DemuxPacket + { + unsigned char* pData; // data +@@ -33,4 +35,5 @@ + double pts; // pts in DVD_TIME_BASE + double dts; // dts in DVD_TIME_BASE + double duration; // duration in DVD_TIME_BASE if available ++ AVPacket *pkt; // to allow packet to be freed + } DemuxPacket; +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp +index ab298b2..10c5ee0 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp +@@ -34,7 +34,12 @@ void CDVDDemuxUtils::FreeDemuxPacket(DemuxPacket* pPacket) + if (pPacket) + { + try { +- if (pPacket->pData) _aligned_free(pPacket->pData); ++ if (pPacket->pkt) ++ { ++ av_free_packet(pPacket->pkt); ++ delete pPacket->pkt; ++ } ++ else if (pPacket->pData) _aligned_free(pPacket->pData); + delete pPacket; + } + catch(...) { + +From cf6da32e13b18eb76794134436b91ed44358f9a6 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:27:59 +0100 +Subject: [PATCH 51/95] - added setting for allowing to hide watched + movies/episodes/musicvideos in the recently added lists of the home screen + +--- + addons/resource.language.en_gb/resources/strings.po | 16 ++++++++++++++-- + system/settings/settings.xml | 5 +++++ + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index af96b08..a4c078c 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -11142,7 +11142,13 @@ msgctxt "#20469" + msgid "Keep current set (%s)" + msgstr "" + +-#empty strings from id 20470 to 21329 ++#. Label of setting "Videos -> Library -> Hide watched videos in recently added list (home screen)" ++#: system/settings/settings.xml ++msgctxt "#20470" ++msgid "Hide watched videos in recently added list (home screen)" ++msgstr "" ++ ++#empty strings from id 20471 to 21329 + #up to 21329 is reserved for the video db !! ! + + #: system/settings/settings.xml +@@ -15958,7 +15964,13 @@ msgctxt "#36435" + msgid "Use DVDPlayer for decoding of video files with MMAL acceleration." + msgstr "" + +-#empty strings from id 36436 to 36499 ++#. Description of setting "Videos -> Library -> Hide watched videos in recently added list." ++#: system/settings/settings.xml ++msgctxt "#36436" ++msgid "If enabled all watched items in the recently added list on the home screen will be hidden. This includes movies, episodes and musicvideos. The effect depends on the used skin and its settings." ++msgstr "" ++ ++#empty strings from id 36437 to 36499 + #end reservation + + #. label of a setting for the stereoscopic 3D mode of the GUI that is/should be applied +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 5a6c12f..92f767d 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -465,6 +465,11 @@ + false + + ++ ++ 1 ++ true ++ ++ + + + + +From 405d02a63d8819fad8bc026d55c02309a4d824e5 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:28:36 +0100 +Subject: [PATCH 52/95] - evaluate the setting for hiding watched + movies/episodes/musicvideos in recently added job (should influence + homescreen of skins only) + +--- + xbmc/utils/RecentlyAddedJob.cpp | 10 +++++----- + xbmc/video/VideoDatabase.cpp | 27 ++++++++++++++++++++++++--- + xbmc/video/VideoDatabase.h | 6 +++--- + 3 files changed, 32 insertions(+), 11 deletions(-) + +diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp +index 1f8ec36..de45783 100644 +--- a/xbmc/utils/RecentlyAddedJob.cpp ++++ b/xbmc/utils/RecentlyAddedJob.cpp +@@ -31,6 +31,7 @@ + #include "utils/Variant.h" + #include "utils/StringUtils.h" + #include "settings/AdvancedSettings.h" ++#include "settings/Settings.h" + #include "music/MusicThumbLoader.h" + #include "video/VideoThumbLoader.h" + +@@ -57,8 +58,8 @@ bool CRecentlyAddedJob::UpdateVideo() + loader.OnLoaderStart(); + + videodatabase.Open(); +- +- if (videodatabase.GetRecentlyAddedMoviesNav("videodb://recentlyaddedmovies/", items, NUM_ITEMS)) ++ bool hideWatched = CSettings::Get().GetBool("videolibrary.hiderecentlywatchedvideos"); ++ if (videodatabase.GetRecentlyAddedMoviesNav("videodb://recentlyaddedmovies/", items, NUM_ITEMS, hideWatched)) + { + for (; i < items.Size(); ++i) + { +@@ -97,8 +98,7 @@ bool CRecentlyAddedJob::UpdateVideo() + + i = 0; + CFileItemList TVShowItems; +- +- if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://recentlyaddedepisodes/", TVShowItems, NUM_ITEMS)) ++ if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://recentlyaddedepisodes/", TVShowItems, NUM_ITEMS, hideWatched)) + { + for (; i < TVShowItems.Size(); ++i) + { +@@ -151,7 +151,7 @@ bool CRecentlyAddedJob::UpdateVideo() + i = 0; + CFileItemList MusicVideoItems; + +- if (videodatabase.GetRecentlyAddedMusicVideosNav("videodb://recentlyaddedmusicvideos/", MusicVideoItems, NUM_ITEMS)) ++ if (videodatabase.GetRecentlyAddedMusicVideosNav("videodb://recentlyaddedmusicvideos/", MusicVideoItems, NUM_ITEMS, hideWatched)) + { + for (; i < MusicVideoItems.Size(); ++i) + { +diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp +index 96fa5fd..ca6f0f3 100644 +--- a/xbmc/video/VideoDatabase.cpp ++++ b/xbmc/video/VideoDatabase.cpp +@@ -6552,27 +6552,48 @@ bool CVideoDatabase::GetMusicVideosNav(const std::string& strBaseDir, CFileItemL + return GetMusicVideosByWhere(videoUrl.ToString(), filter, items, true, sortDescription); + } + +-bool CVideoDatabase::GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit) ++bool CVideoDatabase::GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit, bool hideWatched) + { + Filter filter; + filter.order = "dateAdded desc, idMovie desc"; + filter.limit = PrepareSQL("%u", limit ? limit : g_advancedSettings.m_iVideoLibraryRecentlyAddedItems); ++ ++ if (hideWatched) ++ { ++ filter.AppendWhere("playCount <= 0");// only query unwatched items ++ filter.AppendWhere("playCount IS NULL", false); ++ } ++ + return GetMoviesByWhere(strBaseDir, filter, items); + } + +-bool CVideoDatabase::GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit) ++bool CVideoDatabase::GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit, bool hideWatched) + { + Filter filter; + filter.order = "dateAdded desc, idEpisode desc"; + filter.limit = PrepareSQL("%u", limit ? limit : g_advancedSettings.m_iVideoLibraryRecentlyAddedItems); ++ ++ if (hideWatched) ++ { ++ filter.AppendWhere("playCount <= 0");// only query unwatched items ++ filter.AppendWhere("playCount IS NULL", false); ++ } ++ + return GetEpisodesByWhere(strBaseDir, filter, items, false); + } + +-bool CVideoDatabase::GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit) ++bool CVideoDatabase::GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit, bool hideWatched) + { + Filter filter; + filter.order = "dateAdded desc, idMVideo desc"; + filter.limit = PrepareSQL("%u", limit ? limit : g_advancedSettings.m_iVideoLibraryRecentlyAddedItems); ++ ++ if (hideWatched) ++ { ++ filter.AppendWhere("playCount <= 0");// only query unwatched items ++ filter.AppendWhere("playCount IS NULL", false); ++ } ++ + return GetMusicVideosByWhere(strBaseDir, filter, items); + } + +diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h +index ca62f23..b905e48 100644 +--- a/xbmc/video/VideoDatabase.h ++++ b/xbmc/video/VideoDatabase.h +@@ -683,9 +683,9 @@ class CVideoDatabase : public CDatabase + bool GetEpisodesNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idShow=-1, int idSeason=-1, const SortDescription &sortDescription = SortDescription()); + bool GetMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idArtist=-1, int idDirector=-1, int idStudio=-1, int idAlbum=-1, int idTag=-1, const SortDescription &sortDescription = SortDescription()); + +- bool GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0); +- bool GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0); +- bool GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0); ++ bool GetRecentlyAddedMoviesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, bool hideWatched=false); ++ bool GetRecentlyAddedEpisodesNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, bool hideWatched=false); ++ bool GetRecentlyAddedMusicVideosNav(const std::string& strBaseDir, CFileItemList& items, unsigned int limit=0, bool hideWatched=false); + + bool HasContent(); + bool HasContent(VIDEODB_CONTENT_TYPE type); + +From 8361c453c28e8ee81a663a0ba071c690863b85f6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Jan 2015 21:48:31 +0000 +Subject: [PATCH 53/95] [omximage] Increase timeout - this is sometimes hit + +--- + xbmc/cores/omxplayer/OMXImage.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index 86a683a..54a52a7 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1885,7 +1885,7 @@ bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, uns + } + if (m_encoded_buffer) + { +- omx_err = m_omx_encoder.WaitForOutputDone(1000); ++ 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)\n", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); + +From 6b349309ea57c3b9d997a3766566e554d9fba658 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 24 Jan 2015 17:34:04 +0000 +Subject: [PATCH 54/95] temp: Some hacks to help profiling + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 5 +++++ + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 4 ++-- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++ + 3 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index 7c68e1c..6a2fee9 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -564,6 +564,7 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg) + CActiveAEStream *stream; + streamMsg = (MsgStreamNew*)msg->data; + stream = CreateStream(streamMsg); ++ CLog::Log(LOGNOTICE, "ActiveAE::%s - NEWSTREAM %p %p", __FUNCTION__, streamMsg, stream); + if(stream) + { + msg->Reply(CActiveAEDataProtocol::ACC, &stream, sizeof(CActiveAEStream*)); +@@ -1228,6 +1229,7 @@ CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg) + } + if (hasRawStream || (hasStream && AE_IS_RAW(streamMsg->format.m_dataFormat))) + { ++ CLog::Log(LOGNOTICE, "CActiveAE::CreateStream - raw"); + return NULL; + } + +@@ -1256,6 +1258,7 @@ CActiveAEStream* CActiveAE::CreateStream(MsgStreamNew *streamMsg) + + m_streams.push_back(stream); + ++ CLog::Log(LOGNOTICE, "CActiveAE::CreateStream - %p", stream); + return stream; + } + +@@ -2750,11 +2753,13 @@ IAEStream *CActiveAE::MakeStream(enum AEDataFormat dataFormat, unsigned int samp + msg.options = options; + + Message *reply; ++ CLog::Log(LOGNOTICE, "ActiveAE::%s - about to create stream", __FUNCTION__); + if (m_dataPort.SendOutMessageSync(CActiveAEDataProtocol::NEWSTREAM, + &reply,10000, + &msg, sizeof(MsgStreamNew))) + { + bool success = reply->signal == CActiveAEControlProtocol::ACC; ++ CLog::Log(LOGNOTICE, "ActiveAE::%s - created stream : %d", __FUNCTION__, success); + if (success) + { + CActiveAEStream *stream = *(CActiveAEStream**)reply->data; +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index a064da5..ebc4458 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -36,7 +36,7 @@ + #define CLASSNAME "CMMALRenderer" + + #ifdef _DEBUG +-#define MMAL_DEBUG_VERBOSE ++//#define MMAL_DEBUG_VERBOSE + #endif + + static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) +@@ -372,7 +372,7 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + #endif + omvb->Acquire(); + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); +- } else assert(0); ++ } //else assert(0); + } + else if (m_format == RENDER_FMT_YUV420P) + { +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 5832c58..76c708d 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -162,6 +162,8 @@ CDVDPlayerVideo::CDVDPlayerVideo( CDVDClock* pClock + + CDVDPlayerVideo::~CDVDPlayerVideo() + { ++ CLog::Log(LOGNOTICE, "drop:%d skip:%d", m_iDroppedFrames, g_renderManager.GetSkippedFrames()); ++ + StopThread(); + g_VideoReferenceClock.Stop(); + } + +From 745d0770dda43582b22d82eea82a23157bd2018e Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Wed, 4 Feb 2015 22:32:03 +0100 +Subject: [PATCH 55/95] NFSFile: Chank ChunkSize to 1MB + +--- + xbmc/filesystem/NFSFile.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/filesystem/NFSFile.h b/xbmc/filesystem/NFSFile.h +index 4c01e4e..7afa6b8 100644 +--- a/xbmc/filesystem/NFSFile.h ++++ b/xbmc/filesystem/NFSFile.h +@@ -148,7 +148,7 @@ namespace XFILE + //implement iocontrol for seek_possible for preventing the stat in File class for + //getting this info ... + virtual int IoControl(EIoControl request, void* param){ if(request == IOCTRL_SEEK_POSSIBLE) return 1;return -1;}; +- virtual int GetChunkSize() {return 1;} ++ virtual int GetChunkSize() {return 1024*1024;} + + virtual bool OpenForWrite(const CURL& url, bool bOverWrite = false); + virtual bool Delete(const CURL& url); + +From 86640c251777f7c4cff679270bf00b4f3dde7415 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Feb 2015 00:19:51 +0000 +Subject: [PATCH 58/95] [libnfs] Add streaming cache + +--- + .../libnfs/0001-Sequential-Readahead-Mode.patch | 949 +++++++++++++++++++++ + tools/depends/target/libnfs/Makefile | 1 + + xbmc/filesystem/DllLibNfs.h | 3 + + xbmc/filesystem/NFSFile.cpp | 2 + + 4 files changed, 955 insertions(+) + create mode 100644 tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch + +diff --git a/tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch b/tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch +new file mode 100644 +index 0000000..83b7e11 +--- /dev/null ++++ b/tools/depends/target/libnfs/0001-Sequential-Readahead-Mode.patch +@@ -0,0 +1,949 @@ ++From ae7ef01ad15ea91f669a59d4fd44aa9c03a3a6fb Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 11:16:38 -0800 ++Subject: [PATCH 1/7] Sequential Readahead Mode ++ ++Add a new api to activate sequential reading of files. ++It is activated by calling nfs_set_streaming_mode(fs,size) ++with a filehandle and a size. ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ include/nfsc/libnfs-raw.h | 9 ++ ++ include/nfsc/libnfs.h | 14 +++ ++ lib/libnfs-sync.c | 12 ++- ++ lib/libnfs-win32.def | 5 + ++ lib/libnfs.c | 258 +++++++++++++++++++++++++++++++++++++++++++++- ++ lib/socket.c | 15 ++- ++ 6 files changed, 308 insertions(+), 5 deletions(-) ++ ++diff --git a/include/nfsc/libnfs-raw.h b/include/nfsc/libnfs-raw.h ++index 3ba9de3..4593cc6 100644 ++--- a/include/nfsc/libnfs-raw.h +++++ b/include/nfsc/libnfs-raw.h ++@@ -44,6 +44,15 @@ int rpc_get_fd(struct rpc_context *rpc); ++ int rpc_which_events(struct rpc_context *rpc); ++ int rpc_service(struct rpc_context *rpc, int revents); ++ char *rpc_get_error(struct rpc_context *rpc); +++ +++/* Return the number of PDUs in the outqueue. +++ * This is the count of PDUs not yet written to the socket. +++ */ +++int rpc_outqueue_length(struct rpc_context *rpc); +++/* Return the number all in flight PDUs. +++ * This includes both the PDUs not yet written to the socket as well as +++ * all PDUs we have sent to the server but not yet received a reply to. +++ */ ++ int rpc_queue_length(struct rpc_context *rpc); ++ ++ /* Utility function to get an RPC context from a NFS context. Useful for doing low level NFSACL ++diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h ++index 2d14113..f84650b 100644 ++--- a/include/nfsc/libnfs.h +++++ b/include/nfsc/libnfs.h ++@@ -83,6 +83,15 @@ struct utimbuf { ++ EXTERN int nfs_get_fd(struct nfs_context *nfs); ++ EXTERN int nfs_which_events(struct nfs_context *nfs); ++ EXTERN int nfs_service(struct nfs_context *nfs, int revents); +++ +++/* Return the number of PDUs in the outqueue. +++ * This is the count of PDUs not yet written to the socket. +++ */ +++EXTERN int nfs_outqueue_length(struct nfs_context *nfs); +++/* Return the number all in flight PDUs. +++ * This includes both the PDUs not yet written to the socket as well as +++ * all PDUs we have sent to the server but not yet received a reply to. +++ */ ++ EXTERN int nfs_queue_length(struct nfs_context *nfs); ++ ++ /* ++@@ -191,6 +200,11 @@ EXTERN void nfs_set_uid(struct nfs_context *nfs, int uid); ++ EXTERN void nfs_set_gid(struct nfs_context *nfs, int gid); ++ EXTERN void nfs_set_readahead(struct nfs_context *nfs, uint32_t v); ++ +++/* Optimize for sequentianl streaming reads. size is the amount +++ * of buffering. +++ */ +++EXTERN int nfs_set_streaming_mode(struct nfsfh *nfsfh, uint32_t size); +++ ++ /* ++ * MOUNT THE EXPORT ++ */ ++diff --git a/lib/libnfs-sync.c b/lib/libnfs-sync.c ++index 59911fc..dc696c3 100644 ++--- a/lib/libnfs-sync.c +++++ b/lib/libnfs-sync.c ++@@ -137,9 +137,14 @@ static void wait_for_reply(struct rpc_context *rpc, struct sync_cb_data *cb_data ++ static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data) ++ { ++ struct pollfd pfd; ++- ++- while (!cb_data->is_finished) { ++- +++ int available; +++ +++ /* loop until the command has completed, and we have written all +++ * queued PDUs to the socket, and we have read and processed all +++ * data in the socket receive buffer. +++ */ +++ ioctl(nfs_get_fd(nfs), FIONREAD, &available); +++ while (!cb_data->is_finished || nfs_outqueue_length(nfs) || available) { ++ pfd.fd = nfs_get_fd(nfs); ++ pfd.events = nfs_which_events(nfs); ++ if (poll(&pfd, 1, -1) < 0) { ++@@ -152,6 +157,7 @@ static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_ ++ cb_data->status = -EIO; ++ break; ++ } +++ ioctl(nfs_get_fd(nfs), FIONREAD, &available); ++ } ++ } ++ ++diff --git a/lib/libnfs-win32.def b/lib/libnfs-win32.def ++index 5a0df03..bdfa737 100644 ++--- a/lib/libnfs-win32.def +++++ b/lib/libnfs-win32.def ++@@ -48,6 +48,7 @@ nfs_open ++ nfs_open_async ++ nfs_opendir ++ nfs_opendir_async +++nfs_outqueue_length ++ nfs_parse_url_full ++ nfs_parse_url_dir ++ nfs_parse_url_incomplete ++@@ -56,6 +57,7 @@ nfs_pread ++ nfs_pread_async ++ nfs_pwrite ++ nfs_pwrite_async +++nfs_queue_length ++ nfs_read ++ nfs_read_async ++ nfs_readdir ++@@ -71,6 +73,7 @@ nfs_set_gid ++ nfs_set_tcp_syncnt ++ nfs_set_uid ++ nfs_set_readahead +++nfs_set_streaming_mode ++ nfs_stat ++ nfs_stat_async ++ nfs_stat64 ++@@ -205,6 +208,8 @@ rpc_nsm1_unmon_async ++ rpc_nsm1_unmonall_async ++ rpc_nsm1_simucrash_async ++ rpc_nsm1_notify_async +++rpc_outqueue_length +++rpc_queue_length ++ rpc_rquota1_null_async ++ rpc_rquota1_getquota_async ++ rpc_rquota1_getactivequota_async ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index f807822..5fc921d 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -108,12 +108,37 @@ struct nfs_readahead { ++ uint32_t cur_ra; ++ }; ++ +++/* Store streaming cache in blocks of this size */ +++#define NFS_STREAM_BUF_SIZE (32768 * 4) +++/* Skip trying to streaming caching for reads greater than this */ +++#define NFS_MAX_STREAMING_SIZE (1024 * 1024) +++ +++#define BSS_UNUSED 0 +++#define BSS_PENDING 1 +++#define BSS_VALID 2 +++struct nfs_streaming_block { +++ int state; +++ unsigned char *ptr; +++}; +++ +++struct nfs_streaming_read { +++ uint64_t next_offset; +++ int num_seq; +++ +++ int num_blocks; /* number of buffer blocks */ +++ uint64_t buf_offset; +++ struct nfs_streaming_block *blocks; +++ unsigned char *buf; +++}; +++ ++ struct nfsfh { ++ struct nfs_fh3 fh; ++ int is_sync; ++ int is_append; ++ uint64_t offset; ++- struct nfs_readahead ra; +++ +++ struct nfs_streaming_read *sr; +++ struct nfs_readahead ra; /* broken? */ ++ }; ++ ++ struct nested_mounts { ++@@ -231,6 +256,11 @@ int nfs_get_fd(struct nfs_context *nfs) ++ return rpc_get_fd(nfs->rpc); ++ } ++ +++int nfs_outqueue_length(struct nfs_context *nfs) +++{ +++ return rpc_outqueue_length(nfs->rpc); +++} +++ ++ int nfs_queue_length(struct nfs_context *nfs) ++ { ++ return rpc_queue_length(nfs->rpc); ++@@ -730,12 +760,52 @@ static void free_nfs_cb_data(struct nfs_cb_data *data) ++ free(data); ++ } ++ +++int nfs_set_streaming_mode(struct nfsfh *nfsfh, uint32_t size) +++{ +++ struct nfs_streaming_read *sr; +++ int i; +++ +++ sr = malloc(sizeof(struct nfs_streaming_read)); +++ if (sr == NULL) { +++ return -1; +++ } +++ memset(sr, 0, sizeof(struct nfs_streaming_read)); +++ sr->num_blocks = size / NFS_STREAM_BUF_SIZE; +++ +++ sr->buf = malloc(sr->num_blocks * NFS_STREAM_BUF_SIZE); +++ if (sr->buf == NULL) { +++ free(sr); +++ return -1; +++ } +++ memset(sr->buf, 0, sr->num_blocks * NFS_STREAM_BUF_SIZE); +++ +++ sr->blocks = malloc(sr->num_blocks * sizeof(struct nfs_streaming_block)) +++; +++ if (sr->blocks == NULL) { +++ free(sr->buf); +++ free(sr); +++ return -1; +++ } +++ for (i = 0; i < sr->num_blocks; i++) { +++ sr->blocks[i].state = BSS_UNUSED; +++ sr->blocks[i].ptr = &sr->buf[i * NFS_STREAM_BUF_SIZE]; +++ } +++ nfsfh->sr = sr; +++ +++ return 0; +++} +++ ++ static void free_nfsfh(struct nfsfh *nfsfh) ++ { ++ if (nfsfh->fh.data.data_val != NULL) { ++ free(nfsfh->fh.data.data_val); ++ nfsfh->fh.data.data_val = NULL; ++ } +++ if (nfsfh->sr != NULL) { +++ free(nfsfh->sr->blocks); +++ free(nfsfh->sr->buf); +++ free(nfsfh->sr); +++ } ++ free(nfsfh->ra.buf); ++ free(nfsfh); ++ } ++@@ -2033,6 +2103,8 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, ++ nfsfh->fh = data->fh; ++ data->fh.data.data_val = NULL; ++ +++ nfs_set_streaming_mode(nfsfh, 200 * NFS_STREAM_BUF_SIZE); +++ ++ data->cb(0, nfs, nfsfh, data->private_data); ++ free_nfs_cb_data(data); ++ } ++@@ -2252,10 +2324,194 @@ static void nfs_ra_invalidate(struct nfsfh *nfsfh) { ++ nfsfh->ra.cur_ra = NFS_BLKSIZE; ++ } ++ +++struct stream_cb_data { +++ uint64_t offset; +++ struct nfsfh *nfsfh; +++}; +++ +++static void nfs_stream_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +++{ +++ struct stream_cb_data *stream_data = private_data; +++ struct nfsfh *nfsfh = stream_data->nfsfh; +++ READ3res *res; +++ int i; +++ +++ assert(rpc->magic == RPC_CONTEXT_MAGIC); +++ +++ if (stream_data->offset < nfsfh->sr->buf_offset) { +++ free(stream_data); +++ return; +++ } +++ if (stream_data->offset >= nfsfh->sr->buf_offset + nfsfh->sr->num_blocks * NFS_STREAM_BUF_SIZE) { +++ free(stream_data); +++ return; +++ } +++ +++ i = (stream_data->offset - nfsfh->sr->buf_offset) / NFS_STREAM_BUF_SIZE; +++ nfsfh->sr->blocks[i].state = BSS_UNUSED; +++ free(stream_data); +++ +++ if (status == RPC_STATUS_ERROR) { +++ return; +++ } +++ if (status == RPC_STATUS_CANCEL) { +++ return; +++ } +++ if (status == RPC_STATUS_SUCCESS) { +++ res = command_data; +++ if (res->status != NFS3_OK) { +++ return; +++ } +++ if (res->READ3res_u.resok.count != NFS_STREAM_BUF_SIZE) { +++ return; +++ } +++ memcpy(nfsfh->sr->blocks[i].ptr, +++ res->READ3res_u.resok.data.data_val, +++ NFS_STREAM_BUF_SIZE); +++ nfsfh->sr->blocks[i].state = BSS_VALID; +++ } +++} +++ +++static void prefetch_streaming_blocks(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t next_offset, int num_blocks) +++{ +++ int i; +++ +++ for (i = 0; i < nfsfh->sr->num_blocks && num_blocks; i++) { +++ struct stream_cb_data *stream_data; +++ READ3args args; +++ +++ if (nfsfh->sr->blocks[i].state != BSS_UNUSED) { +++ continue; +++ } +++ +++ stream_data = malloc(sizeof(struct stream_cb_data)); +++ if (stream_data == NULL) { +++ return; +++ } +++ stream_data->offset = i * NFS_STREAM_BUF_SIZE + nfsfh->sr->buf_offset; +++ stream_data->nfsfh = nfsfh; +++ +++ nfs_fill_READ3args(&args, nfsfh, stream_data->offset, NFS_STREAM_BUF_SIZE); +++ if (rpc_nfs3_read_async(nfs->rpc, nfs_stream_cb, &args, stream_data) != 0) { +++ free(stream_data); +++ return; +++ } +++ +++ nfsfh->sr->blocks[i].state = BSS_PENDING; +++ num_blocks--; +++ } +++} +++ ++ static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data, int update_pos) ++ { ++ struct nfs_cb_data *data; ++ +++ if (nfsfh->sr != NULL && count <= NFS_MAX_STREAMING_SIZE) { +++ int i, len, remaining, first_block, last_block; +++ unsigned char *buf, *pos; +++ +++ /* track sequential access */ +++ if (offset == nfsfh->sr->next_offset) { +++ nfsfh->sr->num_seq++; +++ } else { +++ if (nfsfh->sr->blocks[0].state != BSS_UNUSED) { +++ for (i = 0; i < nfsfh->sr->num_blocks; i++) { +++ nfsfh->sr->blocks[i].state = BSS_UNUSED; +++ } +++ } +++ nfsfh->sr->num_seq = 0; +++ } +++ nfsfh->sr->next_offset = offset + count; +++ +++ if (nfsfh->sr->num_seq < 5) { +++ goto end_of_streaming; +++ } +++ +++ /* If we do not have any cached data yet, reset buffer +++ * offset to point slightly ahead of the current read. +++ */ +++ if (nfsfh->sr->blocks[0].state == BSS_UNUSED) { +++ nfsfh->sr->buf_offset = (offset / NFS_STREAM_BUF_SIZE + 1) * NFS_STREAM_BUF_SIZE ; +++ } +++ +++ /* Prune head blocks we have read past */ +++ while (nfsfh->sr->blocks[0].state != BSS_UNUSED && +++ offset >= (nfsfh->sr->buf_offset + NFS_STREAM_BUF_SIZE)) { +++ unsigned char *ptr; +++ +++ ptr = nfsfh->sr->blocks[0].ptr; +++ memmove(&nfsfh->sr->blocks[0], &nfsfh->sr->blocks[1], +++ (nfsfh->sr->num_blocks - 1) +++ * sizeof(struct nfs_streaming_block)); +++ nfsfh->sr->buf_offset += NFS_STREAM_BUF_SIZE; +++ nfsfh->sr->blocks[nfsfh->sr->num_blocks - 1].state = BSS_UNUSED; +++ nfsfh->sr->blocks[nfsfh->sr->num_blocks - 1].ptr = ptr; +++ } +++ +++ /* try to prefetch four more blocks */ +++ prefetch_streaming_blocks(nfs, nfsfh, offset + count, 4); +++ +++ /* can we service the request straight out of cache ? */ +++ if (offset < nfsfh->sr->buf_offset) { +++ goto end_of_streaming; +++ } +++ first_block = (offset - nfsfh->sr->buf_offset) / NFS_STREAM_BUF_SIZE; +++ if (first_block >= nfsfh->sr->num_blocks) { +++ goto end_of_streaming; +++ } +++ +++ if (offset + count > nfsfh->sr->buf_offset + nfsfh->sr->num_blocks * NFS_STREAM_BUF_SIZE) { +++ goto end_of_streaming; +++ } +++ last_block = (offset + count - nfsfh->sr->buf_offset - 1) / NFS_STREAM_BUF_SIZE; +++ if (last_block >= nfsfh->sr->num_blocks) { +++ goto end_of_streaming; +++ } +++ if (last_block < first_block) { +++ goto end_of_streaming; +++ } +++ for (i = first_block; i <= last_block; i++) { +++ if (nfsfh->sr->blocks[i].state != BSS_VALID) { +++ goto end_of_streaming; +++ } +++ } +++ if (first_block == last_block) { +++ if (update_pos) { +++ nfsfh->offset += count; +++ } +++ cb(count, nfs, &nfsfh->sr->blocks[first_block].ptr[offset % NFS_STREAM_BUF_SIZE], private_data); +++ return 0; +++ } +++ +++ buf = malloc(count); +++ if (buf == NULL) { +++ goto end_of_streaming; +++ } +++ remaining = count; +++ pos = buf; +++ len = NFS_STREAM_BUF_SIZE - offset % NFS_STREAM_BUF_SIZE; +++ if (len > count) { +++ len = count; +++ } +++ memcpy(pos, &nfsfh->sr->blocks[first_block].ptr[offset % NFS_STREAM_BUF_SIZE], len); +++ remaining -= len; +++ pos += len; +++ +++ for (i = first_block + 1; remaining; i++) { +++ len = (remaining >= NFS_STREAM_BUF_SIZE) ? NFS_STREAM_BUF_SIZE : remaining; +++ memcpy(pos, &nfsfh->sr->blocks[i].ptr[0], len); +++ remaining -= len; +++ pos += len; +++ } +++ if (update_pos) { +++ nfsfh->offset += count; +++ } +++ cb(count, nfs, buf, private_data); +++ free(buf); +++ return 0; +++ } +++end_of_streaming: +++ ++ data = malloc(sizeof(struct nfs_cb_data)); ++ if (data == NULL) { ++ rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure"); ++diff --git a/lib/socket.c b/lib/socket.c ++index 3588246..41fb5b2 100644 ++--- a/lib/socket.c +++++ b/lib/socket.c ++@@ -755,7 +755,7 @@ struct sockaddr *rpc_get_recv_sockaddr(struct rpc_context *rpc) ++ return (struct sockaddr *)&rpc->udp_src; ++ } ++ ++-int rpc_queue_length(struct rpc_context *rpc) +++int rpc_outqueue_length(struct rpc_context *rpc) ++ { ++ int i=0; ++ struct rpc_pdu *pdu; ++@@ -767,6 +767,19 @@ int rpc_queue_length(struct rpc_context *rpc) ++ i++; ++ } ++ +++ return i; +++} +++ +++int rpc_queue_length(struct rpc_context *rpc) +++{ +++ int i=0; +++ struct rpc_pdu *pdu; +++ unsigned int n; +++ +++ assert(rpc->magic == RPC_CONTEXT_MAGIC); +++ +++ i = rpc_outqueue_length(rpc); +++ ++ for (n = 0; n < HASHES; n++) { ++ struct rpc_queue *q = &rpc->waitpdu[n]; ++ ++-- ++1.9.1 ++ ++ ++From 6f6832b6c19a26557883af924d7135f5ef87f45d Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 12:43:59 -0800 ++Subject: [PATCH 2/7] nfs-stream.c: a simple test tool to check performance ++ sequential read mode ++ ++./nfs-stream ++ ++This tool is for testing sequential read mode. ++It reads 32kbyte one block at a time using the sync API. ++The idea is that when a nfs_[p]read() command is executed, we will once we ++identify a sequential scan start issuing asynchronous commands in the ++background to populate a readahead cache. ++ ++During read, we try to service the request immediately out of cache ++and return immediately to the application. During read from cache we will also ++process any to previous reads and use it to populate the cache. Also, as the ++file offset grows, we will discard the already read blocks from the cache ++and issue new asynchronous commands at the tail of the cache. ++ ++nfs_read() will when the cache is operating behave like : ++ nfs_read() { ++ ... process any previous reads and populate the cache ... ++ ... send async command to replenish the tail of the cache ... ++ return data from cache straigh back to application ++ } ++ ++The test tool will try to read 32kb chunks at a given rate. ++Once the test tool manages to service from cache the read laency should drop ++to <<1ms and the majority of the time spent will be in the sleep() between calls. ++Once the latency is steady at <<1ms this is an indication that we now ++service all reads out of cache instead of the network. ++If the read latency remains <<1ms continously, without any spikes, it means that ++we have been successfull in maintaining the asycntrhous tasks to replenish the cache. ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ nfs-stream.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ 1 file changed, 65 insertions(+) ++ create mode 100644 nfs-stream.c ++ ++diff --git a/nfs-stream.c b/nfs-stream.c ++new file mode 100644 ++index 0000000..5570cd6 ++--- /dev/null +++++ b/nfs-stream.c ++@@ -0,0 +1,65 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include "nfsc/libnfs.h" +++ +++int main(int argc, char *argv[]) +++{ +++ struct nfs_context *nfs; +++ struct nfs_url *url; +++ struct nfsfh *nfsfh = NULL; +++ struct nfs_stat_64 st; +++ uint64_t offset; +++ char buf[32768]; +++ struct timeval t1, t2; +++ uint64_t delta, tpc; +++ +++ nfs = nfs_init_context(); +++ url = nfs_parse_url_full(nfs, argv[1]); +++ if (!url) { +++ fprintf(stderr, "Can not parse URL. %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_mount(nfs, url->server, url->path) != 0) { +++ fprintf(stderr, "Failed to mount nfs share : %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { +++ fprintf(stderr, "Failed to open file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_fstat64(nfs, nfsfh, &st)) { +++ fprintf(stderr, "Failed to stat file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ printf("File size:%lld\n", (long long)st.nfs_size); +++ tpc = 1000000 / (strtol(argv[2], NULL, 10) / 32768); +++ printf("Read one 32kb chunk every %d us\n", (int)tpc); +++ for (offset = 0; offset < st.nfs_size; offset += 32768) { +++ gettimeofday(&t1, NULL); +++ nfs_read(nfs, nfsfh, 8192, buf); +++ gettimeofday(&t2, NULL); +++ delta = t2.tv_sec * 1000000LL + t2.tv_usec - +++ t1.tv_sec * 1000000LL - t1.tv_usec; +++ printf("Read latency:%lld us\n", (long long)delta); +++ if (tpc > delta) { +++ printf("Sleep for %d us\n", (int)(tpc - delta)); +++ usleep(tpc - delta); +++ } +++ } +++ +++ nfs_close(nfs, nfsfh); +++ nfs_destroy_context(nfs); +++ nfs_destroy_url(url); +++ return 0; +++} ++-- ++1.9.1 ++ ++ ++From 225e1c47727871c6ca74d6e3fef79ee6234923a1 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 13:31:02 -0800 ++Subject: [PATCH 3/7] streaming: only try refilling 2 blocks at a time instead ++ of 4 ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ lib/libnfs.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index 5fc921d..84e76b6 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -2448,8 +2448,8 @@ static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh ++ nfsfh->sr->blocks[nfsfh->sr->num_blocks - 1].ptr = ptr; ++ } ++ ++- /* try to prefetch four more blocks */ ++- prefetch_streaming_blocks(nfs, nfsfh, offset + count, 4); +++ /* try to prefetch to more blocks */ +++ prefetch_streaming_blocks(nfs, nfsfh, offset + count, 2); ++ ++ /* can we service the request straight out of cache ? */ ++ if (offset < nfsfh->sr->buf_offset) { ++-- ++1.9.1 ++ ++ ++From ceb35bb17425dda7408ae43ae80a997f4e1c1f95 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Sat, 7 Feb 2015 16:19:59 -0800 ++Subject: [PATCH 4/7] read 32kb at a time, not 8kb ++ ++crapadoodle, if we measure 32kb blob read speed we should actually read ++a 32kb blob too. not a 8kb one. ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ nfs-stream.c | 4 ++-- ++ 1 file changed, 2 insertions(+), 2 deletions(-) ++ ++diff --git a/nfs-stream.c b/nfs-stream.c ++index 5570cd6..dd01218 100644 ++--- a/nfs-stream.c +++++ b/nfs-stream.c ++@@ -47,13 +47,13 @@ int main(int argc, char *argv[]) ++ printf("Read one 32kb chunk every %d us\n", (int)tpc); ++ for (offset = 0; offset < st.nfs_size; offset += 32768) { ++ gettimeofday(&t1, NULL); ++- nfs_read(nfs, nfsfh, 8192, buf); +++ nfs_read(nfs, nfsfh, 32768, buf); ++ gettimeofday(&t2, NULL); ++ delta = t2.tv_sec * 1000000LL + t2.tv_usec - ++ t1.tv_sec * 1000000LL - t1.tv_usec; ++ printf("Read latency:%lld us\n", (long long)delta); ++ if (tpc > delta) { ++- printf("Sleep for %d us\n", (int)(tpc - delta)); +++ //printf("Sleep for %d us\n", (int)(tpc - delta)); ++ usleep(tpc - delta); ++ } ++ } ++-- ++1.9.1 ++ ++ ++From 5f5faa8cfb86057081ccb3e30f987ecdec40fa13 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Mon, 9 Feb 2015 20:46:25 -0800 ++Subject: [PATCH 5/7] prefetch: limit the amount of prefetches we have in ++ flight to 2 ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ lib/libnfs.c | 16 +++++++++++++--- ++ nfs-stream.c | 7 +++++++ ++ 2 files changed, 20 insertions(+), 3 deletions(-) ++ ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index 84e76b6..929d3e0 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -2103,8 +2103,6 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, ++ nfsfh->fh = data->fh; ++ data->fh.data.data_val = NULL; ++ ++- nfs_set_streaming_mode(nfsfh, 200 * NFS_STREAM_BUF_SIZE); ++- ++ data->cb(0, nfs, nfsfh, data->private_data); ++ free_nfs_cb_data(data); ++ } ++@@ -2374,12 +2372,24 @@ static void nfs_stream_cb(struct rpc_context *rpc, int status, void *command_dat ++ ++ static void prefetch_streaming_blocks(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t next_offset, int num_blocks) ++ { ++- int i; +++ int i, num_pending = 0; ++ ++ for (i = 0; i < nfsfh->sr->num_blocks && num_blocks; i++) { ++ struct stream_cb_data *stream_data; ++ READ3args args; ++ +++ /* +++ * BSS_PENDING means we have a request for prefetch in flight. +++ * We don't want an unlimited amount of requests in flight +++ * since it can cause wild latency spikes while initially +++ * filling the prefetch buffer. +++ */ +++ if (nfsfh->sr->blocks[i].state == BSS_PENDING) { +++ num_pending++; +++ } +++ if (num_pending >= num_blocks) { +++ continue; +++ } ++ if (nfsfh->sr->blocks[i].state != BSS_UNUSED) { ++ continue; ++ } ++diff --git a/nfs-stream.c b/nfs-stream.c ++index dd01218..f5a1b0a 100644 ++--- a/nfs-stream.c +++++ b/nfs-stream.c ++@@ -18,6 +18,11 @@ int main(int argc, char *argv[]) ++ struct timeval t1, t2; ++ uint64_t delta, tpc; ++ +++ if (argc != 3) { +++ fprintf(stderr, "Usage: nfs-stream \n"); +++ exit(1); +++ } +++ ++ nfs = nfs_init_context(); ++ url = nfs_parse_url_full(nfs, argv[1]); ++ if (!url) { ++@@ -36,6 +41,8 @@ int main(int argc, char *argv[]) ++ nfs_get_error(nfs)); ++ exit(1); ++ } +++ nfs_set_streaming_mode(nfsfh, 5 * 1024 * 1024); +++ ++ if (nfs_fstat64(nfs, nfsfh, &st)) { ++ fprintf(stderr, "Failed to stat file %s: %s\n", ++ url->file, ++-- ++1.9.1 ++ ++ ++From 503492873f27cefc3bfb368a96c4c7e1c99b303f Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Tue, 10 Feb 2015 16:40:53 -0800 ++Subject: [PATCH 6/7] streaming mode: wait until we have 10 sequential reads ++ before we prefetch ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ lib/libnfs.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/lib/libnfs.c b/lib/libnfs.c ++index 929d3e0..53b71fd 100644 ++--- a/lib/libnfs.c +++++ b/lib/libnfs.c ++@@ -2433,7 +2433,7 @@ static int nfs_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh ++ } ++ nfsfh->sr->next_offset = offset + count; ++ ++- if (nfsfh->sr->num_seq < 5) { +++ if (nfsfh->sr->num_seq < 10) { ++ goto end_of_streaming; ++ } ++ ++-- ++1.9.1 ++ ++ ++From 55a673ae81514f109553d36b71647e8c334f8d81 Mon Sep 17 00:00:00 2001 ++From: Ronnie Sahlberg ++Date: Wed, 11 Feb 2015 01:25:05 -0800 ++Subject: [PATCH 7/7] nfs-stream.c: move this tool to the examples directory ++ ++Signed-off-by: Ronnie Sahlberg ++--- ++ examples/nfs-stream.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ ++ nfs-stream.c | 72 --------------------------------------------------- ++ 2 files changed, 72 insertions(+), 72 deletions(-) ++ create mode 100644 examples/nfs-stream.c ++ delete mode 100644 nfs-stream.c ++ ++diff --git a/examples/nfs-stream.c b/examples/nfs-stream.c ++new file mode 100644 ++index 0000000..f5a1b0a ++--- /dev/null +++++ b/examples/nfs-stream.c ++@@ -0,0 +1,72 @@ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include "nfsc/libnfs.h" +++ +++int main(int argc, char *argv[]) +++{ +++ struct nfs_context *nfs; +++ struct nfs_url *url; +++ struct nfsfh *nfsfh = NULL; +++ struct nfs_stat_64 st; +++ uint64_t offset; +++ char buf[32768]; +++ struct timeval t1, t2; +++ uint64_t delta, tpc; +++ +++ if (argc != 3) { +++ fprintf(stderr, "Usage: nfs-stream \n"); +++ exit(1); +++ } +++ +++ nfs = nfs_init_context(); +++ url = nfs_parse_url_full(nfs, argv[1]); +++ if (!url) { +++ fprintf(stderr, "Can not parse URL. %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_mount(nfs, url->server, url->path) != 0) { +++ fprintf(stderr, "Failed to mount nfs share : %s\n", +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { +++ fprintf(stderr, "Failed to open file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ nfs_set_streaming_mode(nfsfh, 5 * 1024 * 1024); +++ +++ if (nfs_fstat64(nfs, nfsfh, &st)) { +++ fprintf(stderr, "Failed to stat file %s: %s\n", +++ url->file, +++ nfs_get_error(nfs)); +++ exit(1); +++ } +++ printf("File size:%lld\n", (long long)st.nfs_size); +++ tpc = 1000000 / (strtol(argv[2], NULL, 10) / 32768); +++ printf("Read one 32kb chunk every %d us\n", (int)tpc); +++ for (offset = 0; offset < st.nfs_size; offset += 32768) { +++ gettimeofday(&t1, NULL); +++ nfs_read(nfs, nfsfh, 32768, buf); +++ gettimeofday(&t2, NULL); +++ delta = t2.tv_sec * 1000000LL + t2.tv_usec - +++ t1.tv_sec * 1000000LL - t1.tv_usec; +++ printf("Read latency:%lld us\n", (long long)delta); +++ if (tpc > delta) { +++ //printf("Sleep for %d us\n", (int)(tpc - delta)); +++ usleep(tpc - delta); +++ } +++ } +++ +++ nfs_close(nfs, nfsfh); +++ nfs_destroy_context(nfs); +++ nfs_destroy_url(url); +++ return 0; +++} ++diff --git a/nfs-stream.c b/nfs-stream.c ++deleted file mode 100644 ++index f5a1b0a..0000000 ++--- a/nfs-stream.c +++++ /dev/null ++@@ -1,72 +0,0 @@ ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include ++-#include "nfsc/libnfs.h" ++- ++-int main(int argc, char *argv[]) ++-{ ++- struct nfs_context *nfs; ++- struct nfs_url *url; ++- struct nfsfh *nfsfh = NULL; ++- struct nfs_stat_64 st; ++- uint64_t offset; ++- char buf[32768]; ++- struct timeval t1, t2; ++- uint64_t delta, tpc; ++- ++- if (argc != 3) { ++- fprintf(stderr, "Usage: nfs-stream \n"); ++- exit(1); ++- } ++- ++- nfs = nfs_init_context(); ++- url = nfs_parse_url_full(nfs, argv[1]); ++- if (!url) { ++- fprintf(stderr, "Can not parse URL. %s\n", ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- if (nfs_mount(nfs, url->server, url->path) != 0) { ++- fprintf(stderr, "Failed to mount nfs share : %s\n", ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- if (nfs_open(nfs, url->file, O_RDONLY, &nfsfh) != 0) { ++- fprintf(stderr, "Failed to open file %s: %s\n", ++- url->file, ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- nfs_set_streaming_mode(nfsfh, 5 * 1024 * 1024); ++- ++- if (nfs_fstat64(nfs, nfsfh, &st)) { ++- fprintf(stderr, "Failed to stat file %s: %s\n", ++- url->file, ++- nfs_get_error(nfs)); ++- exit(1); ++- } ++- printf("File size:%lld\n", (long long)st.nfs_size); ++- tpc = 1000000 / (strtol(argv[2], NULL, 10) / 32768); ++- printf("Read one 32kb chunk every %d us\n", (int)tpc); ++- for (offset = 0; offset < st.nfs_size; offset += 32768) { ++- gettimeofday(&t1, NULL); ++- nfs_read(nfs, nfsfh, 32768, buf); ++- gettimeofday(&t2, NULL); ++- delta = t2.tv_sec * 1000000LL + t2.tv_usec - ++- t1.tv_sec * 1000000LL - t1.tv_usec; ++- printf("Read latency:%lld us\n", (long long)delta); ++- if (tpc > delta) { ++- //printf("Sleep for %d us\n", (int)(tpc - delta)); ++- usleep(tpc - delta); ++- } ++- } ++- ++- nfs_close(nfs, nfsfh); ++- nfs_destroy_context(nfs); ++- nfs_destroy_url(url); ++- return 0; ++-} ++-- ++1.9.1 +diff --git a/tools/depends/target/libnfs/Makefile b/tools/depends/target/libnfs/Makefile +index 642fba8..aa6bde1 100644 +--- a/tools/depends/target/libnfs/Makefile ++++ b/tools/depends/target/libnfs/Makefile +@@ -25,6 +25,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); ./bootstrap + cd $(PLATFORM); patch -p0 < ../utils.patch + cd $(PLATFORM); patch -p1 < ../readahead.patch ++ cd $(PLATFORM); patch -p1 < ../0001-Sequential-Readahead-Mode.patch + cd $(PLATFORM); $(CONFIGURE) + + $(LIBDYLIB): $(PLATFORM) +diff --git a/xbmc/filesystem/DllLibNfs.h b/xbmc/filesystem/DllLibNfs.h +index 4b5ba29..9ba8ebc 100644 +--- a/xbmc/filesystem/DllLibNfs.h ++++ b/xbmc/filesystem/DllLibNfs.h +@@ -85,6 +85,7 @@ class DllLibNfsInterface + virtual int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf)=0; + virtual int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf)=0; + virtual int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset)=0; ++ virtual void nfs_set_streaming_mode(struct nfsfh *nfsfh, uint32_t v)=0; + }; + + class DllLibNfs : public DllDynamic, DllLibNfsInterface +@@ -131,6 +132,7 @@ class DllLibNfs : public DllDynamic, DllLibNfsInterface + DEFINE_METHOD5(int, nfs_pread, (struct nfs_context *p1, struct nfsfh *p2, uint64_t p3, uint64_t p4, char *p5)) + DEFINE_METHOD5(int, nfs_pwrite, (struct nfs_context *p1, struct nfsfh *p2, uint64_t p3, uint64_t p4, char *p5)) + DEFINE_METHOD5(int, nfs_lseek, (struct nfs_context *p1, struct nfsfh *p2, uint64_t p3, int p4, uint64_t *p5)) ++ DEFINE_METHOD2(void,nfs_set_streaming_mode, (struct nfsfh *p1, uint32_t p2)) + + + +@@ -176,6 +178,7 @@ class DllLibNfs : public DllDynamic, DllLibNfsInterface + RESOLVE_METHOD_RENAME(nfs_symlink, nfs_symlink) + RESOLVE_METHOD_RENAME(nfs_rename, nfs_rename) + RESOLVE_METHOD_RENAME(nfs_link, nfs_link) ++ RESOLVE_METHOD_RENAME(nfs_set_streaming_mode, nfs_set_streaming_mode) + END_METHOD_RESOLVE() + }; + +diff --git a/xbmc/filesystem/NFSFile.cpp b/xbmc/filesystem/NFSFile.cpp +index 9354fd5..eaa1dd7 100644 +--- a/xbmc/filesystem/NFSFile.cpp ++++ b/xbmc/filesystem/NFSFile.cpp +@@ -562,6 +562,8 @@ bool CNFSFile::Open(const CURL& url) + CLog::Log(LOGDEBUG,"CNFSFile::Open - opened %s",url.GetFileName().c_str()); + m_url=url; + ++ //gNfsConnection.GetImpl()->nfs_set_streaming_mode(m_pFileHandle, 5 * 1024 * 1024); ++ + struct __stat64 tmpBuffer; + + if( Stat(&tmpBuffer) ) + +From e4cca8769b7ccbf8b3eae3cf497804032c15a17b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 14:06:12 +0000 +Subject: [PATCH 59/95] [mmal] Allow mmal codec for dvd stills + +--- + xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +index 0cd267a..9d8de2a 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +@@ -49,6 +49,9 @@ + #include "Video/DVDVideoCodecAndroidMediaCodec.h" + #include "android/activity/AndroidFeatures.h" + #endif ++#if defined(HAS_MMAL) ++#include "linux/RBP.h" ++#endif + #include "Audio/DVDAudioCodecFFmpeg.h" + #include "Audio/DVDAudioCodecPassthrough.h" + #include "Overlay/DVDOverlayCodecSSA.h" +@@ -199,6 +202,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne + #endif + CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); + ++#if defined(HAS_MMAL) ++ // mmal can handle dvd playback including stills ++ if (!CSettings::Get().GetBool("videoplayer.usemmal") || !g_RBP.GetCodecMpg2()) ++#endif + if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO)) + { + // If dvd is an mpeg2 and hint.stills + +From d2e87054304fdf10cb00d1e5441a2e4376d8c335 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 15:29:51 +0000 +Subject: [PATCH 60/95] [rbp] Add Pi 2 specific settings defaults + +Disable omxplayer by default and don't need to warn against using ac3 transcode +--- + system/settings/rbp2.xml | 107 +++++++++++++++++++++++++++++++++++++++++++++ + xbmc/linux/RBP.h | 2 + + xbmc/settings/Settings.cpp | 7 ++- + 3 files changed, 115 insertions(+), 1 deletion(-) + create mode 100644 system/settings/rbp2.xml + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +new file mode 100644 +index 0000000..e118f3a +--- /dev/null ++++ b/system/settings/rbp2.xml +@@ -0,0 +1,107 @@ ++ ++ ++
++ ++ ++ false ++ ++ ++ ++ false ++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ ++ ++ ++ 2 ++ 10 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ false ++ ++ ++ ++
++ ++
++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ false ++ ++ ++ 2 ++ true ++ ++ ++ ++ 2 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 101 ++ ++ ++ 3 ++ 100 ++ ++ 50 ++ 50 ++ 300 ++ ++ ++ 38102 ++ ++ ++ ++ ++
++
+diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h +index 82146d6..4a04183 100644 +--- a/xbmc/linux/RBP.h ++++ b/xbmc/linux/RBP.h +@@ -37,6 +37,7 @@ + #if defined(TARGET_RASPBERRY_PI) + #include "DllBCM.h" + #include "OMXCore.h" ++#include "xbmc/utils/CPUInfo.h" + #include "threads/CriticalSection.h" + #include "threads/Event.h" + +@@ -52,6 +53,7 @@ class CRBP + int GetArmMem() { return m_arm_mem; } + int GetGpuMem() { return m_gpu_mem; } + bool GetCodecMpg2() { return m_codec_mpg2_enabled; } ++ int RasberryPiVersion() { return g_cpuInfo.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); +diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp +index a81fa93..519bd30 100644 +--- a/xbmc/settings/Settings.cpp ++++ b/xbmc/settings/Settings.cpp +@@ -49,6 +49,9 @@ + #if defined(TARGET_DARWIN) + #include "osx/DarwinUtils.h" + #endif ++#if defined(TARGET_RASPBERRY_PI) ++#include "linux/RBP.h" ++#endif + #include "peripherals/Peripherals.h" + #include "powermanagement/PowerManager.h" + #include "profiles/ProfilesManager.h" +@@ -454,8 +457,10 @@ bool CSettings::InitializeDefinitions() + 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")) ++ if (g_RBP.RasberryPiVersion() == 1 && 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.RasberryPiVersion() > 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"); + +From 032835dd2e7944ddf049ea986b3698c78c74b3ad Mon Sep 17 00:00:00 2001 +From: Claudio-Sjo +Date: Mon, 16 Feb 2015 14:51:26 +0100 +Subject: [PATCH 61/95] - allow reads < CDIO_CD_FRAMESIZE_RAW by using a buffer + - fixes #15794 + +--- + xbmc/filesystem/CDDAFile.cpp | 120 ++++++++++++++++++++++++++++++++----------- + xbmc/filesystem/CDDAFile.h | 3 ++ + 2 files changed, 92 insertions(+), 31 deletions(-) + +diff --git a/xbmc/filesystem/CDDAFile.cpp b/xbmc/filesystem/CDDAFile.cpp +index 16796f5..066b49f 100644 +--- a/xbmc/filesystem/CDDAFile.cpp ++++ b/xbmc/filesystem/CDDAFile.cpp +@@ -43,10 +43,14 @@ CFileCDDA::CFileCDDA(void) + m_lsnEnd = CDIO_INVALID_LSN; + m_cdio = CLibcdio::GetInstance(); + m_iSectorCount = 52; ++ m_TrackBuf = (uint8_t *) malloc(CDIO_CD_FRAMESIZE_RAW); ++ p_TrackBuf = 0; ++ f_TrackBuf = 0; + } + + CFileCDDA::~CFileCDDA(void) + { ++ free(m_TrackBuf); + Close(); + } + +@@ -54,6 +58,9 @@ bool CFileCDDA::Open(const CURL& url) + { + std::string strURL = url.GetWithoutFilename(); + ++ // Flag TrackBuffer = FALSE, TrackBuffer is empty ++ f_TrackBuf = 0; ++ + if (!g_mediaManager.IsDiscInDrive(strURL) || !IsValidFile(url)) + return false; + +@@ -118,50 +125,98 @@ int CFileCDDA::Stat(const CURL& url, struct __stat64* buffer) + + ssize_t CFileCDDA::Read(void* lpBuf, size_t uiBufSize) + { +- if (!m_pCdIo || !g_mediaManager.IsDiscInDrive()) +- return -1; + +- if (uiBufSize > SSIZE_MAX) +- uiBufSize = SSIZE_MAX; ++ ssize_t returnValue; ++ int iSectorCount; ++ void *destBuf; + +- // limit number of sectors that fits in buffer by m_iSectorCount +- int iSectorCount = std::min((int)uiBufSize / CDIO_CD_FRAMESIZE_RAW, m_iSectorCount); + +- if (iSectorCount <= 0) ++ if (!m_pCdIo || !g_mediaManager.IsDiscInDrive()) ++ { ++ CLog::Log(LOGERROR, "file cdda: Aborted because no disc in drive or no m_pCdIo"); + return -1; ++ } + +- // Are there enough sectors left to read +- if (m_lsnCurrent + iSectorCount > m_lsnEnd) +- iSectorCount = m_lsnEnd - m_lsnCurrent; ++ uiBufSize = std::min( uiBufSize, (size_t)SSIZE_MAX ); + +- // The loop tries to solve read error problem by lowering number of sectors to read (iSectorCount). +- // When problem is solved the proper number of sectors is stored in m_iSectorCount +- int big_iSectorCount = iSectorCount; +- while (iSectorCount > 0) ++ // If we have data in the TrackBuffer, they must be used first ++ if (f_TrackBuf) + { +- int iret = m_cdio->cdio_read_audio_sectors(m_pCdIo, lpBuf, m_lsnCurrent, iSectorCount); ++ // Get at most the remaining data in m_TrackBuf ++ uiBufSize = std::min(uiBufSize, CDIO_CD_FRAMESIZE_RAW - p_TrackBuf); ++ memcpy(lpBuf, m_TrackBuf + p_TrackBuf, uiBufSize); ++ // Update the data offset ++ p_TrackBuf += uiBufSize; ++ // Is m_TrackBuf empty? ++ f_TrackBuf = (CDIO_CD_FRAMESIZE_RAW == p_TrackBuf); ++ // All done, return read bytes ++ return uiBufSize; ++ } ++ ++ // No data left in buffer ++ ++ // Is this a short read? ++ if (uiBufSize < CDIO_CD_FRAMESIZE_RAW) ++ { ++ // short request, buffer one full sector ++ iSectorCount = 1; ++ destBuf = m_TrackBuf; ++ } ++ else // normal request ++ { ++ // limit number of sectors that fits in buffer by m_iSectorCount ++ iSectorCount = std::min((int)uiBufSize / CDIO_CD_FRAMESIZE_RAW, m_iSectorCount); ++ destBuf = lpBuf; ++ } + ++ // Are there enough sectors left to read? ++ iSectorCount = std::min(iSectorCount, m_lsnEnd - m_lsnCurrent); ++ ++ // Have we reached EOF? ++ if (iSectorCount == 0) ++ { ++ CLog::Log(LOGNOTICE, "file cdda: Read EoF"); ++ return 0; // Success, but nothing read ++ } // Reached EoF ++ ++ // At leat one sector to read ++ int retries; ++ int iret; ++ // Try reading a decresing number of sectors, then 3 times with 1 sector ++ for (retries = 3; retries > 0; iSectorCount>1 ? iSectorCount-- : retries--) ++ { ++ iret = m_cdio->cdio_read_audio_sectors(m_pCdIo, destBuf, m_lsnCurrent, iSectorCount); + if (iret == DRIVER_OP_SUCCESS) ++ break; // Get out from the loop ++ else + { +- // If lower iSectorCount solved the problem limit it's value +- if (iSectorCount < big_iSectorCount) +- { +- m_iSectorCount = iSectorCount; +- } +- break; +- } +- +- // iSectorCount is low so it cannot solve read problem +- if (iSectorCount <= 10) +- { +- CLog::Log(LOGERROR, "file cdda: Reading %d sectors of audio data starting at lsn %d failed with error code %i", iSectorCount, m_lsnCurrent, iret); +- return -1; +- } +- +- iSectorCount = 10; ++ CLog::Log(LOGERROR, "file cdda: Read cdio error when reading track "); ++ } // Errors when reading file + } ++ // retries == 0 only if failed reading at least one sector ++ if (retries == 0) ++ { ++ CLog::Log(LOGERROR, "file cdda: Reading %d sectors of audio data starting at lsn %d failed with error code %i", iSectorCount, m_lsnCurrent, iret); ++ return -1; ++ } ++ ++ // Update position in file + m_lsnCurrent += iSectorCount; + ++ // Was it a short request? ++ if (uiBufSize < CDIO_CD_FRAMESIZE_RAW) ++ { ++ // We copy the amount if requested data into the destination buffer ++ memcpy(lpBuf, m_TrackBuf, uiBufSize); ++ // and keep track of the first available data ++ p_TrackBuf = uiBufSize; ++ // Finally, we set the buffer flag as TRUE ++ f_TrackBuf = true; ++ // We will return uiBufSize ++ return uiBufSize; ++ } ++ ++ // Otherwise, just return the size of read data + return iSectorCount*CDIO_CD_FRAMESIZE_RAW; + } + +@@ -195,6 +250,9 @@ int64_t CFileCDDA::Seek(int64_t iFilePosition, int iWhence /*=SEEK_SET*/) + + void CFileCDDA::Close() + { ++ // Flag TrackBuffer = FALSE, TrackBuffer is empty ++ f_TrackBuf = 0; ++ + if (m_pCdIo) + { + m_cdio->cdio_destroy(m_pCdIo); +diff --git a/xbmc/filesystem/CDDAFile.h b/xbmc/filesystem/CDDAFile.h +index 0427af4..e992362 100644 +--- a/xbmc/filesystem/CDDAFile.h ++++ b/xbmc/filesystem/CDDAFile.h +@@ -50,6 +50,9 @@ class CFileCDDA : public IFile + + protected: + CdIo_t* m_pCdIo; ++ uint8_t *m_TrackBuf; ++ size_t p_TrackBuf; ++ int f_TrackBuf; + lsn_t m_lsnStart; // Start of m_iTrack in logical sector number + lsn_t m_lsnCurrent; // Position inside the track in logical sector number + lsn_t m_lsnEnd; // End of m_iTrack in logical sector number + +From c7b9583bbbb32ff28b10517e2eb654764c592a03 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 20 Feb 2015 14:11:57 +0000 +Subject: [PATCH 62/95] libavformat: add mvcC handling in .mov/.mp4 + +--- + ...ibavformat-add-mvcC-handling-in-.mov-.mp4.patch | 57 ++++++++++++++++++++++ + tools/depends/target/ffmpeg/Makefile | 3 +- + 2 files changed, 59 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + +diff --git a/tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch b/tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch +new file mode 100644 +index 0000000..72fbcb9 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch +@@ -0,0 +1,57 @@ ++From 40bca2ae81bb9cd131b90bf262e976674ca6fab8 Mon Sep 17 00:00:00 2001 ++From: Deborah Crook ++Date: Fri, 16 Jan 2015 14:24:17 +0000 ++Subject: [PATCH] libavformat: add mvcC handling in .mov/.mp4 ++ ++--- ++ libavformat/mov.c | 28 ++++++++++++++++++++++++++++ ++ 1 file changed, 28 insertions(+) ++ ++diff --git a/libavformat/mov.c b/libavformat/mov.c ++index 7455e3b..29bfec9 100644 ++--- a/libavformat/mov.c +++++ b/libavformat/mov.c ++@@ -1201,6 +1201,33 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) ++ return 0; ++ } ++ +++static int mov_read_mvcc(MOVContext *c, AVIOContext *pb, MOVAtom atom) +++{ +++ int extradata_size; +++ int ret, i; +++ uint32_t n; +++ AVStream *st; +++ +++ if (c->fc->nb_streams < 1) +++ return 0; +++ st = c->fc->streams[c->fc->nb_streams-1]; +++ extradata_size = st->codec->extradata_size; +++ +++ if ((uint64_t)atom.size > (1<<30)) +++ return AVERROR_INVALIDDATA; +++ +++ if (extradata_size == 0) +++ return 0; +++ if ((ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_H264)) < 0) +++ return ret; +++ for (i = 0, n = 0; i < 4; i++) +++ n = (n << 8) | st->codec->extradata[extradata_size+i]; +++ n -= 4; +++ for (i = 0; i < 4; i++) +++ st->codec->extradata[extradata_size+i] = (n >> ((3 - i) << 3)) & 0xff; +++ return 0; +++} +++ ++ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) ++ { ++ AVStream *st; ++@@ -3383,6 +3410,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { ++ { MKTAG('C','i','n', 0x8e), mov_read_targa_y216 }, ++ { MKTAG('f','r','e','e'), mov_read_free }, ++ { MKTAG('-','-','-','-'), mov_read_custom }, +++{ MKTAG('m','v','c','C'), mov_read_mvcc }, ++ { 0, NULL } ++ }; ++ ++-- ++1.7.10.4 +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 6e8364a..43dc4ff 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,6 +1,6 @@ + include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -69,6 +69,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure + cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch ++ cd $(PLATFORM); patch -p1 < ../0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) + +From 005ffd4613a34a1a3fca74bdb4fda56abe27cdf3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 00:09:19 +0000 +Subject: [PATCH 63/95] [omxplayer] Limit subtitle updates to 10fps to avoid + stuttering with closed captions + +--- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 4e599e3..b32bd7f 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -222,7 +222,7 @@ double OMXPlayerVideo::NextOverlay(double pts) + else if (delta_stop > 0.0 && (min_delta == DVD_NOPTS_VALUE || delta_stop < min_delta)) + min_delta = delta_stop; + } +- return min_delta == DVD_NOPTS_VALUE ? pts+DVD_MSEC_TO_TIME(500) : pts+min_delta; ++ return min_delta == DVD_NOPTS_VALUE ? pts+DVD_MSEC_TO_TIME(500) : pts+std::max(min_delta, DVD_MSEC_TO_TIME(100)); + } + + +@@ -306,9 +306,9 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket) + double subtitle_pts = m_nextOverlay; + double time = subtitle_pts != DVD_NOPTS_VALUE ? subtitle_pts - media_pts : 0.0; + +- m_nextOverlay = NextOverlay(media_pts); ++ m_nextOverlay = NextOverlay(media_pts + preroll); + +- ProcessOverlays(media_pts); ++ ProcessOverlays(media_pts + preroll); + + time += m_av_clock->GetAbsoluteClock(); + g_renderManager.FlipPage(CThread::m_bStop, time/DVD_TIME_BASE); + +From 8b17d6c5a5d574f554e0b6431df3a8066ef33ce6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 15:57:29 +0000 +Subject: [PATCH 64/95] [mmalrenderer] Fix for stereo view modes + +PR6090 (dirty regions for video) meant that RenderUpate is no longer called with the expected stereo view mode. +So, just explicitly set this before calling ManageDisplay to get the desired rectangles +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index ebc4458..b9d9cd9 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -346,7 +346,11 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + + if (!m_bConfigured) return; + ++ if (g_graphicsContext.GetStereoMode()) ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); + ManageDisplay(); ++ if (g_graphicsContext.GetStereoMode()) ++ g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); + + // if running bypass, then the player might need the src/dst rects + // for sizing video playback on a layer other than the gles layer. + +From 769d01896f4538de56d374838775a93f49f89972 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 14:37:27 +0000 +Subject: [PATCH 65/95] ffmpeg: Add some upstream HEVC optimisations + +--- + tools/depends/target/ffmpeg/Makefile | 5 +- + ...hevcdsp_ARM_NEON_optimized_epel_functions.patch | 406 +++++++++++++++++++++ + 2 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch + +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 43dc4ff..757721c 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,6 +1,7 @@ + include ../../Makefile.include + include FFMPEG-VERSION +-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch ++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch \ ++ hevcdsp_ARM_NEON_optimized_epel_functions.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -70,6 +71,8 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); sed -i".bak" -e "s%pkg_config_default=pkg-config%export PKG_CONFIG_LIBDIR=$(PREFIX)/lib/pkgconfig \&\& pkg_config_default=$(NATIVEPREFIX)/bin/pkg-config%" configure + cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch + cd $(PLATFORM); patch -p1 < ../0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch ++ cd $(PLATFORM); patch -p1 < ../hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + ./configure $(ffmpg_config) +diff --git a/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch b/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch +new file mode 100644 +index 0000000..de95ba6 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/hevcdsp_ARM_NEON_optimized_epel_functions.patch +@@ -0,0 +1,406 @@ ++From 5114c6fb870fe3aea5da05ea218760a47a29ad74 Mon Sep 17 00:00:00 2001 ++From: Seppo Tomperi ++Date: Thu, 5 Feb 2015 13:32:28 +0000 ++Subject: [PATCH] hevcdsp: ARM NEON optimized epel functions ++ ++--- ++ libavcodec/arm/Makefile | 1 + ++ libavcodec/arm/hevcdsp_epel_neon.S | 334 +++++++++++++++++++++++++++++++++++++ ++ libavcodec/arm/hevcdsp_init_neon.c | 23 +++ ++ 3 files changed, 358 insertions(+) ++ create mode 100644 libavcodec/arm/hevcdsp_epel_neon.S ++ ++diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile ++index 434a2d1..95eb814 100644 ++--- a/libavcodec/arm/Makefile +++++ b/libavcodec/arm/Makefile ++@@ -134,6 +134,7 @@ NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ ++ arm/synth_filter_neon.o ++ NEON-OBJS-$(CONFIG_HEVC_DECODER) += arm/hevcdsp_init_neon.o \ ++ arm/hevcdsp_deblock_neon.o \ +++ arm/hevcdsp_epel_neon.o \ ++ arm/hevcdsp_idct_neon.o \ ++ arm/hevcdsp_qpel_neon.o ++ NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o ++diff --git a/libavcodec/arm/hevcdsp_epel_neon.S b/libavcodec/arm/hevcdsp_epel_neon.S ++new file mode 100644 ++index 0000000..424416d ++--- /dev/null +++++ b/libavcodec/arm/hevcdsp_epel_neon.S ++@@ -0,0 +1,334 @@ +++/* +++ * Copyright (c) 2014 - 2015 Seppo Tomperi +++ * +++ * This file is part of FFmpeg. +++ * +++ * FFmpeg is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU Lesser General Public +++ * License as published by the Free Software Foundation; either +++ * version 2.1 of the License, or (at your option) any later version. +++ * +++ * FFmpeg is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ * Lesser General Public License for more details. +++ * +++ * You should have received a copy of the GNU Lesser General Public +++ * License along with FFmpeg; if not, write to the Free Software +++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ */ +++ +++#include "libavutil/arm/asm.S" +++#include "neon.S" +++ +++#define MAX_PB_SIZE #64 +++ +++.macro vextin_d4 +++ vld1.8 {q10}, [r1], r2 +++ vmov d16, d20 +++ vext.8 d17, d20, d21, #1 +++ vext.8 d18, d20, d21, #2 +++ vext.8 d19, d20, d21, #3 +++.endm +++ +++.macro vextin_d4_8 +++ vld1.8 d16, [r1], r2 +++ vext.8 d17, d16, d16, #1 +++ vext.8 d18, d16, d16, #2 +++ vext.8 d19, d16, d16, #3 +++.endm +++ +++.macro load_coeffs_16b coeffs +++ ldr \coeffs, [\coeffs] +++ vdup.i8 d0, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d1, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d2, \coeffs +++ lsr \coeffs, #8 +++ vdup.i8 d3, \coeffs +++.endm +++ +++.macro epel_filter_16b out=q12 +++ vmull.u8 q3, d16, d0 +++ vmull.u8 q11, d19, d3 +++ vmull.u8 \out, d17, d1 +++ vmull.u8 q10, d18, d2 +++ vadd.s16 q3, q11 +++ vadd.s16 \out, q10 +++ vsub.s16 \out, q3 +++.endm +++ +++.macro load_coeffs_32b coeffs +++ ldr \coeffs, [\coeffs] +++ vmov.i64 d4, #0 +++ vmov.8 d4[0], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[2], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[4], \coeffs +++ lsr \coeffs, #8 +++ vmov.8 d4[6], \coeffs +++.endm +++ +++.macro epel_filter_32b +++ vmull.s16 q3, d24, d4[0] //q12 +++ vmull.s16 q4, d25, d4[0] +++ vmull.s16 q5, d30, d4[3] //q15 +++ vmull.s16 q6, d31, d4[3] +++ +++ vmull.s16 q7, d26, d4[1] // q13 +++ vmull.s16 q8, d27, d4[1] +++ vmull.s16 q9, d28, d4[2] // q14 +++ vmull.s16 q10, d29, d4[2] +++ vadd.s32 q3, q5 +++ vadd.s32 q4, q6 +++ vadd.s32 q7, q9 +++ vadd.s32 q8, q10 +++ vsub.s32 q7, q3 +++ vsub.s32 q8, q4 +++ vqshrn.s32 d6, q7, #6 +++ vqshrn.s32 d7, q8, #6 +++.endm +++ +++.macro epel_filter_32b_4 +++ vmull.s16 q3, d24, d4[0] //q12 +++ vmull.s16 q5, d30, d4[3] //q15 +++ vmull.s16 q7, d26, d4[1] // q13 +++ vmull.s16 q9, d28, d4[2] // q14 +++ vadd.s32 q3, q5 +++ vadd.s32 q7, q9 +++ vsub.s32 q7, q3 +++ vqshrn.s32 d6, q7, #6 +++.endm +++ +++function ff_hevc_put_epel_h_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r7, [sp, #16] // mx +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ add r7, r12 +++ sub r1, #1 +++ lsl r4, #1 +++ load_coeffs_16b r7 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: subs r3, #1 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b +++ vst1.16 {q12}, [r0], r4 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ cmp r5, #4 +++ bgt 8b +++4: subs r3, #1 +++ pld [r1] +++ vextin_d4_8 +++ epel_filter_16b +++ vst1.16 d24, [r0], r4 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++2: subs r3, #1 +++ pld [r1] +++ vextin_d4_8 +++ epel_filter_16b +++ vst1.32 d24[0], [r0], r4 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++function ff_hevc_put_epel_v_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r7, [sp, #20] // my +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ add r7, r12 +++ load_coeffs_16b r7 +++ sub r1, r2 +++ lsl r4, #1 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++0: pld [r1] +++ vld1.8 {d16}, [r1], r2 +++ pld [r1] +++ vld1.8 {d17}, [r1], r2 +++ pld [r1] +++ vld1.8 {d18}, [r1], r2 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.16 {q12}, [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ b 0b +++4: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.16 d24, [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++ b 0b +++2: pld [r1] +++ vld1.8 {d19}, [r1], r2 +++ subs r3, #1 +++ epel_filter_16b +++ vst1.32 d24[0], [r0], r4 +++ vmov d16, d17 +++ vmov d17, d18 +++ vmov d18, d19 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++function ff_hevc_put_epel_hv_neon_8, export=1 +++ push {r4-r7} +++ mov r4, MAX_PB_SIZE +++ ldr r6, [sp, #16] // mx +++ ldr r7, [sp, #20] // my +++ ldr r5, [sp, #24] // width +++ sub r7, #1 +++ lsl r7, #2 +++ vpush {d8-d15} +++ adrl r12, epel_coeffs +++ sub r6, #1 +++ lsl r6, #2 +++ add r6, r12 // mx epel coeff offset +++ add r7, r12 +++ sub r1, #1 +++ sub r1, r2 +++ lsl r4, #1 +++ load_coeffs_16b r6 +++ load_coeffs_32b r7 +++ mov r12, r3 +++ mov r6, r0 +++ mov r7, r1 +++0: pld [r1] +++ vextin_d4 +++ epel_filter_16b q12 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b q13 +++ pld [r1] +++ vextin_d4 +++ epel_filter_16b q14 +++ cmp r5, #6 +++ bgt 8f +++ cmp r5, #4 +++ blt 2f +++ b 4f +++8: pld [r1] +++ vextin_d4 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b +++ vst1.16 {q3}, [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 8b +++ subs r5, #8 +++ beq 99f +++ mov r3, r12 +++ add r6, #16 +++ mov r0, r6 +++ add r7, #8 +++ mov r1, r7 +++ b 0b +++4: pld [r1] +++ vextin_d4_8 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b_4 +++ vst1.16 d6, [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 4b +++ subs r5, #4 +++ beq 99f +++ mov r3, r12 +++ add r6, #8 +++ mov r0, r6 +++ add r7, #4 +++ mov r1, r7 +++ b 0b +++2: pld [r1] +++ vextin_d4_8 +++ epel_filter_16b q15 +++ subs r3, #1 +++ epel_filter_32b_4 +++ vst1.32 d6[0], [r0], r4 +++ vmov q12, q13 +++ vmov q13, q14 +++ vmov q14, q15 +++ bne 2b +++99: vpop {d8-d15} +++ pop {r4-r7} +++ bx lr +++endfunc +++ +++epel_coeffs: +++ .byte 2, 58, 10, 2 +++ .byte 4, 54, 16, 2 +++ .byte 6, 46, 28, 4 +++ .byte 4, 36, 36, 4 +++ .byte 4, 28, 46, 6 +++ .byte 2, 16, 54, 4 +++ .byte 2, 10, 58, 2 ++diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c ++index 61e6462..917abc4 100644 ++--- a/libavcodec/arm/hevcdsp_init_neon.c +++++ b/libavcodec/arm/hevcdsp_init_neon.c ++@@ -57,6 +57,15 @@ PUT_PIXELS(ff_hevc_put_pixels_w32_neon_8); ++ PUT_PIXELS(ff_hevc_put_pixels_w48_neon_8); ++ PUT_PIXELS(ff_hevc_put_pixels_w64_neon_8); ++ #undef PUT_PIXELS +++void ff_hevc_put_epel_h_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); +++void ff_hevc_put_epel_v_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); +++void ff_hevc_put_epel_hv_neon_8(int16_t *dst, uint8_t *src, +++ ptrdiff_t srcstride, int height, +++ intptr_t mx, intptr_t my, int width); ++ ++ static void (*put_hevc_qpel_neon[4][4])(int16_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, ++ int height, int width); ++@@ -201,7 +210,21 @@ static av_cold void hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth) ++ c->put_hevc_qpel_bi[x][1][0] = ff_hevc_put_qpel_bi_neon_wrapper; ++ c->put_hevc_qpel_bi[x][0][1] = ff_hevc_put_qpel_bi_neon_wrapper; ++ c->put_hevc_qpel_bi[x][1][1] = ff_hevc_put_qpel_bi_neon_wrapper; +++ c->put_hevc_epel[x][1][0] = ff_hevc_put_epel_v_neon_8; +++ c->put_hevc_epel[x][0][1] = ff_hevc_put_epel_h_neon_8; +++ c->put_hevc_epel[x][1][1] = ff_hevc_put_epel_hv_neon_8; ++ } +++ c->put_hevc_epel[0][0][0] = ff_hevc_put_pixels_w2_neon_8; +++ c->put_hevc_epel[1][0][0] = ff_hevc_put_pixels_w4_neon_8; +++ c->put_hevc_epel[2][0][0] = ff_hevc_put_pixels_w6_neon_8; +++ c->put_hevc_epel[3][0][0] = ff_hevc_put_pixels_w8_neon_8; +++ c->put_hevc_epel[4][0][0] = ff_hevc_put_pixels_w12_neon_8; +++ c->put_hevc_epel[5][0][0] = ff_hevc_put_pixels_w16_neon_8; +++ c->put_hevc_epel[6][0][0] = ff_hevc_put_pixels_w24_neon_8; +++ c->put_hevc_epel[7][0][0] = ff_hevc_put_pixels_w32_neon_8; +++ c->put_hevc_epel[8][0][0] = ff_hevc_put_pixels_w48_neon_8; +++ c->put_hevc_epel[9][0][0] = ff_hevc_put_pixels_w64_neon_8; +++ ++ c->put_hevc_qpel[0][0][0] = ff_hevc_put_pixels_w2_neon_8; ++ c->put_hevc_qpel[1][0][0] = ff_hevc_put_pixels_w4_neon_8; ++ c->put_hevc_qpel[2][0][0] = ff_hevc_put_pixels_w6_neon_8; + +From d137a1d0d7d29115c6764efec13d8ffff66335c1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 19:07:17 +0000 +Subject: [PATCH 66/95] [omxplayer] Attempt to fix missing subtitles after seek + +--- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index b32bd7f..8becff1 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -296,7 +296,7 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket) + const double preroll = DVD_MSEC_TO_TIME(100); + double media_pts = m_av_clock->OMXMediaTime(); + +- if (m_nextOverlay != DVD_NOPTS_VALUE && media_pts + preroll <= m_nextOverlay) ++ if (m_nextOverlay != DVD_NOPTS_VALUE && media_pts != 0.0 && media_pts + preroll <= m_nextOverlay) + return; + + int buffer = g_renderManager.WaitForBuffer(CThread::m_bStop); + +From b5afc5f7e110f8f0e28fb8b634a8bafd01259573 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Wed, 25 Feb 2015 18:22:21 +0100 +Subject: [PATCH 67/95] Load OSD dialogs on startup. + +Fixes skipped frames the first time they're loaded in memory on less powered +devices, like a Raspberry Pi, when using DVDPlayer. +See http://forum.kodi.tv/showthread.php?tid=211501&pid=1938811#pid1938811 +--- + xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp | 1 + + xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp | 1 + + xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp | 4 +++- + xbmc/video/dialogs/GUIDialogSubtitles.cpp | 2 +- + xbmc/video/dialogs/GUIDialogVideoOSD.cpp | 2 +- + xbmc/video/dialogs/GUIDialogVideoSettings.cpp | 4 +++- + 6 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp +index 499f926..9f85783 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp +@@ -50,6 +50,7 @@ CGUIDialogPVRChannelsOSD::CGUIDialogPVRChannelsOSD() : + CGUIDialog(WINDOW_DIALOG_PVR_OSD_CHANNELS, "DialogPVRChannelsOSD.xml"), + Observer() + { ++ m_loadType = LOAD_ON_GUI_INIT; + m_vecItems = new CFileItemList; + } + +diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp +index 1670190..329a3b8 100644 +--- a/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp ++++ b/xbmc/pvr/dialogs/GUIDialogPVRGuideOSD.cpp +@@ -35,6 +35,7 @@ using namespace PVR; + CGUIDialogPVRGuideOSD::CGUIDialogPVRGuideOSD() + : CGUIDialog(WINDOW_DIALOG_PVR_OSD_GUIDE, "DialogPVRGuideOSD.xml") + { ++ m_loadType = LOAD_ON_GUI_INIT; + m_vecItems = new CFileItemList; + } + +diff --git a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +index 55a72e9..f5d6ffc 100644 +--- a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp ++++ b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +@@ -62,7 +62,9 @@ using namespace std; + CGUIDialogAudioSubtitleSettings::CGUIDialogAudioSubtitleSettings() + : CGUIDialogSettingsManualBase(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "VideoOSDSettings.xml"), + m_passthrough(false) +-{ } ++{ ++ m_loadType = LOAD_ON_GUI_INIT; ++} + + CGUIDialogAudioSubtitleSettings::~CGUIDialogAudioSubtitleSettings() + { } +diff --git a/xbmc/video/dialogs/GUIDialogSubtitles.cpp b/xbmc/video/dialogs/GUIDialogSubtitles.cpp +index 5da2daa..a7fc7a0 100644 +--- a/xbmc/video/dialogs/GUIDialogSubtitles.cpp ++++ b/xbmc/video/dialogs/GUIDialogSubtitles.cpp +@@ -100,7 +100,7 @@ class CSubtitlesJob: public CJob + CGUIDialogSubtitles::CGUIDialogSubtitles(void) + : CGUIDialog(WINDOW_DIALOG_SUBTITLES, "DialogSubtitles.xml") + { +- m_loadType = KEEP_IN_MEMORY; ++ m_loadType = LOAD_ON_GUI_INIT; + m_subtitles = new CFileItemList; + m_serviceItems = new CFileItemList; + m_pausedOnRun = false; +diff --git a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp +index 8a856e1..18b25fd 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp +@@ -35,7 +35,7 @@ using namespace PVR; + CGUIDialogVideoOSD::CGUIDialogVideoOSD(void) + : CGUIDialog(WINDOW_DIALOG_VIDEO_OSD, "VideoOSD.xml") + { +- m_loadType = KEEP_IN_MEMORY; ++ m_loadType = LOAD_ON_GUI_INIT; + } + + CGUIDialogVideoOSD::~CGUIDialogVideoOSD(void) +diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +index 4940561..f52698c 100644 +--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp ++++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +@@ -64,7 +64,9 @@ using namespace std; + CGUIDialogVideoSettings::CGUIDialogVideoSettings() + : CGUIDialogSettingsManualBase(WINDOW_DIALOG_VIDEO_OSD_SETTINGS, "VideoOSDSettings.xml"), + m_viewModeChanged(false) +-{ } ++{ ++ m_loadType = LOAD_ON_GUI_INIT; ++} + + CGUIDialogVideoSettings::~CGUIDialogVideoSettings() + { } + +From 1ace25f5d8722f5df80c23756e52f8d434db589a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 4 Mar 2015 20:15:18 +0000 +Subject: [PATCH 68/95] test: fix for dirty rendering with skipped updates + +--- + xbmc/Application.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index fb38cd3..edb4271 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -1979,6 +1979,8 @@ void CApplication::Render() + if (RenderNoPresent()) + hasRendered = true; + } ++ // execute post rendering actions (finalize window closing) ++ g_windowManager.AfterRender(); + } + + // render video layer +@@ -1986,9 +1988,6 @@ void CApplication::Render() + + g_Windowing.EndRender(); + +- // execute post rendering actions (finalize window closing) +- g_windowManager.AfterRender(); +- + // reset our info cache - we do this at the end of Render so that it is + // fresh for the next process(), or after a windowclose animation (where process() + // isn't called) + +From 09745d35cbd1b89639ba77bf83560558e3f3f784 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 5 Mar 2015 20:00:59 +0000 +Subject: [PATCH 69/95] [ffmpmeg] Discard data before VO/VOL in mpeg-4 over + mpegts + +--- + ...-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch | 69 ++++++++++++++++++++++ + tools/depends/target/ffmpeg/Makefile | 4 +- + 2 files changed, 72 insertions(+), 1 deletion(-) + create mode 100644 tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + +diff --git a/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch b/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch +new file mode 100644 +index 0000000..eef7385 +--- /dev/null ++++ b/tools/depends/target/ffmpeg/0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch +@@ -0,0 +1,69 @@ ++From ff289b3678b3b102f76c0fc0ffc802e3c8026fdb Mon Sep 17 00:00:00 2001 ++From: Deborah Crook ++Date: Thu, 5 Mar 2015 19:48:43 +0000 ++Subject: [PATCH] Discard data before VO/VOL in mpeg-4 over mpegts ++ ++--- ++ libavcodec/mpeg4video_parser.c | 26 ++++++++++++++++++++++---- ++ 1 file changed, 22 insertions(+), 4 deletions(-) ++ ++diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c ++index aa5e87a..0d8b15a 100644 ++--- a/libavcodec/mpeg4video_parser.c +++++ b/libavcodec/mpeg4video_parser.c ++@@ -43,18 +43,32 @@ int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) ++ state = pc->state; ++ ++ i = 0; ++- if (!vop_found) { +++ if (vop_found < 0) { +++ for (i = 0; i < buf_size; i++) { +++ state = (state << 8) | buf[i]; +++ if (state >= 0x100 && state <= 0x12f) { +++ i++; +++ vop_found = 0; +++ break; +++ } +++ } +++ } +++ +++ if (vop_found == 0) +++ vop_found = 1; +++ +++ if (vop_found == 1) { ++ for (i = 0; i < buf_size; i++) { ++ state = (state << 8) | buf[i]; ++ if (state == 0x1B6) { ++ i++; ++- vop_found = 1; +++ vop_found = 2; ++ break; ++ } ++ } ++ } ++ ++- if (vop_found) { +++ if (vop_found == 2) { ++ /* EOF considered as end of frame */ ++ if (buf_size == 0) ++ return 0; ++@@ -133,12 +147,16 @@ static int mpeg4video_parse(AVCodecParserContext *s, ++ ParseContext *pc = s->priv_data; ++ int next; ++ +++ if (pc->frame_start_found == 0 && !avctx->extradata) +++ pc->frame_start_found = -1; +++ ++ if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { ++ next = buf_size; ++ } else { ++ next = ff_mpeg4_find_frame_end(pc, buf, buf_size); ++ ++- if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { +++ if (pc->frame_start_found < 0 || +++ ff_combine_frame(pc, next, &buf, &buf_size) < 0) { ++ *poutbuf = NULL; ++ *poutbuf_size = 0; ++ return buf_size; ++-- ++2.1.4 +diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile +index 757721c..fbef09a 100644 +--- a/tools/depends/target/ffmpeg/Makefile ++++ b/tools/depends/target/ffmpeg/Makefile +@@ -1,7 +1,8 @@ + include ../../Makefile.include + include FFMPEG-VERSION + DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch 0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch \ +- hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ hevcdsp_ARM_NEON_optimized_epel_functions.patch \ ++ 0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + + # set to "yes" to enable patching + # we don't apply patches until we move to a vanilla ffmpeg tarball +@@ -72,6 +73,7 @@ $(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + cd $(PLATFORM); patch -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch + cd $(PLATFORM); patch -p1 < ../0001-libavformat-add-mvcC-handling-in-.mov-.mp4.patch + cd $(PLATFORM); patch -p1 < ../hevcdsp_ARM_NEON_optimized_epel_functions.patch ++ cd $(PLATFORM); patch -p1 < ../0001-Discard-data-before-VO-VOL-in-mpeg-4-over-mpegts.patch + + cd $(PLATFORM);\ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \ + +From c5a96aa31d597241d2cf42acaa81761827ab2136 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 7 Mar 2015 22:46:21 +0000 +Subject: [PATCH 70/95] configure: Add raspberry-pi2 platform + +--- + configure.ac | 14 +++++++-- + m4/xbmc_arch.m4 | 8 ++--- + tools/depends/Makefile.include.in | 2 +- + tools/depends/configure.ac | 38 ++++++++++++++++------- + tools/depends/target/Toolchain.cmake.in | 2 +- + tools/depends/target/Toolchain_binaddons.cmake.in | 2 +- + 6 files changed, 44 insertions(+), 22 deletions(-) + +diff --git a/configure.ac b/configure.ac +index fb7c782..129c57a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -746,8 +746,17 @@ case $use_platform in + raspberry-pi) + target_platform=target_raspberry_pi + use_neon=no +- use_arch="arm" + use_cpu=arm1176jzf-s ++ ;; ++ raspberry-pi2) ++ target_platform=target_raspberry_pi ++ use_neon=yes ++ use_cpu=cortex-a7 ++ ;; ++esac ++ ++if test "$target_platform" = "target_raspberry_pi" ; then ++ use_arch="arm" + use_hardcoded_tables="yes" + ARCH="arm" + AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) +@@ -755,8 +764,7 @@ case $use_platform in + USE_MMAL=1; AC_DEFINE([HAS_MMAL],[1],["Define to 1 if MMAL libs is enabled"]) + CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS" +- ;; +-esac ++fi + + XBMC_SETUP_ARCH_DEFINES() + +diff --git a/m4/xbmc_arch.m4 b/m4/xbmc_arch.m4 +index 0b66a82..adb8e97 100644 +--- a/m4/xbmc_arch.m4 ++++ b/m4/xbmc_arch.m4 +@@ -77,9 +77,7 @@ if test "$target_platform" = "target_android" ; then + AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -DTARGET_ANDROID") + fi + +-case $use_platform in +- raspberry-pi) +- AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_ARMEL -DTARGET_RASPBERRY_PI") +- ;; +-esac ++if test "$target_platform" = "target_raspberry_pi" ; then ++ AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_ARMEL -DTARGET_RASPBERRY_PI") ++fi + ]) +diff --git a/tools/depends/Makefile.include.in b/tools/depends/Makefile.include.in +index e1ac05c..d60cccf 100644 +--- a/tools/depends/Makefile.include.in ++++ b/tools/depends/Makefile.include.in +@@ -20,7 +20,7 @@ NATIVE_OS=@build_os@ + CROSS_COMPILING=@cross_compiling@ + ARCH_DEFINES=@ARCH_DEFINES@ + NATIVE_ARCH_DEFINES=@NATIVE_ARCH_DEFINES@ +-TARGET_PLATFORM=@use_platform@ ++TARGET_PLATFORM=@target_platform@ + XCODE_VERSION=@use_xcode@ + AAPT=@AAPT@ + DX=@DX@ +diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac +index f21af0b..74060b1 100644 +--- a/tools/depends/configure.ac ++++ b/tools/depends/configure.ac +@@ -17,7 +17,8 @@ AC_ARG_WITH([toolchain], + AC_ARG_WITH([platform], + [AS_HELP_STRING([--with-platform], + [target platform [auto]])], +- [use_platform=$withval]) ++ [use_platform=$withval], ++ [target_platform=$withval]) + + AC_ARG_WITH([firmware], + [AS_HELP_STRING([--with-firmware], +@@ -305,34 +306,49 @@ case $host in + AC_MSG_ERROR(unsupported host ($use_host)) + esac + +-if test "$use_platform" = "raspberry-pi"; then ++case $use_platform in ++ raspberry-pi) ++ target_platform=raspberry_pi ++ use_neon=no ++ use_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_neon=yes ++ use_cpu=cortex-a7 ++ platform_cflags="-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4" ++ platform_cxxflags="-fPIC -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4" ++ platform_ldflags="-lpthread" ++ ;; ++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_neon=no + use_arch="arm" +- use_cpu="arm1176jzf-s" + use_hardcoded_tables="yes" +- use_alsa="no" + ARCH="arm" + platform_os="linux" + cross_compiling="yes" + use_host="arm-linux-gnueabihf" + deps_dir="$use_host" +- platform_cflags="-pipe -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mfloat-abi=hard \ +- -mfpu=vfp -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated \ +- -Wno-deprecated-declarations -isystem${use_firmware}/opt/vc/include \ ++ 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 -mcpu=arm1176jzf-s -mtune=arm1176jzf-s \ +- -mfloat-abi=hard -mfpu=vfp -mabi=aapcs-linux -Wno-psabi \ ++ 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 \ ++ platform_ldflags+=" -L${use_firmware}/opt/vc/lib -lEGL -lGLESv2 -lbcm_host -lvcos \ + -lvchiq_arm" + fi + +diff --git a/tools/depends/target/Toolchain.cmake.in b/tools/depends/target/Toolchain.cmake.in +index 943be73..59385e8 100644 +--- a/tools/depends/target/Toolchain.cmake.in ++++ b/tools/depends/target/Toolchain.cmake.in +@@ -1,6 +1,6 @@ + SET(OS "@platform_os@") + SET(CPU "@use_cpu@") +-SET(PLATFORM "@use_platform@") ++SET(PLATFORM "@target_platform@") + IF("${OS}" STREQUAL "linux" OR "${OS}" STREQUAL "android") + SET(CMAKE_SYSTEM_NAME Linux) + ENDIF() +diff --git a/tools/depends/target/Toolchain_binaddons.cmake.in b/tools/depends/target/Toolchain_binaddons.cmake.in +index cdc2fe4..379bd1d 100644 +--- a/tools/depends/target/Toolchain_binaddons.cmake.in ++++ b/tools/depends/target/Toolchain_binaddons.cmake.in +@@ -1,7 +1,7 @@ + set(CMAKE_SYSTEM_VERSION 1) + set(OS "@platform_os@") + set(CPU "@use_cpu@") +-set(PLATFORM "@use_platform@") ++set(PLATFORM "@target_platform@") + if("${OS}" STREQUAL "linux" OR "${OS}" STREQUAL "android") + set(CMAKE_SYSTEM_NAME Linux) + endif() + +From f3f95dcbb1a5533babac13a1e76b75d897d3f626 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 16 Apr 2014 21:18:06 +0100 +Subject: [PATCH 71/95] [omxplayer] Don't propagate 3d flags based on supported + 3d modes + +--- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 29 +++-------------------------- + 1 file changed, 3 insertions(+), 26 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 8becff1..86d97bd 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -763,40 +763,17 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f + uint32_t video_width = CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth; + uint32_t video_height = CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight; + +- unsigned flags = 0; + ERenderFormat format = RENDER_FMT_BYPASS; + ++ /* figure out steremode expected based on user settings and hints */ ++ unsigned flags = GetStereoModeFlags(GetStereoMode()); ++ + if(m_bAllowFullscreen) + { + flags |= CONF_FLAGS_FULLSCREEN; + m_bAllowFullscreen = false; // only allow on first configure + } + +- flags |= GetStereoModeFlags(GetStereoMode()); +- +- if(flags & CONF_FLAGS_STEREO_MODE_SBS) +- { +- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS)) +- CLog::Log(LOGNOTICE, "3DSBS movie found"); +- else +- { +- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); +- CLog::Log(LOGNOTICE, "3DSBS movie found but not supported"); +- } +- } +- else if(flags & CONF_FLAGS_STEREO_MODE_TAB) +- { +- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB)) +- CLog::Log(LOGNOTICE, "3DTB movie found"); +- else +- { +- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0); +- CLog::Log(LOGNOTICE, "3DTB movie found but not supported"); +- } +- } +- else +- CLog::Log(LOGNOTICE, "not a 3D movie"); +- + unsigned int iDisplayWidth = width; + unsigned int iDisplayHeight = height; + + +From b1b33de65735c6a374a0bafd86c971a8249c42af Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:01:51 +0100 +Subject: [PATCH 72/95] [graphics] Allow switching to a more suitable 3D + resolution + +--- + xbmc/guilib/GraphicContext.cpp | 40 +++++++++++++++++++++++++++++++++++++++- + xbmc/guilib/GraphicContext.h | 1 + + 2 files changed, 40 insertions(+), 1 deletion(-) + +diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp +index 58406f7..a476cd8 100644 +--- a/xbmc/guilib/GraphicContext.cpp ++++ b/xbmc/guilib/GraphicContext.cpp +@@ -35,6 +35,7 @@ + #include "utils/JobManager.h" + #include "video/VideoReferenceClock.h" + #include "cores/IPlayer.h" ++#include + + using namespace std; + +@@ -500,6 +501,43 @@ RESOLUTION CGraphicContext::GetVideoResolution() const + return m_Resolution; + } + ++RESOLUTION CGraphicContext::Get3DVideoResolution(RESOLUTION resolution, RENDER_STEREO_MODE mode) const ++{ ++ RESOLUTION best = resolution; ++ RESOLUTION_INFO curr = CDisplaySettings::Get().GetResolutionInfo(best); ++ // Find closest refresh rate ++ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) ++ { ++ const RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo((RESOLUTION)i); ++ ++ //discard resolutions that are not the same width and height (and interlaced/3D flags) ++ //or have a too low refreshrate ++ if (info.iScreenWidth != curr.iScreenWidth ++ || info.iScreenHeight != curr.iScreenHeight ++ || info.iScreen != curr.iScreen ++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED) ++ || fabs(info.fRefreshRate - curr.fRefreshRate) >= FLT_EPSILON) ++ continue; ++ ++ if (mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ++ { ++ best = (RESOLUTION)i; ++ break; ++ } ++ else if (mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && info.dwFlags & D3DPRESENTFLAG_MODE3DTB) ++ { ++ best = (RESOLUTION)i; ++ break; ++ } ++ else if ((mode == RENDER_STEREO_MODE_OFF || mode == RENDER_STEREO_MODE_MONO) && !(info.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))) ++ { ++ best = (RESOLUTION)i; ++ break; ++ } ++ } ++ return best; ++} ++ + void CGraphicContext::ResetOverscan(RESOLUTION_INFO &res) + { + res.Overscan.left = 0; +@@ -1037,7 +1075,7 @@ void CGraphicContext::Flip(const CDirtyRegionList& dirty) + if(m_stereoMode != m_nextStereoMode) + { + m_stereoMode = m_nextStereoMode; +- SetVideoResolution(GetVideoResolution(), true); ++ SetVideoResolution(Get3DVideoResolution(m_Resolution, m_stereoMode), true); + g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET); + } + } +diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h +index 5c1501a..aba11cd 100644 +--- a/xbmc/guilib/GraphicContext.h ++++ b/xbmc/guilib/GraphicContext.h +@@ -108,6 +108,7 @@ class CGraphicContext : public CCriticalSection, + bool IsValidResolution(RESOLUTION res); + void SetVideoResolution(RESOLUTION res, bool forceUpdate = false); + RESOLUTION GetVideoResolution() const; ++ RESOLUTION Get3DVideoResolution(RESOLUTION resolution, RENDER_STEREO_MODE mode) const; + void ResetOverscan(RESOLUTION res, OVERSCAN &overscan); + void ResetOverscan(RESOLUTION_INFO &resinfo); + void ResetScreenParameters(RESOLUTION res); + +From f1e42a2b7d6056020781ea1291c996aa34721f57 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:38:55 +0100 +Subject: [PATCH 73/95] [3D] Support switching to 3D resolutions + +Include matching 3D flags (SBS/TAB) in the score of a resolution to switch to, to enable switching to 3d modes. +Also remove the old code that treated 3D modes differently when assigning a score. +--- + xbmc/cores/VideoRenderers/BaseRenderer.cpp | 47 +++++++++++------------------- + 1 file changed, 17 insertions(+), 30 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +index 751a61b..ca4eba6 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +@@ -222,10 +222,14 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) + RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight) + { + RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current); ++ unsigned int stereo_mode = CONF_FLAGS_STEREO_MODE_MASK(m_iFlags); + + float fRefreshRate = fps; + +- float last_diff = fRefreshRate; ++ int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); ++ if (!(stereo_mode == CONF_FLAGS_STEREO_MODE_SBS) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) || ++ !(stereo_mode == CONF_FLAGS_STEREO_MODE_TAB) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DTB)) ++ c_weight += 1000; + + // Find closest refresh rate + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) +@@ -241,40 +245,23 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES + || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) + continue; + +- // For 3D choose the closest refresh rate +- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) +- { +- float diff = (info.fRefreshRate - fRefreshRate); +- if(diff < 0) +- diff *= -1.0f; ++ int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); + +- if(diff < last_diff) +- { +- last_diff = diff; +- current = (RESOLUTION)i; +- curr = info; +- } +- } +- else +- { +- int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0); +- int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0); ++ if (!(stereo_mode == CONF_FLAGS_STEREO_MODE_SBS) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) || ++ !(stereo_mode == CONF_FLAGS_STEREO_MODE_TAB) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DTB)) ++ i_weight += 1000; + +- // Closer the better, prefer higher refresh rate if the same +- if ((i_weight < c_weight) +- || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) +- { +- current = (RESOLUTION)i; +- curr = info; +- } ++ // Closer the better, prefer higher refresh rate if the same ++ if ((i_weight < c_weight) ++ || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate)) ++ { ++ current = (RESOLUTION)i; ++ curr = info; ++ c_weight = i_weight; + } + } + +- // For 3D overwrite weight +- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags)) +- weight = 0; +- else +- weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); ++ weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier); + + return current; + } + +From 186abff1aefa3a4f085fd4395be1af2cdb998164 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 23 Apr 2014 00:05:07 +0100 +Subject: [PATCH 74/95] [graphics] Make pixel ratio for 3d modes consistent + +Note: Use the stored stereo flags from lists of resolutions. +Use current stereo mode for current resolution. +--- + xbmc/cores/VideoRenderers/BaseRenderer.cpp | 10 +++---- + xbmc/guilib/GraphicContext.cpp | 37 ++++++++++++------------- + xbmc/guilib/GraphicContext.h | 12 ++++++-- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 8 ------ + 4 files changed, 32 insertions(+), 35 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +index ca4eba6..6db7c86 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp +@@ -119,7 +119,7 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa + + for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++) + { +- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j); ++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j, g_graphicsContext.GetStereoMode((RESOLUTION)j)); + + if (info.iScreenWidth == curr.iScreenWidth + && info.iScreenHeight == curr.iScreenHeight +@@ -179,7 +179,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) + //get the resolution with the refreshrate closest to 60 hertz + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) + { +- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i)); + + if (MathUtils::round_int(info.fRefreshRate) == 60 + && info.iScreenWidth == curr.iScreenWidth +@@ -200,7 +200,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight) + CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest"); + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) + { +- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i)); + + if (info.fRefreshRate > curr.fRefreshRate + && info.iScreenWidth == curr.iScreenWidth +@@ -234,14 +234,14 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES + // Find closest refresh rate + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++) + { +- const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i); ++ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i)); + + //discard resolutions that are not the same width and height (and interlaced/3D flags) + //or have a too low refreshrate + if (info.iScreenWidth != curr.iScreenWidth + || info.iScreenHeight != curr.iScreenHeight + || info.iScreen != curr.iScreen +- || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK) ++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED) + || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001) + continue; + +diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp +index a476cd8..9882935 100644 +--- a/xbmc/guilib/GraphicContext.cpp ++++ b/xbmc/guilib/GraphicContext.cpp +@@ -747,32 +747,33 @@ void CGraphicContext::ApplyStateBlock() + g_Windowing.ApplyStateBlock(); + } + +-const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const ++RENDER_STEREO_MODE CGraphicContext::GetStereoMode(RESOLUTION res) const + { + RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res); ++ return (info.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL : ++ (info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL : RENDER_STEREO_MODE_OFF; ++} + +- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res, RENDER_STEREO_MODE stereoMode) const ++{ ++ RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res); ++ ++ if(stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) + { +- if((info.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) +- { +- info.fPixelRatio /= 2; +- info.iBlanking = 0; +- info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; +- } ++ info.fPixelRatio /= 2; ++ info.iBlanking = 0; ++ info.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + info.iHeight = (info.iHeight - info.iBlanking) / 2; + info.Overscan.top /= 2; + info.Overscan.bottom = (info.Overscan.bottom - info.iBlanking) / 2; + info.iSubtitles = (info.iSubtitles - info.iBlanking) / 2; + } + +- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ if(stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL) + { +- if((info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) +- { +- info.fPixelRatio *= 2; +- info.iBlanking = 0; +- info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; +- } ++ info.fPixelRatio *= 2; ++ info.iBlanking = 0; ++ info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; + info.iWidth = (info.iWidth - info.iBlanking) / 2; + info.Overscan.left /= 2; + info.Overscan.right = (info.Overscan.right - info.iBlanking) / 2; +@@ -790,16 +791,14 @@ void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info) + if(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) + { + curr.Overscan.right = info.Overscan.right * 2 + info.iBlanking; +- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0) +- curr.fPixelRatio /= 2.0; ++ curr.fPixelRatio /= 2.0; + } + + if(info.dwFlags & D3DPRESENTFLAG_MODE3DTB) + { + curr.Overscan.bottom = info.Overscan.bottom * 2 + info.iBlanking; + curr.iSubtitles = info.iSubtitles * 2 + info.iBlanking; +- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0) +- curr.fPixelRatio *= 2.0; ++ curr.fPixelRatio *= 2.0; + } + } + +diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h +index aba11cd..c84aed0 100644 +--- a/xbmc/guilib/GraphicContext.h ++++ b/xbmc/guilib/GraphicContext.h +@@ -120,11 +120,15 @@ class CGraphicContext : public CCriticalSection, + void GetAllowedResolutions(std::vector &res); + + // output scaling ++ const RESOLUTION_INFO GetResInfo(RESOLUTION res) const ++ { ++ return GetResInfo(res, GetStereoMode()); ++ } + const RESOLUTION_INFO GetResInfo() const + { + return GetResInfo(m_Resolution); + } +- const RESOLUTION_INFO GetResInfo(RESOLUTION res) const; ++ const RESOLUTION_INFO GetResInfo(RESOLUTION res, RENDER_STEREO_MODE stereo_mode) const; + void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info); + + /* \brief Get UI scaling information from a given resolution to the screen resolution. +@@ -161,9 +165,11 @@ class CGraphicContext : public CCriticalSection, + void RestoreOrigin(); + void SetCameraPosition(const CPoint &camera); + void SetStereoView(RENDER_STEREO_VIEW view); +- RENDER_STEREO_VIEW GetStereoView() { return m_stereoView; } ++ RENDER_STEREO_VIEW GetStereoView() const { return m_stereoView; } + void SetStereoMode(RENDER_STEREO_MODE mode) { m_nextStereoMode = mode; } +- RENDER_STEREO_MODE GetStereoMode() { return m_stereoMode; } ++ RENDER_STEREO_MODE GetStereoMode() const { return m_stereoMode; } ++ RENDER_STEREO_MODE GetStereoMode(RESOLUTION res) const; ++ + void RestoreCameraPosition(); + /*! \brief Set a region in which to clip all rendering + Anything that is rendered after setting a clip region will be clipped so that no part renders +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index d388373..ba14e40 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -546,15 +546,9 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r + 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); + // Also add 3D flags + if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF) +- { + m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; +- m_desktopRes.fPixelRatio *= 2.0; +- } + else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF) +- { + m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB; +- m_desktopRes.fPixelRatio *= 0.5; +- } + HDMI_PROPERTY_PARAM_T property; + property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; + vc_tv_hdmi_get_property(&property); +@@ -694,7 +688,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v + RESOLUTION_INFO res2 = res; + res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS; + res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); +- res2.fPixelRatio *= 2.0f; + res2.iSubtitles = (int)(0.965 * res2.iHeight); + + AddUniqueResolution(res2, resolutions); +@@ -710,7 +703,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v + RESOLUTION_INFO res2 = res; + res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB; + res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight); +- res2.fPixelRatio *= 0.5f; + res2.iSubtitles = (int)(0.965 * res2.iHeight); + + AddUniqueResolution(res2, resolutions); + +From f27b17812aedc6cd1bfb9e52fbacb39defbfd8fe Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 13 Mar 2015 20:48:37 +0100 +Subject: [PATCH 75/95] renderer: Allow gui updates to be skipped when playing + video + +--- + xbmc/Application.cpp | 23 ++++++++++++++++------- + xbmc/Application.h | 1 + + 2 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index edb4271..87b5d37 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -328,6 +328,7 @@ CApplication::CApplication(void) + m_currentStackPosition = 0; + m_lastFrameTime = 0; + m_lastRenderTime = 0; ++ m_skipGuiRender = false; + m_bTestMode = false; + + m_muted = false; +@@ -1952,12 +1953,7 @@ void CApplication::Render() + CDirtyRegionList dirtyRegions; + + // render gui layer +- int fps = 0; +- if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) +- fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); +- unsigned int now = XbmcThreads::SystemClockMillis(); +- unsigned int frameTime = now - m_lastRenderTime; +- if (fps <= 0 || frameTime * fps >= 1000) ++ if (!m_skipGuiRender) + { + dirtyRegions = g_windowManager.GetDirty(); + if (g_graphicsContext.GetStereoMode()) +@@ -1994,6 +1990,7 @@ void CApplication::Render() + g_infoManager.ResetCache(); + lock.Leave(); + ++ unsigned int now = XbmcThreads::SystemClockMillis(); + if (hasRendered) + m_lastRenderTime = now; + +@@ -2478,8 +2475,20 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) + } + if (processGUI && m_renderGUI) + { ++ m_skipGuiRender = false; ++ int fps = 0; ++ if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); ++ unsigned int now = XbmcThreads::SystemClockMillis(); ++ unsigned int frameTime = now - m_lastRenderTime; ++ if (fps > 0 && frameTime * fps < 1000) ++ m_skipGuiRender = true; ++ + if (!m_bStop) +- g_windowManager.Process(CTimeUtils::GetFrameTime()); ++ { ++ if (!m_skipGuiRender) ++ g_windowManager.Process(CTimeUtils::GetFrameTime()); ++ } + g_windowManager.FrameMove(); + } + } +diff --git a/xbmc/Application.h b/xbmc/Application.h +index 1b9a4bf..cc064c3 100644 +--- a/xbmc/Application.h ++++ b/xbmc/Application.h +@@ -465,6 +465,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs + bool m_bPresentFrame; + unsigned int m_lastFrameTime; + unsigned int m_lastRenderTime; ++ bool m_skipGuiRender; + + bool m_bStandalone; + bool m_bEnableLegacyRes; + +From 31705fdeef0bc8947cbd8951b57a9f7b4e64cb46 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Mar 2015 17:05:18 +0000 +Subject: [PATCH 76/95] [players] Add settings option to enable MVC support + +--- + addons/resource.language.en_gb/resources/strings.po | 10 ++++++++++ + system/settings/rbp.xml | 10 ++++++++++ + system/settings/rbp2.xml | 10 ++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 5 +++++ + xbmc/cores/omxplayer/OMXVideo.cpp | 5 +++++ + 5 files changed, 40 insertions(+) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index a4c078c..58b6424 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16662,6 +16662,16 @@ msgctxt "#38102" + msgid "%i ms" + msgstr "" + ++#: system/settings/rbp.xml ++msgctxt "#38110" ++msgid "Support MVC video (full frame 3D)" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38111" ++msgid "This option decodes frames for both eyes of MVC video. Disabling may improve performance if you don't require 3D" ++msgstr "" ++ + #: system/settings/settings.xml + msgctxt "#38015" + msgid "Extract thumbnails from video files" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index a3b6f6f..384bfdb 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -31,6 +31,16 @@ + +
+
++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index e118f3a..0320f32 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -34,6 +34,16 @@ + +
+ ++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 1bfec44..21282dc 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -534,6 +534,11 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + // H.264 + m_codingType = MMAL_ENCODING_H264; + m_pFormatName = "mmal-h264"; ++ if (CSettings::Get().GetBool("videoplayer.supportmvc")) ++ { ++ m_codingType = MMAL_ENCODING_MVC; ++ m_pFormatName= "mmal-mvc"; ++ } + break; + case AV_CODEC_ID_H263: + case AV_CODEC_ID_MPEG4: +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 55e16c4..5a74c79 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -434,6 +434,11 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + break; + } + } ++ if (CSettings::Get().GetBool("videoplayer.supportmvc")) ++ { ++ m_codingType = OMX_VIDEO_CodingMVC; ++ m_video_codec_name = "omx-mvc"; ++ } + break; + case AV_CODEC_ID_MPEG4: + // (role name) video_decoder.mpeg4 + +From 7bd4b8bdd382d21aa557f1188351e151c02cf652 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Mar 2015 12:38:08 +0000 +Subject: [PATCH 77/95] [mmalrenderer] Switch to using transform flags for 3d + modes + +--- + .../resource.language.en_gb/resources/strings.po | 10 +++ + system/settings/rbp.xml | 8 ++ + system/settings/rbp2.xml | 8 ++ + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 92 ++++++---------------- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 46 ++--------- + xbmc/cores/omxplayer/OMXVideo.cpp | 36 ++++----- + xbmc/cores/omxplayer/OMXVideo.h | 2 +- + xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 11 ++- + 8 files changed, 83 insertions(+), 130 deletions(-) + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index 58b6424..97a9c5c 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16672,6 +16672,16 @@ msgctxt "#38111" + msgid "This option decodes frames for both eyes of MVC video. Disabling may improve performance if you don't require 3D" + msgstr "" + ++#: system/settings/rbp.xml ++msgctxt "#38112" ++msgid "Use Full HD HDMI modes for 3D" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38113" ++msgid "This option uses frame-packing to output full resolution for 3D through HDMI" ++msgstr "" ++ + #: system/settings/settings.xml + msgctxt "#38015" + msgid "Extract thumbnails from video files" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 384bfdb..945e981 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -40,6 +40,14 @@ + true + +
++ ++ ++ true ++ ++ 2 ++ true ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index 0320f32..11bd850 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -43,6 +43,14 @@ + true + +
++ ++ ++ true ++ ++ 2 ++ true ++ ++ + + + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index b9d9cd9..f4c59ea 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -346,11 +346,7 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + + if (!m_bConfigured) return; + +- if (g_graphicsContext.GetStereoMode()) +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT); + ManageDisplay(); +- if (g_graphicsContext.GetStereoMode()) +- g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF); + + // if running bypass, then the player might need the src/dst rects + // for sizing video playback on a layer other than the gles layer. +@@ -541,9 +537,7 @@ EINTERLACEMETHOD CMMALRenderer::AutoInterlaceMethod() + + void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect) + { +- // we get called twice a frame for left/right. Can ignore the rights. +- if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT) +- return; ++ assert(g_graphicsContext.GetStereoView() != RENDER_STEREO_VIEW_RIGHT); + + if (!m_vout_input) + return; +@@ -585,41 +579,10 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect + CRect gui(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight); + CRect display(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight); + +- if (display_stereo_mode != RENDER_STEREO_MODE_OFF && display_stereo_mode != RENDER_STEREO_MODE_MONO) +- switch (video_stereo_mode) +- { +- case RENDER_STEREO_MODE_SPLIT_VERTICAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert) +- { +- SrcRect.x2 *= 2.0f; +- DestRect.x2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE) +- { +- SrcRect.x2 *= 2.0f; +- } +- break; +- +- case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert) +- { +- SrcRect.y2 *= 2.0f; +- DestRect.y2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA || display_stereo_mode == RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE) +- { +- SrcRect.y2 *= 2.0f; +- } +- break; +- +- default: break; +- } ++ if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ DestRect.x2 *= 2.0f; ++ else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++ DestRect.y2 *= 2.0f; + + if (gui != display) + { +@@ -634,7 +597,7 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect + 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; ++ 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()); +@@ -647,35 +610,32 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect + + 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_renderOrientation) +- { +- region.set |= MMAL_DISPLAY_SET_TRANSFORM; +- 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 assert(0); +- } +- +- if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_TOP_TO_TOP; +- else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_TOP_TO_LEFT; +- else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_LEFT_TO_TOP; +- else if (video_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- region.mode = MMAL_DISPLAY_MODE_STEREO_LEFT_TO_LEFT; ++ 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.mode = MMAL_DISPLAY_MODE_LETTERBOX; ++ 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 mode:%d", CLASSNAME, __func__, ++ 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.mode); ++ region.dest_rect.x, region.dest_rect.y, region.dest_rect.width, region.dest_rect.height, region.transform); + } +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 86d97bd..018e65f 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -660,9 +660,7 @@ int OMXPlayerVideo::GetFreeSpace() + + void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRect) + { +- // we get called twice a frame for left/right. Can ignore the rights. +- if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT) +- return; ++ assert(g_graphicsContext.GetStereoView() != RENDER_STEREO_VIEW_RIGHT); + + CRect SrcRect = InSrcRect, DestRect = InDestRect; + unsigned flags = GetStereoModeFlags(GetStereoMode()); +@@ -702,42 +700,10 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec + CRect gui(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight); + CRect display(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight); + +- switch (video_stereo_mode) +- { +- case RENDER_STEREO_MODE_SPLIT_VERTICAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert) +- { +- SrcRect.x2 *= 2.0f; +- DestRect.x2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (stereo_invert) +- { +- SrcRect.x1 += m_hints.width / 2; +- SrcRect.x2 += m_hints.width / 2; +- } +- break; +- +- case RENDER_STEREO_MODE_SPLIT_HORIZONTAL: +- // optimisation - use simpler display mode in common case of unscaled 3d with same display mode +- if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert) +- { +- SrcRect.y2 *= 2.0f; +- DestRect.y2 *= 2.0f; +- video_stereo_mode = RENDER_STEREO_MODE_OFF; +- display_stereo_mode = RENDER_STEREO_MODE_OFF; +- } +- else if (stereo_invert) +- { +- SrcRect.y1 += m_hints.height / 2; +- SrcRect.y2 += m_hints.height / 2; +- } +- break; +- +- default: break; +- } ++ if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ DestRect.x2 *= 2.0f; ++ else if (display_stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++ DestRect.y2 *= 2.0f; + + if (gui != display) + { +@@ -748,7 +714,7 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec + DestRect.y1 *= yscale; + DestRect.y2 *= yscale; + } +- m_omxVideo.SetVideoRect(SrcRect, DestRect, video_stereo_mode, display_stereo_mode); ++ m_omxVideo.SetVideoRect(SrcRect, DestRect, m_video_stereo_mode, m_display_stereo_mode, m_StereoInvert); + } + + void OMXPlayerVideo::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 5a74c79..aa97396 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -224,15 +224,6 @@ bool COMXVideo::PortSettingsChanged() + OMX_INIT_STRUCTURE(configDisplay); + configDisplay.nPortIndex = m_omx_render.GetInputPort(); + +- configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; +- configDisplay.transform = m_transform; +- omx_err = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); +- if(omx_err != OMX_ErrorNone) +- { +- CLog::Log(LOGWARNING, "%s::%s - could not set transform : %d", CLASSNAME, __func__, m_transform); +- return false; +- } +- + if(m_hdmi_clock_sync) + { + OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; +@@ -877,7 +868,7 @@ void COMXVideo::Reset(void) + } + + /////////////////////////////////////////////////////////////////////////////////////////// +-void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode) ++void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode, bool stereo_invert) + { + CSingleLock lock (m_critSection); + if(!m_is_open) +@@ -887,7 +878,7 @@ void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER + + OMX_INIT_STRUCTURE(configDisplay); + configDisplay.nPortIndex = m_omx_render.GetInputPort(); +- configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT|OMX_DISPLAY_SET_MODE); ++ configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT|OMX_DISPLAY_SET_MODE|OMX_DISPLAY_SET_TRANSFORM); + configDisplay.dest_rect.x_offset = lrintf(DestRect.x1); + configDisplay.dest_rect.y_offset = lrintf(DestRect.y1); + configDisplay.dest_rect.width = lrintf(DestRect.Width()); +@@ -900,23 +891,24 @@ void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER + + configDisplay.fullscreen = OMX_FALSE; + configDisplay.noaspect = OMX_TRUE; ++ configDisplay.mode = OMX_DISPLAY_MODE_LETTERBOX; ++ configDisplay.transform = m_transform; + +- if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_TOP_TO_TOP; +- else if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_TOP_TO_LEFT; +- else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_LEFT_TO_TOP; +- else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) +- configDisplay.mode = OMX_DISPLAY_MODE_STEREO_LEFT_TO_LEFT; ++ if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_TB); ++ else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_SBS); + else +- configDisplay.mode = OMX_DISPLAY_MODE_LETTERBOX; ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_MONO); ++ ++ if (stereo_invert) ++ configDisplay.transform = (OMX_DISPLAYTRANSFORMTYPE)(configDisplay.transform | DISPMANX_STEREOSCOPIC_INVERT); + + m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); + +- CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d mode:%d", CLASSNAME, __func__, ++ CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d t:%x", CLASSNAME, __func__, + configDisplay.src_rect.x_offset, configDisplay.src_rect.y_offset, configDisplay.src_rect.width, configDisplay.src_rect.height, +- configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset, configDisplay.dest_rect.width, configDisplay.dest_rect.height, configDisplay.mode); ++ configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset, configDisplay.dest_rect.width, configDisplay.dest_rect.height, configDisplay.transform); + } + + int COMXVideo::GetInputBufferSize() +diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h +index 9f26427..3ea02dc 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.h ++++ b/xbmc/cores/omxplayer/OMXVideo.h +@@ -59,7 +59,7 @@ class COMXVideo + void Reset(void); + void SetDropState(bool bDrop); + std::string GetDecoderName() { return m_video_codec_name; }; +- void SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode); ++ void SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode, bool stereo_invert); + int GetInputBufferSize(); + bool GetPlayerInfo(double &match, double &phase, double &pll); + void SubmitEOS(); +diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +index ba14e40..10a0409 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp +@@ -284,7 +284,9 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + /* 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; +- if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ++ if (CSettings::Get().GetBool("videoplayer.framepacking")) ++ property.param1 = HDMI_3D_FORMAT_FRAME_PACKING; ++ else if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) + property.param1 = HDMI_3D_FORMAT_SBS_HALF; + else if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) + property.param1 = HDMI_3D_FORMAT_TB_HALF; +@@ -384,6 +386,13 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res) + DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE; + DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0); + ++ if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ++ transform = DISPMANX_STEREOSCOPIC_SBS; ++ else if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) ++ 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\n", + 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); + + +From 247752fc9fd63a9544d93081720bd15ca172e660 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Mon, 16 Mar 2015 19:12:17 +0100 +Subject: [PATCH 78/95] Avoid breaking skins comparing System.StereoscopicMode + after 6345. + +See http://forum.kodi.tv/showthread.php?tid=211501&pid=1956983#pid1956983 +--- + xbmc/rendering/RenderSystem.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h +index 9f1daf4..60c5e4b 100644 +--- a/xbmc/rendering/RenderSystem.h ++++ b/xbmc/rendering/RenderSystem.h +@@ -74,10 +74,10 @@ enum RENDER_STEREO_MODE + RENDER_STEREO_MODE_SPLIT_VERTICAL, + RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN, + RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA, +- RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE, + RENDER_STEREO_MODE_INTERLACED, + RENDER_STEREO_MODE_HARDWAREBASED, + RENDER_STEREO_MODE_MONO, ++ RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE, + RENDER_STEREO_MODE_COUNT, + + // psuevdo modes + +From 88a85cfa522676d95bdcd30fed1e10f0aef5337e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 17 Mar 2015 20:33:54 +0000 +Subject: [PATCH 79/95] alsa: enable-shared is required + +--- + tools/depends/target/alsa-lib/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/depends/target/alsa-lib/Makefile b/tools/depends/target/alsa-lib/Makefile +index b03fc19..a04d933 100644 +--- a/tools/depends/target/alsa-lib/Makefile ++++ b/tools/depends/target/alsa-lib/Makefile +@@ -19,7 +19,7 @@ CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + --with-ctl-plugins=ext \ + --with-pcm-plugins="copy,linear,route,mulaw,alaw,adpcm,rate,plug,multi,file,null,empty,share,meter,hooks,lfloat,ladspa,asym,iec958,softvol,extplug,ioplug,mmap_emul" \ + --disable-resmgr --enable-aload --enable-mixer --enable-pcm --disable-rawmidi --enable-hwdep --disable-seq --disable-alisp --disable-old-symbols --disable-python \ +- --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no --disable-shared \ ++ --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no --enable-shared \ + + LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + + +From 2e6ff5a10adfabb2fbc51e343ea8444452321270 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 21 Mar 2015 21:46:16 +0000 +Subject: [PATCH 80/95] squash: Move m_output_busy into lock + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 21282dc..3d90b92 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -273,7 +273,6 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + else + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); +- m_output_busy++; + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - %p (%p) buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x frame:%d", + CLASSNAME, __func__, buffer, omvb, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); +@@ -285,6 +284,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + omvb->height = m_decoded_height; + omvb->m_aspect_ratio = m_aspect_ratio; + pthread_mutex_lock(&m_output_mutex); ++ m_output_busy++; + m_output_ready.push(omvb); + pthread_mutex_unlock(&m_output_mutex); + kept = true; + +From 1086403e7c84699464d2646d7323989e4ee4481a Mon Sep 17 00:00:00 2001 +From: "Chris \\\"Koying\\\" Browet" +Date: Sun, 28 Dec 2014 19:31:09 +0100 +Subject: [PATCH 81/95] ADD: Handle bitmap subtitles in 3D + +--- + .../DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp | 78 +++++++++++++--------- + 1 file changed, 48 insertions(+), 30 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +index 75fd6bb..c01b09b 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +@@ -26,6 +26,8 @@ + #include "DVDClock.h" + #include "utils/log.h" + #include "utils/EndianSwap.h" ++#include "guilib/GraphicContext.h" ++#include "xbmc/rendering/RenderSystem.h" + + CDVDOverlayCodecFFmpeg::CDVDOverlayCodecFFmpeg() : CDVDOverlayCodec("FFmpeg Subtitle Decoder") + { +@@ -237,10 +239,28 @@ CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() + if(m_Subtitle.rects[m_SubtitleIndex] == NULL) + return NULL; + +- AVSubtitleRect& rect = *m_Subtitle.rects[m_SubtitleIndex]; ++ AVSubtitleRect rect = *m_Subtitle.rects[m_SubtitleIndex]; + if (rect.pict.data[0] == NULL) + return NULL; + ++ m_height = m_pCodecContext->height; ++ m_width = m_pCodecContext->width; ++ ++ RENDER_STEREO_MODE render_stereo_mode = g_graphicsContext.GetStereoMode(); ++ if (render_stereo_mode != RENDER_STEREO_MODE_OFF) ++ { ++ if (rect.h > m_height / 2) ++ { ++ m_height /= 2; ++ rect.h -= m_pCodecContext->height / 2; ++ } ++ else if (rect.w > m_width / 2) ++ { ++ m_width /= 2; ++ rect.w -= m_pCodecContext->width / 2; ++ } ++ } ++ + CDVDOverlayImage* overlay = new CDVDOverlayImage(); + + overlay->iPTSStartTime = m_StartTime; +@@ -259,36 +279,34 @@ CDVDOverlay* CDVDOverlayCodecFFmpeg::GetOverlay() + int right = overlay->x + overlay->width; + int bottom = overlay->y + overlay->height; + +- if(m_height == 0 && m_pCodecContext->height) +- m_height = m_pCodecContext->height; +- if(m_width == 0 && m_pCodecContext->width) +- m_width = m_pCodecContext->width; +- +- if(bottom > m_height) +- { +- if (bottom <= 480) +- m_height = 480; +- else if(bottom <= 576) +- m_height = 576; +- else if(bottom <= 720) +- m_height = 720; +- else if(bottom <= 1080) +- m_height = 1080; +- else +- m_height = bottom; +- } +- if(right > m_width) ++ if (render_stereo_mode == RENDER_STEREO_MODE_OFF) + { +- if (right <= 720) +- m_width = 720; +- else if(right <= 1024) +- m_width = 1024; +- else if(right <= 1280) +- m_width = 1280; +- else if(right <= 1920) +- m_width = 1920; +- else +- m_width = right; ++ if(bottom > m_height) ++ { ++ if (bottom <= 480) ++ m_height = 480; ++ else if(bottom <= 576) ++ m_height = 576; ++ else if(bottom <= 720) ++ m_height = 720; ++ else if(bottom <= 1080) ++ m_height = 1080; ++ else ++ m_height = bottom; ++ } ++ if(right > m_width) ++ { ++ if (right <= 720) ++ m_width = 720; ++ else if(right <= 1024) ++ m_width = 1024; ++ else if(right <= 1280) ++ m_width = 1280; ++ else if(right <= 1920) ++ m_width = 1920; ++ else ++ m_width = right; ++ } + } + + overlay->source_width = m_width; + +From e8c4361333aee9a8979e809d76303e70baac9863 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 22 Mar 2015 19:32:36 +0000 +Subject: [PATCH 82/95] [omxplayer] Handle failures from EmptyThisBuffer and + FillThisBuffer + +Avoid leak of buffer as seen in PR6260 +--- + .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 +++- + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 3 ++ + xbmc/cores/omxplayer/OMXAudio.cpp | 42 +++++++--------------- + xbmc/cores/omxplayer/OMXImage.cpp | 28 ++++++++++++--- + xbmc/cores/omxplayer/OMXVideo.cpp | 38 ++++++-------------- + 5 files changed, 55 insertions(+), 62 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +index fa8112d..759ba7b 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +@@ -506,6 +506,7 @@ int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t + 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; + } + +@@ -518,8 +519,11 @@ int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t + } + 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) + { +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 363b7d5..7f4d103 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -468,7 +468,10 @@ unsigned int CAESinkPi::AddPackets(uint8_t **data, unsigned int frames, unsigned + } + 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(); +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 602d2fa..2e39224 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -858,12 +858,8 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + } + + omx_buffer->nOffset = 0; +- omx_buffer->nFilledLen = sizeof(m_wave_header); +- if(omx_buffer->nFilledLen > omx_buffer->nAllocLen) +- { +- CLog::Log(LOGERROR, "COMXAudio::Initialize - omx_buffer->nFilledLen > omx_buffer->nAllocLen"); +- return false; +- } ++ omx_buffer->nFilledLen = std::min(sizeof(m_wave_header), omx_buffer->nAllocLen); ++ + memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen); + memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; +@@ -872,6 +868,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -889,12 +886,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + } + + omx_buffer->nOffset = 0; +- omx_buffer->nFilledLen = m_extrasize; +- if(omx_buffer->nFilledLen > omx_buffer->nAllocLen) +- { +- CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__); +- return false; +- } ++ omx_buffer->nFilledLen = std::min((OMX_U32)m_extrasize, omx_buffer->nAllocLen); + + memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen); + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); +@@ -904,6 +896,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -1223,26 +1216,14 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt + if(demuxer_samples_sent == demuxer_samples) + omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + +- int nRetry = 0; +- while(true) ++ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); ++ if (omx_err != OMX_ErrorNone) + { +- omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); +- if (omx_err == OMX_ErrorNone) +- { +- //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len); +- break; +- } +- else +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); +- nRetry++; +- } +- if(nRetry == 5) +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__); +- return 0; +- } ++ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); ++ return 0; + } ++ //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len); + + omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); + if (omx_err == OMX_ErrorNone) +@@ -1477,6 +1458,7 @@ void COMXAudio::SubmitEOS() + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return; + } + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index 54a52a7..e79f41d 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1058,6 +1058,7 @@ bool COMXImageDec::HandlePortSettingChange(unsigned int resize_width, unsigned i + if(omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s m_omx_resize FillThisBuffer result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_resize.DecoderFillBufferDone(m_omx_resize.GetComponent(), m_decoded_buffer); + return false; + } + } +@@ -1174,6 +1175,7 @@ bool COMXImageDec::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -1240,8 +1242,17 @@ COMXImageEnc::~COMXImageEnc() + + OMX_INIT_STRUCTURE(m_encoded_format); + m_encoded_buffer = NULL; +- if(m_omx_encoder.IsInitialized()) +- m_omx_encoder.Deinitialize(); ++ 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(); + } + +@@ -1383,6 +1394,7 @@ bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsig + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_encoder.DecoderEmptyBufferDone(m_omx_encoder.GetComponent(), omx_buffer); + break; + } + } +@@ -1397,12 +1409,15 @@ bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsig + + 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)\n", CLASSNAME, __func__, omx_err); ++ m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); + return false; +- ++ } + omx_err = m_omx_encoder.WaitForOutputDone(1000); + if(omx_err != OMX_ErrorNone) + { +- CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForOutputDone result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ CLog::Log(LOGERROR, "%s::%s m_omx_encoder.WaitForOutputDone result(0x%x)\n", CLASSNAME, __func__, omx_err); + return false; + } + +@@ -1445,6 +1460,7 @@ bool COMXImageEnc::CreateThumbnailFromSurface(unsigned char* buffer, unsigned in + return true; + } + ++ m_success = true; + return false; + } + +@@ -1842,6 +1858,7 @@ bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, uns + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s %s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -1880,6 +1897,7 @@ bool COMXImageReEnc::ReEncode(COMXImageFile &srcFile, unsigned int maxWidth, uns + if(omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s %s FillThisBuffer() failed (%x)\n", CLASSNAME, __func__, srcFile.GetFilename(), omx_err); ++ m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); + return false; + } + } +@@ -2199,6 +2217,7 @@ bool COMXTexture::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes, + 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; + } + } +@@ -2248,6 +2267,7 @@ bool COMXTexture::Decode(const uint8_t *demuxer_content, unsigned demuxer_bytes, + 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; + } + +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index aa97396..3f37d44 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -109,12 +109,7 @@ bool COMXVideo::SendDecoderConfig() + } + + omx_buffer->nOffset = 0; +- omx_buffer->nFilledLen = m_extrasize; +- if(omx_buffer->nFilledLen > omx_buffer->nAllocLen) +- { +- CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__); +- return false; +- } ++ omx_buffer->nFilledLen = std::min((OMX_U32)m_extrasize, omx_buffer->nAllocLen); + + memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen); + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); +@@ -124,6 +119,7 @@ bool COMXVideo::SendDecoderConfig() + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return false; + } + } +@@ -654,8 +650,7 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + return false; + } + +- if(!SendDecoderConfig()) +- return false; ++ SendDecoderConfig(); + + m_is_open = true; + m_drop_state = false; +@@ -799,7 +794,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; + + omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); +- omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; ++ omx_buffer->nFilledLen = std::min((OMX_U32)demuxer_bytes, omx_buffer->nAllocLen); + memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); + + demuxer_bytes -= omx_buffer->nFilledLen; +@@ -808,26 +803,14 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + if(demuxer_bytes == 0) + omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + +- int nRetry = 0; +- while(true) ++ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); ++ if (omx_err != OMX_ErrorNone) + { +- omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); +- if (omx_err == OMX_ErrorNone) +- { +- //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize); +- break; +- } +- else +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); +- nRetry++; +- } +- if(nRetry == 5) +- { +- CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finally failed\n", CLASSNAME, __func__); +- return false; +- } ++ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); ++ return false; + } ++ //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize); + + omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); + if (omx_err == OMX_ErrorNone) +@@ -946,6 +929,7 @@ void COMXVideo::SubmitEOS() + if (omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); ++ m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); + return; + } + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); + + +From 055fe2e21ad53d210eb86054a6b1452c07e93fd8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 23 Mar 2015 23:50:50 +0000 +Subject: [PATCH 85/95] [OMXAudio] Make stereoupmix and fixed behave more like + dvdplayer + +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 2e39224..dd5cdb8 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -600,13 +600,12 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") + stdLayout = AE_CH_LAYOUT_2_0; + +- // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix +- if (m_InputChannels <= 2) +- stdLayout = AE_CH_LAYOUT_2_0; +- +- + CAEChannelInfo resolvedMap = channelMap; + resolvedMap.ResolveChannels(stdLayout); ++ ++ if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED || (upmix && channelMap.Count() <= 2)) ++ resolvedMap = stdLayout; ++ + uint64_t m_dst_chan_layout = GetAVChannelLayout(resolvedMap); + uint64_t m_src_chan_layout = GetAVChannelLayout(channelMap); + + +From 2980f063267a39aff75454ec0794b951f06e51b9 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Mar 2015 17:24:27 +0000 +Subject: [PATCH 86/95] [mmal] Explicitly use fast deinterlace for HD and + reduce buffers allocated by 2 + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 3d90b92..03d397f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -361,10 +361,13 @@ bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) + CLog::Log(LOGERROR, "%s::%s Failed to create deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); + return false; + } ++ bool advanced_deinterlace = (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF) && ++ m_decoded_width * m_decoded_height <= 576 * 720; ++ bool half_framerate = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF; ++ + MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, +- interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF ? +- MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, +- 3, {3, 0, interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF }}; ++ advanced_deinterlace ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 3, {3, 0, half_framerate }}; ++ + status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr); + if (status != MMAL_SUCCESS) + { +@@ -375,6 +378,14 @@ bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) + MMAL_PORT_T *m_deint_input = m_deint->input[0]; + m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; + ++ if (!advanced_deinterlace) ++ { ++ // 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, -2); ++ 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)); ++ } ++ + // Now connect the decoder output port to deinterlace input port + status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); + if (status != MMAL_SUCCESS) + +From cbe862cd4ba91370d31a9b015c413eeb2a504864 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:36:48 +0100 +Subject: [PATCH 87/95] [mmalrenderer] Avoid submitting a buffer to renderer + twice + +Bad things happen when submitting a buffer to renderer twice. We were attempting to protect against that with +a flip count. However that was getting reset from AddProcessor, the the sequence: +Decode->AddProcessor->RenderUpdate->AddProcessor->RenderUpdate +could occur. Instead use a bit from the MMAL flags which is unlikely to get out of sync with the MMAL buffer. +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 15 ++++++++++++--- + xbmc/cores/VideoRenderers/MMALRenderer.h | 1 - + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 3 ++- + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index f4c59ea..357d023 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -54,6 +54,7 @@ void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T * + + if (m_format == RENDER_FMT_MMAL) + { ++ buffer->flags &= ~MMAL_BUFFER_HEADER_FLAG_USER2; + mmal_queue_put(m_release_queue, buffer); + } + else if (m_format == RENDER_FMT_YUV420P) +@@ -359,9 +360,6 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + SetVideoRect(m_sourceRect, m_destRect); + + YUVBUFFER *buffer = &m_buffers[source]; +- // we only want to upload frames once +- if (buffer->flipindex++) +- return; + if (m_format == RENDER_FMT_MMAL) + { + CMMALVideoBuffer *omvb = buffer->MMALBuffer; +@@ -370,7 +368,11 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s %p (%p)", CLASSNAME, __func__, omvb, omvb->mmal_buffer); + #endif ++ // we only want to upload frames once ++ if (omvb->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER1) ++ return; + omvb->Acquire(); ++ omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1 | MMAL_BUFFER_HEADER_FLAG_USER2; + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); + } //else assert(0); + } +@@ -378,7 +380,14 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + { + CLog::Log(LOGDEBUG, "%s::%s - %p %d", CLASSNAME, __func__, buffer->mmal_buffer, source); + if (buffer->mmal_buffer) ++ { ++ // we only want to upload frames once ++ if (buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER1) ++ return; ++ // sanity check it is not on display ++ buffer->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1; + mmal_port_send_buffer(m_vout_input, buffer->mmal_buffer); ++ } + else assert(0); + } + else assert(0); +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h +index 3422e2d..6e8f240 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.h ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.h +@@ -49,7 +49,6 @@ class CMMALRenderer : public CBaseRenderer, public CThread + { + CMMALVideoBuffer *MMALBuffer; // used for hw decoded buffers + MMAL_BUFFER_HEADER_T *mmal_buffer; // used for sw decoded buffers +- unsigned flipindex; /* used to decide if this has been uploaded */ + }; + public: + CMMALRenderer(); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 03d397f..7410c36 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -1007,7 +1007,8 @@ void CMMALVideo::ReturnBuffer(CMMALVideoBuffer *buffer) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_output_busy); +- ++ // sanity check it is not on display ++ assert(!(buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER2)); + mmal_buffer_header_release(buffer->mmal_buffer); + } + + +From 3246e4b15054daaa27afdab80fe55035c174158a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:37:25 +0100 +Subject: [PATCH 88/95] [omximage] Increase timeout on encode + +--- + xbmc/cores/omxplayer/OMXImage.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp +index e79f41d..d99d719 100644 +--- a/xbmc/cores/omxplayer/OMXImage.cpp ++++ b/xbmc/cores/omxplayer/OMXImage.cpp +@@ -1414,7 +1414,7 @@ bool COMXImageEnc::Encode(unsigned char *buffer, int size, unsigned width, unsig + m_omx_encoder.DecoderFillBufferDone(m_omx_encoder.GetComponent(), m_encoded_buffer); + return false; + } +- omx_err = m_omx_encoder.WaitForOutputDone(1000); ++ omx_err = m_omx_encoder.WaitForOutputDone(2000); + if(omx_err != OMX_ErrorNone) + { + CLog::Log(LOGERROR, "%s::%s m_omx_encoder.WaitForOutputDone result(0x%x)\n", CLASSNAME, __func__, omx_err); + +From f760ec8883cf487ef38ae6729f72b4f880327057 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 01:25:04 +0100 +Subject: [PATCH 89/95] [mmalrenderer] Reset m_buffers on PreInit + +When switching rapidly between different files you sometimes ended up with a stale buffer +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 357d023..82a066b 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -374,7 +374,9 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + omvb->Acquire(); + omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1 | MMAL_BUFFER_HEADER_FLAG_USER2; + mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); +- } //else assert(0); ++ } ++ else ++ CLog::Log(LOGDEBUG, "%s::%s - No buffer to update", CLASSNAME, __func__); + } + else if (m_format == RENDER_FMT_YUV420P) + { +@@ -388,7 +390,8 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + buffer->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1; + mmal_port_send_buffer(m_vout_input, buffer->mmal_buffer); + } +- else assert(0); ++ else ++ CLog::Log(LOGDEBUG, "%s::%s - No buffer to update", CLASSNAME, __func__); + } + else assert(0); + } +@@ -423,6 +426,7 @@ unsigned int CMMALRenderer::PreInit() + m_formats.push_back(RENDER_FMT_MMAL); + m_formats.push_back(RENDER_FMT_BYPASS); + ++ memset(m_buffers, 0, sizeof m_buffers); + m_iYV12RenderBuffer = 0; + m_NumYV12Buffers = NUM_BUFFERS; + + +From e9da9c7eec1b031b9735ec665aa6a6d300566074 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:34:00 +0100 +Subject: [PATCH 90/95] [mmalrenderer] Add locking around m_droppedPics + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 7410c36..5018f3e 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -267,6 +267,9 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + + if (m_drop_state) + { ++ pthread_mutex_lock(&m_output_mutex); ++ m_droppedPics++; ++ pthread_mutex_unlock(&m_output_mutex); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); + } +@@ -756,6 +759,7 @@ void CMMALVideo::SetDropState(bool bDrop) + { + buffer = m_output_ready.front(); + m_output_ready.pop(); ++ m_droppedPics++; + } + pthread_mutex_unlock(&m_output_mutex); + if (buffer) +@@ -869,6 +873,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + + if (demuxer_bytes == 0) + { ++ pthread_mutex_lock(&m_output_mutex); + m_decode_frame_number++; + m_startframe = true; + if (m_drop_state) +@@ -878,11 +883,10 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + else + { + // only push if we are successful with feeding mmal +- pthread_mutex_lock(&m_output_mutex); + m_dts_queue.push(dts); + assert(m_dts_queue.size() < 5000); +- pthread_mutex_unlock(&m_output_mutex); + } ++ pthread_mutex_unlock(&m_output_mutex); + if (m_changed_count_dec != m_changed_count) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -981,6 +985,7 @@ void CMMALVideo::Reset(void) + while (!m_demux_queue.empty()) + m_demux_queue.pop(); + m_demux_queue_length = 0; ++ m_droppedPics = 0; + pthread_mutex_unlock(&m_output_mutex); + if (!old_drop_state) + SetDropState(false); +@@ -990,7 +995,6 @@ void CMMALVideo::Reset(void) + + m_startframe = false; + m_decoderPts = DVD_NOPTS_VALUE; +- m_droppedPics = 0; + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + } +@@ -1124,9 +1128,11 @@ bool CMMALVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) + + bool CMMALVideo::GetCodecStats(double &pts, int &droppedPics) + { ++ pthread_mutex_lock(&m_output_mutex); + pts = m_decoderPts; + droppedPics = m_droppedPics; + m_droppedPics = 0; ++ pthread_mutex_unlock(&m_output_mutex); + //if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + // CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); + return true; + +From be542f7a57abb5cc6a0faf94cc9a740721c36af5 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:31:47 +0100 +Subject: [PATCH 91/95] [mmalrenderer] Add SetCodecControl function and prefer + to return pictures when renderer is low (disabled) + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp | 5 +++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h | 1 + + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 12 ++++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 ++ + 4 files changed, 20 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +index 262283d..ee7d6f2 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +@@ -96,6 +96,11 @@ bool CDVDVideoCodecMMAL::GetCodecStats(double &pts, int &droppedPics) + return m_decoder->GetCodecStats(pts, droppedPics); + } + ++void CDVDVideoCodecMMAL::SetCodecControl(int flags) ++{ ++ m_decoder->SetCodecControl(flags); ++} ++ + void CDVDVideoCodecMMAL::SetSpeed(int iSpeed) + { + m_decoder->SetSpeed(iSpeed); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +index a768e70..aa8e87f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +@@ -42,6 +42,7 @@ class CDVDVideoCodecMMAL : public CDVDVideoCodec + virtual void SetDropState(bool bDrop); + virtual const char* GetName(void); + virtual bool GetCodecStats(double &pts, int &droppedPics); ++ virtual void SetCodecControl(int flags); + virtual void SetSpeed(int iSpeed); + + protected: +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 5018f3e..3868342 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -130,6 +130,7 @@ CMMALVideo::CMMALVideo() + m_es_format = mmal_format_alloc(); + m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; ++ m_codecControlFlags = 0; + } + + CMMALVideo::~CMMALVideo() +@@ -945,6 +946,9 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - got output picture:%d", CLASSNAME, __func__, m_output_ready.size()); + ret |= VC_PICTURE; ++ // renderer is low - give priority to returning pictures ++ if (0 && m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) ++ ret &= ~VC_BUFFER; + } + if (!ret) + { +@@ -997,6 +1001,7 @@ void CMMALVideo::Reset(void) + m_decoderPts = DVD_NOPTS_VALUE; + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); ++ m_codecControlFlags = 0; + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -1137,3 +1142,10 @@ bool CMMALVideo::GetCodecStats(double &pts, int &droppedPics) + // CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); + return true; + } ++ ++void CMMALVideo::SetCodecControl(int flags) ++{ ++ m_codecControlFlags = flags; ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "%s::%s flags:%x", CLASSNAME, __func__, flags); ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index ca513f6..ec44b13 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -90,6 +90,7 @@ class CMMALVideo + virtual void SetDropState(bool bDrop); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } + virtual bool GetCodecStats(double &pts, int &droppedPics); ++ virtual void SetCodecControl(int flags); + virtual void SetSpeed(int iSpeed); + + // MMAL decoder callback routines. +@@ -143,6 +144,7 @@ class CMMALVideo + unsigned int m_droppedPics; + int m_speed; + bool m_preroll; ++ int m_codecControlFlags; + + MMAL_COMPONENT_T *m_dec; + MMAL_PORT_T *m_dec_input; + +From 9e4a74b068b7b92187627fd116dc0a1454152dc7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 16:31:37 +0100 +Subject: [PATCH 92/95] [mmalcodec] Limit submitted video frames. Seems to + avoid stutter issues with low bitrate videos + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 3868342..2e23430 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -929,7 +929,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + break; + } + int ret = 0; +- if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length) ++ int fps = m_hints.fpsrate && m_hints.fpsscale ? (float)m_hints.fpsrate / (float)m_hints.fpsscale : 25; ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length && m_dts_queue.size() <= fps/2) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); + +From 1c57cab24d5ee75a1f47ed05110b647335dd8872 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 18:35:01 +0100 +Subject: [PATCH 93/95] [rbp] Disable analogue output of sync when passthrough + is enabled + +The analogue and output of Pi Sink doesn't support passthrough. +This also applies to the 'Both' (HDMI and Analogue) setting. +If passthrough is enabled in GUI you get black screen and errors: +https://discourse.osmc.tv/t/some-streams-are-staying-black/2311 + +We need to either disable passthrough or disable analogue. + +I think the best solution to this is to force HDMI output when passthrough is active. + +This allows a user to use receiver for videos with dts/ac3 and TV for music or lower quality formats. +--- + xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 22 ++++++++++++++-------- + xbmc/cores/AudioEngine/Sinks/AESinkPi.h | 1 + + xbmc/cores/omxplayer/OMXAudio.cpp | 21 +++++++++++++++------ + xbmc/cores/omxplayer/OMXAudio.h | 1 + + 4 files changed, 31 insertions(+), 14 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +index 7f4d103..b69925a 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -45,7 +45,8 @@ CAESinkPi::CAESinkPi() : + m_latency(0), + m_Initialized(false), + m_submitted(0), +- m_omx_output(NULL) ++ m_omx_output(NULL), ++ m_output(AESINKPI_UNKNOWN) + { + } + +@@ -60,7 +61,7 @@ void CAESinkPi::SetAudioDest() + OMX_INIT_STRUCTURE(audioDest); + if ( m_omx_render.IsInitialized() ) + { +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (m_output == AESINKPI_ANALOGUE) + strncpy((char *)audioDest.sName, "local", strlen("local")); + else + strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); +@@ -70,7 +71,7 @@ void CAESinkPi::SetAudioDest() + } + if ( m_omx_render_slave.IsInitialized() ) + { +- if (CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue") ++ if (m_output != AESINKPI_ANALOGUE) + strncpy((char *)audioDest.sName, "local", strlen("local")); + else + strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi")); +@@ -193,12 +194,17 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + m_latency = CSettings::Get().GetInt("audiooutput.latency") * 1e-3; + m_latency = std::max(m_latency, 50e-3); + ++ if (m_passthrough || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:HDMI") ++ m_output = AESINKPI_HDMI; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ m_output = AESINKPI_ANALOGUE; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ m_output = AESINKPI_BOTH; ++ else assert(0); ++ + // analogue only supports stereo +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") +- { ++ if (m_output == AESINKPI_ANALOGUE || m_output == AESINKPI_BOTH) + format.m_channelLayout = AE_CH_LAYOUT_2_0; +- m_passthrough = false; +- } + + // setup for a 50ms sink feed from SoftAE + if (format.m_dataFormat != AE_FMT_FLOATP && format.m_dataFormat != AE_FMT_FLOAT && +@@ -226,7 +232,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) + 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 (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ 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); +diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +index cac5051..10b0ec6 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.h ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.h +@@ -65,6 +65,7 @@ class CAESinkPi : public IAESink + bool m_passthrough; + COMXCoreTunel m_omx_tunnel_splitter; + COMXCoreTunel m_omx_tunnel_splitter_slave; ++ enum { AESINKPI_UNKNOWN, AESINKPI_HDMI, AESINKPI_ANALOGUE, AESINKPI_BOTH } m_output; + }; + + #endif +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index dd5cdb8..9d960aa 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -88,7 +88,8 @@ COMXAudio::COMXAudio() : + m_extrasize (0 ), + m_last_pts (DVD_NOPTS_VALUE), + m_submitted_eos (false ), +- m_failed_eos (false ) ++ m_failed_eos (false ), ++ m_output (AESINKPI_UNKNOWN) + { + CAEFactory::Suspend(); + while (!CAEFactory::IsSuspended()) +@@ -119,17 +120,17 @@ bool COMXAudio::PortSettingsChanged() + if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit)) + return false; + } +- if(CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ if(m_output == AESINKPI_BOTH) + { + if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit)) + return false; + } +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (m_output == AESINKPI_BOTH || m_output == AESINKPI_ANALOGUE) + { + if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; + } +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue") ++ if (m_output == AESINKPI_BOTH || m_output != AESINKPI_ANALOGUE) + { + if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit)) + return false; +@@ -248,7 +249,7 @@ bool COMXAudio::PortSettingsChanged() + // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock. + // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync + if((CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) || +- CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ m_output == AESINKPI_BOTH) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -570,6 +571,14 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + } + SetCodingType(format.m_dataFormat); + ++ if (m_Passthrough || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:HDMI") ++ m_output = AESINKPI_HDMI; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ m_output = AESINKPI_ANALOGUE; ++ else if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both") ++ m_output = AESINKPI_BOTH; ++ else assert(0); ++ + if(hints.extrasize > 0 && hints.extradata != NULL) + { + m_extrasize = hints.extrasize; +@@ -597,7 +606,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo + CAEChannelInfo stdLayout = (enum AEStdChLayout)CSettings::Get().GetInt("audiooutput.channels"); + + // ignore layout setting for analogue +- if (CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both" || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue") ++ if (m_output == AESINKPI_ANALOGUE || m_output == AESINKPI_BOTH) + stdLayout = AE_CH_LAYOUT_2_0; + + CAEChannelInfo resolvedMap = channelMap; +diff --git a/xbmc/cores/omxplayer/OMXAudio.h b/xbmc/cores/omxplayer/OMXAudio.h +index 569cb09..c31d25e 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.h ++++ b/xbmc/cores/omxplayer/OMXAudio.h +@@ -124,6 +124,7 @@ class COMXAudio + double m_last_pts; + bool m_submitted_eos; + bool m_failed_eos; ++ enum { AESINKPI_UNKNOWN, AESINKPI_HDMI, AESINKPI_ANALOGUE, AESINKPI_BOTH } m_output; + + typedef struct { + double pts; + +From dcecbf718d05a56d6dad63f451693780eb706fcb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 15:40:22 +0100 +Subject: [PATCH 94/95] [mmalrenderer] Discard corrupt frames later so we can + track the number of discarded frames + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 2e23430..fc4b29f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -274,6 +274,11 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); + } ++ else if (g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED)) ++ { ++ CLog::Log(LOGDEBUG, "%s::%s - %p buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x Corrupted", ++ CLASSNAME, __func__, buffer, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags); ++ } + else + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); +@@ -643,7 +648,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + + error_concealment.hdr.id = MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT; + error_concealment.hdr.size = sizeof(MMAL_PARAMETER_BOOLEAN_T); +- error_concealment.enable = g_advancedSettings.m_omxDecodeStartWithValidFrame; ++ error_concealment.enable = false;; + status = mmal_port_parameter_set(m_dec_input, &error_concealment.hdr); + 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)); + +From 9de11dd235a93e84e64fe033e32c4961b14552ed Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 00:25:26 +0100 +Subject: [PATCH 95/95] [mmalcodec] Allocate more buffers when deinterlacing + +Needed with trickplay with deinterlace. TODO: can this be reduced +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index fc4b29f..342c9cb 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -387,13 +387,10 @@ bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) + MMAL_PORT_T *m_deint_input = m_deint->input[0]; + m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; + +- if (!advanced_deinterlace) +- { +- // 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, -2); +- 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)); +- } ++ // 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, GetAllowedReferences() - 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)); + + // Now connect the decoder output port to deinterlace input port + status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT);