#include "threads/CriticalSection.h"
#include "video/VideoReferenceClock.h"
#include "utils/MathUtils.h"
+#include "threads/Atomics.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
#include "utils/TimeUtils.h"
+#include "utils/StringUtils.h"
#include "Application.h"
#include "ApplicationMessenger.h"
#include "settings/AdvancedSettings.h"
#include "settings/MediaSettings.h"
#include "settings/Settings.h"
+#include "guilib/GUIFontManager.h"
#if defined(HAS_GL)
#include "LinuxRendererGL.h"
return;
}
- bool ismaster = CDVDClock::IsMasterClock();
-
- //the videoreferenceclock updates its clock on every vertical blank
- //we want every frame's presenttime to end up in the middle of two vblanks
- //if CDVDPlayerAudio is the master clock, we add a correction to the presenttime
- if (ismaster)
- presenttime += m_presentcorr * frametime;
-
double clock = CDVDClock::WaitAbsoluteClock(presenttime * DVD_TIME_BASE) / DVD_TIME_BASE;
double target = 0.5;
double error = ( clock - presenttime ) / frametime - target;
avgerror /= ERRORBUFFSIZE;
- //if CDVDPlayerAudio is not the master clock, we change the clock speed slightly
+ //we change the clock speed slightly
//to make every frame's presenttime end up in the middle of two vblanks
- if (!ismaster)
- {
- //integral correction, clamp to -0.5:0.5 range
- m_presentcorr = std::max(std::min(m_presentcorr + avgerror * 0.01, 0.1), -0.1);
- g_VideoReferenceClock.SetFineAdjust(1.0 - avgerror * 0.01 - m_presentcorr * 0.01);
- }
- else
- {
- //integral correction, wrap to -0.5:0.5 range
- m_presentcorr = wrap(m_presentcorr + avgerror * 0.01, target - 1.0, target);
- g_VideoReferenceClock.SetFineAdjust(1.0);
- }
+ //integral correction, clamp to -0.5:0.5 range
+ m_presentcorr = std::max(std::min(m_presentcorr + avgerror * 0.01, 0.1), -0.1);
+ g_VideoReferenceClock.SetFineAdjust(1.0 - avgerror * 0.01 - m_presentcorr * 0.01);
//printf("%f %f % 2.0f%% % f % f\n", presenttime, clock, m_presentcorr * 100, error, error_org);
}
avgerror += m_errorbuff[i];
avgerror /= ERRORBUFFSIZE;
- CStdString state;
- state.Format("sync:%+3d%% avg:%3d%% error:%2d%%"
- , MathUtils::round_int(m_presentcorr * 100)
- , MathUtils::round_int(avgerror * 100)
- , abs(MathUtils::round_int(m_presenterr * 100)));
+ CStdString state = StringUtils::Format("sync:%+3d%% avg:%3d%% error:%2d%%"
+ , MathUtils::round_int(m_presentcorr * 100)
+ , MathUtils::round_int(avgerror * 100)
+ , abs(MathUtils::round_int(m_presenterr * 100)));
return state;
}
m_format = format;
int processor = m_pRenderer->GetProcessorSize();
- if(processor)
+ if(processor > buffers) /* DXVA-HD returns processor size 6 */
+ m_QueueSize = 3; /* we need queue size of 3 to get future frames in the processor */
+ else if(processor)
m_QueueSize = buffers - processor + 1; /* respect maximum refs */
else
m_QueueSize = m_pRenderer->GetMaxBufferSize(); /* no refs to data */
if(g_graphicsContext.IsFullScreenVideo())
WaitPresentTime(m.timestamp);
+ m_clock_framefinish = GetPresentTime();
+
{ CSingleLock lock(m_presentlock);
if(m_presentstep == PRESENT_FRAME)
m_bIsStarted = false;
m_overlays.Flush();
+ g_fontManager.Unload("__subtitle__");
+ g_fontManager.Unload("__subtitleborder__");
// free renderer resources.
// TODO: we may also want to release the renderer here.
CDVDCodecUtils::CopyDXVA2Picture(&image, &pic);
}
#ifdef HAVE_LIBVDPAU
- else if(pic.format == RENDER_FMT_VDPAU)
+ else if(pic.format == RENDER_FMT_VDPAU
+ || pic.format == RENDER_FMT_VDPAU_420)
m_pRenderer->AddProcessor(pic.vdpau, index);
#endif
#ifdef HAVE_LIBOPENMAX
else if(pic.format == RENDER_FMT_EGLIMG)
m_pRenderer->AddProcessor(pic.stf, pic.eglimg, index);
#endif
+#if defined(TARGET_ANDROID)
+ else if(pic.format == RENDER_FMT_MEDIACODEC)
+ m_pRenderer->AddProcessor(pic.mediacodec, index);
+#endif
m_pRenderer->ReleaseImage(index, false);
double clocktime = GetPresentTime();
double frametime = 1.0 / GetMaximumFPS();
+ double correction = 0.0;
+ int fps = g_VideoReferenceClock.GetRefreshRate();
+ if((fps > 0) && g_graphicsContext.IsFullScreenVideo() && (clocktime != m_clock_framefinish))
+ {
+ correction = frametime;
+ }
/* see if any future queued frames are already due */
std::deque<int>::reverse_iterator curr, prev;
++prev;
while (prev != m_queued.rend())
{
- if(clocktime > m_Queue[*prev].timestamp /* previous frame is late */
- && clocktime > m_Queue[*curr].timestamp - frametime) /* selected frame is close to it's display time */
+ if(clocktime > m_Queue[*prev].timestamp + correction /* previous frame is late */
+ && clocktime > m_Queue[*curr].timestamp - frametime + correction) /* selected frame is close to it's display time */
break;
++curr;
++prev;