mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
kodi: update to kodi-14-bd7da38
Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
parent
8744b4876c
commit
243886e415
@ -17,7 +17,7 @@
|
||||
################################################################################
|
||||
|
||||
PKG_NAME="kodi-theme-Confluence"
|
||||
PKG_VERSION="14-2d88a9a"
|
||||
PKG_VERSION="14-bd7da38"
|
||||
PKG_REV="1"
|
||||
PKG_ARCH="any"
|
||||
PKG_LICENSE="GPL"
|
||||
|
@ -17,7 +17,7 @@
|
||||
################################################################################
|
||||
|
||||
PKG_NAME="kodi"
|
||||
PKG_VERSION="14-2d88a9a"
|
||||
PKG_VERSION="14-bd7da38"
|
||||
PKG_REV="1"
|
||||
PKG_ARCH="any"
|
||||
PKG_LICENSE="GPL"
|
||||
|
@ -1,726 +1,3 @@
|
||||
From 30460a1c4259c3b3591349a894dc51ccbd22fd2b Mon Sep 17 00:00:00 2001
|
||||
From: xbmc <fernetmenta@online.de>
|
||||
Date: Mon, 28 May 2012 10:34:39 +0200
|
||||
Subject: [PATCH 01/24] videoplayer: adapt lateness detection and dropping to
|
||||
buffering
|
||||
|
||||
---
|
||||
xbmc/cores/VideoRenderers/RenderManager.cpp | 16 +-
|
||||
xbmc/cores/VideoRenderers/RenderManager.h | 12 +-
|
||||
.../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 40 ++++-
|
||||
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 41 +++++
|
||||
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 +
|
||||
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 199 ++++++++++++++++-----
|
||||
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 23 ++-
|
||||
7 files changed, 290 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
||||
index 529f62f..1ecdc16 100644
|
||||
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
|
||||
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
|
||||
@@ -286,6 +286,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
|
||||
m_bIsStarted = true;
|
||||
m_bReconfigured = true;
|
||||
m_presentstep = PRESENT_IDLE;
|
||||
+ m_presentpts = DVD_NOPTS_VALUE;
|
||||
+ m_sleeptime = 1.0;
|
||||
m_presentevent.notifyAll();
|
||||
|
||||
m_firstFlipPage = false; // tempfix
|
||||
@@ -646,7 +648,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode)
|
||||
m_pRenderer->SetViewMode(iViewMode);
|
||||
}
|
||||
|
||||
-void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
|
||||
+void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
|
||||
{
|
||||
{ CSharedLock lock(m_sharedSection);
|
||||
|
||||
@@ -714,6 +716,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L
|
||||
m.timestamp = timestamp;
|
||||
m.presentfield = sync;
|
||||
m.presentmethod = presentmethod;
|
||||
+ m.pts = pts;
|
||||
requeue(m_queued, m_free);
|
||||
|
||||
/* signal to any waiters to check state */
|
||||
@@ -1105,6 +1108,8 @@ void CXBMCRenderManager::PrepareNextRender()
|
||||
m_discard.push_back(m_presentsource);
|
||||
m_presentsource = idx;
|
||||
m_queued.pop_front();
|
||||
+ m_sleeptime = m_Queue[idx].timestamp - clocktime;
|
||||
+ m_presentpts = m_Queue[idx].pts;
|
||||
m_presentevent.notifyAll();
|
||||
}
|
||||
}
|
||||
@@ -1121,3 +1126,12 @@ void CXBMCRenderManager::DiscardBuffer()
|
||||
m_presentstep = PRESENT_IDLE;
|
||||
m_presentevent.notifyAll();
|
||||
}
|
||||
+
|
||||
+bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel)
|
||||
+{
|
||||
+ CSingleLock lock(m_presentlock);
|
||||
+ sleeptime = m_sleeptime;
|
||||
+ pts = m_presentpts;
|
||||
+ bufferLevel = m_queued.size() + m_discard.size();
|
||||
+ return true;
|
||||
+}
|
||||
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
|
||||
index c438651..d3c2f1d 100644
|
||||
--- a/xbmc/cores/VideoRenderers/RenderManager.h
|
||||
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
|
||||
@@ -99,10 +99,11 @@ class CXBMCRenderManager
|
||||
*
|
||||
* @param bStop reference to stop flag of calling thread
|
||||
* @param timestamp of frame delivered with AddVideoPicture
|
||||
+ * @param pts used for lateness detection
|
||||
* @param source depreciated
|
||||
* @param sync signals frame, top, or bottom field
|
||||
*/
|
||||
- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
|
||||
+ void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
|
||||
unsigned int PreInit();
|
||||
void UnInit();
|
||||
bool Flush();
|
||||
@@ -179,6 +180,12 @@ class CXBMCRenderManager
|
||||
int WaitForBuffer(volatile bool& bStop, int timeout = 100);
|
||||
|
||||
/**
|
||||
+ * Can be called by player for lateness detection. This is done best by
|
||||
+ * looking at the end of the queue.
|
||||
+ */
|
||||
+ bool GetStats(double &sleeptime, double &pts, int &bufferLevel);
|
||||
+
|
||||
+ /**
|
||||
* Video player call this on flush in oder to discard any queued frames
|
||||
*/
|
||||
void DiscardBuffer();
|
||||
@@ -225,6 +232,7 @@ class CXBMCRenderManager
|
||||
|
||||
struct SPresent
|
||||
{
|
||||
+ double pts;
|
||||
double timestamp;
|
||||
EFIELDSYNC presentfield;
|
||||
EPRESENTMETHOD presentmethod;
|
||||
@@ -236,6 +244,8 @@ class CXBMCRenderManager
|
||||
|
||||
ERenderFormat m_format;
|
||||
|
||||
+ double m_sleeptime;
|
||||
+ double m_presentpts;
|
||||
double m_presentcorr;
|
||||
double m_presenterr;
|
||||
double m_errorbuff[ERRORBUFFSIZE];
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
||||
index 0386abb..1dd7590 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
||||
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
|
||||
@@ -149,6 +149,10 @@ struct DVDVideoUserData
|
||||
#define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped
|
||||
#define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data
|
||||
|
||||
+#define DVD_CODEC_CTRL_SKIPDEINT 0x01000000 // indicate that this picture was requested to have been dropped in deint stage
|
||||
+#define DVD_CODEC_CTRL_NO_POSTPROC 0x02000000 // see GetCodecStats
|
||||
+#define DVD_CODEC_CTRL_DRAIN 0x04000000 // see GetCodecStats
|
||||
+
|
||||
// DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2!
|
||||
|
||||
#define DVP_QSCALE_UNKNOWN 0
|
||||
@@ -166,6 +170,8 @@ class CDVDCodecOptions;
|
||||
#define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data
|
||||
#define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data
|
||||
#define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again
|
||||
+#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped
|
||||
+
|
||||
class CDVDVideoCodec
|
||||
{
|
||||
public:
|
||||
@@ -283,7 +289,6 @@ class CDVDVideoCodec
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
/**
|
||||
* Number of references to old pictures that are allowed to
|
||||
* be retained when calling decode on the next demux packet
|
||||
@@ -300,4 +305,37 @@ class CDVDVideoCodec
|
||||
* Interact with user settings so that user disabled codecs are disabled
|
||||
*/
|
||||
static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id);
|
||||
+
|
||||
+ /* For calculation of dropping requirements player asks for some information.
|
||||
+ *
|
||||
+ * - pts : right after decoder, used to detect gaps (dropped frames in decoder)
|
||||
+ * - droppedPics : indicates if decoder has dropped a picture
|
||||
+ * -1 means that decoder has no info on this.
|
||||
+ *
|
||||
+ * If codec does not implement this method, pts of decoded frame at input
|
||||
+ * video player is used. In case decoder does post-proc and de-interlacing there
|
||||
+ * may be quite some frames queued up between exit decoder and entry player.
|
||||
+ */
|
||||
+ virtual bool GetCodecStats(double &pts, int &droppedPics)
|
||||
+ {
|
||||
+ droppedPics= -1;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Codec can be informed by player with the following flags:
|
||||
+ *
|
||||
+ * DVD_CODEC_CTRL_NO_POSTPROC :
|
||||
+ * if speed is not normal the codec can switch off
|
||||
+ * postprocessing and de-interlacing
|
||||
+ *
|
||||
+ * DVD_CODEC_CTRL_DRAIN :
|
||||
+ * codecs may do postprocessing and de-interlacing.
|
||||
+ * If video buffers in RenderManager are about to run dry,
|
||||
+ * this is signaled to codec. Codec can wait for post-proc
|
||||
+ * to be finished instead of returning empty and getting another
|
||||
+ * packet.
|
||||
+ *
|
||||
+ */
|
||||
+ virtual void SetCodecControl(int flags) {}
|
||||
};
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
||||
index 0c4f0e5..84b1eff 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
||||
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
|
||||
@@ -173,6 +173,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
|
||||
m_iLastKeyframe = 0;
|
||||
m_dts = DVD_NOPTS_VALUE;
|
||||
m_started = false;
|
||||
+ m_decoderPts = DVD_NOPTS_VALUE;
|
||||
}
|
||||
|
||||
CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
|
||||
@@ -342,6 +343,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop)
|
||||
{
|
||||
if( m_pCodecContext )
|
||||
{
|
||||
+ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint())
|
||||
+ {
|
||||
+ m_requestSkipDeint = true;
|
||||
+ bDrop = false;
|
||||
+ }
|
||||
+ else
|
||||
+ m_requestSkipDeint = false;
|
||||
+
|
||||
// i don't know exactly how high this should be set
|
||||
// couldn't find any good docs on it. think it varies
|
||||
// from codec to codec on what it does
|
||||
@@ -543,6 +552,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
|
||||
void CDVDVideoCodecFFmpeg::Reset()
|
||||
{
|
||||
m_started = false;
|
||||
+ m_decoderPts = DVD_NOPTS_VALUE;
|
||||
m_iLastKeyframe = m_pCodecContext->has_b_frames;
|
||||
avcodec_flush_buffers(m_pCodecContext);
|
||||
|
||||
@@ -640,6 +650,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
|
||||
else
|
||||
pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
|
||||
|
||||
+ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE)
|
||||
+ m_decoderPts = pDvdVideoPicture->pts;
|
||||
+ else
|
||||
+ m_decoderPts = m_dts;
|
||||
+
|
||||
+ if (m_requestSkipDeint)
|
||||
+ {
|
||||
+ pDvdVideoPicture->iFlags |= DVD_CODEC_CTRL_SKIPDEINT;
|
||||
+ m_skippedDeint = 1;
|
||||
+ }
|
||||
+ else
|
||||
+ m_skippedDeint = 0;
|
||||
+
|
||||
+ m_requestSkipDeint = false;
|
||||
+ pDvdVideoPicture->iFlags |= m_codecControlFlags;
|
||||
+
|
||||
if(!m_started)
|
||||
pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
|
||||
|
||||
@@ -821,3 +847,18 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences()
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &droppedPics)
|
||||
+{
|
||||
+ pts = m_decoderPts;
|
||||
+ if (m_skippedDeint)
|
||||
+ droppedPics = m_skippedDeint;
|
||||
+ else
|
||||
+ droppedPics = -1;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void CDVDVideoCodecFFmpeg::SetCodecControl(int flags)
|
||||
+{
|
||||
+ m_codecControlFlags = flags;
|
||||
+}
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
||||
index 1f564bb..48564d1 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
||||
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
|
||||
@@ -50,6 +50,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
||||
virtual int Check (AVCodecContext* avctx) = 0;
|
||||
virtual void Reset () {}
|
||||
virtual unsigned GetAllowedReferences() { return 0; }
|
||||
+ virtual bool CanSkipDeint() {return false; }
|
||||
virtual const std::string Name() = 0;
|
||||
virtual CCriticalSection* Section() { return NULL; }
|
||||
};
|
||||
@@ -67,6 +68,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
||||
virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
|
||||
virtual unsigned GetConvergeCount();
|
||||
virtual unsigned GetAllowedReferences();
|
||||
+ virtual bool GetCodecStats(double &pts, int &droppedPics);
|
||||
+ virtual void SetCodecControl(int flags);
|
||||
|
||||
bool IsHardwareAllowed() { return !m_bSoftware; }
|
||||
IHardwareDecoder * GetHardware() { return m_pHardware; };
|
||||
@@ -122,4 +125,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
|
||||
double m_dts;
|
||||
bool m_started;
|
||||
std::vector<PixelFormat> m_formats;
|
||||
+ double m_decoderPts, m_decoderInterval;
|
||||
+ int m_skippedDeint;
|
||||
+ bool m_requestSkipDeint;
|
||||
+ int m_codecControlFlags;
|
||||
};
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
index 5a758ab..c3db6ba 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "DVDCodecs/DVDCodecs.h"
|
||||
#include "DVDCodecs/Overlay/DVDOverlayCodecCC.h"
|
||||
#include "DVDCodecs/Overlay/DVDOverlaySSA.h"
|
||||
+#include "guilib/GraphicContext.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
@@ -147,7 +148,6 @@ CDVDPlayerVideo::CDVDPlayerVideo( CDVDClock* pClock
|
||||
m_messageQueue.SetMaxDataSize(40 * 1024 * 1024);
|
||||
m_messageQueue.SetMaxTimeSize(8.0);
|
||||
|
||||
- m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_iDroppedFrames = 0;
|
||||
m_fFrameRate = 25;
|
||||
m_bCalcFrameRate = false;
|
||||
@@ -296,7 +296,6 @@ void CDVDPlayerVideo::OnStartup()
|
||||
m_crop.x1 = m_crop.x2 = 0.0f;
|
||||
m_crop.y1 = m_crop.y2 = 0.0f;
|
||||
|
||||
- m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_FlipTimeStamp = m_pClock->GetAbsoluteClock();
|
||||
m_FlipTimePts = 0.0;
|
||||
}
|
||||
@@ -318,8 +317,10 @@ void CDVDPlayerVideo::Process()
|
||||
|
||||
int iDropped = 0; //frames dropped in a row
|
||||
bool bRequestDrop = false;
|
||||
+ int iDropDirective;
|
||||
|
||||
m_videoStats.Start();
|
||||
+ m_droppingStats.Reset();
|
||||
|
||||
while (!m_bStop)
|
||||
{
|
||||
@@ -431,6 +432,7 @@ void CDVDPlayerVideo::Process()
|
||||
picture.iFlags &= ~DVP_FLAG_ALLOCATED;
|
||||
m_packets.clear();
|
||||
m_started = false;
|
||||
+ m_droppingStats.Reset();
|
||||
}
|
||||
else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush())
|
||||
{
|
||||
@@ -443,6 +445,7 @@ void CDVDPlayerVideo::Process()
|
||||
//we need to recalculate the framerate
|
||||
//TODO: this needs to be set on a streamchange instead
|
||||
ResetFrameRateCalc();
|
||||
+ m_droppingStats.Reset();
|
||||
|
||||
m_stalled = true;
|
||||
m_started = false;
|
||||
@@ -462,6 +465,7 @@ void CDVDPlayerVideo::Process()
|
||||
m_iNrOfPicturesNotToSkip = 0;
|
||||
if (m_pVideoCodec)
|
||||
m_pVideoCodec->SetSpeed(m_speed);
|
||||
+ m_droppingStats.Reset();
|
||||
}
|
||||
else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
|
||||
{
|
||||
@@ -507,6 +511,28 @@ void CDVDPlayerVideo::Process()
|
||||
m_iNrOfPicturesNotToSkip = 1;
|
||||
}
|
||||
|
||||
+ bRequestDrop = false;
|
||||
+ iDropDirective = CalcDropRequirement(pts);
|
||||
+ if (iDropDirective & EOS_VERYLATE)
|
||||
+ {
|
||||
+ if (m_bAllowDrop)
|
||||
+ {
|
||||
+ m_pullupCorrection.Flush();
|
||||
+ bRequestDrop = true;
|
||||
+ }
|
||||
+ }
|
||||
+ int codecControl = 0;
|
||||
+ if (iDropDirective & EOS_BUFFER_LEVEL)
|
||||
+ codecControl |= DVD_CODEC_CTRL_DRAIN;
|
||||
+ if (m_speed > DVD_PLAYSPEED_NORMAL)
|
||||
+ codecControl |= DVD_CODEC_CTRL_NO_POSTPROC;
|
||||
+ m_pVideoCodec->SetCodecControl(codecControl);
|
||||
+ if (iDropDirective & EOS_DROPPED)
|
||||
+ {
|
||||
+ m_iDroppedFrames++;
|
||||
+ iDropped++;
|
||||
+ }
|
||||
+
|
||||
if (m_messageQueue.GetDataSize() == 0
|
||||
|| m_speed < 0)
|
||||
{
|
||||
@@ -559,15 +585,7 @@ void CDVDPlayerVideo::Process()
|
||||
}
|
||||
|
||||
m_videoStats.AddSampleBytes(pPacket->iSize);
|
||||
- // assume decoder dropped a picture if it didn't give us any
|
||||
- // picture from a demux packet, this should be reasonable
|
||||
- // for libavformat as a demuxer as it normally packetizes
|
||||
- // pictures when they come from demuxer
|
||||
- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE))
|
||||
- {
|
||||
- m_iDroppedFrames++;
|
||||
- iDropped++;
|
||||
- }
|
||||
+
|
||||
// reset the request, the following while loop may break before
|
||||
// setting the flag to a new value
|
||||
bRequestDrop = false;
|
||||
@@ -1170,45 +1188,17 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
||||
, "CDVDPlayerVideo::OutputPicture");
|
||||
}
|
||||
|
||||
- // present the current pts of this frame to user, and include the actual
|
||||
- // presentation delay, to allow him to adjust for it
|
||||
- if( m_stalled )
|
||||
- m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
- else
|
||||
- m_iCurrentPts = pts - max(0.0, iSleepTime);
|
||||
-
|
||||
// timestamp when we think next picture should be displayed based on current duration
|
||||
m_FlipTimeStamp = iCurrentClock;
|
||||
m_FlipTimeStamp += max(0.0, iSleepTime);
|
||||
m_FlipTimePts = pts;
|
||||
|
||||
- if (iSleepTime <= 0 && m_speed)
|
||||
- m_iLateFrames++;
|
||||
- else
|
||||
- m_iLateFrames = 0;
|
||||
-
|
||||
- // ask decoder to drop frames next round, as we are very late
|
||||
- if(m_iLateFrames > 10)
|
||||
+ if ((pPicture->iFlags & DVP_FLAG_DROPPED))
|
||||
{
|
||||
- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP))
|
||||
- {
|
||||
- //if we're calculating the framerate,
|
||||
- //don't drop frames until we've calculated a stable framerate
|
||||
- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL)
|
||||
- {
|
||||
- result |= EOS_VERYLATE;
|
||||
- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it
|
||||
- }
|
||||
- m_iDroppedRequest++;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- m_iDroppedRequest = 0;
|
||||
- }
|
||||
-
|
||||
- if( (pPicture->iFlags & DVP_FLAG_DROPPED) )
|
||||
+ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate);
|
||||
+ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__);
|
||||
return result | EOS_DROPPED;
|
||||
+ }
|
||||
|
||||
// set fieldsync if picture is interlaced
|
||||
EFIELDSYNC mDisplayField = FS_NONE;
|
||||
@@ -1241,7 +1231,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
|
||||
if (index < 0)
|
||||
return EOS_DROPPED;
|
||||
|
||||
- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField);
|
||||
+ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField);
|
||||
|
||||
return result;
|
||||
#else
|
||||
@@ -1543,3 +1533,124 @@ void CDVDPlayerVideo::CalcFrameRate()
|
||||
m_iFrameRateCount = 0;
|
||||
}
|
||||
}
|
||||
+
|
||||
+int CDVDPlayerVideo::CalcDropRequirement(double pts)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ double iSleepTime;
|
||||
+ double iDecoderPts, iRenderPts;
|
||||
+ double iInterval;
|
||||
+ double iGain;
|
||||
+ double iLateness;
|
||||
+ bool bNewFrame;
|
||||
+ int iDroppedPics = -1;
|
||||
+ int iBufferLevel;
|
||||
+
|
||||
+ // get decoder stats
|
||||
+ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iDroppedPics))
|
||||
+ iDecoderPts = pts;
|
||||
+ if (iDecoderPts == DVD_NOPTS_VALUE)
|
||||
+ iDecoderPts = pts;
|
||||
+
|
||||
+ // get render stats
|
||||
+ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel);
|
||||
+
|
||||
+ if (iBufferLevel < 0)
|
||||
+ result |= EOS_BUFFER_LEVEL;
|
||||
+ else if (iBufferLevel < 2)
|
||||
+ {
|
||||
+ result |= EOS_BUFFER_LEVEL;
|
||||
+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel);
|
||||
+ }
|
||||
+
|
||||
+ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts;
|
||||
+
|
||||
+ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE;
|
||||
+
|
||||
+ if (m_droppingStats.m_lastDecoderPts > 0
|
||||
+ && bNewFrame
|
||||
+ && m_bAllowDrop)
|
||||
+ {
|
||||
+ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE;
|
||||
+ if (iDroppedPics > 0)
|
||||
+ {
|
||||
+ CDroppingStats::CGain gain;
|
||||
+ gain.gain = iDroppedPics * 1/m_fFrameRate;
|
||||
+ gain.pts = iDecoderPts;
|
||||
+ m_droppingStats.m_gain.push_back(gain);
|
||||
+ m_droppingStats.m_totalGain += gain.gain;
|
||||
+ result |= EOS_DROPPED;
|
||||
+ m_droppingStats.m_dropRequests = 0;
|
||||
+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped pictures, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain);
|
||||
+ }
|
||||
+ else if (iDroppedPics < 0 && iGain > (1/m_fFrameRate + 0.001))
|
||||
+ {
|
||||
+ CDroppingStats::CGain gain;
|
||||
+ gain.gain = iGain;
|
||||
+ gain.pts = iDecoderPts;
|
||||
+ m_droppingStats.m_gain.push_back(gain);
|
||||
+ m_droppingStats.m_totalGain += iGain;
|
||||
+ result |= EOS_DROPPED;
|
||||
+ m_droppingStats.m_dropRequests = 0;
|
||||
+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain);
|
||||
+ }
|
||||
+ }
|
||||
+ m_droppingStats.m_lastDecoderPts = iDecoderPts;
|
||||
+
|
||||
+ // subtract gains
|
||||
+ while (!m_droppingStats.m_gain.empty() &&
|
||||
+ iRenderPts >= m_droppingStats.m_gain.front().pts)
|
||||
+ {
|
||||
+ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain;
|
||||
+ m_droppingStats.m_gain.pop_front();
|
||||
+ }
|
||||
+
|
||||
+ // calculate lateness
|
||||
+ iLateness = iSleepTime + m_droppingStats.m_totalGain;
|
||||
+ if (iLateness < 0 && m_speed)
|
||||
+ {
|
||||
+ if (bNewFrame)
|
||||
+ m_droppingStats.m_lateFrames++;
|
||||
+
|
||||
+ // if lateness is smaller than frametime, we observe this state
|
||||
+ // for 10 cycles
|
||||
+ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate)
|
||||
+ {
|
||||
+ // is frame allowed to skip
|
||||
+ if (m_iNrOfPicturesNotToSkip <= 0)
|
||||
+ {
|
||||
+ if (bNewFrame || m_droppingStats.m_dropRequests < 5)
|
||||
+ {
|
||||
+ result |= EOS_VERYLATE;
|
||||
+ }
|
||||
+ m_droppingStats.m_dropRequests++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ m_droppingStats.m_dropRequests = 0;
|
||||
+ m_droppingStats.m_lateFrames = 0;
|
||||
+ }
|
||||
+ m_droppingStats.m_lastRenderPts = iRenderPts;
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+void CDroppingStats::Reset()
|
||||
+{
|
||||
+ m_gain.clear();
|
||||
+ m_totalGain = 0;
|
||||
+ m_lastDecoderPts = 0;
|
||||
+ m_lastRenderPts = 0;
|
||||
+ m_lateFrames = 0;
|
||||
+ m_dropRequests = 0;
|
||||
+}
|
||||
+
|
||||
+void CDroppingStats::AddOutputDropGain(double pts, double frametime)
|
||||
+{
|
||||
+ CDroppingStats::CGain gain;
|
||||
+ gain.gain = frametime;
|
||||
+ gain.pts = pts;
|
||||
+ m_gain.push_back(gain);
|
||||
+ m_totalGain += frametime;
|
||||
+}
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
||||
index dcd0ffd..1f0e661 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
||||
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
||||
@@ -37,6 +37,24 @@ class CDVDOverlayCodecCC;
|
||||
|
||||
#define VIDEO_PICTURE_QUEUE_SIZE 1
|
||||
|
||||
+class CDroppingStats
|
||||
+{
|
||||
+public:
|
||||
+ void Reset();
|
||||
+ void AddOutputDropGain(double pts, double frametime);
|
||||
+ struct CGain
|
||||
+ {
|
||||
+ double gain;
|
||||
+ double pts;
|
||||
+ };
|
||||
+ std::deque<CGain> m_gain;
|
||||
+ double m_totalGain;
|
||||
+ double m_lastDecoderPts;
|
||||
+ double m_lastRenderPts;
|
||||
+ unsigned int m_lateFrames;
|
||||
+ unsigned int m_dropRequests;
|
||||
+};
|
||||
+
|
||||
class CDVDPlayerVideo : public CThread, public IDVDStreamPlayerVideo
|
||||
{
|
||||
public:
|
||||
@@ -103,6 +121,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayerVideo
|
||||
#define EOS_ABORT 1
|
||||
#define EOS_DROPPED 2
|
||||
#define EOS_VERYLATE 4
|
||||
+#define EOS_BUFFER_LEVEL 8
|
||||
|
||||
void AutoCrop(DVDVideoPicture* pPicture);
|
||||
void AutoCrop(DVDVideoPicture *pPicture, RECT &crop);
|
||||
@@ -118,7 +137,6 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayerVideo
|
||||
CDVDMessageQueue m_messageQueue;
|
||||
CDVDMessageQueue& m_messageParent;
|
||||
|
||||
- double m_iCurrentPts; // last pts displayed
|
||||
double m_iVideoDelay;
|
||||
double m_iSubtitleDelay;
|
||||
double m_FlipTimeStamp; // time stamp of last flippage. used to play at a forced framerate
|
||||
@@ -130,6 +148,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayerVideo
|
||||
|
||||
void ResetFrameRateCalc();
|
||||
void CalcFrameRate();
|
||||
+ int CalcDropRequirement(double pts);
|
||||
|
||||
double m_fFrameRate; //framerate of the video currently playing
|
||||
bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps
|
||||
@@ -183,5 +202,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayerVideo
|
||||
CPullupCorrection m_pullupCorrection;
|
||||
|
||||
std::list<DVDMessageListItem> m_packets;
|
||||
+
|
||||
+ CDroppingStats m_droppingStats;
|
||||
};
|
||||
|
||||
|
||||
From 2d14428010383f68e60acdfff79ed9fcba1030af Mon Sep 17 00:00:00 2001
|
||||
From: xbmc <fernetmenta@online.de>
|
||||
Date: Sun, 2 Sep 2012 16:05:21 +0200
|
||||
Subject: [PATCH 02/24] video player: present correct pts to user for a/v sync
|
||||
(after buffering in renderer)
|
||||
|
||||
---
|
||||
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 16 ++++++++++++++++
|
||||
xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +-
|
||||
2 files changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
index c3db6ba..48f8f60 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
@@ -1451,6 +1451,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc()
|
||||
g_advancedSettings.m_videoFpsDetect == 0;
|
||||
}
|
||||
|
||||
+double CDVDPlayerVideo::GetCurrentPts()
|
||||
+{
|
||||
+ double iSleepTime, iRenderPts;
|
||||
+ int iBufferLevel;
|
||||
+
|
||||
+ // get render stats
|
||||
+ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel);
|
||||
+
|
||||
+ if( m_stalled )
|
||||
+ iRenderPts = DVD_NOPTS_VALUE;
|
||||
+ else
|
||||
+ iRenderPts = iRenderPts - max(0.0, iSleepTime);
|
||||
+
|
||||
+ return iRenderPts;
|
||||
+}
|
||||
+
|
||||
#define MAXFRAMERATEDIFF 0.01
|
||||
#define MAXFRAMESERR 1000
|
||||
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
||||
index 1f0e661..a38a9c3 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
||||
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
|
||||
@@ -98,7 +98,7 @@ class CDVDPlayerVideo : public CThread, public IDVDStreamPlayerVideo
|
||||
bool IsEOS() { return false; }
|
||||
bool SubmittedEOS() const { return false; }
|
||||
|
||||
- double GetCurrentPts() { return m_iCurrentPts; }
|
||||
+ double GetCurrentPts();
|
||||
|
||||
double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */
|
||||
int GetDecoderFreeSpace() { return 0; }
|
||||
|
||||
From 47b6e876f00601c7b15712be16a3e2f13e7aca91 Mon Sep 17 00:00:00 2001
|
||||
From: xbmc <fernetmenta@online.de>
|
||||
Date: Mon, 28 May 2012 10:41:31 +0200
|
||||
Subject: [PATCH 03/24] videoplayer: update frametime, it might change due to
|
||||
fps detection
|
||||
|
||||
---
|
||||
xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
index 48f8f60..4f35e3a 100644
|
||||
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
|
||||
@@ -705,6 +705,8 @@ void CDVDPlayerVideo::Process()
|
||||
|
||||
int iResult = OutputPicture(&picture, pts);
|
||||
|
||||
+ frametime = (double)DVD_TIME_BASE/m_fFrameRate;
|
||||
+
|
||||
if(m_started == false)
|
||||
{
|
||||
m_codecname = m_pVideoCodec->GetName();
|
||||
|
||||
From 5acb9e7a7c70dc38ca18799d4908b96f242551dc Mon Sep 17 00:00:00 2001
|
||||
From: xbmc <fernetmenta@online.de>
|
||||
Date: Mon, 28 May 2012 10:49:05 +0200
|
||||
@ -1716,6 +993,7 @@ index 707d609..e0709226 100644
|
||||
VAProcFilterParameterBufferDeinterlacing *filterParams;
|
||||
VABufferID pipelineBuf;
|
||||
|
||||
|
||||
From 0d3311557fe32505770ed28bcb8fbcde7c751399 Mon Sep 17 00:00:00 2001
|
||||
From: Rainer Hochecker <fernetmenta@online.de>
|
||||
Date: Sat, 4 Oct 2014 21:25:31 +0200
|
||||
@ -2196,14 +1474,13 @@ index 7e05ce6..1177f41 100644
|
||||
class CAESinkALSA : public IAESink
|
||||
{
|
||||
public:
|
||||
@@ -79,6 +84,10 @@ class CAESinkALSA : public IAESink
|
||||
snd_pcm_t *m_pcm;
|
||||
int m_timeout;
|
||||
|
||||
@@ -82,6 +87,9 @@ class CAESinkALSA : public IAESink
|
||||
// support fragmentation, e.g. looping in the sink to get a certain amount of data onto the device
|
||||
bool m_fragmented;
|
||||
unsigned int m_originalPeriodSize;
|
||||
+#if HAVE_LIBUDEV
|
||||
+ static CALSADeviceMonitor m_deviceMonitor;
|
||||
+#endif
|
||||
+
|
||||
struct ALSAConfig
|
||||
{
|
||||
unsigned int sampleRate;
|
||||
|
@ -1,141 +0,0 @@
|
||||
From 970ff0341f05a0adfe3ca79e5fba26a7070a12b7 Mon Sep 17 00:00:00 2001
|
||||
From: fritsch <Peter.Fruehberger@gmail.com>
|
||||
Date: Sun, 9 Nov 2014 17:46:10 +0100
|
||||
Subject: [PATCH 2/2] AESinkALSA: Allow fragmentation, e.g. even multiply of
|
||||
PeriodSize
|
||||
|
||||
---
|
||||
xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 66 ++++++++++++++++++++++-------
|
||||
xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 4 +-
|
||||
2 files changed, 53 insertions(+), 17 deletions(-)
|
||||
|
||||
diff -Naur kodi-14-2d88a9a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp kodi-14-2d88a9a.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
|
||||
--- kodi-14-2d88a9a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-11-09 22:28:18.035651639 +0100
|
||||
+++ kodi-14-2d88a9a.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp 2014-11-10 00:35:57.351393193 +0100
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "utils/AMLUtils.h"
|
||||
#endif
|
||||
|
||||
+
|
||||
+#define AE_MIN_PERIODSIZE 256
|
||||
#define ALSA_CHMAP_KERNEL_BLACKLIST
|
||||
|
||||
#define ALSA_OPTIONS (SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE)
|
||||
@@ -86,7 +88,9 @@
|
||||
m_formatSampleRateMul(0.0),
|
||||
m_passthrough(false),
|
||||
m_pcm(NULL),
|
||||
- m_timeout(0)
|
||||
+ m_timeout(0),
|
||||
+ m_fragmented(false),
|
||||
+ m_originalPeriodSize(AE_MIN_PERIODSIZE)
|
||||
{
|
||||
/* ensure that ALSA has been initialized */
|
||||
if (!snd_config)
|
||||
@@ -479,7 +483,8 @@
|
||||
|
||||
params += ",AES1=0x82,AES2=0x00";
|
||||
|
||||
- if (format.m_sampleRate == 192000) params += ",AES3=0x0e";
|
||||
+ if (m_passthrough && format.m_channelLayout.Count() == 8) params += ",AES3=0x09";
|
||||
+ else if (format.m_sampleRate == 192000) params += ",AES3=0x0e";
|
||||
else if (format.m_sampleRate == 176400) params += ",AES3=0x0c";
|
||||
else if (format.m_sampleRate == 96000) params += ",AES3=0x0a";
|
||||
else if (format.m_sampleRate == 88200) params += ",AES3=0x08";
|
||||
@@ -806,7 +811,19 @@
|
||||
|
||||
/* set the format parameters */
|
||||
outconfig.sampleRate = sampleRate;
|
||||
- outconfig.periodSize = periodSize;
|
||||
+
|
||||
+ /* if periodSize is too small Audio Engine might starve */
|
||||
+ m_fragmented = false;
|
||||
+ unsigned int fragments = 1;
|
||||
+ if (periodSize < AE_MIN_PERIODSIZE)
|
||||
+ {
|
||||
+ fragments = std::ceil((double) AE_MIN_PERIODSIZE / periodSize);
|
||||
+ CLog::Log(LOGDEBUG, "Audio Driver reports too low periodSize %d - will use %d fragments", (int) periodSize, (int) fragments);
|
||||
+ m_fragmented = true;
|
||||
+ }
|
||||
+
|
||||
+ m_originalPeriodSize = periodSize;
|
||||
+ outconfig.periodSize = fragments * periodSize;
|
||||
outconfig.frameSize = snd_pcm_frames_to_bytes(m_pcm, 1);
|
||||
|
||||
m_bufferSize = (unsigned int)bufferSize;
|
||||
@@ -893,27 +910,45 @@
|
||||
}
|
||||
|
||||
void *buffer = data[0]+offset*m_format.m_frameSize;
|
||||
- int ret = snd_pcm_writei(m_pcm, buffer, frames);
|
||||
- if (ret < 0)
|
||||
- {
|
||||
- CLog::Log(LOGERROR, "CAESinkALSA - snd_pcm_writei(%d) %s - trying to recover", ret, snd_strerror(ret));
|
||||
- ret = snd_pcm_recover(m_pcm, ret, 1);
|
||||
- if(ret < 0)
|
||||
- {
|
||||
- HandleError("snd_pcm_writei(1)", ret);
|
||||
- ret = snd_pcm_writei(m_pcm, buffer, frames);
|
||||
- if (ret < 0)
|
||||
+ unsigned int amount = 0;
|
||||
+ int64_t data_left = (int64_t) frames;
|
||||
+ int frames_written = 0;
|
||||
+
|
||||
+ while (data_left > 0)
|
||||
+ {
|
||||
+ if (m_fragmented)
|
||||
+ amount = std::min((unsigned int) data_left, m_originalPeriodSize);
|
||||
+ else // take care as we can come here a second time if the sink does not eat all data
|
||||
+ amount = (unsigned int) data_left;
|
||||
+
|
||||
+ int ret = snd_pcm_writei(m_pcm, buffer, amount);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ CLog::Log(LOGERROR, "CAESinkALSA - snd_pcm_writei(%d) %s - trying to recover", ret, snd_strerror(ret));
|
||||
+ ret = snd_pcm_recover(m_pcm, ret, 1);
|
||||
+ if(ret < 0)
|
||||
{
|
||||
- HandleError("snd_pcm_writei(2)", ret);
|
||||
- ret = 0;
|
||||
+ HandleError("snd_pcm_writei(1)", ret);
|
||||
+ ret = snd_pcm_writei(m_pcm, buffer, amount);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ HandleError("snd_pcm_writei(2)", ret);
|
||||
+ ret = 0;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
- }
|
||||
|
||||
- if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
|
||||
- snd_pcm_start(m_pcm);
|
||||
+ if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
|
||||
+ snd_pcm_start(m_pcm);
|
||||
|
||||
- return ret;
|
||||
+ if (ret <= 0)
|
||||
+ break;
|
||||
+
|
||||
+ frames_written += ret;
|
||||
+ data_left -= ret;
|
||||
+ buffer = data[0]+offset*m_format.m_frameSize + frames_written*m_format.m_frameSize;
|
||||
+ }
|
||||
+ return frames_written;
|
||||
}
|
||||
|
||||
void CAESinkALSA::HandleError(const char* name, int err)
|
||||
diff -Naur kodi-14-2d88a9a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h kodi-14-2d88a9a.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h
|
||||
--- kodi-14-2d88a9a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h 2014-11-09 22:28:18.036651638 +0100
|
||||
+++ kodi-14-2d88a9a.patch/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h 2014-11-10 00:36:24.936426057 +0100
|
||||
@@ -90,6 +90,10 @@
|
||||
#endif
|
||||
static CALSAHControlMonitor m_controlMonitor;
|
||||
|
||||
+ // support fragmentation, e.g. looping in the sink to get a certain amount of data onto the device
|
||||
+ bool m_fragmented;
|
||||
+ unsigned int m_originalPeriodSize;
|
||||
+
|
||||
struct ALSAConfig
|
||||
{
|
||||
unsigned int sampleRate;
|
Loading…
x
Reference in New Issue
Block a user