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..05de2d0d20 --- /dev/null +++ b/projects/RPi/patches/kodi/kodi-001-isengard-rpb-backports.patch @@ -0,0 +1,9725 @@ +From 9d98beccd9d65e5a86b488f0ceb90448f2c9a5f3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 18:19:32 +0100 +Subject: [PATCH 001/103] [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 274fcbff2f4a4c64f92a0d4cf1cdfed8f3045259 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 29 Apr 2014 15:23:22 +0100 +Subject: [PATCH 002/103] [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 681ca292791c12e51b745db0629376902377367b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 2 Aug 2014 17:48:04 +0100 +Subject: [PATCH 003/103] [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 3e320b31a6b000fbcd212e8b7138c88e2b77dfaa Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 8 Mar 2014 15:36:06 +0000 +Subject: [PATCH 004/103] [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 6828241cd39ce51a64ef4e25394620d034afd10f Mon Sep 17 00:00:00 2001 +From: Ben Avison +Date: Thu, 1 May 2014 16:28:39 +0100 +Subject: [PATCH 005/103] 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 cdd2b2e9dacd31ab126e635aee2061bc8dc1e920 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 12 Aug 2014 00:31:36 +0100 +Subject: [PATCH 006/103] [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 143ea06..e029c16 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3345,7 +3345,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 bb8c24c64263afa825341429bd22a49a774c96b8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 10 Aug 2014 16:45:16 +0100 +Subject: [PATCH 007/103] 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 e7244d1..a762609 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 323a2f1..f008579 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 14b7c230cf053a22a015126b6bce83bc8ad7cf5c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 13:06:57 +0000 +Subject: [PATCH 009/103] [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 910468040e6fe46799e99ecdd4ae3223c37b2b50 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 30 May 2014 14:58:43 +0100 +Subject: [PATCH 011/103] [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 7285aff9a873a23fd65867428cb0007b9ea07948 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 9 Sep 2014 12:04:26 +0100 +Subject: [PATCH 012/103] 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 897c19a7803148ca067b9e5cea4e43e320c4fd67 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 14:24:56 +0100 +Subject: [PATCH 013/103] [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 503f7e7fb4a0e74ff3092c7ff461620634f01d09 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 19 Sep 2014 11:54:49 +0100 +Subject: [PATCH 014/103] [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 a762609..8cd2b39 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" +@@ -16565,3 +16580,10 @@ msgstr "" + msgctxt "#38016" + msgid "%d 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 f008579..8395973 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 74df969..416e6f8 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) + { +@@ -484,7 +489,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"; + +@@ -638,8 +647,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; + } +@@ -749,7 +758,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; + } + + bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) +@@ -802,6 +823,7 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + { + m_dvdAudio.AddPackets(audioframe); + } ++ m_plladjust = 1.0; + } + else if (m_synctype == SYNC_DISCON) + { +@@ -836,6 +858,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 99ce952..635c184 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +@@ -232,6 +232,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 3f55c9edc572baeb0c43fdd4e60a030ce1a6ea9e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 27 Sep 2014 15:32:37 +0100 +Subject: [PATCH 015/103] [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 e029c16..63f4a30 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3330,7 +3330,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 3d434543097974c95cc25dc07f9ece37ba2e6bc1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 24 Sep 2014 23:13:52 +0100 +Subject: [PATCH 016/103] [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 8cd2b39..fa7c455 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16587,3 +16587,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 8395973..29a9ef6 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 ccd32242f5696ac4e639cb2c686c277b876112f5 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:40:06 +0100 +Subject: [PATCH 017/103] [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 d54c0004c7889382e48a3b2015d7e6920fdae119 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 15:23:51 +0000 +Subject: [PATCH 018/103] [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 cb83297..8496abf 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -38,6 +38,16 @@ + + + ++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ + + +
+ +From 49ef564d2e2c4f15a81fb727ed4abb03f299a66e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 15 Nov 2014 12:03:34 +0000 +Subject: [PATCH 022/103] [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 63f4a30..3c313cd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -529,6 +529,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)) + { +@@ -558,6 +559,7 @@ void CDVDPlayer::CreatePlayers() + + void CDVDPlayer::DestroyPlayers() + { ++ CSingleLock lock(m_players_lock); + if (!m_players_created) + return; + delete m_dvdPlayerVideo; +@@ -4190,6 +4192,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 468239c..3b8cefb 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -558,4 +558,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 d2e6086e65aa2bb6fee41c413db5cac0e31b2c0e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 24 Nov 2014 22:07:25 +0000 +Subject: [PATCH 023/103] [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 4f95fb3b9cacf2e968291b0bc448df6ce684928b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 27 Nov 2014 16:31:56 +0000 +Subject: [PATCH 024/103] [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 4ac74fa770ca65859284e1541d1b8ef5ed658d30 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Dec 2013 16:55:05 +0000 +Subject: [PATCH 025/103] 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 602c2edc4b65379dd6872e245ced5f240505f932 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:24:42 +0200 +Subject: [PATCH 026/103] 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 cac8aa5c89dbfe566b0d410bb4b66012b0ffaa2c Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:29:03 +0200 +Subject: [PATCH 027/103] 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 3861ee5d79e6daa334b19247ace9753027fad450 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:50:58 +0200 +Subject: [PATCH 028/103] 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 bfe83fe7109a35fc5b323cd71fededa78375cc8f Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:54:59 +0200 +Subject: [PATCH 029/103] 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 b3fc8a5fc3e58091b95aa0f2ca9f78353ce27c9e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Aug 2013 15:03:36 +0100 +Subject: [PATCH 030/103] 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 51fdf84..e00916a 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 c6f62d8db0..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 bdd759a61f9ff2da25014aa45da9997fd51bd7a6 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:23:01 +0200 +Subject: [PATCH 031/103] 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 33be5d47278da30a21fda820324af9a3423fb2e8 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:24:22 +0200 +Subject: [PATCH 032/103] 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 709dfc42ba253ec392a266efa986b3da0f2020b2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:16:29 +0000 +Subject: [PATCH 033/103] [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 d3f8b6d306df8585bf4109b29bcab90c8a938ab4 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:47:54 +0000 +Subject: [PATCH 034/103] [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 27bc221d7dd08c12f07a7c3b7ddef78e19798777 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 17:30:07 +0000 +Subject: [PATCH 035/103] [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 8609e7646814b273206d83b4fb973eab4ce768fe Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 4 Mar 2014 19:33:44 +0000 +Subject: [PATCH 036/103] [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 c8eceb5866e755200441f9301d96d6cf99760b77 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 26 Apr 2014 17:27:52 +0100 +Subject: [PATCH 037/103] [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 15b45e982c686259159223839618d0422c789f92 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Jun 2014 00:01:05 +0100 +Subject: [PATCH 038/103] [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 20f0bf8ef85a8c11b6fe4b6318ee925b753a9097 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 11 Apr 2014 16:12:27 +0100 +Subject: [PATCH 039/103] [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 22a1696..5fc9d65 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 61c67e0ee0a882807b80a4ad85c5c9a476fc58b0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 040/103] [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 5fc9d65..caf6ee6 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 3d935ad808f8f753468091b5f7461d0cc4b781a6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 18 Aug 2014 19:09:32 +0100 +Subject: [PATCH 041/103] 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 648a6b3b7564b05e77b0039560755225c02852c4 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Nov 2014 17:16:54 +0000 +Subject: [PATCH 042/103] 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 caf6ee6..5fc9d65 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 14bfe644ca9aba1a482bf631ca0fa714d4502b61 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 043/103] [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 5fc9d65..caf6ee6 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 3c313cd..8ceb498 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); +@@ -974,6 +1029,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) +@@ -3475,6 +3536,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 718edc6ac5a59f2473592bd4646f54f904807a6f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 29 Nov 2014 15:25:16 +0000 +Subject: [PATCH 044/103] [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 0b3bfb6bac019ffbd0af4689fbdd3e785cc44957 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 5 Oct 2014 14:05:25 +0100 +Subject: [PATCH 045/103] [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 caf6ee6..7b1089d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16631,3 +16631,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 8496abf..5068b20 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -89,6 +89,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 15eeb598e03a492404dfb754a0eb5e07342f990e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 11 Dec 2014 17:00:57 +0000 +Subject: [PATCH 046/103] 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 7b1089d..e8d5f7c 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 +@@ -16646,3 +16646,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 5068b20..6e9ceaf 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -36,10 +36,6 @@ + + false + +- +- +- +- + + false + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 29a9ef6..bdba486 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 b2a98eb56639907c3305775d0fcaee9f6bc0f03e Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Thu, 11 Sep 2014 21:30:43 +0200 +Subject: [PATCH 047/103] 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 e00916a..6e0aeff 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -4948,3 +4948,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 b4da8f2..cc064c3 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 7b7f2ac4ef55297e4328736678a5ed436f83a830 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 13 Dec 2014 18:35:20 +0000 +Subject: [PATCH 048/103] [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 6b4af4de9aaa4c125272e087680652db3b924ec1 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:27:59 +0100 +Subject: [PATCH 049/103] - 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 e8d5f7c..8858c95 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 bdba486..67472f6 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -465,6 +465,11 @@ + false + + ++ ++ 1 ++ true ++ ++ + + + + +From 8eb308d186e18f8c8d23c1d77fa28fd11fa0238f Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:28:36 +0100 +Subject: [PATCH 050/103] - 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 a703de3..1212e09 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 6626ed33fcd8daa13811c72bbdd1fe455dd19366 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Jan 2015 21:48:31 +0000 +Subject: [PATCH 051/103] [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 1664527d983c1a063d7145e90749af5b0d212990 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 24 Jan 2015 17:34:04 +0000 +Subject: [PATCH 052/103] 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 e4f51eb17146ed9b71c99968cc8a539894c02b97 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Wed, 4 Feb 2015 22:32:03 +0100 +Subject: [PATCH 053/103] 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 1bf1cc0f8335f67ab3ddff9aac3bfe86d57b6138 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Feb 2015 00:19:51 +0000 +Subject: [PATCH 056/103] [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 4b88d98c3ba80b522d1a34cfebe6e9a629113cee Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 14:06:12 +0000 +Subject: [PATCH 057/103] [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 17f7f8502ce5429461202b3f4b609d9478577485 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 15:29:51 +0000 +Subject: [PATCH 058/103] [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 | 106 +++++++++++++++++++++++++++++++++++++++++++++ + xbmc/linux/RBP.h | 2 + + xbmc/settings/Settings.cpp | 7 ++- + 3 files changed, 114 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..ffdcb36 +--- /dev/null ++++ b/system/settings/rbp2.xml +@@ -0,0 +1,106 @@ ++ ++ ++
++ ++ ++ false ++ ++ ++ ++ false ++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ ++ ++ ++ 2 ++ 10 ++ ++ 0 ++ 5 ++ 25 ++ ++ ++ 38016 ++ ++ ++ ++ ++ ++ ++ ++ ++ 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 139817f..ab9c6fd 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 750290b96315c47a5cf1dbc2f4696481d9be8750 Mon Sep 17 00:00:00 2001 +From: Claudio-Sjo +Date: Mon, 16 Feb 2015 14:51:26 +0100 +Subject: [PATCH 059/103] - 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 af144ae9182175bd150cfd6c5920d019f7608d34 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 20 Feb 2015 14:11:57 +0000 +Subject: [PATCH 060/103] 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 d51cbcb8bab40754cf93919b1c5604944781375e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 00:09:19 +0000 +Subject: [PATCH 061/103] [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 a7fd3cef4b00d619163cf633077536887fc0f36d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 15:57:29 +0000 +Subject: [PATCH 062/103] [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 25817c925fec4954e78a2e852b7ca1c0ef50ba6c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 14:37:27 +0000 +Subject: [PATCH 063/103] 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 2780425800930e12a685727f6ea67d47bace6b41 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 19:07:17 +0000 +Subject: [PATCH 064/103] [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 59faf7fd1d9849cd8f6524a14d86b02b065ebdd3 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Wed, 25 Feb 2015 18:22:21 +0100 +Subject: [PATCH 065/103] 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 5e091eb..35b417f 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 6c14cd5..7e960ad 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 50d352d6656308960ad3e651f78688aec8237423 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 5 Mar 2015 20:00:59 +0000 +Subject: [PATCH 066/103] [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 e0feb4ed215e9fbe93c44eceb45214027f3c87c0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 7 Mar 2015 22:46:21 +0000 +Subject: [PATCH 067/103] 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 ae0626f..85d0c72 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], +@@ -300,34 +301,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 da6be7609a0ce66cc87d86b308e0561b04835875 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 16 Apr 2014 21:18:06 +0100 +Subject: [PATCH 068/103] [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 595f15cd5e389f7d3c37b06d5cdddb878560a303 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:01:51 +0100 +Subject: [PATCH 069/103] [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 241c252fd08754d237c78288b6aaed2595c86dda Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:38:55 +0100 +Subject: [PATCH 070/103] [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 4345c0f..cc5dc60 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 a813ff2c01902d9e5c7f59ae43b08c3c63a7c3db Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 23 Apr 2014 00:05:07 +0100 +Subject: [PATCH 071/103] [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 cc5dc60..0c23290 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 8e2a045b4f3746e523f40d22db434801c72d9adf Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Mar 2015 17:05:18 +0000 +Subject: [PATCH 072/103] [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 8858c95..82bb99d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16659,6 +16659,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 6e9ceaf..ed61ca6 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -30,6 +30,16 @@ + +
+
++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index ffdcb36..e909cc4 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -33,6 +33,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 18240f9b0072c6ea1e8707824ab8ff4b3e75aa5b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Mar 2015 12:38:08 +0000 +Subject: [PATCH 073/103] [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 82bb99d..d0d77c5 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16669,6 +16669,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 ed61ca6..42d4da7 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -39,6 +39,14 @@ + true + +
++ ++ ++ true ++ ++ 2 ++ true ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index e909cc4..dff4da8 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -42,6 +42,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 a45bafbf944a6a91f9b2d778714877bd7cb89b0f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 17 Mar 2015 20:33:54 +0000 +Subject: [PATCH 074/103] 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 fc62ae2cfaac76e0fc667ce298befbf240d7981b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 21 Mar 2015 21:46:16 +0000 +Subject: [PATCH 075/103] 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 6881d9550814c63db3c9eeea719c73a34f3ccd0e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 22 Mar 2015 19:32:36 +0000 +Subject: [PATCH 076/103] [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 cd89da5ff195c665573488bc23d5064590b5dfb6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 23 Mar 2015 23:50:50 +0000 +Subject: [PATCH 079/103] [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 ca7ac79e3ae84f9004d6ad1ff97f284d5792963e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Mar 2015 17:24:27 +0000 +Subject: [PATCH 080/103] [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 93285a243328c5d05e7437715e90c4fb4ed701b2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:36:48 +0100 +Subject: [PATCH 081/103] [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 e0aa63a4be636c5f6bee31df646170d616836c72 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:37:25 +0100 +Subject: [PATCH 082/103] [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 6b974ed76e12bd270969ad6f8bf3ec43f2193d34 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 01:25:04 +0100 +Subject: [PATCH 083/103] [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 f3983e34dde74a7cb8b0f0c8b3bd8c573ec66b3d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:34:00 +0100 +Subject: [PATCH 084/103] [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 26a386aac6449208c791dbf0de920aca4c46a4ce Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:31:47 +0100 +Subject: [PATCH 085/103] [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 74cc992c8216da6e5a39fe5f470005c9d1accdbb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 16:31:37 +0100 +Subject: [PATCH 086/103] [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 66bb7019bb917be310d6a2bd21fb206302d8ee1a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 18:35:01 +0100 +Subject: [PATCH 087/103] [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 91009891251f052d8a1dc74deac32990cd8deb65 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 15:40:22 +0100 +Subject: [PATCH 088/103] [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..a842ddd 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 0e0ac43fad3b3ec91c7fb11ac482e7e0b655d213 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 6 Apr 2015 19:08:20 +0100 +Subject: [PATCH 089/103] Revert "[mmalrenderer] Discard corrupt frames later + so we can track the number of discarded frames" + +This reverts commit e3f57826eff42a3f1843dffd978ac98bda372826. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index a842ddd..2e23430 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -274,11 +274,6 @@ 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); +@@ -648,7 +643,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 = false; ++ error_concealment.enable = g_advancedSettings.m_omxDecodeStartWithValidFrame; + 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 3c322da17a4b5e38cd9e683db4353badca1dab42 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 00:25:26 +0100 +Subject: [PATCH 090/103] [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 2e23430..180b96f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -382,13 +382,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); + +From 0248c175316462dfe5bf4721b062db88f109c561 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 3 Apr 2015 10:49:55 +0200 +Subject: [PATCH 091/103] dvdplayer: cosmetics + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 41 ++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 19 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 8ceb498..1f220c6 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1454,16 +1454,18 @@ void CDVDPlayer::Process() + + m_OmxPlayerState.bOmxSentEOFs = true; + } ++ + if(m_CurrentAudio.inited) +- m_dvdPlayerAudio->SendMessage (new CDVDMsg(CDVDMsg::GENERAL_EOF)); ++ m_dvdPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); + if(m_CurrentVideo.inited) +- m_dvdPlayerVideo->SendMessage (new CDVDMsg(CDVDMsg::GENERAL_EOF)); ++ m_dvdPlayerVideo->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); + if(m_CurrentSubtitle.inited) + m_dvdPlayerSubtitle->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); + if(m_CurrentTeletext.inited) + m_dvdPlayerTeletext->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); +- m_CurrentAudio.inited = false; +- m_CurrentVideo.inited = false; ++ ++ m_CurrentAudio.inited = false; ++ m_CurrentVideo.inited = false; + m_CurrentSubtitle.inited = false; + m_CurrentTeletext.inited = false; + +@@ -1573,21 +1575,22 @@ bool CDVDPlayer::CheckIsCurrent(CCurrentStream& current, CDemuxStream* stream, D + + void CDVDPlayer::ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket) + { +- /* process packet if it belongs to selected stream. for dvd's don't allow automatic opening of streams*/ +- +- if (CheckIsCurrent(m_CurrentAudio, pStream, pPacket)) +- ProcessAudioData(pStream, pPacket); +- else if (CheckIsCurrent(m_CurrentVideo, pStream, pPacket)) +- ProcessVideoData(pStream, pPacket); +- else if (CheckIsCurrent(m_CurrentSubtitle, pStream, pPacket)) +- ProcessSubData(pStream, pPacket); +- else if (CheckIsCurrent(m_CurrentTeletext, pStream, pPacket)) +- ProcessTeletextData(pStream, pPacket); +- else +- { +- pStream->SetDiscard(AVDISCARD_ALL); +- CDVDDemuxUtils::FreeDemuxPacket(pPacket); // free it since we won't do anything with it +- } ++ // process packet if it belongs to selected stream. ++ // for dvd's don't allow automatic opening of streams*/ ++ ++ if (CheckIsCurrent(m_CurrentAudio, pStream, pPacket)) ++ ProcessAudioData(pStream, pPacket); ++ else if (CheckIsCurrent(m_CurrentVideo, pStream, pPacket)) ++ ProcessVideoData(pStream, pPacket); ++ else if (CheckIsCurrent(m_CurrentSubtitle, pStream, pPacket)) ++ ProcessSubData(pStream, pPacket); ++ else if (CheckIsCurrent(m_CurrentTeletext, pStream, pPacket)) ++ ProcessTeletextData(pStream, pPacket); ++ else ++ { ++ pStream->SetDiscard(AVDISCARD_ALL); ++ CDVDDemuxUtils::FreeDemuxPacket(pPacket); // free it since we won't do anything with it ++ } + } + + void CDVDPlayer::CheckStreamChanges(CCurrentStream& current, CDemuxStream* stream) + +From c1a1141d6ed1699fc2ab1bae805786a58d38786f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 6 Apr 2015 19:06:26 +0100 +Subject: [PATCH 092/103] [mmalcodec] Remove the decoder queue and use gpu + timestamps + +There are too many streams that don't have a 1:1 mapping of encoded video frames to decoded pictures. +If that isn't true, the dts queues gets out of sync with the real frames. + +Interlaces streams and streams with errors cause issues. + +Instead remove the dts queue and use the gpu's timestamps. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 91 +++++++++++----------- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 +- + 2 files changed, 46 insertions(+), 47 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 180b96f..e5ea365 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -131,6 +131,7 @@ CMMALVideo::CMMALVideo() + m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; + m_codecControlFlags = 0; ++ m_history_valid_pts = 0; + } + + CMMALVideo::~CMMALVideo() +@@ -254,27 +255,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); + double dts = DVD_NOPTS_VALUE; +- if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER0) +- { +- pthread_mutex_lock(&m_output_mutex); +- if (!m_dts_queue.empty()) +- { +- dts = m_dts_queue.front(); +- m_dts_queue.pop(); +- } +- else assert(0); +- pthread_mutex_unlock(&m_output_mutex); +- } +- +- 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); +- } +- else ++ if (!m_drop_state) // && !(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -293,6 +274,14 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + pthread_mutex_unlock(&m_output_mutex); + kept = true; + } ++ else ++ { ++ 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 dts:%.3f pts:%.3f (drop:%d len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, m_drop_state, buffer->length, buffer->flags); ++ } + } + } + else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) +@@ -649,6 +638,10 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + ++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, 1); ++ if (status != MMAL_SUCCESS) ++ CLog::Log(LOGERROR, "%s::%s Failed to enable timestamp fifo mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); ++ + status = mmal_port_format_commit(m_dec_input); + if (status != MMAL_SUCCESS) + { +@@ -717,6 +710,8 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + m_startframe = false; + m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; ++ // start from assuming all recent frames had valid pts ++ m_history_valid_pts = ~0; + + return true; + } +@@ -732,10 +727,9 @@ void CMMALVideo::Dispose() + done = true; + pthread_mutex_unlock(&m_output_mutex); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done); ++ CLog::Log(LOGDEBUG, "%s::%s ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_output_ready.size(), m_output_busy, done); + if (done) + { +- assert(m_dts_queue.empty()); + m_myself.reset(); + } + } +@@ -768,11 +762,19 @@ void CMMALVideo::SetDropState(bool bDrop) + } + } + ++static unsigned count_bits(int32_t value) ++{ ++ unsigned bits = 0; ++ for(;value;++bits) ++ value &= value - 1; ++ return bits; ++} ++ + int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + { + //if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- // CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f dts_queue(%d) ready_queue(%d) busy_queue(%d)", +- // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ // CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f ready_queue(%d) busy_queue(%d)", ++ // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_output_ready.size(), m_output_busy); + + unsigned int demuxer_bytes = 0; + uint8_t *demuxer_content = NULL; +@@ -836,6 +838,13 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + return VC_ERROR; + } + ++ // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. ++ // the valid pts values match the dts values. ++ // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts ++ m_history_valid_pts = (m_history_valid_pts << 1) | (pts != DVD_NOPTS_VALUE); ++ if (count_bits(m_history_valid_pts & 0xffff) < 4) ++ pts = dts; ++ + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + if (m_startframe && pts == DVD_NOPTS_VALUE) +@@ -843,9 +852,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->pts = pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pts; + buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts; + buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes; +- buffer->user_data = (void *)m_decode_frame_number; +- // set a flag so we can identify primary frames from generated frames (deinterlace) +- buffer->flags = MMAL_BUFFER_HEADER_FLAG_USER0; + + // Request decode only (maintain ref frames, but don't return a picture) + if (m_drop_state) +@@ -859,8 +865,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)", +- CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); ++ CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)", ++ CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); + assert((int)buffer->length > 0); + status = mmal_port_send_buffer(m_dec_input, buffer); + if (status != MMAL_SUCCESS) +@@ -878,12 +884,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + { + m_droppedPics += m_deint ? 2:1; + } +- else +- { +- // only push if we are successful with feeding mmal +- m_dts_queue.push(dts); +- assert(m_dts_queue.size() < 5000); +- } + pthread_mutex_unlock(&m_output_mutex); + if (m_changed_count_dec != m_changed_count) + { +@@ -926,11 +926,11 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + break; + } + int ret = 0; +- 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) ++ double queued = m_decoderPts != DVD_NOPTS_VALUE && pts != DVD_NOPTS_VALUE ? pts - m_decoderPts : 0.0; ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length && queued <= DVD_MSEC_TO_TIME(500)) + { + 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); ++ CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d) queued(%.2f)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, queued*1e-6); + ret |= VC_BUFFER; + } + else +@@ -951,8 +951,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + if (!ret) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)", +- CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll); ++ CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)", ++ CLASSNAME, __func__, m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll); + Sleep(10); // otherwise we busy spin + } + return ret; +@@ -982,8 +982,6 @@ void CMMALVideo::Reset(void) + bool old_drop_state = m_drop_state; + SetDropState(true); + pthread_mutex_lock(&m_output_mutex); +- while(!m_dts_queue.empty()) +- m_dts_queue.pop(); + while (!m_demux_queue.empty()) + m_demux_queue.pop(); + m_demux_queue_length = 0; +@@ -1000,6 +998,7 @@ void CMMALVideo::Reset(void) + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + m_codecControlFlags = 0; ++ m_history_valid_pts = ~0; + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -1028,8 +1027,8 @@ void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p dts_queue(%d) ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output, +- m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output, ++ m_output_ready.size(), m_output_busy); + status = mmal_port_send_buffer(m_dec_output, buffer); + if (status != MMAL_SUCCESS) + { +@@ -1054,7 +1053,7 @@ void CMMALVideo::ReleaseBuffer(CMMALVideoBuffer *buffer) + if (done) + m_myself.reset(); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s %p (%p) dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done); ++ CLog::Log(LOGDEBUG, "%s::%s %p (%p) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_output_ready.size(), m_output_busy, done); + delete buffer; + } + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index ec44b13..a859467 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -119,7 +119,6 @@ class CMMALVideo + const char *m_pFormatName; + MMALVideoPtr m_myself; + +- std::queue m_dts_queue; + std::queue m_demux_queue; + unsigned m_demux_queue_length; + +@@ -145,6 +144,7 @@ class CMMALVideo + int m_speed; + bool m_preroll; + int m_codecControlFlags; ++ uint32_t m_history_valid_pts; + + MMAL_COMPONENT_T *m_dec; + MMAL_PORT_T *m_dec_input; + +From b4f0f4e150544d573bd61baa8842ecd10212a526 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 7 Apr 2015 19:50:15 +0100 +Subject: [PATCH 093/103] [mmalrenderer] Fix for inverted check for first frame + +--- + 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 e5ea365..7c53347 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -847,7 +847,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; +- if (m_startframe && pts == DVD_NOPTS_VALUE) ++ if (!m_startframe && pts == DVD_NOPTS_VALUE) + pts = 0; + buffer->pts = pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pts; + buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts; + +From 8f998d7464019a7aa254b08f338ba73a0f8e4c03 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 Apr 2015 22:52:03 +0100 +Subject: [PATCH 094/103] Revert "[omxplayer] Only enable audio clock master + when A/V sync method is set to audio clock" + +This reverts commit 56491e6e9f01744f4c43abe7a7ddc1f5a5b179c3. +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 9d960aa..9bb967a 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -248,8 +248,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) || +- m_output == AESINKPI_BOTH) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || m_output == AESINKPI_BOTH) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -275,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") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock")) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); + +From a71bb2cbab462337944da1c6499b5c0c8973bff3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 9 Apr 2015 17:12:56 +0100 +Subject: [PATCH 095/103] squash: add timeout to vc_dispmanx_vsync_callback + +--- + xbmc/linux/RBP.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index fe1df00..8bf0f14 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -196,7 +196,7 @@ void CRBP::WaitVsync() + s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); + if (s == 0) + { +- m_vsync.Wait(); ++ m_vsync.WaitMSec(1000); + } + else assert(0); + s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); + +From 3da7de0426191fae9e88ff8b39fd4c850d7b00df Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 9 Apr 2015 18:18:09 +0100 +Subject: [PATCH 096/103] [mmalrenderer] Remove dropping logic. It only seems + to make things worse + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 76 +++++++--------------- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 - + 2 files changed, 23 insertions(+), 55 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 7c53347..670e13f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -98,7 +98,6 @@ CMMALVideo::CMMALVideo() + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); + pthread_mutex_init(&m_output_mutex, NULL); + +- m_drop_state = false; + m_decoded_width = 0; + m_decoded_height = 0; + +@@ -109,7 +108,6 @@ CMMALVideo::CMMALVideo() + m_interlace_method = VS_INTERLACEMETHOD_NONE; + m_startframe = false; + m_decoderPts = DVD_NOPTS_VALUE; +- m_droppedPics = 0; + m_decode_frame_number = 1; + + m_dec = NULL; +@@ -255,7 +253,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); + double dts = DVD_NOPTS_VALUE; +- if (!m_drop_state) // && !(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) ++ if (1)//(!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -276,11 +274,8 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + } + else + { +- 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 dts:%.3f pts:%.3f (drop:%d len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, m_drop_state, buffer->length, buffer->flags); ++ CLog::Log(LOGDEBUG, "%s::%s - discarding %p dts:%.3f pts:%.3f (len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->flags); + } + } + } +@@ -706,7 +701,6 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + if (!SendCodecConfigData()) + return false; + +- m_drop_state = false; + m_startframe = false; + m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; +@@ -736,30 +730,8 @@ void CMMALVideo::Dispose() + + void CMMALVideo::SetDropState(bool bDrop) + { +- if (m_drop_state != bDrop) +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)", CLASSNAME, __func__, bDrop); +- m_drop_state = bDrop; +- if (m_drop_state) +- { +- while (1) +- { +- CMMALVideoBuffer *buffer = NULL; +- pthread_mutex_lock(&m_output_mutex); +- // fetch a output buffer and pop it off the ready list +- if (!m_output_ready.empty()) +- { +- buffer = m_output_ready.front(); +- m_output_ready.pop(); +- m_droppedPics++; +- } +- pthread_mutex_unlock(&m_output_mutex); +- if (buffer) +- ReleaseBuffer(buffer); +- else +- break; +- } +- } ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "%s::%s - bDrop(%d)", CLASSNAME, __func__, bDrop); + } + + static unsigned count_bits(int32_t value) +@@ -853,10 +825,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts; + buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes; + +- // Request decode only (maintain ref frames, but don't return a picture) +- if (m_drop_state) +- buffer->flags |= MMAL_BUFFER_HEADER_FLAG_DECODEONLY; +- + memcpy(buffer->data, demuxer_content, buffer->length); + demuxer_bytes -= buffer->length; + demuxer_content += buffer->length; +@@ -880,10 +848,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + pthread_mutex_lock(&m_output_mutex); + m_decode_frame_number++; + m_startframe = true; +- if (m_drop_state) +- { +- m_droppedPics += m_deint ? 2:1; +- } + pthread_mutex_unlock(&m_output_mutex); + if (m_changed_count_dec != m_changed_count) + { +@@ -979,16 +943,28 @@ void CMMALVideo::Reset(void) + mmal_port_enable(m_dec_output, dec_output_port_cb_static); + } + // blow all ready video frames +- bool old_drop_state = m_drop_state; +- SetDropState(true); ++ while (1) ++ { ++ CMMALVideoBuffer *buffer = NULL; ++ pthread_mutex_lock(&m_output_mutex); ++ // fetch a output buffer and pop it off the ready list ++ if (!m_output_ready.empty()) ++ { ++ buffer = m_output_ready.front(); ++ m_output_ready.pop(); ++ } ++ pthread_mutex_unlock(&m_output_mutex); ++ if (buffer) ++ ReleaseBuffer(buffer); ++ else ++ break; ++ } ++ + pthread_mutex_lock(&m_output_mutex); + 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); + + if (!m_finished) + SendCodecConfigData(); +@@ -1130,14 +1106,8 @@ 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; ++ droppedPics= -1; ++ return false; + } + + void CMMALVideo::SetCodecControl(int flags) +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index a859467..7161f59 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -110,7 +110,6 @@ class CMMALVideo + bool DestroyDeinterlace(); + + // Video format +- bool m_drop_state; + int m_decoded_width; + int m_decoded_height; + unsigned int m_egl_buffer_count; +@@ -140,7 +139,6 @@ class CMMALVideo + bool m_startframe; + unsigned int m_decode_frame_number; + double m_decoderPts; +- unsigned int m_droppedPics; + int m_speed; + bool m_preroll; + int m_codecControlFlags; + +From e533440ab93a6682c978dbdc6a4fb915f1eb216c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 10 Apr 2015 13:24:41 +0100 +Subject: [PATCH 097/103] [mmalrenderer] squash: logging + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 82a066b..52eb6b3 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -46,9 +46,8 @@ static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer + + void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) + { +- CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; +- + #if defined(MMAL_DEBUG_VERBOSE) ++ CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; + CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p (%p), len %d cmd:%x", CLASSNAME, __func__, port, buffer, omvb, buffer->length, buffer->cmd); + #endif + +@@ -305,7 +304,7 @@ void CMMALRenderer::ReleaseBuffer(int idx) + return; + + #if defined(MMAL_DEBUG_VERBOSE) +- CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, idx); ++ CLog::Log(LOGDEBUG, "%s::%s - %d (%p)", CLASSNAME, __func__, idx, m_buffers[idx].MMALBuffer); + #endif + YUVBUFFER &buf = m_buffers[idx]; + SAFE_RELEASE(buf.MMALBuffer); +@@ -314,7 +313,7 @@ void CMMALRenderer::ReleaseBuffer(int idx) + void CMMALRenderer::ReleaseImage(int source, bool preserve) + { + #if defined(MMAL_DEBUG_VERBOSE) +- CLog::Log(LOGDEBUG, "%s::%s - %d %d", CLASSNAME, __func__, source, preserve); ++ CLog::Log(LOGDEBUG, "%s::%s - %d %d (%p)", CLASSNAME, __func__, source, preserve, m_buffers[idx].MMALBuffer); + #endif + } + + +From af78e68c38ce0b9ae50856f54391eac299895a21 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 Apr 2015 12:47:04 +0100 +Subject: [PATCH 098/103] [players] Make use of new scheme to submit DTS + timestamps + +Latest firmware supports marking timestamps as DTS, +and it will reorder the timestamps with the decoded frame + +This avoids some of the current hacks of supporting PTS and DTS +timestamps in a single field. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 35 +++++----------------- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 -- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 28 ++++++----------- + xbmc/cores/omxplayer/OMXPlayerVideo.h | 1 - + xbmc/cores/omxplayer/OMXVideo.cpp | 25 ++++------------ + xbmc/cores/omxplayer/OMXVideo.h | 2 +- + 6 files changed, 23 insertions(+), 70 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 670e13f..c5746bb 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -58,7 +58,6 @@ CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv) + index = 0; + m_aspect_ratio = 0.0f; + m_changed_count = 0; +- dts = DVD_NOPTS_VALUE; + } + + CMMALVideoBuffer::~CMMALVideoBuffer() +@@ -129,7 +128,6 @@ CMMALVideo::CMMALVideo() + m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; + m_codecControlFlags = 0; +- m_history_valid_pts = 0; + } + + CMMALVideo::~CMMALVideo() +@@ -252,17 +250,15 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + if (buffer->length > 0) + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); +- double dts = DVD_NOPTS_VALUE; + if (1)//(!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + 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); ++ CLASSNAME, __func__, buffer, omvb, buffer->length, buffer->dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); + omvb->mmal_buffer = buffer; + buffer->user_data = (void *)omvb; + omvb->m_changed_count = m_changed_count; +- omvb->dts = dts; + omvb->width = m_decoded_width; + omvb->height = m_decoded_height; + omvb->m_aspect_ratio = m_aspect_ratio; +@@ -275,7 +271,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + else + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - discarding %p dts:%.3f pts:%.3f (len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->flags); ++ CLog::Log(LOGDEBUG, "%s::%s - dropping %p dts:%.3f pts:%.3f (len:%d flags:%x)", CLASSNAME, __func__, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->flags); + } + } + } +@@ -633,7 +629,11 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + +- status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, 1); ++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, 0); ++ if (status != MMAL_SUCCESS) ++ CLog::Log(LOGERROR, "%s::%s Failed to enable timestamp fifo mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); ++ ++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0); + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable timestamp fifo mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + +@@ -704,8 +704,6 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + m_startframe = false; + m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; +- // start from assuming all recent frames had valid pts +- m_history_valid_pts = ~0; + + return true; + } +@@ -734,14 +732,6 @@ void CMMALVideo::SetDropState(bool bDrop) + CLog::Log(LOGDEBUG, "%s::%s - bDrop(%d)", CLASSNAME, __func__, bDrop); + } + +-static unsigned count_bits(int32_t value) +-{ +- unsigned bits = 0; +- for(;value;++bits) +- value &= value - 1; +- return bits; +-} +- + int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + { + //if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -809,14 +799,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); + return VC_ERROR; + } +- +- // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. +- // the valid pts values match the dts values. +- // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts +- m_history_valid_pts = (m_history_valid_pts << 1) | (pts != DVD_NOPTS_VALUE); +- if (count_bits(m_history_valid_pts & 0xffff) < 4) +- pts = dts; +- + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + if (!m_startframe && pts == DVD_NOPTS_VALUE) +@@ -974,7 +956,6 @@ void CMMALVideo::Reset(void) + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + m_codecControlFlags = 0; +- m_history_valid_pts = ~0; + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -1067,7 +1048,7 @@ bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) + } + + // timestamp is in microseconds +- pDvdVideoPicture->dts = buffer->dts; ++ pDvdVideoPicture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->dts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts; + pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->pts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts; + + pDvdVideoPicture->MMALBuffer->Acquire(); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index 7161f59..52290b6 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -56,7 +56,6 @@ class CMMALVideoBuffer + int height; + float m_aspect_ratio; + int index; +- double dts; + uint32_t m_changed_count; + // reference counting + CMMALVideoBuffer* Acquire(); +@@ -142,7 +141,6 @@ class CMMALVideo + int m_speed; + bool m_preroll; + int m_codecControlFlags; +- uint32_t m_history_valid_pts; + + MMAL_COMPONENT_T *m_dec; + MMAL_PORT_T *m_dec_input; +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 018e65f..4315993 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -106,7 +106,6 @@ OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock, + m_iCurrentPts = DVD_NOPTS_VALUE; + m_nextOverlay = DVD_NOPTS_VALUE; + m_flush = false; +- m_history_valid_pts = 0; + } + + OMXPlayerVideo::~OMXPlayerVideo() +@@ -314,14 +313,6 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket) + g_renderManager.FlipPage(CThread::m_bStop, time/DVD_TIME_BASE); + } + +-static unsigned count_bits(int32_t value) +-{ +- unsigned bits = 0; +- for(;value;++bits) +- value &= value - 1; +- return bits; +-} +- + void OMXPlayerVideo::Process() + { + double frametime = (double)DVD_TIME_BASE / m_fFrameRate; +@@ -496,18 +487,20 @@ void OMXPlayerVideo::Process() + m_stalled = false; + } + +- // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. +- // the valid pts values match the dts values. +- // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts +- m_history_valid_pts = (m_history_valid_pts << 1) | (pPacket->pts != DVD_NOPTS_VALUE); ++ double dts = pPacket->dts; + double pts = pPacket->pts; +- if(count_bits(m_history_valid_pts & 0xffff) < 4) +- pts = pPacket->dts; ++ ++ if (dts != DVD_NOPTS_VALUE) ++ dts += m_iVideoDelay; + + if (pts != DVD_NOPTS_VALUE) + pts += m_iVideoDelay; + +- m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pts); ++ m_omxVideo.Decode(pPacket->pData, pPacket->iSize, dts, pts); ++ ++ if (pts == DVD_NOPTS_VALUE) ++ pts = dts; ++ + Output(pts, bRequestDrop); + if(pts != DVD_NOPTS_VALUE) + m_iCurrentPts = pts; +@@ -583,9 +576,6 @@ bool OMXPlayerVideo::OpenDecoder() + m_codecname = m_omxVideo.GetDecoderName(); + } + +- // start from assuming all recent frames had valid pts +- m_history_valid_pts = ~0; +- + return bVideoDecoderOpen; + } + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h +index 2748a41..3bd5625 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.h ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h +@@ -69,7 +69,6 @@ class OMXPlayerVideo : public CThread, public IDVDStreamPlayerVideo + RENDER_STEREO_MODE m_video_stereo_mode; + RENDER_STEREO_MODE m_display_stereo_mode; + bool m_StereoInvert; +- uint32_t m_history_valid_pts; + DllBcmHost m_DllBcmHost; + + CDVDOverlayContainer *m_pOverlayContainer; +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 3f37d44..832a9c9 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -602,23 +602,6 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + return false; + } + +- // broadcom omx entension: +- // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. +- // In this mode the incoming timestamps get used without re-ordering on output images. +- // recent firmware will actually automatically choose the timestamp stream with the least variance, so always enable +- { +- OMX_CONFIG_BOOLEANTYPE timeStampMode; +- OMX_INIT_STRUCTURE(timeStampMode); +- timeStampMode.bEnabled = OMX_TRUE; +- +- omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); +- if (omx_err != OMX_ErrorNone) +- { +- CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err); +- return false; +- } +- } +- + if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) + { + OMX_NALSTREAMFORMATTYPE nalStreamFormat; +@@ -758,7 +741,7 @@ bool COMXVideo::GetPlayerInfo(double &match, double &phase, double &pll) + } + + +-int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) ++int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts) + { + CSingleLock lock (m_critSection); + OMX_ERRORTYPE omx_err; +@@ -783,6 +766,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + + omx_buffer->nFlags = 0; + omx_buffer->nOffset = 0; ++ omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts != DVD_NOPTS_VALUE ? pts : dts != DVD_NOPTS_VALUE ? dts : 0)); + + if(m_setStartTime) + { +@@ -790,10 +774,11 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE); + m_setStartTime = false; + } +- if(pts == DVD_NOPTS_VALUE) ++ else if (pts == DVD_NOPTS_VALUE && dts == DVD_NOPTS_VALUE) + omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; ++ else if (pts == DVD_NOPTS_VALUE) ++ omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_IS_DTS; + +- omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); + omx_buffer->nFilledLen = std::min((OMX_U32)demuxer_bytes, omx_buffer->nAllocLen); + memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); + +diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h +index 3ea02dc..86e94ce 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.h ++++ b/xbmc/cores/omxplayer/OMXVideo.h +@@ -55,7 +55,7 @@ class COMXVideo + void Close(void); + unsigned int GetFreeSpace(); + unsigned int GetSize(); +- int Decode(uint8_t *pData, int iSize, double pts); ++ int Decode(uint8_t *pData, int iSize, double dts, double pts); + void Reset(void); + void SetDropState(bool bDrop); + std::string GetDecoderName() { return m_video_codec_name; }; + +From 7bf14e5742366171b81f30d6ef6f93017903ccdc Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Mon, 13 Apr 2015 18:18:00 +0200 +Subject: [PATCH 099/103] dvdplayer audio: do not consider dropped packets for + sync error + +--- + xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +index 416e6f8..58761e9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +@@ -557,7 +557,7 @@ void CDVDPlayerAudio::Process() + if( audioframe.nb_frames == 0 ) + continue; + +- packetadded = true; ++ packetadded = false; + + // we have succesfully decoded an audio frame, setup renderer to match + if (!m_dvdAudio.IsValidFormat(audioframe)) +@@ -607,7 +607,7 @@ void CDVDPlayerAudio::Process() + } + + // signal to our parent that we have initialized +- if(m_started == false && packetadded) ++ if(m_started == false) + { + m_started = true; + m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_AUDIO)); + +From 5b007c4c0b681703f5a0e4eb170f68be7797cf41 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Mon, 13 Apr 2015 18:18:59 +0200 +Subject: [PATCH 100/103] dvdplayer audio: fix/improve calculation of playing + pts + +--- + xbmc/cores/dvdplayer/DVDAudio.cpp | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDAudio.cpp b/xbmc/cores/dvdplayer/DVDAudio.cpp +index a2b1325..d1601b1 100644 +--- a/xbmc/cores/dvdplayer/DVDAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDAudio.cpp +@@ -276,5 +276,17 @@ double CDVDAudio::GetPlayingPts() + if (m_playingPts == DVD_NOPTS_VALUE) + return 0.0; + +- return m_playingPts + CDVDClock::GetAbsoluteClock() - m_timeOfPts; ++ double now = CDVDClock::GetAbsoluteClock(); ++ double diff = now - m_timeOfPts; ++ double cache = GetCacheTime(); ++ double played = 0.0; ++ ++ if (diff < cache) ++ played = diff; ++ else ++ played = cache; ++ ++ m_timeOfPts = now; ++ m_playingPts += played; ++ return m_playingPts; + } + +From 19e1a724d89949b78e2153840ce5b9d15d9f4cd6 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Mon, 13 Apr 2015 17:11:47 +0200 +Subject: [PATCH 101/103] Application: Don't slow down videos rendered on + GuiLayer + +--- + xbmc/Application.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 6e0aeff..059b7de 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2485,7 +2485,7 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) + #if defined(TARGET_RASPBERRY_PI) || defined(HAS_IMXVPU) + // This code reduces rendering fps of the GUI layer when playing videos in fullscreen mode + // it makes only sense on architectures with multiple layers +- if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ if (g_renderManager.IsVideoLayer() && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) + fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); + #endif + + +From 299175629df95667144a23b8fa7530775a9d6afd Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 10 Apr 2015 13:23:11 +0100 +Subject: [PATCH 102/103] [mmalrenderer] Avoid blank frame on resolution change + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 52eb6b3..5164ffb 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -178,6 +178,7 @@ void CMMALRenderer::AddProcessor(CMMALVideoBuffer *buffer, int index) + + bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) + { ++ bool formatChanged = m_format != format; + ReleaseBuffers(); + + m_sourceWidth = width; +@@ -230,9 +231,10 @@ bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned + else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) + es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; + } +- if (m_bConfigured) ++ if (m_bConfigured && formatChanged) + UnInitMMAL(); +- m_bConfigured = init_vout(es_format); ++ if (!m_bConfigured) ++ m_bConfigured = init_vout(es_format); + mmal_format_free(es_format); + } + else + +From 62360236fc8ad14ce64a50ce4e91567d7cb14dbf Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 Apr 2015 17:04:55 +0100 +Subject: [PATCH 103/103] [mmalcodec] Discard corrupt frames later so we can + still count dropped frames + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index c5746bb..5ac12dd 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -250,7 +250,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + if (buffer->length > 0) + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); +- if (1)//(!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) ++ if (!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -620,7 +620,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)); 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..05de2d0d20 --- /dev/null +++ b/projects/RPi2/patches/kodi/kodi-001-isengard-rpb-backports.patch @@ -0,0 +1,9725 @@ +From 9d98beccd9d65e5a86b488f0ceb90448f2c9a5f3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 18:19:32 +0100 +Subject: [PATCH 001/103] [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 274fcbff2f4a4c64f92a0d4cf1cdfed8f3045259 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 29 Apr 2014 15:23:22 +0100 +Subject: [PATCH 002/103] [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 681ca292791c12e51b745db0629376902377367b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 2 Aug 2014 17:48:04 +0100 +Subject: [PATCH 003/103] [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 3e320b31a6b000fbcd212e8b7138c88e2b77dfaa Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 8 Mar 2014 15:36:06 +0000 +Subject: [PATCH 004/103] [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 6828241cd39ce51a64ef4e25394620d034afd10f Mon Sep 17 00:00:00 2001 +From: Ben Avison +Date: Thu, 1 May 2014 16:28:39 +0100 +Subject: [PATCH 005/103] 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 cdd2b2e9dacd31ab126e635aee2061bc8dc1e920 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 12 Aug 2014 00:31:36 +0100 +Subject: [PATCH 006/103] [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 143ea06..e029c16 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3345,7 +3345,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 bb8c24c64263afa825341429bd22a49a774c96b8 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 10 Aug 2014 16:45:16 +0100 +Subject: [PATCH 007/103] 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 e7244d1..a762609 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 323a2f1..f008579 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 14b7c230cf053a22a015126b6bce83bc8ad7cf5c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 13:06:57 +0000 +Subject: [PATCH 009/103] [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 910468040e6fe46799e99ecdd4ae3223c37b2b50 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 30 May 2014 14:58:43 +0100 +Subject: [PATCH 011/103] [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 7285aff9a873a23fd65867428cb0007b9ea07948 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 9 Sep 2014 12:04:26 +0100 +Subject: [PATCH 012/103] 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 897c19a7803148ca067b9e5cea4e43e320c4fd67 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 18 Sep 2014 14:24:56 +0100 +Subject: [PATCH 013/103] [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 503f7e7fb4a0e74ff3092c7ff461620634f01d09 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 19 Sep 2014 11:54:49 +0100 +Subject: [PATCH 014/103] [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 a762609..8cd2b39 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" +@@ -16565,3 +16580,10 @@ msgstr "" + msgctxt "#38016" + msgid "%d 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 f008579..8395973 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 74df969..416e6f8 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) + { +@@ -484,7 +489,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"; + +@@ -638,8 +647,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; + } +@@ -749,7 +758,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; + } + + bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) +@@ -802,6 +823,7 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) + { + m_dvdAudio.AddPackets(audioframe); + } ++ m_plladjust = 1.0; + } + else if (m_synctype == SYNC_DISCON) + { +@@ -836,6 +858,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 99ce952..635c184 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h +@@ -232,6 +232,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 3f55c9edc572baeb0c43fdd4e60a030ce1a6ea9e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 27 Sep 2014 15:32:37 +0100 +Subject: [PATCH 015/103] [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 e029c16..63f4a30 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -3330,7 +3330,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 3d434543097974c95cc25dc07f9ece37ba2e6bc1 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 24 Sep 2014 23:13:52 +0100 +Subject: [PATCH 016/103] [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 8cd2b39..fa7c455 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16587,3 +16587,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 8395973..29a9ef6 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 ccd32242f5696ac4e639cb2c686c277b876112f5 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:40:06 +0100 +Subject: [PATCH 017/103] [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 d54c0004c7889382e48a3b2015d7e6920fdae119 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 27 Oct 2014 15:23:51 +0000 +Subject: [PATCH 018/103] [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 cb83297..8496abf 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -38,6 +38,16 @@ + + + ++ ++ ++ ++ false ++ ++ ++ false ++ ++ ++ +
+ +
+ +From 49ef564d2e2c4f15a81fb727ed4abb03f299a66e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 15 Nov 2014 12:03:34 +0000 +Subject: [PATCH 022/103] [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 63f4a30..3c313cd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -529,6 +529,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)) + { +@@ -558,6 +559,7 @@ void CDVDPlayer::CreatePlayers() + + void CDVDPlayer::DestroyPlayers() + { ++ CSingleLock lock(m_players_lock); + if (!m_players_created) + return; + delete m_dvdPlayerVideo; +@@ -4190,6 +4192,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 468239c..3b8cefb 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -558,4 +558,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 d2e6086e65aa2bb6fee41c413db5cac0e31b2c0e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 24 Nov 2014 22:07:25 +0000 +Subject: [PATCH 023/103] [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 4f95fb3b9cacf2e968291b0bc448df6ce684928b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 27 Nov 2014 16:31:56 +0000 +Subject: [PATCH 024/103] [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 4ac74fa770ca65859284e1541d1b8ef5ed658d30 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Dec 2013 16:55:05 +0000 +Subject: [PATCH 025/103] 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 602c2edc4b65379dd6872e245ced5f240505f932 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:24:42 +0200 +Subject: [PATCH 026/103] 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 cac8aa5c89dbfe566b0d410bb4b66012b0ffaa2c Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 18:29:03 +0200 +Subject: [PATCH 027/103] 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 3861ee5d79e6daa334b19247ace9753027fad450 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:50:58 +0200 +Subject: [PATCH 028/103] 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 bfe83fe7109a35fc5b323cd71fededa78375cc8f Mon Sep 17 00:00:00 2001 +From: macrule +Date: Thu, 11 Apr 2013 19:54:59 +0200 +Subject: [PATCH 029/103] 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 b3fc8a5fc3e58091b95aa0f2ca9f78353ce27c9e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Aug 2013 15:03:36 +0100 +Subject: [PATCH 030/103] 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 51fdf84..e00916a 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 c6f62d8db0..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 bdd759a61f9ff2da25014aa45da9997fd51bd7a6 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:23:01 +0200 +Subject: [PATCH 031/103] 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 33be5d47278da30a21fda820324af9a3423fb2e8 Mon Sep 17 00:00:00 2001 +From: macrule +Date: Wed, 17 Apr 2013 13:24:22 +0200 +Subject: [PATCH 032/103] 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 709dfc42ba253ec392a266efa986b3da0f2020b2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:16:29 +0000 +Subject: [PATCH 033/103] [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 d3f8b6d306df8585bf4109b29bcab90c8a938ab4 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 16:47:54 +0000 +Subject: [PATCH 034/103] [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 27bc221d7dd08c12f07a7c3b7ddef78e19798777 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Mar 2014 17:30:07 +0000 +Subject: [PATCH 035/103] [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 8609e7646814b273206d83b4fb973eab4ce768fe Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 4 Mar 2014 19:33:44 +0000 +Subject: [PATCH 036/103] [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 c8eceb5866e755200441f9301d96d6cf99760b77 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 26 Apr 2014 17:27:52 +0100 +Subject: [PATCH 037/103] [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 15b45e982c686259159223839618d0422c789f92 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Jun 2014 00:01:05 +0100 +Subject: [PATCH 038/103] [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 20f0bf8ef85a8c11b6fe4b6318ee925b753a9097 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 11 Apr 2014 16:12:27 +0100 +Subject: [PATCH 039/103] [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 22a1696..5fc9d65 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 61c67e0ee0a882807b80a4ad85c5c9a476fc58b0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 040/103] [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 5fc9d65..caf6ee6 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 3d935ad808f8f753468091b5f7461d0cc4b781a6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 18 Aug 2014 19:09:32 +0100 +Subject: [PATCH 041/103] 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 648a6b3b7564b05e77b0039560755225c02852c4 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 3 Nov 2014 17:16:54 +0000 +Subject: [PATCH 042/103] 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 caf6ee6..5fc9d65 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 14bfe644ca9aba1a482bf631ca0fa714d4502b61 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 043/103] [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 5fc9d65..caf6ee6 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 3c313cd..8ceb498 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); +@@ -974,6 +1029,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) +@@ -3475,6 +3536,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 718edc6ac5a59f2473592bd4646f54f904807a6f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 29 Nov 2014 15:25:16 +0000 +Subject: [PATCH 044/103] [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 0b3bfb6bac019ffbd0af4689fbdd3e785cc44957 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 5 Oct 2014 14:05:25 +0100 +Subject: [PATCH 045/103] [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 caf6ee6..7b1089d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16631,3 +16631,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 8496abf..5068b20 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -89,6 +89,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 15eeb598e03a492404dfb754a0eb5e07342f990e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 11 Dec 2014 17:00:57 +0000 +Subject: [PATCH 046/103] 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 7b1089d..e8d5f7c 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 +@@ -16646,3 +16646,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 5068b20..6e9ceaf 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -36,10 +36,6 @@ + + false + +- +- +- +- + + false + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 29a9ef6..bdba486 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 b2a98eb56639907c3305775d0fcaee9f6bc0f03e Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Thu, 11 Sep 2014 21:30:43 +0200 +Subject: [PATCH 047/103] 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 e00916a..6e0aeff 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -4948,3 +4948,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 b4da8f2..cc064c3 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 7b7f2ac4ef55297e4328736678a5ed436f83a830 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 13 Dec 2014 18:35:20 +0000 +Subject: [PATCH 048/103] [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 6b4af4de9aaa4c125272e087680652db3b924ec1 Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:27:59 +0100 +Subject: [PATCH 049/103] - 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 e8d5f7c..8858c95 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 bdba486..67472f6 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -465,6 +465,11 @@ + false + + ++ ++ 1 ++ true ++ ++ + + + + +From 8eb308d186e18f8c8d23c1d77fa28fd11fa0238f Mon Sep 17 00:00:00 2001 +From: Memphiz +Date: Tue, 18 Nov 2014 13:28:36 +0100 +Subject: [PATCH 050/103] - 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 a703de3..1212e09 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 6626ed33fcd8daa13811c72bbdd1fe455dd19366 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 11 Jan 2015 21:48:31 +0000 +Subject: [PATCH 051/103] [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 1664527d983c1a063d7145e90749af5b0d212990 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 24 Jan 2015 17:34:04 +0000 +Subject: [PATCH 052/103] 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 e4f51eb17146ed9b71c99968cc8a539894c02b97 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Wed, 4 Feb 2015 22:32:03 +0100 +Subject: [PATCH 053/103] 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 1bf1cc0f8335f67ab3ddff9aac3bfe86d57b6138 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Feb 2015 00:19:51 +0000 +Subject: [PATCH 056/103] [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 4b88d98c3ba80b522d1a34cfebe6e9a629113cee Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 14:06:12 +0000 +Subject: [PATCH 057/103] [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 17f7f8502ce5429461202b3f4b609d9478577485 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 15 Feb 2015 15:29:51 +0000 +Subject: [PATCH 058/103] [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 | 106 +++++++++++++++++++++++++++++++++++++++++++++ + xbmc/linux/RBP.h | 2 + + xbmc/settings/Settings.cpp | 7 ++- + 3 files changed, 114 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..ffdcb36 +--- /dev/null ++++ b/system/settings/rbp2.xml +@@ -0,0 +1,106 @@ ++ ++ ++
++ ++ ++ false ++ ++ ++ ++ false ++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ ++ ++ ++ 2 ++ 10 ++ ++ 0 ++ 5 ++ 25 ++ ++ ++ 38016 ++ ++ ++ ++ ++ ++ ++ ++ ++ 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 139817f..ab9c6fd 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 750290b96315c47a5cf1dbc2f4696481d9be8750 Mon Sep 17 00:00:00 2001 +From: Claudio-Sjo +Date: Mon, 16 Feb 2015 14:51:26 +0100 +Subject: [PATCH 059/103] - 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 af144ae9182175bd150cfd6c5920d019f7608d34 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 20 Feb 2015 14:11:57 +0000 +Subject: [PATCH 060/103] 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 d51cbcb8bab40754cf93919b1c5604944781375e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 00:09:19 +0000 +Subject: [PATCH 061/103] [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 a7fd3cef4b00d619163cf633077536887fc0f36d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Feb 2015 15:57:29 +0000 +Subject: [PATCH 062/103] [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 25817c925fec4954e78a2e852b7ca1c0ef50ba6c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 14:37:27 +0000 +Subject: [PATCH 063/103] 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 2780425800930e12a685727f6ea67d47bace6b41 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 27 Feb 2015 19:07:17 +0000 +Subject: [PATCH 064/103] [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 59faf7fd1d9849cd8f6524a14d86b02b065ebdd3 Mon Sep 17 00:00:00 2001 +From: anaconda +Date: Wed, 25 Feb 2015 18:22:21 +0100 +Subject: [PATCH 065/103] 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 5e091eb..35b417f 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 6c14cd5..7e960ad 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 50d352d6656308960ad3e651f78688aec8237423 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 5 Mar 2015 20:00:59 +0000 +Subject: [PATCH 066/103] [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 e0feb4ed215e9fbe93c44eceb45214027f3c87c0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 7 Mar 2015 22:46:21 +0000 +Subject: [PATCH 067/103] 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 ae0626f..85d0c72 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], +@@ -300,34 +301,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 da6be7609a0ce66cc87d86b308e0561b04835875 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 16 Apr 2014 21:18:06 +0100 +Subject: [PATCH 068/103] [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 595f15cd5e389f7d3c37b06d5cdddb878560a303 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:01:51 +0100 +Subject: [PATCH 069/103] [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 241c252fd08754d237c78288b6aaed2595c86dda Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 17 Apr 2014 13:38:55 +0100 +Subject: [PATCH 070/103] [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 4345c0f..cc5dc60 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 a813ff2c01902d9e5c7f59ae43b08c3c63a7c3db Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 23 Apr 2014 00:05:07 +0100 +Subject: [PATCH 071/103] [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 cc5dc60..0c23290 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 8e2a045b4f3746e523f40d22db434801c72d9adf Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 10 Mar 2015 17:05:18 +0000 +Subject: [PATCH 072/103] [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 8858c95..82bb99d 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16659,6 +16659,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 6e9ceaf..ed61ca6 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -30,6 +30,16 @@ + +
+
++ ++ ++ ++ 1 ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index ffdcb36..e909cc4 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -33,6 +33,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 18240f9b0072c6ea1e8707824ab8ff4b3e75aa5b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 14 Mar 2015 12:38:08 +0000 +Subject: [PATCH 073/103] [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 82bb99d..d0d77c5 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -16669,6 +16669,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 ed61ca6..42d4da7 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -39,6 +39,14 @@ + true + +
++ ++ ++ true ++ ++ 2 ++ true ++ ++ + + + +diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml +index e909cc4..dff4da8 100644 +--- a/system/settings/rbp2.xml ++++ b/system/settings/rbp2.xml +@@ -42,6 +42,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 a45bafbf944a6a91f9b2d778714877bd7cb89b0f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 17 Mar 2015 20:33:54 +0000 +Subject: [PATCH 074/103] 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 fc62ae2cfaac76e0fc667ce298befbf240d7981b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 21 Mar 2015 21:46:16 +0000 +Subject: [PATCH 075/103] 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 6881d9550814c63db3c9eeea719c73a34f3ccd0e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 22 Mar 2015 19:32:36 +0000 +Subject: [PATCH 076/103] [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 cd89da5ff195c665573488bc23d5064590b5dfb6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 23 Mar 2015 23:50:50 +0000 +Subject: [PATCH 079/103] [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 ca7ac79e3ae84f9004d6ad1ff97f284d5792963e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 24 Mar 2015 17:24:27 +0000 +Subject: [PATCH 080/103] [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 93285a243328c5d05e7437715e90c4fb4ed701b2 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:36:48 +0100 +Subject: [PATCH 081/103] [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 e0aa63a4be636c5f6bee31df646170d616836c72 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 00:37:25 +0100 +Subject: [PATCH 082/103] [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 6b974ed76e12bd270969ad6f8bf3ec43f2193d34 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 01:25:04 +0100 +Subject: [PATCH 083/103] [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 f3983e34dde74a7cb8b0f0c8b3bd8c573ec66b3d Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:34:00 +0100 +Subject: [PATCH 084/103] [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 26a386aac6449208c791dbf0de920aca4c46a4ce Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 31 Mar 2015 17:31:47 +0100 +Subject: [PATCH 085/103] [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 74cc992c8216da6e5a39fe5f470005c9d1accdbb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 16:31:37 +0100 +Subject: [PATCH 086/103] [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 66bb7019bb917be310d6a2bd21fb206302d8ee1a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Apr 2015 18:35:01 +0100 +Subject: [PATCH 087/103] [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 91009891251f052d8a1dc74deac32990cd8deb65 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 15:40:22 +0100 +Subject: [PATCH 088/103] [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..a842ddd 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 0e0ac43fad3b3ec91c7fb11ac482e7e0b655d213 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 6 Apr 2015 19:08:20 +0100 +Subject: [PATCH 089/103] Revert "[mmalrenderer] Discard corrupt frames later + so we can track the number of discarded frames" + +This reverts commit e3f57826eff42a3f1843dffd978ac98bda372826. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index a842ddd..2e23430 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -274,11 +274,6 @@ 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); +@@ -648,7 +643,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 = false; ++ error_concealment.enable = g_advancedSettings.m_omxDecodeStartWithValidFrame; + 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 3c322da17a4b5e38cd9e683db4353badca1dab42 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 2 Apr 2015 00:25:26 +0100 +Subject: [PATCH 090/103] [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 2e23430..180b96f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -382,13 +382,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); + +From 0248c175316462dfe5bf4721b062db88f109c561 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 3 Apr 2015 10:49:55 +0200 +Subject: [PATCH 091/103] dvdplayer: cosmetics + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 41 ++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 19 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 8ceb498..1f220c6 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1454,16 +1454,18 @@ void CDVDPlayer::Process() + + m_OmxPlayerState.bOmxSentEOFs = true; + } ++ + if(m_CurrentAudio.inited) +- m_dvdPlayerAudio->SendMessage (new CDVDMsg(CDVDMsg::GENERAL_EOF)); ++ m_dvdPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); + if(m_CurrentVideo.inited) +- m_dvdPlayerVideo->SendMessage (new CDVDMsg(CDVDMsg::GENERAL_EOF)); ++ m_dvdPlayerVideo->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); + if(m_CurrentSubtitle.inited) + m_dvdPlayerSubtitle->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); + if(m_CurrentTeletext.inited) + m_dvdPlayerTeletext->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF)); +- m_CurrentAudio.inited = false; +- m_CurrentVideo.inited = false; ++ ++ m_CurrentAudio.inited = false; ++ m_CurrentVideo.inited = false; + m_CurrentSubtitle.inited = false; + m_CurrentTeletext.inited = false; + +@@ -1573,21 +1575,22 @@ bool CDVDPlayer::CheckIsCurrent(CCurrentStream& current, CDemuxStream* stream, D + + void CDVDPlayer::ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket) + { +- /* process packet if it belongs to selected stream. for dvd's don't allow automatic opening of streams*/ +- +- if (CheckIsCurrent(m_CurrentAudio, pStream, pPacket)) +- ProcessAudioData(pStream, pPacket); +- else if (CheckIsCurrent(m_CurrentVideo, pStream, pPacket)) +- ProcessVideoData(pStream, pPacket); +- else if (CheckIsCurrent(m_CurrentSubtitle, pStream, pPacket)) +- ProcessSubData(pStream, pPacket); +- else if (CheckIsCurrent(m_CurrentTeletext, pStream, pPacket)) +- ProcessTeletextData(pStream, pPacket); +- else +- { +- pStream->SetDiscard(AVDISCARD_ALL); +- CDVDDemuxUtils::FreeDemuxPacket(pPacket); // free it since we won't do anything with it +- } ++ // process packet if it belongs to selected stream. ++ // for dvd's don't allow automatic opening of streams*/ ++ ++ if (CheckIsCurrent(m_CurrentAudio, pStream, pPacket)) ++ ProcessAudioData(pStream, pPacket); ++ else if (CheckIsCurrent(m_CurrentVideo, pStream, pPacket)) ++ ProcessVideoData(pStream, pPacket); ++ else if (CheckIsCurrent(m_CurrentSubtitle, pStream, pPacket)) ++ ProcessSubData(pStream, pPacket); ++ else if (CheckIsCurrent(m_CurrentTeletext, pStream, pPacket)) ++ ProcessTeletextData(pStream, pPacket); ++ else ++ { ++ pStream->SetDiscard(AVDISCARD_ALL); ++ CDVDDemuxUtils::FreeDemuxPacket(pPacket); // free it since we won't do anything with it ++ } + } + + void CDVDPlayer::CheckStreamChanges(CCurrentStream& current, CDemuxStream* stream) + +From c1a1141d6ed1699fc2ab1bae805786a58d38786f Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 6 Apr 2015 19:06:26 +0100 +Subject: [PATCH 092/103] [mmalcodec] Remove the decoder queue and use gpu + timestamps + +There are too many streams that don't have a 1:1 mapping of encoded video frames to decoded pictures. +If that isn't true, the dts queues gets out of sync with the real frames. + +Interlaces streams and streams with errors cause issues. + +Instead remove the dts queue and use the gpu's timestamps. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 91 +++++++++++----------- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 +- + 2 files changed, 46 insertions(+), 47 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 180b96f..e5ea365 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -131,6 +131,7 @@ CMMALVideo::CMMALVideo() + m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; + m_codecControlFlags = 0; ++ m_history_valid_pts = 0; + } + + CMMALVideo::~CMMALVideo() +@@ -254,27 +255,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); + double dts = DVD_NOPTS_VALUE; +- if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER0) +- { +- pthread_mutex_lock(&m_output_mutex); +- if (!m_dts_queue.empty()) +- { +- dts = m_dts_queue.front(); +- m_dts_queue.pop(); +- } +- else assert(0); +- pthread_mutex_unlock(&m_output_mutex); +- } +- +- 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); +- } +- else ++ if (!m_drop_state) // && !(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -293,6 +274,14 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + pthread_mutex_unlock(&m_output_mutex); + kept = true; + } ++ else ++ { ++ 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 dts:%.3f pts:%.3f (drop:%d len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, m_drop_state, buffer->length, buffer->flags); ++ } + } + } + else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) +@@ -649,6 +638,10 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + ++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, 1); ++ if (status != MMAL_SUCCESS) ++ CLog::Log(LOGERROR, "%s::%s Failed to enable timestamp fifo mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); ++ + status = mmal_port_format_commit(m_dec_input); + if (status != MMAL_SUCCESS) + { +@@ -717,6 +710,8 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + m_startframe = false; + m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; ++ // start from assuming all recent frames had valid pts ++ m_history_valid_pts = ~0; + + return true; + } +@@ -732,10 +727,9 @@ void CMMALVideo::Dispose() + done = true; + pthread_mutex_unlock(&m_output_mutex); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done); ++ CLog::Log(LOGDEBUG, "%s::%s ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_output_ready.size(), m_output_busy, done); + if (done) + { +- assert(m_dts_queue.empty()); + m_myself.reset(); + } + } +@@ -768,11 +762,19 @@ void CMMALVideo::SetDropState(bool bDrop) + } + } + ++static unsigned count_bits(int32_t value) ++{ ++ unsigned bits = 0; ++ for(;value;++bits) ++ value &= value - 1; ++ return bits; ++} ++ + int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + { + //if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- // CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f dts_queue(%d) ready_queue(%d) busy_queue(%d)", +- // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ // CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f ready_queue(%d) busy_queue(%d)", ++ // CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_output_ready.size(), m_output_busy); + + unsigned int demuxer_bytes = 0; + uint8_t *demuxer_content = NULL; +@@ -836,6 +838,13 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + return VC_ERROR; + } + ++ // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. ++ // the valid pts values match the dts values. ++ // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts ++ m_history_valid_pts = (m_history_valid_pts << 1) | (pts != DVD_NOPTS_VALUE); ++ if (count_bits(m_history_valid_pts & 0xffff) < 4) ++ pts = dts; ++ + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + if (m_startframe && pts == DVD_NOPTS_VALUE) +@@ -843,9 +852,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->pts = pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pts; + buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts; + buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes; +- buffer->user_data = (void *)m_decode_frame_number; +- // set a flag so we can identify primary frames from generated frames (deinterlace) +- buffer->flags = MMAL_BUFFER_HEADER_FLAG_USER0; + + // Request decode only (maintain ref frames, but don't return a picture) + if (m_drop_state) +@@ -859,8 +865,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)", +- CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); ++ CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)", ++ CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size); + assert((int)buffer->length > 0); + status = mmal_port_send_buffer(m_dec_input, buffer); + if (status != MMAL_SUCCESS) +@@ -878,12 +884,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + { + m_droppedPics += m_deint ? 2:1; + } +- else +- { +- // only push if we are successful with feeding mmal +- m_dts_queue.push(dts); +- assert(m_dts_queue.size() < 5000); +- } + pthread_mutex_unlock(&m_output_mutex); + if (m_changed_count_dec != m_changed_count) + { +@@ -926,11 +926,11 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + break; + } + int ret = 0; +- 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) ++ double queued = m_decoderPts != DVD_NOPTS_VALUE && pts != DVD_NOPTS_VALUE ? pts - m_decoderPts : 0.0; ++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length && queued <= DVD_MSEC_TO_TIME(500)) + { + 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); ++ CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d) queued(%.2f)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, queued*1e-6); + ret |= VC_BUFFER; + } + else +@@ -951,8 +951,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + if (!ret) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)", +- CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll); ++ CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)", ++ CLASSNAME, __func__, m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll); + Sleep(10); // otherwise we busy spin + } + return ret; +@@ -982,8 +982,6 @@ void CMMALVideo::Reset(void) + bool old_drop_state = m_drop_state; + SetDropState(true); + pthread_mutex_lock(&m_output_mutex); +- while(!m_dts_queue.empty()) +- m_dts_queue.pop(); + while (!m_demux_queue.empty()) + m_demux_queue.pop(); + m_demux_queue_length = 0; +@@ -1000,6 +998,7 @@ void CMMALVideo::Reset(void) + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + m_codecControlFlags = 0; ++ m_history_valid_pts = ~0; + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -1028,8 +1027,8 @@ void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p dts_queue(%d) ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output, +- m_dts_queue.size(), m_output_ready.size(), m_output_busy); ++ CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output, ++ m_output_ready.size(), m_output_busy); + status = mmal_port_send_buffer(m_dec_output, buffer); + if (status != MMAL_SUCCESS) + { +@@ -1054,7 +1053,7 @@ void CMMALVideo::ReleaseBuffer(CMMALVideoBuffer *buffer) + if (done) + m_myself.reset(); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s %p (%p) dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done); ++ CLog::Log(LOGDEBUG, "%s::%s %p (%p) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_output_ready.size(), m_output_busy, done); + delete buffer; + } + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index ec44b13..a859467 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -119,7 +119,6 @@ class CMMALVideo + const char *m_pFormatName; + MMALVideoPtr m_myself; + +- std::queue m_dts_queue; + std::queue m_demux_queue; + unsigned m_demux_queue_length; + +@@ -145,6 +144,7 @@ class CMMALVideo + int m_speed; + bool m_preroll; + int m_codecControlFlags; ++ uint32_t m_history_valid_pts; + + MMAL_COMPONENT_T *m_dec; + MMAL_PORT_T *m_dec_input; + +From b4f0f4e150544d573bd61baa8842ecd10212a526 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 7 Apr 2015 19:50:15 +0100 +Subject: [PATCH 093/103] [mmalrenderer] Fix for inverted check for first frame + +--- + 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 e5ea365..7c53347 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -847,7 +847,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; +- if (m_startframe && pts == DVD_NOPTS_VALUE) ++ if (!m_startframe && pts == DVD_NOPTS_VALUE) + pts = 0; + buffer->pts = pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pts; + buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts; + +From 8f998d7464019a7aa254b08f338ba73a0f8e4c03 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 Apr 2015 22:52:03 +0100 +Subject: [PATCH 094/103] Revert "[omxplayer] Only enable audio clock master + when A/V sync method is set to audio clock" + +This reverts commit 56491e6e9f01744f4c43abe7a7ddc1f5a5b179c3. +--- + xbmc/cores/omxplayer/OMXAudio.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index 9d960aa..9bb967a 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -248,8 +248,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) || +- m_output == AESINKPI_BOTH) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || m_output == AESINKPI_BOTH) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); +@@ -275,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") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) ++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock")) + { + OMX_CONFIG_BOOLEANTYPE configBool; + OMX_INIT_STRUCTURE(configBool); + +From a71bb2cbab462337944da1c6499b5c0c8973bff3 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 9 Apr 2015 17:12:56 +0100 +Subject: [PATCH 095/103] squash: add timeout to vc_dispmanx_vsync_callback + +--- + xbmc/linux/RBP.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp +index fe1df00..8bf0f14 100644 +--- a/xbmc/linux/RBP.cpp ++++ b/xbmc/linux/RBP.cpp +@@ -196,7 +196,7 @@ void CRBP::WaitVsync() + s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); + if (s == 0) + { +- m_vsync.Wait(); ++ m_vsync.WaitMSec(1000); + } + else assert(0); + s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); + +From 3da7de0426191fae9e88ff8b39fd4c850d7b00df Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 9 Apr 2015 18:18:09 +0100 +Subject: [PATCH 096/103] [mmalrenderer] Remove dropping logic. It only seems + to make things worse + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 76 +++++++--------------- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 - + 2 files changed, 23 insertions(+), 55 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 7c53347..670e13f 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -98,7 +98,6 @@ CMMALVideo::CMMALVideo() + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); + pthread_mutex_init(&m_output_mutex, NULL); + +- m_drop_state = false; + m_decoded_width = 0; + m_decoded_height = 0; + +@@ -109,7 +108,6 @@ CMMALVideo::CMMALVideo() + m_interlace_method = VS_INTERLACEMETHOD_NONE; + m_startframe = false; + m_decoderPts = DVD_NOPTS_VALUE; +- m_droppedPics = 0; + m_decode_frame_number = 1; + + m_dec = NULL; +@@ -255,7 +253,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); + double dts = DVD_NOPTS_VALUE; +- if (!m_drop_state) // && !(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) ++ if (1)//(!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -276,11 +274,8 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + } + else + { +- 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 dts:%.3f pts:%.3f (drop:%d len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, m_drop_state, buffer->length, buffer->flags); ++ CLog::Log(LOGDEBUG, "%s::%s - discarding %p dts:%.3f pts:%.3f (len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->flags); + } + } + } +@@ -706,7 +701,6 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + if (!SendCodecConfigData()) + return false; + +- m_drop_state = false; + m_startframe = false; + m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; +@@ -736,30 +730,8 @@ void CMMALVideo::Dispose() + + void CMMALVideo::SetDropState(bool bDrop) + { +- if (m_drop_state != bDrop) +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)", CLASSNAME, __func__, bDrop); +- m_drop_state = bDrop; +- if (m_drop_state) +- { +- while (1) +- { +- CMMALVideoBuffer *buffer = NULL; +- pthread_mutex_lock(&m_output_mutex); +- // fetch a output buffer and pop it off the ready list +- if (!m_output_ready.empty()) +- { +- buffer = m_output_ready.front(); +- m_output_ready.pop(); +- m_droppedPics++; +- } +- pthread_mutex_unlock(&m_output_mutex); +- if (buffer) +- ReleaseBuffer(buffer); +- else +- break; +- } +- } ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "%s::%s - bDrop(%d)", CLASSNAME, __func__, bDrop); + } + + static unsigned count_bits(int32_t value) +@@ -853,10 +825,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts; + buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes; + +- // Request decode only (maintain ref frames, but don't return a picture) +- if (m_drop_state) +- buffer->flags |= MMAL_BUFFER_HEADER_FLAG_DECODEONLY; +- + memcpy(buffer->data, demuxer_content, buffer->length); + demuxer_bytes -= buffer->length; + demuxer_content += buffer->length; +@@ -880,10 +848,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + pthread_mutex_lock(&m_output_mutex); + m_decode_frame_number++; + m_startframe = true; +- if (m_drop_state) +- { +- m_droppedPics += m_deint ? 2:1; +- } + pthread_mutex_unlock(&m_output_mutex); + if (m_changed_count_dec != m_changed_count) + { +@@ -979,16 +943,28 @@ void CMMALVideo::Reset(void) + mmal_port_enable(m_dec_output, dec_output_port_cb_static); + } + // blow all ready video frames +- bool old_drop_state = m_drop_state; +- SetDropState(true); ++ while (1) ++ { ++ CMMALVideoBuffer *buffer = NULL; ++ pthread_mutex_lock(&m_output_mutex); ++ // fetch a output buffer and pop it off the ready list ++ if (!m_output_ready.empty()) ++ { ++ buffer = m_output_ready.front(); ++ m_output_ready.pop(); ++ } ++ pthread_mutex_unlock(&m_output_mutex); ++ if (buffer) ++ ReleaseBuffer(buffer); ++ else ++ break; ++ } ++ + pthread_mutex_lock(&m_output_mutex); + 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); + + if (!m_finished) + SendCodecConfigData(); +@@ -1130,14 +1106,8 @@ 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; ++ droppedPics= -1; ++ return false; + } + + void CMMALVideo::SetCodecControl(int flags) +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index a859467..7161f59 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -110,7 +110,6 @@ class CMMALVideo + bool DestroyDeinterlace(); + + // Video format +- bool m_drop_state; + int m_decoded_width; + int m_decoded_height; + unsigned int m_egl_buffer_count; +@@ -140,7 +139,6 @@ class CMMALVideo + bool m_startframe; + unsigned int m_decode_frame_number; + double m_decoderPts; +- unsigned int m_droppedPics; + int m_speed; + bool m_preroll; + int m_codecControlFlags; + +From e533440ab93a6682c978dbdc6a4fb915f1eb216c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 10 Apr 2015 13:24:41 +0100 +Subject: [PATCH 097/103] [mmalrenderer] squash: logging + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 82a066b..52eb6b3 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -46,9 +46,8 @@ static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer + + void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) + { +- CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; +- + #if defined(MMAL_DEBUG_VERBOSE) ++ CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; + CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p (%p), len %d cmd:%x", CLASSNAME, __func__, port, buffer, omvb, buffer->length, buffer->cmd); + #endif + +@@ -305,7 +304,7 @@ void CMMALRenderer::ReleaseBuffer(int idx) + return; + + #if defined(MMAL_DEBUG_VERBOSE) +- CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, idx); ++ CLog::Log(LOGDEBUG, "%s::%s - %d (%p)", CLASSNAME, __func__, idx, m_buffers[idx].MMALBuffer); + #endif + YUVBUFFER &buf = m_buffers[idx]; + SAFE_RELEASE(buf.MMALBuffer); +@@ -314,7 +313,7 @@ void CMMALRenderer::ReleaseBuffer(int idx) + void CMMALRenderer::ReleaseImage(int source, bool preserve) + { + #if defined(MMAL_DEBUG_VERBOSE) +- CLog::Log(LOGDEBUG, "%s::%s - %d %d", CLASSNAME, __func__, source, preserve); ++ CLog::Log(LOGDEBUG, "%s::%s - %d %d (%p)", CLASSNAME, __func__, source, preserve, m_buffers[idx].MMALBuffer); + #endif + } + + +From af78e68c38ce0b9ae50856f54391eac299895a21 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 Apr 2015 12:47:04 +0100 +Subject: [PATCH 098/103] [players] Make use of new scheme to submit DTS + timestamps + +Latest firmware supports marking timestamps as DTS, +and it will reorder the timestamps with the decoded frame + +This avoids some of the current hacks of supporting PTS and DTS +timestamps in a single field. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 35 +++++----------------- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 -- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 28 ++++++----------- + xbmc/cores/omxplayer/OMXPlayerVideo.h | 1 - + xbmc/cores/omxplayer/OMXVideo.cpp | 25 ++++------------ + xbmc/cores/omxplayer/OMXVideo.h | 2 +- + 6 files changed, 23 insertions(+), 70 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index 670e13f..c5746bb 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -58,7 +58,6 @@ CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv) + index = 0; + m_aspect_ratio = 0.0f; + m_changed_count = 0; +- dts = DVD_NOPTS_VALUE; + } + + CMMALVideoBuffer::~CMMALVideoBuffer() +@@ -129,7 +128,6 @@ CMMALVideo::CMMALVideo() + m_preroll = true; + m_speed = DVD_PLAYSPEED_NORMAL; + m_codecControlFlags = 0; +- m_history_valid_pts = 0; + } + + CMMALVideo::~CMMALVideo() +@@ -252,17 +250,15 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + if (buffer->length > 0) + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); +- double dts = DVD_NOPTS_VALUE; + if (1)//(!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + 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); ++ CLASSNAME, __func__, buffer, omvb, buffer->length, buffer->dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); + omvb->mmal_buffer = buffer; + buffer->user_data = (void *)omvb; + omvb->m_changed_count = m_changed_count; +- omvb->dts = dts; + omvb->width = m_decoded_width; + omvb->height = m_decoded_height; + omvb->m_aspect_ratio = m_aspect_ratio; +@@ -275,7 +271,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + else + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "%s::%s - discarding %p dts:%.3f pts:%.3f (len:%d flags:%x)", CLASSNAME, __func__, buffer, dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->flags); ++ CLog::Log(LOGDEBUG, "%s::%s - dropping %p dts:%.3f pts:%.3f (len:%d flags:%x)", CLASSNAME, __func__, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->flags); + } + } + } +@@ -633,7 +629,11 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + +- status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, 1); ++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, 0); ++ if (status != MMAL_SUCCESS) ++ CLog::Log(LOGERROR, "%s::%s Failed to enable timestamp fifo mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); ++ ++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0); + if (status != MMAL_SUCCESS) + CLog::Log(LOGERROR, "%s::%s Failed to enable timestamp fifo mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); + +@@ -704,8 +704,6 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + m_startframe = false; + m_preroll = !m_hints.stills; + m_speed = DVD_PLAYSPEED_NORMAL; +- // start from assuming all recent frames had valid pts +- m_history_valid_pts = ~0; + + return true; + } +@@ -734,14 +732,6 @@ void CMMALVideo::SetDropState(bool bDrop) + CLog::Log(LOGDEBUG, "%s::%s - bDrop(%d)", CLASSNAME, __func__, bDrop); + } + +-static unsigned count_bits(int32_t value) +-{ +- unsigned bits = 0; +- for(;value;++bits) +- value &= value - 1; +- return bits; +-} +- + int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + { + //if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -809,14 +799,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) + CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); + return VC_ERROR; + } +- +- // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. +- // the valid pts values match the dts values. +- // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts +- m_history_valid_pts = (m_history_valid_pts << 1) | (pts != DVD_NOPTS_VALUE); +- if (count_bits(m_history_valid_pts & 0xffff) < 4) +- pts = dts; +- + mmal_buffer_header_reset(buffer); + buffer->cmd = 0; + if (!m_startframe && pts == DVD_NOPTS_VALUE) +@@ -974,7 +956,6 @@ void CMMALVideo::Reset(void) + m_decode_frame_number = 1; + m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + m_codecControlFlags = 0; +- m_history_valid_pts = ~0; + } + + void CMMALVideo::SetSpeed(int iSpeed) +@@ -1067,7 +1048,7 @@ bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) + } + + // timestamp is in microseconds +- pDvdVideoPicture->dts = buffer->dts; ++ pDvdVideoPicture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->dts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts; + pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->pts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts; + + pDvdVideoPicture->MMALBuffer->Acquire(); +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index 7161f59..52290b6 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +@@ -56,7 +56,6 @@ class CMMALVideoBuffer + int height; + float m_aspect_ratio; + int index; +- double dts; + uint32_t m_changed_count; + // reference counting + CMMALVideoBuffer* Acquire(); +@@ -142,7 +141,6 @@ class CMMALVideo + int m_speed; + bool m_preroll; + int m_codecControlFlags; +- uint32_t m_history_valid_pts; + + MMAL_COMPONENT_T *m_dec; + MMAL_PORT_T *m_dec_input; +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +index 018e65f..4315993 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +@@ -106,7 +106,6 @@ OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock, + m_iCurrentPts = DVD_NOPTS_VALUE; + m_nextOverlay = DVD_NOPTS_VALUE; + m_flush = false; +- m_history_valid_pts = 0; + } + + OMXPlayerVideo::~OMXPlayerVideo() +@@ -314,14 +313,6 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket) + g_renderManager.FlipPage(CThread::m_bStop, time/DVD_TIME_BASE); + } + +-static unsigned count_bits(int32_t value) +-{ +- unsigned bits = 0; +- for(;value;++bits) +- value &= value - 1; +- return bits; +-} +- + void OMXPlayerVideo::Process() + { + double frametime = (double)DVD_TIME_BASE / m_fFrameRate; +@@ -496,18 +487,20 @@ void OMXPlayerVideo::Process() + m_stalled = false; + } + +- // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. +- // the valid pts values match the dts values. +- // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts +- m_history_valid_pts = (m_history_valid_pts << 1) | (pPacket->pts != DVD_NOPTS_VALUE); ++ double dts = pPacket->dts; + double pts = pPacket->pts; +- if(count_bits(m_history_valid_pts & 0xffff) < 4) +- pts = pPacket->dts; ++ ++ if (dts != DVD_NOPTS_VALUE) ++ dts += m_iVideoDelay; + + if (pts != DVD_NOPTS_VALUE) + pts += m_iVideoDelay; + +- m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pts); ++ m_omxVideo.Decode(pPacket->pData, pPacket->iSize, dts, pts); ++ ++ if (pts == DVD_NOPTS_VALUE) ++ pts = dts; ++ + Output(pts, bRequestDrop); + if(pts != DVD_NOPTS_VALUE) + m_iCurrentPts = pts; +@@ -583,9 +576,6 @@ bool OMXPlayerVideo::OpenDecoder() + m_codecname = m_omxVideo.GetDecoderName(); + } + +- // start from assuming all recent frames had valid pts +- m_history_valid_pts = ~0; +- + return bVideoDecoderOpen; + } + +diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h +index 2748a41..3bd5625 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerVideo.h ++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h +@@ -69,7 +69,6 @@ class OMXPlayerVideo : public CThread, public IDVDStreamPlayerVideo + RENDER_STEREO_MODE m_video_stereo_mode; + RENDER_STEREO_MODE m_display_stereo_mode; + bool m_StereoInvert; +- uint32_t m_history_valid_pts; + DllBcmHost m_DllBcmHost; + + CDVDOverlayContainer *m_pOverlayContainer; +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 3f37d44..832a9c9 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -602,23 +602,6 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de + return false; + } + +- // broadcom omx entension: +- // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. +- // In this mode the incoming timestamps get used without re-ordering on output images. +- // recent firmware will actually automatically choose the timestamp stream with the least variance, so always enable +- { +- OMX_CONFIG_BOOLEANTYPE timeStampMode; +- OMX_INIT_STRUCTURE(timeStampMode); +- timeStampMode.bEnabled = OMX_TRUE; +- +- omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); +- if (omx_err != OMX_ErrorNone) +- { +- CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err); +- return false; +- } +- } +- + if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) + { + OMX_NALSTREAMFORMATTYPE nalStreamFormat; +@@ -758,7 +741,7 @@ bool COMXVideo::GetPlayerInfo(double &match, double &phase, double &pll) + } + + +-int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) ++int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts) + { + CSingleLock lock (m_critSection); + OMX_ERRORTYPE omx_err; +@@ -783,6 +766,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + + omx_buffer->nFlags = 0; + omx_buffer->nOffset = 0; ++ omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts != DVD_NOPTS_VALUE ? pts : dts != DVD_NOPTS_VALUE ? dts : 0)); + + if(m_setStartTime) + { +@@ -790,10 +774,11 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) + CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE); + m_setStartTime = false; + } +- if(pts == DVD_NOPTS_VALUE) ++ else if (pts == DVD_NOPTS_VALUE && dts == DVD_NOPTS_VALUE) + omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; ++ else if (pts == DVD_NOPTS_VALUE) ++ omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_IS_DTS; + +- omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); + omx_buffer->nFilledLen = std::min((OMX_U32)demuxer_bytes, omx_buffer->nAllocLen); + memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); + +diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h +index 3ea02dc..86e94ce 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.h ++++ b/xbmc/cores/omxplayer/OMXVideo.h +@@ -55,7 +55,7 @@ class COMXVideo + void Close(void); + unsigned int GetFreeSpace(); + unsigned int GetSize(); +- int Decode(uint8_t *pData, int iSize, double pts); ++ int Decode(uint8_t *pData, int iSize, double dts, double pts); + void Reset(void); + void SetDropState(bool bDrop); + std::string GetDecoderName() { return m_video_codec_name; }; + +From 7bf14e5742366171b81f30d6ef6f93017903ccdc Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Mon, 13 Apr 2015 18:18:00 +0200 +Subject: [PATCH 099/103] dvdplayer audio: do not consider dropped packets for + sync error + +--- + xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +index 416e6f8..58761e9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +@@ -557,7 +557,7 @@ void CDVDPlayerAudio::Process() + if( audioframe.nb_frames == 0 ) + continue; + +- packetadded = true; ++ packetadded = false; + + // we have succesfully decoded an audio frame, setup renderer to match + if (!m_dvdAudio.IsValidFormat(audioframe)) +@@ -607,7 +607,7 @@ void CDVDPlayerAudio::Process() + } + + // signal to our parent that we have initialized +- if(m_started == false && packetadded) ++ if(m_started == false) + { + m_started = true; + m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_AUDIO)); + +From 5b007c4c0b681703f5a0e4eb170f68be7797cf41 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Mon, 13 Apr 2015 18:18:59 +0200 +Subject: [PATCH 100/103] dvdplayer audio: fix/improve calculation of playing + pts + +--- + xbmc/cores/dvdplayer/DVDAudio.cpp | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDAudio.cpp b/xbmc/cores/dvdplayer/DVDAudio.cpp +index a2b1325..d1601b1 100644 +--- a/xbmc/cores/dvdplayer/DVDAudio.cpp ++++ b/xbmc/cores/dvdplayer/DVDAudio.cpp +@@ -276,5 +276,17 @@ double CDVDAudio::GetPlayingPts() + if (m_playingPts == DVD_NOPTS_VALUE) + return 0.0; + +- return m_playingPts + CDVDClock::GetAbsoluteClock() - m_timeOfPts; ++ double now = CDVDClock::GetAbsoluteClock(); ++ double diff = now - m_timeOfPts; ++ double cache = GetCacheTime(); ++ double played = 0.0; ++ ++ if (diff < cache) ++ played = diff; ++ else ++ played = cache; ++ ++ m_timeOfPts = now; ++ m_playingPts += played; ++ return m_playingPts; + } + +From 19e1a724d89949b78e2153840ce5b9d15d9f4cd6 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Mon, 13 Apr 2015 17:11:47 +0200 +Subject: [PATCH 101/103] Application: Don't slow down videos rendered on + GuiLayer + +--- + xbmc/Application.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 6e0aeff..059b7de 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2485,7 +2485,7 @@ void CApplication::FrameMove(bool processEvents, bool processGUI) + #if defined(TARGET_RASPBERRY_PI) || defined(HAS_IMXVPU) + // This code reduces rendering fps of the GUI layer when playing videos in fullscreen mode + // it makes only sense on architectures with multiple layers +- if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) ++ if (g_renderManager.IsVideoLayer() && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback()) + fps = CSettings::Get().GetInt("videoplayer.limitguiupdate"); + #endif + + +From 299175629df95667144a23b8fa7530775a9d6afd Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 10 Apr 2015 13:23:11 +0100 +Subject: [PATCH 102/103] [mmalrenderer] Avoid blank frame on resolution change + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 52eb6b3..5164ffb 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -178,6 +178,7 @@ void CMMALRenderer::AddProcessor(CMMALVideoBuffer *buffer, int index) + + bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) + { ++ bool formatChanged = m_format != format; + ReleaseBuffers(); + + m_sourceWidth = width; +@@ -230,9 +231,10 @@ bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned + else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) + es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; + } +- if (m_bConfigured) ++ if (m_bConfigured && formatChanged) + UnInitMMAL(); +- m_bConfigured = init_vout(es_format); ++ if (!m_bConfigured) ++ m_bConfigured = init_vout(es_format); + mmal_format_free(es_format); + } + else + +From 62360236fc8ad14ce64a50ce4e91567d7cb14dbf Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 8 Apr 2015 17:04:55 +0100 +Subject: [PATCH 103/103] [mmalcodec] Discard corrupt frames later so we can + still count dropped frames + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index c5746bb..5ac12dd 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -250,7 +250,7 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf + if (buffer->length > 0) + { + assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); +- if (1)//(!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) ++ if (!(g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))) + { + CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +@@ -620,7 +620,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));