diff --git a/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch b/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch index 21b1b4c8cc..0219638a9d 100644 --- a/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch +++ b/projects/RPi/patches/xbmc/xbmc-001-newclock4.patch @@ -1,7 +1,7 @@ -From 7be44c1396b421d18385dba981f7dad00b981cc5 Mon Sep 17 00:00:00 2001 +From cf3fb928d3e89202c8c64ace9460676d6284e561 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 18 Aug 2014 17:48:04 +0100 -Subject: [PATCH 001/104] omxplayer: Reset codec on flush to stop a stale +Subject: [PATCH 01/99] omxplayer: Reset codec on flush to stop a stale timestamp from being returned --- @@ -22,899 +22,10 @@ index f1208e6..01d2afc 100644 m_messageQueue.Put( new CDVDMsg(CDVDMsg::GENERAL_FLUSH), 1); } -From dc1337bfb333b7d4c0123fc577d015ae2ee52441 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 30 Dec 2013 12:02:14 +0000 -Subject: [PATCH 002/104] [rbp] Hardware accelerated resampling - -This replaces the format conversion, up/down mixing and resampling code from ActiveAE with a GPU accelerated version. -Should significantly reduce CPU when using paplayer or dvdplayer. - -Requires updated firmware ---- - .../Engines/ActiveAE/ActiveAEResample.cpp | 5 + - .../Engines/ActiveAE/ActiveAEResample.h | 8 + - .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 656 +++++++++++++++++++++ - .../Engines/ActiveAE/ActiveAEResamplePi.h | 63 ++ - xbmc/cores/AudioEngine/Makefile.in | 1 + - xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 14 +- - xbmc/linux/OMXCore.cpp | 4 +- - 7 files changed, 742 insertions(+), 9 deletions(-) - create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp - create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h - -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -index cbb6d69..99cd607 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -@@ -18,6 +18,10 @@ - * - */ - -+#include "system.h" -+ -+#if !defined(TARGET_RASPBERRY_PI) -+ - #include "ActiveAEResample.h" - #include "utils/log.h" - -@@ -386,3 +390,4 @@ int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layo - { - return av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel)); - } -+#endif -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h -index a471e02..5d37cc7 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h -@@ -19,6 +19,8 @@ - * - */ - -+#include "system.h" -+ - #include "cores/AudioEngine/Utils/AEChannelInfo.h" - #include "cores/AudioEngine/Utils/AEAudioFormat.h" - #include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" -@@ -29,6 +31,10 @@ extern "C" { - #include "libswresample/swresample.h" - } - -+#if defined(TARGET_RASPBERRY_PI) -+#include "ActiveAEResamplePi.h" -+#else -+ - namespace ActiveAE - { - -@@ -63,3 +69,5 @@ class CActiveAEResample - }; - - } -+ -+#endif -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -new file mode 100644 -index 0000000..cc01738 ---- /dev/null -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -@@ -0,0 +1,656 @@ -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include "system.h" -+ -+#if defined(TARGET_RASPBERRY_PI) -+ -+#include "ActiveAEResample.h" -+#include "linux/RBP.h" -+#include "settings/Settings.h" -+#include "utils/log.h" -+ -+extern "C" { -+#include "libavutil/channel_layout.h" -+#include "libavutil/opt.h" -+#include "libswresample/swresample.h" -+} -+ -+//#define DEBUG_VERBOSE -+ -+#define CLASSNAME "CActiveAEResamplePi" -+ -+#define BUFFERSIZE (32*1024*2*8) -+ -+//#define BENCHMARKING -+#ifdef BENCHMARKING -+#define LOGTIMEINIT(f) \ -+ struct timespec now; \ -+ uint64_t Start, End; \ -+ clock_gettime(CLOCK_MONOTONIC, &now); \ -+ Start = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \ -+ const char *_filename = f; -+ -+#define LOGTIME(n) \ -+ clock_gettime(CLOCK_MONOTONIC, &now); \ -+ End = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \ -+ CLog::Log(LOGNOTICE, "ActiveAE::%s %d - resample %s took %.0fms", __FUNCTION__, n, _filename, (End-Start)*1e-6); \ -+ Start=End; -+#else -+#define LOGTIMEINIT(f) -+#define LOGTIME(n) -+#endif -+ -+using namespace ActiveAE; -+ -+CActiveAEResample::CActiveAEResample() -+{ -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ -+ m_Initialized = false; -+ m_last_src_fmt = AV_SAMPLE_FMT_NONE; -+ m_last_dst_fmt = AV_SAMPLE_FMT_NONE; -+ m_last_src_channels = 0; -+ m_last_dst_channels = 0; -+ m_encoded_buffer = NULL; -+} -+ -+CActiveAEResample::~CActiveAEResample() -+{ -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ DeInit(); -+} -+ -+void CActiveAEResample::DeInit() -+{ -+ CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); -+ if (m_Initialized) -+ { -+ m_omx_mixer.FlushAll(); -+ m_omx_mixer.Deinitialize(); -+ m_Initialized = false; -+ } -+} -+ -+static int format_to_bits(AVSampleFormat fmt) -+{ -+ switch (fmt) -+ { -+ case AV_SAMPLE_FMT_U8: -+ case AV_SAMPLE_FMT_U8P: -+ return 8; -+ case AV_SAMPLE_FMT_S16: -+ case AV_SAMPLE_FMT_S16P: -+ return 16; -+ case AV_SAMPLE_FMT_S32: -+ case AV_SAMPLE_FMT_S32P: -+ case AV_SAMPLE_FMT_FLT: -+ case AV_SAMPLE_FMT_FLTP: -+ return 32; -+ default: -+ assert(0); -+ } -+ return 0; -+} -+ -+bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) -+{ -+ LOGTIMEINIT("x"); -+ -+ CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d rate:%d->%d format:%d->%d bits:%d->%d norm:%d upmix:%d", CLASSNAME, __func__, remapLayout, src_channels, dst_channels, src_rate, dst_rate, src_fmt, dst_fmt, src_bits, dst_bits, normalize, upmix); -+ -+ // replace passed in number of bits with correct ones -+ src_bits = format_to_bits(src_fmt); -+ dst_bits = format_to_bits(dst_fmt); -+ -+ m_dst_chan_layout = dst_chan_layout; -+ m_dst_channels = dst_channels; -+ m_dst_rate = dst_rate; -+ m_dst_fmt = dst_fmt; -+ m_dst_bits = dst_bits; -+ m_src_chan_layout = src_chan_layout; -+ m_src_channels = src_channels; -+ m_src_rate = src_rate; -+ m_src_fmt = src_fmt; -+ m_src_bits = src_bits; -+ -+ if (m_dst_chan_layout == 0) -+ m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels); -+ if (m_src_chan_layout == 0) -+ m_src_chan_layout = av_get_default_channel_layout(m_src_channels); -+ -+ OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix; -+ OMX_INIT_STRUCTURE(mix); -+ -+ assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64); -+ -+ LOGTIME(1); -+// this code is just uses ffmpeg to produce the 8x8 mixing matrix -+{ -+ // dummy sample rate and format, as we only care about channel mapping -+ SwrContext *m_pContext = swr_alloc_set_opts(NULL, m_dst_chan_layout, AV_SAMPLE_FMT_FLT, 48000, -+ m_src_chan_layout, AV_SAMPLE_FMT_FLT, 48000, 0, NULL); -+ if (!m_pContext) -+ { -+ CLog::Log(LOGERROR, "CActiveAEResample::Init - create context failed"); -+ return false; -+ } -+ // tell resampler to clamp float values -+ // not required for sink stage (remapLayout == true) -+ if (!remapLayout && normalize) -+ { -+ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); -+ } -+ -+ if (remapLayout) -+ { -+ // one-to-one mapping of channels -+ // remapLayout is the layout of the sink, if the channel is in our src layout -+ // the channel is mapped by setting coef 1.0 -+ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; -+ memset(m_rematrix, 0, sizeof(m_rematrix)); -+ m_dst_chan_layout = 0; -+ for (unsigned int out=0; outCount(); out++) -+ { -+ m_dst_chan_layout += (uint64_t) (1 << out); -+ int idx = GetAVChannelIndex((*remapLayout)[out], m_src_chan_layout); -+ if (idx >= 0) -+ { -+ m_rematrix[out][idx] = 1.0; -+ } -+ } -+ -+ av_opt_set_int(m_pContext, "out_channel_count", m_dst_channels, 0); -+ av_opt_set_int(m_pContext, "out_channel_layout", m_dst_chan_layout, 0); -+ -+ if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) -+ { -+ CLog::Log(LOGERROR, "CActiveAEResample::Init - setting channel matrix failed"); -+ return false; -+ } -+ } -+ // stereo upmix -+ else if (upmix && m_src_channels == 2 && m_dst_channels > 2) -+ { -+ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; -+ memset(m_rematrix, 0, sizeof(m_rematrix)); -+ for (int out=0; out 192000 || dst_rate > 192000) -+ src_rate >>= 1, dst_rate >>= 1; -+ -+ OMX_INIT_STRUCTURE(m_pcm_input); -+ m_pcm_input.nPortIndex = m_omx_mixer.GetInputPort(); -+ m_pcm_input.eNumData = OMX_NumericalDataSigned; -+ m_pcm_input.eEndian = OMX_EndianLittle; -+ m_pcm_input.bInterleaved = OMX_TRUE; -+ m_pcm_input.nBitPerSample = m_src_bits; -+ // 0x8000 = float, 0x10000 = planar -+ uint32_t flags = 0; -+ if (m_src_fmt == AV_SAMPLE_FMT_FLT || m_src_fmt == AV_SAMPLE_FMT_FLTP) -+ flags |= 0x8000; -+ if (m_src_fmt >= AV_SAMPLE_FMT_U8P) -+ flags |= 0x10000; -+ m_pcm_input.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; -+ m_pcm_input.nChannels = src_channels; -+ m_pcm_input.nSamplingRate = src_rate; -+ -+ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer in SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ OMX_INIT_STRUCTURE(m_pcm_output); -+ m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort(); -+ m_pcm_output.eNumData = OMX_NumericalDataSigned; -+ m_pcm_output.eEndian = OMX_EndianLittle; -+ m_pcm_output.bInterleaved = OMX_TRUE; -+ m_pcm_output.nBitPerSample = m_dst_bits; -+ flags = 0; -+ if (m_dst_fmt == AV_SAMPLE_FMT_FLT || m_dst_fmt == AV_SAMPLE_FMT_FLTP) -+ flags |= 0x8000; -+ if (m_dst_fmt >= AV_SAMPLE_FMT_U8P) -+ flags |= 0x10000; -+ m_pcm_output.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; -+ m_pcm_output.nChannels = dst_channels; -+ m_pcm_output.nSamplingRate = dst_rate; -+ -+ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer out SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ LOGTIME(4); -+ -+ mix.nPortIndex = m_omx_mixer.GetInputPort(); -+ omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n", -+ CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ // set up the number/size of buffers for decoder input -+ OMX_PARAM_PORTDEFINITIONTYPE port_param; -+ OMX_INIT_STRUCTURE(port_param); -+ port_param.nPortIndex = m_omx_mixer.GetInputPort(); -+ -+ omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)1); -+ port_param.nBufferSize = BUFFERSIZE; -+ -+ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ LOGTIME(5); -+ -+ omx_err = m_omx_mixer.AllocInputBuffers(); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); -+ -+ LOGTIME(6); -+ -+ // set up the number/size of buffers for decoder output -+ OMX_INIT_STRUCTURE(port_param); -+ port_param.nPortIndex = m_omx_mixer.GetOutputPort(); -+ -+ omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)1); -+ port_param.nBufferSize = BUFFERSIZE; -+ -+ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ LOGTIME(7); -+ -+ omx_err = m_omx_mixer.AllocOutputBuffers(); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); -+ -+ LOGTIME(8); -+ -+ omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting); -+ if (omx_err != OMX_ErrorNone) -+ CLog::Log(LOGERROR, "%s:%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); -+ -+ LOGTIME(9); -+ -+ m_Initialized = true; -+ -+ return true; -+} -+ -+ -+static void copy_planes(uint8_t **dst_buffer, int d_pitch, int d_planes, int d_samplesize, int offset, uint8_t *src_buffer, int src_samples) -+{ -+ int planesize = src_samples * d_samplesize / d_planes; -+ for (int i=0; i < d_planes; i++) -+ memcpy(dst_buffer[i] + offset * d_pitch, src_buffer + i * planesize, planesize); -+} -+ -+int CActiveAEResample::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s samples:%d->%d (%.2f)", CLASSNAME, __func__, src_samples, dst_samples, ratio); -+ #endif -+ if (!m_Initialized) -+ return 0; -+ OMX_ERRORTYPE omx_err = OMX_ErrorNone; -+ -+ const int s_planes = m_src_fmt >= AV_SAMPLE_FMT_U8P ? m_src_channels : 1; -+ const int d_planes = m_dst_fmt >= AV_SAMPLE_FMT_U8P ? m_dst_channels : 1; -+ const int s_chans = m_src_fmt >= AV_SAMPLE_FMT_U8P ? 1 : m_src_channels; -+ const int d_chans = m_dst_fmt >= AV_SAMPLE_FMT_U8P ? 1 : m_dst_channels; -+ const int s_pitch = s_chans * m_src_bits >> 3; -+ const int d_pitch = d_chans * m_dst_bits >> 3; -+ -+ const int s_samplesize = m_src_channels * m_src_bits >> 3; -+ const int d_samplesize = m_dst_channels * m_dst_bits >> 3; -+ const int max_src_samples = BUFFERSIZE / s_samplesize; -+ const int max_dst_samples = (long long)(BUFFERSIZE / d_samplesize) * m_src_rate / (m_dst_rate + m_src_rate-1); -+ -+ int sent = 0; -+ int received = 0; -+ -+ if (m_encoded_buffer && m_encoded_buffer->nFilledLen) -+ { -+ int samples_available = m_encoded_buffer->nFilledLen / d_samplesize - m_encoded_buffer->nOffset; -+ int samples = std::min(samples_available, dst_samples - received); -+ copy_planes(dst_buffer, d_pitch, d_planes, d_samplesize, received, (uint8_t *)m_encoded_buffer->pBuffer + m_encoded_buffer->nOffset * d_pitch, samples); -+ received += samples; -+ samples_available -= samples; -+ if (samples_available > 0) -+ m_encoded_buffer->nOffset += samples; -+ else -+ m_encoded_buffer = NULL; -+ } -+ assert(!m_encoded_buffer); -+ while (sent < src_samples) -+ { -+ OMX_BUFFERHEADERTYPE *omx_buffer = NULL; -+ -+ omx_buffer = m_omx_mixer.GetInputBuffer(1000); -+ if (omx_buffer == NULL) -+ return false; -+ -+ int send = std::min(std::min(max_dst_samples, max_src_samples), src_samples - sent); -+ -+ omx_buffer->nOffset = 0; -+ omx_buffer->nFlags = OMX_BUFFERFLAG_EOS; -+ omx_buffer->nFilledLen = send * s_samplesize; -+ -+ assert(omx_buffer->nFilledLen > 0 && omx_buffer->nFilledLen <= omx_buffer->nAllocLen); -+ -+ if (omx_buffer->nFilledLen) -+ { -+ int planesize = omx_buffer->nFilledLen / s_planes; -+ for (int i=0; i < s_planes; i++) -+ memcpy((uint8_t *)omx_buffer->pBuffer + i * planesize, src_buffer[i] + sent * s_pitch, planesize); -+ sent += send; -+ } -+ -+ omx_err = m_omx_mixer.EmptyThisBuffer(omx_buffer); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ -+ m_encoded_buffer = m_omx_mixer.GetOutputBuffer(); -+ -+ if (!m_encoded_buffer) -+ { -+ CLog::Log(LOGERROR, "%s::%s no output buffer", CLASSNAME, __func__); -+ return false; -+ } -+ -+ omx_err = m_omx_mixer.FillThisBuffer(m_encoded_buffer); -+ if (omx_err != OMX_ErrorNone) -+ return false; -+ -+ omx_err = m_omx_mixer.WaitForOutputDone(1000); -+ if (omx_err != OMX_ErrorNone) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_mixer.WaitForOutputDone result(0x%x)", CLASSNAME, __func__, omx_err); -+ return false; -+ } -+ assert(m_encoded_buffer->nFilledLen > 0 && m_encoded_buffer->nFilledLen <= m_encoded_buffer->nAllocLen); -+ -+ if (m_omx_mixer.BadState()) -+ { -+ CLog::Log(LOGERROR, "%s::%s m_omx_mixer.BadState", CLASSNAME, __func__); -+ return false; -+ } -+ -+ if (m_encoded_buffer->nFilledLen) -+ { -+ int samples_available = m_encoded_buffer->nFilledLen / d_samplesize; -+ int samples = std::min(samples_available, dst_samples - received); -+ copy_planes(dst_buffer, d_pitch, d_planes, d_samplesize, received, (uint8_t *)m_encoded_buffer->pBuffer, samples); -+ received += samples; -+ samples_available -= samples; -+ if (samples_available > 0) -+ m_encoded_buffer->nOffset += samples; -+ else -+ m_encoded_buffer = NULL; -+ } -+ } -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s format:%d->%d rate:%d->%d chan:%d->%d samples %d->%d (%f) %d =%d", CLASSNAME, __func__, -+ (int)m_src_fmt, (int)m_dst_fmt, m_src_rate, m_dst_rate, m_src_channels, m_dst_channels, src_samples, dst_samples, ratio, m_Initialized, received); -+ #endif -+ assert(received <= dst_samples); -+ return received; -+} -+ -+int64_t CActiveAEResample::GetDelay(int64_t base) -+{ -+ int ret = m_dst_rate ? 1000 * GetBufferedSamples() / m_dst_rate : 0; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::GetBufferedSamples() -+{ -+ int samples = 0; -+ if (m_encoded_buffer) -+ { -+ const int d_samplesize = m_dst_channels * m_dst_bits >> 3; -+ samples = m_encoded_buffer->nFilledLen / d_samplesize - m_encoded_buffer->nOffset; -+ } -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, samples); -+ #endif -+ return samples; -+} -+ -+int CActiveAEResample::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) -+{ -+ int ret = ((long long)src_samples * dst_rate + src_rate-1) / src_rate; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::GetSrcBufferSize(int samples) -+{ -+ int ret = 0; -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+int CActiveAEResample::GetDstBufferSize(int samples) -+{ -+ int ret = CalcDstSampleCount(samples, m_dst_rate, m_src_rate); -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); -+ #endif -+ return ret; -+} -+ -+uint64_t CActiveAEResample::GetAVChannelLayout(CAEChannelInfo &info) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ uint64_t channelLayout = 0; -+ if (info.HasChannel(AE_CH_FL)) channelLayout |= AV_CH_FRONT_LEFT; -+ if (info.HasChannel(AE_CH_FR)) channelLayout |= AV_CH_FRONT_RIGHT; -+ if (info.HasChannel(AE_CH_FC)) channelLayout |= AV_CH_FRONT_CENTER; -+ if (info.HasChannel(AE_CH_LFE)) channelLayout |= AV_CH_LOW_FREQUENCY; -+ if (info.HasChannel(AE_CH_BL)) channelLayout |= AV_CH_BACK_LEFT; -+ if (info.HasChannel(AE_CH_BR)) channelLayout |= AV_CH_BACK_RIGHT; -+ if (info.HasChannel(AE_CH_FLOC)) channelLayout |= AV_CH_FRONT_LEFT_OF_CENTER; -+ if (info.HasChannel(AE_CH_FROC)) channelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER; -+ if (info.HasChannel(AE_CH_BC)) channelLayout |= AV_CH_BACK_CENTER; -+ if (info.HasChannel(AE_CH_SL)) channelLayout |= AV_CH_SIDE_LEFT; -+ if (info.HasChannel(AE_CH_SR)) channelLayout |= AV_CH_SIDE_RIGHT; -+ if (info.HasChannel(AE_CH_TC)) channelLayout |= AV_CH_TOP_CENTER; -+ if (info.HasChannel(AE_CH_TFL)) channelLayout |= AV_CH_TOP_FRONT_LEFT; -+ if (info.HasChannel(AE_CH_TFC)) channelLayout |= AV_CH_TOP_FRONT_CENTER; -+ if (info.HasChannel(AE_CH_TFR)) channelLayout |= AV_CH_TOP_FRONT_RIGHT; -+ if (info.HasChannel(AE_CH_TBL)) channelLayout |= AV_CH_TOP_BACK_LEFT; -+ if (info.HasChannel(AE_CH_TBC)) channelLayout |= AV_CH_TOP_BACK_CENTER; -+ if (info.HasChannel(AE_CH_TBR)) channelLayout |= AV_CH_TOP_BACK_RIGHT; -+ -+ return channelLayout; -+} -+ -+AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ if (format == AE_FMT_U8) return AV_SAMPLE_FMT_U8; -+ else if (format == AE_FMT_S16NE) return AV_SAMPLE_FMT_S16; -+ else if (format == AE_FMT_S32NE) return AV_SAMPLE_FMT_S32; -+ else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32; -+ else if (format == AE_FMT_S24NE4MSB)return AV_SAMPLE_FMT_S32; -+ else if (format == AE_FMT_FLOAT) return AV_SAMPLE_FMT_FLT; -+ else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL; -+ -+ else if (format == AE_FMT_U8P) return AV_SAMPLE_FMT_U8P; -+ else if (format == AE_FMT_S16NEP) return AV_SAMPLE_FMT_S16P; -+ else if (format == AE_FMT_S32NEP) return AV_SAMPLE_FMT_S32P; -+ else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P; -+ else if (format == AE_FMT_S24NE4MSB)return AV_SAMPLE_FMT_S32; -+ else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP; -+ else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; -+ -+ if (AE_IS_PLANAR(format)) -+ return AV_SAMPLE_FMT_FLTP; -+ else -+ return AV_SAMPLE_FMT_FLT; -+} -+ -+uint64_t CActiveAEResample::GetAVChannel(enum AEChannel aechannel) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ switch (aechannel) -+ { -+ case AE_CH_FL: return AV_CH_FRONT_LEFT; -+ case AE_CH_FR: return AV_CH_FRONT_RIGHT; -+ case AE_CH_FC: return AV_CH_FRONT_CENTER; -+ case AE_CH_LFE: return AV_CH_LOW_FREQUENCY; -+ case AE_CH_BL: return AV_CH_BACK_LEFT; -+ case AE_CH_BR: return AV_CH_BACK_RIGHT; -+ case AE_CH_FLOC: return AV_CH_FRONT_LEFT_OF_CENTER; -+ case AE_CH_FROC: return AV_CH_FRONT_RIGHT_OF_CENTER; -+ case AE_CH_BC: return AV_CH_BACK_CENTER; -+ case AE_CH_SL: return AV_CH_SIDE_LEFT; -+ case AE_CH_SR: return AV_CH_SIDE_RIGHT; -+ case AE_CH_TC: return AV_CH_TOP_CENTER; -+ case AE_CH_TFL: return AV_CH_TOP_FRONT_LEFT; -+ case AE_CH_TFC: return AV_CH_TOP_FRONT_CENTER; -+ case AE_CH_TFR: return AV_CH_TOP_FRONT_RIGHT; -+ case AE_CH_TBL: return AV_CH_TOP_BACK_LEFT; -+ case AE_CH_TBC: return AV_CH_TOP_BACK_CENTER; -+ case AE_CH_TBR: return AV_CH_TOP_BACK_RIGHT; -+ default: -+ return 0; -+ } -+} -+ -+int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout) -+{ -+ #ifdef DEBUG_VERBOSE -+ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); -+ #endif -+ return av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel)); -+} -+ -+#endif -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h -new file mode 100644 -index 0000000..b88a90b ---- /dev/null -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h -@@ -0,0 +1,63 @@ -+#pragma once -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include "linux/OMXCore.h" -+ -+namespace ActiveAE -+{ -+ -+class CActiveAEResample -+{ -+public: -+ CActiveAEResample(); -+ virtual ~CActiveAEResample(); -+ bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality); -+ int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio); -+ int64_t GetDelay(int64_t base); -+ int GetBufferedSamples(); -+ int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate); -+ int GetSrcBufferSize(int samples); -+ int GetDstBufferSize(int samples); -+ static uint64_t GetAVChannelLayout(CAEChannelInfo &info); -+// static CAEChannelInfo GetAEChannelLayout(uint64_t layout); -+ static AVSampleFormat GetAVSampleFormat(AEDataFormat format); -+ static AEDataFormat GetAESampleFormat(AVSampleFormat format, int bits); -+ static uint64_t GetAVChannel(enum AEChannel aechannel); -+ int GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout); -+ -+protected: -+ void DeInit(); -+ uint64_t m_src_chan_layout, m_dst_chan_layout; -+ int m_src_rate, m_dst_rate; -+ int m_src_channels, m_dst_channels; -+ AVSampleFormat m_src_fmt, m_dst_fmt; -+ int m_src_bits, m_dst_bits; -+ -+ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input; -+ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output; -+ COMXCoreComponent m_omx_mixer; -+ bool m_Initialized; -+ AVSampleFormat m_last_src_fmt, m_last_dst_fmt; -+ int m_last_src_channels, m_last_dst_channels; -+ OMX_BUFFERHEADERTYPE *m_encoded_buffer; -+}; -+ -+} -diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in -index 581249e..20c05bb 100644 ---- a/xbmc/cores/AudioEngine/Makefile.in -+++ b/xbmc/cores/AudioEngine/Makefile.in -@@ -31,6 +31,7 @@ SRCS += Engines/ActiveAE/ActiveAESink.cpp - SRCS += Engines/ActiveAE/ActiveAEStream.cpp - SRCS += Engines/ActiveAE/ActiveAESound.cpp - SRCS += Engines/ActiveAE/ActiveAEResample.cpp -+SRCS += Engines/ActiveAE/ActiveAEResamplePi.cpp - SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp - - ifeq (@USE_ANDROID@,1) -diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -index 7af2078..b199acd 100644 ---- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -@@ -78,9 +78,9 @@ static void SetAudioProps(bool stream_channels, uint32_t channel_map) - CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map); - } - --static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) -+static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough) - { -- unsigned int channels = format.m_channelLayout.Count(); -+ unsigned int channels = channelLayout.Count(); - uint32_t channel_map = 0; - if (passthrough) - return 0; -@@ -119,12 +119,12 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) - // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels - // but no BR BL channels, we use the wide map in order to open only the num of channels really - // needed. -- if (format.m_channelLayout.HasChannel(AE_CH_BL) && !format.m_channelLayout.HasChannel(AE_CH_SL)) -+ if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL)) - map = map_back; - - for (unsigned int i = 0; i < channels; ++i) - { -- AEChannel c = format.m_channelLayout[i]; -+ AEChannel c = channelLayout[i]; - unsigned int chan = 0; - if ((unsigned int)c < sizeof map_normal / sizeof *map_normal) - chan = map[(unsigned int)c]; -@@ -155,9 +155,9 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough) - 0xff, // 7 - 0x13, // 7.1 - }; -- uint8_t cea = format.m_channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; -+ uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels]; - if (cea == 0xff) -- CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, format.m_channelLayout.HasChannel(AE_CH_LFE), channels); -+ CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels); - - channel_map |= cea << 24; - -@@ -191,7 +191,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device) - format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS; - format.m_frameSamples = format.m_frames * channels; - -- SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough)); -+ SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough)); - - m_format = format; - m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate); -diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp -index 4ae29ba..4caa304 100644 ---- a/xbmc/linux/OMXCore.cpp -+++ b/xbmc/linux/OMXCore.cpp -@@ -419,7 +419,7 @@ void COMXCoreComponent::FlushAll() - - void COMXCoreComponent::FlushInput() - { -- if(!m_handle) -+ if(!m_handle || m_resource_error) - return; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; -@@ -436,7 +436,7 @@ void COMXCoreComponent::FlushInput() - - void COMXCoreComponent::FlushOutput() - { -- if(!m_handle) -+ if(!m_handle || m_resource_error) - return; - - OMX_ERRORTYPE omx_err = OMX_ErrorNone; - -From b6524129f2df11f4b13aa09e4a3c4e4af8651e44 Mon Sep 17 00:00:00 2001 +From dfb8943208c17327c3ef1040c6e7b018b501925d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 7 Apr 2014 18:19:32 +0100 -Subject: [PATCH 003/104] [rbp/omxplayer] When opening a stream don't try to +Subject: [PATCH 02/99] [rbp/omxplayer] When opening a stream don't try to update gui so often --- @@ -922,10 +33,10 @@ Subject: [PATCH 003/104] [rbp/omxplayer] When opening a stream don't try to 1 file changed, 4 insertions(+) diff --git a/xbmc/dialogs/GUIDialogBusy.cpp b/xbmc/dialogs/GUIDialogBusy.cpp -index e9ba7d3..0fdc3c2 100644 +index e7cfcdd..20b99ad 100644 --- a/xbmc/dialogs/GUIDialogBusy.cpp +++ b/xbmc/dialogs/GUIDialogBusy.cpp -@@ -64,7 +64,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10 +@@ -68,7 +68,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10 if (dialog) { dialog->Show(); @@ -938,10 +49,10 @@ index e9ba7d3..0fdc3c2 100644 g_windowManager.ProcessRenderLoop(false); if (allowCancel && dialog->IsCanceled()) -From 7482553be39d4856de3923a55f3eda7fa144e7ae Mon Sep 17 00:00:00 2001 +From 83739b52ad8654b3245ff41343dd5900c975b312 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 29 Apr 2014 15:23:22 +0100 -Subject: [PATCH 004/104] [ffmpeg] Speed up wtv index creation +Subject: [PATCH 03/99] [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. @@ -1027,10 +138,10 @@ index 0000000..4ac5636 + } + } -From 7bde828f6438e10ed301568bb2de280bb469ca6a Mon Sep 17 00:00:00 2001 +From d8bcb56bcfb580860e3e0dc26c94ee9c80f643e9 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:49:17 +1300 -Subject: [PATCH 005/104] adds GetTvShowSeasons +Subject: [PATCH 04/99] adds GetTvShowSeasons --- xbmc/video/VideoDatabase.cpp | 30 ++++++++++++++++++++++++------ @@ -1038,7 +149,7 @@ Subject: [PATCH 005/104] adds GetTvShowSeasons 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp -index 6ed419d..131b598 100644 +index 769bf30..a6e9efa 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -4213,7 +4213,7 @@ bool CVideoDatabase::RemoveArtForItem(int mediaId, const MediaType &mediaType, c @@ -1106,10 +217,10 @@ index 78259ed..cbb26b7 100644 bool GetArtTypes(const MediaType &mediaType, std::vector &artTypes); -From 7112083b9f825a9eb977c6d30bc385e0f9d5f7f8 Mon Sep 17 00:00:00 2001 +From 5389ca816eccfe0b3eef345d904f3e104614b8c9 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:50:10 +1300 -Subject: [PATCH 006/104] move AddSeason() public. +Subject: [PATCH 05/99] move AddSeason() public. --- xbmc/video/VideoDatabase.h | 2 +- @@ -1136,10 +247,10 @@ index cbb26b7..1a79c00 100644 /*! \brief Adds a path to the tvshow link table. \param idShow the id of the show. -From 6af0c481f4a9a29f606b7446a380e92ca1cd5a5e Mon Sep 17 00:00:00 2001 +From 96dac4a1e5c700d091fd7dba8d13dace8b914ab4 Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:48:24 +1300 -Subject: [PATCH 007/104] adds GetArt function to (video) scraper, allowing art +Subject: [PATCH 06/99] adds GetArt function to (video) scraper, allowing art to be fetched given the video identifier. --- @@ -1254,11 +365,11 @@ index 22ac229..75bc341 100644 enum LOOKUP_STATE { DO_NOTHING = 0, FIND_MOVIE = 1, -From b3e4aae2290c23ee0cfb47e33e604f03a0623e21 Mon Sep 17 00:00:00 2001 +From 9e2ba737076ae127290a5e4abc6d9599d1c2cd1c Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:53:14 +1300 -Subject: [PATCH 008/104] refresh season art if a new season is found that - isn't recorded in the database yet. Fixes #14339 +Subject: [PATCH 07/99] refresh season art if a new season is found that isn't + recorded in the database yet. Fixes #14339 --- xbmc/video/VideoInfoScanner.cpp | 33 ++++++++++++++++++++++++++++++++- @@ -1361,10 +472,10 @@ index 7da1bf2..c764e20 100644 bool ProcessItemByVideoInfoTag(const CFileItem *item, EPISODELIST &episodeList); -From 12e255511287dfd6a4689082c0c3bc77e8636468 Mon Sep 17 00:00:00 2001 +From 3f7128d405004113fcc237427a35ae423ab89a2f Mon Sep 17 00:00:00 2001 From: Jonathan Marshall Date: Sat, 2 Nov 2013 23:53:34 +1300 -Subject: [PATCH 009/104] REMOVEME: updated thetvdb.com scraper to support art +Subject: [PATCH 08/99] REMOVEME: updated thetvdb.com scraper to support art updates --- @@ -1472,10 +583,10 @@ index f27e4fc..bdf329f 100644 -From 3ad334d6c1bb339b1c3c603907757e8d871ee867 Mon Sep 17 00:00:00 2001 +From ce3a875e3134f9a030e490f16dd59c9175b52923 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 2 Aug 2014 17:48:04 +0100 -Subject: [PATCH 010/104] [omx] Report decoded image name +Subject: [PATCH 09/99] [omx] Report decoded image name --- xbmc/cores/omxplayer/OMXImage.cpp | 1 + @@ -1494,17 +605,17 @@ index 3fbea3b..57f69c5 100644 else { -From 72a0f68ff4e794930c42d3c509996a93d12faec5 Mon Sep 17 00:00:00 2001 +From 02dda99b8168816aeea1126ca2eeeae7403395a6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 14 Dec 2013 16:55:05 +0000 -Subject: [PATCH 011/104] logging: Add microsecond timer to log messages +Subject: [PATCH 10/99] logging: Add microsecond timer to log messages --- - xbmc/utils/log.cpp | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) + 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 4e51166..8ed8eec 100644 +index 4e51166..3c405ab 100644 --- a/xbmc/utils/log.cpp +++ b/xbmc/utils/log.cpp @@ -23,6 +23,7 @@ @@ -1515,13 +626,16 @@ index 4e51166..8ed8eec 100644 static const char* const levelNames[] = {"DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "SEVERE", "FATAL", "NONE"}; -@@ -195,19 +196,22 @@ void CLog::PrintDebugString(const std::string& line) +@@ -195,19 +196,31 @@ void CLog::PrintDebugString(const std::string& line) bool CLog::WriteLogString(int logLevel, const std::string& logString) { -- static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%" PRIu64" %7s: "; -- ++#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 "); @@ -1530,22 +644,27 @@ index 4e51166..8ed8eec 100644 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, -+ second, Now, + second, ++#if defined(TARGET_LINUX) ++ Now, ++#endif (uint64_t)CThread::GetCurrentThreadId(), levelNames[logLevel]) + strData; -From a192fdf71cc6591de293da7d3408b6144c2c7b08 Mon Sep 17 00:00:00 2001 + +From 6c35f600273abd1b53ea06dbb950f83cedeada00 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Mar 2014 15:36:06 +0000 -Subject: [PATCH 014/104] [hifiberry] Hack: force it to be recognised as IEC958 +Subject: [PATCH 13/99] [hifiberry] Hack: force it to be recognised as IEC958 capable to enable passthrough options --- @@ -1568,11 +687,11 @@ index a464b4b..7eba389 100644 info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") { -From 22dfa5801feda5faf17d74941d02667210630227 Mon Sep 17 00:00:00 2001 +From 44e7c31812dfaf5b38835a8fb96794efd44590ac Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 11 Dec 2013 17:21:54 +0000 -Subject: [PATCH 015/104] Move the reference-counting of Begin and End calls - from DX and GL source files into GUIFontTTF.cpp. +Subject: [PATCH 14/99] Move the reference-counting of Begin and End calls from + DX and GL source files into GUIFontTTF.cpp. --- xbmc/guilib/GUIFontTTF.cpp | 21 ++++++ @@ -1959,10 +1078,10 @@ index c0bb53a..735fb3a 100644 protected: virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); -From daf5e06ce68b4161b12325042f3ee52a0abfb9ec Mon Sep 17 00:00:00 2001 +From b0eb8735bb06d3f50b546bfc65607b841a926f5f Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 11 Dec 2013 18:47:54 +0000 -Subject: [PATCH 016/104] Convert CGUIFontTTFBase::m_vertex to be managed as a +Subject: [PATCH 15/99] Convert CGUIFontTTFBase::m_vertex to be managed as a std::vector. Also retired CGUIFontTTFBase::m_vertex_count and @@ -2142,10 +1261,10 @@ index 97853fd..b76c6a5 100644 *vertices++ = m_vertex[i]; *vertices++ = m_vertex[i+1]; -From 233254ab13f45af902d8ce5f47997e1be52cb2d6 Mon Sep 17 00:00:00 2001 +From f59702d81eba5e5de5cb856047d4821dad0d6415 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Mon, 16 Dec 2013 18:58:12 +0000 -Subject: [PATCH 017/104] CGUIFontTTFBase::RenderCharacter can now append to +Subject: [PATCH 16/99] CGUIFontTTFBase::RenderCharacter can now append to arbitrary vectors of vertices rather than only CGUIFontTTFBase::m_vertex --- @@ -2218,10 +1337,10 @@ index 10a7060..dde0350 100644 virtual CBaseTexture* ReallocTexture(unsigned int& newHeight) = 0; -From 1ae3e4a6f07b74244511e9388817c482aa1581a0 Mon Sep 17 00:00:00 2001 +From 4aa871df47379c79ff394e5aa694560f68d5c638 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 17:18:38 +0000 -Subject: [PATCH 018/104] Add a cache of font glyph bounding box vertices. +Subject: [PATCH 17/99] Add a cache of font glyph bounding box vertices. This is implemented as a template because ultimately we will key on different parameters and store values of different types, depending upon whether we @@ -2244,7 +1363,7 @@ applicable transformation matrices permit the use of hardware clipping. create mode 100644 xbmc/guilib/GUIFontCache.h diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj -index 3c6c77e..f6722e7 100644 +index 4924acd..1d312b8 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -168,6 +168,9 @@ @@ -2291,7 +1410,7 @@ index 3c6c77e..f6722e7 100644 DFF0F45E17528350002DA3A4 /* InfoTagMusic.cpp in Sources */, DFF0F45F17528350002DA3A4 /* InfoTagVideo.cpp in Sources */, DFF0F46017528350002DA3A4 /* Keyboard.cpp in Sources */, -@@ -13474,6 +13483,7 @@ +@@ -13473,6 +13482,7 @@ E499131D174E5DAD00741B6D /* GUIVisualisationControl.cpp in Sources */, E499131E174E5DAD00741B6D /* GUIWindow.cpp in Sources */, E499131F174E5DAD00741B6D /* GUIWindowManager.cpp in Sources */, @@ -2300,10 +1419,10 @@ index 3c6c77e..f6722e7 100644 E4991321174E5DAD00741B6D /* imagefactory.cpp in Sources */, E4991322174E5DAD00741B6D /* IWindowManagerCallback.cpp in Sources */, diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj -index ff9e0ff..d3639f2 100644 +index 64f7d5c..1dcad9d 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj -@@ -426,6 +426,7 @@ +@@ -425,6 +425,7 @@ @@ -2311,7 +1430,7 @@ index ff9e0ff..d3639f2 100644 -@@ -1748,6 +1749,7 @@ +@@ -1747,6 +1748,7 @@ @@ -2320,10 +1439,10 @@ index ff9e0ff..d3639f2 100644 diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters -index 2e43d7c..5d9c6f3 100644 +index 2f3a22d..8c73472 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters -@@ -994,6 +994,9 @@ +@@ -991,6 +991,9 @@ guilib @@ -2333,7 +1452,7 @@ index 2e43d7c..5d9c6f3 100644 guilib -@@ -3891,6 +3894,9 @@ +@@ -3885,6 +3888,9 @@ guilib @@ -2981,10 +2100,10 @@ index f351c99..9036ba9 100644 + return !operator==(a, b); +} -From 8e4547b5330150713b36ba8118d7d9498972e884 Mon Sep 17 00:00:00 2001 +From 4da5d7b1677f96874f09f3f1cc910651eb3460ec Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 23 Jan 2014 22:24:17 +0000 -Subject: [PATCH 019/104] Lay the groundwork for hardware clipping. +Subject: [PATCH 18/99] Lay the groundwork for hardware clipping. For glScissor() to replace CGraphicContext::ClipRect, a necessary condition is that no shear or rotation is introduced between the coordinate systems @@ -3246,10 +2365,10 @@ index 98e398a..81ee49e 100644 virtual void ResetScissors(); -From 029e8265c92499ceca873ecf2e4c67ae5eb5792d Mon Sep 17 00:00:00 2001 +From eb9a11b15a9ea6566bc7e218efe91c3590f43d3e Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 23 Jan 2014 16:42:22 +0000 -Subject: [PATCH 020/104] Increase font cache hit rate by keying on the +Subject: [PATCH 19/99] Increase font cache hit rate by keying on the fractional part of m_originX and m_originY *after* they have been through the graphics context's transformation matrix, plus the scale/rotation elements of the matrix, rather than the origin in the original frame of reference plus @@ -3450,10 +2569,10 @@ index 77111bc..39bfa52 100644 private: virtual bool FirstBegin() = 0; -From 6b50757e8a97870099dfb9a7a36ad9f7f834a7c9 Mon Sep 17 00:00:00 2001 +From 0fb48b90145afac07a2dccb6d3f48b45e892e975 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 8 Jan 2014 12:16:33 +0000 -Subject: [PATCH 021/104] Rewrite of scrolling text code. +Subject: [PATCH 20/99] Rewrite of scrolling text code. No longer shuffles the string round to minimise the number of characters before the clipping rectangle; this doesn't save much on rendering time but @@ -3769,10 +2888,10 @@ index 2cda726..fbc579e 100644 private: void Process(); -From d20743f609051a962f1518c3d8561606c90fbf93 Mon Sep 17 00:00:00 2001 +From 2a40513f06b7c0e3eb8b23c29de7446c718a6ea5 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Mon, 27 Jan 2014 23:21:10 +0000 -Subject: [PATCH 022/104] Move the application of the translation offsets into +Subject: [PATCH 21/99] Move the application of the translation offsets into the GLES code. Still all pure software at this stage. Main change is in the data types at @@ -3966,10 +3085,10 @@ index 9935ea4..18c9358 100644 memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch()); if (m_texture) -From 41c5ce4e4718d6c8e3142d54fac777bb183d9ed5 Mon Sep 17 00:00:00 2001 +From 0225bf11ee27a23f9401e6148c3760979854da2f Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 15:28:06 +0000 -Subject: [PATCH 023/104] Rather than applying the translation offsets to the +Subject: [PATCH 22/99] Rather than applying the translation offsets to the vertices, now applies them to the model view matrix from the top of the matrix stack and pushes it over to OpenGL. The vertices themselves are still all held client-side. @@ -4113,10 +3232,10 @@ index 81ee49e..d2f9cd1 100644 protected: virtual void SetVSyncImpl(bool enable) = 0; -From 9a0081678df533209c53cb657267561edb5d6f64 Mon Sep 17 00:00:00 2001 +From f0f3a7eb67396c45efa7ca3e73d8f86da7a94f4d Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 29 Jan 2014 13:21:19 +0000 -Subject: [PATCH 024/104] Enable hardware clipping. +Subject: [PATCH 23/99] Enable hardware clipping. --- xbmc/guilib/GUIFontTTF.cpp | 4 ++-- @@ -4189,10 +3308,10 @@ index ea08bf4..b63e337 100644 glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW)); } -From 1abcfe29c3228c993dcfc5351b64e2a2eca5b596 Mon Sep 17 00:00:00 2001 +From a8ce03ce098cc780bf08fd7d12680ba54382ee2b Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 15:32:51 +0000 -Subject: [PATCH 025/104] Move the vertex data across to a vertex buffer object +Subject: [PATCH 24/99] Move the vertex data across to a vertex buffer object just prior to drawing. --- @@ -4243,11 +3362,11 @@ index b63e337..b00055d 100644 // Disable the attributes used by this shader -From 9869fbaa1dd57919b3d61a535363b7018ca32b3f Mon Sep 17 00:00:00 2001 +From ba5d1de62ed376b4f621b878730625558fe64eee Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Wed, 15 Jan 2014 16:04:04 +0000 -Subject: [PATCH 026/104] Move vertex data into an OpenGL VBO when the font - cache entry is populated. +Subject: [PATCH 25/99] Move vertex data into an OpenGL VBO when the font cache + entry is populated. The font cache now stores the "name" (handle) of the VBO, rather than a vector of vertices. @@ -4519,10 +3638,10 @@ index 735fb3a..6102c90 100644 protected: virtual CBaseTexture* ReallocTexture(unsigned int& newHeight); -From f57a6d2eb833010d606237fe66616665bfca8255 Mon Sep 17 00:00:00 2001 +From 3ec6539aba4d894458e3a537632aa550a58a7a27 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 16 Jan 2014 16:29:42 +0000 -Subject: [PATCH 027/104] Switch from glDrawArrays() to glDrawElements(). +Subject: [PATCH 26/99] Switch from glDrawArrays() to glDrawElements(). This involves setting up a static VBO containing the indexes necessary to convert from quads to triangles on the fly in the GPU. @@ -4743,10 +3862,10 @@ index 6de3532..258a293 100644 if (m_display != EGL_NO_DISPLAY) -From 629e43cfebff705ac49a69d7fcfbd1c2b8b900ce Mon Sep 17 00:00:00 2001 +From a662cca8f8e0208b92ef71c00743f31d27bb7055 Mon Sep 17 00:00:00 2001 From: Ben Avison Date: Thu, 1 May 2014 16:28:39 +0100 -Subject: [PATCH 028/104] Improved file buffering in CArchive +Subject: [PATCH 27/99] 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 @@ -4806,2594 +3925,10 @@ index 6ed0f8f..8506d95 100644 } else -From 770893e5c924a92ef9de7ac4f69c0ab5505dfd27 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 10 Sep 2014 21:35:12 +0100 -Subject: [PATCH 029/104] [mmal] Add MMAL decoder and MMAL renderer for - Raspberry Pi - -While omxplayer is the best performing player on the Pi (and the only option for raw Blu-Rays) -there are some reasons to use dvdplayer on a Pi: - -DVDs with menus do not work well with omxplayer -support of software decode for SD codecs like divx3, msmpeg, sorenson spark etc -omxplayer doesn't support alsa, so can't be used with USB and I2S sound cards -dvdplayer may behave better with dodgy timestamps and packet loss, e.g. with live TV - -So this PR adds hardware acceleration to dvdplayer using the MMAL api. - -There is also a MMAL based video renderer. Compared to using GL, this: -saves the processing cost of YUV->RGB conversion -saves the memory cost of the RGB textures for video frames (1080p = 3MB for YUV and 8MB for RGB) -allows high quality (cubic) scaling ---- - configure.in | 4 +- - language/English/strings.po | 14 +- - system/settings/rbp.xml | 10 + - xbmc/cores/VideoRenderers/MMALRenderer.cpp | 728 +++++++++++++ - xbmc/cores/VideoRenderers/MMALRenderer.h | 129 +++ - xbmc/cores/VideoRenderers/Makefile.in | 4 + - xbmc/cores/VideoRenderers/RenderFormats.h | 1 + - xbmc/cores/VideoRenderers/RenderManager.cpp | 8 + - xbmc/cores/VideoRenderers/RenderManager.h | 3 + - xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 14 + - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 5 + - .../DVDCodecs/Video/DVDVideoCodecMMAL.cpp | 99 ++ - .../dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h | 50 + - xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 1099 ++++++++++++++++++++ - xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 157 +++ - xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 5 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 1 + - 17 files changed, 2329 insertions(+), 2 deletions(-) - create mode 100644 xbmc/cores/VideoRenderers/MMALRenderer.cpp - create mode 100644 xbmc/cores/VideoRenderers/MMALRenderer.h - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp - create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h - -diff --git a/configure.in b/configure.in -index 50eb8b4..8026979 100644 ---- a/configure.in -+++ b/configure.in -@@ -721,6 +721,7 @@ case $use_platform in - ARCH="arm" - AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) - USE_OMXLIB=1; AC_DEFINE([HAVE_OMXLIB],[1],["Define to 1 if OMX libs is enabled"]) -+ USE_MMAL=1; AC_DEFINE([HAS_MMAL],[1],["Define to 1 if MMAL libs is enabled"]) - CFLAGS="$CFLAGS" - CXXFLAGS="$CXXFLAGS" - ;; -@@ -1010,7 +1011,7 @@ if test "$use_gles" = "yes"; then - AC_DEFINE([HAVE_LIBEGL],[1],["Define to 1 if you have the `EGL' library (-lEGL)."]) - AC_DEFINE([HAVE_LIBGLESV2],[1],["Define to 1 if you have the `GLESv2' library (-lGLESv2)."]) - AC_MSG_RESULT(== WARNING: OpenGLES support is assumed.) -- LIBS="$LIBS -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm" -+ LIBS="$LIBS -lEGL -lGLESv2 -lbcm_host -lvcos -lvchiq_arm -lmmal -lmmal_core -lmmal_util" - else - AC_CHECK_LIB([EGL], [main],, AC_MSG_ERROR($missing_library)) - AC_CHECK_LIB([GLESv2],[main],, AC_MSG_ERROR($missing_library)) -@@ -2584,6 +2585,7 @@ AC_SUBST(USE_DOXYGEN) - AC_SUBST(USE_PVR_ADDONS) - AC_SUBST(UPNP_DEFINES) - AC_SUBST(USE_SSE4) -+AC_SUBST(USE_MMAL) - - # pushd and popd are not available in other shells besides bash, so implement - # our own pushd/popd functions -diff --git a/language/English/strings.po b/language/English/strings.po -index 00561a5..ddd8ce8 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -15410,7 +15410,19 @@ msgctxt "#36433" - msgid "If enabled VAAPI render method is prefered. This puts less load on the CPU but driver may hang!" - msgstr "" - --#empty strings from id 36434 to 36499 -+#. Description of setting "Videos -> Playback -> Enable MMAL hardware decoding of video files" -+#: system/settings/settings.xml -+msgctxt "#36434" -+msgid "Allow hardware acceleration (MMAL)" -+msgstr "" -+ -+#. Description of setting "Videos -> Playback -> Enable MMAL hardware decoding of video files" -+#: system/settings/settings.xml -+msgctxt "#36435" -+msgid "Use DVDPlayer for decoding of video files with MMAL acceleration." -+msgstr "" -+ -+#empty strings from id 36436 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/rbp.xml b/system/settings/rbp.xml -index 21f06ed..570798b 100644 ---- a/system/settings/rbp.xml -+++ b/system/settings/rbp.xml -@@ -12,6 +12,16 @@ - - false - -+ -+ -+ -+ 1 -+ -+ 2 -+ true -+ -+ -+ - - - -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -new file mode 100644 -index 0000000..b7bcaeb ---- /dev/null -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -@@ -0,0 +1,728 @@ -+/* -+ * Copyright (C) 2005-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#include "Util.h" -+#include "MMALRenderer.h" -+#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" -+#include "filesystem/File.h" -+#include "settings/AdvancedSettings.h" -+#include "settings/DisplaySettings.h" -+#include "settings/MediaSettings.h" -+#include "settings/Settings.h" -+#include "threads/SingleLock.h" -+#include "utils/log.h" -+#include "utils/MathUtils.h" -+#include "windowing/WindowingFactory.h" -+#include "cores/dvdplayer/DVDCodecs/Video/MMALCodec.h" -+#include "xbmc/Application.h" -+ -+#define CLASSNAME "CMMALRenderer" -+ -+#ifdef _DEBUG -+#define MMAL_DEBUG_VERBOSE -+#endif -+ -+static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+ mmal_buffer_header_release(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) -+ CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p (%p), len %d cmd:%x", CLASSNAME, __func__, port, buffer, omvb, buffer->length, buffer->cmd); -+ #endif -+ -+ if (m_format == RENDER_FMT_MMAL) -+ { -+ mmal_queue_put(m_release_queue, buffer); -+ } -+ else if (m_format == RENDER_FMT_YUV420P) -+ { -+ mmal_buffer_header_release(buffer); -+ } -+ else assert(0); -+} -+ -+static void vout_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+ CMMALRenderer *mmal = reinterpret_cast(port->userdata); -+ mmal->vout_input_port_cb(port, buffer); -+} -+ -+bool CMMALRenderer::init_vout(MMAL_ES_FORMAT_T *format) -+{ -+ MMAL_STATUS_T status; -+ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ -+ /* Create video renderer */ -+ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout); -+ if(status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_vout->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ status = mmal_port_enable(m_vout->control, vout_control_port_cb); -+ if(status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable vout control port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ m_vout_input = m_vout->input[0]; -+ m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ mmal_format_full_copy(m_vout_input->format, format); -+ status = mmal_port_format_commit(m_vout_input); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ if (m_format == RENDER_FMT_YUV420P) -+ m_vout_input->buffer_num = NUM_BUFFERS; -+ else -+ m_vout_input->buffer_num = m_vout_input->buffer_num_min; -+ m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; -+ -+ status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); -+ if(status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ status = mmal_component_enable(m_vout); -+ if(status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ if (m_format == RENDER_FMT_YUV420P) -+ { -+ m_vout_input_pool = mmal_pool_create(m_vout_input->buffer_num, m_vout_input->buffer_size); -+ if (!m_vout_input_pool) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ } -+ return true; -+} -+ -+void CMMALRenderer::Process() -+{ -+ MMAL_BUFFER_HEADER_T *buffer; -+ while (buffer = mmal_queue_wait(m_release_queue), buffer) -+ { -+ CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data; -+ omvb->Release(); -+ } -+ m_sync.Set(); -+} -+ -+CMMALRenderer::CMMALRenderer() -+: CThread("CMMALRenderer") -+{ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ m_vout = NULL; -+ m_vout_input = NULL; -+ m_vout_input_pool = NULL; -+ memset(m_buffers, 0, sizeof m_buffers); -+ m_release_queue = mmal_queue_create(); -+ Create(); -+} -+ -+CMMALRenderer::~CMMALRenderer() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ // shutdown thread -+ mmal_queue_put(m_release_queue, NULL); -+ m_sync.Wait(); -+ mmal_queue_destroy(m_release_queue); -+ UnInit(); -+} -+ -+void CMMALRenderer::AddProcessor(CMMALVideoBuffer *buffer, int index) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p) %i", CLASSNAME, __func__, buffer, buffer->mmal_buffer, index); -+#endif -+ -+ YUVBUFFER &buf = m_buffers[index]; -+ assert(!buf.MMALBuffer); -+ memset(&buf, 0, sizeof buf); -+ buf.MMALBuffer = buffer->Acquire(); -+} -+ -+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) -+{ -+ ReleaseBuffers(); -+ -+ m_sourceWidth = width; -+ m_sourceHeight = height; -+ m_renderOrientation = orientation; -+ -+ m_fps = fps; -+ m_iFlags = flags; -+ m_format = format; -+ -+ CLog::Log(LOGDEBUG, "%s::%s - %dx%d->%dx%d@%.2f flags:%x format:%d ext:%x orient:%d", CLASSNAME, __func__, width, height, d_width, d_height, fps, flags, format, extended_format, orientation); -+ -+ m_RenderUpdateCallBackFn = NULL; -+ m_RenderUpdateCallBackCtx = NULL; -+ if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer()) -+ { -+ m_renderFeatures.clear(); -+ m_scalingMethods.clear(); -+ m_deinterlaceModes.clear(); -+ m_deinterlaceMethods.clear(); -+ -+ if (m_RenderFeaturesCallBackFn) -+ { -+ (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures); -+ // after setting up m_renderFeatures, we are done with the callback -+ m_RenderFeaturesCallBackFn = NULL; -+ m_RenderFeaturesCallBackCtx = NULL; -+ } -+ g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures); -+ g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods); -+ g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes); -+ g_application.m_pPlayer->GetScalingMethods(m_scalingMethods); -+ } -+ -+ // calculate the input frame aspect ratio -+ CalculateFrameAspectRatio(d_width, d_height); -+ ChooseBestResolution(fps); -+ m_destWidth = g_graphicsContext.GetResInfo(m_resolution).iWidth; -+ m_destHeight = g_graphicsContext.GetResInfo(m_resolution).iHeight; -+ SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode); -+ ManageDisplay(); -+ -+ if (m_format == RENDER_FMT_MMAL|| m_format == RENDER_FMT_YUV420P) -+ { -+ MMAL_ES_FORMAT_T *es_format = mmal_format_alloc(); -+ es_format->type = MMAL_ES_TYPE_VIDEO; -+ es_format->es->video.crop.width = m_sourceWidth; -+ es_format->es->video.crop.height = m_sourceHeight; -+ -+ if (m_format == RENDER_FMT_MMAL) -+ { -+ es_format->encoding = MMAL_ENCODING_OPAQUE; -+ es_format->es->video.width = m_sourceWidth; -+ es_format->es->video.height = m_sourceHeight; -+ } -+ else if (m_format == RENDER_FMT_YUV420P) -+ { -+ const int pitch = ALIGN_UP(m_sourceWidth, 32); -+ const int aligned_height = ALIGN_UP(m_sourceHeight, 16); -+ -+ es_format->encoding = MMAL_ENCODING_I420; -+ es_format->es->video.width = pitch; -+ es_format->es->video.height = aligned_height; -+ -+ if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) -+ es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; -+ else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) -+ es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; -+ 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) -+ UnInit(); -+ m_bConfigured = init_vout(es_format); -+ mmal_format_free(es_format); -+ } -+ else -+ m_bConfigured = true; -+ -+ return m_bConfigured; -+} -+ -+int CMMALRenderer::GetImage(YV12Image *image, int source, bool readonly) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p %d %d", CLASSNAME, __func__, image, source, readonly); -+#endif -+ if (!image) return -1; -+ -+ if( source < 0) -+ return -1; -+ -+ if (m_format == RENDER_FMT_MMAL) -+ { -+ } -+ else if (m_format == RENDER_FMT_YUV420P) -+ { -+ const int pitch = ALIGN_UP(m_sourceWidth, 32); -+ const int aligned_height = ALIGN_UP(m_sourceHeight, 16); -+ -+ MMAL_BUFFER_HEADER_T *buffer = mmal_queue_timedwait(m_vout_input_pool->queue, 500); -+ if (!buffer) -+ { -+ CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); -+ return -1; -+ } -+ -+ mmal_buffer_header_reset(buffer); -+ -+ buffer->length = 3 * pitch * aligned_height >> 1; -+ assert(buffer->length <= buffer->alloc_size); -+ -+ image->width = m_sourceWidth; -+ image->height = m_sourceHeight; -+ image->flags = 0; -+ image->cshift_x = 1; -+ image->cshift_y = 1; -+ image->bpp = 1; -+ -+ image->stride[0] = pitch; -+ image->stride[1] = image->stride[2] = pitch>>image->cshift_x; -+ -+ image->planesize[0] = pitch * aligned_height; -+ image->planesize[1] = image->planesize[2] = (pitch>>image->cshift_x)*(aligned_height>>image->cshift_y); -+ -+ image->plane[0] = (uint8_t *)buffer->data; -+ image->plane[1] = image->plane[0] + image->planesize[0]; -+ image->plane[2] = image->plane[1] + image->planesize[1]; -+ -+ CLog::Log(LOGDEBUG, "%s::%s - %p %d", CLASSNAME, __func__, buffer, source); -+ YUVBUFFER &buf = m_buffers[source]; -+ memset(&buf, 0, sizeof buf); -+ buf.mmal_buffer = buffer; -+ } -+ else assert(0); -+ -+ return source; -+} -+ -+void CMMALRenderer::ReleaseBuffer(int idx) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, idx); -+#endif -+ YUVBUFFER &buf = m_buffers[idx]; -+ SAFE_RELEASE(buf.MMALBuffer); -+} -+ -+void CMMALRenderer::ReleaseImage(int source, bool preserve) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %d %d", CLASSNAME, __func__, source, preserve); -+#endif -+} -+ -+void CMMALRenderer::Reset() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+} -+ -+void CMMALRenderer::Flush() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+} -+ -+void CMMALRenderer::Update() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ if (!m_bConfigured) return; -+ ManageDisplay(); -+} -+ -+void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %d %x %d", CLASSNAME, __func__, clear, flags, alpha); -+#endif -+ -+ if (!m_bConfigured) return; -+ -+ CSingleLock lock(g_graphicsContext); -+ -+ ManageDisplay(); -+ -+ // if running bypass, then the player might need the src/dst rects -+ // for sizing video playback on a layer other than the gles layer. -+ if (m_RenderUpdateCallBackFn) -+ (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); -+ -+ SetVideoRect(m_sourceRect, m_destRect); -+ -+ CRect old = g_graphicsContext.GetScissors(); -+ -+ g_graphicsContext.BeginPaint(); -+ g_graphicsContext.SetScissors(m_destRect); -+ -+ glEnable(GL_BLEND); -+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -+ glClearColor(0, 0, 0, 0); -+ glClear(GL_COLOR_BUFFER_BIT); -+ -+ g_graphicsContext.SetScissors(old); -+ g_graphicsContext.EndPaint(); -+} -+ -+void CMMALRenderer::FlipPage(int source) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, source); -+#endif -+ -+ if (!m_bConfigured || m_format == RENDER_FMT_BYPASS) -+ return; -+ -+ 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; -+ if (omvb) -+ { -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%p)", CLASSNAME, __func__, omvb, omvb->mmal_buffer); -+#endif -+ omvb->Acquire(); -+ mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer); -+ } else assert(0); -+ } -+ else if (m_format == RENDER_FMT_YUV420P) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s - %p %d", CLASSNAME, __func__, buffer->mmal_buffer, source); -+ if (buffer->mmal_buffer) -+ mmal_port_send_buffer(m_vout_input, buffer->mmal_buffer); -+ else assert(0); -+ } -+ else assert(0); -+} -+ -+unsigned int CMMALRenderer::PreInit() -+{ -+ CSingleLock lock(g_graphicsContext); -+ m_bConfigured = false; -+ UnInit(); -+ -+ m_iFlags = 0; -+ -+ m_resolution = CDisplaySettings::Get().GetCurrentResolution(); -+ if ( m_resolution == RES_WINDOW ) -+ m_resolution = RES_DESKTOP; -+ -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ -+ m_formats.clear(); -+ m_formats.push_back(RENDER_FMT_YUV420P); -+ m_formats.push_back(RENDER_FMT_MMAL); -+ m_formats.push_back(RENDER_FMT_BYPASS); -+ -+ m_NumYV12Buffers = NUM_BUFFERS; -+ -+ return 0; -+} -+ -+void CMMALRenderer::ReleaseBuffers() -+{ -+ for (int i=0; icontrol); -+ } -+ -+ if (m_vout_input) -+ { -+ mmal_port_flush(m_vout_input); -+ mmal_port_disable(m_vout_input); -+ m_vout_input = NULL; -+ } -+ -+ if (m_vout_input_pool) -+ { -+ mmal_pool_destroy(m_vout_input_pool); -+ m_vout_input_pool = NULL; -+ } -+ -+ if (m_vout) -+ { -+ mmal_component_release(m_vout); -+ m_vout = NULL; -+ } -+ ReleaseBuffers(); -+ -+ m_RenderUpdateCallBackFn = NULL; -+ m_RenderUpdateCallBackCtx = NULL; -+ m_RenderFeaturesCallBackFn = NULL; -+ m_RenderFeaturesCallBackCtx = NULL; -+ -+ m_src_rect.SetRect(0, 0, 0, 0); -+ m_dst_rect.SetRect(0, 0, 0, 0); -+ m_video_stereo_mode = RENDER_STEREO_MODE_OFF; -+ m_display_stereo_mode = RENDER_STEREO_MODE_OFF; -+ m_StereoInvert = false; -+ -+ m_bConfigured = false; -+} -+ -+bool CMMALRenderer::RenderCapture(CRenderCapture* capture) -+{ -+ if (!m_bConfigured) -+ return false; -+ -+ CLog::Log(LOGDEBUG, "%s::%s - %p", CLASSNAME, __func__, capture); -+ -+ capture->BeginRender(); -+ capture->EndRender(); -+ -+ return true; -+} -+ -+//******************************************************************************************************** -+// YV12 Texture creation, deletion, copying + clearing -+//******************************************************************************************************** -+ -+bool CMMALRenderer::Supports(EDEINTERLACEMODE mode) -+{ -+ // Player controls render, let it dictate available deinterlace modes -+ if (m_format == RENDER_FMT_BYPASS) -+ { -+ Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode); -+ return itr != m_deinterlaceModes.end(); -+ } -+ -+ if(mode == VS_DEINTERLACEMODE_OFF -+ || mode == VS_DEINTERLACEMODE_AUTO -+ || mode == VS_DEINTERLACEMODE_FORCE) -+ return true; -+ -+ return false; -+} -+ -+bool CMMALRenderer::Supports(EINTERLACEMETHOD method) -+{ -+ // Player controls render, let it dictate available deinterlace methods -+ if (m_format == RENDER_FMT_BYPASS) -+ { -+ Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method); -+ return itr != m_deinterlaceMethods.end(); -+ } -+ -+ if (method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) -+ return true; -+ -+ return false; -+} -+ -+bool CMMALRenderer::Supports(ERENDERFEATURE feature) -+{ -+ // Player controls render, let it dictate available render features -+ if (m_format == RENDER_FMT_BYPASS) -+ { -+ Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature); -+ return itr != m_renderFeatures.end(); -+ } -+ -+ if (feature == RENDERFEATURE_STRETCH || -+ feature == RENDERFEATURE_CROP || -+ feature == RENDERFEATURE_ZOOM || -+ feature == RENDERFEATURE_ROTATION || -+ feature == RENDERFEATURE_VERTICAL_SHIFT || -+ feature == RENDERFEATURE_PIXEL_RATIO) -+ return true; -+ -+ return false; -+} -+ -+bool CMMALRenderer::Supports(ESCALINGMETHOD method) -+{ -+ // Player controls render, let it dictate available scaling methods -+ if (m_format == RENDER_FMT_BYPASS) -+ { -+ Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method); -+ return itr != m_scalingMethods.end(); -+ } -+ return false; -+} -+ -+EINTERLACEMETHOD CMMALRenderer::AutoInterlaceMethod() -+{ -+ return VS_INTERLACEMETHOD_DEINTERLACE_HALF; -+} -+ -+unsigned int CMMALRenderer::GetProcessorSize() -+{ -+ if (m_format == RENDER_FMT_MMAL) -+ return 1; -+ else -+ return 0; -+} -+ -+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; -+ -+ if (!m_vout_input) -+ return; -+ -+ CRect SrcRect = InSrcRect, DestRect = InDestRect; -+ RENDER_STEREO_MODE video_stereo_mode = (m_iFlags & CONF_FLAGS_STEREO_MODE_SBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL : -+ (m_iFlags & CONF_FLAGS_STEREO_MODE_TAB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL : RENDER_STEREO_MODE_OFF; -+ bool stereo_invert = (m_iFlags & CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) ? true : false; -+ RENDER_STEREO_MODE display_stereo_mode = g_graphicsContext.GetStereoMode(); -+ -+ // fix up transposed video -+ if (m_renderOrientation == 90 || m_renderOrientation == 270) -+ { -+ float diff = (DestRect.Height() - DestRect.Width()) * 0.5f; -+ DestRect.x1 -= diff; -+ DestRect.x2 += diff; -+ DestRect.y1 += diff; -+ DestRect.y2 -= diff; -+ } -+ -+ // check if destination rect or video view mode has changed -+ if (!(m_dst_rect != DestRect) && !(m_src_rect != SrcRect) && m_video_stereo_mode == video_stereo_mode && m_display_stereo_mode == display_stereo_mode && m_StereoInvert == stereo_invert) -+ return; -+ -+ CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d (o:%d v:%d d:%d i:%d)", CLASSNAME, __func__, -+ (int)SrcRect.x1, (int)SrcRect.y1, (int)SrcRect.x2, (int)SrcRect.y2, -+ (int)DestRect.x1, (int)DestRect.y1, (int)DestRect.x2, (int)DestRect.y2, -+ m_renderOrientation, video_stereo_mode, display_stereo_mode, stereo_invert); -+ -+ m_src_rect = SrcRect; -+ m_dst_rect = DestRect; -+ m_video_stereo_mode = video_stereo_mode; -+ m_display_stereo_mode = display_stereo_mode; -+ m_StereoInvert = stereo_invert; -+ -+ // might need to scale up m_dst_rect to display size as video decodes -+ // to separate video plane that is at display size. -+ RESOLUTION res = g_graphicsContext.GetVideoResolution(); -+ 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) -+ { -+ 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) -+ { -+ SrcRect.y2 *= 2.0f; -+ } -+ break; -+ -+ default: break; -+ } -+ -+ if (gui != display) -+ { -+ float xscale = display.Width() / gui.Width(); -+ float yscale = display.Height() / gui.Height(); -+ DestRect.x1 *= xscale; -+ DestRect.x2 *= xscale; -+ DestRect.y1 *= yscale; -+ DestRect.y2 *= yscale; -+ } -+ -+ MMAL_DISPLAYREGION_T region; -+ memset(®ion, 0, sizeof region); -+ -+ region.set = MMAL_DISPLAY_SET_DEST_RECT|MMAL_DISPLAY_SET_SRC_RECT|MMAL_DISPLAY_SET_FULLSCREEN|MMAL_DISPLAY_SET_NOASPECT|MMAL_DISPLAY_SET_MODE; -+ region.dest_rect.x = lrintf(DestRect.x1); -+ region.dest_rect.y = lrintf(DestRect.y1); -+ region.dest_rect.width = lrintf(DestRect.Width()); -+ region.dest_rect.height = lrintf(DestRect.Height()); -+ -+ region.src_rect.x = lrintf(SrcRect.x1); -+ region.src_rect.y = lrintf(SrcRect.y1); -+ region.src_rect.width = lrintf(SrcRect.Width()); -+ region.src_rect.height = lrintf(SrcRect.Height()); -+ -+ region.fullscreen = MMAL_FALSE; -+ region.noaspect = MMAL_TRUE; -+ -+ 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; -+ else -+ region.mode = MMAL_DISPLAY_MODE_LETTERBOX; -+ -+ 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__, -+ 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); -+} -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h -new file mode 100644 -index 0000000..8cff140 ---- /dev/null -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.h -@@ -0,0 +1,129 @@ -+#pragma once -+ -+/* -+ * Copyright (C) 2005-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#ifdef HAS_MMAL -+ -+#include "guilib/GraphicContext.h" -+#include "RenderFlags.h" -+#include "RenderFormats.h" -+#include "BaseRenderer.h" -+#include "RenderCapture.h" -+#include "settings/VideoSettings.h" -+#include "cores/dvdplayer/DVDStreamInfo.h" -+#include "guilib/Geometry.h" -+#include "threads/Thread.h" -+ -+#include -+#include -+#include -+#include -+ -+#define AUTOSOURCE -1 -+ -+class CBaseTexture; -+class CMMALVideoBuffer; -+ -+struct DVDVideoPicture; -+ -+class CMMALRenderer : public CBaseRenderer, public CThread -+{ -+ struct YUVBUFFER -+ { -+ 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(); -+ ~CMMALRenderer(); -+ -+ virtual void Update(); -+ virtual void SetupScreenshot() {}; -+ virtual void Process(); -+ -+ bool RenderCapture(CRenderCapture* capture); -+ -+ // Player functions -+ virtual bool 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); -+ virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); -+ virtual void ReleaseImage(int source, bool preserve = false); -+ virtual void ReleaseBuffer(int idx); -+ virtual void FlipPage(int source); -+ virtual unsigned int PreInit(); -+ virtual void UnInit(); -+ virtual void Reset(); /* resets renderer after seek for example */ -+ virtual void Flush(); -+ virtual bool IsConfigured() { return m_bConfigured; } -+ virtual void AddProcessor(CMMALVideoBuffer *buffer, int index); -+ virtual std::vector SupportedFormats() { return m_formats; } -+ -+ virtual bool Supports(ERENDERFEATURE feature); -+ virtual bool Supports(EDEINTERLACEMODE mode); -+ virtual bool Supports(EINTERLACEMETHOD method); -+ virtual bool Supports(ESCALINGMETHOD method); -+ -+ virtual EINTERLACEMETHOD AutoInterlaceMethod(); -+ -+ void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); -+ -+ virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } -+ virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } -+ virtual unsigned int GetProcessorSize(); -+ virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); -+ -+ void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); -+protected: -+ int m_NumYV12Buffers; -+ -+ std::vector m_formats; -+ -+ YUVBUFFER m_buffers[NUM_BUFFERS]; -+ bool m_bConfigured; -+ unsigned int m_extended_format; -+ unsigned int m_destWidth; -+ unsigned int m_destHeight; -+ int m_neededBuffers; -+ -+ Features m_renderFeatures; -+ Features m_deinterlaceMethods; -+ Features m_deinterlaceModes; -+ Features m_scalingMethods; -+ -+ CRect m_src_rect; -+ CRect m_dst_rect; -+ RENDER_STEREO_MODE m_video_stereo_mode; -+ RENDER_STEREO_MODE m_display_stereo_mode; -+ bool m_StereoInvert; -+ -+ MMAL_COMPONENT_T *m_vout; -+ MMAL_PORT_T *m_vout_input; -+ MMAL_POOL_T *m_vout_input_pool; -+ -+ MMAL_QUEUE_T *m_release_queue; -+ CEvent m_sync; -+ bool init_vout(MMAL_ES_FORMAT_T *m_format); -+ void ReleaseBuffers(); -+}; -+ -+#else -+#include "LinuxRenderer.h" -+#endif -diff --git a/xbmc/cores/VideoRenderers/Makefile.in b/xbmc/cores/VideoRenderers/Makefile.in -index d964285..7fcc322 100644 ---- a/xbmc/cores/VideoRenderers/Makefile.in -+++ b/xbmc/cores/VideoRenderers/Makefile.in -@@ -20,6 +20,10 @@ SRCS += LinuxRendererGLES.cpp - SRCS += OverlayRendererGL.cpp - endif - -+ifeq (@USE_MMAL@,1) -+SRCS += MMALRenderer.cpp -+endif -+ - LIB = VideoRenderer.a - - include @abs_top_srcdir@/Makefile.include -diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h -index 1bdd1d3..6394ef1 100644 ---- a/xbmc/cores/VideoRenderers/RenderFormats.h -+++ b/xbmc/cores/VideoRenderers/RenderFormats.h -@@ -39,6 +39,7 @@ enum ERenderFormat { - RENDER_FMT_EGLIMG, - RENDER_FMT_MEDIACODEC, - RENDER_FMT_IMXMAP, -+ RENDER_FMT_MMAL, - }; - - #endif -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index 91d7635..e72d791 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -41,6 +41,8 @@ - - #if defined(HAS_GL) - #include "LinuxRendererGL.h" -+#elif defined(HAS_MMAL) -+ #include "MMALRenderer.h" - #elif HAS_GLES == 2 - #include "LinuxRendererGLES.h" - #elif defined(HAS_DX) -@@ -423,6 +425,8 @@ unsigned int CXBMCRenderManager::PreInit() - { - #if defined(HAS_GL) - m_pRenderer = new CLinuxRendererGL(); -+#elif defined(HAS_MMAL) -+ m_pRenderer = new CMMALRenderer(); - #elif HAS_GLES == 2 - m_pRenderer = new CLinuxRendererGLES(); - #elif defined(HAS_DX) -@@ -951,6 +955,10 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) - else if(pic.format == RENDER_FMT_IMXMAP) - m_pRenderer->AddProcessor(pic.IMXBuffer, index); - #endif -+#ifdef HAS_MMAL -+ else if(pic.format == RENDER_FMT_MMAL) -+ m_pRenderer->AddProcessor(pic.MMALBuffer, index); -+#endif - - m_pRenderer->ReleaseImage(index, false); - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index 850890f..d3c2f1d 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -42,6 +42,7 @@ struct DVDVideoPicture; - #define ERRORBUFFSIZE 30 - - class CWinRenderer; -+class CMMALRenderer; - class CLinuxRenderer; - class CLinuxRendererGL; - class CLinuxRendererGLES; -@@ -146,6 +147,8 @@ class CXBMCRenderManager - - #ifdef HAS_GL - CLinuxRendererGL *m_pRenderer; -+#elif defined(HAS_MMAL) -+ CMMALRenderer *m_pRenderer; - #elif HAS_GLES == 2 - CLinuxRendererGLES *m_pRenderer; - #elif defined(HAS_DX) -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -index ac6ac73..f139433 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp -@@ -39,6 +39,7 @@ - #if defined(HAS_IMXVPU) - #include "Video/DVDVideoCodecIMX.h" - #endif -+#include "Video/DVDVideoCodecMMAL.h" - #include "Video/DVDVideoCodecStageFright.h" - #if defined(HAS_LIBAMCODEC) - #include "utils/AMLUtils.h" -@@ -259,6 +260,19 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne - } - #endif - -+#if defined(HAS_MMAL) -+ if (CSettings::Get().GetBool("videoplayer.usemmal") && !hint.software ) -+ { -+ if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_H263 || hint.codec == AV_CODEC_ID_MPEG4 || -+ hint.codec == AV_CODEC_ID_MPEG1VIDEO || hint.codec == AV_CODEC_ID_MPEG2VIDEO || -+ hint.codec == AV_CODEC_ID_VP6 || hint.codec == AV_CODEC_ID_VP6F || hint.codec == AV_CODEC_ID_VP6A || hint.codec == AV_CODEC_ID_VP8 || -+ hint.codec == AV_CODEC_ID_THEORA || hint.codec == AV_CODEC_ID_MJPEG || hint.codec == AV_CODEC_ID_MJPEGB || hint.codec == AV_CODEC_ID_VC1 || hint.codec == AV_CODEC_ID_WMV3) -+ { -+ if ( (pCodec = OpenCodec(new CDVDVideoCodecMMAL(), hint, options)) ) return pCodec; -+ } -+ } -+#endif -+ - #if defined(HAS_LIBSTAGEFRIGHT) - if (!hint.software && CSettings::Get().GetBool("videoplayer.usestagefright")) - { -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index a4dae79..e80358f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -56,6 +56,7 @@ struct OpenMaxVideoBufferHolder; - class CDVDVideoCodecStageFright; - class CDVDMediaCodecInfo; - class CDVDVideoCodecIMXBuffer; -+class CMMALVideoBuffer; - typedef void* EGLImageKHR; - - -@@ -103,6 +104,10 @@ struct DVDVideoPicture - CDVDVideoCodecIMXBuffer *IMXBuffer; - }; - -+ struct { -+ CMMALVideoBuffer *MMALBuffer; -+ }; -+ - }; - - unsigned int iFlags; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp -new file mode 100644 -index 0000000..55b9969 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp -@@ -0,0 +1,99 @@ -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) -+ #include "config.h" -+#elif defined(TARGET_WINDOWS) -+#include "system.h" -+#endif -+ -+#if defined(HAS_MMAL) -+#include "DVDClock.h" -+#include "DVDStreamInfo.h" -+#include "DVDVideoCodecMMAL.h" -+#include "settings/Settings.h" -+#include "utils/log.h" -+ -+#define CLASSNAME "CDVDVideoCodecMMAL" -+//////////////////////////////////////////////////////////////////////////////////////////// -+//////////////////////////////////////////////////////////////////////////////////////////// -+CDVDVideoCodecMMAL::CDVDVideoCodecMMAL() -+ : m_decoder( new CMMALVideo ) -+{ -+ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); -+} -+ -+CDVDVideoCodecMMAL::~CDVDVideoCodecMMAL() -+{ -+ CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this); -+ Dispose(); -+} -+ -+bool CDVDVideoCodecMMAL::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) -+{ -+ return m_decoder->Open(hints, options, m_decoder); -+} -+ -+const char* CDVDVideoCodecMMAL::GetName(void) -+{ -+ return m_decoder ? m_decoder->GetName() : "mmal-xxx"; -+} -+ -+void CDVDVideoCodecMMAL::Dispose() -+{ -+ m_decoder->Dispose(); -+} -+ -+void CDVDVideoCodecMMAL::SetDropState(bool bDrop) -+{ -+ m_decoder->SetDropState(bDrop); -+} -+ -+int CDVDVideoCodecMMAL::Decode(uint8_t* pData, int iSize, double dts, double pts) -+{ -+ return m_decoder->Decode(pData, iSize, dts, pts); -+} -+ -+unsigned CDVDVideoCodecMMAL::GetAllowedReferences() -+{ -+ return m_decoder->GetAllowedReferences(); -+} -+ -+void CDVDVideoCodecMMAL::Reset(void) -+{ -+ m_decoder->Reset(); -+} -+ -+bool CDVDVideoCodecMMAL::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ return m_decoder->GetPicture(pDvdVideoPicture); -+} -+ -+bool CDVDVideoCodecMMAL::ClearPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ return m_decoder->ClearPicture(pDvdVideoPicture); -+} -+ -+bool CDVDVideoCodecMMAL::GetCodecStats(double &pts, int &droppedPics) -+{ -+ return m_decoder->GetCodecStats(pts, droppedPics); -+} -+ -+#endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h -new file mode 100644 -index 0000000..67aa505 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h -@@ -0,0 +1,50 @@ -+#pragma once -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#if defined(HAS_MMAL) -+ -+#include "DVDVideoCodec.h" -+#include "MMALCodec.h" -+ -+class CMMALVideo; -+class CDVDVideoCodecMMAL : public CDVDVideoCodec -+{ -+public: -+ CDVDVideoCodecMMAL(); -+ virtual ~CDVDVideoCodecMMAL(); -+ -+ // Required overrides -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); -+ virtual void Dispose(void); -+ virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); -+ virtual void Reset(void); -+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); -+ virtual unsigned GetAllowedReferences(); -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName(void); -+ virtual bool GetCodecStats(double &pts, int &droppedPics); -+ -+protected: -+ MMALVideoPtr m_decoder; -+}; -+ -+#endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -new file mode 100644 -index 0000000..d9a94d5 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -@@ -0,0 +1,1099 @@ -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) -+ #include "config.h" -+#elif defined(TARGET_WINDOWS) -+#include "system.h" -+#endif -+ -+#include "MMALCodec.h" -+ -+#include "DVDClock.h" -+#include "DVDStreamInfo.h" -+#include "windowing/WindowingFactory.h" -+#include "DVDVideoCodec.h" -+#include "utils/log.h" -+#include "utils/TimeUtils.h" -+#include "settings/Settings.h" -+#include "settings/MediaSettings.h" -+#include "ApplicationMessenger.h" -+#include "Application.h" -+#include "threads/Atomics.h" -+#include "guilib/GUIWindowManager.h" -+#include "cores/VideoRenderers/RenderFlags.h" -+#include "settings/DisplaySettings.h" -+#include "cores/VideoRenderers/RenderManager.h" -+ -+#include "linux/RBP.h" -+ -+#ifdef _DEBUG -+#define MMAL_DEBUG_VERBOSE -+#endif -+ -+#define CLASSNAME "CMMALVideoBuffer" -+ -+CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv) -+ : m_omv(omv), m_refs(0) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+#endif -+ mmal_buffer = NULL; -+ width = 0; -+ height = 0; -+ index = 0; -+ m_aspect_ratio = 0.0f; -+ m_changed_count = 0; -+ dts = DVD_NOPTS_VALUE; -+} -+ -+CMMALVideoBuffer::~CMMALVideoBuffer() -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+#endif -+} -+ -+ -+CMMALVideoBuffer* CMMALVideoBuffer::Acquire() -+{ -+ long count = AtomicIncrement(&m_refs); -+ #if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%p) ref:%ld", CLASSNAME, __func__, this, mmal_buffer, count); -+ #endif -+ (void)count; -+ return this; -+} -+ -+long CMMALVideoBuffer::Release() -+{ -+ long count = AtomicDecrement(&m_refs); -+#if defined(MMAL_DEBUG_VERBOSE) -+CLog::Log(LOGDEBUG, "%s::%s %p (%p) ref:%ld", CLASSNAME, __func__, this, mmal_buffer, count); -+#endif -+ if (count == 0) -+ { -+ m_omv->ReleaseBuffer(this); -+ } -+ return count; -+} -+ -+#undef CLASSNAME -+#define CLASSNAME "CMMALVideo" -+ -+CMMALVideo::CMMALVideo() -+{ -+ #if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+ #endif -+ pthread_mutex_init(&m_output_mutex, NULL); -+ -+ m_drop_state = false; -+ m_decoded_width = 0; -+ m_decoded_height = 0; -+ -+ m_finished = false; -+ m_pFormatName = "mmal-xxxx"; -+ -+ m_interlace_mode = MMAL_InterlaceProgressive; -+ m_startframe = false; -+ m_decoderPts = DVD_NOPTS_VALUE; -+ m_droppedPics = 0; -+ m_decode_frame_number = 1; -+ -+ m_dec = NULL; -+ m_dec_input = NULL; -+ m_dec_output = NULL; -+ m_dec_input_pool = NULL; -+ m_dec_output_pool = NULL; -+ -+ m_deint = NULL; -+ m_deint_connection = NULL; -+ -+ m_codingType = 0; -+ -+ m_changed_count = 0; -+ m_changed_count_dec = 0; -+ m_output_busy = 0; -+ m_demux_queue_length = 0; -+ m_es_format = mmal_format_alloc(); -+} -+ -+CMMALVideo::~CMMALVideo() -+{ -+ #if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this); -+ #endif -+ assert(m_finished); -+ Reset(); -+ -+ pthread_mutex_destroy(&m_output_mutex); -+ -+ if (m_deint && m_deint->control && m_deint->control->is_enabled) -+ mmal_port_disable(m_deint->control); -+ -+ if (m_dec && m_dec->control && m_dec->control->is_enabled) -+ mmal_port_disable(m_dec->control); -+ -+ if (m_dec_input && m_dec_input->is_enabled) -+ mmal_port_disable(m_dec_input); -+ m_dec_input = NULL; -+ -+ if (m_dec_output && m_dec_output->is_enabled) -+ mmal_port_disable(m_dec_output); -+ m_dec_output = NULL; -+ -+ if (m_deint_connection) -+ mmal_connection_destroy(m_deint_connection); -+ m_deint_connection = NULL; -+ -+ if (m_deint && m_deint->is_enabled) -+ mmal_component_disable(m_deint); -+ -+ if (m_dec && m_dec->is_enabled) -+ mmal_component_disable(m_dec); -+ -+ if (m_dec_input_pool) -+ mmal_pool_destroy(m_dec_input_pool); -+ m_dec_input_pool = NULL; -+ -+ if (m_dec_output_pool) -+ mmal_pool_destroy(m_dec_output_pool); -+ m_dec_output_pool = NULL; -+ -+ if (m_deint) -+ mmal_component_destroy(m_deint); -+ m_deint = NULL; -+ -+ if (m_dec) -+ mmal_component_destroy(m_dec); -+ m_dec = NULL; -+ mmal_format_free(m_es_format); -+ m_es_format = NULL; -+} -+ -+void CMMALVideo::PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+ MMAL_EVENT_FORMAT_CHANGED_T *fmt = mmal_event_format_changed_get(buffer); -+ mmal_format_copy(m_es_format, fmt->format); -+ m_changed_count++; -+ -+ if (m_es_format->es->video.crop.width && m_es_format->es->video.crop.height) -+ { -+ if (m_es_format->es->video.par.num && m_es_format->es->video.par.den) -+ m_aspect_ratio = (float)(m_es_format->es->video.par.num * m_es_format->es->video.crop.width) / (m_es_format->es->video.par.den * m_es_format->es->video.crop.height); -+ m_decoded_width = m_es_format->es->video.crop.width; -+ m_decoded_height = m_es_format->es->video.crop.height; -+ CLog::Log(LOGDEBUG, "%s::%s format changed: %dx%d %.2f frame:%d", CLASSNAME, __func__, m_decoded_width, m_decoded_height, m_aspect_ratio, m_changed_count); -+ } -+ else -+ CLog::Log(LOGERROR, "%s::%s format changed: Unexpected %dx%d", CLASSNAME, __func__, m_es_format->es->video.crop.width, m_es_format->es->video.crop.height); -+} -+ -+void CMMALVideo::dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+ MMAL_STATUS_T status; -+ -+ if (buffer->cmd == MMAL_EVENT_ERROR) -+ { -+ status = (MMAL_STATUS_T)*(uint32_t *)buffer->data; -+ CLog::Log(LOGERROR, "%s::%s Error (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ } -+ else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s format changed", CLASSNAME, __func__); -+ PortSettingsChanged(port, buffer); -+ } -+ else -+ CLog::Log(LOGERROR, "%s::%s other (cmd:%x data:%x)", CLASSNAME, __func__, buffer->cmd, *(uint32_t *)buffer->data); -+ -+ mmal_buffer_header_release(buffer); -+} -+ -+static void dec_control_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+ CMMALVideo *mmal = reinterpret_cast(port->userdata); -+ mmal->dec_control_port_cb(port, buffer); -+} -+ -+ -+static void dec_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd); -+#endif -+ mmal_buffer_header_release(buffer); -+} -+ -+ -+void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ if (!(buffer->cmd == 0 && buffer->length > 0)) -+ CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd); -+#endif -+ bool kept = false; -+ -+ if (buffer->cmd == 0) -+ { -+ if (buffer->length > 0) -+ { -+ assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); -+ double dts = DVD_NOPTS_VALUE; -+ 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) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); -+ } -+ else -+ { -+ CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); -+ m_output_busy++; -+#if defined(MMAL_DEBUG_VERBOSE) -+ 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); -+#endif -+ 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; -+ pthread_mutex_lock(&m_output_mutex); -+ m_output_ready.push(omvb); -+ pthread_mutex_unlock(&m_output_mutex); -+ kept = true; -+ } -+ } -+ } -+ else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) -+ { -+ PortSettingsChanged(port, buffer); -+ } -+ if (!kept) -+ mmal_buffer_header_release(buffer); -+} -+ -+static void dec_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) -+{ -+ CMMALVideo *mmal = reinterpret_cast(port->userdata); -+ mmal->dec_output_port_cb(port, buffer); -+} -+ -+bool CMMALVideo::change_dec_output_format() -+{ -+ MMAL_STATUS_T status; -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ -+ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type = {{ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE, sizeof( interlace_type )}}; -+ status = mmal_port_parameter_get( m_dec_output, &interlace_type.hdr ); -+ -+ if (status == MMAL_SUCCESS) -+ { -+ if (m_interlace_mode != interlace_type.eMode) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s Interlace mode %d->%d", CLASSNAME, __func__, m_interlace_mode, interlace_type.eMode); -+ m_interlace_mode = interlace_type.eMode; -+ } -+ } -+ else -+ CLog::Log(LOGERROR, "%s::%s Failed to query interlace type on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); -+ -+ // todo: if we don't disable/enable we can do this from callback -+ mmal_format_copy(m_dec_output->format, m_es_format); -+ status = mmal_port_format_commit(m_dec_output); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ return true; -+} -+ -+bool CMMALVideo::CreateDeinterlace() -+{ -+ MMAL_STATUS_T status; -+ -+ assert(!m_deint); -+ assert(m_dec_output == m_dec->output[0]); -+ -+ status = mmal_port_disable(m_dec_output); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ /* Create deinterlace filter */ -+ status = mmal_component_create("vc.ril.image_fx", &m_deint); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to create deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 1, {3}}; -+ status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ MMAL_PORT_T *m_deint_input = m_deint->input[0]; -+ m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ -+ // 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) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to connect deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ status = mmal_connection_enable(m_deint_connection); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable connection %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ mmal_format_copy(m_deint->output[0]->format, m_es_format); -+ status = mmal_port_format_commit(m_deint->output[0]); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ status = mmal_component_enable(m_deint); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_deint->output[0]->buffer_size = m_deint->output[0]->buffer_size_min; -+ m_deint->output[0]->buffer_num = m_deint->output[0]->buffer_num_recommended; -+ m_deint->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ status = mmal_port_enable(m_deint->output[0], dec_output_port_cb_static); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_output = m_deint->output[0]; -+ -+ return true; -+} -+ -+bool CMMALVideo::DestroyDeinterlace() -+{ -+ MMAL_STATUS_T status; -+ -+ assert(m_deint); -+ assert(m_dec_output == m_deint->output[0]); -+ -+ status = mmal_port_disable(m_dec_output); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ status = mmal_connection_destroy(m_deint_connection); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to destroy deinterlace connection (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ m_deint_connection = NULL; -+ -+ status = mmal_component_disable(m_deint); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ status = mmal_component_destroy(m_deint); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to destroy deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ m_deint = NULL; -+ -+ m_dec->output[0]->buffer_size = m_dec->output[0]->buffer_size_min; -+ m_dec->output[0]->buffer_num = m_dec->output[0]->buffer_num_recommended; -+ m_dec->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ status = mmal_port_enable(m_dec->output[0], dec_output_port_cb_static); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_output = m_dec->output[0]; -+ return true; -+} -+ -+bool CMMALVideo::SendCodecConfigData() -+{ -+ MMAL_STATUS_T status; -+ if (!m_dec_input_pool) -+ return true; -+ // send code config data -+ MMAL_BUFFER_HEADER_T *buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500); -+ if (!buffer) -+ { -+ CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); -+ return false; -+ } -+ -+ mmal_buffer_header_reset(buffer); -+ buffer->cmd = 0; -+ buffer->length = std::min(m_hints.extrasize, buffer->alloc_size); -+ memcpy(buffer->data, m_hints.extradata, buffer->length); -+ buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_CONFIG; -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d flags:%x", CLASSNAME, __func__, buffer, buffer->length, buffer->flags); -+#endif -+ status = mmal_port_send_buffer(m_dec_input, buffer); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ return true; -+} -+ -+bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself) -+{ -+ #if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s usemmal:%d software:%d %dx%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.usemmal"), hints.software, hints.width, hints.height); -+ #endif -+ -+ // we always qualify even if DVDFactoryCodec does this too. -+ if (!CSettings::Get().GetBool("videoplayer.usemmal") || hints.software) -+ return false; -+ -+ m_hints = hints; -+ MMAL_STATUS_T status; -+ MMAL_PARAMETER_BOOLEAN_T error_concealment; -+ -+ m_myself = myself; -+ m_decoded_width = hints.width; -+ m_decoded_height = hints.height; -+ -+ // use aspect in stream if available -+ if (m_hints.forced_aspect) -+ m_aspect_ratio = m_hints.aspect; -+ else -+ m_aspect_ratio = 0.0; -+ -+ switch (hints.codec) -+ { -+ case AV_CODEC_ID_H264: -+ // H.264 -+ m_codingType = MMAL_ENCODING_H264; -+ m_pFormatName = "mmal-h264"; -+ break; -+ case AV_CODEC_ID_H263: -+ case AV_CODEC_ID_MPEG4: -+ // MPEG-4, DivX 4/5 and Xvid compatible -+ m_codingType = MMAL_ENCODING_MP4V; -+ m_pFormatName = "mmal-mpeg4"; -+ break; -+ case AV_CODEC_ID_MPEG1VIDEO: -+ case AV_CODEC_ID_MPEG2VIDEO: -+ // MPEG-2 -+ m_codingType = MMAL_ENCODING_MP2V; -+ m_pFormatName = "mmal-mpeg2"; -+ break; -+ case AV_CODEC_ID_VP6: -+ // this form is encoded upside down -+ // fall through -+ case AV_CODEC_ID_VP6F: -+ case AV_CODEC_ID_VP6A: -+ // VP6 -+ m_codingType = MMAL_ENCODING_VP6; -+ m_pFormatName = "mmal-vp6"; -+ break; -+ case AV_CODEC_ID_VP8: -+ // VP8 -+ m_codingType = MMAL_ENCODING_VP8; -+ m_pFormatName = "mmal-vp8"; -+ break; -+ case AV_CODEC_ID_THEORA: -+ // theora -+ m_codingType = MMAL_ENCODING_THEORA; -+ m_pFormatName = "mmal-theora"; -+ break; -+ case AV_CODEC_ID_MJPEG: -+ case AV_CODEC_ID_MJPEGB: -+ // mjpg -+ m_codingType = MMAL_ENCODING_MJPEG; -+ m_pFormatName = "mmal-mjpg"; -+ break; -+ case AV_CODEC_ID_VC1: -+ case AV_CODEC_ID_WMV3: -+ // VC-1, WMV9 -+ m_codingType = MMAL_ENCODING_WVC1; -+ m_pFormatName = "mmal-vc1"; -+ break; -+ default: -+ CLog::Log(LOGERROR, "%s::%s : Video codec unknown: %x", CLASSNAME, __func__, hints.codec); -+ return false; -+ break; -+ } -+ -+ if ( (m_codingType == MMAL_ENCODING_MP2V && !g_RBP.GetCodecMpg2() ) || -+ (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) -+ { -+ CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported", CLASSNAME, __func__, m_pFormatName); -+ return false; -+ } -+ -+ // initialize mmal. -+ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &m_dec); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to create MMAL decoder component %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ status = mmal_port_enable(m_dec->control, dec_control_port_cb_static); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable decoder control port %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_input = m_dec->input[0]; -+ -+ m_dec_input->format->type = MMAL_ES_TYPE_VIDEO; -+ m_dec_input->format->encoding = m_codingType; -+ if (m_hints.width && m_hints.height) -+ { -+ m_dec_input->format->es->video.crop.width = m_hints.width; -+ m_dec_input->format->es->video.crop.height = m_hints.height; -+ -+ m_dec_input->format->es->video.width = ALIGN_UP(m_hints.width, 32); -+ m_dec_input->format->es->video.height = ALIGN_UP(m_hints.height, 16); -+ } -+ m_dec_input->format->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; -+ -+ error_concealment.hdr.id = MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT; -+ error_concealment.hdr.size = sizeof(MMAL_PARAMETER_BOOLEAN_T); -+ error_concealment.enable = MMAL_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)); -+ -+ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, 5); -+ 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_format_commit(m_dec_input); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to commit format for decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); -+ return false; -+ } -+ m_dec_input->buffer_size = m_dec_input->buffer_size_recommended; -+ m_dec_input->buffer_num = m_dec_input->buffer_num_recommended; -+ -+ m_dec_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ status = mmal_port_enable(m_dec_input, dec_input_port_cb); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_output = m_dec->output[0]; -+ -+ // set up initial decoded frame format - will likely change from this -+ m_dec_output->format->encoding = MMAL_ENCODING_OPAQUE; -+ mmal_format_copy(m_es_format, m_dec_output->format); -+ -+ status = mmal_port_format_commit(m_dec_output); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_output->buffer_size = m_dec_output->buffer_size_min; -+ m_dec_output->buffer_num = m_dec_output->buffer_num_recommended; -+ m_dec_output->userdata = (struct MMAL_PORT_USERDATA_T *)this; -+ status = mmal_port_enable(m_dec_output, dec_output_port_cb_static); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ status = mmal_component_enable(m_dec); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to enable decoder component %s (status=%x %s)", CLASSNAME, __func__, m_dec->name, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_input_pool = mmal_pool_create(m_dec_input->buffer_num, m_dec_input->buffer_size); -+ if (!m_dec_input_pool) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ m_dec_output_pool = mmal_pool_create(m_dec_output->buffer_num, m_dec_output->buffer_size); -+ if(!m_dec_output_pool) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed to create pool for decode output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return false; -+ } -+ -+ if (!SendCodecConfigData()) -+ return false; -+ -+ m_drop_state = false; -+ m_startframe = false; -+ -+ return true; -+} -+ -+void CMMALVideo::Dispose() -+{ -+ // we are happy to exit, but let last shared pointer being deleted trigger the destructor -+ bool done = false; -+ Reset(); -+ pthread_mutex_lock(&m_output_mutex); -+ if (!m_output_busy) -+ done = true; -+ m_finished = true; -+ pthread_mutex_unlock(&m_output_mutex); -+ #if defined(MMAL_DEBUG_VERBOSE) -+ 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); -+ #endif -+ if (done) -+ { -+ assert(m_dts_queue.empty()); -+ m_myself.reset(); -+ } -+} -+ -+void CMMALVideo::SetDropState(bool bDrop) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ if (m_drop_state != bDrop) -+ CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)", CLASSNAME, __func__, bDrop); -+#endif -+ m_drop_state = bDrop; -+ if (m_drop_state) -+ { -+ 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; -+ } -+ } -+} -+ -+int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) -+{ -+ #if defined(MMAL_DEBUG_VERBOSE) -+ //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); -+ #endif -+ -+ unsigned int demuxer_bytes = 0; -+ uint8_t *demuxer_content = NULL; -+ MMAL_BUFFER_HEADER_T *buffer; -+ MMAL_STATUS_T status; -+ -+ while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer) -+ Recycle(buffer); -+ // we need to queue then de-queue the demux packet, seems silly but -+ // mmal might not have an input buffer available when we are called -+ // and we must store the demuxer packet and try again later. -+ // try to send any/all demux packets to mmal decoder. -+ unsigned space = mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size; -+ if (pData && m_demux_queue.empty() && space >= (unsigned int)iSize) -+ { -+ demuxer_bytes = iSize; -+ demuxer_content = pData; -+ } -+ else if (pData && iSize) -+ { -+ mmal_demux_packet demux_packet; -+ demux_packet.dts = dts; -+ demux_packet.pts = pts; -+ demux_packet.size = iSize; -+ demux_packet.buff = new uint8_t[iSize]; -+ memcpy(demux_packet.buff, pData, iSize); -+ m_demux_queue_length += demux_packet.size; -+ m_demux_queue.push(demux_packet); -+ } -+ -+ uint8_t *buffer_to_free = NULL; -+ -+ while (1) -+ { -+ while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer) -+ Recycle(buffer); -+ -+ space = mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size; -+ if (!demuxer_bytes && !m_demux_queue.empty()) -+ { -+ mmal_demux_packet &demux_packet = m_demux_queue.front(); -+ if (space >= (unsigned int)demux_packet.size) -+ { -+ // need to lock here to retrieve an input buffer and pop the queue -+ m_demux_queue_length -= demux_packet.size; -+ m_demux_queue.pop(); -+ demuxer_bytes = (unsigned int)demux_packet.size; -+ demuxer_content = demux_packet.buff; -+ buffer_to_free = demux_packet.buff; -+ dts = demux_packet.dts; -+ pts = demux_packet.pts; -+ } -+ } -+ if (demuxer_content) -+ { -+ // 500ms timeout -+ buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500); -+ if (!buffer) -+ { -+ CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__); -+ return VC_ERROR; -+ } -+ -+ mmal_buffer_header_reset(buffer); -+ buffer->cmd = 0; -+ 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; -+ buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes; -+ buffer->user_data = (void *)m_decode_frame_number; -+ -+ // 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; -+ -+ if (demuxer_bytes == 0) -+ buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; -+ -+ #if defined(MMAL_DEBUG_VERBOSE) -+ 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); -+ #endif -+ assert((int)buffer->length > 0); -+ status = mmal_port_send_buffer(m_dec_input, buffer); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return VC_ERROR; -+ } -+ -+ if (demuxer_bytes == 0) -+ { -+ m_decode_frame_number++; -+ m_startframe = true; -+ if (m_drop_state) -+ { -+ m_droppedPics += m_deint ? 2:1; -+ } -+ else -+ { -+ // only push if we are successful with feeding mmal -+ pthread_mutex_lock(&m_output_mutex); -+ m_dts_queue.push(dts); -+ if (m_deint) -+ m_dts_queue.push(DVD_NOPTS_VALUE); -+ //assert(m_dts_queue.size() < 5000); -+ pthread_mutex_unlock(&m_output_mutex); -+ } -+ if (m_changed_count_dec != m_changed_count) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s format changed frame:%d(%d)", CLASSNAME, __func__, m_changed_count_dec, m_changed_count); -+ m_changed_count_dec = m_changed_count; -+ if (!change_dec_output_format()) -+ { -+ CLog::Log(LOGERROR, "%s::%s - change_dec_output_format() failed", CLASSNAME, __func__); -+ return VC_ERROR; -+ } -+ } -+ EDEINTERLACEMODE deinterlace_request = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; -+ -+ bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive; -+ -+ if (deinterlace_request == VS_DEINTERLACEMODE_OFF) -+ deinterlace = false; -+ else if (deinterlace_request == VS_DEINTERLACEMODE_FORCE) -+ deinterlace = true; -+ -+ if (!deinterlace && m_deint) -+ DestroyDeinterlace(); -+ else if (deinterlace && !m_deint) -+ CreateDeinterlace(); -+ -+ if (buffer_to_free) -+ { -+ delete [] buffer_to_free; -+ buffer_to_free = NULL; -+ demuxer_content = NULL; -+ continue; -+ } -+ while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer) -+ Recycle(buffer); -+ } -+ } -+ if (!demuxer_bytes) -+ break; -+ } -+ int ret = 0; -+ if (!m_output_ready.empty()) -+ { -+ #if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - got output picture:%d", CLASSNAME, __func__, m_output_ready.size()); -+ #endif -+ ret |= VC_PICTURE; -+ } -+ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length) -+ { -+ #if defined(MMAL_DEBUG_VERBOSE) -+ 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); -+ #endif -+ ret |= VC_BUFFER; -+ } -+ if (!ret) -+ { -+ CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%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); -+ Sleep(10); // otherwise we busy spin -+ } -+ return ret; -+} -+ -+void CMMALVideo::Reset(void) -+{ -+ #if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+ #endif -+ -+ if (m_dec_input) -+ mmal_port_disable(m_dec_input); -+ if (m_deint_connection) -+ mmal_connection_disable(m_deint_connection); -+ if (m_dec_output) -+ mmal_port_disable(m_dec_output); -+ if (m_dec_input) -+ mmal_port_enable(m_dec_input, dec_input_port_cb); -+ if (m_deint_connection) -+ mmal_connection_enable(m_deint_connection); -+ if (m_dec_output) -+ 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); -+ 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; -+ pthread_mutex_unlock(&m_output_mutex); -+ if (!old_drop_state) -+ SetDropState(false); -+ -+ SendCodecConfigData(); -+ -+ m_startframe = false; -+ m_decoderPts = DVD_NOPTS_VALUE; -+ m_droppedPics = 0; -+ m_decode_frame_number = 1; -+} -+ -+ -+void CMMALVideo::ReturnBuffer(CMMALVideoBuffer *buffer) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_output_busy); -+#endif -+ -+ mmal_buffer_header_release(buffer->mmal_buffer); -+} -+ -+void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer) -+{ -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, buffer); -+#endif -+ -+ MMAL_STATUS_T status; -+ mmal_buffer_header_reset(buffer); -+ buffer->cmd = 0; -+ #if defined(MMAL_DEBUG_VERBOSE) -+ 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); -+ #endif -+ status = mmal_port_send_buffer(m_dec_output, buffer); -+ if (status != MMAL_SUCCESS) -+ { -+ CLog::Log(LOGERROR, "%s::%s - Failed send buffer to decoder output port (status=0%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); -+ return; -+ } -+} -+ -+void CMMALVideo::ReleaseBuffer(CMMALVideoBuffer *buffer) -+{ -+ // remove from busy list -+ pthread_mutex_lock(&m_output_mutex); -+ assert(m_output_busy > 0); -+ m_output_busy--; -+ pthread_mutex_unlock(&m_output_mutex); -+ ReturnBuffer(buffer); -+ bool done = false; -+ pthread_mutex_lock(&m_output_mutex); -+ if (m_finished && !m_output_busy) -+ done = true; -+ pthread_mutex_unlock(&m_output_mutex); -+ if (done) -+ m_myself.reset(); -+ #if defined(MMAL_DEBUG_VERBOSE) -+ 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); -+ #endif -+ delete buffer; -+} -+ -+bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ if (!m_output_ready.empty()) -+ { -+ CMMALVideoBuffer *buffer; -+ // fetch a output buffer and pop it off the ready list -+ pthread_mutex_lock(&m_output_mutex); -+ buffer = m_output_ready.front(); -+ m_output_ready.pop(); -+ pthread_mutex_unlock(&m_output_mutex); -+ -+ assert(buffer->mmal_buffer); -+ memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); -+ pDvdVideoPicture->format = RENDER_FMT_MMAL; -+ pDvdVideoPicture->MMALBuffer = buffer; -+ pDvdVideoPicture->color_range = 0; -+ pDvdVideoPicture->color_matrix = 4; -+ pDvdVideoPicture->iWidth = buffer->width ? buffer->width : m_decoded_width; -+ pDvdVideoPicture->iHeight = buffer->height ? buffer->height : m_decoded_height; -+ pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; -+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; -+ //CLog::Log(LOGDEBUG, "%s::%s - %dx%d %dx%d %dx%d %dx%d %f,%f", CLASSNAME, __func__, pDvdVideoPicture->iWidth, pDvdVideoPicture->iHeight, pDvdVideoPicture->iDisplayWidth, pDvdVideoPicture->iDisplayHeight, m_decoded_width, m_decoded_height, buffer->width, buffer->height, buffer->m_aspect_ratio, m_hints.aspect); -+ -+ if (buffer->m_aspect_ratio > 0.0) -+ { -+ pDvdVideoPicture->iDisplayWidth = ((int)lrint(pDvdVideoPicture->iHeight * buffer->m_aspect_ratio)) & -3; -+ if (pDvdVideoPicture->iDisplayWidth > pDvdVideoPicture->iWidth) -+ { -+ pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; -+ pDvdVideoPicture->iDisplayHeight = ((int)lrint(pDvdVideoPicture->iWidth / buffer->m_aspect_ratio)) & -3; -+ } -+ } -+ -+ // timestamp is in microseconds -+ pDvdVideoPicture->dts = 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(); -+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x MMALBuffer:%p mmal_buffer:%p", CLASSNAME, __func__, -+ pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6, -+ pDvdVideoPicture->iFlags, buffer->mmal_buffer->flags, pDvdVideoPicture->MMALBuffer, pDvdVideoPicture->MMALBuffer->mmal_buffer); -+#endif -+ assert(!(buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); -+ } -+ else -+ { -+ CLog::Log(LOGERROR, "%s::%s - called but m_output_ready is empty", CLASSNAME, __func__); -+ return false; -+ } -+ -+ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) -+ m_decoderPts = pDvdVideoPicture->pts; -+ else -+ m_decoderPts = pDvdVideoPicture->dts; // xxx is DVD_NOPTS_VALUE better? -+ -+ return true; -+} -+ -+bool CMMALVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture) -+{ -+ if (pDvdVideoPicture->format == RENDER_FMT_MMAL) -+ { -+#if defined(MMAL_DEBUG_VERBOSE) -+ CLog::Log(LOGDEBUG, "%s::%s - %p (%p)", CLASSNAME, __func__, pDvdVideoPicture->MMALBuffer, pDvdVideoPicture->MMALBuffer->mmal_buffer); -+#endif -+ pDvdVideoPicture->MMALBuffer->Release(); -+ } -+ memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture); -+ return true; -+} -+ -+bool CMMALVideo::GetCodecStats(double &pts, int &droppedPics) -+{ -+ pts = m_decoderPts; -+ droppedPics = m_droppedPics; -+ m_droppedPics = 0; -+#if defined(MMAL_DEBUG_VERBOSE) -+ //CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics); -+#endif -+ return true; -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -new file mode 100644 -index 0000000..ef83a65 ---- /dev/null -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -@@ -0,0 +1,157 @@ -+#pragma once -+/* -+ * Copyright (C) 2010-2013 Team XBMC -+ * http://xbmc.org -+ * -+ * This Program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ * -+ * This Program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with XBMC; see the file COPYING. If not, see -+ * . -+ * -+ */ -+ -+#if defined(HAS_MMAL) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cores/dvdplayer/DVDStreamInfo.h" -+#include "DVDVideoCodec.h" -+#include "threads/Event.h" -+#include "xbmc/settings/VideoSettings.h" -+ -+#include -+#include -+#include -+#include "utils/StdString.h" -+#include "guilib/Geometry.h" -+#include "rendering/RenderSystem.h" -+ -+class CMMALVideo; -+typedef boost::shared_ptr MMALVideoPtr; -+ -+// a mmal video frame -+class CMMALVideoBuffer -+{ -+public: -+ CMMALVideoBuffer(CMMALVideo *omv); -+ virtual ~CMMALVideoBuffer(); -+ -+ MMAL_BUFFER_HEADER_T *mmal_buffer; -+ int width; -+ int height; -+ float m_aspect_ratio; -+ int index; -+ double dts; -+ uint32_t m_changed_count; -+ // reference counting -+ CMMALVideoBuffer* Acquire(); -+ long Release(); -+ CMMALVideo *m_omv; -+ long m_refs; -+private: -+}; -+ -+class CMMALVideo -+{ -+ typedef struct mmal_demux_packet { -+ uint8_t *buff; -+ int size; -+ double dts; -+ double pts; -+ } mmal_demux_packet; -+ -+public: -+ CMMALVideo(); -+ virtual ~CMMALVideo(); -+ -+ // Required overrides -+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself); -+ virtual void Dispose(void); -+ virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); -+ virtual void Reset(void); -+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); -+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); -+ virtual unsigned GetAllowedReferences() { return 2; } -+ virtual void SetDropState(bool bDrop); -+ virtual const char* GetName(void) { return (const char*)m_pFormatName; } -+ virtual bool GetCodecStats(double &pts, int &droppedPics); -+ -+ // MMAL decoder callback routines. -+ void ReleaseBuffer(CMMALVideoBuffer *buffer); -+ void Recycle(MMAL_BUFFER_HEADER_T *buffer); -+ -+ // MMAL decoder callback routines. -+ void dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); -+ void dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); -+ uint32_t m_changed_count; -+ uint32_t m_changed_count_dec; -+ -+protected: -+ void QueryCodec(void); -+ void ReturnBuffer(CMMALVideoBuffer *buffer); -+ bool CreateDeinterlace(); -+ bool DestroyDeinterlace(); -+ -+ // Video format -+ bool m_drop_state; -+ int m_decoded_width; -+ int m_decoded_height; -+ unsigned int m_egl_buffer_count; -+ bool m_finished; -+ float m_aspect_ratio; -+ const char *m_pFormatName; -+ MMALVideoPtr m_myself; -+ -+ std::queue m_dts_queue; -+ std::queue m_demux_queue; -+ unsigned m_demux_queue_length; -+ -+ // mmal output buffers (video frames) -+ pthread_mutex_t m_output_mutex; -+ int m_output_busy; -+ std::queue m_output_ready; -+ std::vector m_output_buffers; -+ -+ // initialize mmal and get decoder component -+ bool Initialize( const CStdString &decoder_name); -+ void PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); -+ bool SendCodecConfigData(); -+ -+ CDVDStreamInfo m_hints; -+ // Components -+ MMAL_INTERLACETYPE_T m_interlace_mode; -+ bool m_startframe; -+ unsigned int m_decode_frame_number; -+ double m_decoderPts; -+ unsigned int m_droppedPics; -+ -+ MMAL_COMPONENT_T *m_dec; -+ MMAL_PORT_T *m_dec_input; -+ MMAL_PORT_T *m_dec_output; -+ MMAL_POOL_T *m_dec_input_pool; -+ MMAL_POOL_T *m_dec_output_pool; -+ -+ MMAL_ES_FORMAT_T *m_es_format; -+ MMAL_COMPONENT_T *m_deint; -+ MMAL_CONNECTION_T *m_deint_connection; -+ -+ MMAL_FOURCC_T m_codingType; -+ bool change_dec_output_format(); -+}; -+ -+// defined(HAS_MMAL) -+#endif -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -index 50dc8b7..6f5d3e8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in -@@ -37,6 +37,11 @@ ifeq (@USE_LIBSTAGEFRIGHT@,1) - SRCS += DVDVideoCodecStageFright.cpp - endif - -+ifeq (@USE_MMAL@,1) -+SRCS += MMALCodec.cpp -+SRCS += DVDVideoCodecMMAL.cpp -+endif -+ - LIB=Video.a - - include @abs_top_srcdir@/Makefile.include -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index d3d37d1..374f4bd 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1016,6 +1016,7 @@ static std::string GetRenderFormatName(ERenderFormat format) - case RENDER_FMT_BYPASS: return "BYPASS"; - case RENDER_FMT_MEDIACODEC:return "MEDIACODEC"; - case RENDER_FMT_IMXMAP: return "IMXMAP"; -+ case RENDER_FMT_MMAL: return "MMAL"; - case RENDER_FMT_NONE: return "NONE"; - } - return "UNKNOWN"; - -From 2cb71f73ec0abbae7918eb3f7096883362eea538 Mon Sep 17 00:00:00 2001 +From 551b00e9f67182d167102565ee7cbfe58619eb80 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 10 Sep 2014 22:07:21 +0100 -Subject: [PATCH 030/104] [mmal] Allow mmal codec for dvd stills +Subject: [PATCH 28/99] [mmal] Allow mmal codec for dvd stills --- xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 4 ++++ @@ -7415,10 +3950,11 @@ index f139433..4183a2b 100644 { // If dvd is an mpeg2 and hint.stills -From fb100256efd93aa41acdd8d31b62ffdee23940d9 Mon Sep 17 00:00:00 2001 + +From 91b24766d05447e555bba1597f1c3ed5f3bc9120 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 2 Aug 2014 17:47:38 +0100 -Subject: [PATCH 032/104] [VideoReferenceClock] Add OMX support +Subject: [PATCH 30/99] [VideoReferenceClock] Add OMX support --- xbmc/linux/RBP.cpp | 34 ++++++++++++++++++++++++ @@ -7617,10 +4153,10 @@ index 6027031..2dabac1 100644 }; -From ed081e7ab0e9883b99c2c9150b91085f190ba3d7 Mon Sep 17 00:00:00 2001 +From a0daccf59266bc73f53cd2a228ff7ee038b96ae4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 12 Aug 2014 00:03:18 +0100 -Subject: [PATCH 033/104] videoreferenceclock: Boost priority +Subject: [PATCH 31/99] videoreferenceclock: Boost priority --- xbmc/video/VideoReferenceClock.cpp | 3 +++ @@ -7641,10 +4177,10 @@ index 916a15c..c491d29 100644 //register callback m_D3dCallback.Reset(); -From 4cea68e319efc35e6b5f1d73bc43a7a3571052a2 Mon Sep 17 00:00:00 2001 +From 05f051804af616f5b49eace7bd2317a96294d10f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 5 Feb 2014 11:46:33 +0000 -Subject: [PATCH 034/104] [rbp/settings] Allow av sync type to be enabled +Subject: [PATCH 32/99] [rbp/settings] Allow av sync type to be enabled It works for dvdplayer --- @@ -7670,11 +4206,12 @@ index 570798b..e09d974 100644 false -From caa29bc74b7d90435b7dd5061125474812cd83b9 Mon Sep 17 00:00:00 2001 + +From 650a56964c98baebeb2197d2fdd7402677347ef9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 16 Apr 2014 21:18:06 +0100 -Subject: [PATCH 039/104] [omxplayer] Don't propagate 3d flags based on - supported 3d modes +Subject: [PATCH 37/99] [omxplayer] Don't propagate 3d flags based on supported + 3d modes --- xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 29 ++++------------------------- @@ -7726,10 +4263,10 @@ index 2c25fd9..c2bd788 100644 unsigned int iDisplayWidth = width; unsigned int iDisplayHeight = height; -From d0f2d2ad29151d1720b6918940d0cedda98800ab Mon Sep 17 00:00:00 2001 +From 44a8c528fd577b270aeb627e28d5620b514f0328 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 Apr 2014 13:00:52 +0100 -Subject: [PATCH 040/104] [graphics] Don't set stereo mode based on resolution +Subject: [PATCH 38/99] [graphics] Don't set stereo mode based on resolution The resolution change should follow stereo mode --- @@ -7787,10 +4324,10 @@ index 5bffdf5..4be1c8b 100644 m_iScreenWidth = info_mod.iWidth; -From 62c3a2aa13dc560c9910dcc881a8dc2df2620158 Mon Sep 17 00:00:00 2001 +From 1160a07cd80a264d5ddef8b9a98199c749cf498e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 Apr 2014 13:01:51 +0100 -Subject: [PATCH 041/104] [graphics] Allow switching to a more suitable 3D +Subject: [PATCH 39/99] [graphics] Allow switching to a more suitable 3D resolution --- @@ -7876,10 +4413,10 @@ index 0a27643..ef5bc74 100644 void ResetOverscan(RESOLUTION_INFO &resinfo); void ResetScreenParameters(RESOLUTION res); -From 3678d7821fcfee38da05934a0442d5efe968a39e Mon Sep 17 00:00:00 2001 +From 01d7fa85b9e1c7772e03c7ed43b1f02e9112da02 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 Apr 2014 13:38:55 +0100 -Subject: [PATCH 042/104] [3D] Support switching to 3D resolutions +Subject: [PATCH 40/99] [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. @@ -7961,10 +4498,10 @@ index 83c3adb..8076e76 100644 return current; } -From 079a31fc0821af31e72b879c180fb5e2508fa80d Mon Sep 17 00:00:00 2001 +From 600c839947ddeb8328c1c21feea3794bd46b2050 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 23 Apr 2014 00:05:07 +0100 -Subject: [PATCH 043/104] [graphics] Make pixel ratio for 3d modes consistent +Subject: [PATCH 41/99] [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. @@ -8167,10 +4704,10 @@ index c58c28a..bf1e589 100644 AddUniqueResolution(res2, resolutions); -From 4c1122d41c5b6bafba4b244f4887a9a555469326 Mon Sep 17 00:00:00 2001 +From 3f99e3d224941891c549d9169e13d844e1bc5b66 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 10 Aug 2014 16:45:16 +0100 -Subject: [PATCH 044/104] filesystem: Make support of browsing into archives +Subject: [PATCH 42/99] 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. @@ -8186,25 +4723,25 @@ Add a settings option to enable this feature and default to disabled on Pi 4 files changed, 29 insertions(+) diff --git a/language/English/strings.po b/language/English/strings.po -index ddd8ce8..30b3566 100755 +index f8e7820..260ac22 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15905,3 +15905,13 @@ msgstr "" - msgctxt "#37030" - msgid "Unlimited" +@@ -15931,3 +15931,13 @@ msgstr "" + msgctxt "#37031" + msgid "Specifies how Blu-rays should be opened/played back. Disc menus are not fully supported yet and may cause problems." msgstr "" + +#: system/settings/settings.xml -+msgctxt "#37031" ++msgctxt "#38020" +msgid "Support browsing into archives" +msgstr "" + +#: system/settings/settings.xml -+msgctxt "#37032" ++msgctxt "#38021" +msgid "Allow viewing and playing files in archives (e.g. zip, rar)" +msgstr "" diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index e09d974..49706c0 100644 +index e09d974..9cc4fd2 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -1,5 +1,15 @@ @@ -8213,7 +4750,7 @@ index e09d974..49706c0 100644 +
+ + -+ ++ + false + + @@ -8224,14 +4761,14 @@ index e09d974..49706c0 100644 diff --git a/system/settings/settings.xml b/system/settings/settings.xml -index 57fddfd..57dec06 100644 +index 304c308..ef6c141 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -226,6 +226,11 @@ false -+ ++ + 1 + true + @@ -8269,10 +4806,10 @@ index 2fd8777..3b294cd 100644 { // XBMC Smart playlist - just XML renamed to XSP // read the name of the playlist in -From 1160ab085404320b446656c6b205debda2da9b70 Mon Sep 17 00:00:00 2001 +From 7d00ed3ce60079e9309d42e753c008edb5e6458f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 11 Aug 2014 22:56:13 +0100 -Subject: [PATCH 046/104] [omxplayer] Add acceleration option to choose +Subject: [PATCH 44/99] [omxplayer] Add acceleration option to choose omxplayer/dvdplayer automatically --- @@ -8282,11 +4819,11 @@ Subject: [PATCH 046/104] [omxplayer] Add acceleration option to choose 3 files changed, 77 insertions(+) diff --git a/language/English/strings.po b/language/English/strings.po -index 30b3566..73213b8 100755 +index 260ac22..160e83c 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15915,3 +15915,13 @@ msgstr "" - msgctxt "#37032" +@@ -15941,3 +15941,13 @@ msgstr "" + msgctxt "#38021" msgid "Allow viewing and playing files in archives (e.g. zip, rar)" msgstr "" + @@ -8300,7 +4837,7 @@ index 30b3566..73213b8 100755 +msgid "Uses codec information and audio setting to choose dvdplayer or omxplayer as appropriate" +msgstr "" diff --git a/system/settings/settings.xml b/system/settings/settings.xml -index 57dec06..9a4cefb 100644 +index ef6c141..14f18d9 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -751,6 +751,15 @@ @@ -8320,10 +4857,10 @@ index 57dec06..9a4cefb 100644 HAS_OMXPLAYER diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index c2654c3b..6547880 100644 +index bbcf514..c89aae2 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp -@@ -490,6 +490,62 @@ void CSelectionStreams::Update(CDVDInputStream* input, CDVDDemux* demuxer) +@@ -490,6 +490,62 @@ void CSelectionStreams::Update(CDVDInputStream* input, CDVDDemux* demuxer, std:: void CDVDPlayer::CreatePlayers() { @@ -8396,10 +4933,10 @@ index c2654c3b..6547880 100644 // allow renderer to switch to fullscreen if requested m_dvdPlayerVideo->EnableFullscreen(m_PlayerOptions.fullscreen); -From e9f29c552f27e4c69641a33fa501194b93cc8736 Mon Sep 17 00:00:00 2001 +From 430ad54c3e2921a8e4f6d3a328a056b296b87517 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 12 Aug 2014 16:51:18 +0100 -Subject: [PATCH 047/104] AE: Add some logging for suspend/resume +Subject: [PATCH 45/99] AE: Add some logging for suspend/resume --- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 5 +++++ @@ -8470,11 +5007,11 @@ index 7e85441..a73dd0a 100644 } -From f630e36058272d201b7973e77d9418d19ff0f3aa Mon Sep 17 00:00:00 2001 +From 017e54e4c9aff11a199ed0a82ea8354f5aad0f7b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 9 Jul 2014 22:45:43 +0100 -Subject: [PATCH 048/104] [rbp] Make cachemembuffersize default depend on - memory size +Subject: [PATCH 46/99] [rbp] Make cachemembuffersize default depend on memory + size --- xbmc/linux/RBP.cpp | 5 +++++ @@ -8512,7 +5049,7 @@ index 11376fc..b67fbb1 100644 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 237e903..8e32a68 100644 +index 888ede3..2e2854f 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -363,7 +363,12 @@ void CAdvancedSettings::Initialize() @@ -8529,10 +5066,11 @@ index 237e903..8e32a68 100644 // the following setting determines the readRate of a player data // as multiply of the default data read rate -From 374062d2bfe2a8850b4ec58d193d2e37db64c1c8 Mon Sep 17 00:00:00 2001 + +From 3ea42987e583c6fe2867a37dea15ef8d4a45bb9b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 16 Jun 2014 19:06:00 +0100 -Subject: [PATCH 050/104] [experimental] Disable quiet-noise generation +Subject: [PATCH 48/99] [experimental] Disable quiet-noise generation --- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp | 2 ++ @@ -8559,10 +5097,10 @@ index 488a0df..d9f4a43 100644 void CActiveAESink::SetSilenceTimer() -From cce8c49bfaaf32a918c5f081dd4487089c525df1 Mon Sep 17 00:00:00 2001 +From 2cd450a1ebf8fc2d20cda35b9b1e60fd1306fbe3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 30 May 2014 14:58:43 +0100 -Subject: [PATCH 051/104] [settings] Experiment: Report DESKTOP resolution in +Subject: [PATCH 49/99] [settings] Experiment: Report DESKTOP resolution in video settings --- @@ -8584,10 +5122,10 @@ index 6902f83..50c5f97 100644 StringUtils::Format("%dx%d%s", resolution->width, resolution->height, ModeFlagsToString(resolution->flags, false).c_str()), -From c48fb57d3b3f702568d9bf52a3e6c76561317240 Mon Sep 17 00:00:00 2001 +From e6de67283fb1e636afc9c8edd08f81831a79bc2e Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 18:24:42 +0200 -Subject: [PATCH 052/104] Added some vc_tv_* functions that were missing in +Subject: [PATCH 50/99] Added some vc_tv_* functions that were missing in DllBCM. --- @@ -8622,10 +5160,10 @@ index b92fdb8..9c7e293 100644 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 2b0cf26e90dea818424ed6f8f71dcdf0258b7542 Mon Sep 17 00:00:00 2001 +From 15d4b97c14f412f8cc5f0315a50cfd8033009846 Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 18:29:03 +0200 -Subject: [PATCH 053/104] Added private utility function to map a float display +Subject: [PATCH 51/99] Added private utility function to map a float display aspect, to the respective SDTV_ASPECT_* enum value. --- @@ -8663,10 +5201,10 @@ index bf1e589..518a87d 100644 bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &resolutions) -From 9f9c2344327e30a18c73b8f3f6cf5ab952964b66 Mon Sep 17 00:00:00 2001 +From 053a9bd554194f3e2cfcb2e453d74807bf5e2496 Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 19:50:58 +0200 -Subject: [PATCH 054/104] Changed SDTV resolutions to be treated similarly to +Subject: [PATCH 52/99] 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. @@ -8763,10 +5301,10 @@ index 59401f5..a0acb1a 100644 int m_width; int m_height; -From f1136389343982869ed389bf12536ee44b1effa0 Mon Sep 17 00:00:00 2001 +From 3cb062892523c15718a1fb577e1928ecfa1fe4bc Mon Sep 17 00:00:00 2001 From: macrule Date: Thu, 11 Apr 2013 19:54:59 +0200 -Subject: [PATCH 055/104] Added methods SuspendVideoOutput() and +Subject: [PATCH 53/99] 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. @@ -8830,12 +5368,12 @@ index 9dc39d5..ca36082 100644 CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI() { -From 0634c431adb611ee08deddc65aa5cadc11bc39a4 Mon Sep 17 00:00:00 2001 +From 81d7fd629130f5be6562ad5ba1a28fabb3eaed3e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 11 Aug 2013 15:03:36 +0100 -Subject: [PATCH 056/104] 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. +Subject: [PATCH 54/99] 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 | 7 +++++++ @@ -8845,10 +5383,10 @@ Subject: [PATCH 056/104] PowerManager (and its IPowerSyscall instance) now 4 files changed, 23 insertions(+) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index ead4b6a..376d8c4 100644 +index 186ea7f..0a41343 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp -@@ -2320,6 +2320,13 @@ bool CApplication::OnKey(const CKey& key) +@@ -2332,6 +2332,13 @@ bool CApplication::OnKey(const CKey& key) // special handling if the screensaver is active CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key); @@ -8926,12 +5464,12 @@ index 0b1f10a..e42b143 100644 void OnSleep(); void OnWake(); -From 0ca4dcca30ca3827416a68c952439d3452f1b933 Mon Sep 17 00:00:00 2001 +From bf6321c429e5b929bc93fb75c64e0c855632d349 Mon Sep 17 00:00:00 2001 From: macrule Date: Wed, 17 Apr 2013 13:23:01 +0200 -Subject: [PATCH 057/104] 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. +Subject: [PATCH 55/99] 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 + @@ -9105,10 +5643,10 @@ index 0000000..ef6e682 + +#endif // _POWER_SYSCALL_VIRTUAL_SLEEP_H_ -From 9d6b4966e1c3f5903ddc8b01e73781bf6f8c7989 Mon Sep 17 00:00:00 2001 +From c02b03c0fbd8b83cd71c1c32493cbf648dd1d249 Mon Sep 17 00:00:00 2001 From: macrule Date: Wed, 17 Apr 2013 13:24:22 +0200 -Subject: [PATCH 058/104] Added power management support for the Raspberry Pi. +Subject: [PATCH 56/99] 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. @@ -9254,10 +5792,10 @@ index 0000000..fd1d67c + +#endif // _RASPBERRY_PI_POWER_SYSCALL_H_ -From b4ee4ae439c0436e7d25628cd21a7c17762b186b Mon Sep 17 00:00:00 2001 +From d4343f847b7c527598660d7bb6295f000874c939 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Mar 2014 16:16:29 +0000 -Subject: [PATCH 059/104] [power] hack - don't kill lirc or cec +Subject: [PATCH 57/99] [power] hack - don't kill lirc or cec --- xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 37 +++++++++++++++++++++++ @@ -9341,10 +5879,10 @@ index 2d8c750..901f449 100644 CBuiltins::Execute("LIRC.Start"); #endif -From 2b99e9a0b3ccdc73f958db6cfbf8090f73a83caa Mon Sep 17 00:00:00 2001 +From e5e5fbc455a23da78bce9d1e1f218323ece08daf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Mar 2014 16:47:54 +0000 -Subject: [PATCH 060/104] [power] hack - wake on any action +Subject: [PATCH 58/99] [power] hack - wake on any action --- xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 6 +++--- @@ -9373,10 +5911,10 @@ index 6a1e47b..a717a09 100644 if(VirtualWake()) { -From 8a90a0c4bedb99f9fc182f975375203d8bfeb739 Mon Sep 17 00:00:00 2001 +From 3aacd299ec2bd4a9640d9edff9bc4820040ae6b4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 3 Mar 2014 17:30:07 +0000 -Subject: [PATCH 061/104] [power] hack - Make suspend toggle suspend state +Subject: [PATCH 59/99] [power] hack - Make suspend toggle suspend state --- xbmc/powermanagement/PowerSyscallVirtualSleep.cpp | 5 +++++ @@ -9399,10 +5937,10 @@ index a717a09..d39c3ed 100644 return false; } -From a2f53cd773498d06e8ab7adb45d6c7b12cd3413f Mon Sep 17 00:00:00 2001 +From d58641d07873f7e84e8e902123a23012baf6451b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 4 Mar 2014 19:33:44 +0000 -Subject: [PATCH 062/104] [power] Add back in powerdown and reboot +Subject: [PATCH 60/99] [power] Add back in powerdown and reboot --- .../linux/RaspberryPIPowerSyscall.cpp | 34 ++++++++++++++++++++++ @@ -9480,11 +6018,11 @@ index fd1d67c..062132e 100644 virtual bool CanReboot() { return true; } -From 65fd6d6f82e7221d4dda92568111cfbe4395d52d Mon Sep 17 00:00:00 2001 +From 1b42a074be346ac5f723b0c1931def7b3c72148b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 26 Apr 2014 17:27:52 +0100 -Subject: [PATCH 067/104] [cec] Don't suspend pi on tv switch off - it can't - wake up +Subject: [PATCH 65/99] [cec] Don't suspend pi on tv switch off - it can't wake + up --- system/peripherals.xml | 2 +- @@ -9504,10 +6042,10 @@ index a906628..9b5271a 100644 -From 6a0b086eb8b731b16f96715dd83e70778492f1f0 Mon Sep 17 00:00:00 2001 +From 1279d3fb5faf0fd513ff85dcd2fc76270bfb854d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 18 Aug 2014 19:09:32 +0100 -Subject: [PATCH 068/104] rbp: Use new dispmanx function for vsync callbacks +Subject: [PATCH 66/99] rbp: Use new dispmanx function for vsync callbacks --- xbmc/linux/RBP.cpp | 85 ++++++++++++++----------- @@ -9719,10 +6257,10 @@ index ca36082..4b74ea0 100644 } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); -From 3843e14de62575738037c33713766e44937e388b Mon Sep 17 00:00:00 2001 +From ec1bede710310c5a4e865ee0847ca33bfce568bd Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 19 Aug 2014 17:56:45 +0100 -Subject: [PATCH 069/104] Revert "rbp: Use new dispmanx function for vsync +Subject: [PATCH 67/99] Revert "rbp: Use new dispmanx function for vsync callbacks" This reverts commit afbf8fbceaa6649fb4a6bbd9a1cee6087590412b. @@ -9936,10 +6474,10 @@ index 4b74ea0..ca36082 100644 } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); -From ba4e721c97a87b3b7cadbb492b8b5fea3af6348c Mon Sep 17 00:00:00 2001 +From f5ca95842aa2601aec05a6bfaf316d5c394525f8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 27 Jun 2014 00:01:05 +0100 -Subject: [PATCH 070/104] [rbp] Resume video output on startup +Subject: [PATCH 68/99] [rbp] Resume video output on startup --- xbmc/linux/RBP.cpp | 3 +++ @@ -9960,10 +6498,10 @@ index 2ff6078..34e0108 100644 m_omx_image_init = true; return true; -From afab9b008a0541d7d1c2ff625add58e20ad2a39c Mon Sep 17 00:00:00 2001 +From 5ec02d54792052a230a35645a33f88297664406e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 16 Aug 2014 21:01:42 +0100 -Subject: [PATCH 071/104] omxrender: Hacks to reduce GUI rendering rate when +Subject: [PATCH 69/99] omxrender: Hacks to reduce GUI rendering rate when playing video --- @@ -9973,10 +6511,10 @@ Subject: [PATCH 071/104] omxrender: Hacks to reduce GUI rendering rate when 3 files changed, 60 insertions(+) diff --git a/language/English/strings.po b/language/English/strings.po -index 73213b8..ef3022b 100755 +index 160e83c..d9b4519 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15925,3 +15925,30 @@ msgstr "" +@@ -15951,3 +15951,30 @@ msgstr "" msgctxt "#37034" msgid "Uses codec information and audio setting to choose dvdplayer or omxplayer as appropriate" msgstr "" @@ -10008,7 +6546,7 @@ index 73213b8..ef3022b 100755 +msgid "24 fps" +msgstr "" diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index 49706c0..649e8fe 100644 +index 9cc4fd2..97eb3e3c 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -25,6 +25,22 @@ @@ -10035,10 +6573,10 @@ index 49706c0..649e8fe 100644
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 376d8c4..06ff301 100644 +index 0a41343..34cb9db 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp -@@ -2168,6 +2168,23 @@ void CApplication::Render() +@@ -2180,6 +2180,23 @@ void CApplication::Render() if (m_bStop) return; @@ -10063,11 +6601,10 @@ index 376d8c4..06ff301 100644 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync"); -From f6a9fe90c39b28de9ed2d3278d8506efd30bab10 Mon Sep 17 00:00:00 2001 +From b3e5eb969927b2e45b356fe70c6c94051441a53c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 9 Sep 2014 12:04:26 +0100 -Subject: [PATCH 072/104] egl: Treat unknown display aspect ratio as square - pixel +Subject: [PATCH 70/99] egl: Treat unknown display aspect ratio as square pixel --- xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 ++-- @@ -10096,10 +6633,10 @@ index ca36082..1529045 100644 SetResolutionString(m_desktopRes); -From 6f9fb5c6beeb827e20d8e26888287f2900ac0a37 Mon Sep 17 00:00:00 2001 +From 96bbf2e2b66398bcef70f48cbd62097209c0a1a7 Mon Sep 17 00:00:00 2001 From: anaconda Date: Thu, 11 Sep 2014 21:30:43 +0200 -Subject: [PATCH 073/104] Disable textbox autoscrolling while on screensaver. +Subject: [PATCH 71/99] Disable textbox autoscrolling while on screensaver. --- xbmc/guilib/GUITextBox.cpp | 3 ++- @@ -10127,10 +6664,10 @@ index b7ef051..ba68fad 100644 if (m_lastRenderTime) m_autoScrollDelayTime += currentTime - m_lastRenderTime; -From dd4c199e7930d4ee3bf4f4da1076129a0335e194 Mon Sep 17 00:00:00 2001 +From 9fb850204d9931af9c29529e64c1a9f6c309f4a9 Mon Sep 17 00:00:00 2001 From: anaconda Date: Sat, 13 Sep 2014 19:49:01 +0200 -Subject: [PATCH 074/104] SQUASH: only if dim or black +Subject: [PATCH 72/99] SQUASH: only if dim or black --- xbmc/Application.cpp | 7 +++++++ @@ -10139,10 +6676,10 @@ Subject: [PATCH 074/104] SQUASH: only if dim or black 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index 06ff301..e044be2 100644 +index 34cb9db..d89a379 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp -@@ -5802,3 +5802,10 @@ void CApplication::CloseNetworkShares() +@@ -5814,3 +5814,10 @@ void CApplication::CloseNetworkShares() CSFTPSessionManager::DisconnectAllSessions(); #endif } @@ -10182,10 +6719,10 @@ index ba68fad..e149418 100644 if (m_lastRenderTime) m_autoScrollDelayTime += currentTime - m_lastRenderTime; -From e44208133fa914e8ef20efb039aceab7bdc1c2b1 Mon Sep 17 00:00:00 2001 +From 36b350c61d9648a03f7c5731bb2a213c5362407a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Sep 2014 00:52:02 +0100 -Subject: [PATCH 075/104] [PiSink] Initial dual audio support +Subject: [PATCH 73/99] [PiSink] Initial dual audio support --- system/settings/rbp.xml | 7 - @@ -10195,7 +6732,7 @@ Subject: [PATCH 075/104] [PiSink] Initial dual audio support 4 files changed, 186 insertions(+), 57 deletions(-) diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index 649e8fe..d4760df 100644 +index 97eb3e3c..3c372bf 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -79,13 +79,6 @@ @@ -10213,7 +6750,7 @@ index 649e8fe..d4760df 100644 diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp -index b199acd..fd9a03d 100644 +index 7af2078..89684e4 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp @@ -43,7 +43,8 @@ CAEDeviceInfo CAESinkPi::m_info; @@ -10594,10 +7131,10 @@ index a73dd0a..13899bc 100644 // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix -From 98779eb1e8d399ea2266507985a9bdad7fc5881e Mon Sep 17 00:00:00 2001 +From 3ff4ef08779e7b03bd219b19e4cf688b1c2b015b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 18 Sep 2014 14:24:56 +0100 -Subject: [PATCH 076/104] [omxplayer] Only enable audio clock master when A/V +Subject: [PATCH 74/99] [omxplayer] Only enable audio clock master when A/V sync method is set to audio clock --- @@ -10628,10 +7165,10 @@ index 13899bc..3c6c73b 100644 OMX_CONFIG_BOOLEANTYPE configBool; OMX_INIT_STRUCTURE(configBool); -From 74eb025ec90c425b0b4bbbd7571aa97dd92b1bea Mon Sep 17 00:00:00 2001 +From d9f3d0781c9978e31abda2388c43f827b981a202 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 18 Aug 2014 19:09:32 +0100 -Subject: [PATCH 077/104] rbp: Use new dispmanx function for vsync callbacks +Subject: [PATCH 75/99] rbp: Use new dispmanx function for vsync callbacks [rbp] Enable vsync handler all the time --- @@ -10864,10 +7401,10 @@ index 1529045..b6bf1fc 100644 } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); -From 53a24c9ccefaf5920c4802ef5d19c3ed3477bf75 Mon Sep 17 00:00:00 2001 +From acb93970c12591f2b3c5cc2e514a6055b1128f35 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 18 Sep 2014 23:14:31 +0100 -Subject: [PATCH 078/104] Revert "rbp: Use new dispmanx function for vsync +Subject: [PATCH 76/99] Revert "rbp: Use new dispmanx function for vsync callbacks" This reverts commit e56163da23b6a844e7eee076e4583bce606f788b. @@ -11101,10 +7638,10 @@ index b6bf1fc..1529045 100644 } DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n"); -From bf63f0d814ac60141fff0e1bc207b60e40d66c86 Mon Sep 17 00:00:00 2001 +From ae43237eccd719fd1760f7d2bfd44c4229617c9d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 19 Sep 2014 11:54:49 +0100 -Subject: [PATCH 079/104] [dvdplayer/rbp] Add pi specific option to maintain +Subject: [PATCH 77/99] [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". @@ -11114,19 +7651,19 @@ or drop/dupe audio packets which is normally required. Needed updated firmware --- language/English/strings.po | 5 +++++ - system/settings/rbp.xml | 20 +++++++++++++++++++ + system/settings/rbp.xml | 20 ++++++++++++++++++ xbmc/cores/AudioEngine/Utils/AEUtil.h | 3 ++- - xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 34 +++++++++++++++++++++++++++++++-- + xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 36 +++++++++++++++++++++++++++++++-- xbmc/cores/dvdplayer/DVDPlayerAudio.h | 1 + - xbmc/linux/RBP.cpp | 13 +++++++++++++ + xbmc/linux/RBP.cpp | 13 ++++++++++++ xbmc/linux/RBP.h | 1 + - 7 files changed, 74 insertions(+), 3 deletions(-) + 7 files changed, 76 insertions(+), 3 deletions(-) diff --git a/language/English/strings.po b/language/English/strings.po -index ef3022b..63f969a 100755 +index d9b4519..aba172a 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15952,3 +15952,8 @@ msgstr "" +@@ -15978,3 +15978,8 @@ msgstr "" msgctxt "#38005" msgid "24 fps" msgstr "" @@ -11136,7 +7673,7 @@ index ef3022b..63f969a 100755 +msgid "Adjust PLL" +msgstr "" diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml -index d4760df..bc8ebc9 100644 +index 3c372bf..9ecae65 100644 --- a/system/settings/rbp.xml +++ b/system/settings/rbp.xml @@ -11,6 +11,26 @@ @@ -11147,7 +7684,7 @@ index d4760df..bc8ebc9 100644 + + + 2 -+ 4 ++ 2 + + + @@ -11181,7 +7718,7 @@ index 1e61c50..039cd69 100644 struct AEDelayStatus diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp -index 98da461..36b2568 100644 +index 98da461..bb2c375 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp @@ -112,6 +112,7 @@ CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent) @@ -11212,12 +7749,13 @@ index 98da461..36b2568 100644 CLog::Log(LOGDEBUG, "CDVDPlayerAudio:: synctype set to %i: %s", m_synctype, synctypes[synctype]); m_prevsynctype = m_synctype; } -@@ -697,6 +700,29 @@ void CDVDPlayerAudio::HandleSyncError(double duration) +@@ -697,6 +700,31 @@ void CDVDPlayerAudio::HandleSyncError(double duration) } m_resampleratio = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral; } + else if (m_synctype == SYNC_PLLADJUST) + { ++#if defined(TARGET_RASPBERRY_PI) + //reset the integral on big errors, failsafe + if (fabs(m_error) > DVD_TIME_BASE) + m_integral = 0; @@ -11238,11 +7776,12 @@ index 98da461..36b2568 100644 + m_plladjust = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral; + double new_adjust = g_RBP.AdjustHDMIClock(m_plladjust); + CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.4f (%.4f) proportional:%.4f integral:%.4f", __FUNCTION__, m_plladjust, new_adjust, proportional, m_integral); ++#endif + } } } -@@ -735,6 +761,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) +@@ -735,6 +763,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) m_dvdAudio.SetResampleRatio(m_resampleratio); m_dvdAudio.AddPackets(audioframe); } @@ -11300,10 +7839,10 @@ index f947acc..606c24f 100644 void SuspendVideoOutput(); void ResumeVideoOutput(); -From a414cbab2ea8706e936e6ea1d62a1df61e3d4930 Mon Sep 17 00:00:00 2001 +From af3c4e730f3dec154902fd1c1dd7ce300e839b6f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 21 Sep 2014 18:31:31 +0100 -Subject: [PATCH 080/104] hack: revert squash: don't update originaldts when +Subject: [PATCH 78/99] hack: revert squash: don't update originaldts when marked as invalid --- @@ -11311,7 +7850,7 @@ Subject: [PATCH 080/104] hack: revert squash: don't update originaldts when 1 file changed, 1 insertion(+) diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp -index 6547880..32374d4 100644 +index c89aae2..c34b96f 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -2106,6 +2106,7 @@ void CDVDPlayer::CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket) @@ -11323,1107 +7862,21 @@ index 6547880..32374d4 100644 } else -From 94e00aa1aeb369306a4d95ef59fbf4b0d54e6d9c Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 24 Sep 2014 23:13:52 +0100 -Subject: [PATCH 081/104] [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 ---- - language/English/strings.po | 15 +++++++++++++++ - system/settings/settings.xml | 12 ++++++++++++ - .../AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp | 6 ++++++ - .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 ++++++ - xbmc/cores/omxplayer/OMXAudio.cpp | 6 ++++++ - 5 files changed, 45 insertions(+) - -diff --git a/language/English/strings.po b/language/English/strings.po -index 63f969a..b58a405 100755 ---- a/language/English/strings.po -+++ b/language/English/strings.po -@@ -15957,3 +15957,18 @@ msgstr "" - msgctxt "#38006" - msgid "Adjust 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 9a4cefb..5c29ce3 100644 ---- a/system/settings/settings.xml -+++ b/system/settings/settings.xml -@@ -2435,6 +2435,18 @@ - true - - -+ -+ 2 -+ 0 -+ -+ 0 -+ 1 -+ 30 -+ -+ -+ 38009 -+ -+ - - HAS_AE_QUALITY_LEVELS - 2 -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -index 99cd607..a9a03ce 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -@@ -108,6 +108,12 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst - { - 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 cc01738..a05ef3a 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp -@@ -158,6 +158,12 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst - { - 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 3c6c73b..2b7a83a 100644 ---- a/xbmc/cores/omxplayer/OMXAudio.cpp -+++ b/xbmc/cores/omxplayer/OMXAudio.cpp -@@ -639,6 +639,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 de2e291694f5150a745d093561f08391d9561d5e Mon Sep 17 00:00:00 2001 -From: xhaggi -Date: Wed, 24 Sep 2014 17:30:32 +0200 -Subject: [PATCH 091/104] fix wrong printf format mismatches - ---- - xbmc/GUIInfoManager.cpp | 4 +- - xbmc/cdrip/CDDARipJob.cpp | 2 +- - xbmc/cores/FFmpeg.cpp | 2 +- - xbmc/cores/dvdplayer/Edl.cpp | 2 +- - xbmc/filesystem/VideoDatabaseDirectory.cpp | 2 +- - xbmc/guilib/TextureManager.cpp | 4 +- - xbmc/interfaces/json-rpc/AudioLibrary.cpp | 4 +- - .../interfaces/json-rpc/JSONServiceDescription.cpp | 4 +- - xbmc/interfaces/json-rpc/VideoLibrary.cpp | 2 +- - xbmc/music/MusicDatabase.cpp | 12 ++-- - xbmc/music/windows/GUIWindowMusicBase.cpp | 2 +- - xbmc/music/windows/GUIWindowMusicNav.cpp | 6 +- - xbmc/network/DNSNameCache.cpp | 2 +- - xbmc/network/upnp/UPnPRenderer.cpp | 4 +- - xbmc/network/upnp/UPnPServer.cpp | 12 ++-- - xbmc/peripherals/devices/Peripheral.cpp | 14 +++-- - xbmc/playlists/PlayListB4S.cpp | 2 +- - xbmc/playlists/PlayListPLS.cpp | 2 +- - xbmc/playlists/SmartPlayList.cpp | 2 +- - xbmc/profiles/ProfilesManager.cpp | 2 +- - xbmc/pvr/PVRGUIInfo.cpp | 4 +- - xbmc/pvr/PVRManager.cpp | 2 +- - xbmc/pvr/channels/PVRChannelGroups.cpp | 6 +- - xbmc/utils/Fanart.cpp | 2 +- - xbmc/utils/GroupUtils.cpp | 2 +- - xbmc/utils/LabelFormatter.cpp | 2 +- - xbmc/utils/RecentlyAddedJob.cpp | 4 +- - xbmc/utils/ScraperParser.cpp | 2 +- - xbmc/utils/SortUtils.cpp | 6 +- - xbmc/video/VideoDatabase.cpp | 66 +++++++++++----------- - xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp | 2 +- - xbmc/video/dialogs/GUIDialogVideoInfo.cpp | 2 +- - xbmc/video/windows/GUIWindowVideoNav.cpp | 4 +- - xbmc/windows/GUIMediaWindow.cpp | 2 +- - 34 files changed, 99 insertions(+), 93 deletions(-) - -diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp -index ab243b5..dcb31e7 100644 ---- a/xbmc/GUIInfoManager.cpp -+++ b/xbmc/GUIInfoManager.cpp -@@ -1905,7 +1905,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, std::string *f - strLabel = CProfilesManager::Get().GetCurrentProfile().getName(); - break; - case SYSTEM_PROFILECOUNT: -- strLabel = StringUtils::Format("%i", CProfilesManager::Get().GetNumberOfProfiles()); -+ strLabel = StringUtils::Format("%" PRIuS, CProfilesManager::Get().GetNumberOfProfiles()); - break; - case SYSTEM_PROFILEAUTOLOGIN: - { -@@ -5163,7 +5163,7 @@ CStdString CGUIInfoManager::GetItemImage(const CFileItem *item, int info, std::s - CStdString rating; - if (item->HasVideoInfoTag()) - { // rating for videos is assumed 0..10, so convert to 0..5 -- rating = StringUtils::Format("rating%d.png", (long)((item->GetVideoInfoTag()->m_fRating * 0.5f) + 0.5f)); -+ rating = StringUtils::Format("rating%ld.png", (long)((item->GetVideoInfoTag()->m_fRating * 0.5f) + 0.5f)); - } - else if (item->HasMusicInfoTag()) - { // song rating. -diff --git a/xbmc/cdrip/CDDARipJob.cpp b/xbmc/cdrip/CDDARipJob.cpp -index bbacedb..87798ce 100644 ---- a/xbmc/cdrip/CDDARipJob.cpp -+++ b/xbmc/cdrip/CDDARipJob.cpp -@@ -201,7 +201,7 @@ CEncoder* CCDDARipJob::SetupEncoder(CFile& reader) - return NULL; - - // we have to set the tags before we init the Encoder -- std::string strTrack = StringUtils::Format("%i", strtol(m_input.substr(13, m_input.size() - 13 - 5).c_str(),NULL,10)); -+ std::string strTrack = StringUtils::Format("%li", strtol(m_input.substr(13, m_input.size() - 13 - 5).c_str(),NULL,10)); - - encoder->SetComment("Ripped with XBMC"); - encoder->SetArtist(StringUtils::Join(m_tag.GetArtist(), -diff --git a/xbmc/cores/FFmpeg.cpp b/xbmc/cores/FFmpeg.cpp -index 7e72df1..305966b 100644 ---- a/xbmc/cores/FFmpeg.cpp -+++ b/xbmc/cores/FFmpeg.cpp -@@ -103,7 +103,7 @@ void ff_avutil_log(void* ptr, int level, const char* format, va_list va) - } - - std::string message = StringUtils::FormatV(format, va); -- std::string prefix = StringUtils::Format("ffmpeg[%X]: ", threadId); -+ std::string prefix = StringUtils::Format("ffmpeg[%lX]: ", threadId); - if(avc) - { - if(avc->item_name) -diff --git a/xbmc/cores/dvdplayer/Edl.cpp b/xbmc/cores/dvdplayer/Edl.cpp -index 958d22f..0797c08 100644 ---- a/xbmc/cores/dvdplayer/Edl.cpp -+++ b/xbmc/cores/dvdplayer/Edl.cpp -@@ -846,7 +846,7 @@ std::string CEdl::GetInfo() const - strInfo += StringUtils::Format("b%i", commBreakCount); - } - if (HasSceneMarker()) -- strInfo += StringUtils::Format("s%i", m_vecSceneMarkers.size()); -+ strInfo += StringUtils::Format("s%" PRIuS, m_vecSceneMarkers.size()); - - return strInfo.empty() ? "-" : strInfo; - } -diff --git a/xbmc/filesystem/VideoDatabaseDirectory.cpp b/xbmc/filesystem/VideoDatabaseDirectory.cpp -index 5eae9ee..fb65f60 100644 ---- a/xbmc/filesystem/VideoDatabaseDirectory.cpp -+++ b/xbmc/filesystem/VideoDatabaseDirectory.cpp -@@ -174,7 +174,7 @@ bool CVideoDatabaseDirectory::GetLabel(const std::string& strDirectory, std::str - // get year - if (params.GetYear() != -1) - { -- std::string strTemp = StringUtils::Format("%i",params.GetYear()); -+ std::string strTemp = StringUtils::Format("%li",params.GetYear()); - if (!strLabel.empty()) - strLabel += " / "; - strLabel += strTemp; -diff --git a/xbmc/guilib/TextureManager.cpp b/xbmc/guilib/TextureManager.cpp -index fbe42db..f295674 100644 ---- a/xbmc/guilib/TextureManager.cpp -+++ b/xbmc/guilib/TextureManager.cpp -@@ -178,7 +178,7 @@ void CTextureMap::Dump() const - if (!m_referenceCount) - return; // nothing to see here - -- CLog::Log(LOGDEBUG, "%s: texture:%s has %i frames %i refcount", __FUNCTION__, m_textureName.c_str(), m_texture.m_textures.size(), m_referenceCount); -+ CLog::Log(LOGDEBUG, "%s: texture:%s has %" PRIuS" frames %i refcount", __FUNCTION__, m_textureName.c_str(), m_texture.m_textures.size(), m_referenceCount); - } - - unsigned int CTextureMap::GetMemoryUsage() const -@@ -510,7 +510,7 @@ void CGUITextureManager::Cleanup() - - void CGUITextureManager::Dump() const - { -- CLog::Log(LOGDEBUG, "%s: total texturemaps size:%i", __FUNCTION__, m_vecTextures.size()); -+ CLog::Log(LOGDEBUG, "%s: total texturemaps size:%" PRIuS, __FUNCTION__, m_vecTextures.size()); - - for (int i = 0; i < (int)m_vecTextures.size(); ++i) - { -diff --git a/xbmc/interfaces/json-rpc/AudioLibrary.cpp b/xbmc/interfaces/json-rpc/AudioLibrary.cpp -index bd87624..b3bc8b6 100644 ---- a/xbmc/interfaces/json-rpc/AudioLibrary.cpp -+++ b/xbmc/interfaces/json-rpc/AudioLibrary.cpp -@@ -287,7 +287,7 @@ JSONRPC_STATUS CAudioLibrary::GetRecentlyAddedAlbums(const std::string &method, - CFileItemList items; - for (unsigned int index = 0; index < albums.size(); index++) - { -- std::string path = StringUtils::Format("musicdb://recentlyaddedalbums/%i/", albums[index].idAlbum); -+ std::string path = StringUtils::Format("musicdb://recentlyaddedalbums/%li/", albums[index].idAlbum); - - CFileItemPtr item; - FillAlbumItem(albums[index], path, item); -@@ -337,7 +337,7 @@ JSONRPC_STATUS CAudioLibrary::GetRecentlyPlayedAlbums(const std::string &method, - CFileItemList items; - for (unsigned int index = 0; index < albums.size(); index++) - { -- std::string path = StringUtils::Format("musicdb://recentlyplayedalbums/%i/", albums[index].idAlbum); -+ std::string path = StringUtils::Format("musicdb://recentlyplayedalbums/%li/", albums[index].idAlbum); - - CFileItemPtr item; - FillAlbumItem(albums[index], path, item); -diff --git a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp -index a5f1fee..ec889f3 100644 ---- a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp -+++ b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp -@@ -673,7 +673,7 @@ JSONRPC_STATUS JSONSchemaTypeDefinition::Check(const CVariant &value, CVariant & - if (status != OK) - { - CLog::Log(LOGDEBUG, "JSONRPC: Value does not match extended type %s of type %s", extends.at(extendsIndex)->ID.c_str(), name.c_str()); -- errorMessage = StringUtils::Format("value does not match extended type %s", extends.at(extendsIndex)->ID.c_str(), name.c_str()); -+ errorMessage = StringUtils::Format("value does not match extended type %s", extends.at(extendsIndex)->ID.c_str()); - errorData["message"] = errorMessage.c_str(); - return status; - } -@@ -735,7 +735,7 @@ JSONRPC_STATUS JSONSchemaTypeDefinition::Check(const CVariant &value, CVariant & - if (value.size() < items.size() || (value.size() != items.size() && additionalItems.size() == 0)) - { - CLog::Log(LOGDEBUG, "JSONRPC: One of the array elements does not match in type %s", name.c_str()); -- errorMessage = StringUtils::Format("%d array elements expected but %d received", items.size(), value.size()); -+ errorMessage = StringUtils::Format("%" PRIuS" array elements expected but %d received", items.size(), value.size()); - errorData["message"] = errorMessage.c_str(); - return InvalidParams; - } -diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.cpp b/xbmc/interfaces/json-rpc/VideoLibrary.cpp -index 353cdff..cc6405f 100644 ---- a/xbmc/interfaces/json-rpc/VideoLibrary.cpp -+++ b/xbmc/interfaces/json-rpc/VideoLibrary.cpp -@@ -324,7 +324,7 @@ JSONRPC_STATUS CVideoLibrary::GetEpisodeDetails(const std::string &method, ITran - if (tvshowid <= 0) - tvshowid = videodatabase.GetTvShowForEpisode(id); - -- std::string basePath = StringUtils::Format("videodb://tvshows/titles/%ld/%ld/%ld", tvshowid, infos.m_iSeason, id); -+ std::string basePath = StringUtils::Format("videodb://tvshows/titles/%i/%i/%i", tvshowid, infos.m_iSeason, id); - pItem->SetPath(basePath); - - HandleFileItem("episodeid", true, "episodedetails", pItem, parameterObject, parameterObject["properties"], result, false); -diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp -index 5f33943..3da8072 100644 ---- a/xbmc/music/MusicDatabase.cpp -+++ b/xbmc/music/MusicDatabase.cpp -@@ -1606,7 +1606,7 @@ void CMusicDatabase::GetFileItemFromDataset(const dbiplus::sql_record* const rec - CMusicDbUrl itemUrl = baseUrl; - CStdString strFileName = record->at(song_strFileName).get_asString(); - CStdString strExt = URIUtils::GetExtension(strFileName); -- CStdString path = StringUtils::Format("%ld%s", record->at(song_idSong).get_asInt(), strExt.c_str()); -+ CStdString path = StringUtils::Format("%i%s", record->at(song_idSong).get_asInt(), strExt.c_str()); - itemUrl.AppendPath(path); - item->SetPath(itemUrl.ToString()); - } -@@ -1804,7 +1804,7 @@ bool CMusicDatabase::SearchArtists(const CStdString& search, CFileItemList &arti - CStdString artistLabel(g_localizeStrings.Get(557)); // Artist - while (!m_pDS->eof()) - { -- CStdString path = StringUtils::Format("musicdb://artists/%ld/", m_pDS->fv(0).get_asInt()); -+ CStdString path = StringUtils::Format("musicdb://artists/%i/", m_pDS->fv(0).get_asInt()); - CFileItemPtr pItem(new CFileItem(path, true)); - CStdString label = StringUtils::Format("[%s] %s", artistLabel.c_str(), m_pDS->fv(1).get_asString().c_str()); - pItem->SetLabel(label); -@@ -2911,7 +2911,7 @@ bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& i - pItem->GetMusicInfoTag()->SetDatabaseId(m_pDS->fv("genre.idGenre").get_asInt(), "genre"); - - CMusicDbUrl itemUrl = musicUrl; -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("genre.idGenre").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("genre.idGenre").get_asInt()); - itemUrl.AppendPath(strDir); - pItem->SetPath(itemUrl.ToString()); - -@@ -2973,7 +2973,7 @@ bool CMusicDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it - pItem->GetMusicInfoTag()->SetReleaseDate(stTime); - - CMusicDbUrl itemUrl = musicUrl; -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv(0).get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv(0).get_asInt()); - itemUrl.AppendPath(strDir); - pItem->SetPath(itemUrl.ToString()); - -@@ -3397,7 +3397,7 @@ bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const Filter &f - try - { - CMusicDbUrl itemUrl = musicUrl; -- CStdString path = StringUtils::Format("%ld/", record->at(album_idAlbum).get_asInt()); -+ CStdString path = StringUtils::Format("%i/", record->at(album_idAlbum).get_asInt()); - itemUrl.AppendPath(path); - - CFileItemPtr pItem(new CFileItem(itemUrl.ToString(), GetAlbumFromDataset(record))); -@@ -5075,7 +5075,7 @@ void CMusicDatabase::ExportKaraokeInfo(const CStdString & outFile, bool asHTML) - while (!m_pDS->eof()) - { - CSong song = GetSongFromDataset(); -- CStdString songnum = StringUtils::Format("%06d", song.iKaraokeNumber); -+ CStdString songnum = StringUtils::Format("%06ld", song.iKaraokeNumber); - - if ( asHTML ) - outdoc = "" + songnum + "" + (CStdString)StringUtils::Join(song.artist, g_advancedSettings.m_musicItemSeparator) + "" + song.strTitle + "\r\n"; -diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp -index b57998b..e31a859 100644 ---- a/xbmc/music/windows/GUIWindowMusicBase.cpp -+++ b/xbmc/music/windows/GUIWindowMusicBase.cpp -@@ -328,7 +328,7 @@ void CGUIWindowMusicBase::OnInfo(CFileItem *pItem, bool bShowInfo) - CAlbum album; - if (!m_musicdatabase.GetAlbum(albumID, album)) - return; -- CFileItem item(StringUtils::Format("musicdb://albums/%ld/", albumID), album); -+ CFileItem item(StringUtils::Format("musicdb://albums/%i/", albumID), album); - if (ShowAlbumInfo(&item)) - return; - } -diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp -index 5333598..74d0d48 100644 ---- a/xbmc/music/windows/GUIWindowMusicNav.cpp -+++ b/xbmc/music/windows/GUIWindowMusicNav.cpp -@@ -652,7 +652,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) - CStdString strPath; - CVideoDatabase database; - database.Open(); -- strPath = StringUtils::Format("videodb://musicvideos/artists/%ld/", -+ strPath = StringUtils::Format("videodb://musicvideos/artists/%i/", - database.GetMatchingMusicVideo(StringUtils::Join(item->GetMusicInfoTag()->GetArtist(), g_advancedSettings.m_musicItemSeparator))); - g_windowManager.ActivateWindow(WINDOW_VIDEO_NAV,strPath); - return true; -@@ -696,10 +696,10 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) - CDirectoryNode::GetDatabaseInfo(item->GetPath(), params); - CONTENT_TYPE content = CONTENT_ALBUMS; - if (params.GetAlbumId() != -1) -- path = StringUtils::Format("musicdb://albums/%i/",params.GetAlbumId()); -+ path = StringUtils::Format("musicdb://albums/%li/",params.GetAlbumId()); - else if (params.GetArtistId() != -1) - { -- path = StringUtils::Format("musicdb://artists/%i/",params.GetArtistId()); -+ path = StringUtils::Format("musicdb://artists/%li/",params.GetArtistId()); - content = CONTENT_ARTISTS; - } - -diff --git a/xbmc/network/DNSNameCache.cpp b/xbmc/network/DNSNameCache.cpp -index c5f6397..f12c782 100644 ---- a/xbmc/network/DNSNameCache.cpp -+++ b/xbmc/network/DNSNameCache.cpp -@@ -48,7 +48,7 @@ bool CDNSNameCache::Lookup(const std::string& strHostName, std::string& strIpAdd - - if (address != INADDR_NONE) - { -- strIpAddress = StringUtils::Format("%d.%d.%d.%d", (address & 0xFF), (address & 0xFF00) >> 8, (address & 0xFF0000) >> 16, (address & 0xFF000000) >> 24 ); -+ strIpAddress = StringUtils::Format("%lu.%lu.%lu.%lu", (address & 0xFF), (address & 0xFF00) >> 8, (address & 0xFF0000) >> 16, (address & 0xFF000000) >> 24 ); - return true; - } - -diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp -index ef74d59..7aeb034 100644 ---- a/xbmc/network/upnp/UPnPRenderer.cpp -+++ b/xbmc/network/upnp/UPnPRenderer.cpp -@@ -279,10 +279,10 @@ CUPnPRenderer::Announce(AnnouncementFlag flag, const char *sender, const char *m - - CStdString buffer; - -- buffer = StringUtils::Format("%ld", data["volume"].asInteger()); -+ buffer = StringUtils::Format("%" PRId64, data["volume"].asInteger()); - rct->SetStateVariable("Volume", buffer.c_str()); - -- buffer = StringUtils::Format("%ld", 256 * (data["volume"].asInteger() * 60 - 60) / 100); -+ buffer = StringUtils::Format("%" PRId64, 256 * (data["volume"].asInteger() * 60 - 60) / 100); - rct->SetStateVariable("VolumeDb", buffer.c_str()); - - rct->SetStateVariable("Mute", data["muted"].asBoolean() ? "1" : "0"); -diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp -index b9bc25b..20e3bf5 100644 ---- a/xbmc/network/upnp/UPnPServer.cpp -+++ b/xbmc/network/upnp/UPnPServer.cpp -@@ -895,7 +895,7 @@ CUPnPServer::OnSearchContainer(PLT_ActionReference& action, - if (genre.GetLength() > 0) { - // all tracks by genre filtered by artist and/or album - CStdString strPath; -- strPath = StringUtils::Format("musicdb://genres/%ld/%ld/%ld/", -+ strPath = StringUtils::Format("musicdb://genres/%i/%i/%i/", - database.GetGenreByName((const char*)genre), - database.GetArtistByName((const char*)artist), // will return -1 if no artist - database.GetAlbumByName((const char*)album)); // will return -1 if no album -@@ -904,14 +904,14 @@ CUPnPServer::OnSearchContainer(PLT_ActionReference& action, - } else if (artist.GetLength() > 0) { - // all tracks by artist name filtered by album if passed - CStdString strPath; -- strPath = StringUtils::Format("musicdb://artists/%ld/%ld/", -+ strPath = StringUtils::Format("musicdb://artists/%i/%i/", - database.GetArtistByName((const char*)artist), - database.GetAlbumByName((const char*)album)); // will return -1 if no album - - return OnBrowseDirectChildren(action, strPath.c_str(), filter, starting_index, requested_count, sort_criteria, context); - } else if (album.GetLength() > 0) { - // all tracks by album name -- CStdString strPath = StringUtils::Format("musicdb://albums/%ld/", -+ CStdString strPath = StringUtils::Format("musicdb://albums/%i/", - database.GetAlbumByName((const char*)album)); - - return OnBrowseDirectChildren(action, strPath.c_str(), filter, starting_index, requested_count, sort_criteria, context); -@@ -934,12 +934,12 @@ CUPnPServer::OnSearchContainer(PLT_ActionReference& action, - database.Open(); - - if (genre.GetLength() > 0) { -- CStdString strPath = StringUtils::Format("musicdb://genres/%ld/%ld/", -+ CStdString strPath = StringUtils::Format("musicdb://genres/%i/%i/", - database.GetGenreByName((const char*)genre), - database.GetArtistByName((const char*)artist)); // no artist should return -1 - return OnBrowseDirectChildren(action, strPath.c_str(), filter, starting_index, requested_count, sort_criteria, context); - } else if (artist.GetLength() > 0) { -- CStdString strPath = StringUtils::Format("musicdb://artists/%ld/", -+ CStdString strPath = StringUtils::Format("musicdb://artists/%i/", - database.GetArtistByName((const char*)artist)); - return OnBrowseDirectChildren(action, strPath.c_str(), filter, starting_index, requested_count, sort_criteria, context); - } -@@ -952,7 +952,7 @@ CUPnPServer::OnSearchContainer(PLT_ActionReference& action, - if (genre.GetLength() > 0) { - CMusicDatabase database; - database.Open(); -- CStdString strPath = StringUtils::Format("musicdb://genres/%ld/", database.GetGenreByName((const char*)genre)); -+ CStdString strPath = StringUtils::Format("musicdb://genres/%i/", database.GetGenreByName((const char*)genre)); - return OnBrowseDirectChildren(action, strPath.c_str(), filter, starting_index, requested_count, sort_criteria, context); - } - return OnBrowseDirectChildren(action, "musicdb://artists/", filter, starting_index, requested_count, sort_criteria, context); -diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp -index b1eaa1f..35415d1 100644 ---- a/xbmc/peripherals/devices/Peripheral.cpp -+++ b/xbmc/peripherals/devices/Peripheral.cpp -@@ -55,10 +55,16 @@ CPeripheral::CPeripheral(const PeripheralScanResult& scanResult) : - { - PeripheralTypeTranslator::FormatHexString(scanResult.m_iVendorId, m_strVendorId); - PeripheralTypeTranslator::FormatHexString(scanResult.m_iProductId, m_strProductId); -- m_strFileLocation = StringUtils::Format(scanResult.m_iSequence > 0 ? "peripherals://%s/%s_%d.dev" : "peripherals://%s/%s.dev", -- PeripheralTypeTranslator::BusTypeToString(scanResult.m_busType), -- scanResult.m_strLocation.c_str(), -- scanResult.m_iSequence); -+ -+ if (scanResult.m_iSequence > 0) -+ m_strFileLocation = StringUtils::Format("peripherals://%s/%s_%d.dev", -+ PeripheralTypeTranslator::BusTypeToString(scanResult.m_busType), -+ scanResult.m_strLocation.c_str(), -+ scanResult.m_iSequence); -+ else -+ m_strFileLocation = StringUtils::Format("peripherals://%s/%s.dev", -+ PeripheralTypeTranslator::BusTypeToString(scanResult.m_busType), -+ scanResult.m_strLocation.c_str()); - } - - CPeripheral::~CPeripheral(void) -diff --git a/xbmc/playlists/PlayListB4S.cpp b/xbmc/playlists/PlayListB4S.cpp -index aaa91d7..d09af8c 100644 ---- a/xbmc/playlists/PlayListB4S.cpp -+++ b/xbmc/playlists/PlayListB4S.cpp -@@ -125,7 +125,7 @@ void CPlayListB4S::Save(const std::string& strFileName) const - std::string write; - write += StringUtils::Format("\n", 34, 34, 34, 34); - write += StringUtils::Format("\n"); -- write += StringUtils::Format(" \n", 34, m_vecItems.size(), 34, 34, m_strPlayListName.c_str(), 34); -+ write += StringUtils::Format(" \n", 34, m_vecItems.size(), 34, 34, m_strPlayListName.c_str(), 34); - for (int i = 0; i < (int)m_vecItems.size(); ++i) - { - const CFileItemPtr item = m_vecItems[i]; -diff --git a/xbmc/playlists/PlayListPLS.cpp b/xbmc/playlists/PlayListPLS.cpp -index a34d546..312af79 100644 ---- a/xbmc/playlists/PlayListPLS.cpp -+++ b/xbmc/playlists/PlayListPLS.cpp -@@ -233,7 +233,7 @@ void CPlayListPLS::Save(const std::string& strFileName) const - write += StringUtils::Format("Length%i=%u\n", i + 1, item->GetMusicInfoTag()->GetDuration() / 1000 ); - } - -- write += StringUtils::Format("NumberOfEntries=%i\n", m_vecItems.size()); -+ write += StringUtils::Format("NumberOfEntries=%" PRIuS"\n", m_vecItems.size()); - write += StringUtils::Format("Version=2\n"); - file.Write(write.c_str(), write.size()); - file.Close(); -diff --git a/xbmc/playlists/SmartPlayList.cpp b/xbmc/playlists/SmartPlayList.cpp -index 7599816..21a41a6 100644 ---- a/xbmc/playlists/SmartPlayList.cpp -+++ b/xbmc/playlists/SmartPlayList.cpp -@@ -699,7 +699,7 @@ std::string CSmartPlaylistRule::FormatParameter(const std::string &operatorStrin - // special-casing - if (m_field == FieldTime) - { // translate time to seconds -- std::string seconds = StringUtils::Format("%i", StringUtils::TimeStringToSeconds(param)); -+ std::string seconds = StringUtils::Format("%li", StringUtils::TimeStringToSeconds(param)); - return db.PrepareSQL(operatorString.c_str(), seconds.c_str()); - } - return CDatabaseQueryRule::FormatParameter(operatorString, param, db, strType); -diff --git a/xbmc/profiles/ProfilesManager.cpp b/xbmc/profiles/ProfilesManager.cpp -index 2b4cf63..93e2946 100644 ---- a/xbmc/profiles/ProfilesManager.cpp -+++ b/xbmc/profiles/ProfilesManager.cpp -@@ -355,7 +355,7 @@ void CProfilesManager::CreateProfileFolders() - CDirectory::Create(GetVideoThumbFolder()); - CDirectory::Create(GetBookmarksThumbFolder()); - for (size_t hex = 0; hex < 16; hex++) -- CDirectory::Create(URIUtils::AddFileToFolder(GetThumbnailsFolder(), StringUtils::Format("%x", hex))); -+ CDirectory::Create(URIUtils::AddFileToFolder(GetThumbnailsFolder(), StringUtils::Format("%lx", hex))); - - CDirectory::Create("special://profile/addon_data"); - CDirectory::Create("special://profile/keymaps"); -diff --git a/xbmc/pvr/PVRGUIInfo.cpp b/xbmc/pvr/PVRGUIInfo.cpp -index c938295..5bde0e4 100644 ---- a/xbmc/pvr/PVRGUIInfo.cpp -+++ b/xbmc/pvr/PVRGUIInfo.cpp -@@ -552,12 +552,12 @@ void CPVRGUIInfo::CharInfoSNR(std::string &strValue) const - - void CPVRGUIInfo::CharInfoBER(std::string &strValue) const - { -- strValue = StringUtils::Format("%08X", m_qualityInfo.iBER); -+ strValue = StringUtils::Format("%08lX", m_qualityInfo.iBER); - } - - void CPVRGUIInfo::CharInfoUNC(std::string &strValue) const - { -- strValue = StringUtils::Format("%08X", m_qualityInfo.iUNC); -+ strValue = StringUtils::Format("%08lX", m_qualityInfo.iUNC); - } - - void CPVRGUIInfo::CharInfoFrontendName(std::string &strValue) const -diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp -index 076920c..74d3950 100644 ---- a/xbmc/pvr/PVRManager.cpp -+++ b/xbmc/pvr/PVRManager.cpp -@@ -546,7 +546,7 @@ bool CPVRManager::SetWakeupCommand(void) - { - nextEvent.GetAsTime(iWakeupTime); - -- std::string strExecCommand = StringUtils::Format("%s %d", strWakeupCommand.c_str(), iWakeupTime); -+ std::string strExecCommand = StringUtils::Format("%s %ld", strWakeupCommand.c_str(), iWakeupTime); - - const int iReturn = system(strExecCommand.c_str()); - if (iReturn != 0) -diff --git a/xbmc/pvr/channels/PVRChannelGroups.cpp b/xbmc/pvr/channels/PVRChannelGroups.cpp -index c5a022a..7f7398b 100644 ---- a/xbmc/pvr/channels/PVRChannelGroups.cpp -+++ b/xbmc/pvr/channels/PVRChannelGroups.cpp -@@ -225,7 +225,7 @@ bool CPVRChannelGroups::LoadUserDefinedChannelGroups(void) - if (bSyncWithBackends) - { - GetGroupsFromClients(); -- CLog::Log(LOGDEBUG, "PVR - %s - %"PRIuS" new user defined %s channel groups fetched from clients", __FUNCTION__, (m_groups.size() - iSize), m_bRadio ? "radio" : "TV"); -+ CLog::Log(LOGDEBUG, "PVR - %s - %" PRIuS" new user defined %s channel groups fetched from clients", __FUNCTION__, (m_groups.size() - iSize), m_bRadio ? "radio" : "TV"); - } - else - CLog::Log(LOGDEBUG, "PVR - %s - 'synchannelgroups' is disabled; skipping groups from clients", __FUNCTION__); -@@ -279,7 +279,7 @@ bool CPVRChannelGroups::Load(void) - - // load groups from the database - database->Get(*this); -- CLog::Log(LOGDEBUG, "PVR - %s - %"PRIuS" %s groups fetched from the database", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); -+ CLog::Log(LOGDEBUG, "PVR - %s - %" PRIuS" %s groups fetched from the database", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); - - // load channels of internal group - if (!internalGroup->Load()) -@@ -299,7 +299,7 @@ bool CPVRChannelGroups::Load(void) - CPVRChannelGroupPtr lastPlayedGroup = GetLastPlayedGroup(); - SetSelectedGroup(lastPlayedGroup ? lastPlayedGroup : internalGroup); - -- CLog::Log(LOGDEBUG, "PVR - %s - %"PRIuS" %s channel groups loaded", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); -+ CLog::Log(LOGDEBUG, "PVR - %s - %" PRIuS" %s channel groups loaded", __FUNCTION__, m_groups.size(), m_bRadio ? "radio" : "TV"); - - // need at least 1 group - return m_groups.size() > 0; -diff --git a/xbmc/utils/Fanart.cpp b/xbmc/utils/Fanart.cpp -index d7bde1d..9a86bd0 100644 ---- a/xbmc/utils/Fanart.cpp -+++ b/xbmc/utils/Fanart.cpp -@@ -160,7 +160,7 @@ bool CFanart::ParseColors(const std::string &colorsIn, std::string &colorsOut) - { // convert - if (colorsOut.size()) - colorsOut += ","; -- colorsOut += StringUtils::Format("FF%2x%2x%2x", atol(strTriplets[0].c_str()), atol(strTriplets[1].c_str()), atol(strTriplets[2].c_str())); -+ colorsOut += StringUtils::Format("FF%2lx%2lx%2lx", atol(strTriplets[0].c_str()), atol(strTriplets[1].c_str()), atol(strTriplets[2].c_str())); - } - } - } -diff --git a/xbmc/utils/GroupUtils.cpp b/xbmc/utils/GroupUtils.cpp -index 47ceae1..208403e 100644 ---- a/xbmc/utils/GroupUtils.cpp -+++ b/xbmc/utils/GroupUtils.cpp -@@ -80,7 +80,7 @@ bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileI - pItem->GetVideoInfoTag()->m_iDbId = set->first; - pItem->GetVideoInfoTag()->m_type = MediaTypeVideoCollection; - -- std::string basePath = StringUtils::Format("videodb://movies/sets/%ld/", set->first); -+ std::string basePath = StringUtils::Format("videodb://movies/sets/%i/", set->first); - CVideoDbUrl videoUrl; - if (!videoUrl.FromString(basePath)) - pItem->SetPath(basePath); -diff --git a/xbmc/utils/LabelFormatter.cpp b/xbmc/utils/LabelFormatter.cpp -index 7ad8201..c548569 100644 ---- a/xbmc/utils/LabelFormatter.cpp -+++ b/xbmc/utils/LabelFormatter.cpp -@@ -303,7 +303,7 @@ std::string CLabelFormatter::GetMaskContent(const CMaskString &mask, const CFile - break; - case 'X': // Bitrate - if( !item->m_bIsFolder && item->m_dwSize != 0 ) -- value = StringUtils::Format("%i kbps", item->m_dwSize); -+ value = StringUtils::Format("%" PRId64" kbps", item->m_dwSize); - break; - case 'W': // Listeners - if( !item->m_bIsFolder && music && music->GetListeners() != 0 ) -diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp -index e9f512e..f4770c7 100644 ---- a/xbmc/utils/RecentlyAddedJob.cpp -+++ b/xbmc/utils/RecentlyAddedJob.cpp -@@ -269,8 +269,8 @@ bool CRecentlyAddedJob::UpdateMusic() - CStdString value = StringUtils::Format("%i", i + 1); - CStdString strThumb = musicdatabase.GetArtForItem(album.idAlbum, MediaTypeAlbum, "thumb"); - CStdString strFanart = musicdatabase.GetArtistArtForItem(album.idAlbum, MediaTypeAlbum, "fanart"); -- CStdString strDBpath = StringUtils::Format("musicdb://albums/%i/", album.idAlbum); -- CStdString strSQLAlbum = StringUtils::Format("idAlbum=%i", album.idAlbum); -+ CStdString strDBpath = StringUtils::Format("musicdb://albums/%li/", album.idAlbum); -+ CStdString strSQLAlbum = StringUtils::Format("idAlbum=%li", album.idAlbum); - CStdString strArtist = musicdatabase.GetSingleValue("albumview", "strArtists", strSQLAlbum); - - home->SetProperty("LatestAlbum." + value + ".Title" , album.strAlbum); -diff --git a/xbmc/utils/ScraperParser.cpp b/xbmc/utils/ScraperParser.cpp -index a6ebaba..4dc3b48 100644 ---- a/xbmc/utils/ScraperParser.cpp -+++ b/xbmc/utils/ScraperParser.cpp -@@ -560,7 +560,7 @@ void CScraperParser::ConvertJSON(std::string &string) - int pos2 = reg2.GetSubStart(2); - std::string szHexValue(reg2.GetMatch(1)); - -- std::string replace = StringUtils::Format("%c", strtol(szHexValue.c_str(), NULL, 16)); -+ std::string replace = StringUtils::Format("%li", strtol(szHexValue.c_str(), NULL, 16)); - string.replace(string.begin()+pos1-2, string.begin()+pos2+reg2.GetSubLength(2), replace); - } - -diff --git a/xbmc/utils/SortUtils.cpp b/xbmc/utils/SortUtils.cpp -index 8292648..a2601dd 100644 ---- a/xbmc/utils/SortUtils.cpp -+++ b/xbmc/utils/SortUtils.cpp -@@ -68,12 +68,12 @@ string ByFile(SortAttribute attributes, const SortItem &values) - { - CURL url(values.at(FieldPath).asString()); - -- return StringUtils::Format("%s %d", url.GetFileNameWithoutPath().c_str(), values.at(FieldStartOffset).asInteger()); -+ return StringUtils::Format("%s %" PRId64, url.GetFileNameWithoutPath().c_str(), values.at(FieldStartOffset).asInteger()); - } - - string ByPath(SortAttribute attributes, const SortItem &values) - { -- return StringUtils::Format("%s %d", values.at(FieldPath).asString().c_str(), values.at(FieldStartOffset).asInteger()); -+ return StringUtils::Format("%s %" PRId64, values.at(FieldPath).asString().c_str(), values.at(FieldStartOffset).asInteger()); - } - - string ByLastPlayed(SortAttribute attributes, const SortItem &values) -@@ -355,7 +355,7 @@ string ByBitrate(SortAttribute attributes, const SortItem &values) - - string ByListeners(SortAttribute attributes, const SortItem &values) - { -- return StringUtils::Format("%i", values.at(FieldListeners).asInteger());; -+ return StringUtils::Format("%" PRId64, values.at(FieldListeners).asInteger());; - } - - string ByRandom(SortAttribute attributes, const SortItem &values) -diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp -index 131b598..a6e9efa 100644 ---- a/xbmc/video/VideoDatabase.cpp -+++ b/xbmc/video/VideoDatabase.cpp -@@ -2010,7 +2010,7 @@ bool CVideoDatabase::GetSeasonInfo(int idSeason, CVideoInfoTag& details) - return false; - - CFileItemList seasons; -- if (!GetSeasonsNav(StringUtils::Format("videodb://tvshows/titles/%ld/", idShow), seasons, -1, -1, -1, -1, idShow, false) || seasons.Size() <= 0) -+ if (!GetSeasonsNav(StringUtils::Format("videodb://tvshows/titles/%i/", idShow), seasons, -1, -1, -1, -1, idShow, false) || seasons.Size() <= 0) - return false; - - for (int index = 0; index < seasons.Size(); index++) -@@ -5259,7 +5259,7 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i - pItem->GetVideoInfoTag()->m_type = type; - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", it->first); -+ CStdString path = StringUtils::Format("%i/", it->first); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5282,7 +5282,7 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i - pItem->GetVideoInfoTag()->m_type = type; - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", m_pDS->fv(0).get_asInt()); -+ CStdString path = StringUtils::Format("%i/", m_pDS->fv(0).get_asInt()); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5373,7 +5373,7 @@ bool CVideoDatabase::GetTagsNav(const CStdString& strBaseDir, CFileItemList& ite - pItem->GetVideoInfoTag()->m_type = "tag"; - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", idTag); -+ CStdString path = StringUtils::Format("%i/", idTag); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5519,7 +5519,7 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileI - CFileItemPtr pItem(new CFileItem(it->second.first)); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", it->first); -+ CStdString path = StringUtils::Format("%i/", it->first); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5542,7 +5542,7 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileI - CFileItemPtr pItem(new CFileItem(m_pDS->fv(0).get_asString())); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", m_pDS->fv(1).get_asInt()); -+ CStdString path = StringUtils::Format("%i/", m_pDS->fv(1).get_asInt()); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5749,7 +5749,7 @@ bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& i - CFileItemPtr pItem(new CFileItem(it->second.name)); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", it->first); -+ CStdString path = StringUtils::Format("%i/", it->first); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5770,7 +5770,7 @@ bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& i - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", m_pDS->fv(0).get_asInt()); -+ CStdString path = StringUtils::Format("%i/", m_pDS->fv(0).get_asInt()); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5911,7 +5911,7 @@ bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it - CFileItemPtr pItem(new CFileItem(it->second.first)); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", it->first); -+ CStdString path = StringUtils::Format("%i/", it->first); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -5947,7 +5947,7 @@ bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it - CFileItemPtr pItem(new CFileItem(strLabel)); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", lYear); -+ CStdString path = StringUtils::Format("%i/", lYear); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -6330,7 +6330,7 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter - CFileItemPtr pItem(new CFileItem(movie)); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld", movie.m_iDbId); -+ CStdString path = StringUtils::Format("%i", movie.m_iDbId); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -6438,7 +6438,7 @@ bool CVideoDatabase::GetTvShowsByWhere(const CStdString& strBaseDir, const Filte - pItem->SetFromVideoInfoTag(movie); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld/", record->at(0).get_asInt()); -+ CStdString path = StringUtils::Format("%i/", record->at(0).get_asInt()); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -6570,9 +6570,9 @@ bool CVideoDatabase::GetEpisodesByWhere(const CStdString& strBaseDir, const Filt - CVideoDbUrl itemUrl = videoUrl; - CStdString path; - if (appendFullShowPath && videoUrl.GetItemType() != "episodes") -- path = StringUtils::Format("%ld/%ld/%ld", record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(), movie.m_iSeason, idEpisode); -+ path = StringUtils::Format("%i/%i/%i", record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(), movie.m_iSeason, idEpisode); - else -- path = StringUtils::Format("%ld", idEpisode); -+ path = StringUtils::Format("%i", idEpisode); - itemUrl.AppendPath(path); - pItem->SetPath(itemUrl.ToString()); - -@@ -7008,7 +7008,7 @@ void CVideoDatabase::GetMovieGenresByName(const CStdString& strSearch, CFileItem - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("genre.strGenre").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("genre.idGenre").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("genre.idGenre").get_asInt()); - pItem->SetPath("videodb://movies/genres/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7048,7 +7048,7 @@ void CVideoDatabase::GetMovieCountriesByName(const CStdString& strSearch, CFileI - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("country.strCountry").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("country.idCountry").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("country.idCountry").get_asInt()); - pItem->SetPath("videodb://movies/genres/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7087,7 +7087,7 @@ void CVideoDatabase::GetTvShowGenresByName(const CStdString& strSearch, CFileIte - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("genre.strGenre").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("genre.idGenre").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("genre.idGenre").get_asInt()); - pItem->SetPath("videodb://tvshows/genres/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7126,7 +7126,7 @@ void CVideoDatabase::GetMovieActorsByName(const CStdString& strSearch, CFileItem - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("actors.strActor").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("actors.idActor").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("actors.idActor").get_asInt()); - pItem->SetPath("videodb://movies/actors/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7165,7 +7165,7 @@ void CVideoDatabase::GetTvShowsActorsByName(const CStdString& strSearch, CFileIt - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("actors.strActor").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("actors.idActor").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("actors.idActor").get_asInt()); - pItem->SetPath("videodb://tvshows/actors/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7207,7 +7207,7 @@ void CVideoDatabase::GetMusicVideoArtistsByName(const CStdString& strSearch, CFi - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("actors.strActor").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("actors.idActor").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("actors.idActor").get_asInt()); - pItem->SetPath("videodb://musicvideos/artists/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7246,7 +7246,7 @@ void CVideoDatabase::GetMusicVideoGenresByName(const CStdString& strSearch, CFil - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv("genre.strGenre").get_asString())); -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("genre.idGenre").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("genre.idGenre").get_asInt()); - pItem->SetPath("videodb://musicvideos/genres/"+ strDir); - pItem->m_bIsFolder=true; - items.Add(pItem); -@@ -7300,7 +7300,7 @@ void CVideoDatabase::GetMusicVideoAlbumsByName(const CStdString& strSearch, CFil - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(0).get_asString())); -- CStdString strDir = StringUtils::Format("%ld", m_pDS->fv(1).get_asInt()); -+ CStdString strDir = StringUtils::Format("%i", m_pDS->fv(1).get_asInt()); - pItem->SetPath("videodb://musicvideos/titles/"+ strDir); - pItem->m_bIsFolder=false; - items.Add(pItem); -@@ -7339,7 +7339,7 @@ void CVideoDatabase::GetMusicVideosByAlbum(const CStdString& strSearch, CFileIte - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString()+" - "+m_pDS->fv(2).get_asString())); -- CStdString strDir = StringUtils::Format("3/2/%ld",m_pDS->fv("musicvideo.idMVideo").get_asInt()); -+ CStdString strDir = StringUtils::Format("3/2/%i",m_pDS->fv("musicvideo.idMVideo").get_asInt()); - - pItem->SetPath("videodb://"+ strDir); - pItem->m_bIsFolder=false; -@@ -7415,7 +7415,7 @@ bool CVideoDatabase::GetMusicVideosByWhere(const CStdString &baseDir, const Filt - CFileItemPtr item(new CFileItem(musicvideo)); - - CVideoDbUrl itemUrl = videoUrl; -- CStdString path = StringUtils::Format("%ld", record->at(0).get_asInt()); -+ CStdString path = StringUtils::Format("%i", record->at(0).get_asInt()); - itemUrl.AppendPath(path); - item->SetPath(itemUrl.ToString()); - -@@ -7489,7 +7489,7 @@ bool CVideoDatabase::GetRandomMusicVideo(CFileItem* item, int& idSong, const CSt - return false; - } - *item->GetVideoInfoTag() = GetDetailsForMusicVideo(m_pDS); -- CStdString path = StringUtils::Format("videodb://musicvideos/titles/%ld",item->GetVideoInfoTag()->m_iDbId); -+ CStdString path = StringUtils::Format("videodb://musicvideos/titles/%i",item->GetVideoInfoTag()->m_iDbId); - item->SetPath(path); - idSong = m_pDS->fv("idMVideo").get_asInt(); - item->SetLabel(item->GetVideoInfoTag()->m_strTitle); -@@ -7618,7 +7618,7 @@ void CVideoDatabase::GetTvShowsByName(const CStdString& strSearch, CFileItemList - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); -- CStdString strDir = StringUtils::Format("tvshows/titles/%ld/", m_pDS->fv("tvshow.idShow").get_asInt()); -+ CStdString strDir = StringUtils::Format("tvshows/titles/%i/", m_pDS->fv("tvshow.idShow").get_asInt()); - - pItem->SetPath("videodb://"+ strDir); - pItem->m_bIsFolder=true; -@@ -7659,7 +7659,7 @@ void CVideoDatabase::GetEpisodesByName(const CStdString& strSearch, CFileItemLis - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString()+" ("+m_pDS->fv(4).get_asString()+")")); -- CStdString path = StringUtils::Format("videodb://tvshows/titles/%ld/%ld/%ld",m_pDS->fv("episode.idShow").get_asInt(),m_pDS->fv(2).get_asInt(),m_pDS->fv(0).get_asInt()); -+ CStdString path = StringUtils::Format("videodb://tvshows/titles/%i/%i/%i",m_pDS->fv("episode.idShow").get_asInt(),m_pDS->fv(2).get_asInt(),m_pDS->fv(0).get_asInt()); - pItem->SetPath(path); - pItem->m_bIsFolder=false; - items.Add(pItem); -@@ -7702,7 +7702,7 @@ void CVideoDatabase::GetMusicVideosByName(const CStdString& strSearch, CFileItem - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); -- CStdString strDir = StringUtils::Format("3/2/%ld",m_pDS->fv("musicvideo.idMVideo").get_asInt()); -+ CStdString strDir = StringUtils::Format("3/2/%i",m_pDS->fv("musicvideo.idMVideo").get_asInt()); - - pItem->SetPath("videodb://"+ strDir); - pItem->m_bIsFolder=false; -@@ -7749,7 +7749,7 @@ void CVideoDatabase::GetEpisodesByPlot(const CStdString& strSearch, CFileItemLis - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString()+" ("+m_pDS->fv(4).get_asString()+")")); -- CStdString path = StringUtils::Format("videodb://tvshows/titles/%ld/%ld/%ld",m_pDS->fv("episode.idShow").get_asInt(),m_pDS->fv(2).get_asInt(),m_pDS->fv(0).get_asInt()); -+ CStdString path = StringUtils::Format("videodb://tvshows/titles/%i/%i/%i",m_pDS->fv("episode.idShow").get_asInt(),m_pDS->fv(2).get_asInt(),m_pDS->fv(0).get_asInt()); - pItem->SetPath(path); - pItem->m_bIsFolder=false; - items.Add(pItem); -@@ -7789,7 +7789,7 @@ void CVideoDatabase::GetMoviesByPlot(const CStdString& strSearch, CFileItemList& - } - - CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); -- CStdString path = StringUtils::Format("videodb://movies/titles/%ld", m_pDS->fv(0).get_asInt()); -+ CStdString path = StringUtils::Format("videodb://movies/titles/%i", m_pDS->fv(0).get_asInt()); - pItem->SetPath(path); - pItem->m_bIsFolder=false; - -@@ -7830,7 +7830,7 @@ void CVideoDatabase::GetMovieDirectorsByName(const CStdString& strSearch, CFileI - continue; - } - -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("directorlinkmovie.idDirector").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("directorlinkmovie.idDirector").get_asInt()); - CFileItemPtr pItem(new CFileItem(m_pDS->fv("actors.strActor").get_asString())); - - pItem->SetPath("videodb://movies/directors/"+ strDir); -@@ -7871,7 +7871,7 @@ void CVideoDatabase::GetTvShowsDirectorsByName(const CStdString& strSearch, CFil - continue; - } - -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("directorlinktvshow.idDirector").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("directorlinktvshow.idDirector").get_asInt()); - CFileItemPtr pItem(new CFileItem(m_pDS->fv("actors.strActor").get_asString())); - - pItem->SetPath("videodb://tvshows/studios/"+ strDir); -@@ -7912,7 +7912,7 @@ void CVideoDatabase::GetMusicVideoDirectorsByName(const CStdString& strSearch, C - continue; - } - -- CStdString strDir = StringUtils::Format("%ld/", m_pDS->fv("directorlinkmusicvideo.idDirector").get_asInt()); -+ CStdString strDir = StringUtils::Format("%i/", m_pDS->fv("directorlinkmusicvideo.idDirector").get_asInt()); - CFileItemPtr pItem(new CFileItem(m_pDS->fv("actors.strActor").get_asString())); - - pItem->SetPath("videodb://musicvideos/albums/"+ strDir); -diff --git a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp -index a744218..c792dfc 100644 ---- a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp -+++ b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp -@@ -220,7 +220,7 @@ void CGUIDialogVideoBookmarks::OnRefreshList() - - CStdString bookmarkTime; - if (m_bookmarks[i].type == CBookmark::EPISODE) -- bookmarkTime = StringUtils::Format("%s %i %s %i", g_localizeStrings.Get(20373).c_str(), m_bookmarks[i].seasonNumber, g_localizeStrings.Get(20359).c_str(), m_bookmarks[i].episodeNumber); -+ bookmarkTime = StringUtils::Format("%s %li %s %li", g_localizeStrings.Get(20373).c_str(), m_bookmarks[i].seasonNumber, g_localizeStrings.Get(20359).c_str(), m_bookmarks[i].episodeNumber); - else - bookmarkTime = StringUtils::SecondsToTimeString((long)m_bookmarks[i].timeInSeconds, TIME_FORMAT_HH_MM_SS); - -diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp -index a7d0c31..21d2a58 100644 ---- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp -+++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp -@@ -1702,7 +1702,7 @@ bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const CFileItemPtr &item, const - - for (size_t i = 0; i < thumbs.size(); i++) - { -- CFileItemPtr item(new CFileItem(StringUtils::Format("thumb://Remote%i", i), false)); -+ CFileItemPtr item(new CFileItem(StringUtils::Format("thumb://Remote%" PRIuS, i), false)); - item->SetArt("thumb", thumbs[i]); - item->SetIconImage("DefaultPicture.png"); - item->SetLabel(g_localizeStrings.Get(13513)); -diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp -index 03944cd..7dcca9c 100644 ---- a/xbmc/video/windows/GUIWindowVideoNav.cpp -+++ b/xbmc/video/windows/GUIWindowVideoNav.cpp -@@ -992,7 +992,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) - CStdString strPath; - CMusicDatabase database; - database.Open(); -- strPath = StringUtils::Format("musicdb://artists/%ld/", -+ strPath = StringUtils::Format("musicdb://artists/%i/", - database.GetArtistByName(StringUtils::Join(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator))); - g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV,strPath); - return true; -@@ -1002,7 +1002,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) - CStdString strPath; - CMusicDatabase database; - database.Open(); -- strPath = StringUtils::Format("musicdb://albums/%ld/", -+ strPath = StringUtils::Format("musicdb://albums/%i/", - database.GetAlbumByName(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum)); - g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV,strPath); - return true; -diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp -index 5473267..1a87307 100644 ---- a/xbmc/windows/GUIMediaWindow.cpp -+++ b/xbmc/windows/GUIMediaWindow.cpp -@@ -1218,7 +1218,7 @@ void CGUIMediaWindow::GetDirectoryHistoryString(const CFileItem* pItem, std::str - { - // Could be a cue item, all items of a cue share the same filename - // so add the offsets to build the history string -- strHistoryString = StringUtils::Format("%ld%ld", -+ strHistoryString = StringUtils::Format("%i%i", - pItem->m_lStartOffset, - pItem->m_lEndOffset); - strHistoryString += pItem->GetPath(); - -From 8e291c0d32d5996cf4c3ffc4645ebfc46b23fc93 Mon Sep 17 00:00:00 2001 +From b1acf2753346ecdf070a2c3b29af797b008545e7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 27 Sep 2014 15:27:04 +0100 -Subject: [PATCH 092/104] [omxplayer] Don't sync up to passthrough audio - packets - let GPU handle it +Subject: [PATCH 79/99] [omxplayer] Don't sync up to passthrough audio packets + - let GPU handle it --- xbmc/cores/omxplayer/OMXAudio.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp -index 2b7a83a..c0d7d01 100644 +index 3c6c73b..d7149d9 100644 --- a/xbmc/cores/omxplayer/OMXAudio.cpp +++ b/xbmc/cores/omxplayer/OMXAudio.cpp -@@ -1125,6 +1125,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt +@@ -1119,6 +1119,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt return len; } @@ -12431,7 +7884,7 @@ index 2b7a83a..c0d7d01 100644 if(m_eEncoding == OMX_AUDIO_CodingDTS && m_LostSync && (m_Passthrough || m_HWDecode)) { int skip = SyncDTS((uint8_t *)data, len); -@@ -1138,6 +1139,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt +@@ -1132,6 +1133,7 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt if(skip > 0) return len; } @@ -12440,18 +7893,18 @@ index 2b7a83a..c0d7d01 100644 unsigned pitch = (m_Passthrough || m_HWDecode) ? 1:(m_BitsPerSample >> 3) * m_InputChannels; unsigned int demuxer_samples = len / pitch; -From c381be449aa55772cc55ae0ba10df7f43024564a Mon Sep 17 00:00:00 2001 +From d7b9180b0396eee6fec27289de65960482032c1f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 27 Sep 2014 15:32:37 +0100 -Subject: [PATCH 093/104] [dvdplayer] exerimental: don't raise priority of - audio thread +Subject: [PATCH 80/99] [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 32374d4..f19d425 100644 +index c34b96f..c55e119 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -3320,7 +3320,11 @@ bool CDVDPlayer::OpenAudioStream(CDVDStreamInfo& hint, bool reset) @@ -12467,58 +7920,10 @@ index 32374d4..f19d425 100644 } -From f41e1e46ea972bf74526270a1ed1b04e2bf274a6 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 27 Sep 2014 18:15:50 +0100 -Subject: [PATCH 094/104] [mmalrenderer] squash: Make update logging only - verbose - ---- - xbmc/cores/VideoRenderers/MMALRenderer.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -index b7bcaeb..6c4636e 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -@@ -346,7 +346,9 @@ void CMMALRenderer::Flush() - - void CMMALRenderer::Update() - { -+#if defined(MMAL_DEBUG_VERBOSE) - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); -+#endif - if (!m_bConfigured) return; - ManageDisplay(); - } - -From 95e5a56c6fd12f95755ccfd722e339926e5bbf9f Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 27 Sep 2014 18:23:38 +0100 -Subject: [PATCH 095/104] [mmalcodec] squash: whitespace - ---- - 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 d9a94d5..10af56f 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -@@ -576,7 +576,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide - } - - if ( (m_codingType == MMAL_ENCODING_MP2V && !g_RBP.GetCodecMpg2() ) || -- (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) -+ (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) - { - CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported", CLASSNAME, __func__, m_pFormatName); - return false; - -From 5a59f7db698bdd5185e489cfca5e0145eeb04528 Mon Sep 17 00:00:00 2001 +From f201e6105d7268d3c49fca9059621a4511db09d5 Mon Sep 17 00:00:00 2001 From: da-anda Date: Sun, 17 Aug 2014 21:09:59 +0200 -Subject: [PATCH 096/104] handle stereoscopic mode of videos in mixed playlists +Subject: [PATCH 81/99] handle stereoscopic mode of videos in mixed playlists --- language/English/strings.po | 2 +- @@ -12526,10 +7931,10 @@ Subject: [PATCH 096/104] handle stereoscopic mode of videos in mixed playlists 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/language/English/strings.po b/language/English/strings.po -index 0ca4b23..8ed90bd 100755 +index aba172a..5143e3e 100755 --- a/language/English/strings.po +++ b/language/English/strings.po -@@ -15596,7 +15596,7 @@ msgstr "" +@@ -15612,7 +15612,7 @@ msgstr "" #. Description of setting "Videos -> Playback -> Disable stereoscopic mode when playback is stopped" with label #36526 #: system/settings/settings.xml msgctxt "#36538" @@ -12686,10 +8091,10 @@ index 35ba597..b013942 100644 case 2: // Mono SetStereoMode( RENDER_STEREO_MODE_MONO ); -From 54147b9da63d18e41f87bc16a162c237fe70a67c Mon Sep 17 00:00:00 2001 +From 9e888b8b6d3e4b55d57e16c443449497ac7ef520 Mon Sep 17 00:00:00 2001 From: da-anda Date: Sat, 16 Aug 2014 11:20:54 +0200 -Subject: [PATCH 097/104] remember user selected 3D modes between videos until +Subject: [PATCH 82/99] remember user selected 3D modes between videos until playback ended --- @@ -12906,89 +8311,10 @@ index c1dfb93..cb54bd0 100644 -From 8a3efec846daa70e9cf64bbdf0e725c927ca7698 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 28 Sep 2014 12:13:37 +0100 -Subject: [PATCH 098/104] [mmalrenderer] Always use higher buffer_num. Avoids - an ENOMEM failure - ---- - xbmc/cores/VideoRenderers/MMALRenderer.cpp | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -index 6c4636e..fdeabf4 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -@@ -100,10 +100,7 @@ bool CMMALRenderer::init_vout(MMAL_ES_FORMAT_T *format) - return false; - } - -- if (m_format == RENDER_FMT_YUV420P) -- m_vout_input->buffer_num = NUM_BUFFERS; -- else -- m_vout_input->buffer_num = m_vout_input->buffer_num_min; -+ m_vout_input->buffer_num = NUM_BUFFERS; - m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; - - status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); - -From 22afde57a22b2c9dd2bdb82ab76dd2c8a5a136d0 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 28 Sep 2014 12:35:59 +0100 -Subject: [PATCH 099/104] squash: boost centre - ---- - xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -index a9a03ce..bb60f9d 100644 ---- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp -@@ -23,6 +23,7 @@ - #if !defined(TARGET_RASPBERRY_PI) - - #include "ActiveAEResample.h" -+#include "settings/Settings.h" - #include "utils/log.h" - - extern "C" { - -From fb7eaeb3a030f53e0458b2e380c1a01b0d437f32 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 28 Sep 2014 16:20:28 +0100 -Subject: [PATCH 100/104] [omxplayer] Fix bad audio when sample_fmt is not - reported on Open - -For most codecs ffmpeg reports m_pCodecContext->sample_fmt on the avcodec_open2 call (e.g. ac3, dts, aac). -However some (PCM on dvd) report AV_SAMPLE_FMT_NONE on open, and only provide the correct format on decode. - -This can cause the GetBitsPerSample call to change between open and decode and results in white noise when the word size is misinterpreted. - -The simple solution is to always convert to float when open doesn't report the format and ensure GetBitsPerSample reports this value ---- - xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp -index ffbaf56..94b673e 100644 ---- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp -+++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp -@@ -302,7 +302,7 @@ int COMXAudioCodecOMX::GetBitsPerSample() - { - if (!m_pCodecContext) - return 0; -- return m_pCodecContext->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 32; -+ return m_desiredSampleFormat == AV_SAMPLE_FMT_S16 ? 16 : 32; - } - - int COMXAudioCodecOMX::GetBitRate() - -From 061846bbd7f9b8c63bd1ba593bc5276a0774aeee Mon Sep 17 00:00:00 2001 +From 636340c2550eb0e990b9e9a3f6f198dcbee6027e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 28 Sep 2014 17:35:31 +0100 -Subject: [PATCH 101/104] [renderer] Avoid warning for too few buffers with +Subject: [PATCH 83/99] [renderer] Avoid warning for too few buffers with bypass renderer Bypass renderer doesn't use a video render queue, so shouldn't generate a warning message @@ -12997,7 +8323,7 @@ Bypass renderer doesn't use a video render queue, so shouldn't generate a warnin 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index e72d791..b02f368 100644 +index 1ecdc16..cc3a76b 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -270,7 +270,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi @@ -13011,118 +8337,10 @@ index e72d791..b02f368 100644 m_pRenderer->SetBufferSize(m_QueueSize); -From 11091ce1c1679e07780ecaaffd088166d2561c04 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 28 Sep 2014 18:55:25 +0100 -Subject: [PATCH 102/104] [mmalrenderer] squash: Remove GetProcessorSize - ---- - xbmc/cores/VideoRenderers/MMALRenderer.cpp | 8 -------- - xbmc/cores/VideoRenderers/MMALRenderer.h | 1 - - 2 files changed, 9 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -index fdeabf4..1e73649 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp -@@ -577,14 +577,6 @@ EINTERLACEMETHOD CMMALRenderer::AutoInterlaceMethod() - return VS_INTERLACEMETHOD_DEINTERLACE_HALF; - } - --unsigned int CMMALRenderer::GetProcessorSize() --{ -- if (m_format == RENDER_FMT_MMAL) -- return 1; -- else -- return 0; --} -- - void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect) - { - // we get called twice a frame for left/right. Can ignore the rights. -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h -index 8cff140..952c154 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.h -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.h -@@ -87,7 +87,6 @@ class CMMALRenderer : public CBaseRenderer, public CThread - - virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } -- virtual unsigned int GetProcessorSize(); - virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); - - void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); - -From 19e595cb97adbe1f1bce0fefc66db7c90492f8ed Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 28 Sep 2014 17:03:49 +0100 -Subject: [PATCH 103/104] [mmal] Increase number of render buffers - ---- - xbmc/cores/VideoRenderers/MMALRenderer.h | 2 ++ - xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 2 +- - xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 3 ++- - 3 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h -index 952c154..3488ce0 100644 ---- a/xbmc/cores/VideoRenderers/MMALRenderer.h -+++ b/xbmc/cores/VideoRenderers/MMALRenderer.h -@@ -31,6 +31,7 @@ - #include "cores/dvdplayer/DVDStreamInfo.h" - #include "guilib/Geometry.h" - #include "threads/Thread.h" -+#include "BaseRenderer.h" - - #include - #include -@@ -87,6 +88,7 @@ class CMMALRenderer : public CBaseRenderer, public CThread - - virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } -+ virtual unsigned int GetOptimalBufferSize() { return NUM_BUFFERS; } - virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); - - void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer); -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -index 10af56f..69e36d8 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -@@ -619,7 +619,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide - 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)); - -- status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, 5); -+ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, NUM_BUFFERS); - 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)); - -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -index ef83a65..96573c6 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -@@ -39,6 +39,7 @@ - #include "utils/StdString.h" - #include "guilib/Geometry.h" - #include "rendering/RenderSystem.h" -+#include "cores/VideoRenderers/BaseRenderer.h" - - class CMMALVideo; - typedef boost::shared_ptr MMALVideoPtr; -@@ -85,7 +86,7 @@ class CMMALVideo - virtual void Reset(void); - virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); - virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); -- virtual unsigned GetAllowedReferences() { return 2; } -+ virtual unsigned GetAllowedReferences() { return NUM_BUFFERS; } - virtual void SetDropState(bool bDrop); - virtual const char* GetName(void) { return (const char*)m_pFormatName; } - virtual bool GetCodecStats(double &pts, int &droppedPics); - -From 35b513bf8db50180ae889f4214b0073565737a5e Mon Sep 17 00:00:00 2001 +From a0b4e3298118625508321a8d132bd06b8440741d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 28 Sep 2014 19:28:17 +0100 -Subject: [PATCH 104/104] [mmalcodec] Introduce a preroll period to buffer up +Subject: [PATCH 84/99] [mmalcodec] Introduce a preroll period to buffer up frames on startup --- @@ -13131,10 +8349,10 @@ Subject: [PATCH 104/104] [mmalcodec] Introduce a preroll period to buffer up 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -index 69e36d8..b77e9e2 100644 +index 6a1f70a..c9aa390 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp -@@ -135,6 +135,7 @@ CMMALVideo::CMMALVideo() +@@ -136,6 +136,7 @@ CMMALVideo::CMMALVideo() m_output_busy = 0; m_demux_queue_length = 0; m_es_format = mmal_format_alloc(); @@ -13142,7 +8360,7 @@ index 69e36d8..b77e9e2 100644 } CMMALVideo::~CMMALVideo() -@@ -689,6 +690,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide +@@ -699,6 +700,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide m_drop_state = false; m_startframe = false; @@ -13150,7 +8368,7 @@ index 69e36d8..b77e9e2 100644 return true; } -@@ -899,24 +901,26 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) +@@ -910,24 +912,26 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts) break; } int ret = 0; @@ -13185,7 +8403,7 @@ index 69e36d8..b77e9e2 100644 Sleep(10); // otherwise we busy spin } return ret; -@@ -960,6 +964,7 @@ void CMMALVideo::Reset(void) +@@ -971,6 +975,7 @@ void CMMALVideo::Reset(void) m_decoderPts = DVD_NOPTS_VALUE; m_droppedPics = 0; m_decode_frame_number = 1; @@ -13194,10 +8412,10 @@ index 69e36d8..b77e9e2 100644 diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -index 96573c6..99dcd7f 100644 +index b4aa571..a2da46b 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h -@@ -139,6 +139,7 @@ class CMMALVideo +@@ -140,6 +140,7 @@ class CMMALVideo unsigned int m_decode_frame_number; double m_decoderPts; unsigned int m_droppedPics; @@ -13205,3 +8423,3318 @@ index 96573c6..99dcd7f 100644 MMAL_COMPONENT_T *m_dec; MMAL_PORT_T *m_dec_input; + +From e661aa6bc04e0848bfb1f022014a95ef69c79ecc Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 11 Apr 2014 16:12:27 +0100 +Subject: [PATCH 85/99] [omxplayer] Add ability to log more timestamp info in + extra debug settings + +--- + language/English/strings.po | 5 +++++ + xbmc/commons/ilog.h | 1 + + xbmc/cores/dvdplayer/DVDPlayer.cpp | 10 ++++++---- + xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 8 ++++---- + xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 9 +++++---- + xbmc/settings/AdvancedSettings.cpp | 3 +++ + 6 files changed, 24 insertions(+), 12 deletions(-) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 5143e3e..2800c80 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -2886,6 +2886,11 @@ msgctxt "#679" + msgid "Verbose logging for CEC library" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#697" ++msgid "Verbose logging for OMXPLAYER" ++msgstr "" ++ + #empty strings from id 680 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index 92e2835..ad02d95 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -53,6 +53,7 @@ + #define LOGAIRTUNES (1 << (LOGMASKBIT + 8)) + #define LOGUPNP (1 << (LOGMASKBIT + 9)) + #define LOGCEC (1 << (LOGMASKBIT + 10)) ++#define LOGOMXPLAYER (1 << (LOGMASKBIT+11)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index c55e119..6a9707b7 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1135,7 +1135,8 @@ void CDVDPlayer::OMXDoProcessing() + 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) + { +@@ -1155,7 +1156,7 @@ void CDVDPlayer::OMXDoProcessing() + 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; +@@ -1171,13 +1172,14 @@ void CDVDPlayer::OMXDoProcessing() + 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)) + { +diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +index 01d2afc..b4d8418 100644 +--- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +@@ -362,10 +362,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 c2bd788..5c4a515 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 2e2854f..413c55a 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1389,6 +1389,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 dc0d123d7e79e9c56f950ba2cb543ec1e8e624a7 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 7 Apr 2014 23:13:55 +0100 +Subject: [PATCH 86/99] [omxplayer] Add ability to dump out audio/video data + for later debugging + +--- + language/English/strings.po | 10 ++++++++ + xbmc/commons/ilog.h | 2 ++ + xbmc/cores/omxplayer/OMXAudio.cpp | 49 ++++++++++++++++++++++++++++++++++++++ + xbmc/cores/omxplayer/OMXVideo.cpp | 47 ++++++++++++++++++++++++++++++++++++ + xbmc/settings/AdvancedSettings.cpp | 4 ++++ + 5 files changed, 112 insertions(+) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 2800c80..989cfcc 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -2891,6 +2891,16 @@ msgctxt "#697" + msgid "Verbose logging for OMXPLAYER" + msgstr "" + ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#698" ++msgid "Dump video frames to debug file" ++msgstr "" ++ ++#: xbmc/settings/AdvancedSettings.cpp ++msgctxt "#699" ++msgid "Dump audio frames to debug file" ++msgstr "" ++ + #empty strings from id 680 to 699 + + msgctxt "#700" +diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h +index ad02d95..be40370 100644 +--- a/xbmc/commons/ilog.h ++++ b/xbmc/commons/ilog.h +@@ -54,6 +54,8 @@ + #define LOGUPNP (1 << (LOGMASKBIT + 9)) + #define LOGCEC (1 << (LOGMASKBIT + 10)) + #define LOGOMXPLAYER (1 << (LOGMASKBIT+11)) ++#define LOGDUMPVIDEO (1 << (LOGMASKBIT+12)) ++#define LOGDUMPAUDIO (1 << (LOGMASKBIT+13)) + + #include "utils/params_check_macros.h" + +diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp +index d7149d9..f0ae0cc 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -60,6 +60,49 @@ static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0}; + + static const uint16_t DTSFSCod [] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0}; + ++//#define DEBUG_PLAYBACK ++static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) ++{ ++ if (!(g_advancedSettings.CanLogComponent(LOGDUMPAUDIO))) ++ return; ++ static FILE *fp; ++ if (!omx_buffer) ++ { ++ if (fp) ++ { ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, "audio.dat"); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ OMX_BUFFERHEADERTYPE omx = {0}; ++ int s = fread(&omx, sizeof omx, 1, fp); ++ omx_buffer->nFilledLen = omx.nFilledLen; ++ omx_buffer->nFlags = omx.nFlags; ++ omx_buffer->nTimeStamp = omx.nTimeStamp; ++ if (s==1) ++ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#else ++ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) ++ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#endif ++ } ++} ++ + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// +@@ -867,6 +910,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) + { +@@ -899,6 +943,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() + CLog::Log(LOGNOTICE, "COMXAudio::%s start", __func__); + 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() ) +@@ -1243,6 +1290,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) + { +@@ -1490,6 +1538,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 0363aaa..6cfb148 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -63,6 +63,49 @@ + + #define MAX_TEXT_LENGTH 1024 + ++//#define DEBUG_PLAYBACK ++static void dump_omx_buffer(OMX_BUFFERHEADERTYPE *omx_buffer) ++{ ++ if (!(g_advancedSettings.CanLogComponent(LOGDUMPVIDEO))) ++ return; ++ static FILE *fp; ++ if (!omx_buffer) ++ { ++ if (fp) ++ { ++ fclose(fp); ++ fp = NULL; ++ } ++ return; ++ } ++ if (!fp) ++ { ++ char filename[1024]; ++ strcpy(filename, g_advancedSettings.m_logFolder.c_str()); ++ strcat(filename, "video.dat"); ++#ifdef DEBUG_PLAYBACK ++ fp = fopen(filename, "rb"); ++#else ++ fp = fopen(filename, "wb"); ++#endif ++ } ++ if (fp) ++ { ++#ifdef DEBUG_PLAYBACK ++ OMX_BUFFERHEADERTYPE omx = {0}; ++ int s = fread(&omx, sizeof omx, 1, fp); ++ omx_buffer->nFilledLen = omx.nFilledLen; ++ omx_buffer->nFlags = omx.nFlags; ++ omx_buffer->nTimeStamp = omx.nTimeStamp; ++ if (s==1) ++ fread(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#else ++ if (fwrite(omx_buffer, sizeof *omx_buffer, 1, fp) == 1) ++ fwrite(omx_buffer->pBuffer, omx_buffer->nFilledLen, 1, fp); ++#endif ++ } ++} ++ + COMXVideo::COMXVideo() : m_video_codec_name("") + { + m_is_open = false; +@@ -118,6 +161,7 @@ bool COMXVideo::SendDecoderConfig() + memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen); + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + ++ dump_omx_buffer(omx_buffer); + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); + if (omx_err != OMX_ErrorNone) + { +@@ -707,6 +751,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) +@@ -801,6 +846,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) + { +@@ -931,6 +977,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 413c55a..0c84e99 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -1392,6 +1392,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 73b1c2d5ff0942e1f873d8a219560955bae83fbb Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 30 Sep 2014 20:52:13 +0100 +Subject: [PATCH 87/99] Revert "hack: revert squash: don't update originaldts + when marked as invalid" + +This reverts commit 001dbfdefe45a3883e6f7d59525462e97bade4ee. +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 6a9707b7..90dd142 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -2108,7 +2108,6 @@ void CDVDPlayer::CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket) + // not sure yet - flags the packets as unknown until we get confirmation on another audio/video packet + pPacket->dts = DVD_NOPTS_VALUE; + pPacket->pts = DVD_NOPTS_VALUE; +- current.originaldts = pPacket->dts; + } + } + else + +From 87bb444eb6b641078daee9ce43cc7a97d9b0111c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Oct 2014 16:34:51 +0100 +Subject: [PATCH 88/99] [mmalcodec] squash: Avoid preroll when using trickplay + +--- + 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, 19 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +index 55b9969..262283d 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp +@@ -96,4 +96,9 @@ bool CDVDVideoCodecMMAL::GetCodecStats(double &pts, int &droppedPics) + return m_decoder->GetCodecStats(pts, droppedPics); + } + ++void CDVDVideoCodecMMAL::SetSpeed(int iSpeed) ++{ ++ m_decoder->SetSpeed(iSpeed); ++} ++ + #endif +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h +index 67aa505..a768e70 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 SetSpeed(int iSpeed); + + protected: + MMALVideoPtr m_decoder; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index c9aa390..cee1499 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -137,6 +137,7 @@ CMMALVideo::CMMALVideo() + m_demux_queue_length = 0; + m_es_format = mmal_format_alloc(); + m_preroll = true; ++ m_speed = DVD_PLAYSPEED_NORMAL; + } + + CMMALVideo::~CMMALVideo() +@@ -701,6 +702,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide + m_drop_state = false; + m_startframe = false; + m_preroll = !m_hints.stills; ++ m_speed = DVD_PLAYSPEED_NORMAL; + + return true; + } +@@ -975,9 +977,17 @@ void CMMALVideo::Reset(void) + m_decoderPts = DVD_NOPTS_VALUE; + m_droppedPics = 0; + m_decode_frame_number = 1; +- m_preroll = !m_hints.stills; ++ m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE); + } + ++void CMMALVideo::SetSpeed(int iSpeed) ++{ ++#if defined(MMAL_DEBUG_VERBOSE) ++ CLog::Log(LOGDEBUG, "%s::%s %d->%d", CLASSNAME, __func__, m_speed, iSpeed); ++#endif ++ ++ m_speed = iSpeed; ++} + + void CMMALVideo::ReturnBuffer(CMMALVideoBuffer *buffer) + { +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +index a2da46b..4f81bbd 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 SetSpeed(int iSpeed); + + // MMAL decoder callback routines. + void ReleaseBuffer(CMMALVideoBuffer *buffer); +@@ -140,6 +141,7 @@ class CMMALVideo + unsigned int m_decode_frame_number; + double m_decoderPts; + unsigned int m_droppedPics; ++ int m_speed; + bool m_preroll; + + MMAL_COMPONENT_T *m_dec; + +From 53f4c6a2d2f39fbecd30316cdb3f99626a1b9f5c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Oct 2014 22:44:22 +0100 +Subject: [PATCH 90/99] [dvdplayer] Remove omx render features from dvdplayer + and handle in mmalrenderer + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 48 ------------------------------ + xbmc/cores/VideoRenderers/MMALRenderer.h | 5 ---- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 29 ------------------ + xbmc/cores/dvdplayer/DVDPlayer.h | 6 ---- + 4 files changed, 88 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 692379c..5fb6dce 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -190,25 +190,6 @@ bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned + + m_RenderUpdateCallBackFn = NULL; + m_RenderUpdateCallBackCtx = NULL; +- if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer()) +- { +- m_renderFeatures.clear(); +- m_scalingMethods.clear(); +- m_deinterlaceModes.clear(); +- m_deinterlaceMethods.clear(); +- +- if (m_RenderFeaturesCallBackFn) +- { +- (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures); +- // after setting up m_renderFeatures, we are done with the callback +- m_RenderFeaturesCallBackFn = NULL; +- m_RenderFeaturesCallBackCtx = NULL; +- } +- g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures); +- g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods); +- g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes); +- g_application.m_pPlayer->GetScalingMethods(m_scalingMethods); +- } + + // calculate the input frame aspect ratio + CalculateFrameAspectRatio(d_width, d_height); +@@ -480,8 +461,6 @@ void CMMALRenderer::UnInit() + + m_RenderUpdateCallBackFn = NULL; + m_RenderUpdateCallBackCtx = NULL; +- m_RenderFeaturesCallBackFn = NULL; +- m_RenderFeaturesCallBackCtx = NULL; + + m_src_rect.SetRect(0, 0, 0, 0); + m_dst_rect.SetRect(0, 0, 0, 0); +@@ -511,13 +490,6 @@ bool CMMALRenderer::RenderCapture(CRenderCapture* capture) + + bool CMMALRenderer::Supports(EDEINTERLACEMODE mode) + { +- // Player controls render, let it dictate available deinterlace modes +- if (m_format == RENDER_FMT_BYPASS) +- { +- Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode); +- return itr != m_deinterlaceModes.end(); +- } +- + if(mode == VS_DEINTERLACEMODE_OFF + || mode == VS_DEINTERLACEMODE_AUTO + || mode == VS_DEINTERLACEMODE_FORCE) +@@ -528,13 +500,6 @@ bool CMMALRenderer::Supports(EDEINTERLACEMODE mode) + + bool CMMALRenderer::Supports(EINTERLACEMETHOD method) + { +- // Player controls render, let it dictate available deinterlace methods +- if (m_format == RENDER_FMT_BYPASS) +- { +- Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method); +- return itr != m_deinterlaceMethods.end(); +- } +- + if (method == VS_INTERLACEMETHOD_DEINTERLACE) + return true; + +@@ -543,13 +508,6 @@ bool CMMALRenderer::Supports(EINTERLACEMETHOD method) + + bool CMMALRenderer::Supports(ERENDERFEATURE feature) + { +- // Player controls render, let it dictate available render features +- if (m_format == RENDER_FMT_BYPASS) +- { +- Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature); +- return itr != m_renderFeatures.end(); +- } +- + if (feature == RENDERFEATURE_STRETCH || + feature == RENDERFEATURE_ZOOM || + feature == RENDERFEATURE_ROTATION || +@@ -562,12 +520,6 @@ bool CMMALRenderer::Supports(ERENDERFEATURE feature) + + bool CMMALRenderer::Supports(ESCALINGMETHOD method) + { +- // Player controls render, let it dictate available scaling methods +- if (m_format == RENDER_FMT_BYPASS) +- { +- Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method); +- return itr != m_scalingMethods.end(); +- } + return false; + } + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h +index 3488ce0..8ca0b94 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.h ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.h +@@ -104,11 +104,6 @@ class CMMALRenderer : public CBaseRenderer, public CThread + unsigned int m_destHeight; + int m_neededBuffers; + +- Features m_renderFeatures; +- Features m_deinterlaceMethods; +- Features m_deinterlaceModes; +- Features m_scalingMethods; +- + CRect m_src_rect; + CRect m_dst_rect; + RENDER_STEREO_MODE m_video_stereo_mode; +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 90dd142..22e27ea 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -4497,32 +4497,3 @@ bool CDVDPlayer::CachePVRStream(void) const + !g_PVRManager.IsPlayingRecording() && + g_advancedSettings.m_bPVRCacheInDvdPlayer; + } +- +-void CDVDPlayer::OMXGetRenderFeatures(std::vector &renderFeatures) +-{ +- if (m_omxplayer_mode) +- { +- renderFeatures.push_back(RENDERFEATURE_STRETCH); +- renderFeatures.push_back(RENDERFEATURE_CROP); +- renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO); +- renderFeatures.push_back(RENDERFEATURE_ZOOM); +- } +-} +- +-void CDVDPlayer::OMXGetDeinterlaceMethods(std::vector &deinterlaceMethods) +-{ +- if (m_omxplayer_mode) +- { +- deinterlaceMethods.push_back(VS_INTERLACEMETHOD_DEINTERLACE); +- } +-} +- +-void CDVDPlayer::OMXGetDeinterlaceModes(std::vector &deinterlaceModes) +-{ +- if (m_omxplayer_mode) +- { +- deinterlaceModes.push_back(VS_DEINTERLACEMODE_AUTO); +- deinterlaceModes.push_back(VS_DEINTERLACEMODE_OFF); +- deinterlaceModes.push_back(VS_DEINTERLACEMODE_FORCE); +- } +-} +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h +index 32f350b..dac00e9 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -286,12 +286,6 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer + + virtual int OnDVDNavResult(void* pData, int iMessage); + +- // Note: the following "OMX" methods are deprecated and will be removed in the future +- // They should be handled by the video renderer, not the player +- virtual void OMXGetRenderFeatures(std::vector &renderFeatures); +- virtual void OMXGetDeinterlaceMethods(std::vector &deinterlaceMethods); +- virtual void OMXGetDeinterlaceModes(std::vector &deinterlaceModes); +- + virtual bool ControlsVolume() {return m_omxplayer_mode;} + + protected: + +From b37024fd026e62b5357b4a663ef7af35ad175af5 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Oct 2014 22:45:09 +0100 +Subject: [PATCH 91/99] [mmalrenderer] Add choice of 3 deinterlace schemes + +--- + xbmc/cores/VideoRenderers/MMALRenderer.cpp | 4 ++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 4 +++- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 5 ++++- + xbmc/cores/dvdplayer/DVDPlayer.h | 1 + + xbmc/cores/omxplayer/OMXVideo.cpp | 11 ++++++++--- + 5 files changed, 20 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +index 5fb6dce..9cb4d60 100644 +--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp ++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp +@@ -502,6 +502,10 @@ bool CMMALRenderer::Supports(EINTERLACEMETHOD method) + { + if (method == VS_INTERLACEMETHOD_DEINTERLACE) + return true; ++ if (method == VS_INTERLACEMETHOD_DEINTERLACE_HALF) ++ return true; ++ if (method == VS_INTERLACEMETHOD_RENDER_BOB) ++ return true; + + return false; + } +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +index cee1499..42c62db 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +@@ -366,7 +366,9 @@ 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; + } +- MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 1, {3}}; ++ MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, ++ interlace_method == VS_INTERLACEMETHOD_DEINTERLACE ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, ++ 3, {3, 0, interlace_method == VS_INTERLACEMETHOD_DEINTERLACE_HALF }}; + status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr); + if (status != MMAL_SUCCESS) + { +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 22e27ea..b335a83 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -618,6 +618,7 @@ CDVDPlayer::CDVDPlayer(IPlayerCallback& callback) + m_OmxPlayerState.bOmxSentEOFs = false; + m_OmxPlayerState.threshold = 0.2f; + m_OmxPlayerState.current_deinterlace = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ m_OmxPlayerState.interlace_method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); + #ifdef HAS_OMXPLAYER + m_omxplayer_mode = CSettings::Get().GetBool("videoplayer.useomxplayer"); + #else +@@ -1123,13 +1124,15 @@ void CDVDPlayer::OMXDoProcessing() + bool audio_fifo_low = false, video_fifo_low = false, audio_fifo_high = false, video_fifo_high = false; + + // if deinterlace setting has changed, we should close and open video +- if (m_OmxPlayerState.current_deinterlace != CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode) ++ if (m_OmxPlayerState.current_deinterlace != CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode || ++ m_OmxPlayerState.interlace_method != g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod)) + { + CloseStream(m_CurrentVideo, false); + OpenStream(m_CurrentVideo, m_CurrentVideo.id, m_CurrentVideo.source); + if (m_State.canseek) + m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true, true, true)); + m_OmxPlayerState.current_deinterlace = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ m_OmxPlayerState.interlace_method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); + } + + m_OmxPlayerState.video_fifo = (int)(100.0*(m_dvdPlayerVideo->GetDecoderBufferSize()-m_dvdPlayerVideo->GetDecoderFreeSpace())/m_dvdPlayerVideo->GetDecoderBufferSize()); +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h +index dac00e9..88f5cf8 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -541,6 +541,7 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer + { + OMXClock av_clock; // openmax clock component + EDEINTERLACEMODE current_deinterlace; // whether deinterlace is currently enabled ++ EINTERLACEMETHOD interlace_method; // current deinterlace method + bool bOmxWaitVideo; // whether we need to wait for video to play out on EOS + bool bOmxWaitAudio; // whether we need to wait for audio to play out on EOS + bool bOmxSentEOFs; // flag if we've send EOFs to audio/video players +diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp +index 6cfb148..37765b1 100644 +--- a/xbmc/cores/omxplayer/OMXVideo.cpp ++++ b/xbmc/cores/omxplayer/OMXVideo.cpp +@@ -30,6 +30,8 @@ + #include "linux/XMemUtils.h" + #include "DVDDemuxers/DVDDemuxUtils.h" + #include "settings/AdvancedSettings.h" ++#include "settings/MediaSettings.h" ++#include "cores/VideoRenderers/RenderManager.h" + #include "xbmc/guilib/GraphicContext.h" + #include "settings/Settings.h" + #include "utils/BitstreamConverter.h" +@@ -298,8 +300,9 @@ bool COMXVideo::PortSettingsChanged() + + if(m_deinterlace) + { +- bool advanced_deinterlace = port_image.format.video.nFrameWidth * port_image.format.video.nFrameHeight <= 576 * 720; +- ++ EINTERLACEMETHOD interlace_method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); ++ bool advanced_deinterlace = interlace_method == VS_INTERLACEMETHOD_DEINTERLACE && port_image.format.video.nFrameWidth * port_image.format.video.nFrameHeight <= 576 * 720; ++ bool half_framerate = interlace_method == VS_INTERLACEMETHOD_DEINTERLACE_HALF; + if (!advanced_deinterlace) + { + // Image_fx assumed 3 frames of context. simple deinterlace doesn't require this +@@ -319,8 +322,10 @@ bool COMXVideo::PortSettingsChanged() + OMX_INIT_STRUCTURE(image_filter); + + image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); +- image_filter.nNumParams = 1; ++ image_filter.nNumParams = 3; + image_filter.nParams[0] = 3; ++ image_filter.nParams[1] = 0; ++ image_filter.nParams[2] = half_framerate; + if (!advanced_deinterlace) + image_filter.eImageFilter = OMX_ImageFilterDeInterlaceFast; + else + +From 268ea34172c14df4daaab4f4533f6a45eef5c9d6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 17:50:28 +0100 +Subject: [PATCH 93/99] [AE] Add factory for AEResampler + +--- + xbmc/cores/AudioEngine/AEResampleFactory.cpp | 149 ++++++++ + xbmc/cores/AudioEngine/AEResampleFactory.h | 43 +++ + .../AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 6 +- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h | 2 +- + .../Engines/ActiveAE/ActiveAEBuffer.cpp | 25 +- + .../AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h | 4 +- + .../Engines/ActiveAE/ActiveAEResample.cpp | 388 --------------------- + .../Engines/ActiveAE/ActiveAEResample.h | 65 ---- + .../Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp | 282 +++++++++++++++ + .../Engines/ActiveAE/ActiveAEResampleFFMPEG.h | 62 ++++ + .../AudioEngine/Engines/ActiveAE/ActiveAESink.cpp | 12 +- + .../AudioEngine/Engines/ActiveAE/ActiveAESink.h | 2 +- + .../AudioEngine/Engines/ActiveAE/ActiveAESound.h | 2 +- + .../Engines/ActiveAE/ActiveAEStream.cpp | 15 +- + .../AudioEngine/Engines/ActiveAE/ActiveAEStream.h | 2 +- + xbmc/cores/AudioEngine/Interfaces/AEResample.h | 53 +++ + xbmc/cores/AudioEngine/Makefile.in | 4 +- + xbmc/cores/paplayer/DVDPlayerCodec.cpp | 12 +- + xbmc/cores/paplayer/DVDPlayerCodec.h | 4 +- + 19 files changed, 637 insertions(+), 495 deletions(-) + create mode 100644 xbmc/cores/AudioEngine/AEResampleFactory.cpp + create mode 100644 xbmc/cores/AudioEngine/AEResampleFactory.h + delete mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp + delete mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h + create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp + create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h + create mode 100644 xbmc/cores/AudioEngine/Interfaces/AEResample.h + +diff --git a/xbmc/cores/AudioEngine/AEResampleFactory.cpp b/xbmc/cores/AudioEngine/AEResampleFactory.cpp +new file mode 100644 +index 0000000..a0aef34 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/AEResampleFactory.cpp +@@ -0,0 +1,149 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "AEResampleFactory.h" ++#include "Engines/ActiveAE/ActiveAEResampleFFMPEG.h" ++ ++extern "C" { ++#include "libavutil/channel_layout.h" ++#include "libavutil/opt.h" ++#include "libswresample/swresample.h" ++} ++ ++namespace ActiveAE ++{ ++ ++IAEResample *CAEResampleFactory::Create() ++{ ++ return new CActiveAEResampleFFMPEG(); ++} ++ ++ ++uint64_t CAEResampleFactory::GetAVChannelLayout(CAEChannelInfo &info) ++{ ++ uint64_t channelLayout = 0; ++ if (info.HasChannel(AE_CH_FL)) channelLayout |= AV_CH_FRONT_LEFT; ++ if (info.HasChannel(AE_CH_FR)) channelLayout |= AV_CH_FRONT_RIGHT; ++ if (info.HasChannel(AE_CH_FC)) channelLayout |= AV_CH_FRONT_CENTER; ++ if (info.HasChannel(AE_CH_LFE)) channelLayout |= AV_CH_LOW_FREQUENCY; ++ if (info.HasChannel(AE_CH_BL)) channelLayout |= AV_CH_BACK_LEFT; ++ if (info.HasChannel(AE_CH_BR)) channelLayout |= AV_CH_BACK_RIGHT; ++ if (info.HasChannel(AE_CH_FLOC)) channelLayout |= AV_CH_FRONT_LEFT_OF_CENTER; ++ if (info.HasChannel(AE_CH_FROC)) channelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER; ++ if (info.HasChannel(AE_CH_BC)) channelLayout |= AV_CH_BACK_CENTER; ++ if (info.HasChannel(AE_CH_SL)) channelLayout |= AV_CH_SIDE_LEFT; ++ if (info.HasChannel(AE_CH_SR)) channelLayout |= AV_CH_SIDE_RIGHT; ++ if (info.HasChannel(AE_CH_TC)) channelLayout |= AV_CH_TOP_CENTER; ++ if (info.HasChannel(AE_CH_TFL)) channelLayout |= AV_CH_TOP_FRONT_LEFT; ++ if (info.HasChannel(AE_CH_TFC)) channelLayout |= AV_CH_TOP_FRONT_CENTER; ++ if (info.HasChannel(AE_CH_TFR)) channelLayout |= AV_CH_TOP_FRONT_RIGHT; ++ if (info.HasChannel(AE_CH_TBL)) channelLayout |= AV_CH_TOP_BACK_LEFT; ++ if (info.HasChannel(AE_CH_TBC)) channelLayout |= AV_CH_TOP_BACK_CENTER; ++ if (info.HasChannel(AE_CH_TBR)) channelLayout |= AV_CH_TOP_BACK_RIGHT; ++ ++ return channelLayout; ++} ++ ++//CAEChannelInfo CActiveAEResampleFFMPEG::GetAEChannelLayout(uint64_t layout) ++//{ ++// CAEChannelInfo channelLayout; ++// channelLayout.Reset(); ++// ++// if (layout & AV_CH_FRONT_LEFT ) channelLayout += AE_CH_FL ; ++// if (layout & AV_CH_FRONT_RIGHT ) channelLayout += AE_CH_FR ; ++// if (layout & AV_CH_FRONT_CENTER ) channelLayout += AE_CH_FC ; ++// if (layout & AV_CH_LOW_FREQUENCY ) channelLayout += AE_CH_LFE ; ++// if (layout & AV_CH_BACK_LEFT ) channelLayout += AE_CH_BL ; ++// if (layout & AV_CH_BACK_RIGHT ) channelLayout += AE_CH_BR ; ++// if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelLayout += AE_CH_FLOC; ++// if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelLayout += AE_CH_FROC; ++// if (layout & AV_CH_BACK_CENTER ) channelLayout += AE_CH_BC ; ++// if (layout & AV_CH_SIDE_LEFT ) channelLayout += AE_CH_SL ; ++// if (layout & AV_CH_SIDE_RIGHT ) channelLayout += AE_CH_SR ; ++// if (layout & AV_CH_TOP_CENTER ) channelLayout += AE_CH_TC ; ++// if (layout & AV_CH_TOP_FRONT_LEFT ) channelLayout += AE_CH_TFL ; ++// if (layout & AV_CH_TOP_FRONT_CENTER ) channelLayout += AE_CH_TFC ; ++// if (layout & AV_CH_TOP_FRONT_RIGHT ) channelLayout += AE_CH_TFR ; ++// if (layout & AV_CH_TOP_BACK_LEFT ) channelLayout += AE_CH_BL ; ++// if (layout & AV_CH_TOP_BACK_CENTER ) channelLayout += AE_CH_BC ; ++// if (layout & AV_CH_TOP_BACK_RIGHT ) channelLayout += AE_CH_BR ; ++// ++// return channelLayout; ++//} ++ ++AVSampleFormat CAEResampleFactory::GetAVSampleFormat(AEDataFormat format) ++{ ++ if (format == AE_FMT_U8) return AV_SAMPLE_FMT_U8; ++ else if (format == AE_FMT_S16NE) return AV_SAMPLE_FMT_S16; ++ else if (format == AE_FMT_S32NE) return AV_SAMPLE_FMT_S32; ++ else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32; ++ else if (format == AE_FMT_S24NE4MSB)return AV_SAMPLE_FMT_S32; ++ else if (format == AE_FMT_S24NE3) return AV_SAMPLE_FMT_S32; ++ else if (format == AE_FMT_FLOAT) return AV_SAMPLE_FMT_FLT; ++ else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL; ++ ++ else if (format == AE_FMT_U8P) return AV_SAMPLE_FMT_U8P; ++ else if (format == AE_FMT_S16NEP) return AV_SAMPLE_FMT_S16P; ++ else if (format == AE_FMT_S32NEP) return AV_SAMPLE_FMT_S32P; ++ else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P; ++ else if (format == AE_FMT_S24NE4MSBP)return AV_SAMPLE_FMT_S32P; ++ else if (format == AE_FMT_S24NE3P) return AV_SAMPLE_FMT_S32P; ++ else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP; ++ else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; ++ ++ if (AE_IS_PLANAR(format)) ++ return AV_SAMPLE_FMT_FLTP; ++ else ++ return AV_SAMPLE_FMT_FLT; ++} ++ ++uint64_t CAEResampleFactory::GetAVChannel(enum AEChannel aechannel) ++{ ++ switch (aechannel) ++ { ++ case AE_CH_FL: return AV_CH_FRONT_LEFT; ++ case AE_CH_FR: return AV_CH_FRONT_RIGHT; ++ case AE_CH_FC: return AV_CH_FRONT_CENTER; ++ case AE_CH_LFE: return AV_CH_LOW_FREQUENCY; ++ case AE_CH_BL: return AV_CH_BACK_LEFT; ++ case AE_CH_BR: return AV_CH_BACK_RIGHT; ++ case AE_CH_FLOC: return AV_CH_FRONT_LEFT_OF_CENTER; ++ case AE_CH_FROC: return AV_CH_FRONT_RIGHT_OF_CENTER; ++ case AE_CH_BC: return AV_CH_BACK_CENTER; ++ case AE_CH_SL: return AV_CH_SIDE_LEFT; ++ case AE_CH_SR: return AV_CH_SIDE_RIGHT; ++ case AE_CH_TC: return AV_CH_TOP_CENTER; ++ case AE_CH_TFL: return AV_CH_TOP_FRONT_LEFT; ++ case AE_CH_TFC: return AV_CH_TOP_FRONT_CENTER; ++ case AE_CH_TFR: return AV_CH_TOP_FRONT_RIGHT; ++ case AE_CH_TBL: return AV_CH_TOP_BACK_LEFT; ++ case AE_CH_TBC: return AV_CH_TOP_BACK_CENTER; ++ case AE_CH_TBR: return AV_CH_TOP_BACK_RIGHT; ++ default: ++ return 0; ++ } ++} ++ ++int CAEResampleFactory::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout) ++{ ++ return av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel)); ++} ++ ++} +diff --git a/xbmc/cores/AudioEngine/AEResampleFactory.h b/xbmc/cores/AudioEngine/AEResampleFactory.h +new file mode 100644 +index 0000000..21f1803 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/AEResampleFactory.h +@@ -0,0 +1,43 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "cores/AudioEngine/Interfaces/AEResample.h" ++ ++class IAEResample; ++ ++namespace ActiveAE ++{ ++ ++class CAEResampleFactory ++{ ++public: ++ static IAEResample *Create(); ++ static uint64_t GetAVChannelLayout(CAEChannelInfo &info); ++ static AVSampleFormat GetAVSampleFormat(AEDataFormat format); ++ static uint64_t GetAVChannel(enum AEChannel aechannel); ++ static int GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout); ++}; ++ ++} +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index c825b4b..72cd8ce 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -2676,14 +2676,14 @@ bool CActiveAE::ResampleSound(CActiveAESound *sound) + + orig_config = sound->GetSound(true)->config; + +- dst_config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_internalFormat.m_channelLayout); ++ dst_config.channel_layout = CAEResampleFactory::GetAVChannelLayout(m_internalFormat.m_channelLayout); + dst_config.channels = m_internalFormat.m_channelLayout.Count(); + dst_config.sample_rate = m_internalFormat.m_sampleRate; +- dst_config.fmt = CActiveAEResample::GetAVSampleFormat(m_internalFormat.m_dataFormat); ++ dst_config.fmt = CAEResampleFactory::GetAVSampleFormat(m_internalFormat.m_dataFormat); + dst_config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_internalFormat.m_dataFormat); + dst_config.dither_bits = CAEUtil::DataFormatToDitherBits(m_internalFormat.m_dataFormat); + +- CActiveAEResample *resampler = new CActiveAEResample(); ++ IAEResample *resampler = CAEResampleFactory::Create(); + resampler->Init(dst_config.channel_layout, + dst_config.channels, + dst_config.sample_rate, +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h +index de94850..9ae3c40 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h +@@ -23,7 +23,7 @@ + #include "threads/Thread.h" + + #include "ActiveAESink.h" +-#include "ActiveAEResample.h" ++#include "cores/AudioEngine/Interfaces/AEResample.h" + #include "cores/AudioEngine/Interfaces/AEStream.h" + #include "cores/AudioEngine/Interfaces/AESound.h" + #include "cores/AudioEngine/AEFactory.h" +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp +index 9e834c6..4e4ec92 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp +@@ -22,6 +22,7 @@ + #include "cores/AudioEngine/AEFactory.h" + #include "cores/AudioEngine/Engines/ActiveAE/ActiveAE.h" + #include "cores/AudioEngine/Utils/AEUtil.h" ++#include "cores/AudioEngine/AEResampleFactory.h" + + using namespace ActiveAE; + +@@ -107,12 +108,12 @@ bool CActiveAEBufferPool::Create(unsigned int totaltime) + { + CSampleBuffer *buffer; + SampleConfig config; +- config.fmt = CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat); ++ config.fmt = CAEResampleFactory::GetAVSampleFormat(m_format.m_dataFormat); + config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat); + config.dither_bits = CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat); + config.channels = m_format.m_channelLayout.Count(); + config.sample_rate = m_format.m_sampleRate; +- config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout); ++ config.channel_layout = CAEResampleFactory::GetAVChannelLayout(m_format.m_channelLayout); + + unsigned int time = 0; + unsigned int buffertime = (m_format.m_frames*1000) / m_format.m_sampleRate; +@@ -171,17 +172,17 @@ bool CActiveAEBufferPoolResample::Create(unsigned int totaltime, bool remap, boo + m_inputFormat.m_dataFormat != m_format.m_dataFormat || + m_changeResampler) + { +- m_resampler = new CActiveAEResample(); +- m_resampler->Init(CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout), ++ m_resampler = CAEResampleFactory::Create(); ++ m_resampler->Init(CAEResampleFactory::GetAVChannelLayout(m_format.m_channelLayout), + m_format.m_channelLayout.Count(), + m_format.m_sampleRate, +- CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat), ++ CAEResampleFactory::GetAVSampleFormat(m_format.m_dataFormat), + CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat), +- CActiveAEResample::GetAVChannelLayout(m_inputFormat.m_channelLayout), ++ CAEResampleFactory::GetAVChannelLayout(m_inputFormat.m_channelLayout), + m_inputFormat.m_channelLayout.Count(), + m_inputFormat.m_sampleRate, +- CActiveAEResample::GetAVSampleFormat(m_inputFormat.m_dataFormat), ++ CAEResampleFactory::GetAVSampleFormat(m_inputFormat.m_dataFormat), + CAEUtil::DataFormatToUsedBits(m_inputFormat.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_inputFormat.m_dataFormat), + upmix, +@@ -199,17 +200,17 @@ void CActiveAEBufferPoolResample::ChangeResampler() + { + delete m_resampler; + +- m_resampler = new CActiveAEResample(); +- m_resampler->Init(CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout), ++ m_resampler = CAEResampleFactory::Create(); ++ m_resampler->Init(CAEResampleFactory::GetAVChannelLayout(m_format.m_channelLayout), + m_format.m_channelLayout.Count(), + m_format.m_sampleRate, +- CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat), ++ CAEResampleFactory::GetAVSampleFormat(m_format.m_dataFormat), + CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat), +- CActiveAEResample::GetAVChannelLayout(m_inputFormat.m_channelLayout), ++ CAEResampleFactory::GetAVChannelLayout(m_inputFormat.m_channelLayout), + m_inputFormat.m_channelLayout.Count(), + m_inputFormat.m_sampleRate, +- CActiveAEResample::GetAVSampleFormat(m_inputFormat.m_dataFormat), ++ CAEResampleFactory::GetAVSampleFormat(m_inputFormat.m_dataFormat), + CAEUtil::DataFormatToUsedBits(m_inputFormat.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_inputFormat.m_dataFormat), + m_stereoUpmix, +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h +index b0912be..961db98 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h +@@ -89,7 +89,7 @@ class CActiveAEBufferPool + std::deque m_freeSamples; + }; + +-class CActiveAEResample; ++class IAEResample; + + class CActiveAEBufferPoolResample : public CActiveAEBufferPool + { +@@ -105,7 +105,7 @@ class CActiveAEBufferPoolResample : public CActiveAEBufferPool + std::deque m_inputSamples; + std::deque m_outputSamples; + CSampleBuffer *m_procSample; +- CActiveAEResample *m_resampler; ++ IAEResample *m_resampler; + uint8_t *m_planes[16]; + bool m_fillPackets; + bool m_drain; +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp +deleted file mode 100644 +index d7e0e0f..0000000 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp ++++ /dev/null +@@ -1,388 +0,0 @@ +-/* +- * Copyright (C) 2010-2013 Team XBMC +- * http://xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, see +- * . +- * +- */ +- +-#include "ActiveAEResample.h" +-#include "utils/log.h" +- +-extern "C" { +-#include "libavutil/channel_layout.h" +-#include "libavutil/opt.h" +-#include "libswresample/swresample.h" +-} +- +-using namespace ActiveAE; +- +-CActiveAEResample::CActiveAEResample() +-{ +- m_pContext = NULL; +- m_loaded = true; +-} +- +-CActiveAEResample::~CActiveAEResample() +-{ +- if (m_pContext) +- swr_free(&m_pContext); +-} +- +-bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) +-{ +- if (!m_loaded) +- return false; +- +- m_dst_chan_layout = dst_chan_layout; +- m_dst_channels = dst_channels; +- m_dst_rate = dst_rate; +- m_dst_fmt = dst_fmt; +- m_dst_bits = dst_bits; +- m_dst_dither_bits = dst_dither; +- m_src_chan_layout = src_chan_layout; +- m_src_channels = src_channels; +- m_src_rate = src_rate; +- m_src_fmt = src_fmt; +- m_src_bits = src_bits; +- m_src_dither_bits = src_dither; +- +- if (m_dst_chan_layout == 0) +- m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels); +- if (m_src_chan_layout == 0) +- m_src_chan_layout = av_get_default_channel_layout(m_src_channels); +- +- m_pContext = swr_alloc_set_opts(NULL, m_dst_chan_layout, m_dst_fmt, m_dst_rate, +- m_src_chan_layout, m_src_fmt, m_src_rate, +- 0, NULL); +- +- if(!m_pContext) +- { +- CLog::Log(LOGERROR, "CActiveAEResample::Init - create context failed"); +- return false; +- } +- +- if(quality == AE_QUALITY_HIGH) +- { +- av_opt_set_double(m_pContext, "cutoff", 1.0, 0); +- av_opt_set_int(m_pContext,"filter_size", 256, 0); +- } +- else if(quality == AE_QUALITY_MID) +- { +- // 0.97 is default cutoff so use (1.0 - 0.97) / 2.0 + 0.97 +- av_opt_set_double(m_pContext, "cutoff", 0.985, 0); +- av_opt_set_int(m_pContext,"filter_size", 64, 0); +- } +- else if(quality == AE_QUALITY_LOW) +- { +- av_opt_set_double(m_pContext, "cutoff", 0.97, 0); +- av_opt_set_int(m_pContext,"filter_size", 32, 0); +- } +- +- if (m_dst_fmt == AV_SAMPLE_FMT_S32 || m_dst_fmt == AV_SAMPLE_FMT_S32P) +- { +- av_opt_set_int(m_pContext, "output_sample_bits", m_dst_bits, 0); +- } +- +- // tell resampler to clamp float values +- // not required for sink stage (remapLayout == true) +- if ((m_dst_fmt == AV_SAMPLE_FMT_FLT || m_dst_fmt == AV_SAMPLE_FMT_FLTP) && +- (m_src_fmt == AV_SAMPLE_FMT_FLT || m_src_fmt == AV_SAMPLE_FMT_FLTP) && +- !remapLayout && normalize) +- { +- av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); +- } +- +- if (remapLayout) +- { +- // one-to-one mapping of channels +- // remapLayout is the layout of the sink, if the channel is in our src layout +- // the channel is mapped by setting coef 1.0 +- memset(m_rematrix, 0, sizeof(m_rematrix)); +- m_dst_chan_layout = 0; +- for (unsigned int out=0; outCount(); out++) +- { +- m_dst_chan_layout += (uint64_t) (1 << out); +- int idx = GetAVChannelIndex((*remapLayout)[out], m_src_chan_layout); +- if (idx >= 0) +- { +- m_rematrix[out][idx] = 1.0; +- } +- } +- +- av_opt_set_int(m_pContext, "out_channel_count", m_dst_channels, 0); +- av_opt_set_int(m_pContext, "out_channel_layout", m_dst_chan_layout, 0); +- +- if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) +- { +- CLog::Log(LOGERROR, "CActiveAEResample::Init - setting channel matrix failed"); +- return false; +- } +- } +- // stereo upmix +- else if (upmix && m_src_channels == 2 && m_dst_channels > 2) +- { +- memset(m_rematrix, 0, sizeof(m_rematrix)); +- for (int out=0; out> 8 = 0 1 1 1 = SNE24NE +- else if (m_dst_bits != 32 && (m_dst_dither_bits + m_dst_bits) != 32) +- { +- int planes = av_sample_fmt_is_planar(m_dst_fmt) ? m_dst_channels : 1; +- int samples = ret * m_dst_channels / planes; +- for (int i=0; i> (32 - m_dst_bits - m_dst_dither_bits); +- buf++; +- } +- } +- } +- } +- return ret; +-} +- +-int64_t CActiveAEResample::GetDelay(int64_t base) +-{ +- return swr_get_delay(m_pContext, base); +-} +- +-int CActiveAEResample::GetBufferedSamples() +-{ +- return av_rescale_rnd(swr_get_delay(m_pContext, m_src_rate), +- m_dst_rate, m_src_rate, AV_ROUND_UP); +-} +- +-int CActiveAEResample::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) +-{ +- return av_rescale_rnd(src_samples, dst_rate, src_rate, AV_ROUND_UP); +-} +- +-int CActiveAEResample::GetSrcBufferSize(int samples) +-{ +- return av_samples_get_buffer_size(NULL, m_src_channels, samples, m_src_fmt, 1); +-} +- +-int CActiveAEResample::GetDstBufferSize(int samples) +-{ +- return av_samples_get_buffer_size(NULL, m_dst_channels, samples, m_dst_fmt, 1); +-} +- +-uint64_t CActiveAEResample::GetAVChannelLayout(CAEChannelInfo &info) +-{ +- uint64_t channelLayout = 0; +- if (info.HasChannel(AE_CH_FL)) channelLayout |= AV_CH_FRONT_LEFT; +- if (info.HasChannel(AE_CH_FR)) channelLayout |= AV_CH_FRONT_RIGHT; +- if (info.HasChannel(AE_CH_FC)) channelLayout |= AV_CH_FRONT_CENTER; +- if (info.HasChannel(AE_CH_LFE)) channelLayout |= AV_CH_LOW_FREQUENCY; +- if (info.HasChannel(AE_CH_BL)) channelLayout |= AV_CH_BACK_LEFT; +- if (info.HasChannel(AE_CH_BR)) channelLayout |= AV_CH_BACK_RIGHT; +- if (info.HasChannel(AE_CH_FLOC)) channelLayout |= AV_CH_FRONT_LEFT_OF_CENTER; +- if (info.HasChannel(AE_CH_FROC)) channelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER; +- if (info.HasChannel(AE_CH_BC)) channelLayout |= AV_CH_BACK_CENTER; +- if (info.HasChannel(AE_CH_SL)) channelLayout |= AV_CH_SIDE_LEFT; +- if (info.HasChannel(AE_CH_SR)) channelLayout |= AV_CH_SIDE_RIGHT; +- if (info.HasChannel(AE_CH_TC)) channelLayout |= AV_CH_TOP_CENTER; +- if (info.HasChannel(AE_CH_TFL)) channelLayout |= AV_CH_TOP_FRONT_LEFT; +- if (info.HasChannel(AE_CH_TFC)) channelLayout |= AV_CH_TOP_FRONT_CENTER; +- if (info.HasChannel(AE_CH_TFR)) channelLayout |= AV_CH_TOP_FRONT_RIGHT; +- if (info.HasChannel(AE_CH_TBL)) channelLayout |= AV_CH_TOP_BACK_LEFT; +- if (info.HasChannel(AE_CH_TBC)) channelLayout |= AV_CH_TOP_BACK_CENTER; +- if (info.HasChannel(AE_CH_TBR)) channelLayout |= AV_CH_TOP_BACK_RIGHT; +- +- return channelLayout; +-} +- +-//CAEChannelInfo CActiveAEResample::GetAEChannelLayout(uint64_t layout) +-//{ +-// CAEChannelInfo channelLayout; +-// channelLayout.Reset(); +-// +-// if (layout & AV_CH_FRONT_LEFT ) channelLayout += AE_CH_FL ; +-// if (layout & AV_CH_FRONT_RIGHT ) channelLayout += AE_CH_FR ; +-// if (layout & AV_CH_FRONT_CENTER ) channelLayout += AE_CH_FC ; +-// if (layout & AV_CH_LOW_FREQUENCY ) channelLayout += AE_CH_LFE ; +-// if (layout & AV_CH_BACK_LEFT ) channelLayout += AE_CH_BL ; +-// if (layout & AV_CH_BACK_RIGHT ) channelLayout += AE_CH_BR ; +-// if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelLayout += AE_CH_FLOC; +-// if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelLayout += AE_CH_FROC; +-// if (layout & AV_CH_BACK_CENTER ) channelLayout += AE_CH_BC ; +-// if (layout & AV_CH_SIDE_LEFT ) channelLayout += AE_CH_SL ; +-// if (layout & AV_CH_SIDE_RIGHT ) channelLayout += AE_CH_SR ; +-// if (layout & AV_CH_TOP_CENTER ) channelLayout += AE_CH_TC ; +-// if (layout & AV_CH_TOP_FRONT_LEFT ) channelLayout += AE_CH_TFL ; +-// if (layout & AV_CH_TOP_FRONT_CENTER ) channelLayout += AE_CH_TFC ; +-// if (layout & AV_CH_TOP_FRONT_RIGHT ) channelLayout += AE_CH_TFR ; +-// if (layout & AV_CH_TOP_BACK_LEFT ) channelLayout += AE_CH_BL ; +-// if (layout & AV_CH_TOP_BACK_CENTER ) channelLayout += AE_CH_BC ; +-// if (layout & AV_CH_TOP_BACK_RIGHT ) channelLayout += AE_CH_BR ; +-// +-// return channelLayout; +-//} +- +-AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format) +-{ +- if (format == AE_FMT_U8) return AV_SAMPLE_FMT_U8; +- else if (format == AE_FMT_S16NE) return AV_SAMPLE_FMT_S16; +- else if (format == AE_FMT_S32NE) return AV_SAMPLE_FMT_S32; +- else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32; +- else if (format == AE_FMT_S24NE4MSB)return AV_SAMPLE_FMT_S32; +- else if (format == AE_FMT_S24NE3) return AV_SAMPLE_FMT_S32; +- else if (format == AE_FMT_FLOAT) return AV_SAMPLE_FMT_FLT; +- else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL; +- +- else if (format == AE_FMT_U8P) return AV_SAMPLE_FMT_U8P; +- else if (format == AE_FMT_S16NEP) return AV_SAMPLE_FMT_S16P; +- else if (format == AE_FMT_S32NEP) return AV_SAMPLE_FMT_S32P; +- else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P; +- else if (format == AE_FMT_S24NE4MSBP)return AV_SAMPLE_FMT_S32P; +- else if (format == AE_FMT_S24NE3P) return AV_SAMPLE_FMT_S32P; +- else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP; +- else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP; +- +- if (AE_IS_PLANAR(format)) +- return AV_SAMPLE_FMT_FLTP; +- else +- return AV_SAMPLE_FMT_FLT; +-} +- +-uint64_t CActiveAEResample::GetAVChannel(enum AEChannel aechannel) +-{ +- switch (aechannel) +- { +- case AE_CH_FL: return AV_CH_FRONT_LEFT; +- case AE_CH_FR: return AV_CH_FRONT_RIGHT; +- case AE_CH_FC: return AV_CH_FRONT_CENTER; +- case AE_CH_LFE: return AV_CH_LOW_FREQUENCY; +- case AE_CH_BL: return AV_CH_BACK_LEFT; +- case AE_CH_BR: return AV_CH_BACK_RIGHT; +- case AE_CH_FLOC: return AV_CH_FRONT_LEFT_OF_CENTER; +- case AE_CH_FROC: return AV_CH_FRONT_RIGHT_OF_CENTER; +- case AE_CH_BC: return AV_CH_BACK_CENTER; +- case AE_CH_SL: return AV_CH_SIDE_LEFT; +- case AE_CH_SR: return AV_CH_SIDE_RIGHT; +- case AE_CH_TC: return AV_CH_TOP_CENTER; +- case AE_CH_TFL: return AV_CH_TOP_FRONT_LEFT; +- case AE_CH_TFC: return AV_CH_TOP_FRONT_CENTER; +- case AE_CH_TFR: return AV_CH_TOP_FRONT_RIGHT; +- case AE_CH_TBL: return AV_CH_TOP_BACK_LEFT; +- case AE_CH_TBC: return AV_CH_TOP_BACK_CENTER; +- case AE_CH_TBR: return AV_CH_TOP_BACK_RIGHT; +- default: +- return 0; +- } +-} +- +-int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout) +-{ +- return av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel)); +-} +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h +deleted file mode 100644 +index a471e02..0000000 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h ++++ /dev/null +@@ -1,65 +0,0 @@ +-#pragma once +-/* +- * Copyright (C) 2010-2013 Team XBMC +- * http://xbmc.org +- * +- * This Program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2, or (at your option) +- * any later version. +- * +- * This Program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with XBMC; see the file COPYING. If not, see +- * . +- * +- */ +- +-#include "cores/AudioEngine/Utils/AEChannelInfo.h" +-#include "cores/AudioEngine/Utils/AEAudioFormat.h" +-#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" +-#include "cores/AudioEngine/Interfaces/AE.h" +- +-extern "C" { +-#include "libavutil/avutil.h" +-#include "libswresample/swresample.h" +-} +- +-namespace ActiveAE +-{ +- +-class CActiveAEResample +-{ +-public: +- CActiveAEResample(); +- virtual ~CActiveAEResample(); +- bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality); +- int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio); +- int64_t GetDelay(int64_t base); +- int GetBufferedSamples(); +- int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate); +- int GetSrcBufferSize(int samples); +- int GetDstBufferSize(int samples); +- static uint64_t GetAVChannelLayout(CAEChannelInfo &info); +-// static CAEChannelInfo GetAEChannelLayout(uint64_t layout); +- static AVSampleFormat GetAVSampleFormat(AEDataFormat format); +- static uint64_t GetAVChannel(enum AEChannel aechannel); +- int GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout); +- +-protected: +- bool m_loaded; +- uint64_t m_src_chan_layout, m_dst_chan_layout; +- int m_src_rate, m_dst_rate; +- int m_src_channels, m_dst_channels; +- AVSampleFormat m_src_fmt, m_dst_fmt; +- int m_src_bits, m_dst_bits; +- int m_src_dither_bits, m_dst_dither_bits; +- SwrContext *m_pContext; +- double m_rematrix[AE_CH_MAX][AE_CH_MAX]; +-}; +- +-} +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +new file mode 100644 +index 0000000..8107f44 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +@@ -0,0 +1,282 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++ ++#include "ActiveAEResampleFFMPEG.h" ++#include "cores/AudioEngine/AEResampleFactory.h" ++#include "settings/Settings.h" ++#include "utils/log.h" ++ ++extern "C" { ++#include "libavutil/channel_layout.h" ++#include "libavutil/opt.h" ++#include "libswresample/swresample.h" ++} ++ ++using namespace ActiveAE; ++ ++CActiveAEResampleFFMPEG::CActiveAEResampleFFMPEG() ++{ ++ m_pContext = NULL; ++ m_loaded = true; ++} ++ ++CActiveAEResampleFFMPEG::~CActiveAEResampleFFMPEG() ++{ ++ if (m_pContext) ++ swr_free(&m_pContext); ++} ++ ++bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) ++{ ++ if (!m_loaded) ++ return false; ++ ++ m_dst_chan_layout = dst_chan_layout; ++ m_dst_channels = dst_channels; ++ m_dst_rate = dst_rate; ++ m_dst_fmt = dst_fmt; ++ m_dst_bits = dst_bits; ++ m_dst_dither_bits = dst_dither; ++ m_src_chan_layout = src_chan_layout; ++ m_src_channels = src_channels; ++ m_src_rate = src_rate; ++ m_src_fmt = src_fmt; ++ m_src_bits = src_bits; ++ m_src_dither_bits = src_dither; ++ ++ if (m_dst_chan_layout == 0) ++ m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels); ++ if (m_src_chan_layout == 0) ++ m_src_chan_layout = av_get_default_channel_layout(m_src_channels); ++ ++ m_pContext = swr_alloc_set_opts(NULL, m_dst_chan_layout, m_dst_fmt, m_dst_rate, ++ m_src_chan_layout, m_src_fmt, m_src_rate, ++ 0, NULL); ++ ++ if(!m_pContext) ++ { ++ CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Init - create context failed"); ++ return false; ++ } ++ ++ if(quality == AE_QUALITY_HIGH) ++ { ++ av_opt_set_double(m_pContext, "cutoff", 1.0, 0); ++ av_opt_set_int(m_pContext,"filter_size", 256, 0); ++ } ++ else if(quality == AE_QUALITY_MID) ++ { ++ // 0.97 is default cutoff so use (1.0 - 0.97) / 2.0 + 0.97 ++ av_opt_set_double(m_pContext, "cutoff", 0.985, 0); ++ av_opt_set_int(m_pContext,"filter_size", 64, 0); ++ } ++ else if(quality == AE_QUALITY_LOW) ++ { ++ av_opt_set_double(m_pContext, "cutoff", 0.97, 0); ++ av_opt_set_int(m_pContext,"filter_size", 32, 0); ++ } ++ ++ if (m_dst_fmt == AV_SAMPLE_FMT_S32 || m_dst_fmt == AV_SAMPLE_FMT_S32P) ++ { ++ av_opt_set_int(m_pContext, "output_sample_bits", m_dst_bits, 0); ++ } ++ ++ // tell resampler to clamp float values ++ // not required for sink stage (remapLayout == true) ++ if ((m_dst_fmt == AV_SAMPLE_FMT_FLT || m_dst_fmt == AV_SAMPLE_FMT_FLTP) && ++ (m_src_fmt == AV_SAMPLE_FMT_FLT || m_src_fmt == AV_SAMPLE_FMT_FLTP) && ++ !remapLayout && normalize) ++ { ++ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); ++ } ++ ++ if (remapLayout) ++ { ++ // one-to-one mapping of channels ++ // remapLayout is the layout of the sink, if the channel is in our src layout ++ // the channel is mapped by setting coef 1.0 ++ memset(m_rematrix, 0, sizeof(m_rematrix)); ++ m_dst_chan_layout = 0; ++ for (unsigned int out=0; outCount(); out++) ++ { ++ m_dst_chan_layout += (uint64_t) (1 << out); ++ int idx = CAEResampleFactory::GetAVChannelIndex((*remapLayout)[out], m_src_chan_layout); ++ if (idx >= 0) ++ { ++ m_rematrix[out][idx] = 1.0; ++ } ++ } ++ ++ av_opt_set_int(m_pContext, "out_channel_count", m_dst_channels, 0); ++ av_opt_set_int(m_pContext, "out_channel_layout", m_dst_chan_layout, 0); ++ ++ if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) ++ { ++ CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Init - setting channel matrix failed"); ++ return false; ++ } ++ } ++ // stereo upmix ++ else if (upmix && m_src_channels == 2 && m_dst_channels > 2) ++ { ++ memset(m_rematrix, 0, sizeof(m_rematrix)); ++ for (int out=0; out> 8 = 0 1 1 1 = SNE24NE ++ else if (m_dst_bits != 32 && (m_dst_dither_bits + m_dst_bits) != 32) ++ { ++ int planes = av_sample_fmt_is_planar(m_dst_fmt) ? m_dst_channels : 1; ++ int samples = ret * m_dst_channels / planes; ++ for (int i=0; i> (32 - m_dst_bits - m_dst_dither_bits); ++ buf++; ++ } ++ } ++ } ++ } ++ return ret; ++} ++ ++int64_t CActiveAEResampleFFMPEG::GetDelay(int64_t base) ++{ ++ return swr_get_delay(m_pContext, base); ++} ++ ++int CActiveAEResampleFFMPEG::GetBufferedSamples() ++{ ++ return av_rescale_rnd(swr_get_delay(m_pContext, m_src_rate), ++ m_dst_rate, m_src_rate, AV_ROUND_UP); ++} ++ ++int CActiveAEResampleFFMPEG::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) ++{ ++ return av_rescale_rnd(src_samples, dst_rate, src_rate, AV_ROUND_UP); ++} ++ ++int CActiveAEResampleFFMPEG::GetSrcBufferSize(int samples) ++{ ++ return av_samples_get_buffer_size(NULL, m_src_channels, samples, m_src_fmt, 1); ++} ++ ++int CActiveAEResampleFFMPEG::GetDstBufferSize(int samples) ++{ ++ return av_samples_get_buffer_size(NULL, m_dst_channels, samples, m_dst_fmt, 1); ++} +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h +new file mode 100644 +index 0000000..2f11c8e +--- /dev/null ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.h +@@ -0,0 +1,62 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "cores/AudioEngine/Utils/AEChannelInfo.h" ++#include "cores/AudioEngine/Utils/AEAudioFormat.h" ++#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" ++#include "cores/AudioEngine/Interfaces/AE.h" ++#include "cores/AudioEngine/Interfaces/AEResample.h" ++ ++extern "C" { ++#include "libavutil/avutil.h" ++#include "libswresample/swresample.h" ++} ++ ++namespace ActiveAE ++{ ++ ++class CActiveAEResampleFFMPEG : public IAEResample ++{ ++public: ++ const char *GetName() { return "ActiveAEResampleFFMPEG"; } ++ CActiveAEResampleFFMPEG(); ++ virtual ~CActiveAEResampleFFMPEG(); ++ bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality); ++ int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio); ++ int64_t GetDelay(int64_t base); ++ int GetBufferedSamples(); ++ int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate); ++ int GetSrcBufferSize(int samples); ++ int GetDstBufferSize(int samples); ++ ++protected: ++ bool m_loaded; ++ uint64_t m_src_chan_layout, m_dst_chan_layout; ++ int m_src_rate, m_dst_rate; ++ int m_src_channels, m_dst_channels; ++ AVSampleFormat m_src_fmt, m_dst_fmt; ++ int m_src_bits, m_dst_bits; ++ int m_src_dither_bits, m_dst_dither_bits; ++ SwrContext *m_pContext; ++ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; ++}; ++ ++} +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp +index d9f4a43..52e87a0 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp +@@ -24,6 +24,7 @@ + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "utils/EndianSwap.h" + #include "ActiveAE.h" ++#include "cores/AudioEngine/AEResampleFactory.h" + + #include "settings/Settings.h" + +@@ -754,10 +755,10 @@ void CActiveAESink::OpenSink() + + // init sample of silence + SampleConfig config; +- config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat); ++ config.fmt = CAEResampleFactory::GetAVSampleFormat(m_sinkFormat.m_dataFormat); + config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat); + config.dither_bits = CAEUtil::DataFormatToDitherBits(m_sinkFormat.m_dataFormat); +- config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout); ++ config.channel_layout = CAEResampleFactory::GetAVChannelLayout(m_sinkFormat.m_channelLayout); + config.channels = m_sinkFormat.m_channelLayout.Count(); + config.sample_rate = m_sinkFormat.m_sampleRate; + +@@ -890,8 +891,8 @@ void CActiveAESink::GenerateNoise() + } + + SampleConfig config = m_sampleOfSilence.pkt->config; +- CActiveAEResample resampler; +- resampler.Init(config.channel_layout, ++ IAEResample *resampler = CAEResampleFactory::Create(); ++ resampler->Init(config.channel_layout, + config.channels, + config.sample_rate, + config.fmt, +@@ -904,10 +905,11 @@ void CActiveAESink::GenerateNoise() + CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_sinkFormat.m_dataFormat), + false, false, NULL, AE_QUALITY_UNKNOWN); +- resampler.Resample(m_sampleOfSilence.pkt->data, m_sampleOfSilence.pkt->max_nb_samples, ++ resampler->Resample(m_sampleOfSilence.pkt->data, m_sampleOfSilence.pkt->max_nb_samples, + (uint8_t**)&noise, m_sampleOfSilence.pkt->max_nb_samples, 1.0); + + _aligned_free(noise); ++ delete resampler; + #endif + } + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h +index 0650a70..cf137b6 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h +@@ -25,7 +25,7 @@ + #include "cores/AudioEngine/Interfaces/AE.h" + #include "cores/AudioEngine/Interfaces/AESink.h" + #include "cores/AudioEngine/AESinkFactory.h" +-#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h" ++#include "cores/AudioEngine/Interfaces/AEResample.h" + + namespace ActiveAE + { +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h +index 01aafe3..fbee6b2 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h +@@ -20,7 +20,7 @@ + */ + + #include "cores/AudioEngine/Interfaces/AESound.h" +-#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h" ++#include "cores/AudioEngine/AEResampleFactory.h" + #include "filesystem/File.h" + + class DllAvUtil; +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +index 7acc0d0..09d430c 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +@@ -25,6 +25,7 @@ + + #include "cores/AudioEngine/AEFactory.h" + #include "cores/AudioEngine/Utils/AEUtil.h" ++#include "cores/AudioEngine/AEResampleFactory.h" + + #include "ActiveAE.h" + #include "ActiveAEStream.h" +@@ -94,7 +95,7 @@ void CActiveAEStream::InitRemapper() + for(unsigned int i=0; iGetAVChannelIndex(m_format.m_channelLayout[j], avLayout); ++ idx = CAEResampleFactory::GetAVChannelIndex(m_format.m_channelLayout[j], avLayout); + if (idx == (int)i) + { + ffmpegLayout += m_format.m_channelLayout[j]; +@@ -134,7 +135,7 @@ void CActiveAEStream::InitRemapper() + { + for(unsigned int j=0; jGetAVChannelIndex(m_format.m_channelLayout[j], avLayout); ++ idx = CAEResampleFactory::GetAVChannelIndex(m_format.m_channelLayout[j], avLayout); + if (idx == (int)i) + { + remapLayout += ffmpegLayout[j]; +@@ -147,13 +148,13 @@ void CActiveAEStream::InitRemapper() + m_remapper->Init(avLayout, + m_format.m_channelLayout.Count(), + m_format.m_sampleRate, +- CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat), ++ CAEResampleFactory::GetAVSampleFormat(m_format.m_dataFormat), + CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat), + avLayout, + m_format.m_channelLayout.Count(), + m_format.m_sampleRate, +- CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat), ++ CAEResampleFactory::GetAVSampleFormat(m_format.m_dataFormat), + CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat), + CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat), + false, +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.h +index 70e8107..09fda0f 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.h ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.h +@@ -98,7 +98,7 @@ class CActiveAEStream : public IAEStream + int m_leftoverBytes; + CSampleBuffer *m_currentBuffer; + CSoundPacket *m_remapBuffer; +- CActiveAEResample *m_remapper; ++ IAEResample *m_remapper; + int m_clockId; + + // only accessed by engine +diff --git a/xbmc/cores/AudioEngine/Interfaces/AEResample.h b/xbmc/cores/AudioEngine/Interfaces/AEResample.h +new file mode 100644 +index 0000000..dbe39bf +--- /dev/null ++++ b/xbmc/cores/AudioEngine/Interfaces/AEResample.h +@@ -0,0 +1,53 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++ ++#include "cores/AudioEngine/Utils/AEChannelInfo.h" ++#include "cores/AudioEngine/Utils/AEAudioFormat.h" ++#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" ++#include "cores/AudioEngine/Interfaces/AE.h" ++ ++extern "C" { ++#include "libavutil/avutil.h" ++#include "libswresample/swresample.h" ++} ++ ++namespace ActiveAE ++{ ++ ++class IAEResample ++{ ++public: ++ /* return the name of this sync for logging */ ++ virtual const char *GetName() = 0; ++ IAEResample() {} ++ virtual ~IAEResample() {} ++ virtual bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) = 0; ++ virtual int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio) = 0; ++ virtual int64_t GetDelay(int64_t base) = 0; ++ virtual int GetBufferedSamples() = 0; ++ virtual int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) = 0; ++ virtual int GetSrcBufferSize(int samples) = 0; ++ virtual int GetDstBufferSize(int samples) = 0; ++}; ++ ++} +diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in +index 581249e..b58db3e 100644 +--- a/xbmc/cores/AudioEngine/Makefile.in ++++ b/xbmc/cores/AudioEngine/Makefile.in +@@ -26,11 +26,13 @@ SRCS += Sinks/AESinkProfiler.cpp + + SRCS += Sinks/AESinkPi.cpp + ++SRCS += AEResampleFactory.cpp ++ + SRCS += Engines/ActiveAE/ActiveAE.cpp + SRCS += Engines/ActiveAE/ActiveAESink.cpp + SRCS += Engines/ActiveAE/ActiveAEStream.cpp + SRCS += Engines/ActiveAE/ActiveAESound.cpp +-SRCS += Engines/ActiveAE/ActiveAEResample.cpp ++SRCS += Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp + SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp + + ifeq (@USE_ANDROID@,1) +diff --git a/xbmc/cores/paplayer/DVDPlayerCodec.cpp b/xbmc/cores/paplayer/DVDPlayerCodec.cpp +index c619b32..130d4f95 100644 +--- a/xbmc/cores/paplayer/DVDPlayerCodec.cpp ++++ b/xbmc/cores/paplayer/DVDPlayerCodec.cpp +@@ -20,7 +20,7 @@ + + #include "DVDPlayerCodec.h" + #include "cores/AudioEngine/Utils/AEUtil.h" +-#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h" ++#include "cores/AudioEngine/AEResampleFactory.h" + + #include "cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.h" + #include "cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.h" +@@ -234,17 +234,17 @@ bool DVDPlayerCodec::Init(const std::string &strFile, unsigned int filecache) + if (NeedConvert(m_DataFormat)) + { + m_needConvert = true; +- m_pResampler = new ActiveAE::CActiveAEResample(); +- m_pResampler->Init(ActiveAE::CActiveAEResample::GetAVChannelLayout(m_ChannelInfo), ++ m_pResampler = ActiveAE::CAEResampleFactory::Create(); ++ m_pResampler->Init(ActiveAE::CAEResampleFactory::GetAVChannelLayout(m_ChannelInfo), + m_ChannelInfo.Count(), + m_SampleRate, +- ActiveAE::CActiveAEResample::GetAVSampleFormat(AE_FMT_FLOAT), ++ ActiveAE::CAEResampleFactory::GetAVSampleFormat(AE_FMT_FLOAT), + CAEUtil::DataFormatToUsedBits(AE_FMT_FLOAT), + CAEUtil::DataFormatToDitherBits(AE_FMT_FLOAT), +- ActiveAE::CActiveAEResample::GetAVChannelLayout(m_ChannelInfo), ++ ActiveAE::CAEResampleFactory::GetAVChannelLayout(m_ChannelInfo), + m_ChannelInfo.Count(), + m_SampleRate, +- ActiveAE::CActiveAEResample::GetAVSampleFormat(m_DataFormat), ++ ActiveAE::CAEResampleFactory::GetAVSampleFormat(m_DataFormat), + CAEUtil::DataFormatToUsedBits(m_DataFormat), + CAEUtil::DataFormatToDitherBits(m_DataFormat), + false, +diff --git a/xbmc/cores/paplayer/DVDPlayerCodec.h b/xbmc/cores/paplayer/DVDPlayerCodec.h +index 469e2ff..576fb97 100644 +--- a/xbmc/cores/paplayer/DVDPlayerCodec.h ++++ b/xbmc/cores/paplayer/DVDPlayerCodec.h +@@ -29,7 +29,7 @@ + + namespace ActiveAE + { +- class CActiveAEResample; ++ class IAEResample; + }; + + class DVDPlayerCodec : public ICodec +@@ -71,7 +71,7 @@ class DVDPlayerCodec : public ICodec + bool m_bInited; + bool m_bCanSeek; + +- ActiveAE::CActiveAEResample *m_pResampler; ++ ActiveAE::IAEResample *m_pResampler; + uint8_t *m_audioPlanes[8]; + int m_planes; + bool m_needConvert; + +From d574a64ad703984f46204bac05d05ce361415aed Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 30 Dec 2013 12:02:14 +0000 +Subject: [PATCH 94/99] [rbp] Hardware accelerated resampling + +This replaces the format conversion, up/down mixing and resampling code from ActiveAE with a GPU accelerated version. +Should significantly reduce CPU when using paplayer or dvdplayer. + +Requires updated firmware +--- + .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 563 +++++++++++++++++++++ + .../Engines/ActiveAE/ActiveAEResamplePi.h | 71 +++ + xbmc/cores/AudioEngine/Makefile.in | 1 + + 3 files changed, 635 insertions(+) + create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp + create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +new file mode 100644 +index 0000000..77ed266 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +@@ -0,0 +1,563 @@ ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++ ++#if defined(TARGET_RASPBERRY_PI) ++ ++#include "ActiveAEResamplePi.h" ++#include "cores/AudioEngine/AEResampleFactory.h" ++#include "linux/RBP.h" ++#include "settings/Settings.h" ++#include "utils/log.h" ++ ++extern "C" { ++#include "libavutil/channel_layout.h" ++#include "libavutil/opt.h" ++#include "libswresample/swresample.h" ++} ++ ++//#define DEBUG_VERBOSE ++ ++#define CLASSNAME "CActiveAEResamplePi" ++ ++#define BUFFERSIZE (32*1024*2*8) ++ ++//#define BENCHMARKING ++#ifdef BENCHMARKING ++#define LOGTIMEINIT(f) \ ++ struct timespec now; \ ++ uint64_t Start, End; \ ++ clock_gettime(CLOCK_MONOTONIC, &now); \ ++ Start = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \ ++ const char *_filename = f; ++ ++#define LOGTIME(n) \ ++ clock_gettime(CLOCK_MONOTONIC, &now); \ ++ End = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \ ++ CLog::Log(LOGNOTICE, "ActiveAE::%s %d - resample %s took %.0fms", __FUNCTION__, n, _filename, (End-Start)*1e-6); \ ++ Start=End; ++#else ++#define LOGTIMEINIT(f) ++#define LOGTIME(n) ++#endif ++ ++using namespace ActiveAE; ++ ++CActiveAEResamplePi::CActiveAEResamplePi() ++{ ++ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); ++ ++ m_Initialized = false; ++ m_last_src_fmt = AV_SAMPLE_FMT_NONE; ++ m_last_dst_fmt = AV_SAMPLE_FMT_NONE; ++ m_last_src_channels = 0; ++ m_last_dst_channels = 0; ++ m_encoded_buffer = NULL; ++} ++ ++CActiveAEResamplePi::~CActiveAEResamplePi() ++{ ++ CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__); ++ DeInit(); ++} ++ ++void CActiveAEResamplePi::DeInit() ++{ ++ CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__); ++ if (m_Initialized) ++ { ++ m_omx_mixer.FlushAll(); ++ m_omx_mixer.Deinitialize(); ++ m_Initialized = false; ++ } ++} ++ ++static int format_to_bits(AVSampleFormat fmt) ++{ ++ switch (fmt) ++ { ++ case AV_SAMPLE_FMT_U8: ++ case AV_SAMPLE_FMT_U8P: ++ return 8; ++ case AV_SAMPLE_FMT_S16: ++ case AV_SAMPLE_FMT_S16P: ++ return 16; ++ case AV_SAMPLE_FMT_S32: ++ case AV_SAMPLE_FMT_S32P: ++ case AV_SAMPLE_FMT_FLT: ++ case AV_SAMPLE_FMT_FLTP: ++ return 32; ++ default: ++ assert(0); ++ } ++ return 0; ++} ++ ++bool CActiveAEResamplePi::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality) ++{ ++ LOGTIMEINIT("x"); ++ ++ CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d rate:%d->%d format:%d->%d bits:%d->%d norm:%d upmix:%d", CLASSNAME, __func__, remapLayout, src_channels, dst_channels, src_rate, dst_rate, src_fmt, dst_fmt, src_bits, dst_bits, normalize, upmix); ++ ++ // replace passed in number of bits with correct ones ++ src_bits = format_to_bits(src_fmt); ++ dst_bits = format_to_bits(dst_fmt); ++ ++ m_dst_chan_layout = dst_chan_layout; ++ m_dst_channels = dst_channels; ++ m_dst_rate = dst_rate; ++ m_dst_fmt = dst_fmt; ++ m_dst_bits = dst_bits; ++ m_src_chan_layout = src_chan_layout; ++ m_src_channels = src_channels; ++ m_src_rate = src_rate; ++ m_src_fmt = src_fmt; ++ m_src_bits = src_bits; ++ ++ if (m_dst_chan_layout == 0) ++ m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels); ++ if (m_src_chan_layout == 0) ++ m_src_chan_layout = av_get_default_channel_layout(m_src_channels); ++ ++ OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix; ++ OMX_INIT_STRUCTURE(mix); ++ ++ assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64); ++ ++ LOGTIME(1); ++// this code is just uses ffmpeg to produce the 8x8 mixing matrix ++{ ++ // dummy sample rate and format, as we only care about channel mapping ++ SwrContext *m_pContext = swr_alloc_set_opts(NULL, m_dst_chan_layout, AV_SAMPLE_FMT_FLT, 48000, ++ m_src_chan_layout, AV_SAMPLE_FMT_FLT, 48000, 0, NULL); ++ if (!m_pContext) ++ { ++ CLog::Log(LOGERROR, "CActiveAEResamplePi::Init - create context failed"); ++ return false; ++ } ++ // tell resampler to clamp float values ++ // not required for sink stage (remapLayout == true) ++ if (!remapLayout && normalize) ++ { ++ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); ++ } ++ ++ if (remapLayout) ++ { ++ // one-to-one mapping of channels ++ // remapLayout is the layout of the sink, if the channel is in our src layout ++ // the channel is mapped by setting coef 1.0 ++ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; ++ memset(m_rematrix, 0, sizeof(m_rematrix)); ++ m_dst_chan_layout = 0; ++ for (unsigned int out=0; outCount(); out++) ++ { ++ m_dst_chan_layout += (uint64_t) (1 << out); ++ int idx = CAEResampleFactory::GetAVChannelIndex((*remapLayout)[out], m_src_chan_layout); ++ if (idx >= 0) ++ { ++ m_rematrix[out][idx] = 1.0; ++ } ++ } ++ ++ av_opt_set_int(m_pContext, "out_channel_count", m_dst_channels, 0); ++ av_opt_set_int(m_pContext, "out_channel_layout", m_dst_chan_layout, 0); ++ ++ if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) ++ { ++ CLog::Log(LOGERROR, "CActiveAEResamplePi::Init - setting channel matrix failed"); ++ return false; ++ } ++ } ++ // stereo upmix ++ else if (upmix && m_src_channels == 2 && m_dst_channels > 2) ++ { ++ double m_rematrix[AE_CH_MAX][AE_CH_MAX]; ++ memset(m_rematrix, 0, sizeof(m_rematrix)); ++ for (int out=0; out 192000 || dst_rate > 192000) ++ src_rate >>= 1, dst_rate >>= 1; ++ ++ OMX_INIT_STRUCTURE(m_pcm_input); ++ m_pcm_input.nPortIndex = m_omx_mixer.GetInputPort(); ++ m_pcm_input.eNumData = OMX_NumericalDataSigned; ++ m_pcm_input.eEndian = OMX_EndianLittle; ++ m_pcm_input.bInterleaved = OMX_TRUE; ++ m_pcm_input.nBitPerSample = m_src_bits; ++ // 0x8000 = float, 0x10000 = planar ++ uint32_t flags = 0; ++ if (m_src_fmt == AV_SAMPLE_FMT_FLT || m_src_fmt == AV_SAMPLE_FMT_FLTP) ++ flags |= 0x8000; ++ if (m_src_fmt >= AV_SAMPLE_FMT_U8P) ++ flags |= 0x10000; ++ m_pcm_input.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; ++ m_pcm_input.nChannels = src_channels; ++ m_pcm_input.nSamplingRate = src_rate; ++ ++ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer in SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ OMX_INIT_STRUCTURE(m_pcm_output); ++ m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort(); ++ m_pcm_output.eNumData = OMX_NumericalDataSigned; ++ m_pcm_output.eEndian = OMX_EndianLittle; ++ m_pcm_output.bInterleaved = OMX_TRUE; ++ m_pcm_output.nBitPerSample = m_dst_bits; ++ flags = 0; ++ if (m_dst_fmt == AV_SAMPLE_FMT_FLT || m_dst_fmt == AV_SAMPLE_FMT_FLTP) ++ flags |= 0x8000; ++ if (m_dst_fmt >= AV_SAMPLE_FMT_U8P) ++ flags |= 0x10000; ++ m_pcm_output.ePCMMode = flags == 0 ? OMX_AUDIO_PCMModeLinear : (OMX_AUDIO_PCMMODETYPE)flags; ++ m_pcm_output.nChannels = dst_channels; ++ m_pcm_output.nSamplingRate = dst_rate; ++ ++ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer out SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ LOGTIME(4); ++ ++ mix.nPortIndex = m_omx_mixer.GetInputPort(); ++ omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix); ++ if (omx_err != OMX_ErrorNone) ++ { ++ CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n", ++ CLASSNAME, __func__, omx_err); ++ return false; ++ } ++ ++ // set up the number/size of buffers for decoder input ++ OMX_PARAM_PORTDEFINITIONTYPE port_param; ++ OMX_INIT_STRUCTURE(port_param); ++ port_param.nPortIndex = m_omx_mixer.GetInputPort(); ++ ++ omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)1); ++ port_param.nBufferSize = BUFFERSIZE; ++ ++ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ LOGTIME(5); ++ ++ omx_err = m_omx_mixer.AllocInputBuffers(); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); ++ ++ LOGTIME(6); ++ ++ // set up the number/size of buffers for decoder output ++ OMX_INIT_STRUCTURE(port_param); ++ port_param.nPortIndex = m_omx_mixer.GetOutputPort(); ++ ++ omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)1); ++ port_param.nBufferSize = BUFFERSIZE; ++ ++ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ LOGTIME(7); ++ ++ omx_err = m_omx_mixer.AllocOutputBuffers(); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err); ++ ++ LOGTIME(8); ++ ++ omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting); ++ if (omx_err != OMX_ErrorNone) ++ CLog::Log(LOGERROR, "%s:%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err); ++ ++ LOGTIME(9); ++ ++ m_Initialized = true; ++ ++ return true; ++} ++ ++ ++static void copy_planes(uint8_t **dst_buffer, int d_pitch, int d_planes, int d_samplesize, int offset, uint8_t *src_buffer, int src_samples) ++{ ++ int planesize = src_samples * d_samplesize / d_planes; ++ for (int i=0; i < d_planes; i++) ++ memcpy(dst_buffer[i] + offset * d_pitch, src_buffer + i * planesize, planesize); ++} ++ ++int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio) ++{ ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s samples:%d->%d (%.2f)", CLASSNAME, __func__, src_samples, dst_samples, ratio); ++ #endif ++ if (!m_Initialized) ++ return 0; ++ OMX_ERRORTYPE omx_err = OMX_ErrorNone; ++ ++ const int s_planes = m_src_fmt >= AV_SAMPLE_FMT_U8P ? m_src_channels : 1; ++ const int d_planes = m_dst_fmt >= AV_SAMPLE_FMT_U8P ? m_dst_channels : 1; ++ const int s_chans = m_src_fmt >= AV_SAMPLE_FMT_U8P ? 1 : m_src_channels; ++ const int d_chans = m_dst_fmt >= AV_SAMPLE_FMT_U8P ? 1 : m_dst_channels; ++ const int s_pitch = s_chans * m_src_bits >> 3; ++ const int d_pitch = d_chans * m_dst_bits >> 3; ++ ++ const int s_samplesize = m_src_channels * m_src_bits >> 3; ++ const int d_samplesize = m_dst_channels * m_dst_bits >> 3; ++ const int max_src_samples = BUFFERSIZE / s_samplesize; ++ const int max_dst_samples = (long long)(BUFFERSIZE / d_samplesize) * m_src_rate / (m_dst_rate + m_src_rate-1); ++ ++ int sent = 0; ++ int received = 0; ++ ++ if (m_encoded_buffer && m_encoded_buffer->nFilledLen) ++ { ++ int samples_available = m_encoded_buffer->nFilledLen / d_samplesize - m_encoded_buffer->nOffset; ++ int samples = std::min(samples_available, dst_samples - received); ++ copy_planes(dst_buffer, d_pitch, d_planes, d_samplesize, received, (uint8_t *)m_encoded_buffer->pBuffer + m_encoded_buffer->nOffset * d_pitch, samples); ++ received += samples; ++ samples_available -= samples; ++ if (samples_available > 0) ++ m_encoded_buffer->nOffset += samples; ++ else ++ m_encoded_buffer = NULL; ++ } ++ assert(!m_encoded_buffer); ++ while (sent < src_samples) ++ { ++ OMX_BUFFERHEADERTYPE *omx_buffer = NULL; ++ ++ omx_buffer = m_omx_mixer.GetInputBuffer(1000); ++ if (omx_buffer == NULL) ++ return false; ++ ++ int send = std::min(std::min(max_dst_samples, max_src_samples), src_samples - sent); ++ ++ omx_buffer->nOffset = 0; ++ omx_buffer->nFlags = OMX_BUFFERFLAG_EOS; ++ omx_buffer->nFilledLen = send * s_samplesize; ++ ++ assert(omx_buffer->nFilledLen > 0 && omx_buffer->nFilledLen <= omx_buffer->nAllocLen); ++ ++ if (omx_buffer->nFilledLen) ++ { ++ int planesize = omx_buffer->nFilledLen / s_planes; ++ for (int i=0; i < s_planes; i++) ++ memcpy((uint8_t *)omx_buffer->pBuffer + i * planesize, src_buffer[i] + sent * s_pitch, planesize); ++ sent += send; ++ } ++ ++ omx_err = m_omx_mixer.EmptyThisBuffer(omx_buffer); ++ if (omx_err != OMX_ErrorNone) ++ { ++ CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err); ++ return false; ++ } ++ ++ m_encoded_buffer = m_omx_mixer.GetOutputBuffer(); ++ ++ if (!m_encoded_buffer) ++ { ++ CLog::Log(LOGERROR, "%s::%s no output buffer", CLASSNAME, __func__); ++ return false; ++ } ++ omx_err = m_omx_mixer.FillThisBuffer(m_encoded_buffer); ++ if (omx_err != OMX_ErrorNone) ++ return false; ++ ++ omx_err = m_omx_mixer.WaitForOutputDone(1000); ++ if (omx_err != OMX_ErrorNone) ++ { ++ CLog::Log(LOGERROR, "%s::%s m_omx_mixer.WaitForOutputDone result(0x%x)", CLASSNAME, __func__, omx_err); ++ return false; ++ } ++ assert(m_encoded_buffer->nFilledLen > 0 && m_encoded_buffer->nFilledLen <= m_encoded_buffer->nAllocLen); ++ ++ if (m_omx_mixer.BadState()) ++ { ++ CLog::Log(LOGERROR, "%s::%s m_omx_mixer.BadState", CLASSNAME, __func__); ++ return false; ++ } ++ ++ if (m_encoded_buffer->nFilledLen) ++ { ++ int samples_available = m_encoded_buffer->nFilledLen / d_samplesize; ++ int samples = std::min(samples_available, dst_samples - received); ++ copy_planes(dst_buffer, d_pitch, d_planes, d_samplesize, received, (uint8_t *)m_encoded_buffer->pBuffer, samples); ++ received += samples; ++ samples_available -= samples; ++ if (samples_available > 0) ++ m_encoded_buffer->nOffset += samples; ++ else ++ m_encoded_buffer = NULL; ++ } ++ } ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s format:%d->%d rate:%d->%d chan:%d->%d samples %d->%d (%f) %d =%d", CLASSNAME, __func__, ++ (int)m_src_fmt, (int)m_dst_fmt, m_src_rate, m_dst_rate, m_src_channels, m_dst_channels, src_samples, dst_samples, ratio, m_Initialized, received); ++ #endif ++ assert(received <= dst_samples); ++ return received; ++} ++ ++int64_t CActiveAEResamplePi::GetDelay(int64_t base) ++{ ++ int ret = m_dst_rate ? 1000 * GetBufferedSamples() / m_dst_rate : 0; ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); ++ #endif ++ return ret; ++} ++ ++int CActiveAEResamplePi::GetBufferedSamples() ++{ ++ int samples = 0; ++ if (m_encoded_buffer) ++ { ++ const int d_samplesize = m_dst_channels * m_dst_bits >> 3; ++ samples = m_encoded_buffer->nFilledLen / d_samplesize - m_encoded_buffer->nOffset; ++ } ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, samples); ++ #endif ++ return samples; ++} ++ ++int CActiveAEResamplePi::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate) ++{ ++ int ret = ((long long)src_samples * dst_rate + src_rate-1) / src_rate; ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); ++ #endif ++ return ret; ++} ++ ++int CActiveAEResamplePi::GetSrcBufferSize(int samples) ++{ ++ int ret = 0; ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); ++ #endif ++ return ret; ++} ++ ++int CActiveAEResamplePi::GetDstBufferSize(int samples) ++{ ++ int ret = CalcDstSampleCount(samples, m_dst_rate, m_src_rate); ++ #ifdef DEBUG_VERBOSE ++ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret); ++ #endif ++ return ret; ++} ++ ++#endif +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h +new file mode 100644 +index 0000000..9e61f37 +--- /dev/null ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h +@@ -0,0 +1,71 @@ ++#pragma once ++/* ++ * Copyright (C) 2010-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++ ++#include "cores/AudioEngine/Utils/AEChannelInfo.h" ++#include "cores/AudioEngine/Utils/AEAudioFormat.h" ++#include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h" ++#include "cores/AudioEngine/Interfaces/AE.h" ++#include "cores/AudioEngine/Interfaces/AEResample.h" ++ ++extern "C" { ++#include "libavutil/avutil.h" ++#include "libswresample/swresample.h" ++} ++ ++#include "linux/OMXCore.h" ++ ++namespace ActiveAE ++{ ++ ++class CActiveAEResamplePi : public IAEResample ++{ ++public: ++ const char *GetName() { return "ActiveAEResamplePi"; } ++ CActiveAEResamplePi(); ++ virtual ~CActiveAEResamplePi(); ++ bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality); ++ int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio); ++ int64_t GetDelay(int64_t base); ++ int GetBufferedSamples(); ++ int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate); ++ int GetSrcBufferSize(int samples); ++ int GetDstBufferSize(int samples); ++ ++protected: ++ void DeInit(); ++ uint64_t m_src_chan_layout, m_dst_chan_layout; ++ int m_src_rate, m_dst_rate; ++ int m_src_channels, m_dst_channels; ++ AVSampleFormat m_src_fmt, m_dst_fmt; ++ int m_src_bits, m_dst_bits; ++ ++ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input; ++ OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output; ++ COMXCoreComponent m_omx_mixer; ++ bool m_Initialized; ++ AVSampleFormat m_last_src_fmt, m_last_dst_fmt; ++ int m_last_src_channels, m_last_dst_channels; ++ OMX_BUFFERHEADERTYPE *m_encoded_buffer; ++}; ++ ++} +diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in +index b58db3e..efb44cc 100644 +--- a/xbmc/cores/AudioEngine/Makefile.in ++++ b/xbmc/cores/AudioEngine/Makefile.in +@@ -33,6 +33,7 @@ SRCS += Engines/ActiveAE/ActiveAESink.cpp + SRCS += Engines/ActiveAE/ActiveAEStream.cpp + SRCS += Engines/ActiveAE/ActiveAESound.cpp + SRCS += Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp ++SRCS += Engines/ActiveAE/ActiveAEResamplePi.cpp + SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp + + ifeq (@USE_ANDROID@,1) + +From f2874956b54c197cbe22292d62bfcf6e6ac39e04 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:14:04 +0100 +Subject: [PATCH 95/99] settings: Add acceleration option for resampling + +--- + language/English/strings.po | 10 ++++++++++ + system/settings/rbp.xml | 7 +++++++ + xbmc/cores/AudioEngine/AEResampleFactory.cpp | 8 ++++++++ + 3 files changed, 25 insertions(+) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 989cfcc..58ee88f 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -15998,3 +15998,13 @@ msgstr "" + msgctxt "#38006" + msgid "Adjust PLL" + msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38010" ++msgid "Use accelerated resampling" ++msgstr "" ++ ++#: system/settings/rbp.xml ++msgctxt "#38011" ++msgid "This setting reduces CPU by handling audio resampling on the GPU" ++msgstr "" +diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml +index 9ecae65..a7a0e50 100644 +--- a/system/settings/rbp.xml ++++ b/system/settings/rbp.xml +@@ -61,6 +61,13 @@ + + + ++ ++ ++ 2 ++ true ++ ++ ++ + + + +diff --git a/xbmc/cores/AudioEngine/AEResampleFactory.cpp b/xbmc/cores/AudioEngine/AEResampleFactory.cpp +index a0aef34..03e3ddb 100644 +--- a/xbmc/cores/AudioEngine/AEResampleFactory.cpp ++++ b/xbmc/cores/AudioEngine/AEResampleFactory.cpp +@@ -18,8 +18,12 @@ + * + */ + ++#include "settings/Settings.h" + #include "AEResampleFactory.h" + #include "Engines/ActiveAE/ActiveAEResampleFFMPEG.h" ++#if defined(TARGET_RASPBERRY_PI) ++ #include "Engines/ActiveAE/ActiveAEResamplePi.h" ++#endif + + extern "C" { + #include "libavutil/channel_layout.h" +@@ -32,6 +36,10 @@ namespace ActiveAE + + IAEResample *CAEResampleFactory::Create() + { ++#if defined(TARGET_RASPBERRY_PI) ++ if (CSettings::Get().GetBool("videoplayer.resamplepi")) ++ return new CActiveAEResamplePi(); ++#endif + return new CActiveAEResampleFFMPEG(); + } + + +From 52f41c5bf98b71418a754a0d1a41c6d7371fde0b Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 24 Sep 2014 23:13:52 +0100 +Subject: [PATCH 96/99] [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 +--- + language/English/strings.po | 14 ++++++++++++++ + system/settings/settings.xml | 12 ++++++++++++ + .../Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp | 6 ++++++ + .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 ++++++ + xbmc/cores/omxplayer/OMXAudio.cpp | 6 ++++++ + 5 files changed, 44 insertions(+) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 58ee88f..6cb308c 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -15999,6 +15999,20 @@ msgctxt "#38006" + msgid "Adjust 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" ++ + #: system/settings/rbp.xml + msgctxt "#38010" + msgid "Use accelerated resampling" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 14f18d9..c8a7d3b 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2449,6 +2449,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 8107f44..79f2a0f 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +@@ -108,6 +108,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 77ed266..7a25964 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp +@@ -159,6 +159,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 f0ae0cc..c0931b0 100644 +--- a/xbmc/cores/omxplayer/OMXAudio.cpp ++++ b/xbmc/cores/omxplayer/OMXAudio.cpp +@@ -682,6 +682,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 d2cc69cecc28c00513a1eb5497ebc97d9344a670 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:38:07 +0100 +Subject: [PATCH 97/99] [omxcore] Skip out of flush on error + +--- + xbmc/linux/OMXCore.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp +index 4ae29ba..4caa304 100644 +--- a/xbmc/linux/OMXCore.cpp ++++ b/xbmc/linux/OMXCore.cpp +@@ -419,7 +419,7 @@ void COMXCoreComponent::FlushAll() + + void COMXCoreComponent::FlushInput() + { +- if(!m_handle) ++ if(!m_handle || m_resource_error) + return; + + OMX_ERRORTYPE omx_err = OMX_ErrorNone; +@@ -436,7 +436,7 @@ void COMXCoreComponent::FlushInput() + + void COMXCoreComponent::FlushOutput() + { +- if(!m_handle) ++ if(!m_handle || m_resource_error) + return; + + OMX_ERRORTYPE omx_err = OMX_ErrorNone; + +From 702755b0ba747a1c5a33f3c5a52997c4d9f25381 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 3 Oct 2014 18:40:06 +0100 +Subject: [PATCH 98/99] [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 89684e4..fd9a03d 100644 +--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp ++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp +@@ -92,9 +92,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; +@@ -133,12 +133,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]; +@@ -169,9 +169,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; + +@@ -208,7 +208,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 b5a13e0d867266a424c28b04c48df46f8b83b985 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sat, 4 Oct 2014 14:20:59 +0100 +Subject: [PATCH 99/99] [vobsub] Fix for incorrect colours with vobsubs and + GLES + +Fixes #15146 + +The code provides the overlay texture in BGRA format, which it informs GL about. +However GLES does not support BGRA, and just claims it is RGBA which results in a red/blue swap. + +So this code path needs a red/blue swap. +--- + xbmc/cores/VideoRenderers/OverlayRendererGL.cpp | 29 ++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp b/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp +index a7a2552..ba60958 100644 +--- a/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp ++++ b/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp +@@ -70,8 +70,35 @@ static void LoadTexture(GLenum target + } + + #ifdef HAS_GLES ++ ++ /** OpenGL ES does not support BGR **/ ++ if (externalFormat == GL_RGBA) ++ { ++ int bytesPerLine = bytesPerPixel * width; ++ ++ pixelVector = (char *)malloc(bytesPerLine * height); ++ ++ const char *src = (const char*)pixels; ++ char *dst = pixelVector; ++ for (int y = 0;y < height;++y) ++ { ++ src = (const char*)pixels + y * stride; ++ dst = pixelVector + y * bytesPerLine; ++ ++ for (unsigned int i = 0; i < width; i++, src+=4, dst+=4) ++ { ++ dst[0] = src[2]; ++ dst[1] = src[1]; ++ dst[2] = src[0]; ++ dst[3] = src[3]; ++ } ++ } ++ ++ pixelData = pixelVector; ++ stride = width; ++ } + /** OpenGL ES does not support strided texture input. Make a copy without stride **/ +- if (stride != width) ++ else if (stride != width) + { + int bytesPerLine = bytesPerPixel * width; +