Skip to content

Commit

Permalink
PR 831 Inclusions (credit goes to bobo1on1):
Browse files Browse the repository at this point in the history
- Use Free Ram Percentage as Buffer Size
- Adjust Read Rate Based On Max Bitrate

Enhancements to PR 831:

- move variables over to advanced settings under <network> section ("alwaysforcebuffer" default false and "freememorycachepercent" default 50% max 80% with hard limit of 1GB and 0 value will force filecache. It also removes "cachemembuffersize" variable as it is no longer needed)

- "alwaysforcebuffer" variable will cache everything run through dvdplayer (i.e. OS network shares, local media, etc) except Optical Media Drives

- Memory buffer is straight percentage of free ram (i.e. if 50% free ram is used ~75% of the 50% will be forward looking buffer and ~25% of the 50% will be back buffer)

- Rate limiting which fixes SMB issues with PR 831 as far as I can tell (1.25 times max bitrate up to 40 MB/s in which case it is throttled to max bitrate)

- ios and linux fixes

Advanced Settings Notes: This PR adds 2 setting under advanced settings and removes the "cachemembuffersize" setting as it is no longer needed. The added settings are as follows:

1. alwaysforcebuffer: This will force everything ran through dvdplayer to be buffered that would not be normal buffered except Optical Media.  This includes SMB, Local Files, OS Network Shares, etc.  The current default is false due to it not really being a help to people who use hardwired connections (as they probably do not need buffering for SMB, etc).

2. "freememorycachepercent": The amount of free memory to use as buffer size.  Please note that of the percentage of free memory used ~75% will be used for forward buffering and ~25% will be used for the back buffer.  The default is 50% which is a good default for memory limted devices such as the atv2.  The max is 80 percent and there is a hard limit of 1GB buffer size irregardless of free ram.  Setting it to 0 will force filecaching (same as the way cachemembuffersize was used)

Merged again
  • Loading branch information
classicspam committed Dec 7, 2012
1 parent e979ca9 commit a46ea2b
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 13 deletions.
9 changes: 8 additions & 1 deletion xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp
Expand Up @@ -23,6 +23,7 @@
#include "filesystem/IFile.h"
#include "utils/log.h"
#include "utils/URIUtils.h"
#include "settings/AdvancedSettings.h"

using namespace XFILE;

Expand Down Expand Up @@ -51,8 +52,13 @@ bool CDVDInputStreamFile::Open(const char* strFile, const std::string& content)
if (!m_pFile)
return false;

unsigned int flags = READ_TRUNCATED | READ_BITRATE | READ_CHUNKED;

if (!URIUtils::IsOnDVD(strFile) && !URIUtils::IsBluray(strFile) && g_advancedSettings.m_alwaysForceBuffer)
flags |= READ_CACHED;

// open file in binary mode
if (!m_pFile->Open(strFile, READ_TRUNCATED | READ_BITRATE | READ_CHUNKED))
if (!m_pFile->Open(strFile, flags))
{
delete m_pFile;
m_pFile = NULL;
Expand Down Expand Up @@ -144,6 +150,7 @@ int CDVDInputStreamFile::GetBlockSize()
void CDVDInputStreamFile::SetReadRate(unsigned rate)
{
unsigned maxrate = rate + 1024 * 1024 / 8;
CLog::Log(LOGDEBUG, "CDVDInputStreamFile::SetReadRate - Read rate set to %u bytes per second", maxrate);
if(m_pFile->IoControl(IOCTRL_CACHE_SETRATE, &maxrate) >= 0)
CLog::Log(LOGDEBUG, "CDVDInputStreamFile::SetReadRate - set cache throttle rate to %u bytes per second", maxrate);
}
26 changes: 24 additions & 2 deletions xbmc/cores/dvdplayer/DVDPlayer.cpp
Expand Up @@ -419,6 +419,7 @@ CDVDPlayer::CDVDPlayer(IPlayerCallback& callback)
m_offset_pts = 0.0;
m_playSpeed = DVD_PLAYSPEED_NORMAL;
m_caching = CACHESTATE_DONE;
m_readrate = 0;

memset(&m_SpeedState, 0, sizeof(m_SpeedState));

Expand Down Expand Up @@ -676,7 +677,11 @@ bool CDVDPlayer::OpenDemuxStream()
int64_t len = m_pInputStream->GetLength();
int64_t tim = m_pDemuxer->GetStreamLength();
if(len > 0 && tim > 0)
m_pInputStream->SetReadRate(len * 1000 / tim);
{
//cap to intital read rate to 40 megabits/second if less than average bitrate * 1.25
m_readrate = std::min((unsigned int)((len * 1000 / tim) * 1.25), (unsigned int) (40000000 / 8));
m_pInputStream->SetReadRate(m_readrate);
}

return true;
}
Expand Down Expand Up @@ -1075,7 +1080,10 @@ void CDVDPlayer::Process()

// update application with our state
UpdateApplication(1000);


//update readrate based on peak bitrate
UpdateReadRate();

if (CheckDelayedChannelEntry())
continue;

Expand Down Expand Up @@ -3926,6 +3934,20 @@ void CDVDPlayer::UpdateApplication(double timeout)
m_UpdateApplication = CDVDClock::GetAbsoluteClock();
}

void CDVDPlayer::UpdateReadRate()
{
unsigned int bytespersecond = (GetVideoBitrate() + GetAudioBitrate()) / 8;

if (bytespersecond > m_readrate)
{
//if current bitrate * 1.25 is over 40 Mbs then cap at at max of actual bitrate or 40 Mb/s whichever is greater
//otherwise set read rate to current bitrate * 1.25
m_readrate = std::min((unsigned int)(bytespersecond * 1.25), std::max((unsigned int) bytespersecond, (unsigned int) (40000000 / 8)));

m_pInputStream->SetReadRate(m_readrate);
}
}

bool CDVDPlayer::CanRecord()
{
CSingleLock lock(m_StateSection);
Expand Down
3 changes: 2 additions & 1 deletion xbmc/cores/dvdplayer/DVDPlayer.h
Expand Up @@ -338,6 +338,7 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer

void UpdateApplication(double timeout);
void UpdatePlayState(double timeout);
void UpdateReadRate();
double m_UpdateApplication;

bool m_bAbortRequest;
Expand All @@ -347,7 +348,7 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
ECacheState m_caching;
CFileItem m_item;
unsigned int m_iChannelEntryTimeOut;

unsigned int m_readrate;

CCurrentStream m_CurrentAudio;
CCurrentStream m_CurrentVideo;
Expand Down
23 changes: 20 additions & 3 deletions xbmc/filesystem/FileCache.cpp
Expand Up @@ -18,6 +18,7 @@
*
*/

#include <limits.h>
#include "threads/SystemClock.h"
#include "utils/AutoPtrHandle.h"
#include "FileCache.h"
Expand Down Expand Up @@ -85,11 +86,27 @@ CFileCache::CFileCache() : CThread("CFileCache")
m_seekPos = 0;
m_readPos = 0;
m_writePos = 0;
if (g_advancedSettings.m_cacheMemBufferSize == 0)
if (g_advancedSettings.m_freeMemCachePercent == 0)
m_pCache = new CSimpleFileCache();
else
m_pCache = new CCircularCache(g_advancedSettings.m_cacheMemBufferSize
, std::max<unsigned int>( g_advancedSettings.m_cacheMemBufferSize / 4, 1024 * 1024));
{
//set cache size of m_freeMemCachePercent of free ram, with hardcoded 1 GB upper limit
MEMORYSTATUSEX stat;
stat.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&stat);

//limit max cache to 1 GB
unsigned int maxcache = (1024 * 1024 * 1000);
double ramamount = (stat.ullAvailPhys * (g_advancedSettings.m_freeMemCachePercent / 100.00));

unsigned int cacheRam = std::min(static_cast<unsigned int>(ramamount), maxcache);

unsigned int frontCache = static_cast<unsigned int>(cacheRam * 0.75);
unsigned int backCache = cacheRam - frontCache;

m_pCache = new CCircularCache(frontCache, std::max<unsigned int>(backCache, 1024 * 1024));
}

m_seekPossible = 0;
m_cacheFull = false;
}
Expand Down
6 changes: 3 additions & 3 deletions xbmc/filesystem/MemBufferCache.cpp
Expand Up @@ -38,9 +38,9 @@ MemBufferCache::MemBufferCache()
: CCacheStrategy()
{
m_nStartPosition = 0;
m_buffer.Create(g_advancedSettings.m_cacheMemBufferSize + 1);
m_HistoryBuffer.Create(g_advancedSettings.m_cacheMemBufferSize + 1);
m_forwardBuffer.Create(g_advancedSettings.m_cacheMemBufferSize + 1);
m_buffer.Create((1024 * 1024 * 10) + 1);
m_HistoryBuffer.Create((1024 * 1024 * 10) + 1);
m_forwardBuffer.Create((1024 * 1024 * 10) + 1);
}


Expand Down
6 changes: 4 additions & 2 deletions xbmc/settings/AdvancedSettings.cpp
Expand Up @@ -298,7 +298,8 @@ void CAdvancedSettings::Initialize()

m_measureRefreshrate = false;

m_cacheMemBufferSize = 1024 * 1024 * 20;
m_alwaysForceBuffer = false;
m_freeMemCachePercent = 50;
m_addonPackageFolderSize = 200;

m_jsonOutputCompact = true;
Expand Down Expand Up @@ -684,11 +685,12 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
pElement = pRootElement->FirstChildElement("network");
if (pElement)
{
XMLUtils::GetBoolean(pElement, "alwaysforcebuffer", m_alwaysForceBuffer);
XMLUtils::GetInt(pElement, "curlclienttimeout", m_curlconnecttimeout, 1, 1000);
XMLUtils::GetInt(pElement, "curllowspeedtime", m_curllowspeedtime, 1, 1000);
XMLUtils::GetInt(pElement, "curlretries", m_curlretries, 0, 10);
XMLUtils::GetBoolean(pElement,"disableipv6", m_curlDisableIPV6);
XMLUtils::GetUInt(pElement, "cachemembuffersize", m_cacheMemBufferSize);
XMLUtils::GetInt(pElement, "freememorycachepercent", m_freeMemCachePercent, 0, 80);
}

pElement = pRootElement->FirstChildElement("jsonrpc");
Expand Down
3 changes: 2 additions & 1 deletion xbmc/settings/AdvancedSettings.h
Expand Up @@ -349,7 +349,8 @@ class CAdvancedSettings
int m_guiDirtyRegionNoFlipTimeout;
unsigned int m_addonPackageFolderSize;

unsigned int m_cacheMemBufferSize;
bool m_alwaysForceBuffer;
int m_freeMemCachePercent;

bool m_jsonOutputCompact;
unsigned int m_jsonTcpPort;
Expand Down

0 comments on commit a46ea2b

Please sign in to comment.